Xonsh: Python-powered, cross-platform, Unix-gazing shell
github.com
github.com
I like Xonsh, it’s pretty nice to work with, but it makes going back to Bash, when I have to, even more painful.
I prefer sticking with bash where necessary (where a script is the only thing that will reasonably work), and elsewhere using a programming language with testing, type checking, modularity, and compilation into something with zero or minimal runtime dependencies.
Gonna try nushell soon as that seems even more productive.
its all a bunch of loops and string manipulation in the end. in fact, awk can handle a whole lot of it too! and octave... and others, lol; so long as it does not turn into the python2 to python3 fun we've had in the past and we have some stability between versions; this is why i still choose bash (and the whole gnu binaries)
edit (formatting i hope, and python)
Blegh, now I have to do some digging...
I think the one that catches me off guard the most is:
export FOO=bar
BAZ=qux
Is now $env.FOO = "bar"
BAZ = "qux"
It makes more sense the nu way, but old habits die hard.For short snippets, better to read, understand, and translate as you type.
For some shell integrations or environment setup tools, use fenv or babelfish.
For scripts of any length, just save it and run it. The shebang'll invoke bash or whatever is needed.
$ [1, 2] | math max
2
And here are some strings: $ ["a", "c"] | str join "b"
abc
And there are tables $ [
{name: "foo", value: 6},
{name: "bar", value: 9}
] | where value > 7 | get name
bar
And that's about as weird as the types get.zsh is now the default shell in macOS, so I'd say it's a safe bet if that's what you work with.
careful, there are footguns in those words. It may seem like it's 1-1, but it's not. There are subtle differences especially in escapes. Bash uses \ escapes. Zsh uses % escapes. Zsh has builtin wildcard expansion. There are other differences as well but you can use the emulate command to emulate bash so it actually is 1-1.
Also, once you've made the switch to zsh - checkout oh-my-zsh (https://ohmyz.sh/)
whenever I have some task to deal with data manipulation, i.e. fetch a json, map/filter/reduce on it, save it as some format, I reach for nushell.
If it's just process management or day to day trigger of command in a folder, I use zsh.
There’s no way I’d go back from Fish to Zsh or Bash on my daily driver. It’s just too pleasant to give up just because of “what if?”.
The big problem is that bash is more or less portable (almost everything has bash in the box). They need to start convincing distros to include and/or default xonsh, to really make it worthwhile.
I try to use posix standards when convenient, but I'll switch to bash at the first sign of posix complexity.
Xonsh seems like I'd have to type a lot more than I do with zsh. I would also be concerned about not being able to give my team members the same command I used without forcing them into a non-standard shell.
I don't use fish because I've only met one other person IRL who used it. Everyone I've worked with has use bash, zsh, or ksh (I'm glad I left the ksh company before they had to rewrite all those ksh scripts).
Also, Bash is staying for now. posix will most likely always work for the foreseeable future. Zsh seems to be the new Bash, but I have yet to see anyone put zsh in a shebang at work.
I put it in shebangs for macOS scripts nowadays, since it's been the default shell on macOS for a little while. That's a niche for sure, but still.
Once you're already established and comfortable, it's up to you if you want to keep trying the new flavor of the week. People gravitate towards novelty at different parts of the stack: Some people love running FreeBSD or Alpine, but stick to Bash on top of those; others, like me, try to stick with Ubuntu whenever possible, and mess around with things like shells and tiling window managers. Others even return to Windowsland and instead focus all of their efforts on innovating at the highest levels of what they can do with C# and actually making money with an innovative business model.
But you'll never learn where you don't enjoy the thrill of seeing something new break on you if you don't have that initial "question everything" phase.
If I want it on a server I'm using, I (*gasp!*) just install it.
(I still write Bash sometimes and that's not really a problem, either.)
If you love Bash scripting, xonsh isn't for you. For everyone else, xonsh is.
The only serious headache I have with it - very poor compatibility with fzf. None of the main developers use fzf so they don't feel the pain. As an example, doing:
git checkout $(git branch | fzf)
doesn't work because the result of the fzf command has a newline. So you need something like @$(...).What I really want is to swap the default TAB autocompletion with an fzf selection, and there's no easy way to do it. You have to get deep into the underlying prompt_toolkit library and do a lot of surgery. It's doable, but I haven't had the time.
However, I feel like your criticism re fzf is not really fair, because I run into this with other tools quite often. So often in fact that it took me only a second to convert your command in my head to this:
git checkout @($(git branch |fzf).strip())And the history of fzf support in xonsh has been much worse. Until recently, the command you wrote was not guaranteed to work, because doing anything with fzf under $() would (seemingly) randomly not capture the results of fzf (it would often be any empty string). This was a long standing issue for years, until we finally had a user who knew the xonsh internals well enough to go and debug it.
So people like me had to find alternative ways to use fzf (e.g. attach it to a custom keybinding for specific tasks). I had to modify xontrib-fzf-widgets (because that itself failed often).
Take a look at these issues:
https://github.com/xonsh/xonsh/issues/5190
https://github.com/xonsh/xonsh/issues/5189
https://github.com/xonsh/xonsh/issues/2404 (note that it took 4 years to fix this - and until then your command would not reliably work).
https://github.com/xonsh/xonsh/issues/3548
https://github.com/xonsh/xonsh/issues/3035 (probably a clone of 2404).
The reality is: If people want to use fzf in xonsh the way they do in bash/zsh, they will be in for a lot of pain.
With this setup, you can...
* create a BASIC program right at the command prompt
* execute instructions to read and write to mass storage.
* debug your BASIC program at the command prompt
* direct access to memory addresses via peek and poke commands
What does in the ways that matter mean? It would matter to me that it is 100% Bash compatible, else I won't use another shell in addition to `zsh`.
It's Bash compatible in many/most ways, but there are always exceptions. If you want a Bash-like experience in Windows, xonsh is a good fit.
A shell should be interoperable between users. If everyone on your team uses xonsh, then great, by all means. Otherwise, you're in your own little esoteric world.
a shell has to be stable, a python environment is not. There is just too many ways a python package can break. If python had a good package system perhaps it'd bring something to the table.. but python is by far the winner of the programming language with the worst packaging ecosystem i've seen and used.
Because writing shell scripts in Python/xonsh is much more pleasant than in Bash.
why limit yourself to just one. I'm just talking about the interactive shell here..
That's precisely the rationale behind xonsh! You're not limited to Python. You're not limited to Bash. For the most part, you get the best of both worlds. And you can still run Bash scripts in xonsh.
This is what the shebang in your scripts is for. If you need to write a script that is going to get shared, you have (at least) two perfectly good options:
- use bash (or some lowest common denominator)
- use a fancier (better?) shell, like fish/xonsh/nushell/oil and just require that everyone have that shell installed (they don't have to use it as a daily driver).
xonsh is not really any different from other shells - it can be installed as an isolated environment with its own runtime (in this case Python)A third and usually better option is to use a dedicated scripting language - this is of course an opinion, but many people have recognized that anything longer than ~50 lines and that will need to be iterated upon in the future is a bad fit for a shell-like language.
For example the thing that turned me completely off PowerShell is that its pipelines are sequential not parallel. I use shell a lot, because it has streaming built-in. Many (also standard) libraries do not work around streaming, which I find is the reason why they often crumble when there is more data. For example Python's ZipFile or TarFile work around listing members should have been iterators.
Make sucks, it is a c build tool we have Frankenstein'd into a task runner.
Bash is missing a huge amount of features of modern programming languages, and has a bunch of foot-guns baked in by default ( not setting -e, etc. )
I would love to see a modern language that:
- has a similar mental model a d syntax to other programming languages
- built in argument parsing, declaration, and help string generation
- designed for "scripting" - calling out to other binaries and gluing tools together
- Elvish: https://elv.sh
- Murex: https://murex.rocks
- Nushell: https://www.nushell.sh
Each have their own strengths and weaknesses
I guess that is the point here. With bash there won't be installation or maintenance-problems because of some strange dependencies or unexpected changes.
Though, xonsh seems to only have 3 dependencies, of which one is for unit tests, one for syntax highlighting and something for the prompt. So I guess the danger is kinda low to run into problems.
OK. I lied. Since I installed xonsh and its dependencies in my user directory and not system wide, every time I upgrade my Python to a new major version I have to reinstall xonsh. Usually just one command will do it.
And it's not even in a virtualenv.
It passes Python values instead of json, but otherwise works as you described.
Also, the rc file is way easier to read and manage.
I don't know why they advertise as being like bash. It's absolutely not like bash except that their default prompts look similar on the command line. The similarities pretty much end there.
However, I feel like Xonsh needs a killer app to really demonstrate the advantages of the semantics Xonsh provides. Maybe something like Rawdog (https://github.com/AbanteAI/rawdog) + Xonsh?
There are several projects with the same idea: https://www.cliki.net/Lisp%20as%20a%20shell
Using the same tool everywhere is nice because... that way I don't forget how to use BASH when I eventually need it.
But I absolutely agree with your 2nd point!
As to our domain of discourse, I'm here to speak about what we owe to all people, and I'm not here to make that assumption about our interlocutor. Maybe you know our interlocutor, but I don't think your standalone quote is a morally appropriate argument with a stranger. Setting aside those who might be the sort to possibly play with nix who haven't, I've also met people who have played with nix but cannot afford ChatGPT-4, or don't have access to pay for it. There really may be good reasons our interlocutor hasn't tried ChatGPT-4, and I think your joke can be easily misinterpreted as a flippant response or a putdown.
I appreciate the meme though. You're correct about the vast difference in ability between ChatGPT-4 and every other model the public can access.
Still helpful, just not as helpful as it is for like, python 3.11.
There are so many facets of the nix ecosystem that have so little data in the training corpus, and hopefully that will be fleshed out further in future generations. Probably no way around RLHF from some experts, and whatever magic sauce they can cook up after that either, to get the right sort of data.
(USER)
prints the value of the USER environment variable. (f'Hello {USER}')
evaluates the expression inside the parens and prints "Hello jao" (for me). ls | select (f: time.time() - f.mtime < days(2))
ls finds files in the current directory, pipes them to select, which keeps the files that were modified in the last two days (days is a builtin function).Lots of examples on the website.
winget install marcelDoes it first check if `imagemagick` is installed first and then performs a screenshot?