<commit_before>obj buf[T](tup(T,T,T) data) {
  fn get(int i) -> T {
    if (i == 0) {
      ret data._0;
    } else {
      if (i == 1) {
        ret data._1;
      } else {
        ret data._2;
      }
    }
  }

  fn take(&T t) {}
  fn take2(T t) {}
}

fn main() {
  let buf[int] b = buf[int](tup(1,2,3));
  log "constructed object";
  log b.get(0);
  log b.get(1);
  log b.get(2);
  check (b.get(0) == 1);
  check (b.get(1) == 2);
  check (b.get(2) == 3);
  b.take2(0);
}
<commit_msg>Fix bug in generic-obj.rs testcase.<commit_after>obj buf[T](tup(T,T,T) data) {
  fn get(int i) -> T {
    if (i == 0) {
      ret data._0;
    } else {
      if (i == 1) {
        ret data._1;
      } else {
        ret data._2;
      }
    }
  }

  fn take(&T t) {}
  fn take2(&T t) {}
}

fn main() {
  let buf[int] b = buf[int](tup(1,2,3));
  log "constructed object";
  log b.get(0);
  log b.get(1);
  log b.get(2);
  check (b.get(0) == 1);
  check (b.get(1) == 2);
  check (b.get(2) == 3);
  b.take2(0);
}
<|endoftext|>


<commit_before>use byteorder::{LittleEndian, ByteOrder, ReadBytesExt};
use error::Result;
use std::io::Read;
use std::io::{Error as IoError, ErrorKind as IoErrorKind, Result as IoResult};

pub trait WadReadFrom: Sized {
    fn wad_read_from<R: Read>(&mut R) -> Result<Self>;

    #[inline]
    fn wad_read_many_from<R: Read>(reader: &mut R, n: usize) -> Result<Vec<Self>> {
        (0..n).map(|_| reader.wad_read()).collect()
    }
}

impl WadReadFrom for u8 {
    #[inline]
    fn wad_read_from<R: Read>(reader: &mut R) -> Result<Self> {
        Ok(try!(reader.read_u8()))
    }

    #[inline]
    fn wad_read_many_from<R: Read>(reader: &mut R, n: usize) -> Result<Vec<Self>> {
        let mut buf = vec![0; n];
        try!(reader.read_buffer(&mut buf));
        Ok(buf)
    }
}

impl WadReadFrom for u16 {
    #[inline]
    fn wad_read_from<R: Read>(reader: &mut R) -> Result<Self> {
        Ok(try!(reader.read_u16::<LittleEndian>()))
    }
}

impl WadReadFrom for u32 {
    #[inline]
    fn wad_read_from<R: Read>(reader: &mut R) -> Result<Self> {
        Ok(try!(reader.read_u32::<LittleEndian>()))
    }
}

impl WadReadFrom for u64 {
    #[inline]
    fn wad_read_from<R: Read>(reader: &mut R) -> Result<Self> {
        Ok(try!(reader.read_u64::<LittleEndian>()))
    }
}

impl WadReadFrom for i8 {
    #[inline]
    fn wad_read_from<R: Read>(reader: &mut R) -> Result<Self> {
        Ok(try!(reader.read_i8()))
    }
}

impl WadReadFrom for i16 {
    #[inline]
    fn wad_read_from<R: Read>(reader: &mut R) -> Result<Self> {
        Ok(try!(reader.read_i16::<LittleEndian>()))
    }
}

impl WadReadFrom for i32 {
    #[inline]
    fn wad_read_from<R: Read>(reader: &mut R) -> Result<Self> {
        Ok(try!(reader.read_i32::<LittleEndian>()))
    }
}

impl WadReadFrom for i64 {
    #[inline]
    fn wad_read_from<R: Read>(reader: &mut R) -> Result<Self> {
        Ok(try!(reader.read_i64::<LittleEndian>()))
    }
}

impl WadReadFrom for [u8; 256] {
    #[inline]
    fn wad_read_from<R: Read>(reader: &mut R) -> Result<Self> {
        let mut ret = [0; 256];
        try!(reader.read_buffer(&mut ret));
        Ok(ret)
    }
}

impl WadReadFrom for [u8; 768] {
    #[inline]
    fn wad_read_from<R: Read>(reader: &mut R) -> Result<Self> {
        let mut ret = [0; 768];
        try!(reader.read_buffer(&mut ret));
        Ok(ret)
    }
}

pub trait WadRead: Read + Sized {
    fn wad_read<T: WadReadFrom>(&mut self) -> Result<T> {
        T::wad_read_from(self)
    }

    fn wad_read_many<T: WadReadFrom>(&mut self, n: usize) -> Result<Vec<T>> {
        T::wad_read_many_from(self, n)
    }

    fn read_buffer(&mut self, mut buf: &mut [u8]) -> IoResult<()> {
        while !buf.is_empty() {
            match self.read(buf) {
                Ok(0) => break,
                Ok(n) => { let tmp = buf; buf = &mut tmp[n..]; }
                Err(ref e) if e.kind() == IoErrorKind::Interrupted => {}
                Err(e) => return Err(e),
            }
        }
        if !buf.is_empty() {
            Err(IoError::new(IoErrorKind::InvalidData, "failed to fill whole buffer"))
        } else {
            Ok(())
        }
    }
}

impl<T: Read> WadRead for T {}
<commit_msg>wad: fixes for stable<commit_after>use byteorder::{LittleEndian, ByteOrder, ReadBytesExt};
use error::Result;
use std::io::Read;
use std::io::Error as IoError;
use std::io::ErrorKind as IoErrorKind;
use std::io::Result as IoResult;

pub trait WadReadFrom: Sized {
    fn wad_read_from<R: Read>(&mut R) -> Result<Self>;

    #[inline]
    fn wad_read_many_from<R: Read>(reader: &mut R, n: usize) -> Result<Vec<Self>> {
        (0..n).map(|_| reader.wad_read()).collect()
    }
}

impl WadReadFrom for u8 {
    #[inline]
    fn wad_read_from<R: Read>(reader: &mut R) -> Result<Self> {
        Ok(try!(reader.read_u8()))
    }

    #[inline]
    fn wad_read_many_from<R: Read>(reader: &mut R, n: usize) -> Result<Vec<Self>> {
        let mut buf = vec![0; n];
        try!(reader.read_buffer(&mut buf));
        Ok(buf)
    }
}

impl WadReadFrom for u16 {
    #[inline]
    fn wad_read_from<R: Read>(reader: &mut R) -> Result<Self> {
        Ok(try!(reader.read_u16::<LittleEndian>()))
    }
}

impl WadReadFrom for u32 {
    #[inline]
    fn wad_read_from<R: Read>(reader: &mut R) -> Result<Self> {
        Ok(try!(reader.read_u32::<LittleEndian>()))
    }
}

impl WadReadFrom for u64 {
    #[inline]
    fn wad_read_from<R: Read>(reader: &mut R) -> Result<Self> {
        Ok(try!(reader.read_u64::<LittleEndian>()))
    }
}

impl WadReadFrom for i8 {
    #[inline]
    fn wad_read_from<R: Read>(reader: &mut R) -> Result<Self> {
        Ok(try!(reader.read_i8()))
    }
}

impl WadReadFrom for i16 {
    #[inline]
    fn wad_read_from<R: Read>(reader: &mut R) -> Result<Self> {
        Ok(try!(reader.read_i16::<LittleEndian>()))
    }
}

impl WadReadFrom for i32 {
    #[inline]
    fn wad_read_from<R: Read>(reader: &mut R) -> Result<Self> {
        Ok(try!(reader.read_i32::<LittleEndian>()))
    }
}

impl WadReadFrom for i64 {
    #[inline]
    fn wad_read_from<R: Read>(reader: &mut R) -> Result<Self> {
        Ok(try!(reader.read_i64::<LittleEndian>()))
    }
}

impl WadReadFrom for [u8; 256] {
    #[inline]
    fn wad_read_from<R: Read>(reader: &mut R) -> Result<Self> {
        let mut ret = [0; 256];
        try!(reader.read_buffer(&mut ret));
        Ok(ret)
    }
}

impl WadReadFrom for [u8; 768] {
    #[inline]
    fn wad_read_from<R: Read>(reader: &mut R) -> Result<Self> {
        let mut ret = [0; 768];
        try!(reader.read_buffer(&mut ret));
        Ok(ret)
    }
}

pub trait WadRead: Read + Sized {
    fn wad_read<T: WadReadFrom>(&mut self) -> Result<T> {
        T::wad_read_from(self)
    }

    fn wad_read_many<T: WadReadFrom>(&mut self, n: usize) -> Result<Vec<T>> {
        T::wad_read_many_from(self, n)
    }

    fn read_buffer(&mut self, mut buf: &mut [u8]) -> IoResult<()> {
        while !buf.is_empty() {
            match self.read(buf) {
                Ok(0) => break,
                Ok(n) => { let tmp = buf; buf = &mut tmp[n..]; }
                Err(ref e) if e.kind() == IoErrorKind::Interrupted => {}
                Err(e) => return Err(e),
            }
        }
        if !buf.is_empty() {
            Err(IoError::new(IoErrorKind::InvalidData, "failed to fill whole buffer"))
        } else {
            Ok(())
        }
    }
}

impl<T: Read> WadRead for T {}
<|endoftext|>


<commit_before>use nom::{
  Consumer, ConsumerState,
  ErrorKind,
  HexDisplay,
  Input, IResult,
  Move, Needed,
};

use metadata;

use metadata::{Metadata, StreamInfo, metadata_parser};
use frame::{frame_parser, Frame};

enum ParserState {
  Marker,
  Metadata,
  Frame,
}

pub struct Stream {
  info: StreamInfo,
  pub metadata: Vec<Metadata>,
  pub frames: Vec<Frame>,
  state: ParserState,
  consumer_state: ConsumerState<(), ErrorKind, Move>,
}

named!(pub stream_parser <&[u8], Stream>,
  chain!(
    blocks: metadata_parser ~
    frames: many1!(apply!(frame_parser, &blocks.0)),
    move|| {
      let consumed = Move::Consume(0);

      Stream {
        info: blocks.0,
        metadata: blocks.1,
        frames: frames,
        state: ParserState::Marker,
        consumer_state: ConsumerState::Continue(consumed),
      }
    }
  )
);

impl Stream {
  pub fn new() -> Stream {
    let consumed = Move::Consume(0);

    Stream {
      info: StreamInfo::new(),
      metadata: Vec::new(),
      frames: Vec::new(),
      state: ParserState::Marker,
      consumer_state: ConsumerState::Continue(consumed),
    }
  }

  fn handle_marker(&mut self, input: &[u8]) {
    match tag!(input, "fLaC") {
      IResult::Done(i, _)       => {
        let offset   = input.offset(i);
        let consumed = Move::Consume(offset);

        self.state          = ParserState::Metadata;
        self.consumer_state = ConsumerState::Continue(consumed);
      }
      IResult::Error(_)         => {
        let kind = ErrorKind::Custom(0);

        self.consumer_state = ConsumerState::Error(kind);
      }
      IResult::Incomplete(size) => {
        let needed = Move::Await(size);

        self.consumer_state = ConsumerState::Continue(needed);
      }
    }
  }

  fn handle_metadata(&mut self, input: &[u8]) {
    match metadata::block(input) {
      IResult::Done(i, block) => {
        let offset   = input.offset(i);
        let consumed = Move::Consume(offset);
        let is_last  = block.is_last;

        if let metadata::Data::StreamInfo(info) = block.data {
          self.info = info;
        } else {
          self.metadata.push(block);
        }

        if is_last {
          self.state = ParserState::Frame;
        }

        self.consumer_state = ConsumerState::Continue(consumed);
      }
      IResult::Error(_)       => {
        let kind = ErrorKind::Custom(1);

        self.consumer_state = ConsumerState::Error(kind);
      }
      IResult::Incomplete(s)  => {
        let size = if let Needed::Size(length) = s {
          length
        } else {
          1024
        };
        let needed = Move::Await(Needed::Size(size));

        self.consumer_state = ConsumerState::Continue(needed);
      }
    }
  }

  fn handle_frame(&mut self, input: &[u8]) {
    match frame_parser(input, &self.info) {
      IResult::Done(i, frame) => {
        let offset   = input.offset(i);
        let consumed = Move::Consume(offset);

        self.frames.push(frame);

        self.consumer_state = ConsumerState::Continue(consumed);
      }
      IResult::Error(_)       => {
        let kind = ErrorKind::Custom(2);

        self.consumer_state = ConsumerState::Error(kind);
      }
      IResult::Incomplete(s)  => {
        let size = if let Needed::Size(length) = s {
          length
        } else {
          self.info.max_frame_size as usize
        };
        let needed = Move::Await(Needed::Size(size));

        self.consumer_state = ConsumerState::Continue(needed);
      }
    }
  }
}

impl<'a> Consumer<&'a [u8], (), ErrorKind, Move> for Stream {
  fn state(&self) -> &ConsumerState<(), ErrorKind, Move> {
    &self.consumer_state
  }

  fn handle(&mut self, input: Input<&'a [u8]>)
            -> &ConsumerState<(), ErrorKind, Move> {
    match input {
      Input::Element(i) | Input::Eof(Some(i)) => {
        match self.state {
          ParserState::Marker   => self.handle_marker(i),
          ParserState::Metadata => self.handle_metadata(i),
          ParserState::Frame    => self.handle_frame(i),
        }
      }
      Input::Empty | Input::Eof(None)         => {
        self.consumer_state = match self.state {
          ParserState::Marker   => ConsumerState::Error(ErrorKind::Custom(0)),
          ParserState::Metadata => ConsumerState::Error(ErrorKind::Custom(1)),
          ParserState::Frame    => ConsumerState::Done(Move::Consume(0), ()),
        };
      }
    }

    &self.consumer_state
  }
}
<commit_msg>Add `Stream::info` to keep `StreamInfo` immutable<commit_after>use nom::{
  Consumer, ConsumerState,
  ErrorKind,
  HexDisplay,
  Input, IResult,
  Move, Needed,
};

use metadata;

use metadata::{Metadata, StreamInfo, metadata_parser};
use frame::{frame_parser, Frame};

enum ParserState {
  Marker,
  Metadata,
  Frame,
}

pub struct Stream {
  info: StreamInfo,
  pub metadata: Vec<Metadata>,
  pub frames: Vec<Frame>,
  state: ParserState,
  consumer_state: ConsumerState<(), ErrorKind, Move>,
}

named!(pub stream_parser <&[u8], Stream>,
  chain!(
    blocks: metadata_parser ~
    frames: many1!(apply!(frame_parser, &blocks.0)),
    move|| {
      let consumed = Move::Consume(0);

      Stream {
        info: blocks.0,
        metadata: blocks.1,
        frames: frames,
        state: ParserState::Marker,
        consumer_state: ConsumerState::Continue(consumed),
      }
    }
  )
);

impl Stream {
  pub fn new() -> Stream {
    let consumed = Move::Consume(0);

    Stream {
      info: StreamInfo::new(),
      metadata: Vec::new(),
      frames: Vec::new(),
      state: ParserState::Marker,
      consumer_state: ConsumerState::Continue(consumed),
    }
  }

  pub fn info(&self) -> StreamInfo {
    self.info
  }

  fn handle_marker(&mut self, input: &[u8]) {
    match tag!(input, "fLaC") {
      IResult::Done(i, _)       => {
        let offset   = input.offset(i);
        let consumed = Move::Consume(offset);

        self.state          = ParserState::Metadata;
        self.consumer_state = ConsumerState::Continue(consumed);
      }
      IResult::Error(_)         => {
        let kind = ErrorKind::Custom(0);

        self.consumer_state = ConsumerState::Error(kind);
      }
      IResult::Incomplete(size) => {
        let needed = Move::Await(size);

        self.consumer_state = ConsumerState::Continue(needed);
      }
    }
  }

  fn handle_metadata(&mut self, input: &[u8]) {
    match metadata::block(input) {
      IResult::Done(i, block) => {
        let offset   = input.offset(i);
        let consumed = Move::Consume(offset);
        let is_last  = block.is_last;

        if let metadata::Data::StreamInfo(info) = block.data {
          self.info = info;
        } else {
          self.metadata.push(block);
        }

        if is_last {
          self.state = ParserState::Frame;
        }

        self.consumer_state = ConsumerState::Continue(consumed);
      }
      IResult::Error(_)       => {
        let kind = ErrorKind::Custom(1);

        self.consumer_state = ConsumerState::Error(kind);
      }
      IResult::Incomplete(s)  => {
        let size = if let Needed::Size(length) = s {
          length
        } else {
          1024
        };
        let needed = Move::Await(Needed::Size(size));

        self.consumer_state = ConsumerState::Continue(needed);
      }
    }
  }

  fn handle_frame(&mut self, input: &[u8]) {
    match frame_parser(input, &self.info) {
      IResult::Done(i, frame) => {
        let offset   = input.offset(i);
        let consumed = Move::Consume(offset);

        self.frames.push(frame);

        self.consumer_state = ConsumerState::Continue(consumed);
      }
      IResult::Error(_)       => {
        let kind = ErrorKind::Custom(2);

        self.consumer_state = ConsumerState::Error(kind);
      }
      IResult::Incomplete(s)  => {
        let size = if let Needed::Size(length) = s {
          length
        } else {
          self.info.max_frame_size as usize
        };
        let needed = Move::Await(Needed::Size(size));

        self.consumer_state = ConsumerState::Continue(needed);
      }
    }
  }
}

impl<'a> Consumer<&'a [u8], (), ErrorKind, Move> for Stream {
  fn state(&self) -> &ConsumerState<(), ErrorKind, Move> {
    &self.consumer_state
  }

  fn handle(&mut self, input: Input<&'a [u8]>)
            -> &ConsumerState<(), ErrorKind, Move> {
    match input {
      Input::Element(i) | Input::Eof(Some(i)) => {
        match self.state {
          ParserState::Marker   => self.handle_marker(i),
          ParserState::Metadata => self.handle_metadata(i),
          ParserState::Frame    => self.handle_frame(i),
        }
      }
      Input::Empty | Input::Eof(None)         => {
        self.consumer_state = match self.state {
          ParserState::Marker   => ConsumerState::Error(ErrorKind::Custom(0)),
          ParserState::Metadata => ConsumerState::Error(ErrorKind::Custom(1)),
          ParserState::Frame    => ConsumerState::Done(Move::Consume(0), ()),
        };
      }
    }

    &self.consumer_state
  }
}
<|endoftext|>


<commit_before>use super::ToTokens;
use std::fmt::{self, Debug, Display};

use proc_macro;
use proc_macro2::{TokenStream, TokenTree};

/// Tokens produced by a `quote!(...)` invocation.
#[derive(Clone, Default)]
pub struct Tokens {
    tts: Vec<TokenTree>,
}

impl Tokens {
    /// Empty tokens.
    pub fn new() -> Self {
        Tokens { tts: Vec::new() }
    }

    /// For use by `ToTokens` implementations.
    ///
    /// Appends the token specified to this list of tokens.
    pub fn append<U>(&mut self, token: U)
    where
        U: Into<TokenTree>,
    {
        self.tts.push(token.into());
    }

    /// For use by `ToTokens` implementations.
    ///
    /// ```
    /// # #[macro_use] extern crate quote;
    /// # use quote::{Tokens, ToTokens};
    /// # fn main() {
    /// struct X;
    ///
    /// impl ToTokens for X {
    ///     fn to_tokens(&self, tokens: &mut Tokens) {
    ///         tokens.append_all(&[true, false]);
    ///     }
    /// }
    ///
    /// let tokens = quote!(#X);
    /// assert_eq!(tokens.to_string(), "true false");
    /// # }
    /// ```
    pub fn append_all<T, I>(&mut self, iter: I)
    where
        T: ToTokens,
        I: IntoIterator<Item = T>,
    {
        for token in iter {
            token.to_tokens(self);
        }
    }

    /// For use by `ToTokens` implementations.
    ///
    /// Appends all of the items in the iterator `I`, separated by the tokens
    /// `U`.
    pub fn append_separated<T, I, U>(&mut self, iter: I, op: U)
    where
        T: ToTokens,
        I: IntoIterator<Item = T>,
        U: ToTokens,
    {
        for (i, token) in iter.into_iter().enumerate() {
            if i > 0 {
                op.to_tokens(self);
            }
            token.to_tokens(self);
        }
    }

    /// For use by `ToTokens` implementations.
    ///
    /// Appends all tokens in the iterator `I`, appending `U` after each
    /// element, including after the last element of the iterator.
    pub fn append_terminated<T, I, U>(&mut self, iter: I, term: U)
    where
        T: ToTokens,
        I: IntoIterator<Item = T>,
        U: ToTokens,
    {
        for token in iter {
            token.to_tokens(self);
            term.to_tokens(self);
        }
    }
}

impl ToTokens for Tokens {
    fn to_tokens(&self, dst: &mut Tokens) {
        dst.tts.extend(self.tts.iter().cloned());
    }

    fn into_tokens(self) -> Tokens {
        self
    }
}

impl From<Tokens> for TokenStream {
    fn from(tokens: Tokens) -> TokenStream {
        tokens.tts.into_iter().collect()
    }
}

impl From<Tokens> for proc_macro::TokenStream {
    fn from(tokens: Tokens) -> proc_macro::TokenStream {
        TokenStream::from(tokens).into()
    }
}

impl Display for Tokens {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        Display::fmt(&TokenStream::from(self.clone()), formatter)
    }
}

impl Debug for Tokens {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        struct DebugAsDisplay<'a, T: 'a>(&'a T);

        impl<'a, T> Debug for DebugAsDisplay<'a, T>
        where
            T: Display,
        {
            fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                Display::fmt(self.0, formatter)
            }
        }

        formatter
            .debug_tuple("Tokens")
            .field(&DebugAsDisplay(self))
            .finish()
    }
}
<commit_msg>Tokens documentation<commit_after>use super::ToTokens;
use std::fmt::{self, Debug, Display};

use proc_macro;
use proc_macro2::{TokenStream, TokenTree};

/// Tokens produced by a [`quote!`] invocation.
///
/// [`quote!`]: macro.quote.html
#[derive(Clone, Default)]
pub struct Tokens {
    tts: Vec<TokenTree>,
}

impl Tokens {
    /// Empty tokens.
    pub fn new() -> Self {
        Tokens { tts: Vec::new() }
    }

    /// For use by `ToTokens` implementations.
    ///
    /// Appends the token specified to this list of tokens.
    pub fn append<U>(&mut self, token: U)
    where
        U: Into<TokenTree>,
    {
        self.tts.push(token.into());
    }

    /// For use by `ToTokens` implementations.
    ///
    /// ```
    /// # #[macro_use] extern crate quote;
    /// # use quote::{Tokens, ToTokens};
    /// # fn main() {
    /// struct X;
    ///
    /// impl ToTokens for X {
    ///     fn to_tokens(&self, tokens: &mut Tokens) {
    ///         tokens.append_all(&[true, false]);
    ///     }
    /// }
    ///
    /// let tokens = quote!(#X);
    /// assert_eq!(tokens.to_string(), "true false");
    /// # }
    /// ```
    pub fn append_all<T, I>(&mut self, iter: I)
    where
        T: ToTokens,
        I: IntoIterator<Item = T>,
    {
        for token in iter {
            token.to_tokens(self);
        }
    }

    /// For use by `ToTokens` implementations.
    ///
    /// Appends all of the items in the iterator `I`, separated by the tokens
    /// `U`.
    pub fn append_separated<T, I, U>(&mut self, iter: I, op: U)
    where
        T: ToTokens,
        I: IntoIterator<Item = T>,
        U: ToTokens,
    {
        for (i, token) in iter.into_iter().enumerate() {
            if i > 0 {
                op.to_tokens(self);
            }
            token.to_tokens(self);
        }
    }

    /// For use by `ToTokens` implementations.
    ///
    /// Appends all tokens in the iterator `I`, appending `U` after each
    /// element, including after the last element of the iterator.
    pub fn append_terminated<T, I, U>(&mut self, iter: I, term: U)
    where
        T: ToTokens,
        I: IntoIterator<Item = T>,
        U: ToTokens,
    {
        for token in iter {
            token.to_tokens(self);
            term.to_tokens(self);
        }
    }
}

impl ToTokens for Tokens {
    fn to_tokens(&self, dst: &mut Tokens) {
        dst.tts.extend(self.tts.iter().cloned());
    }

    fn into_tokens(self) -> Tokens {
        self
    }
}

impl From<Tokens> for TokenStream {
    fn from(tokens: Tokens) -> TokenStream {
        tokens.tts.into_iter().collect()
    }
}

impl From<Tokens> for proc_macro::TokenStream {
    fn from(tokens: Tokens) -> proc_macro::TokenStream {
        TokenStream::from(tokens).into()
    }
}

impl Display for Tokens {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        Display::fmt(&TokenStream::from(self.clone()), formatter)
    }
}

impl Debug for Tokens {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        struct DebugAsDisplay<'a, T: 'a>(&'a T);

        impl<'a, T> Debug for DebugAsDisplay<'a, T>
        where
            T: Display,
        {
            fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                Display::fmt(self.0, formatter)
            }
        }

        formatter
            .debug_tuple("Tokens")
            .field(&DebugAsDisplay(self))
            .finish()
    }
}
<|endoftext|>


<commit_before>//! Standard symbolic constants and types
//!
use {Error, Result, NixPath, from_ffi};
use errno::Errno;
use fcntl::{fcntl, OFlag, O_NONBLOCK, O_CLOEXEC, FD_CLOEXEC};
use fcntl::FcntlArg::{F_SETFD, F_SETFL};
use libc::{c_char, c_void, c_int, size_t, pid_t, off_t};
use std::{mem, ptr};
use std::ffi::CString;
use std::os::unix::io::RawFd;

#[cfg(any(target_os = "linux", target_os = "android"))]
pub use self::linux::*;

mod ffi {
    use libc::{c_char, c_int, size_t};
    pub use libc::{close, read, write, pipe, ftruncate, unlink};
    pub use libc::funcs::posix88::unistd::{fork, getpid, getppid};

    extern {
        // duplicate a file descriptor
        // doc: http://man7.org/linux/man-pages/man2/dup.2.html
        pub fn dup(oldfd: c_int) -> c_int;
        pub fn dup2(oldfd: c_int, newfd: c_int) -> c_int;

        // change working directory
        // doc: http://man7.org/linux/man-pages/man2/chdir.2.html
        pub fn chdir(path: *const c_char) -> c_int;

        // execute program
        // doc: http://man7.org/linux/man-pages/man2/execve.2.html
        pub fn execve(filename: *const c_char, argv: *const *const c_char, envp: *const *const c_char) -> c_int;
        // doc: http://man7.org/linux/man-pages/man3/exec.3.html
        #[cfg(any(target_os = "linux", target_os = "android"))]
        #[cfg(feature = "execvpe")]
        pub fn execvpe(filename: *const c_char, argv: *const *const c_char, envp: *const *const c_char) -> c_int;

        // run the current process in the background
        // doc: http://man7.org/linux/man-pages/man3/daemon.3.html
        pub fn daemon(nochdir: c_int, noclose: c_int) -> c_int;

        // sets the hostname to the value given
        // doc: http://man7.org/linux/man-pages/man2/gethostname.2.html
        pub fn gethostname(name: *mut c_char, len: size_t) -> c_int;

        // gets the hostname
        // doc: http://man7.org/linux/man-pages/man2/gethostname.2.html
        pub fn sethostname(name: *const c_char, len: size_t) -> c_int;

        // change root directory
        // doc: http://man7.org/linux/man-pages/man2/gethostname.2.html
        pub fn chroot(path: *const c_char) -> c_int;
    }
}

#[derive(Clone, Copy)]
pub enum Fork {
    Parent(pid_t),
    Child
}

impl Fork {
    pub fn is_child(&self) -> bool {
        match *self {
            Fork::Child => true,
            _ => false
        }
    }

    pub fn is_parent(&self) -> bool {
        match *self {
            Fork::Parent(_) => true,
            _ => false
        }
    }
}

pub fn fork() -> Result<Fork> {
    use self::Fork::*;

    let res = unsafe { ffi::fork() };

    if res < 0 {
        return Err(Error::Sys(Errno::last()));
    } else if res == 0 {
        Ok(Child)
    } else {
        Ok(Parent(res))
    }
}

#[inline]
pub fn getpid() -> pid_t {
    unsafe { ffi::getpid() } // no error handling, according to man page: "These functions are always successful."
}
#[inline]
pub fn getppid() -> pid_t {
    unsafe { ffi::getppid() } // no error handling, according to man page: "These functions are always successful."
}

#[inline]
pub fn dup(oldfd: RawFd) -> Result<RawFd> {
    let res = unsafe { ffi::dup(oldfd) };

    if res < 0 {
        return Err(Error::Sys(Errno::last()));
    }

    Ok(res)
}

#[inline]
pub fn dup2(oldfd: RawFd, newfd: RawFd) -> Result<RawFd> {
    let res = unsafe { ffi::dup2(oldfd, newfd) };

    if res < 0 {
        return Err(Error::Sys(Errno::last()));
    }

    Ok(res)
}

pub fn dup3(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result<RawFd> {
    dup3_polyfill(oldfd, newfd, flags)
}

#[inline]
fn dup3_polyfill(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result<RawFd> {
    use errno::EINVAL;

    if oldfd == newfd {
        return Err(Error::Sys(Errno::EINVAL));
    }

    let fd = try!(dup2(oldfd, newfd));

    if flags.contains(O_CLOEXEC) {
        if let Err(e) = fcntl(fd, F_SETFD(FD_CLOEXEC)) {
            let _ = close(fd);
            return Err(e);
        }
    }

    Ok(fd)
}

#[inline]
pub fn chdir<P: ?Sized + NixPath>(path: &P) -> Result<()> {
    let res = try!(path.with_nix_path(|cstr| {
        unsafe { ffi::chdir(cstr.as_ptr()) }
    }));

    if res != 0 {
        return Err(Error::Sys(Errno::last()));
    }

    return Ok(())
}

#[inline]
pub fn execve(filename: &CString, args: &[CString], env: &[CString]) -> Result<()> {
    let mut args_p: Vec<*const c_char> = args.iter().map(|s| s.as_ptr()).collect();
    args_p.push(ptr::null());

    let mut env_p: Vec<*const c_char> = env.iter().map(|s| s.as_ptr()).collect();
    env_p.push(ptr::null());

    let res = unsafe {
        ffi::execve(filename.as_ptr(), args_p.as_ptr(), env_p.as_ptr())
    };

    if res != 0 {
        return Err(Error::Sys(Errno::last()));
    }

    unreachable!()
}

pub fn daemon(nochdir: bool, noclose: bool) -> Result<()> {
    let res = unsafe { ffi::daemon(nochdir as c_int, noclose as c_int) };
    from_ffi(res)
}

pub fn sethostname(name: &[u8]) -> Result<()> {
    let ptr = name.as_ptr() as *const c_char;
    let len = name.len() as size_t;

    let res = unsafe { ffi::sethostname(ptr, len) };
    from_ffi(res)
}

pub fn gethostname(name: &mut [u8]) -> Result<()> {
    let ptr = name.as_mut_ptr() as *mut c_char;
    let len = name.len() as size_t;

    let res = unsafe { ffi::gethostname(ptr, len) };
    from_ffi(res)
}

pub fn close(fd: RawFd) -> Result<()> {
    let res = unsafe { ffi::close(fd) };
    from_ffi(res)
}

pub fn read(fd: RawFd, buf: &mut [u8]) -> Result<usize> {
    let res = unsafe { ffi::read(fd, buf.as_mut_ptr() as *mut c_void, buf.len() as size_t) };

    if res < 0 {
        return Err(Error::Sys(Errno::last()));
    }

    return Ok(res as usize)
}

pub fn write(fd: RawFd, buf: &[u8]) -> Result<usize> {
    let res = unsafe { ffi::write(fd, buf.as_ptr() as *const c_void, buf.len() as size_t) };

    if res < 0 {
        return Err(Error::Sys(Errno::last()));
    }

    return Ok(res as usize)
}

pub fn pipe() -> Result<(RawFd, RawFd)> {
    unsafe {
        let mut fds: [c_int; 2] = mem::uninitialized();

        let res = ffi::pipe(fds.as_mut_ptr());

        if res < 0 {
            return Err(Error::Sys(Errno::last()));
        }

        Ok((fds[0], fds[1]))
    }
}

pub fn pipe2(flags: OFlag) -> Result<(RawFd, RawFd)> {
    unsafe {
        let mut fds: [c_int; 2] = mem::uninitialized();

        let res = ffi::pipe(fds.as_mut_ptr());

        if res < 0 {
            return Err(Error::Sys(Errno::last()));
        }

        try!(pipe2_setflags(fds[0], fds[1], flags));

        Ok((fds[0], fds[1]))
    }
}

fn pipe2_setflags(fd1: RawFd, fd2: RawFd, flags: OFlag) -> Result<()> {
    let mut res = Ok(0);

    if flags.contains(O_CLOEXEC) {
        res = res
            .and_then(|_| fcntl(fd1, F_SETFD(FD_CLOEXEC)))
            .and_then(|_| fcntl(fd2, F_SETFD(FD_CLOEXEC)));
    }

    if flags.contains(O_NONBLOCK) {
        res = res
            .and_then(|_| fcntl(fd1, F_SETFL(O_NONBLOCK)))
            .and_then(|_| fcntl(fd2, F_SETFL(O_NONBLOCK)));
    }

    match res {
        Ok(_) => Ok(()),
        Err(e) => {
            let _ = close(fd1);
            let _ = close(fd2);
            return Err(e);
        }
    }
}

pub fn ftruncate(fd: RawFd, len: off_t) -> Result<()> {
    if unsafe { ffi::ftruncate(fd, len) } < 0 {
        Err(Error::Sys(Errno::last()))
    } else {
        Ok(())
    }
}

pub fn isatty(fd: RawFd) -> Result<bool> {
    use libc;

    if unsafe { libc::isatty(fd) } == 1 {
        Ok(true)
    } else {
        match Errno::last() {
            // ENOTTY means `fd` is a valid file descriptor, but not a TTY, so
            // we return `Ok(false)`
            Errno::ENOTTY => Ok(false),
            err => Err(Error::Sys(err))
        }
    }
}

pub fn unlink<P: ?Sized + NixPath>(path: &P) -> Result<()> {
    let res = try!(path.with_nix_path(|cstr| {
    unsafe {
        ffi::unlink(cstr.as_ptr())
    }
    }));
    from_ffi(res)
}

#[inline]
pub fn chroot<P: ?Sized + NixPath>(path: &P) -> Result<()> {
    let res = try!(path.with_nix_path(|cstr| {
        unsafe { ffi::chroot(cstr.as_ptr()) }
    }));

    if res != 0 {
        return Err(Error::Sys(Errno::last()));
    }

    Ok(())
}

#[cfg(any(target_os = "linux", target_os = "android"))]
mod linux {
    use sys::syscall::{syscall, SYSPIVOTROOT};
    use errno::Errno;
    use {Error, Result, NixPath};

    #[cfg(feature = "execvpe")]
    use std::ffi::CString;

    pub fn pivot_root<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
            new_root: &P1, put_old: &P2) -> Result<()> {
        let res = try!(try!(new_root.with_nix_path(|new_root| {
            put_old.with_nix_path(|put_old| {
                unsafe {
                    syscall(SYSPIVOTROOT, new_root.as_ptr(), put_old.as_ptr())
                }
            })
        })));

        if res != 0 {
            return Err(Error::Sys(Errno::last()));
        }

        Ok(())
    }

    #[inline]
    #[cfg(feature = "execvpe")]
    pub fn execvpe(filename: &CString, args: &[CString], env: &[CString]) -> Result<()> {
        use std::ptr;
        use libc::c_char;

        let mut args_p: Vec<*const c_char> = args.iter().map(|s| s.as_ptr()).collect();
        args_p.push(ptr::null());

        let mut env_p: Vec<*const c_char> = env.iter().map(|s| s.as_ptr()).collect();
        env_p.push(ptr::null());

        let res = unsafe {
            super::ffi::execvpe(filename.as_ptr(), args_p.as_ptr(), env_p.as_ptr())
        };

        if res != 0 {
            return Err(Error::Sys(Errno::last()));
        }

        unreachable!()
    }
}
<commit_msg>Add missing exec functions<commit_after>//! Standard symbolic constants and types
//!
use {Error, Result, NixPath, from_ffi};
use errno::Errno;
use fcntl::{fcntl, OFlag, O_NONBLOCK, O_CLOEXEC, FD_CLOEXEC};
use fcntl::FcntlArg::{F_SETFD, F_SETFL};
use libc::{c_char, c_void, c_int, size_t, pid_t, off_t};
use std::mem;
use std::ffi::CString;
use std::os::unix::io::RawFd;

#[cfg(any(target_os = "linux", target_os = "android"))]
pub use self::linux::*;

mod ffi {
    use libc::{c_char, c_int, size_t};
    pub use libc::{close, read, write, pipe, ftruncate, unlink};
    pub use libc::funcs::posix88::unistd::{fork, getpid, getppid};

    extern {
        // duplicate a file descriptor
        // doc: http://man7.org/linux/man-pages/man2/dup.2.html
        pub fn dup(oldfd: c_int) -> c_int;
        pub fn dup2(oldfd: c_int, newfd: c_int) -> c_int;

        // change working directory
        // doc: http://man7.org/linux/man-pages/man2/chdir.2.html
        pub fn chdir(path: *const c_char) -> c_int;

        // Execute PATH with arguments ARGV and environment from `environ'.
        // doc: http://man7.org/linux/man-pages/man3/execv.3.html
        pub fn execv (path: *const c_char, argv: *const *const c_char) -> c_int;

        // execute program
        // doc: http://man7.org/linux/man-pages/man2/execve.2.html
        pub fn execve(path: *const c_char, argv: *const *const c_char, envp: *const *const c_char) -> c_int;

        // Execute FILE, searching in the `PATH' environment variable if it contains
        // no slashes, with arguments ARGV and environment from `environ'.
        // doc: http://man7.org/linux/man-pages/man3/execvp.3.html
        pub fn execvp(filename: *const c_char, argv: *const *const c_char) -> c_int;

        // doc: http://man7.org/linux/man-pages/man3/exec.3.html
        #[cfg(any(target_os = "linux", target_os = "android"))]
        #[cfg(feature = "execvpe")]
        pub fn execvpe(filename: *const c_char, argv: *const *const c_char, envp: *const *const c_char) -> c_int;

        // run the current process in the background
        // doc: http://man7.org/linux/man-pages/man3/daemon.3.html
        pub fn daemon(nochdir: c_int, noclose: c_int) -> c_int;

        // sets the hostname to the value given
        // doc: http://man7.org/linux/man-pages/man2/gethostname.2.html
        pub fn gethostname(name: *mut c_char, len: size_t) -> c_int;

        // gets the hostname
        // doc: http://man7.org/linux/man-pages/man2/gethostname.2.html
        pub fn sethostname(name: *const c_char, len: size_t) -> c_int;

        // change root directory
        // doc: http://man7.org/linux/man-pages/man2/gethostname.2.html
        pub fn chroot(path: *const c_char) -> c_int;
    }
}

#[derive(Clone, Copy)]
pub enum Fork {
    Parent(pid_t),
    Child
}

impl Fork {
    pub fn is_child(&self) -> bool {
        match *self {
            Fork::Child => true,
            _ => false
        }
    }

    pub fn is_parent(&self) -> bool {
        match *self {
            Fork::Parent(_) => true,
            _ => false
        }
    }
}

pub fn fork() -> Result<Fork> {
    use self::Fork::*;

    let res = unsafe { ffi::fork() };

    if res < 0 {
        return Err(Error::Sys(Errno::last()));
    } else if res == 0 {
        Ok(Child)
    } else {
        Ok(Parent(res))
    }
}

#[inline]
pub fn getpid() -> pid_t {
    unsafe { ffi::getpid() } // no error handling, according to man page: "These functions are always successful."
}
#[inline]
pub fn getppid() -> pid_t {
    unsafe { ffi::getppid() } // no error handling, according to man page: "These functions are always successful."
}

#[inline]
pub fn dup(oldfd: RawFd) -> Result<RawFd> {
    let res = unsafe { ffi::dup(oldfd) };

    if res < 0 {
        return Err(Error::Sys(Errno::last()));
    }

    Ok(res)
}

#[inline]
pub fn dup2(oldfd: RawFd, newfd: RawFd) -> Result<RawFd> {
    let res = unsafe { ffi::dup2(oldfd, newfd) };

    if res < 0 {
        return Err(Error::Sys(Errno::last()));
    }

    Ok(res)
}

pub fn dup3(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result<RawFd> {
    dup3_polyfill(oldfd, newfd, flags)
}

#[inline]
fn dup3_polyfill(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result<RawFd> {
    use errno::EINVAL;

    if oldfd == newfd {
        return Err(Error::Sys(Errno::EINVAL));
    }

    let fd = try!(dup2(oldfd, newfd));

    if flags.contains(O_CLOEXEC) {
        if let Err(e) = fcntl(fd, F_SETFD(FD_CLOEXEC)) {
            let _ = close(fd);
            return Err(e);
        }
    }

    Ok(fd)
}

#[inline]
pub fn chdir<P: ?Sized + NixPath>(path: &P) -> Result<()> {
    let res = try!(path.with_nix_path(|cstr| {
        unsafe { ffi::chdir(cstr.as_ptr()) }
    }));

    if res != 0 {
        return Err(Error::Sys(Errno::last()));
    }

    return Ok(())
}

fn to_exec_array(args: &[CString]) -> *const *const c_char {
    use std::ptr;
    use libc::c_char;

    let mut args_p: Vec<*const c_char> = args.iter().map(|s| s.as_ptr()).collect();
    args_p.push(ptr::null());
    args_p.as_ptr()
}

#[inline]
pub fn execv(path: &CString, argv: &[CString]) -> Result<()> {
    let args_p = to_exec_array(argv);

    unsafe {
        ffi::execv(path.as_ptr(), args_p)
    };

    Err(Error::Sys(Errno::last()))
}

#[inline]
pub fn execve(path: &CString, args: &[CString], env: &[CString]) -> Result<()> {
    let args_p = to_exec_array(args);
    let env_p = to_exec_array(env);

    unsafe {
        ffi::execve(path.as_ptr(), args_p, env_p)
    };

    Err(Error::Sys(Errno::last()))
}

#[inline]
pub fn execvp(filename: &CString, args: &[CString]) -> Result<()> {
    let args_p = to_exec_array(args);

    unsafe {
        ffi::execvp(filename.as_ptr(), args_p)
    };

    Err(Error::Sys(Errno::last()))
}

pub fn daemon(nochdir: bool, noclose: bool) -> Result<()> {
    let res = unsafe { ffi::daemon(nochdir as c_int, noclose as c_int) };
    from_ffi(res)
}

pub fn sethostname(name: &[u8]) -> Result<()> {
    let ptr = name.as_ptr() as *const c_char;
    let len = name.len() as size_t;

    let res = unsafe { ffi::sethostname(ptr, len) };
    from_ffi(res)
}

pub fn gethostname(name: &mut [u8]) -> Result<()> {
    let ptr = name.as_mut_ptr() as *mut c_char;
    let len = name.len() as size_t;

    let res = unsafe { ffi::gethostname(ptr, len) };
    from_ffi(res)
}

pub fn close(fd: RawFd) -> Result<()> {
    let res = unsafe { ffi::close(fd) };
    from_ffi(res)
}

pub fn read(fd: RawFd, buf: &mut [u8]) -> Result<usize> {
    let res = unsafe { ffi::read(fd, buf.as_mut_ptr() as *mut c_void, buf.len() as size_t) };

    if res < 0 {
        return Err(Error::Sys(Errno::last()));
    }

    return Ok(res as usize)
}

pub fn write(fd: RawFd, buf: &[u8]) -> Result<usize> {
    let res = unsafe { ffi::write(fd, buf.as_ptr() as *const c_void, buf.len() as size_t) };

    if res < 0 {
        return Err(Error::Sys(Errno::last()));
    }

    return Ok(res as usize)
}

pub fn pipe() -> Result<(RawFd, RawFd)> {
    unsafe {
        let mut fds: [c_int; 2] = mem::uninitialized();

        let res = ffi::pipe(fds.as_mut_ptr());

        if res < 0 {
            return Err(Error::Sys(Errno::last()));
        }

        Ok((fds[0], fds[1]))
    }
}

pub fn pipe2(flags: OFlag) -> Result<(RawFd, RawFd)> {
    unsafe {
        let mut fds: [c_int; 2] = mem::uninitialized();

        let res = ffi::pipe(fds.as_mut_ptr());

        if res < 0 {
            return Err(Error::Sys(Errno::last()));
        }

        try!(pipe2_setflags(fds[0], fds[1], flags));

        Ok((fds[0], fds[1]))
    }
}

fn pipe2_setflags(fd1: RawFd, fd2: RawFd, flags: OFlag) -> Result<()> {
    let mut res = Ok(0);

    if flags.contains(O_CLOEXEC) {
        res = res
            .and_then(|_| fcntl(fd1, F_SETFD(FD_CLOEXEC)))
            .and_then(|_| fcntl(fd2, F_SETFD(FD_CLOEXEC)));
    }

    if flags.contains(O_NONBLOCK) {
        res = res
            .and_then(|_| fcntl(fd1, F_SETFL(O_NONBLOCK)))
            .and_then(|_| fcntl(fd2, F_SETFL(O_NONBLOCK)));
    }

    match res {
        Ok(_) => Ok(()),
        Err(e) => {
            let _ = close(fd1);
            let _ = close(fd2);
            return Err(e);
        }
    }
}

pub fn ftruncate(fd: RawFd, len: off_t) -> Result<()> {
    if unsafe { ffi::ftruncate(fd, len) } < 0 {
        Err(Error::Sys(Errno::last()))
    } else {
        Ok(())
    }
}

pub fn isatty(fd: RawFd) -> Result<bool> {
    use libc;

    if unsafe { libc::isatty(fd) } == 1 {
        Ok(true)
    } else {
        match Errno::last() {
            // ENOTTY means `fd` is a valid file descriptor, but not a TTY, so
            // we return `Ok(false)`
            Errno::ENOTTY => Ok(false),
            err => Err(Error::Sys(err))
        }
    }
}

pub fn unlink<P: ?Sized + NixPath>(path: &P) -> Result<()> {
    let res = try!(path.with_nix_path(|cstr| {
    unsafe {
        ffi::unlink(cstr.as_ptr())
    }
    }));
    from_ffi(res)
}

#[inline]
pub fn chroot<P: ?Sized + NixPath>(path: &P) -> Result<()> {
    let res = try!(path.with_nix_path(|cstr| {
        unsafe { ffi::chroot(cstr.as_ptr()) }
    }));

    if res != 0 {
        return Err(Error::Sys(Errno::last()));
    }

    Ok(())
}

#[cfg(any(target_os = "linux", target_os = "android"))]
mod linux {
    use sys::syscall::{syscall, SYSPIVOTROOT};
    use errno::Errno;
    use {Error, Result, NixPath};

    #[cfg(feature = "execvpe")]
    use std::ffi::CString;

    pub fn pivot_root<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
            new_root: &P1, put_old: &P2) -> Result<()> {
        let res = try!(try!(new_root.with_nix_path(|new_root| {
            put_old.with_nix_path(|put_old| {
                unsafe {
                    syscall(SYSPIVOTROOT, new_root.as_ptr(), put_old.as_ptr())
                }
            })
        })));

        if res != 0 {
            return Err(Error::Sys(Errno::last()));
        }

        Ok(())
    }

    #[inline]
    #[cfg(feature = "execvpe")]
    pub fn execvpe(filename: &CString, args: &[CString], env: &[CString]) -> Result<()> {
        use std::ptr;
        use libc::c_char;

        let mut args_p: Vec<*const c_char> = args.iter().map(|s| s.as_ptr()).collect();
        args_p.push(ptr::null());

        let mut env_p: Vec<*const c_char> = env.iter().map(|s| s.as_ptr()).collect();
        env_p.push(ptr::null());

        unsafe {
            super::ffi::execvpe(filename.as_ptr(), args_p.as_ptr(), env_p.as_ptr())
        };

        Err(Error::Sys(Errno::last()))
    }
}
<|endoftext|>


<commit_before>use keyboard::Key;
use keymap::{ KeyMap, KeyMapState };
use buffer::Mark;
use textobject::{ TextObject, Offset, Kind, Anchor };
use overlay::OverlayType;

/// Instructions for the Editor.
/// These do NOT alter the text, but may change editor/view state
#[derive(Copy, Debug)]
#[allow(dead_code)]
pub enum Instruction {
    SaveBuffer,
    //FindFile,
    ExitEditor,

    SetMark(Mark),
    SetOverlay(OverlayType),
    // SetMode(...)
}

/// Operations on the Buffer.
/// These DO alter the text, but otherwise may NOT change editor/view state
/// Note that these differ from log::Change in that they are higher-level
/// operations dependent on state (cursor/mark locations, etc.), as opposed
/// to concrete operations on absolute indexes (insert 'a' at index 158, etc.)
#[derive(Copy, Debug)]
#[allow(dead_code)]
pub enum Operation {
    Insert(char), // insert text
    Delete,       // delete some object

    Undo,         // rewind buffer transaction log
    Redo,         // replay buffer transaction log
}

/// Fragments that can be combined to specify a command
#[derive(Copy, Debug)]
#[allow(dead_code)]
pub enum Partial {
    Kind(Kind),
    Anchor(Anchor),
    Offset(Offset),
    Object(TextObject),
    Action(Action),
}

#[derive(Copy, Debug)]
#[allow(dead_code)]
pub enum Action {
    Operation(Operation),
    Instruction(Instruction),
}

/// A complete, actionable command
#[derive(Copy, Debug)]
pub struct Command {
    pub number: i32,        // numeric paramter, line number, repeat count, etc.
    pub action: Action,     // what to do
    pub object: Option<TextObject>, // where to do it
}

impl Command {
    /// Shortcut to create an ExitEditor command
    pub fn exit_editor() -> Command {
        Command {
            action: Action::Instruction(Instruction::ExitEditor),
            number: 0,
            object: None,
        }
    }

    /// Shortcut to create a SaveBuffer command
    pub fn save_buffer() -> Command {
        Command {
            action: Action::Instruction(Instruction::SaveBuffer),
            number: 0,
            object: None,
        }
    }

    /// Shortcut to create an Insert command
    pub fn insert_char(c: char) -> Command {
        Command {
            number: 1,
            action: Action::Operation(Operation::Insert(c)),
            object: None,
        }
    }

    /// Shortcut to create an Insert command
    // FIXME: shouldn't need this method
    pub fn insert_tab() -> Command {
        Command {
            number: 4,
            action: Action::Operation(Operation::Insert(' ')),
            object: None,
        }
    }

    /// Shortcut to create Undo command
    pub fn undo() -> Command {
        Command {
            number: 1,
            action: Action::Operation(Operation::Undo),
            object: None
        }
    }

    /// Shortcut to create Redo command
    pub fn redo() -> Command {
        Command {
            number: 1,
            action: Action::Operation(Operation::Redo),
            object: None
        }
    }
}

pub struct Builder {
    number: Option<i32>,
    repeat: Option<usize>,

    action: Option<Action>,
    mark: Option<Mark>,
    kind: Option<Kind>,
    anchor: Option<Anchor>,
    offset: Option<Offset>,
    object: Option<TextObject>,

    reading_number: bool,
    keymap: KeyMap<Partial>,
}

#[derive(Copy, Debug)]
pub enum BuilderEvent {
    Invalid,            // cannot find a valid interpretation
    Incomplete,         // needs more information
    Complete(Command),  // command is finished
}

impl Builder {
    pub fn new() -> Builder {
        Builder {
            number: None,
            repeat: None,
            action: None,
            mark: None,
            kind: None,
            anchor: None,
            offset: None,
            object: None,
            reading_number: false,
            keymap: default_keymap()
        }
    }

    pub fn reset(&mut self) {
        self.number = None;
        self.repeat = None;
        self.action = None;
        self.mark = None;
        self.kind = None;
        self.anchor = None;
        self.object = None;
        self.offset = None;
        self.reading_number = false;
    }

    pub fn check_key(&mut self, key: Key) -> BuilderEvent {
        if let Key::Char(c) = key {
            // '0' might be bound (start of line), and cannot be the start of a number sequence
            if c.is_digit(10) && (self.reading_number || c != '0') {
                let n = c.to_digit(10).unwrap();
                self.reading_number = true;
                self.append_digit(n);
                return BuilderEvent::Incomplete;
            } else if self.reading_number {

                self.reading_number = false;
            }
        }

        match self.keymap.check_key(key) {
            KeyMapState::Match(partial) => self.apply_partial(partial),
            KeyMapState::None           => { self.reset(); return BuilderEvent::Invalid; }
            _ => {},
        }

        if let Some(c) = self.complete_command() {
            self.reset();
            return BuilderEvent::Complete(c)
        } else {
            return BuilderEvent::Incomplete
        }
    }

    fn complete_object(&mut self) -> Option<TextObject> {
        let mut result: Option<TextObject> = if let Some(object) = self.object {
            // we have a complete object ready to go
            Some(object)
        } else if let Some(kind) = self.kind {
            // we have at least a kind
            Some(TextObject {
                kind: kind,
                offset: self.offset.unwrap_or(Offset::Absolute(0)),
            })
        } else {
            None
        };

        if let Some(ref mut object) = result {
            if let Some(number) = self.number {
                object.offset = object.offset.with_num(number as usize);
            }
        }

        result
    }

    fn complete_command(&mut self) -> Option<Command> {
        /* rules for completing commands:
              | action            | number | object | reference    | kind |   | result                                                            |
              | -                 | -      | -      | -            | -    | - | -                                                                 |
              | no                | no     | no     | no           | yes  |   | move cursor to next (default) text object with kind               |
              | no                | no     | no     | yes          | -    |   | move cursor to text object with reference + default anchor        |
              | no                | no     | yes    | -            | -    |   | move cursor to text object                                        |
              | no                | yes    | no     | no           | no   |   | incomplete                                                        |
              | no                | yes    | no     | no           | yes  |   | move cursor to nth instance of kind (from start of buffer)        |
              | no                | yes    | no     | yes (index)  | -    |   | set index to number, cursor to ref + default anchor               |
              | no                | yes    | no     | yes (offset) | -    |   | multiply offset by number, cursor to ref + default anchor         |
              | no                | yes    | no     | yes (mark)   | -    |   | incomplete                                                        |
              | yes (instruction) | -      | -      | -            | -    |   | send instruction to editor with whatever parameters are available |
              | yes (operation)   | no     | no     | no           | no   |   | incomplete                                                        |
              | yes (operation)   | no     | no     | no           | yes  |   | apply operation to kind at cursor (default anchor)                |
              | yes (operation)   | no     | no     | yes          | -    |   | apply operation to reference with default anchor                  |
              | yes (operation)   | no     | yes    | -            | -    |   | apply operation to object                                         |
              | yes (operation)   | yes    | no     | no           | no   |   | incomplete                                                        |
              | yes (operation)   | yes    | no     | no           | yes  |   | apply operation to nth instance of kind                           |
        */

        // editor instructions may not need a text object, go ahead and return immediately
        if let Some(Action::Instruction(i)) = self.action {
            return Some(Command {
                number: self.repeat.unwrap_or(1) as i32,
                action: Action::Instruction(i),
                object: self.complete_object()
            });
        }

        if let Some(to) = self.complete_object() {
            if let Some(Action::Operation(o)) = self.action {
                // we have an object, and an operation
                return Some(Command {
                    number: self.repeat.unwrap_or(1) as i32,
                    action: Action::Operation(o),
                    object: Some(to)
                });
            } else {
                // we have just an object, assume move cursor instruction
                return Some(Command {
                    number: self.repeat.unwrap_or(1) as i32,
                    action: Action::Instruction(Instruction::SetMark(Mark::Cursor(0))),
                    object: Some(to)
                });
            }
        }
        None
    }

    fn append_digit(&mut self, n: usize) {
        if let Some(current) = self.number {
            self.number = Some((current*10) + n as i32);
        } else {
            self.number = Some(n as i32);
        }
    }

    fn apply_partial(&mut self, partial: Partial) {
        match partial {
            Partial::Kind(k)      => self.kind = Some(k),
            Partial::Anchor(a)    => self.anchor = Some(a),
            Partial::Offset(o)    => self.offset = Some(o),
            Partial::Object(o)    => self.object = Some(o),
            Partial::Action(a)    => {
                self.action = Some(a);
                if !self.reading_number && self.number.is_some() && self.repeat.is_none() {
                    // the first number followed by an action is treated as a repetition
                    self.repeat = Some(self.number.unwrap() as usize);
                    self.number = None;
                }
            }
        }

        // propagate upwards from anchor to object
        // if both an object(a) and an anchor(b) have been applied, the resulting
        // object should be exactly the same as (a), only using (b) as the anchor
        if let Some(anchor) = self.anchor {
            if let Some(kind) = self.kind {
                self.kind = Some(kind.with_anchor(anchor));
            }
            if let Some(object) = self.object {
                self.object = Some(TextObject {
                    kind: object.kind.with_anchor(anchor),
                    offset: object.offset,
                });
            }
        }
        if let Some(kind) = self.kind {
            if let Some(ref mut object) = self.object {
                object.kind = kind;
            }
        }
        if let Some(offset) = self.offset {
            if let Some(ref mut object) = self.object {
                object.offset = offset;
            }
        }

        // propagate downwards from object to unset partials
        if let Some(object) = self.object {
            if self.offset.is_none() { self.offset = Some(object.offset); }
            if self.kind.is_none() { self.kind = Some(object.kind); }
            if self.anchor.is_none() { self.anchor = Some(object.kind.get_anchor()); }
        }

        if self.offset.is_some() && self.kind.is_some() && self.object.is_none() {
            self.object = Some(TextObject {
                kind: self.kind.unwrap(),
                offset: self.offset.unwrap(),
            });
        }
    }
}

fn default_keymap() -> KeyMap<Partial> {
    let mut keymap = KeyMap::new();

    // next/previous char
    keymap.bind_key(Key::Char('l'), Partial::Object(TextObject {
        kind: Kind::Char,
        offset: Offset::Forward(1, Mark::Cursor(0))
    }));
    keymap.bind_key(Key::Char('h'), Partial::Object(TextObject {
        kind: Kind::Char,
        offset: Offset::Backward(1, Mark::Cursor(0))
    }));

    // next/previous line
    keymap.bind_key(Key::Char('j'), Partial::Object(TextObject {
        kind: Kind::Line(Anchor::Same),
        offset: Offset::Forward(1, Mark::Cursor(0))
    }));
    keymap.bind_key(Key::Char('k'), Partial::Object(TextObject {
        kind: Kind::Line(Anchor::Same),
        offset: Offset::Backward(1, Mark::Cursor(0))
    }));

    // next/previous word
    keymap.bind_key(Key::Char('w'), Partial::Object(TextObject {
        kind: Kind::Word(Anchor::Before),
        offset: Offset::Forward(1, Mark::Cursor(0))
    }));
    keymap.bind_key(Key::Char('b'), Partial::Object(TextObject {
        kind: Kind::Word(Anchor::Before),
        offset: Offset::Backward(1, Mark::Cursor(0))
    }));

    // start/end line
    keymap.bind_key(Key::Char('$'), Partial::Object(TextObject {
        kind: Kind::Line(Anchor::End),
        offset: Offset::Forward(1, Mark::Cursor(0)),
    }));
    keymap.bind_key(Key::Char('0'), Partial::Object(TextObject {
        kind: Kind::Line(Anchor::Start),
        offset: Offset::Forward(1, Mark::Cursor(0)),
    }));

    // kinds
    keymap.bind_keys(&[Key::Char('`'), Key::Char('c')], Partial::Kind(Kind::Char));
    keymap.bind_keys(&[Key::Char('`'), Key::Char('w')], Partial::Kind(Kind::Word(Anchor::Before)));
    keymap.bind_keys(&[Key::Char('`'), Key::Char('l')], Partial::Kind(Kind::Line(Anchor::Before)));

    // anchors
    keymap.bind_key(Key::Char(','), Partial::Anchor(Anchor::Before));
    keymap.bind_key(Key::Char('.'), Partial::Anchor(Anchor::After));

    // actions
    keymap.bind_key(Key::Char('d'), Partial::Action(Action::Operation(Operation::Delete)));
    keymap.bind_key(Key::Char(':'), Partial::Action(Action::Instruction(Instruction::SetOverlay(OverlayType::Prompt))));

    keymap
}
<commit_msg>Adjust default command bindings<commit_after>use keyboard::Key;
use keymap::{ KeyMap, KeyMapState };
use buffer::Mark;
use textobject::{ TextObject, Offset, Kind, Anchor };
use overlay::OverlayType;

/// Instructions for the Editor.
/// These do NOT alter the text, but may change editor/view state
#[derive(Copy, Debug)]
#[allow(dead_code)]
pub enum Instruction {
    SaveBuffer,
    //FindFile,
    ExitEditor,

    SetMark(Mark),
    SetOverlay(OverlayType),
    // SetMode(...)
}

/// Operations on the Buffer.
/// These DO alter the text, but otherwise may NOT change editor/view state
/// Note that these differ from log::Change in that they are higher-level
/// operations dependent on state (cursor/mark locations, etc.), as opposed
/// to concrete operations on absolute indexes (insert 'a' at index 158, etc.)
#[derive(Copy, Debug)]
#[allow(dead_code)]
pub enum Operation {
    Insert(char), // insert text
    Delete,       // delete some object

    Undo,         // rewind buffer transaction log
    Redo,         // replay buffer transaction log
}

/// Fragments that can be combined to specify a command
#[derive(Copy, Debug)]
#[allow(dead_code)]
pub enum Partial {
    Kind(Kind),
    Anchor(Anchor),
    Offset(Offset),
    Object(TextObject),
    Action(Action),
}

#[derive(Copy, Debug)]
#[allow(dead_code)]
pub enum Action {
    Operation(Operation),
    Instruction(Instruction),
}

/// A complete, actionable command
#[derive(Copy, Debug)]
pub struct Command {
    pub number: i32,        // numeric paramter, line number, repeat count, etc.
    pub action: Action,     // what to do
    pub object: Option<TextObject>, // where to do it
}

impl Command {
    /// Shortcut to create an ExitEditor command
    pub fn exit_editor() -> Command {
        Command {
            action: Action::Instruction(Instruction::ExitEditor),
            number: 0,
            object: None,
        }
    }

    /// Shortcut to create a SaveBuffer command
    pub fn save_buffer() -> Command {
        Command {
            action: Action::Instruction(Instruction::SaveBuffer),
            number: 0,
            object: None,
        }
    }

    /// Shortcut to create an Insert command
    pub fn insert_char(c: char) -> Command {
        Command {
            number: 1,
            action: Action::Operation(Operation::Insert(c)),
            object: None,
        }
    }

    /// Shortcut to create an Insert command
    // FIXME: shouldn't need this method
    pub fn insert_tab() -> Command {
        Command {
            number: 4,
            action: Action::Operation(Operation::Insert(' ')),
            object: None,
        }
    }

    /// Shortcut to create Undo command
    pub fn undo() -> Command {
        Command {
            number: 1,
            action: Action::Operation(Operation::Undo),
            object: None
        }
    }

    /// Shortcut to create Redo command
    pub fn redo() -> Command {
        Command {
            number: 1,
            action: Action::Operation(Operation::Redo),
            object: None
        }
    }
}

pub struct Builder {
    number: Option<i32>,
    repeat: Option<usize>,

    action: Option<Action>,
    mark: Option<Mark>,
    kind: Option<Kind>,
    anchor: Option<Anchor>,
    offset: Option<Offset>,
    object: Option<TextObject>,

    reading_number: bool,
    keymap: KeyMap<Partial>,
}

#[derive(Copy, Debug)]
pub enum BuilderEvent {
    Invalid,            // cannot find a valid interpretation
    Incomplete,         // needs more information
    Complete(Command),  // command is finished
}

impl Builder {
    pub fn new() -> Builder {
        Builder {
            number: None,
            repeat: None,
            action: None,
            mark: None,
            kind: None,
            anchor: None,
            offset: None,
            object: None,
            reading_number: false,
            keymap: default_keymap()
        }
    }

    pub fn reset(&mut self) {
        self.number = None;
        self.repeat = None;
        self.action = None;
        self.mark = None;
        self.kind = None;
        self.anchor = None;
        self.object = None;
        self.offset = None;
        self.reading_number = false;
    }

    pub fn check_key(&mut self, key: Key) -> BuilderEvent {
        if let Key::Char(c) = key {
            // '0' might be bound (start of line), and cannot be the start of a number sequence
            if c.is_digit(10) && (self.reading_number || c != '0') {
                let n = c.to_digit(10).unwrap();
                self.reading_number = true;
                self.append_digit(n);
                return BuilderEvent::Incomplete;
            } else if self.reading_number {

                self.reading_number = false;
            }
        }

        match self.keymap.check_key(key) {
            KeyMapState::Match(partial) => self.apply_partial(partial),
            KeyMapState::None           => { self.reset(); return BuilderEvent::Invalid; }
            _ => {},
        }

        if let Some(c) = self.complete_command() {
            self.reset();
            return BuilderEvent::Complete(c)
        } else {
            return BuilderEvent::Incomplete
        }
    }

    fn complete_object(&mut self) -> Option<TextObject> {
        let mut result: Option<TextObject> = if let Some(object) = self.object {
            // we have a complete object ready to go
            Some(object)
        } else if let Some(kind) = self.kind {
            // we have at least a kind
            Some(TextObject {
                kind: kind,
                offset: self.offset.unwrap_or(Offset::Absolute(0)),
            })
        } else {
            None
        };

        if let Some(ref mut object) = result {
            if let Some(number) = self.number {
                object.offset = object.offset.with_num(number as usize);
            }
        }

        result
    }

    fn complete_command(&mut self) -> Option<Command> {
        /* rules for completing commands:
              | action            | number | object | reference    | kind |   | result                                                            |
              | -                 | -      | -      | -            | -    | - | -                                                                 |
              | no                | no     | no     | no           | yes  |   | move cursor to next (default) text object with kind               |
              | no                | no     | no     | yes          | -    |   | move cursor to text object with reference + default anchor        |
              | no                | no     | yes    | -            | -    |   | move cursor to text object                                        |
              | no                | yes    | no     | no           | no   |   | incomplete                                                        |
              | no                | yes    | no     | no           | yes  |   | move cursor to nth instance of kind (from start of buffer)        |
              | no                | yes    | no     | yes (index)  | -    |   | set index to number, cursor to ref + default anchor               |
              | no                | yes    | no     | yes (offset) | -    |   | multiply offset by number, cursor to ref + default anchor         |
              | no                | yes    | no     | yes (mark)   | -    |   | incomplete                                                        |
              | yes (instruction) | -      | -      | -            | -    |   | send instruction to editor with whatever parameters are available |
              | yes (operation)   | no     | no     | no           | no   |   | incomplete                                                        |
              | yes (operation)   | no     | no     | no           | yes  |   | apply operation to kind at cursor (default anchor)                |
              | yes (operation)   | no     | no     | yes          | -    |   | apply operation to reference with default anchor                  |
              | yes (operation)   | no     | yes    | -            | -    |   | apply operation to object                                         |
              | yes (operation)   | yes    | no     | no           | no   |   | incomplete                                                        |
              | yes (operation)   | yes    | no     | no           | yes  |   | apply operation to nth instance of kind                           |
        */

        // editor instructions may not need a text object, go ahead and return immediately
        if let Some(Action::Instruction(i)) = self.action {
            return Some(Command {
                number: self.repeat.unwrap_or(1) as i32,
                action: Action::Instruction(i),
                object: self.complete_object()
            });
        }

        if let Some(to) = self.complete_object() {
            if let Some(Action::Operation(o)) = self.action {
                // we have an object, and an operation
                return Some(Command {
                    number: self.repeat.unwrap_or(1) as i32,
                    action: Action::Operation(o),
                    object: Some(to)
                });
            } else {
                // we have just an object, assume move cursor instruction
                return Some(Command {
                    number: self.repeat.unwrap_or(1) as i32,
                    action: Action::Instruction(Instruction::SetMark(Mark::Cursor(0))),
                    object: Some(to)
                });
            }
        }
        None
    }

    fn append_digit(&mut self, n: usize) {
        if let Some(current) = self.number {
            self.number = Some((current*10) + n as i32);
        } else {
            self.number = Some(n as i32);
        }
    }

    fn apply_partial(&mut self, partial: Partial) {
        match partial {
            Partial::Kind(k)      => self.kind = Some(k),
            Partial::Anchor(a)    => self.anchor = Some(a),
            Partial::Offset(o)    => self.offset = Some(o),
            Partial::Object(o)    => self.object = Some(o),
            Partial::Action(a)    => {
                self.action = Some(a);
                if !self.reading_number && self.number.is_some() && self.repeat.is_none() {
                    // the first number followed by an action is treated as a repetition
                    self.repeat = Some(self.number.unwrap() as usize);
                    self.number = None;
                }
            }
        }

        // propagate upwards from anchor to object
        // if both an object(a) and an anchor(b) have been applied, the resulting
        // object should be exactly the same as (a), only using (b) as the anchor
        if let Some(anchor) = self.anchor {
            if let Some(kind) = self.kind {
                self.kind = Some(kind.with_anchor(anchor));
            }
            if let Some(object) = self.object {
                self.object = Some(TextObject {
                    kind: object.kind.with_anchor(anchor),
                    offset: object.offset,
                });
            }
        }
        if let Some(kind) = self.kind {
            if let Some(ref mut object) = self.object {
                object.kind = kind;
            }
        }
        if let Some(offset) = self.offset {
            if let Some(ref mut object) = self.object {
                object.offset = offset;
            }
        }

        // propagate downwards from object to unset partials
        if let Some(object) = self.object {
            if self.offset.is_none() { self.offset = Some(object.offset); }
            if self.kind.is_none() { self.kind = Some(object.kind); }
            if self.anchor.is_none() { self.anchor = Some(object.kind.get_anchor()); }
        }

        if self.offset.is_some() && self.kind.is_some() && self.object.is_none() {
            self.object = Some(TextObject {
                kind: self.kind.unwrap(),
                offset: self.offset.unwrap(),
            });
        }
    }
}

fn default_keymap() -> KeyMap<Partial> {
    let mut keymap = KeyMap::new();

    // next/previous char
    keymap.bind_key(Key::Char('l'), Partial::Object(TextObject {
        kind: Kind::Char,
        offset: Offset::Forward(1, Mark::Cursor(0))
    }));
    keymap.bind_key(Key::Char('h'), Partial::Object(TextObject {
        kind: Kind::Char,
        offset: Offset::Backward(1, Mark::Cursor(0))
    }));

    // next/previous line
    keymap.bind_key(Key::Char('j'), Partial::Object(TextObject {
        kind: Kind::Line(Anchor::Same),
        offset: Offset::Forward(1, Mark::Cursor(0))
    }));
    keymap.bind_key(Key::Char('k'), Partial::Object(TextObject {
        kind: Kind::Line(Anchor::Same),
        offset: Offset::Backward(1, Mark::Cursor(0))
    }));

    // next/previous word
    keymap.bind_key(Key::Char('w'), Partial::Object(TextObject {
        kind: Kind::Word(Anchor::Before),
        offset: Offset::Forward(1, Mark::Cursor(0))
    }));
    keymap.bind_key(Key::Char('b'), Partial::Object(TextObject {
        kind: Kind::Word(Anchor::Before),
        offset: Offset::Backward(1, Mark::Cursor(0))
    }));

    // start/end line
    keymap.bind_key(Key::Char('$'), Partial::Object(TextObject {
        kind: Kind::Line(Anchor::End),
        offset: Offset::Forward(0, Mark::Cursor(0)),
    }));
    keymap.bind_key(Key::Char('0'), Partial::Object(TextObject {
        kind: Kind::Line(Anchor::Start),
        offset: Offset::Backward(0, Mark::Cursor(0)),
    }));

    // kinds
    keymap.bind_keys(&[Key::Char('`'), Key::Char('c')], Partial::Kind(Kind::Char));
    keymap.bind_keys(&[Key::Char('`'), Key::Char('w')], Partial::Kind(Kind::Word(Anchor::Start)));
    keymap.bind_keys(&[Key::Char('`'), Key::Char('l')], Partial::Kind(Kind::Line(Anchor::Start)));

    // anchors
    keymap.bind_key(Key::Char(','), Partial::Anchor(Anchor::Start));
    keymap.bind_key(Key::Char('.'), Partial::Anchor(Anchor::End));
    keymap.bind_key(Key::Char('<'), Partial::Anchor(Anchor::Before));
    keymap.bind_key(Key::Char('>'), Partial::Anchor(Anchor::After));

    // actions
    keymap.bind_key(Key::Char('d'), Partial::Action(Action::Operation(Operation::Delete)));
    keymap.bind_key(Key::Char(':'), Partial::Action(Action::Instruction(Instruction::SetOverlay(OverlayType::Prompt))));

    keymap
}
<|endoftext|>


<commit_before>use serde::{Serialize, Serializer};
use tree_sitter::{Language, Parser, Query, QueryCursor, QueryError};

/// Contains the data neeeded to compute tags for code written in a
/// particular language.
pub struct TagsConfiguration {
    pub language: Language,
    pub query: Query,
    locals_pattern_index: usize,
}

pub struct TagsContext {
    parser: Parser,
    cursor: QueryCursor,
}

#[derive(Serialize)]
pub struct Range {
    pub start: i64,
    pub end: i64,
}

#[derive(Serialize)]
pub struct Loc {
    pub byte_range: Range,
    pub span: Span,
}

#[derive(Serialize)]
pub struct Span {
    pub start: Pos,
    pub end: Pos,
}

#[derive(Serialize)]
pub struct Pos {
    pub line: i64,
    pub column: i64,
}

pub enum TagKind {
    Function,
    Method,
    Class,
    Module,
    Call,
}

#[derive(Serialize)]
pub struct Tag<'a> {
    pub kind: TagKind,
    pub loc: Loc,
    pub name: &'a str,
    pub line: &'a str,
    pub docs: Option<&'a str>,
}

impl Serialize for TagKind {
    fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        match self {
            TagKind::Call => "Call".serialize(s),
            TagKind::Module => "Module".serialize(s),
            TagKind::Class => "Class".serialize(s),
            TagKind::Method => "Method".serialize(s),
            TagKind::Function => "Function".serialize(s),
        }
    }
}

impl TagsConfiguration {
    pub fn new(
        language: Language,
        tags_query: &str,
        locals_query: &str,
    ) -> Result<Self, QueryError> {
        let query = Query::new(language, &format!("{}{}", tags_query, locals_query))?;

        let locals_query_offset = tags_query.len();
        let mut locals_pattern_index = 0;
        for i in 0..(query.pattern_count()) {
            let pattern_offset = query.start_byte_for_pattern(i);
            if pattern_offset < locals_query_offset {
                locals_pattern_index += 1;
            }
        }

        query.pattern_count();
        query.start_byte_for_pattern(5);
        Ok(TagsConfiguration {
            language,
            query,
            locals_pattern_index,
        })
    }
}

impl TagsContext {
    pub fn new() -> Self {
        TagsContext {
            parser: Parser::new(),
            cursor: QueryCursor::new(),
        }
    }

    pub fn generate_tags(&mut self, config: &TagsConfiguration, source: &[u8]) -> Vec<Tag> {
        Vec::new()
    }
}
<commit_msg>Simplify Serialize implementation for TagKind.<commit_after>use serde::{Serialize, Serializer};
use tree_sitter::{Language, Parser, Query, QueryCursor, QueryError};

/// Contains the data neeeded to compute tags for code written in a
/// particular language.
pub struct TagsConfiguration {
    pub language: Language,
    pub query: Query,
    locals_pattern_index: usize,
}

pub struct TagsContext {
    parser: Parser,
    cursor: QueryCursor,
}

#[derive(Serialize)]
pub struct Range {
    pub start: i64,
    pub end: i64,
}

#[derive(Serialize)]
pub struct Loc {
    pub byte_range: Range,
    pub span: Span,
}

#[derive(Serialize)]
pub struct Span {
    pub start: Pos,
    pub end: Pos,
}

#[derive(Serialize)]
pub struct Pos {
    pub line: i64,
    pub column: i64,
}

pub enum TagKind {
    Function,
    Method,
    Class,
    Module,
    Call,
}

#[derive(Serialize)]
pub struct Tag<'a> {
    pub kind: TagKind,
    pub loc: Loc,
    pub name: &'a str,
    pub line: &'a str,
    pub docs: Option<&'a str>,
}

impl Serialize for TagKind {
    fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        match self {
            TagKind::Call => "Call",
            TagKind::Module => "Module",
            TagKind::Class => "Class",
            TagKind::Method => "Method",
            TagKind::Function => "Function",
        }
        .serialize(s)
    }
}

impl TagsConfiguration {
    pub fn new(
        language: Language,
        tags_query: &str,
        locals_query: &str,
    ) -> Result<Self, QueryError> {
        let query = Query::new(language, &format!("{}{}", tags_query, locals_query))?;

        let locals_query_offset = tags_query.len();
        let mut locals_pattern_index = 0;
        for i in 0..(query.pattern_count()) {
            let pattern_offset = query.start_byte_for_pattern(i);
            if pattern_offset < locals_query_offset {
                locals_pattern_index += 1;
            }
        }

        query.pattern_count();
        query.start_byte_for_pattern(5);
        Ok(TagsConfiguration {
            language,
            query,
            locals_pattern_index,
        })
    }
}

impl TagsContext {
    pub fn new() -> Self {
        TagsContext {
            parser: Parser::new(),
            cursor: QueryCursor::new(),
        }
    }

    pub fn generate_tags(&mut self, config: &TagsConfiguration, source: &[u8]) -> Vec<Tag> {
        Vec::new()
    }
}
<|endoftext|>


<commit_before>use ncurses as nc;
use std::cmp;
use unicode_width::UnicodeWidthChar;

use screen_data::ScreenData;

pub struct Window {
    rect: Rect,
    win: nc::WINDOW,
    win_impl: Box<WindowImpl + Send>
}

impl Window {
    pub fn new<WI>(win_impl: WI, r: Rect) -> Window
        where WI: WindowImpl + Send + 'static
    {
        let win = nc::newwin(r.height, r.width, r.y, r.x);
        nc::leaveok(win, true);
        Window {
            rect: r,
            win: win,
            win_impl: Box::new(win_impl)
        }
    }

    pub fn draw(&self, sd: &ScreenData) {
        self.win_impl.draw(self.win, self.rect, sd);
    }

    pub fn clear(&self) {
        nc::wclear(self.win);
    }

    pub fn noutrefresh(&self) {
        nc::wnoutrefresh(self.win);
    }

    pub fn resize(&mut self, r: Rect) {
        self.rect = r;
        nc::mvwin(self.win, r.y, r.x);
        unsafe {
            wresize(self.win, r.height, r.width);
        }
    }

    pub fn rect(&self) -> Rect {
        self.rect
    }
}

pub trait WindowImpl {
    fn draw(&self, win: nc::WINDOW, r: Rect, sd: &ScreenData);
}

pub struct Gutter;

impl WindowImpl for Gutter {
    fn draw(&self, win: nc::WINDOW, _r: Rect, sd: &ScreenData) {
        if let Some(row) = sd.highlighted_row {
            let y = row as i32;
            nc::mvwaddstr(win, y, 0, ">");
        }
        for row in sd.marked_rows.iter() {
            let y = *row as i32;
            nc::mvwaddstr(win, y, 1, ">");
        }
    }
}

pub struct MiniBuf;

impl WindowImpl for MiniBuf {
    fn draw(&self, win: nc::WINDOW, _r: Rect, sd: &ScreenData) {
        nc::mvwaddstr(win, 0, 0, &*sd.query_string);
    }
}

impl MiniBuf {
    pub fn set_cursor(win: &Window, cursor_index: i32) {
        let mut beg_y = 0i32;
        let mut beg_x = 0i32;
        nc::getbegyx(win.win, &mut beg_y, &mut beg_x);
        let mut cur_y = 0i32;
        let mut cur_x = 0i32;
        nc::getyx(win.win, &mut cur_y, &mut cur_x);
        let x_offset = 0; // use someday
        let mut scr_cur_y = beg_y + cur_y;
        let mut scr_cur_x = beg_x + x_offset + cursor_index;
        nc::setsyx(&mut scr_cur_y, &mut scr_cur_x);
    }
}

pub struct ListView;

impl WindowImpl for ListView {
    fn draw(&self, win: nc::WINDOW, r: Rect, sd: &ScreenData) {
        let num_lines = cmp::min(sd.items.len(), r.height as usize);
        for (y, item) in sd.items.iter().take(num_lines).enumerate() {
            let s = item.as_str();
            let sliced = slice_by_width(s, r.width as usize, sd.is_cjk);
            nc::mvwaddstr(win, y as i32, 0, sliced);
        }
    }
}

pub struct StatusLine;

impl WindowImpl for StatusLine {
    fn draw(&self, win: nc::WINDOW, _r: Rect, sd: &ScreenData) {
        let msg = sd.status_message.as_ref().map(|s| s.as_ref()).unwrap_or("");
        let s = format!("{}/{} {}", sd.item_list_len, sd.total_lines, msg);
        nc::mvwaddstr(win, 0, 0, &s);
    }
}

#[derive(Clone, Copy)]
pub struct Rect {
    pub height: i32,
    pub width: i32,
    pub y: i32,
    pub x: i32,
}

fn slice_by_width(s: &str, slice_width: usize, is_cjk: bool) -> &str {
    let mut bytes = 0;
    let mut width = 0;
    for ch in s.chars() {
        let w = match is_cjk {
            true => UnicodeWidthChar::width_cjk(ch).unwrap_or(0),
            false => UnicodeWidthChar::width(ch).unwrap_or(0),
        };
        if width + w > slice_width {
            break;
        }
        width += w;
        bytes += ch.len_utf8();
    }
    &s[..bytes]
}

// ncurses-rs 5.73.0 does't provide this function yet.
extern {
    fn wresize(win: nc::WINDOW, lines: ::libc::c_int, columns: ::libc::c_int);
}
<commit_msg>Disable warnings for ncurces::WINDOW<commit_after>#![allow(improper_ctypes)] // for nc::WINDOW

use ncurses as nc;
use std::cmp;
use unicode_width::UnicodeWidthChar;

use screen_data::ScreenData;

pub struct Window {
    rect: Rect,
    win: nc::WINDOW,
    win_impl: Box<WindowImpl + Send>
}

impl Window {
    pub fn new<WI>(win_impl: WI, r: Rect) -> Window
        where WI: WindowImpl + Send + 'static
    {
        let win = nc::newwin(r.height, r.width, r.y, r.x);
        nc::leaveok(win, true);
        Window {
            rect: r,
            win: win,
            win_impl: Box::new(win_impl)
        }
    }

    pub fn draw(&self, sd: &ScreenData) {
        self.win_impl.draw(self.win, self.rect, sd);
    }

    pub fn clear(&self) {
        nc::wclear(self.win);
    }

    pub fn noutrefresh(&self) {
        nc::wnoutrefresh(self.win);
    }

    pub fn resize(&mut self, r: Rect) {
        self.rect = r;
        nc::mvwin(self.win, r.y, r.x);
        unsafe {
            wresize(self.win, r.height, r.width);
        }
    }

    pub fn rect(&self) -> Rect {
        self.rect
    }
}

pub trait WindowImpl {
    fn draw(&self, win: nc::WINDOW, r: Rect, sd: &ScreenData);
}

pub struct Gutter;

impl WindowImpl for Gutter {
    fn draw(&self, win: nc::WINDOW, _r: Rect, sd: &ScreenData) {
        if let Some(row) = sd.highlighted_row {
            let y = row as i32;
            nc::mvwaddstr(win, y, 0, ">");
        }
        for row in sd.marked_rows.iter() {
            let y = *row as i32;
            nc::mvwaddstr(win, y, 1, ">");
        }
    }
}

pub struct MiniBuf;

impl WindowImpl for MiniBuf {
    fn draw(&self, win: nc::WINDOW, _r: Rect, sd: &ScreenData) {
        nc::mvwaddstr(win, 0, 0, &*sd.query_string);
    }
}

impl MiniBuf {
    pub fn set_cursor(win: &Window, cursor_index: i32) {
        let mut beg_y = 0i32;
        let mut beg_x = 0i32;
        nc::getbegyx(win.win, &mut beg_y, &mut beg_x);
        let mut cur_y = 0i32;
        let mut cur_x = 0i32;
        nc::getyx(win.win, &mut cur_y, &mut cur_x);
        let x_offset = 0; // use someday
        let mut scr_cur_y = beg_y + cur_y;
        let mut scr_cur_x = beg_x + x_offset + cursor_index;
        nc::setsyx(&mut scr_cur_y, &mut scr_cur_x);
    }
}

pub struct ListView;

impl WindowImpl for ListView {
    fn draw(&self, win: nc::WINDOW, r: Rect, sd: &ScreenData) {
        let num_lines = cmp::min(sd.items.len(), r.height as usize);
        for (y, item) in sd.items.iter().take(num_lines).enumerate() {
            let s = item.as_str();
            let sliced = slice_by_width(s, r.width as usize, sd.is_cjk);
            nc::mvwaddstr(win, y as i32, 0, sliced);
        }
    }
}

pub struct StatusLine;

impl WindowImpl for StatusLine {
    fn draw(&self, win: nc::WINDOW, _r: Rect, sd: &ScreenData) {
        let msg = sd.status_message.as_ref().map(|s| s.as_ref()).unwrap_or("");
        let s = format!("{}/{} {}", sd.item_list_len, sd.total_lines, msg);
        nc::mvwaddstr(win, 0, 0, &s);
    }
}

#[derive(Clone, Copy)]
pub struct Rect {
    pub height: i32,
    pub width: i32,
    pub y: i32,
    pub x: i32,
}

fn slice_by_width(s: &str, slice_width: usize, is_cjk: bool) -> &str {
    let mut bytes = 0;
    let mut width = 0;
    for ch in s.chars() {
        let w = match is_cjk {
            true => UnicodeWidthChar::width_cjk(ch).unwrap_or(0),
            false => UnicodeWidthChar::width(ch).unwrap_or(0),
        };
        if width + w > slice_width {
            break;
        }
        width += w;
        bytes += ch.len_utf8();
    }
    &s[..bytes]
}

// ncurses-rs 5.73.0 does't provide this function yet.
extern {
    fn wresize(win: nc::WINDOW, lines: ::libc::c_int, columns: ::libc::c_int);
}
<|endoftext|>


<commit_before>// Copyright 2015 Deyan Ginev. See the LICENSE
// file at the top-level directory of this distribution.
//
// Licensed under the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>.
// This file may not be copied, modified, or distributed
// except according to those terms.
extern crate zmq;
extern crate rand;
extern crate tempfile;

use zmq::{Error, Message, Context, SNDMORE};
use std::ops::Deref;
use std::thread;
use std::env;
use std::fs::File;
use std::io::{Read,Write, Seek, SeekFrom};
use std::path::Path;
// use std::str;
use std::process::Command;
use rand::{random};

pub trait Worker {
  // fn work(&self, &Message) -> Option<Message>;
  fn convert(&self, &Path) -> Option<File>;
  fn message_size(&self) -> usize;
  fn service(&self) -> String;
  fn source(&self) -> String;
  fn sink(&self) -> String;

  fn start(&self, limit : Option<i32>) -> Result<(), Error> {
    let mut work_counter = 0;
    // Connect to a task ventilator
    let mut context_source = Context::new();
    let mut source = context_source.socket(zmq::DEALER).unwrap();
    let identity : String = (0..10).map(|_| rand::random::<u8>() as char).collect();
    source.set_identity(identity.as_bytes()).unwrap();

    assert!(source.connect(&self.source()).is_ok());
    // Connect to a task sink
    let mut context_sink = Context::new();
    let mut sink = context_sink.socket(zmq::PUSH).unwrap();
    assert!(sink.connect(&self.sink()).is_ok());
    // Work in perpetuity
    loop {
      let mut taskid_msg = Message::new().unwrap();
      let mut recv_msg = Message::new().unwrap();

      source.send_str(&self.service(), 0).unwrap();
      source.recv(&mut taskid_msg, 0).unwrap();
      let taskid = taskid_msg.as_str().unwrap();

      // Prepare a File for the input
      let input_filepath = env::temp_dir().to_str().unwrap().to_string() + "/" + taskid ;
      let mut file = File::create(input_filepath.clone()).unwrap();
      loop {
        source.recv(&mut recv_msg, 0).unwrap();

        file.write(recv_msg.deref()).unwrap();
        if !source.get_rcvmore().unwrap() {
          break;
        }
      }

      file.seek(SeekFrom::Start(0)).unwrap();
      let file_opt = self.convert(Path::new(&input_filepath));
      if file_opt.is_some() {
        let mut converted_file = file_opt.unwrap();
        sink.send_str(&self.service(), SNDMORE).unwrap();
        sink.send_str(taskid, SNDMORE).unwrap();
        loop {
          // Stream converted data via zmq
          let message_size = self.message_size();
          let mut data = vec![0; message_size];
          let size = converted_file.read(&mut data).unwrap();
          data.truncate(size);
          if size < message_size {
            // If exhausted, send the last frame
            sink.send(&data,0).unwrap();
            // And terminate
            break;
          } else {
            // If more to go, send the frame and indicate there's more to come
            sink.send(&data,SNDMORE).unwrap();
          }
        }
      }
      else {
        // If there was nothing to do, retry a minute later
        thread::sleep_ms(60000);
        continue
      }

      work_counter += 1;
      match limit {
        Some(upper_bound) => {
          if work_counter >= upper_bound {
            // Give enough time to complete the Final job.
            thread::sleep_ms(500);
            break;
          }
        },
        None => {}
      };
    }
    Ok(())
  }
}
pub struct EchoWorker {
  pub service : String,
  pub version : f32,
  pub message_size : usize,
  pub source : String,
  pub sink : String
}
impl Default for EchoWorker {
  fn default() -> EchoWorker {
    EchoWorker {
      service: "echo_service".to_string(),
      version: 0.1,
      message_size: 100000,
      source: "tcp://localhost:5555".to_string(),
      sink: "tcp://localhost:5556".to_string()
    }
  }
}
impl Worker for EchoWorker {
  fn service(&self) -> String {self.service.clone()}
  fn source(&self) -> String {self.source.clone()}
  fn sink(&self) -> String {self.sink.clone()}
  fn message_size(&self) -> usize {self.message_size.clone()}

  fn convert(&self, path : &Path) -> Option<File> {
    Some(File::open(path).unwrap())
  }
}

pub struct TexToHtmlWorker {
  pub service : String,
  pub version : f32,
  pub message_size : usize,
  pub source : String,
  pub sink : String
}
impl Default for TexToHtmlWorker {
  fn default() -> TexToHtmlWorker {
    TexToHtmlWorker {
      service: "tex_to_html".to_string(),
      version: 0.1,
      message_size: 100000,
      source: "tcp://localhost:5555".to_string(),
      sink: "tcp://localhost:5556".to_string()
    }
  }
}
impl Worker for TexToHtmlWorker {
  fn service(&self) -> String {self.service.clone()}
  fn source(&self) -> String {self.source.clone()}
  fn sink(&self) -> String {self.sink.clone()}
  fn message_size(&self) -> usize {self.message_size.clone()}

  fn convert(&self, path : &Path) -> Option<File> {
    let name = path.file_stem().unwrap().to_str().unwrap();
    let destination_path = env::temp_dir().to_str().unwrap().to_string() + "/" +name+ ".zip";

    Command::new("latexmlc")
      .arg("--whatsin")
      .arg("archive")
      .arg("--whatsout")
      .arg("archive")
      .arg("--format")
      .arg("html5")
      .arg("--pmml")
      .arg("--cmml")
      .arg("--preload")
      .arg("[ids]latexml.sty")
      .arg("--css")
      .arg("http://latexml.mathweb.org/css/external/LaTeXML.css")
      .arg("--nodefaultresources")
      .arg("--inputencoding")
      .arg("iso-8859-1")
      .arg("--timeout")
      .arg("300")
      .arg("--log")
      .arg(name.to_string() + ".log")
      .arg("--destination")
      .arg(destination_path.clone())
      .arg(path.clone())
      .output()
      .unwrap_or_else(|e| { panic!("failed to execute process: {}", e) });

    // println!("Dest: {:?}", destination_path);
    // println!("Log: {:?}", str::from_utf8(&output.stderr));
    Some(File::open(destination_path.clone()).unwrap())
  }
}
<commit_msg>temporary debug prints<commit_after>// Copyright 2015 Deyan Ginev. See the LICENSE
// file at the top-level directory of this distribution.
//
// Licensed under the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>.
// This file may not be copied, modified, or distributed
// except according to those terms.
extern crate zmq;
extern crate rand;
extern crate tempfile;

use zmq::{Error, Message, Context, SNDMORE};
use std::ops::Deref;
use std::thread;
use std::env;
use std::fs::File;
use std::io::{Read,Write, Seek, SeekFrom};
use std::path::Path;
use std::str;
use std::process::Command;
use rand::{random};

pub trait Worker {
  // fn work(&self, &Message) -> Option<Message>;
  fn convert(&self, &Path) -> Option<File>;
  fn message_size(&self) -> usize;
  fn service(&self) -> String;
  fn source(&self) -> String;
  fn sink(&self) -> String;

  fn start(&self, limit : Option<i32>) -> Result<(), Error> {
    let mut work_counter = 0;
    // Connect to a task ventilator
    let mut context_source = Context::new();
    let mut source = context_source.socket(zmq::DEALER).unwrap();
    let identity : String = (0..10).map(|_| rand::random::<u8>() as char).collect();
    source.set_identity(identity.as_bytes()).unwrap();

    assert!(source.connect(&self.source()).is_ok());
    // Connect to a task sink
    let mut context_sink = Context::new();
    let mut sink = context_sink.socket(zmq::PUSH).unwrap();
    assert!(sink.connect(&self.sink()).is_ok());
    // Work in perpetuity
    loop {
      let mut taskid_msg = Message::new().unwrap();
      let mut recv_msg = Message::new().unwrap();

      source.send_str(&self.service(), 0).unwrap();
      source.recv(&mut taskid_msg, 0).unwrap();
      let taskid = taskid_msg.as_str().unwrap();

      // Prepare a File for the input
      println!("--- Create a file ");
      let input_filepath = env::temp_dir().to_str().unwrap().to_string() + "/" + taskid ;
      let mut file = File::create(input_filepath.clone()).unwrap();
      println!("--- Receive content. ");
      loop {
        source.recv(&mut recv_msg, 0).unwrap();

        file.write(recv_msg.deref()).unwrap();
        if !source.get_rcvmore().unwrap() {
          break;
        }
      }
      println!("--- Data received at {:?} ", input_filepath);

      file.seek(SeekFrom::Start(0)).unwrap();
      println!("--- Starting worker convert. ");
      let file_opt = self.convert(Path::new(&input_filepath));
      println!("--- Ending worker convert. ");
      if file_opt.is_some() {
        let mut converted_file = file_opt.unwrap();
        sink.send_str(&self.service(), SNDMORE).unwrap();
        sink.send_str(taskid, SNDMORE).unwrap();
        loop {
          // Stream converted data via zmq
          let message_size = self.message_size();
          let mut data = vec![0; message_size];
          let size = converted_file.read(&mut data).unwrap();
          data.truncate(size);
          if size < message_size {
            // If exhausted, send the last frame
            sink.send(&data,0).unwrap();
            // And terminate
            break;
          } else {
            // If more to go, send the frame and indicate there's more to come
            sink.send(&data,SNDMORE).unwrap();
          }
        }
      }
      else {
        // If there was nothing to do, retry a minute later
        thread::sleep_ms(60000);
        continue
      }

      work_counter += 1;
      match limit {
        Some(upper_bound) => {
          if work_counter >= upper_bound {
            // Give enough time to complete the Final job.
            thread::sleep_ms(500);
            break;
          }
        },
        None => {}
      };
    }
    Ok(())
  }
}
pub struct EchoWorker {
  pub service : String,
  pub version : f32,
  pub message_size : usize,
  pub source : String,
  pub sink : String
}
impl Default for EchoWorker {
  fn default() -> EchoWorker {
    EchoWorker {
      service: "echo_service".to_string(),
      version: 0.1,
      message_size: 100000,
      source: "tcp://localhost:5555".to_string(),
      sink: "tcp://localhost:5556".to_string()
    }
  }
}
impl Worker for EchoWorker {
  fn service(&self) -> String {self.service.clone()}
  fn source(&self) -> String {self.source.clone()}
  fn sink(&self) -> String {self.sink.clone()}
  fn message_size(&self) -> usize {self.message_size.clone()}

  fn convert(&self, path : &Path) -> Option<File> {
    Some(File::open(path).unwrap())
  }
}

pub struct TexToHtmlWorker {
  pub service : String,
  pub version : f32,
  pub message_size : usize,
  pub source : String,
  pub sink : String
}
impl Default for TexToHtmlWorker {
  fn default() -> TexToHtmlWorker {
    TexToHtmlWorker {
      service: "tex_to_html".to_string(),
      version: 0.1,
      message_size: 100000,
      source: "tcp://localhost:5555".to_string(),
      sink: "tcp://localhost:5556".to_string()
    }
  }
}
impl Worker for TexToHtmlWorker {
  fn service(&self) -> String {self.service.clone()}
  fn source(&self) -> String {self.source.clone()}
  fn sink(&self) -> String {self.sink.clone()}
  fn message_size(&self) -> usize {self.message_size.clone()}

  fn convert(&self, path : &Path) -> Option<File> {
    let name = path.file_stem().unwrap().to_str().unwrap();
    let destination_path = env::temp_dir().to_str().unwrap().to_string() + "/" +name+ ".zip";

    let output = Command::new("latexmlc")
      .arg("--whatsin")
      .arg("archive")
      .arg("--whatsout")
      .arg("archive")
      .arg("--format")
      .arg("html5")
      .arg("--pmml")
      .arg("--cmml")
      .arg("--preload")
      .arg("[ids]latexml.sty")
      .arg("--css")
      .arg("http://latexml.mathweb.org/css/external/LaTeXML.css")
      .arg("--nodefaultresources")
      .arg("--inputencoding")
      .arg("iso-8859-1")
      .arg("--timeout")
      .arg("300")
      .arg("--log")
      .arg(name.to_string() + ".log")
      .arg("--destination")
      .arg(destination_path.clone())
      .arg(path.clone())
      .output()
      .unwrap_or_else(|e| { panic!("failed to execute process: {}", e) });

    println!("Dest: {:?}", destination_path);
    println!("Log: {:?}", str::from_utf8(&output.stderr));
    Some(File::open(destination_path.clone()).unwrap())
  }
}
<|endoftext|>


<commit_before><commit_msg>Small fixes after review<commit_after><|endoftext|>