Skip to content

Commit 7da8b74

Browse files
authored
Merge pull request #112 from fornwall/add-wrapper
Add support for -w/--wrapper
2 parents cf9f1f0 + bf3c5f9 commit 7da8b74

File tree

8 files changed

+75
-13
lines changed

8 files changed

+75
-13
lines changed

.github/workflows/ci.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,10 @@ jobs:
4141
uses: dtolnay/rust-toolchain@stable
4242
with:
4343
toolchain: ${{ matrix.rust }}
44-
- name: Install just
45-
uses: taiki-e/install-action@just
44+
- name: Setup homebrew
45+
uses: Homebrew/actions/setup-homebrew@master
46+
- name: Install hyperfine and just
47+
run: brew install hyperfine just
4648
- name: Install rust-script
4749
run: cargo install --path .
4850
- name: Test examples

Cargo.lock

Lines changed: 9 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ log = "0.4"
2828
pulldown-cmark = "0.9"
2929
regex = "1"
3030
sha1 = "0.10"
31+
shell-words = "1"
3132
tempfile = "3"
3233
toml = "0.7"
3334

docs/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ Useful command-line arguments:
107107
- `--force`: Force the script to be rebuilt. Useful if you want to force a recompile with a different toolchain.
108108
- `--package`: Generate the Cargo package and print the path to it - but don't compile or run it. Effectively "unpacks" the script into a Cargo package.
109109
- `--test`: Compile and run tests.
110+
- `--wrapper`: Add a wrapper around the executable. Can be used to run debugging with e.g. `rust-script --wrapper rust-lldb my-script.rs` or benchmarking with `rust-script --wrapper "hyperfine --runs 100" my-script.rs`
110111

111112
## Executable Scripts
112113

examples/fib.ers

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/usr/bin/env rust-script
2+
3+
fn fib(n: i32) -> i32 {
4+
match n {
5+
1 | 2 => 1,
6+
_ => fib(n-1) + fib(n-2)
7+
}
8+
}
9+
10+
fn main() {
11+
assert_eq!(fib(30), 832040);
12+
}
13+

examples/test-examples.sh

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,14 @@ assert_equals() {
1111
assert_equals "result: 3" "$(just -f justfile/Justfile)"
1212
assert_equals "hello, rust" "$(./hello.ers)"
1313
assert_equals "hello, rust" "$(./hello-without-main.ers)"
14+
15+
HYPERFINE_OUTPUT=$(rust-script --wrapper "hyperfine --runs 99" fib.ers)
16+
17+
case "$HYPERFINE_OUTPUT" in
18+
*"99 runs"*)
19+
;;
20+
*)
21+
echo "Hyperfine output: $HYPERFINE_OUTPUT"
22+
exit 1
23+
;;
24+
esac

src/arguments.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ pub struct Args {
2525
pub install_file_association: bool,
2626
#[cfg(windows)]
2727
pub uninstall_file_association: bool,
28+
pub wrapper: Option<String>,
2829
}
2930

3031
impl Args {
@@ -75,7 +76,7 @@ impl Args {
7576
.help("Base path for resolving dependencies")
7677
.short('b')
7778
.long("base-path")
78-
.num_args(1..=1)
79+
.num_args(1)
7980
)
8081
.arg(Arg::new("cargo-output")
8182
.help("Show output from cargo when building")
@@ -163,6 +164,12 @@ impl Args {
163164
.num_args(1)
164165
// Benchmarking currently requires nightly:
165166
.conflicts_with("bench")
167+
)
168+
.arg(Arg::new("wrapper")
169+
.help("Wrapper injected before the command to run, e.g. 'rust-lldb' or 'hyperfine --runs 100'")
170+
.long("wrapper")
171+
.short('w')
172+
.num_args(1)
166173
);
167174

168175
#[cfg(windows)]
@@ -240,6 +247,7 @@ impl Args {
240247
install_file_association: m.get_flag("install-file-association"),
241248
#[cfg(windows)]
242249
uninstall_file_association: m.get_flag("uninstall-file-association"),
250+
wrapper: m.get_one::<String>("wrapper").map(Into::into),
243251
}
244252
}
245253
}

src/main.rs

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -183,15 +183,14 @@ fn try_main() -> MainResult<i32> {
183183
return Ok(0);
184184
}
185185

186+
let mut cmd = action.command_to_execute(&args.script_args, args.wrapper)?;
186187
#[cfg(unix)]
187188
{
188-
let mut cmd = action.cargo(&args.script_args)?;
189189
let err = cmd.exec();
190190
Err(MainError::from(err))
191191
}
192192
#[cfg(not(unix))]
193193
{
194-
let mut cmd = action.cargo(&args.script_args)?;
195194
let exit_code = cmd.status().map(|st| st.code().unwrap_or(1))?;
196195
Ok(exit_code)
197196
}
@@ -332,7 +331,11 @@ impl InputAction {
332331
self.pkg_path.join("Cargo.toml")
333332
}
334333

335-
fn cargo(&self, script_args: &[String]) -> MainResult<Command> {
334+
fn command_to_execute(
335+
&self,
336+
script_args: &[String],
337+
wrapper: Option<String>,
338+
) -> MainResult<Command> {
336339
let release_mode = !self.debug && !matches!(self.build_kind, BuildKind::Bench);
337340

338341
let built_binary_path = platform::binary_cache_path()
@@ -351,9 +354,25 @@ impl InputAction {
351354
let manifest_path = self.manifest_path();
352355

353356
let execute_command = || {
354-
let mut cmd = Command::new(&built_binary_path);
355-
cmd.args(script_args.iter());
356-
cmd
357+
if let Some(wrapper) = wrapper {
358+
let wrapper_words = shell_words::split(&wrapper).unwrap();
359+
if wrapper_words.is_empty() {
360+
return MainResult::Err(MainError::OtherBorrowed(
361+
"The wrapper cannot be empty",
362+
));
363+
}
364+
let mut cmd = Command::new(&wrapper_words[0]);
365+
if wrapper_words.len() > 1 {
366+
cmd.args(wrapper_words[1..].iter());
367+
}
368+
cmd.arg(&built_binary_path);
369+
cmd.args(script_args.iter());
370+
Ok(cmd)
371+
} else {
372+
let mut cmd = Command::new(&built_binary_path);
373+
cmd.args(script_args.iter());
374+
Ok(cmd)
375+
}
357376
};
358377

359378
if matches!(self.build_kind, BuildKind::Normal) && !self.force_compile {
@@ -376,7 +395,7 @@ impl InputAction {
376395
&& built_binary_time.cmp(&manifest_mtime).is_ge()
377396
{
378397
debug!("Keeping old binary");
379-
return Ok(execute_command());
398+
return execute_command();
380399
} else {
381400
debug!("Old binary too old - rebuilding");
382401
}
@@ -423,7 +442,7 @@ impl InputAction {
423442

424443
if matches!(self.build_kind, BuildKind::Normal) {
425444
if cmd.status()?.code() == Some(0) {
426-
cmd = execute_command();
445+
cmd = execute_command()?;
427446
} else {
428447
return Err(MainError::OtherOwned("Could not execute cargo".to_string()));
429448
}

0 commit comments

Comments
 (0)