elves / elvish

Powerful scripting language & versatile interactive shell
https://elv.sh/
BSD 2-Clause "Simplified" License
5.73k stars 303 forks source link

Make it easy for Elvish users on Windows to access coreutil-like commands #1843

Open IngwiePhoenix opened 2 months ago

IngwiePhoenix commented 2 months ago

What new feature should Elvish have?

I came across this while doing my usual RISC-V shenanigans: https://github.com/u-root/gobusybox Sophgo uses u-root as part of their bootloader which is super cool and I haven't seen that before. But as part of that, u-root features a set of, well, core utilities. And since they too are implemented in Go, I think it'd make a perfect fit!

So, whilst I annotated this as a feature request, I'd actually much rather like to know: Where should I implement that? I have been doing a lot of Go development at work lately and since I really want to use Elvish everywhere, I see no reason not to implement some useful builtins.

Now then, do you have a pointer for me? :)

Output of "elvish -version"

Not applicable!

Code of Conduct

krader1961 commented 2 months ago

The project you linked to says:

Go Busybox is a set of Go tools that allow you to compile many Go commands into one binary. The resulting binary uses its invocation arguments (os.Args) to determine which command is being called.

You asked "Where should I implement that?" What feature do you want to implement in the Elvish project? It is unlikely that Elvish will implement the core feature of gobusybox; namely, including other programs as commands. Primarily because doing so requires glue code that the gobusybox project doesn't require. That is, for Elvish to to treat it as a builtin rather than an external program requires glue code that can't be automagically created.

You seem to be asking how to include external commands ("utilities") as Elvish builtins using a mechanism similar to what the gobusybox project uses to embed external programs in the gobusybox binary. The only way that would work is to do the same thing gobusybox does. Specifically, embed an external command into the Elvish binary but with no Elvish binding. Which means running the embedded command is indistinguishable from running it as an external command. What would be the point? Doing that only serves to increase the size of the Elvish binary and add more dependencies to the Elvish project. If you need one of those commands why not simply compile and install the resulting binary somewhere in $E:PATH?

I may not understand your question. Embedding arbitrary external programs in the Elvish binary (similar to what gobusybox does) doesn't seem useful.

xiaq commented 2 months ago

@krader1961 Please don't be combative in the issue tracker. The Elvish community is about helping people do what they want to do with Elvish, not about proving that one way is better than another. (This is a formal warning from me as the moderator.)

iandol commented 2 months ago

Obviously language is a matter of interpretation, but Kurtis' response doesn't read as combative to me. Not understanding the purpose of a feature, or coming up with potential problems is simply a rational response to a technical question. @krader1961 explicitly says he may not have understood the request. I totally support your aim to be welcoming to new users, but asking technical questions in response to what appears a complex feature request is not being dismissive or combative from my understanding as a non-professional programmer, research scientist, and mostly native English speaker.

xiaq commented 1 month ago

Getting back to the original issue:

Taking a step back, I think the pain point on Windows in particular is that a lot of useful system management commands like dir are in fact internal commands of cmd, so Elvish users don't have access to a set of commands equivalent to Unix's coreutils.

I took a look at u-root's implementation of various utilities but I don't think they actually support Windows - at least the ls command doesn't:

~> go run github.com/u-root/u-root/cmds/core/ls@latest
# github.com/u-root/u-root/cmds/core/ls
go\pkg\mod\github.com\u-root\u-root@v0.14.0\cmds\core\ls\ls.go:129:6: c.printFile undefined (type cmd has no field or method printFile)
go\pkg\mod\github.com\u-root\u-root@v0.14.0\cmds\core\ls\ls.go:154:5: c.printFile undefined (type cmd has no field or method printFile)
Exception: go exited with 1
  [tty 7]:1:1-51: go run github.com/u-root/u-root/cmds/core/ls@latest
xiaq commented 1 month ago

I reworded the issue to reflect what I believe is the underlying issue.

lmorg commented 1 month ago

I looked into this exact issue last year; assuming I understand this correctly and the author was asking about using u-root as a way of integrating coreutils into a Windows-compatible $SHELLs written in Go.

After a bit of investigation, my conclusion was that to get u-root integrated as shell builtins, it required companion functions in the various u-root command packages to enable running them as Go functions rather than OS executables. This would require forking u-root and patching it. And because u-root is a relatively young project and we'd ostensibly be doing the AOT equivalent of monkey patching their code, it didn't feel a particularly robust long term solution maintaining a fork of u-root.

However my personal opinion might not match up with others.

I did also reach out to them to see if they had any preferred way to integrate their project with other shells. This was also last year. I didn't get any response from them. But in fairness, they've got such a mammoth task on their hands that I'm sure my inquiry was seen more as a distraction than an asset.

With all that in mind: I think if any shell was to integrate u-root, it would have to be a partnership reciprocated by u-root rather than Elvish leaning on u-root as a 3rd party package in the same way one might import (for example) a YAML marshaller.

Xiaq/Elvish might have more success here than I though. But my personal opinion is that MinGW (eg https://www.msys2.org/) would be a better experience for Windows coreutils even though it requires a little more set up. Or, WSL, if that's an option.

As an aside, Git for Windows uses MinGW (MSYS2) too.

zQueal commented 1 week ago

Busybox has a port which solves most of your issues.

I simply create C:\Utilities\busybox, unload the binaries to the directory (busybox --install C:\Utilities\busybox), and add it to the path, then using rc.elv import the PATH variable. Ends up looking like this:

image

Instead of inflating elvish to accommodate a small subset of users, I think this method is preferable. It works perfectly fine, covers 99% of use cases.

ejrichards commented 5 days ago

It isn't at a 1.0 release yet, but I found https://github.com/uutils/coreutils to be a great solution for Windows + elvish

pdietl commented 4 days ago

@xiaq given the suggested workarounds from @zQueal and @ejrichards (thank you both!), would you prefer Windows users to use these workarounds, or would you prefer adding additional builtins to elvish such as ls?