From fa68f6f55d4493b9c919259efc8ce04a7d40d368 Mon Sep 17 00:00:00 2001 From: Andrew Bradley Date: Sun, 9 Nov 2025 00:42:55 -0500 Subject: [PATCH 1/2] Add windows-script-interpreter setting, discussed here: https://github.com/casey/just/issues/2260#issuecomment-2741516734 --- src/analyzer.rs | 4 +++ src/keyword.rs | 1 + src/node.rs | 1 + src/parser.rs | 3 ++ src/recipe.rs | 5 +++ src/setting.rs | 6 +++- src/settings.rs | 5 +++ src/unstable_feature.rs | 7 ++++ tests/lib.rs | 2 ++ tests/windows_script_interpreter.rs | 50 +++++++++++++++++++++++++++++ 10 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 tests/windows_script_interpreter.rs diff --git a/src/analyzer.rs b/src/analyzer.rs index bc6cbd56a6..4c122d67be 100644 --- a/src/analyzer.rs +++ b/src/analyzer.rs @@ -169,6 +169,10 @@ impl<'run, 'src> Analyzer<'run, 'src> { unstable_features.insert(UnstableFeature::ScriptInterpreterSetting); } + if settings.windows_script_interpreter.is_some() { + unstable_features.insert(UnstableFeature::WindowsScriptInterpreterSetting); + } + let source = root.to_owned(); let root = paths.get(root).unwrap(); diff --git a/src/keyword.rs b/src/keyword.rs index 7cae3606fa..fb392e0106 100644 --- a/src/keyword.rs +++ b/src/keyword.rs @@ -31,6 +31,7 @@ pub(crate) enum Keyword { Unexport, Unstable, WindowsPowershell, + WindowsScriptInterpreter, WindowsShell, WorkingDirectory, X, diff --git a/src/node.rs b/src/node.rs index 02aa2d0c7c..97dccf1ebf 100644 --- a/src/node.rs +++ b/src/node.rs @@ -317,6 +317,7 @@ impl<'src> Node<'src> for Set<'src> { } Setting::ScriptInterpreter(Interpreter { command, arguments }) | Setting::Shell(Interpreter { command, arguments }) + | Setting::WindowsScriptInterpreter(Interpreter { command, arguments }) | Setting::WindowsShell(Interpreter { command, arguments }) => { set.push_mut(Tree::string(&command.cooked)); for argument in arguments { diff --git a/src/parser.rs b/src/parser.rs index f00d87f085..a609785d38 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1146,6 +1146,9 @@ impl<'run, 'src> Parser<'run, 'src> { Keyword::ScriptInterpreter => Some(Setting::ScriptInterpreter(self.parse_interpreter()?)), Keyword::Shell => Some(Setting::Shell(self.parse_interpreter()?)), Keyword::Tempdir => Some(Setting::Tempdir(self.parse_string_literal()?)), + Keyword::WindowsScriptInterpreter => { + Some(Setting::WindowsScriptInterpreter(self.parse_interpreter()?)) + } Keyword::WindowsShell => Some(Setting::WindowsShell(self.parse_interpreter()?)), Keyword::WorkingDirectory => Some(Setting::WorkingDirectory(self.parse_string_literal()?)), _ => None, diff --git a/src/recipe.rs b/src/recipe.rs index 11b8f2edac..ba363f651a 100644 --- a/src/recipe.rs +++ b/src/recipe.rs @@ -395,6 +395,11 @@ impl<'src, D> Recipe<'src, D> { Executor::Command( interpreter .as_ref() + .or(if cfg!(windows) { + context.module.settings.windows_script_interpreter.as_ref() + } else { + None + }) .or(context.module.settings.script_interpreter.as_ref()) .unwrap_or_else(|| Interpreter::default_script_interpreter()), ) diff --git a/src/setting.rs b/src/setting.rs index 211ba9d319..8aeaec83ac 100644 --- a/src/setting.rs +++ b/src/setting.rs @@ -20,6 +20,7 @@ pub(crate) enum Setting<'src> { Tempdir(StringLiteral<'src>), Unstable(bool), WindowsPowerShell(bool), + WindowsScriptInterpreter(Interpreter<'src>), WindowsShell(Interpreter<'src>), WorkingDirectory(StringLiteral<'src>), } @@ -40,7 +41,10 @@ impl Display for Setting<'_> { | Self::Quiet(value) | Self::Unstable(value) | Self::WindowsPowerShell(value) => write!(f, "{value}"), - Self::ScriptInterpreter(shell) | Self::Shell(shell) | Self::WindowsShell(shell) => { + Self::ScriptInterpreter(shell) + | Self::Shell(shell) + | Self::WindowsScriptInterpreter(shell) + | Self::WindowsShell(shell) => { write!(f, "[{shell}]") } Self::DotenvFilename(value) diff --git a/src/settings.rs b/src/settings.rs index 1b352d61f6..49d5a8dcea 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -26,6 +26,8 @@ pub(crate) struct Settings<'src> { pub(crate) tempdir: Option, pub(crate) unstable: bool, pub(crate) windows_powershell: bool, + #[serde(skip)] + pub(crate) windows_script_interpreter: Option>, pub(crate) windows_shell: Option>, pub(crate) working_directory: Option, } @@ -87,6 +89,9 @@ impl<'src> Settings<'src> { Setting::WindowsPowerShell(windows_powershell) => { settings.windows_powershell = windows_powershell; } + Setting::WindowsScriptInterpreter(windows_script_interpreter) => { + settings.windows_script_interpreter = Some(windows_script_interpreter); + } Setting::WindowsShell(windows_shell) => { settings.windows_shell = Some(windows_shell); } diff --git a/src/unstable_feature.rs b/src/unstable_feature.rs index daa2270b1e..7bec680c61 100644 --- a/src/unstable_feature.rs +++ b/src/unstable_feature.rs @@ -7,6 +7,7 @@ pub(crate) enum UnstableFeature { ScriptAttribute, ScriptInterpreterSetting, WhichFunction, + WindowsScriptInterpreterSetting, } impl Display for UnstableFeature { @@ -22,6 +23,12 @@ impl Display for UnstableFeature { write!(f, "The `script-interpreter` setting is currently unstable.") } Self::WhichFunction => write!(f, "The `which()` function is currently unstable."), + Self::WindowsScriptInterpreterSetting => { + write!( + f, + "The `windows-script-interpreter` setting is currently unstable." + ) + } } } } diff --git a/tests/lib.rs b/tests/lib.rs index 450ac29525..1245b87844 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -133,6 +133,8 @@ mod which_function; #[cfg(windows)] mod windows; #[cfg(target_family = "windows")] +mod windows_script_interpreter; +#[cfg(target_family = "windows")] mod windows_shell; mod working_directory; diff --git a/tests/windows_script_interpreter.rs b/tests/windows_script_interpreter.rs new file mode 100644 index 0000000000..995a1444fa --- /dev/null +++ b/tests/windows_script_interpreter.rs @@ -0,0 +1,50 @@ +use super::*; + +#[test] +fn windows_script_interpreter_setting() { + Test::new() + .justfile( + r#" + set unstable + set windows-script-interpreter := ["pwsh.exe", "-NoLogo", "-Command"] + set script-interpreter := ["asdfasdfasdfasdf"] + + [script] + foo: + Write-Output bar + "#, + ) + .shell(false) + .stdout("bar\r\n") + .stderr("Write-Output bar\n") + .run(); +} + +#[test] +fn script_interpreter_setting_is_unstable() { + Test::new() + .justfile("set windows-script-interpreter := ['sh']") + .status(EXIT_FAILURE) + .stderr_regex(r"error: The `windows-script-interpreter` setting is currently unstable\..*") + .run(); +} + +#[test] +fn overrides_script_interpreter() { + Test::new() + .justfile( + r#" + set unstable + set script-interpreter := ["cmd.exe", "/c"] + set windows-script-interpreter := ["pwsh.exe", "-NoLogo", "-Command"] + + [script] + foo: + Write-Output bar + "#, + ) + .shell(false) + .stdout("bar\r\n") + .stderr("Write-Output bar\n") + .run(); +} From 42a46b2ef6d905234581b350d41b3e64c7e9e9bc Mon Sep 17 00:00:00 2001 From: Andrew Bradley Date: Sun, 9 Nov 2025 01:13:35 -0500 Subject: [PATCH 2/2] fix failing test --- tests/windows_script_interpreter.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/windows_script_interpreter.rs b/tests/windows_script_interpreter.rs index 995a1444fa..0c39143884 100644 --- a/tests/windows_script_interpreter.rs +++ b/tests/windows_script_interpreter.rs @@ -16,7 +16,6 @@ fn windows_script_interpreter_setting() { ) .shell(false) .stdout("bar\r\n") - .stderr("Write-Output bar\n") .run(); } @@ -45,6 +44,5 @@ fn overrides_script_interpreter() { ) .shell(false) .stdout("bar\r\n") - .stderr("Write-Output bar\n") .run(); }