Repository: sharkdp/fd
File: src/exec/mod.rs (Rust)

Code before:
        I: Iterator<Item = PathBuf>,
    {
        let mut cmd = Command::new(self.args[0].generate("").as_ref());
        let mut paths = paths.map(|p| Self::prepare_path(&p));
        let mut has_path = false;

        for arg in &self.args[1..] {
            if arg.has_tokens() {
                // A single `Tokens` is expected
                // So we can directy consume the iterator once and for all
                for path in &mut paths {
                    cmd.arg(arg.generate(&path).as_ref());
                    has_path = true;
                }
            } else {
                cmd.arg(arg.generate("").as_ref());
            }
        }

        if has_path {
            execute_command(cmd, &Mutex::new(()));
        }
    }
}

/// Represents a template for a single command argument.
///
/// The argument is either a collection of `Token`s including at least one placeholder variant, or
/// a fixed text.
#[derive(Clone, Debug, PartialEq)]
enum ArgumentTemplate {
    Tokens(Vec<Token>),
    Text(String),
}

impl ArgumentTemplate {
    pub fn has_tokens(&self) -> bool {
        if let ArgumentTemplate::Tokens(_) = self {
            true
        } else {
            false
        }
    }

    pub fn generate<'a>(&'a self, path: &str) -> Cow<'a, str> {
        use self::Token::*;

        match *self {
            ArgumentTemplate::Tokens(ref tokens) => {
                let mut s = String::new();
                for token in tokens {

Review comment (performance):
If we add the following lines here:
```rust
cmd.stdin(Stdio::inherit());
cmd.stdout(Stdio::inherit());
cmd.stderr(Stdio::inherit());
```

we can use `--exec-batch` with interactive terminal commands such as `vim`.

Code after:

    pub fn generate_and_execute_batch<I>(&self, paths: I)
    where
        I: Iterator<Item = PathBuf>,
    {
        let mut cmd = Command::new(self.args[0].generate("").as_ref());
        cmd.stdin(Stdio::inherit());
        cmd.stdout(Stdio::inherit());
        cmd.stderr(Stdio::inherit());

        let mut paths = paths.map(|p| Self::prepare_path(&p));
        let mut has_path = false;

        for arg in &self.args[1..] {
            if arg.has_tokens() {
                // A single `Tokens` is expected
                // So we can directy consume the iterator once and for all
                for path in &mut paths {
                    cmd.arg(arg.generate(&path).as_ref());
                    has_path = true;
                }
            } else {
                cmd.arg(arg.generate("").as_ref());
            }
        }

        if has_path {
            execute_command(cmd, &Mutex::new(()));
        }
    }
}

/// Represents a template for a single command argument.
///
/// The argument is either a collection of `Token`s including at least one placeholder variant, or
/// a fixed text.
#[derive(Clone, Debug, PartialEq)]
enum ArgumentTemplate {
    Tokens(Vec<Token>),
    Text(String),
}

impl ArgumentTemplate {
    pub fn has_tokens(&self) -> bool {
        match self {
            ArgumentTemplate::Tokens(_) => true,
            _ => false,
        }
    }

    pub fn generate<'a>(&'a self, path: &str) -> Cow<'a, str> {