Rename TokenizedCommand to CommandTemplate

This commit is contained in:
Matthias Reitinger 2017-11-15 02:14:04 +01:00 committed by David Peter
parent c18caaa6f6
commit 0f82fe7ec0
4 changed files with 61 additions and 66 deletions

View File

@ -10,16 +10,12 @@ use std::path::PathBuf;
use std::sync::{Arc, Mutex};
use std::sync::mpsc::Receiver;
use super::TokenizedCommand;
use super::CommandTemplate;
/// An event loop that listens for inputs from the `rx` receiver. Each received input will
/// generate a command with the supplied command template. The generated command will then
/// be executed, and this process will continue until the receiver's sender has closed.
pub fn job(
rx: Arc<Mutex<Receiver<PathBuf>>>,
cmd: Arc<TokenizedCommand>,
out_perm: Arc<Mutex<()>>,
) {
pub fn job(rx: Arc<Mutex<Receiver<PathBuf>>>, cmd: Arc<CommandTemplate>, out_perm: Arc<Mutex<()>>) {
loop {
// Create a lock on the shared receiver for this thread.
let lock = rx.lock().unwrap();

View File

@ -24,52 +24,17 @@ use self::command::execute_command;
use self::token::Token;
pub use self::job::job;
/// Contains a collection of `TokenizedArgument`s that are utilized to generate command strings.
/// Represents a template that is utilized to generate command strings.
///
/// The arguments are a representation of the supplied command template, and are meant to be coupled
/// with an input in order to generate a command. The `generate_and_execute()` method will be used
/// to generate a command and execute it.
/// The template is meant to be coupled with an input in order to generate a command. The
/// `generate_and_execute()` method will be used to generate a command and execute it.
#[derive(Debug, Clone, PartialEq)]
pub struct TokenizedCommand {
args: Vec<TokenizedArgument>,
pub struct CommandTemplate {
args: Vec<ArgumentTemplate>,
}
/// Represents 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 TokenizedArgument {
Tokens(Vec<Token>),
Text(String),
}
impl TokenizedArgument {
pub fn generate<'a>(&'a self, path: &str) -> Cow<'a, str> {
use self::Token::*;
match *self {
TokenizedArgument::Tokens(ref tokens) => {
let mut s = String::new();
for token in tokens {
match *token {
Basename => s += basename(path),
BasenameNoExt => s += remove_extension(basename(path)),
NoExt => s += remove_extension(path),
Parent => s += dirname(path),
Placeholder => s += path,
Text(ref string) => s += string,
}
}
Cow::Owned(s)
}
TokenizedArgument::Text(ref text) => Cow::Borrowed(text),
}
}
}
impl TokenizedCommand {
pub fn new<I, S>(input: I) -> TokenizedCommand
impl CommandTemplate {
pub fn new<I, S>(input: I) -> CommandTemplate
where
I: IntoIterator<Item = S>,
S: AsRef<str>,
@ -109,7 +74,7 @@ impl TokenizedCommand {
// Without a placeholder, the argument is just fixed text.
if tokens.is_empty() {
args.push(TokenizedArgument::Text(arg.to_owned()));
args.push(ArgumentTemplate::Text(arg.to_owned()));
continue;
}
@ -118,15 +83,15 @@ impl TokenizedCommand {
tokens.push(Token::Text(arg[start..].to_owned()));
}
args.push(TokenizedArgument::Tokens(tokens));
args.push(ArgumentTemplate::Tokens(tokens));
}
// If a placeholder token was not supplied, append one at the end of the command.
if !has_placeholder {
args.push(TokenizedArgument::Tokens(vec![Token::Placeholder]));
args.push(ArgumentTemplate::Tokens(vec![Token::Placeholder]));
}
TokenizedCommand { args: args }
CommandTemplate { args: args }
}
/// Generates and executes a command.
@ -149,28 +114,62 @@ impl TokenizedCommand {
}
}
/// 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 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 {
match *token {
Basename => s += basename(path),
BasenameNoExt => s += remove_extension(basename(path)),
NoExt => s += remove_extension(path),
Parent => s += dirname(path),
Placeholder => s += path,
Text(ref string) => s += string,
}
}
Cow::Owned(s)
}
ArgumentTemplate::Text(ref text) => Cow::Borrowed(text),
}
}
}
#[cfg(test)]
mod tests {
use super::{TokenizedCommand, TokenizedArgument, Token};
use super::{CommandTemplate, ArgumentTemplate, Token};
#[test]
fn tokens() {
let expected = TokenizedCommand {
let expected = CommandTemplate {
args: vec![
TokenizedArgument::Text("echo".into()),
TokenizedArgument::Text("${SHELL}:".into()),
TokenizedArgument::Tokens(vec![Token::Placeholder]),
ArgumentTemplate::Text("echo".into()),
ArgumentTemplate::Text("${SHELL}:".into()),
ArgumentTemplate::Tokens(vec![Token::Placeholder]),
],
};
assert_eq!(TokenizedCommand::new(&[&"echo", &"${SHELL}:"]), expected);
assert_eq!(CommandTemplate::new(&[&"echo", &"${SHELL}:"]), expected);
assert_eq!(
TokenizedCommand::new(&["echo", "{.}"]),
TokenizedCommand {
CommandTemplate::new(&["echo", "{.}"]),
CommandTemplate {
args: vec![
TokenizedArgument::Text("echo".into()),
TokenizedArgument::Tokens(vec![Token::NoExt]),
ArgumentTemplate::Text("echo".into()),
ArgumentTemplate::Tokens(vec![Token::NoExt]),
],
}
);

View File

@ -10,7 +10,7 @@ use std::process;
use std::time;
use std::io::Write;
use exec::TokenizedCommand;
use exec::CommandTemplate;
use lscolors::LsColors;
use walk::FileType;
use regex_syntax::{Expr, ExprBuilder};
@ -76,7 +76,7 @@ pub struct FdOptions {
pub extension: Option<String>,
/// If a value is supplied, each item found will be used to generate and execute commands.
pub command: Option<TokenizedCommand>,
pub command: Option<CommandTemplate>,
/// A list of glob patterns that should be excluded from the search.
pub exclude_patterns: Vec<String>,

View File

@ -39,7 +39,7 @@ use std::time;
use atty::Stream;
use regex::RegexBuilder;
use exec::TokenizedCommand;
use exec::CommandTemplate;
use internal::{error, pattern_has_uppercase_char, FdOptions, PathDisplay};
use lscolors::LsColors;
use walk::FileType;
@ -105,7 +105,7 @@ fn main() {
None
};
let command = matches.values_of("exec").map(TokenizedCommand::new);
let command = matches.values_of("exec").map(CommandTemplate::new);
let config = FdOptions {
case_sensitive,