Skip to content

Commit 3f923e2

Browse files
authored
Improve completer config parsing (#3287)
1 parent c5f1a58 commit 3f923e2

8 files changed

Lines changed: 108 additions & 27 deletions

File tree

src/arguments.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ pub struct Arguments {
9595
pub(crate) complete_aliases: bool,
9696
#[arg(
9797
add = ArgValueCompleter::new(PathCompleter::file()),
98-
default_value = "cygpath",
98+
default_value = Self::DEFAULT_CYGPATH,
9999
env = "JUST_CYGPATH",
100100
help = "Use binary at <CYGPATH> to convert between unix and Windows paths.",
101101
long,
@@ -196,15 +196,15 @@ pub struct Arguments {
196196
)]
197197
pub(crate) justfile_names: Option<Vec<String>>,
198198
#[arg(
199-
default_value = "Available recipes:\n",
199+
default_value = Arguments::DEFAULT_LIST_HEADING,
200200
env = "JUST_LIST_HEADING",
201201
help = "Print <TEXT> before list",
202202
long,
203203
value_name = "TEXT"
204204
)]
205205
pub(crate) list_heading: String,
206206
#[arg(
207-
default_value = " ",
207+
default_value = Arguments::DEFAULT_LIST_PREFIX,
208208
env = "JUST_LIST_PREFIX",
209209
help = "Print <TEXT> before each list item",
210210
long,
@@ -288,7 +288,7 @@ pub struct Arguments {
288288
#[arg(env = "JUST_TIMESTAMP", help = "Print recipe command timestamps", long)]
289289
pub(crate) timestamp: bool,
290290
#[arg(
291-
default_value = "%H:%M:%S",
291+
default_value = Self::DEFAULT_TIMESTAMP_FORMAT,
292292
env = "JUST_TIMESTAMP_FORMAT",
293293
help = "Timestamp format string",
294294
long
@@ -473,6 +473,13 @@ pub(crate) struct Subcommand {
473473
pub(crate) variables: bool,
474474
}
475475

476+
impl Arguments {
477+
pub(crate) const DEFAULT_CYGPATH: &str = "cygpath";
478+
pub(crate) const DEFAULT_LIST_HEADING: &str = "Available recipes:\n";
479+
pub(crate) const DEFAULT_LIST_PREFIX: &str = " ";
480+
pub(crate) const DEFAULT_TIMESTAMP_FORMAT: &str = "%H:%M:%S";
481+
}
482+
476483
impl Subcommand {
477484
pub(crate) const HEADING: &str = "Commands";
478485
}

src/compiler.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ impl Compiler {
231231
paths.insert(root.clone(), root.clone());
232232
Analyzer::analyze(
233233
&asts,
234-
&Config::default(),
234+
&Config::new().unwrap(),
235235
None,
236236
&[],
237237
&[],
@@ -261,7 +261,7 @@ mod tests {
261261

262262
let justfile_a_path = tmp.path().join("justfile");
263263
let loader_output =
264-
Compiler::compile(&Config::default(), &loader, &justfile_a_path).unwrap_err();
264+
Compiler::compile(&Config::new().unwrap(), &loader, &justfile_a_path).unwrap_err();
265265

266266
assert_matches!(loader_output, Error::CircularImport { current, import }
267267
if current == tmp.path().join("subdir").join("b").lexiclean() &&

src/completer.rs

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -91,26 +91,31 @@ impl<'run, 'src> Completer<'run, 'src> {
9191
.collect()
9292
}
9393

94-
fn new(current: &'run OsStr, loader: &'src Loader) -> Option<Self> {
95-
Self::try_new(current.to_str()?, loader).ok()
96-
}
97-
98-
fn try_new(current: &'run str, loader: &'src Loader) -> RunResult<'src, Self> {
94+
fn config() -> Option<Config> {
9995
let mut args = env::args_os().collect::<Vec<OsString>>();
10096

10197
args.drain(1..3);
10298

10399
let matches = Arguments::command()
104100
.ignore_errors(true)
105101
.try_get_matches_from(args)
106-
.map_err(|err| Error::internal(format!("failed to parse arguments: {err}")))?;
102+
.ok()?;
103+
104+
let arguments = Arguments::from_arg_matches(&matches).ok()?;
107105

108-
let arguments = Arguments::from_arg_matches(&matches).unwrap();
106+
Config::from_arguments(arguments).ok()
107+
}
109108

110-
let config = Config::from_arguments(arguments).unwrap_or(Config {
111-
invocation_directory: env::current_dir().context(config_error::CurrentDir)?,
112-
..Config::default()
113-
});
109+
fn new(current: &'run OsStr, loader: &'src Loader) -> Option<Self> {
110+
Self::try_new(current.to_str()?, loader).ok()
111+
}
112+
113+
fn try_new(current: &'run str, loader: &'src Loader) -> RunResult<'src, Self> {
114+
let config = if let Some(config) = Self::config() {
115+
config
116+
} else {
117+
Config::new()?
118+
};
114119

115120
let search = Search::search(&config)?;
116121

src/config.rs

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use super::*;
22

3-
#[derive(Debug, Default, PartialEq)]
3+
#[derive(Debug, PartialEq)]
44
pub(crate) struct Config {
55
pub(crate) alias_style: AliasStyle,
66
pub(crate) allow_missing: bool,
@@ -42,6 +42,50 @@ pub(crate) struct Config {
4242
}
4343

4444
impl Config {
45+
pub(crate) fn new() -> ConfigResult<Self> {
46+
Ok(Self {
47+
alias_style: AliasStyle::Right,
48+
allow_missing: false,
49+
ceiling: None,
50+
check: false,
51+
color: Color::default(),
52+
command_color: None,
53+
complete_aliases: false,
54+
cygpath: Arguments::DEFAULT_CYGPATH.into(),
55+
dotenv_filename: None,
56+
dotenv_path: None,
57+
dry_run: false,
58+
explain: false,
59+
groups: Vec::new(),
60+
highlight: true,
61+
invocation_directory: env::current_dir().context(config_error::CurrentDir)?,
62+
justfile_names: None,
63+
list_heading: Arguments::DEFAULT_LIST_HEADING.into(),
64+
list_prefix: Arguments::DEFAULT_LIST_PREFIX.into(),
65+
list_submodules: false,
66+
load_dotenv: true,
67+
no_aliases: false,
68+
no_dependencies: false,
69+
one: false,
70+
overrides: BTreeMap::new(),
71+
search_config: SearchConfig::FromInvocationDirectory,
72+
shell: None,
73+
shell_args: None,
74+
shell_command: false,
75+
subcommand: Subcommand::Run {
76+
arguments: Vec::new(),
77+
},
78+
tempdir: None,
79+
time: false,
80+
timestamp: false,
81+
timestamp_format: Arguments::DEFAULT_TIMESTAMP_FORMAT.into(),
82+
unsorted: false,
83+
unstable: false,
84+
verbosity: Verbosity::Taciturn,
85+
yes: false,
86+
})
87+
}
88+
4589
fn parse_modulepath(values: &[String]) -> ConfigResult<Modulepath> {
4690
let path = values.iter().map(String::as_str).collect::<Vec<&str>>();
4791

@@ -1179,4 +1223,12 @@ mod tests {
11791223
assert_eq!(overrides, vec!["bar=baz"]);
11801224
},
11811225
}
1226+
1227+
#[test]
1228+
fn default_config_matches_parsed_config() {
1229+
assert_eq!(
1230+
Config::new().unwrap(),
1231+
Config::from_arguments(Arguments::try_parse_from(["just"]).unwrap()).unwrap()
1232+
);
1233+
}
11821234
}

src/invocation_parser.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ mod tests {
393393
fs::write(&path, "mod foo").unwrap();
394394
fs::create_dir(tempdir.path().join("foo")).unwrap();
395395
fs::write(tempdir.path().join("foo/mod.just"), "bar:").unwrap();
396-
let compilation = Compiler::compile(&Config::default(), &loader, &path).unwrap();
396+
let compilation = Compiler::compile(&Config::new().unwrap(), &loader, &path).unwrap();
397397

398398
let invocations =
399399
InvocationParser::parse_invocations(&compilation.justfile, &["foo", "bar"]).unwrap();
@@ -411,7 +411,7 @@ mod tests {
411411
fs::write(&path, "mod foo").unwrap();
412412
fs::create_dir(tempdir.path().join("foo")).unwrap();
413413
fs::write(tempdir.path().join("foo/mod.just"), "bar:").unwrap();
414-
let compilation = Compiler::compile(&Config::default(), &loader, &path).unwrap();
414+
let compilation = Compiler::compile(&Config::new().unwrap(), &loader, &path).unwrap();
415415

416416
assert_matches!(
417417
InvocationParser::parse_invocations(&compilation.justfile, &["foo", "zzz"]).unwrap_err(),
@@ -430,7 +430,7 @@ mod tests {
430430

431431
let loader = Loader::new();
432432
let compilation = Compiler::compile(
433-
&Config::default(),
433+
&Config::new().unwrap(),
434434
&loader,
435435
&tempdir.path().join("justfile"),
436436
)
@@ -453,7 +453,7 @@ mod tests {
453453

454454
let loader = Loader::new();
455455
let compilation = Compiler::compile(
456-
&Config::default(),
456+
&Config::new().unwrap(),
457457
&loader,
458458
&tempdir.path().join("justfile"),
459459
)
@@ -474,7 +474,7 @@ mod tests {
474474

475475
let loader = Loader::new();
476476
let compilation = Compiler::compile(
477-
&Config::default(),
477+
&Config::new().unwrap(),
478478
&loader,
479479
&tempdir.path().join("justfile"),
480480
)
@@ -493,7 +493,7 @@ mod tests {
493493

494494
let loader = Loader::new();
495495
let compilation = Compiler::compile(
496-
&Config::default(),
496+
&Config::new().unwrap(),
497497
&loader,
498498
&tempdir.path().join("justfile"),
499499
)
@@ -516,7 +516,7 @@ mod tests {
516516

517517
let loader = Loader::new();
518518
let compilation = Compiler::compile(
519-
&Config::default(),
519+
&Config::new().unwrap(),
520520
&loader,
521521
&tempdir.path().join("justfile"),
522522
)

src/summary.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ mod full {
2828
pub fn summary(path: &Path) -> io::Result<Result<Summary, String>> {
2929
let loader = Loader::new();
3030

31-
match Compiler::compile(&Config::default(), &loader, path) {
31+
match Compiler::compile(&Config::new().unwrap(), &loader, path) {
3232
Ok(compilation) => Ok(Ok(Summary::new(&compilation.justfile))),
3333
Err(error) => Ok(Err(if let Error::Compile { compile_error } = error {
3434
compile_error.to_string()

src/testing.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ pub(crate) fn analysis_error(
6969

7070
match Analyzer::analyze(
7171
&asts,
72-
&Config::default(),
72+
&Config::new().unwrap(),
7373
None,
7474
&[],
7575
&[],

tests/completions.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,3 +420,20 @@ fn usage_recipes() {
420420
.stdout("bar\nfoo\n")
421421
.success();
422422
}
423+
424+
#[test]
425+
fn recipes_with_invalid_config() {
426+
Test::new()
427+
.justfile(
428+
"
429+
foo:
430+
bar:
431+
",
432+
)
433+
.shell(false)
434+
.env("JUST_COMPLETE", "fish")
435+
.env("JUST_ALIAS_STYLE", "foo")
436+
.args(complete_args(&[""]))
437+
.stdout_regex("bar\nfoo\n--.*")
438+
.success();
439+
}

0 commit comments

Comments
 (0)