handle arguments to the #!nix-shell directive

This commit is contained in:
2023-07-04 10:02:58 +00:00
parent 9119b2ebca
commit c45767a005
3 changed files with 173 additions and 6 deletions

View File

@@ -11,5 +11,29 @@ echo "hello, world!"
(first_line) (first_line)
(next_line (next_line
(annotation_line (annotation_line
(nix_shell_args))) (nix_shell_args
(interpreter
(sh_arg)))))
(next_line))
==================
nix-shell with interspersed payload
==================
#!/usr/bin/env nix-shell
echo hello
echo again
#!nix-shell -i bash
echo everybody
---
(source_file
(first_line)
(next_line)
(next_line)
(next_line
(annotation_line
(nix_shell_args
(interpreter
(sh_arg)))))
(next_line)) (next_line))

View File

@@ -1,5 +1,5 @@
================== ==================
Minimal nix-shell invocation minimal nix-shell invocation with interpreter
================== ==================
#!/usr/bin/env nix-shell #!/usr/bin/env nix-shell
@@ -10,4 +10,115 @@ Minimal nix-shell invocation
(first_line) (first_line)
(next_line (next_line
(annotation_line (annotation_line
(nix_shell_args)))) (nix_shell_args
(interpreter
(sh_arg))))))
==================
non-interpreter argument
==================
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p gnused
---
(source_file
(first_line)
(next_line
(annotation_line
(nix_shell_args
(interpreter
(sh_arg))
(sh_arg)
(sh_arg)))))
==================
non-interpreter flags
==================
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p gnused awk
---
(source_file
(first_line)
(next_line
(annotation_line
(nix_shell_args
(interpreter
(sh_arg))
(sh_arg)
(sh_arg)
(sh_arg)))))
==================
quoted arguments
==================
#!/usr/bin/env nix-shell
#!nix-shell -i bash arg\ one 'arg"Two' "'argThree"
---
(source_file
(first_line)
(next_line
(annotation_line
(nix_shell_args
(interpreter
(sh_arg))
(sh_arg)
(sh_arg)
(sh_arg)))))
==================
order-independent
==================
#!/usr/bin/env nix-shell
#!nix-shell -p gnused -i bash
---
(source_file
(first_line)
(next_line
(annotation_line
(nix_shell_args
(sh_arg)
(sh_arg)
(interpreter
(sh_arg))))))
==================
empty nix-shell
==================
#!/usr/bin/env nix-shell
#!nix-shell
---
(source_file
(first_line)
(next_line
(annotation_line)))
==================
multiple annotation lines
==================
#!/usr/bin/env nix-shell
#!nix-shell -p gnused
#!nix-shell -i bash
---
(source_file
(first_line)
(next_line
(annotation_line
(nix_shell_args
(sh_arg)
(sh_arg))))
(next_line
(annotation_line
(nix_shell_args
(interpreter
(sh_arg))))))

View File

@@ -9,10 +9,42 @@ module.exports = grammar({
$.annotation_line, $.annotation_line,
repeat(/./), repeat(/./),
)), )),
annotation_line: $ => seq($._shebang_open, $._opt_ws, $._nix_shell, $.nix_shell_args), annotation_line: $ => seq($._shebang_open, $._opt_ws, $._nix_shell, optional($.nix_shell_args)),
// TODO: actually parse nix-shell arguments // nix acts as if it actually just `exec`'s whichever line contains `#! nix-shell` in the style of `sh`'s `exec`.
nix_shell_args: $ => ' -i bash', // so arguments can be quoted, invoke subshells, interpolate environment variables, etc.
// the full scope cannot be covered, but the minimal scope here gets 99% of use cases.
nix_shell_args: $ => repeat1(seq($._ws, $._nix_shell_arg)),
_nix_shell_arg: $ => choice(
seq('-i', $._opt_ws, $.interpreter),
$.sh_arg,
),
interpreter: $ => $.sh_arg,
sh_arg: $ => choice(
$._sh_lit,
$._sh_quote1,
$._sh_quote2,
),
_sh_lit: $ => repeat1(choice(
/[^ \\]/,
seq('\\', /./),
)),
_sh_quote1: $ => seq(
'\'',
repeat(choice(
/[^'\\]/,
seq('\\', /./),
)),
'\'',
),
_sh_quote2: $ => seq(
'"',
repeat(choice(
/[^"\\]/,
seq('\\', /./),
)),
'"',
),
_shebang_open: $ => '#!', _shebang_open: $ => '#!',
// TODO: allow `usr/bin/env`, `env` // TODO: allow `usr/bin/env`, `env`