Open gyreas opened 3 weeks ago
shell() -
This would be awesome, thanks! Would provide a solution for https://github.com/casey/just/issues/11#issuecomment-2015584186 :+1:
call() - this might require user-defined functions
Why would this require user-defined functions? Even without that, seems like call()
would be a helpful tool.
wildcard()
Already achievable as
foo := `echo *.c`
addprefix()
addsuffix()
basename()
These seem easily implemented with replace_regex()
, and doing it this way is more flexible. Using the examples from make
documentation -
addprefix := replace_regex('foo bar', '(^|\s+)(\S+)', '${1}src/${2}')
addsuffix := replace_regex('foo bar', '(^|\s+)(\S+)', '${1}${2}.c')
basename := replace_regex('src/foo.c src-1.0/bar hacks', '(\S+)\.[^/ ]*(\s+|$)', '${1}${2}')
Why would this require user-defined functions? Even without that, seems like
call()
would be a helpful tool.
My bad. I phrased it wrongly; I guess the proper phrasing would be: "call()
is much useful with user-defined functions". I'll rephrase the description.
Already achievable as
foo := `echo *.c`
The point of these functions is to be mixed and matched. So, while
echo *.c
and its variations covers those cases for wildcard(), more complex mixing betweenwildcard()
and the others might not be so easily covered. For example, from make documentation$(wildcard $(addsuffix suf,$(subst :, ,$(PATH))))
| vwildcard(addsuffix("suf", replace_all(":", PATH)))
addprefix := replace_regex('foo bar', '(^|\s+)(\S+)', '${1}src/${2}') addsuffix := replace_regex('foo bar', '(^|\s+)(\S+)', '${1}${2}.c') basename := replace_regex('src/foo.c src-1.0/bar hacks', '(\S+)\.[^/ ]*(\s+|$)', '${1}${2}')
It's certainly much readable to simply use
addprefix()
,addsuffix()
,basename()
, right?
Thanks for the feedback.
The point of these functions is to be mixed and matched. So, while
echo *.c
and its variations covers those cases for wildcard(), more complex mixing betweenwildcard()
and the others might not be so easily covered.
With shell()
implemented, it could be done something like
shell('echo $@', addsuffix("/suf*", replace(env_var('PATH'), ":", ' ')))
With
shell()
implemented, it could be done something likeshell('echo $@', addsuffix("/suf*", replace(env_var('PATH'), ":", ' ')))
I guess.
What do you think about using backslash for escaping? (Does just support raw strings?)
What do you think about using backslash for escaping?
escaping what?
(Does just support raw strings?)
escaping what?
Placeholder escaping in shell()
. I'm using $\d+
for argument substitution, and I'll naturally need to deal with escaping of $.
Also, is $\d+
preferred over ${\d+}
? (I prefer the former).
Placeholder escaping in
shell()
. I'm using$\d+
for argument substitution, and I'll naturally need to deal with escaping of $.
I think it would be best to leave that to the shell and just pass in the arguments as command-line arguments. In just
the shell could be set to anything, even something that isn't nominally a "shell" e.g. a Python interpreter.
So for example, with bash -
set shell := ['bash', '-uc']
# in bash the first argument is $0
# provide the justfile as dummy argument so that desired arguments are all in $@
foo := shell('ls -la "$@"', justfile(), 'actual_first_arg')
would run bash -uc 'ls -la "$@"' /path/to/justfile 'actual_first_arg'
With Python -
set shell := ['python3', '-c']
# argument 0 is the `-c` flag from above
foo := shell('''
import sys
print(sys.argv[1:])
''', 'argument 1', 'argument 2')
would run
python3 -c 'import sys
print(sys.argv[1:])
' 'argument 1' 'argument 2'
Realizing that even with shell()
using command-line to pass arguments, your question applies to call()
.
There is precedent for escaping $
and related in Replacement string syntax of replace_regex()
, where escaped $
is $$
.
Also, is
$\d+
preferred over${\d+}
? (I prefer the former).
Usually yes. ${\d+}
is secondary alternative form for disambiguation - for example, writing $1
immediately followed by a literal 2 is ${1}2
to distinguish it from twelfth argument $12
.
set shell := ['python3', '-c'] # argument 0 is the `-c` flag from above foo := shell(''' import sys print(sys.argv[1:]) ''', 'argument 1', 'argument 2')
This...
python3 -c 'import sys print(sys.argv[1:]) ' 'argument 1' 'argument 2'
... and this expose something I haven't thought of. I'll probably go this route since it's similar to how ` ` works. That means shell() is a convenient frontend to ` `, no?
I think it would be best to leave that to the shell and just pass in the arguments as command-line arguments. In
just
the shell could be set to anything, even something that isn't nominally a "shell" e.g. a Python interpreter.
Yeah. I'll make the necessary changes and push that.
set shell := ['python3', '-c'] # argument 0 is the `-c` flag from above foo := shell(''' import sys print(sys.argv[1:]) ''', 'argument 1', 'argument 2')
This...
python3 -c 'import sys print(sys.argv[1:]) ' 'argument 1' 'argument 2'
... and this expose something I haven't thought of. I'll probably go this route since it's similar to how ` ` works. That means
shell()
is a convenient frontend to ` `, no?I think it would be best to leave that to the shell and just pass in the arguments as command-line arguments. In
just
the shell could be set to anything, even something that isn't nominally a "shell" e.g. a Python interpreter.
Yeah. I'll make the necessary changes and push that.
That means shell() is a convenient frontend to ` `, no?
It's much better than that:
shell()
can (hopefully) be arbitrary just
expressions, allowing flexible construction of commands and variable parameters.shell()
passing in command-line arguments, it's even better than the feature proposed in https://github.com/casey/just/issues/11 . The shell()
approach would be more easily resistant to shell code injection and make it more straightforward to guarantee preserving values as intended.Alright.
I think we're in sync.
PS: I think string interpolation can be done via a function fe fmt()
that uses Rust/Python's formatting scheme. Maybe I should open a discussion for this (or just chime in to #11)?
PS: I think string interpolation can be done via a function fe
fmt()
that uses Rust/Python's formatting scheme. Maybe I should open a discussion for this (or just chime in to #11)?
I don't know which option would be best. In your place I would probably start by replying to https://github.com/casey/just/issues/11#issuecomment-1506818296
- .trim() // as per Make
- .lines()
- .collect::<Vec<&str>>()
- .join(" "); // as per Make
Please don't force this problematic make-ism.
just
does not need strictmake
compatibility, and an individual justfile can easily opt intomake
's behavior where desired byreplace(trim(...), "\n", ' ')
.
Fair enough. I only did that since it's support to be port, I'm just trying to replicate that.
Saed
This PR adds some useful functions found in make.
Please read the corresponding commit's message for how each works
To be added
as