Skip to content

Commit

Permalink
Add flags to set and clear shell arguments (#551)
Browse files Browse the repository at this point in the history
Add the `--shell-arg` and `--clear-shell-args` flags, which allow
setting and clearing arguments to the shell from the command line.

This allows full control over the shell from the command line. Additionally,
any shell-related arguments on the command line override
 `set shell := [...]` in the Justfile, which I think will be the behavior that most
people expect.
  • Loading branch information
casey authored Nov 22, 2019
1 parent d2decbf commit d0e813c
Show file tree
Hide file tree
Showing 5 changed files with 193 additions and 39 deletions.
2 changes: 1 addition & 1 deletion src/assignment_evaluator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ impl<'a, 'b> AssignmentEvaluator<'a, 'b> {
raw: &str,
token: &Token<'a>,
) -> RunResult<'a, String> {
let mut cmd = self.settings.shell_command(&self.config.shell);
let mut cmd = self.settings.shell_command(self.config);

cmd.arg(raw);

Expand Down
132 changes: 118 additions & 14 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use clap::{App, AppSettings, Arg, ArgGroup, ArgMatches};
use unicode_width::UnicodeWidthStr;

pub(crate) const DEFAULT_SHELL: &str = "sh";
pub(crate) const DEFAULT_SHELL_ARG: &str = "-cu";
pub(crate) const INIT_JUSTFILE: &str = "default:\n\techo 'Hello, world!'\n";

#[derive(Debug, PartialEq)]
Expand All @@ -15,6 +16,8 @@ pub(crate) struct Config {
pub(crate) quiet: bool,
pub(crate) search_config: SearchConfig,
pub(crate) shell: String,
pub(crate) shell_args: Vec<String>,
pub(crate) shell_present: bool,
pub(crate) subcommand: Subcommand,
pub(crate) verbosity: Verbosity,
}
Expand All @@ -34,14 +37,16 @@ mod cmd {

mod arg {
pub(crate) const ARGUMENTS: &str = "ARGUMENTS";
pub(crate) const CLEAR_SHELL_ARGS: &str = "CLEAR-SHELL-ARGS";
pub(crate) const COLOR: &str = "COLOR";
pub(crate) const DRY_RUN: &str = "DRY-RUN";
pub(crate) const HIGHLIGHT: &str = "HIGHLIGHT";
pub(crate) const NO_HIGHLIGHT: &str = "NO-HIGHLIGHT";
pub(crate) const JUSTFILE: &str = "JUSTFILE";
pub(crate) const NO_HIGHLIGHT: &str = "NO-HIGHLIGHT";
pub(crate) const QUIET: &str = "QUIET";
pub(crate) const SET: &str = "SET";
pub(crate) const SHELL: &str = "SHELL";
pub(crate) const SHELL_ARG: &str = "SHELL-ARG";
pub(crate) const VERBOSE: &str = "VERBOSE";
pub(crate) const WORKING_DIRECTORY: &str = "WORKING-DIRECTORY";

Expand Down Expand Up @@ -114,6 +119,23 @@ impl Config {
.default_value(DEFAULT_SHELL)
.help("Invoke <SHELL> to run recipes"),
)
.arg(
Arg::with_name(arg::SHELL_ARG)
.long("shell-arg")
.takes_value(true)
.multiple(true)
.number_of_values(1)
.default_value(DEFAULT_SHELL_ARG)
.allow_hyphen_values(true)
.overrides_with(arg::CLEAR_SHELL_ARGS)
.help("Invoke shell with <SHELL-ARG> as an argument"),
)
.arg(
Arg::with_name(arg::CLEAR_SHELL_ARGS)
.long("clear-shell-args")
.overrides_with(arg::SHELL_ARG)
.help("Clear shell arguments"),
)
.arg(
Arg::with_name(arg::VERBOSE)
.short("v")
Expand Down Expand Up @@ -318,16 +340,33 @@ impl Config {
}
};

let shell_args = if matches.is_present(arg::CLEAR_SHELL_ARGS) {
Vec::new()
} else {
matches
.values_of(arg::SHELL_ARG)
.unwrap()
.into_iter()
.map(str::to_owned)
.collect()
};

let shell_present = matches.occurrences_of(arg::CLEAR_SHELL_ARGS) > 0
|| matches.occurrences_of(arg::SHELL) > 0
|| matches.occurrences_of(arg::SHELL_ARG) > 0;

Ok(Config {
dry_run: matches.is_present(arg::DRY_RUN),
highlight: !matches.is_present(arg::NO_HIGHLIGHT),
quiet: matches.is_present(arg::QUIET),
shell: matches.value_of(arg::SHELL).unwrap().to_owned(),
search_config,
color,
invocation_directory,
search_config,
shell_args,
shell_present,
subcommand,
verbosity,
color,
})
}

Expand Down Expand Up @@ -594,18 +633,19 @@ USAGE:
just [FLAGS] [OPTIONS] [--] [ARGUMENTS]...
FLAGS:
--dry-run Print what just would do without doing it
--dump Print entire justfile
-e, --edit \
--clear-shell-args Clear shell arguments
--dry-run Print what just would do without doing it
--dump Print entire justfile
-e, --edit \
Edit justfile with editor given by $VISUAL or $EDITOR, falling back to `vim`
--evaluate Print evaluated variables
--highlight Highlight echoed recipe lines in bold
--init Initialize new justfile in project root
-l, --list List available recipes and their arguments
--no-highlight Don't highlight echoed recipe lines in bold
-q, --quiet Suppress all output
--summary List names of available recipes
-v, --verbose Use verbose output
--evaluate Print evaluated variables
--highlight Highlight echoed recipe lines in bold
--init Initialize new justfile in project root
-l, --list List available recipes and their arguments
--no-highlight Don't highlight echoed recipe lines in bold
-q, --quiet Suppress all output
--summary List names of available recipes
-v, --verbose Use verbose output
OPTIONS:
--color <COLOR>
Expand All @@ -614,6 +654,8 @@ OPTIONS:
-f, --justfile <JUSTFILE> Use <JUSTFILE> as justfile.
--set <VARIABLE> <VALUE> Override <VARIABLE> with <VALUE>
--shell <SHELL> Invoke <SHELL> to run recipes [default: sh]
--shell-arg <SHELL-ARG>... \
Invoke shell with <SHELL-ARG> as an argument [default: -cu]
-s, --show <RECIPE> Show information about <RECIPE>
-d, --working-directory <WORKING-DIRECTORY>
Use <WORKING-DIRECTORY> as working directory. --justfile must also be set
Expand Down Expand Up @@ -641,6 +683,8 @@ ARGS:
$(quiet: $quiet:expr,)?
$(search_config: $search_config:expr,)?
$(shell: $shell:expr,)?
$(shell_args: $shell_args:expr,)?
$(shell_present: $shell_present:expr,)?
$(subcommand: $subcommand:expr,)?
$(verbosity: $verbosity:expr,)?
} => {
Expand All @@ -658,6 +702,8 @@ ARGS:
$(quiet: $quiet,)?
$(search_config: $search_config,)?
$(shell: $shell.to_string(),)?
$(shell_args: $shell_args,)?
$(shell_present: $shell_present,)?
$(subcommand: $subcommand,)?
$(verbosity: $verbosity,)?
..testing::config(&[])
Expand Down Expand Up @@ -895,12 +941,15 @@ ARGS:
name: shell_default,
args: [],
shell: "sh",
shell_args: vec!["-cu".to_owned()],
shell_present: false,
}

test! {
name: shell_set,
args: ["--shell", "tclsh"],
shell: "tclsh",
shell_present: true,
}

test! {
Expand Down Expand Up @@ -1050,6 +1099,61 @@ ARGS:
},
}

test! {
name: shell_args_default,
args: [],
shell_args: vec!["-cu".to_owned()],
}

test! {
name: shell_args_set_hyphen,
args: ["--shell-arg", "--foo"],
shell_args: vec!["--foo".to_owned()],
shell_present: true,
}

test! {
name: shell_args_set_word,
args: ["--shell-arg", "foo"],
shell_args: vec!["foo".to_owned()],
shell_present: true,
}

test! {
name: shell_args_set_multiple,
args: ["--shell-arg", "foo", "--shell-arg", "bar"],
shell_args: vec!["foo".to_owned(), "bar".to_owned()],
shell_present: true,
}

test! {
name: shell_args_clear,
args: ["--clear-shell-args"],
shell_args: vec![],
shell_present: true,
}

test! {
name: shell_args_clear_and_set,
args: ["--clear-shell-args", "--shell-arg", "bar"],
shell_args: vec!["bar".to_owned()],
shell_present: true,
}

test! {
name: shell_args_set_and_clear,
args: ["--shell-arg", "bar", "--clear-shell-args"],
shell_args: vec![],
shell_present: true,
}

test! {
name: shell_args_set_multiple_and_clear,
args: ["--shell-arg", "bar", "--shell-arg", "baz", "--clear-shell-args"],
shell_args: vec![],
shell_present: true,
}

test! {
name: search_config_default,
args: [],
Expand Down
2 changes: 1 addition & 1 deletion src/recipe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ impl<'a, D> Recipe<'a, D> {
continue;
}

let mut cmd = context.settings.shell_command(&config.shell);
let mut cmd = context.settings.shell_command(config);

cmd.current_dir(context.working_directory);

Expand Down
8 changes: 4 additions & 4 deletions src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ impl<'src> Settings<'src> {
Settings { shell: None }
}

pub(crate) fn shell_command(&self, default_shell: &str) -> Command {
if let Some(shell) = &self.shell {
pub(crate) fn shell_command(&self, config: &Config) -> Command {
if let (Some(shell), false) = (&self.shell, config.shell_present) {
let mut cmd = Command::new(shell.command.cooked.as_ref());

for argument in &shell.arguments {
Expand All @@ -20,9 +20,9 @@ impl<'src> Settings<'src> {

cmd
} else {
let mut cmd = Command::new(default_shell);
let mut cmd = Command::new(&config.shell);

cmd.arg("-cu");
cmd.args(&config.shell_args);

cmd
}
Expand Down
Loading

0 comments on commit d0e813c

Please sign in to comment.