Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is adding the ability to run commands without a shell worth it? #2532

Open
casey opened this issue Dec 19, 2024 · 11 comments
Open

Is adding the ability to run commands without a shell worth it? #2532

casey opened this issue Dec 19, 2024 · 11 comments

Comments

@casey
Copy link
Owner

casey commented Dec 19, 2024

Incomplete initial implementation in #2531. Needs at least string parsing, environment variable access, and throwing an error on unsupported shell constructs to be useful.

I'm honestly not sure it's worth it. It's very easy to get a working sh almost everywhere, so this is useful only for those niche cases where it isn't possible.

@liquidaty
Copy link

Well worth it especially since the core collection of required utilities can be very easily incorporated using already-existing permissively-licensed opensource code. Otherwise, hard to beat Makefile for non-trivial complexity

@inoa-jboliveira
Copy link

inoa-jboliveira commented Dec 22, 2024

Hi, took me a while to check this. It does look interesting, but in the end you will basically be implementing your own shell in rust as you suggested. You will eventually need at least handle pipes, &&, ||, file redirects. All of those with their own idiosyncrasies.

Which in my opinion is not a bad thing, but you need to know if you want basically a side project.

I do not believe you need a full fledged shell, with all the control mechanism like for/if/switch and so on. But in case you do, maybe it is better to use something else like nushell which is written in rust (could it be imported as a lib?).

One thing to keep in mind is that a task runner should be one the 1st things that get installed therefore the fewer external dependencies it has the better.

@casey
Copy link
Owner Author

casey commented Dec 22, 2024

@inoa-jboliveira Definitely agreed on the possibly infinite scope. My thinking is that the goal is just to get it to the point where simple commands function, and if you need more, you need to install a shell.

I've thought about nushell. I'm sort of biased against it, because I think the syntax is quite weird, and it's so different from the bourne shell syntax that most people are used to. (And which is the default for just, since the default shell is sh.)

If someone wanted to open a draft PR with an experimental integration, I would definitely be curious, but I might not merge it, unless it was incredibly compelling.

@liquidaty
Copy link

I tried using [no-shell] with this version and could not avoid a parse error. Is there a trivial example I can try?

Re built-in capabilities, wouldn't there be value in even a limited implementation that only had an expression processor (rather than a shell)? For example, a drop-in evaluator such as jaq https://github.com/01mf02/jaq (not suggesting you use that-- but mention for discussion's sake) could be used to provide all the variable / string / expression manipulation and generate a result that is simply printed.

While this may seem trivial, if the goal is "run commands with no external dependencies, other than the commands themselves", then wouldn't that alone achieve the goal by enabling just to emit the script that could then be run by the caller e.g. 'just -f no-shell.just | sh'.

In addition, if the evaluation engine supports looping, then it might also provide a solution to #1570.

@casey
Copy link
Owner Author

casey commented Dec 30, 2024

@liquidaty What error are you getting?

This works for me:

[no-shell]
foo:
  echo hello
  echo {{"goodbye"}}

I think the goal is to make it easy to run commands without needing a shell, without changing the general workflow of running just.

@liquidaty
Copy link

@casey thank you that works. I was trying to use print, but that-- and other commands I tried (no idea why I didn't try echo!) failed with an error message that made me think my no-shell syntax was wrong, but it seems the issue actually related to not using a recognized command (e.g. echo) in the recipe line.

# test2.just contents (excluding this and the next blank lines)

[no-shell]
foo:
    print "hello"
> just -f test2.just
error: Unknown attribute `no-shell`
 ——▶ test2.just:1:2
  │
1 │ [no-shell]
  │  ^^^^^^^^

Is "echo" a built-in command? if so, where in the code is it defined or where would I find what other commands can be used with [no-shell]?

@casey
Copy link
Owner Author

casey commented Dec 30, 2024

I believe echo is a built-in command in most shells, but that there is an actual /bin/echo on most systems, so it will work without a shell. There is a printf binary available on most systems.

I have a python script ~/bins which prints out all executable binaries, you could use it, along with grep, to see what's available:

#!/usr/bin/env python3

import os, sys

from pathlib import Path

def bins():
  for component in os.environ["PATH"].split(os.path.pathsep):
    path = Path(component)

    if not path.is_dir():
      continue

    for entry in path.iterdir():
      if os.access(entry, os.X_OK):
        yield entry

argc = len(sys.argv)

if argc == 1:
  for bin in bins():
    print(bin)
elif argc == 2:
  for bin in bins():
    if bin.stem == sys.argv[1]:
      print(bin)
      break
  else:
    sys.exit(1)

@liquidaty
Copy link

Sorry, I'm an idiot, I was misunderstanding what "no-shell" means but I get it now. And my brain was stuck in nu-shell mode hence the print instead of printf. And the error msg I described was from the master branch of just, not the no-shell branch (I have fixed that description above). And I haven't even started new years' drinking yet. Argh

@inoa-jboliveira
Copy link

Hi, I wanted to share this:

https://fishshell.com/blog/rustport/

Fish has a much more sensible format than nushell IMO and is more widely adopted.

I had no idea they were re-writing it in rust.

Also no idea if you can use it as a crate (possibly a stripped out version?)

@liquidaty
Copy link

@inoa-jboliveira one concern I would have (though my opinion should not be counted for much) about fish is that it can't run on windows. I do not use windows directly myself, but it is an unavoidably necessary build target (in fact, if I had to pick only one platform, I would have no choice but to pick Windows-- for that reason, I can't use just if it can't run on Win). Perhaps more importantly, there seems to be an existing just user base that runs it on Windows.

Then again, if in getting to the "stripped out" version you mention, the non-portable bits can be excluded, then maybe Win compatibility could be retained.

@casey
Copy link
Owner Author

casey commented Dec 31, 2024

Yah, Fish is awesome, but unfortunately the goal with the no-shell mode is being cross-platform, and Fish doesn't support Windows.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants