Hacker News new | past | comments | ask | show | jobs | submit login
Elvish, expressive programming language and a versatile interactive shell (elv.sh)
177 points by bwidlar 6 months ago | hide | past | favorite | 114 comments



I like Elvish. It's clean, consistent and stable. Writing a shell script in Elvish is so much more productive and simpler than, say, bash. There are are also fewer pitfalls and tricks you need to master.

The Elvish shell language doesn't change much which is nice nowadays. The Elvish executable has also got a built-in lsp which is another nice touch.

Finally it is a "proper" shell because it has job control (which other new age shells like nushell don't).

P.S. I like nushell too which has got more features, is more powerful but is still evolving. Maybe in a couple of more years it will stablize like Elvish already has. There are lots of similarities between Nushell and Elvish scripting language. I would recommend either of them.


Hey, thanks for the compliment! Glad you've enjoyed Elvish.

Re job control - you can run a background job with &, and there are fg and bg commands, but you can't actually ^Z a running program (which is what most people mean by job control). I've heard people have success with https://github.com/yshui/job-security though.

Re Elvish and Nushell, I'd add my biased recommendation for Elvish because it has comprehensive reference documents (https://elv.sh/ref/) :)


I'm afraid I really need ^Z, %-, %3 and %foo for interactive use.

See e.g. the top-right xterm in https://trout.me.uk/screenshot3.jpg for why.

Tried to switch to a ksh for a while and ran face first into that, though OpenBSD ksh has added it so I may attempt that one at some point.

(tabs don't fit my brain nearly as well and https://github.com/n-t-roff/heirloom-ex-vi is my usual editor and doesn't provide anything of that ilk anyway ... I may be an outlier ...)

The syntax and semantics seem really rather nice though, I may attempt elvish for scripting at some point.


I have a ton of respect for whoever sticks to the traditional vi! Not promising anything but this may have bumped the priority of supporting ^Z slightly in my TODO list :)


Also useful for jumping back and forth between e.g. multiple repl sessions (the re.pl on the top left is a readline frontend wired up over a socket to an p3rl.org/Eval::WithLexicals instance running inside the server I was debugging there).

Being able to do e.g. %Task to resume the lib/.../Task.pm editor is -really- nice once you have that many editors open, though I try and stick to about 5 per xterm normally so %- %+ %<digit> would absolutely be enough to get started with.


Traditional Vi? I thought I was hardcore. Certainly an outlier, in a good way :)


If I'm on somebody else's system and need to hit the ground running Right Now then this comes into play instead - https://trout.me.uk/X11/vimrc (I think it's been a few years now since I've been annoyed enough by something in vim to figure out how to turn it off and add yet another line to that ;)


Out of curiosity, why bother to unmap the cursor keys? I don't ever use them in vim either, but is there something that is prevented from working with having them mapped in vim?


Because I don't ever hit them except by accident while using vi(m) so disabling means an accidental keypress does nothing rather than something I didn't want.

(my main reason for preferring original ex-vi is that when I typo a command, it beeps at me, whereas in vim the typo is usually some completely unrelated but valid command sequence and then WTF JUST HAPPENED and argh)


It can be useful to crush old habits.

Also very useful if you do a lot of context switching or are an occasional user, to make sure your brain and fingers are in "vim mode" (at least one other line in the file makes this rather obvious)

And once it's there, why bother removing it? I think you are in minority if you actively prune your vimrc for dead config...


I never had those habits, though I have passed that stanza on to people who were just learning to help remind them to use hjkl.

I just tend to turn off things I only ever hit by accent (see also the :h override).


Clever w.r.t. "job control as task-switcher". The absurdity of that statement being clever kindof stares you in the face a bit, huh? Don't forget ^T for SIGINFO: https://en.wikipedia.org/wiki/Signal_(IPC)#Sending_signals


The documentation of Elvish is indeed top notch. I also like the self contained nature of the project. Elvish is like a beautiful tool in your arsenal while nushell is a powerful but perhaps too feature-full scripting language.

An imperfect analogy: Elvish is like a compact OCaml while nushell is more like a Haskell or C++ of the scripting world !


Murex has had job control support for literally years too.

There’s actually a lot of parallels between murex and Elvish. Both projects started around the same time, both written on Go. Both support structured data and smart data types.

The syntax differs a little between them two but concept wise they’re similar in a number of ways. I as (project author) just don’t do a particularly good job promoting murex. In part because I’d never want to force my own shell preferences onto others.

But It’s good that there’s so much choice these days and people aren’t stuck with the archaic decisions of the 70s


Hiya! I, for one, would definitely welcome more promotion of Murex!

(Also just checked out Murex's website again, seems we reworked the style of the respective homepages around the same time :)


Your new website is nice. Particularly on mobile too, but even just generally. Though to be fair, I've always been impressed with your website layout -- even on the previous one.

I can't take any credit for Murex's site, it was a user who doesn't write Go but wanted to contribute in other ways. Open source is definitely a double edged sword but I'm still always surprised and impressed with how much time people are willing to invest into other peoples projects if they like them.

By the way, one killer feature of Elvish that I admire and think doesn't get talked about enough is how exceptions are raised in pipes. eg:

    ~> cat example | grep foo | grep bar
    Exception: (<nil> | grep exited with 1 | grep exited with 1)
It's really neat how you do that. It's readable, detailed, and valuable to the user.


Thank you for the compliment!


> does not change much so you mean no async await, no union types, no type hinting, no lambdas etc etc.

Kidding, I'll give it a try. Can it replace one's shell as daily driver?


Yes! I haven't been using it as my daily driver for almost 10 years now.

There are detailed instructions on how to get it and use it as your default shell in https://elv.sh/get/.


> I haven't been using it as my daily driver for almost 10 years now.

Is there some humor I'm missing there, or is that just a typo (and you meant to say "I have" )?


Ha it's just a typo.


So, it's not for me, especially given the examples. As usual with these kinds of things (fish, zsh, etc) this really has everything to do with taste, especially since bash has such a difficult syntax...at least for those who aren't used to it. Even to this day, years later, I have to look up bits and pieces here and again if I don't use some of the ${}-type substitutions frequently.


> Even to this day, years later, I have to look up bits and pieces here and again if I don't use some of the ${}-type substitutions frequently.

In that case I think you should give Elvish a chance then :)

Honestly one of the motivations for writing a shell language was that I could never remember which of ${x%y} and ${x#y} is for trimming the suffix vs prefix. So Elvish just use function syntax - "str:trim-suffix $x y" and "str:trim-prefix $x y" - which I highlighted in the explainer of the first snippet (https://elv.sh/learn/scripting-case-studies.html#jpg-to-png....).


# is to the left of $ and removes the prefix. % is to the right of $ and removes the suffix.


I, like the person you replied to, will surely remember it for good thanks to your reminder.


I mean, people learn silly things all the time; I think, often, learning the pattern behind something can make a thing much more transparent... I, too, struggled with this particular distinction until I realized that the choice of characters wasn't, in fact, arbitrary.


Author of Elvish here, glad to see it's on the homepage again :) AMA.


Thanks for Elvish. On a daily driver basis I still use fish. I find the fish autocomplete a bit more compelling. I’m more productive with fish on the prompt (though I do think the elvish scripting language is nicer).

In elvish I need to request an autocomplete— in fish I get a suggestion in a light font which is usually a good one.

Another nice thing in fish is that valid file names get automatically underlined. It’s another subtle but useful feature.

So I think you know what is coming. A feature request :-):

Please make Elvish prompt autocomplete/suggestions more like fish. I wouldn’t be surprised if this has not been requested already !


There's indeed a feature request for it: https://github.com/elves/elvish/issues/322

I can't promise anything, but I'm undertaking a major refactoring of Elvish's TUI and that should make it much easier to implement this feature in the near future.


Hi, thanks for your time! I'm really keen on finding alternatives for bash scripting, and from looking at the examples, it seems to go a long way in that direction.

I'm not keen on trading bashisms for elvishisms though :-) A somewhat random example from looking at the docs, where you have this example:

~> curl -s https://dl.elv.sh/$platform:os'-'$platform:arch/elvish-HEAD....

Quoting '-' instead of using (bash-style) "${platform:os}-${platform:arch}" seems really counterintuitive to me. After all, '-' is simply itself (a plain dash), it's the variable name that is special here and deserves quoting. Any thoughts on this?


You can actually wrap variables with {} (which functions just as a grouping construct in Elvish):

~> curl -s https://dl.elv.sh/{$platform:os}-{$platform:arch}/elvish-HEA.......

It's more verbose than quoting the dash so I opted to the latter.

You seem to use "elvishism" in a negative way, and this particular example is one of the more quirky ones, but the whole reason you would use Elvish is that it's different from other shells! :)


My apologies if the comment came across as negative. I just meant to say that I didn't want to exchange one set of shell quirks for another. But using {$x}-style grouping is a fine solution too. And in any case I'm sure that bash has a lot more quirks than Elvish :-)

So I'll definitely do more testing with Elvish and see what the overall experience is like. Coming from Solaris, we still have a ton of ksh scripts in our shop (with people working on them who have very different backgrounds and scripting skill levels). Something with less pitfalls than bash would be great... Thanks for putting in your time and effort!


Oh, I definitely didn't read your entire comment as negative, just the way you used "elvishism". Elvish definitely has its quirks! But I hope you'll find it a compelling package overall :)


It would be nice to be able to make an executable version of an Elvish script that could be installed and run without having to install Elvish separately. So this executable would have to contain the Elvish interpreter.

Is that doable?


Two quick questions: Is there a way to implement !!? Via functions maybe? "Last Command" looks to be hotkey based, and I can't think of how that would work.

Related: is there a comprehensive list of hotkeys floating around? I didn't see it in the docs. Things like Alt-Enter and Alt-, are mentioned in the Quick Start, but I couldn't find them elsewhere.


The directory history idea seems incredibly useful, but I’ve never see of it before. Did you come up with it yourself?

It has the characteristics of a really great idea: seems obvious in retrospect, doesn’t look too difficult to implement, but somehow everybody seems to have… just missed it?


It was inspired by browsers' location bar - the name (location mode) and the default ^L binding are a nod to browsers too.

These days browsers will often suggest results from search engines but back then (at least in Firefox?) it was just history and bookmarks.


What's the primary reason you set out to build this? I like the look and feel of the language but I'm on the fence whether the drawbacks of using something different than bash are outweighed by the benefits of elvish.


I believe shells have the potential to be much more than what they are today, and traditional shells are held back by their rather weak languages.

Re the cost of switching: on the one hand, I'd say that "switching" is really the wrong mentality, because you can always still use bash! You can "switch" to Elvish as your interactive shell and still use bash for scripting. Or you can "switch" to Elvish for some new scripts and still use bash as your interactive shell (and your existing scripts). If you want to give Elvish a try, you can just do it without giving up everything you do with bash today, and reap the incremental benefits of using a better shell.

On the other hand, the mental barrier of adopting "a new thing" is definitely real, even after you overcome the more irrational fears. We only want so much software in our lives anyway. To that I'd say Elvish needs to be more compelling than what it is today. Elvish today, with its nice interactive features and a real programming language, is perhaps 2x to 4x better than traditional shells on its own (if we ignore the whole ecosystem issue), but it needs to be more than that to stand out to people as something radically better. I'm still trying to figure out how to do that, but two ideas I'm exploring are:

- Make it super easy to build TUIs in Elvish - we've had a "renaissance" of TUI tools in recently years, but if you want to build a TUI from scratch it's still surprisingly complicated. Much simpler than building GUIs, but still much more complex than just building a CLI. I feel Elvish as a shell language is a really good place to have a nice TUI framework in.

- Make it super easy to manage a simple homelab or build farm in Elvish - this is traditionally a strength of shells and people still cobble together shell scripts for this purpose, but traditional shell languages are clumsy and you can't easily expose a nice UI from shell scripts. It would be very nice if you can compose some Elvish scripts together and have a nice TUI or a web UI for management at a very low extra cost.


I personally don’t find the TUI idea compelling. I’d rather use a general purpose language like Rust or Python. Many powerful and mature frameworks are already available to build TUIs there. You want to optimise the average one-off hacked-up script writing experience. Most scripts are written in a hurry to accomplish some boring task or automation.

I would spend time building a top notch LSP for Elvish. Shell scripting languages tend to be highly untyped and flexible so building a good LSP will be tough here. But if you were able to build one that works really well you would have another really compelling reason to use Elvish.

P.S. I am aware that Elvish has a built in LSP. It’s somewhat basic though IIRC.


> I personally don’t find the TUI idea compelling. I’d rather use a general purpose language like Rust or Python. Many powerful and mature frameworks are already available to build TUIs there. You want to optimise the average one-off hacked-up script writing experience. Most scripts are written in a hurry to accomplish some boring task or automation.

That's interesting, because I have the same starting point as you (optimise hacked-up script experience) but a lot of the time as my script grows I really wish there's a nice little TUI for it. For example, rather than finding my invocation of the script from my command history and edit the CLI arguments, can I just have a little "pop-up menu" for my workflows, where I can probably add some string argument? Or allow me to see the outputs of the script in a slightly more fancy way than a stream of text - like a Miller column view, which Elvish already has implemented in its file manager? Ideally, these should be "ready-made" UI components that you can take advantage of from your hacked-up script with just one or two lines of code.

I'm also coming from the viewpoint of implementation - I've built Elvish's TUI using some very generic building blocks but they are only used for very specialized builtin features of Elvish, so I'm really keen on exposing the capability for shell scripts to use.

I guess we're thinking of different things when we say "TUI" - perhaps you are thinking of full blown TUI applications, like an editor? I'd agree that a more [1] general-purpose language is more suitable and Elvish is not in the business of being a good language to implement the next TUI editor :) Maybe I should coin a new term for what I have in mind, which should be something you can hack up as easily as a CLI. "TUIlet" maybe?

> I would spend time building a top notch LSP for Elvish. Shell scripting languages tend to be highly untyped and flexible so building a good LSP will be tough here. But if you were able to build one that works really well you would have another really compelling reason to use Elvish.

Definitely! It's not what I'm working on in the immediate future, but good editor integration is a must to make the experience of writing scripts much better than more traditional shells.

1. Emphasis on "more", because Elvish is a general-purpose language itself, just not the most general-purpose :)


Bash reigns supreme indeed. If you’re writing software for yourself or a small team the benefits of Elvish are higher productivity. Try it out — I was really satisfied at the power and cleanliness of the scripting language.

Bash will be dethroned some day. As general purpose languages like Rust, Julia, Python etc have risen, Fortran, pascal etc have declined. And so that will eventually happen with bash. Not “if” but “when” !


When I see a language with `var` to declare variables, I think I would just use julia as https://github.com/ninjaaron/administrative-scripting-with-j...


Why haven't you decided to stick with the object-oriented shell like PowerShell does?


PowerShell is quite heavyweight. Aside from the feel of the language and the requirement of .Net runtime, it also makes PowerShell very slow to start up, which is a dealbreaker for interactive usage for me.

Also when I started Elvish 10 years ago (!) PowerShell wasn't ported to non-Windows operating systems yet, so it wasn't even viable for most people.


You are right, even now on my Linux laptop poweshell process takes 100-200ms to start while bash takes 5ms. But these problems you mentioned are a specifics of a particular implementation, not the approach (objects instead of text processing) itself.


Well, Elvish doesn't have objects, but it's also not based only on text processing - it has lists and maps that can be arbitrarily nested. On this front it is somewhat aligned with PowerShell but without all the OO paradigm.


Personally, I'd argue that I don't find OO to be desirable in a shell anyway. The future is FP for almost everything.

(This is a really neat tool, great work!)


Unix shells are already a bit LISP-y on a superficial level, because commands are syntactically like impure functions in prefix notation. Subshells act a lot like parens in a LISP, and the pipeline itself has analogs in FP like Clojure's thread macro. And of course, the command line itself is a REPL.

Elvish visibly leans into this to try to have a consistent syntax. Sometimes the similarities go deeper, too; IIRC, its number types are inspired by Scheme, for example.


> Elvish visibly leans into this to try to have a consistent syntax. Sometimes the similarities go deeper, too; IIRC, its number types are inspired by Scheme, for example.

Yes! Similarity to Lisp is very much a deliberate design choice and I feel happy every time a Lisper picks that up :)

I believe Elvish has also contributed a novel solution to the Lisp-1/Lisp-2 divide by making the space of command names equivalent to the subspace of variable names with a suffix - the command "foo" is equivalent to the variable "$foo~" and vice versa. (There's a bit more twist than that - the command "foo" can also resolve to the external command named "foo", but then that's represented by the "$e:foo~" variable.)


Powershell is closer to FP than OOP. What people mean is that it supports structured data.

Powershell is not true FP, but, if you stretch terminology:

- the unit of feature delivery is the function - you can pass functions as values (but it's not idiomatic or elegant) - objects tend to look more like anonymous records than OOP classes with methods - pattern matching is supported (sort of)


Thanks, I like that it seems similar enough to posix shell to draw me in before surprising me :). I like how the option vs arguments distinction is done and generally a lot of posix shell issues are improved. A few feature requests/impressions:

1) Maybe link at the top of the ref page to the learn page? I started looking at ref but some stuff I needed to know was much better explained under learn and it took me a while to notice that it was there also (I'm guessing the existance of ref would be more obvious from the learn page).

2) Local documentation is vital for a shell, if there is a way to generate a man page from the available documentation that would be quite helpful (at least instaling the website would be good, but that looks like a package issue that should be easy to do).

3) If I want the equivalent of fd -X but being able to use aliases (functions in elvish) there is from-terminated and (all) but despite the long command line lengths these days it can overflow. A builtin simplified version of xargs that works with elvish lists and aggregates arguments while breaking into acceptable length command lines would be great.

4) There seems to be no way to execute code from a different file in the current context? For bash to get aliases in fd -X you can use a complicated fd ... -X bash -ic '<alias> "$@"' 'fd bash', however it seems that elvish both doesn't have -i and has no way to even source the rc file from elvish -c? Or to split rc files into multiple files without using modules?

5) &> and to a lesser extent |& are handy in bash to simplify combining stderr and stdout. Hopefully elvish doesn't have the 2>&1 placement issues that posix shells do but even if not I'd consider a shorthand worthwhile.

6) Some type of cooperative locking would be helpful along the lines of Debian's lockfile-progs but built in to make it easy to avoid scripts that break if you accidently run it twice at the same time (ideally compatible with lockfile-progs unless there is a good reason not to be).

7) Beyond that, some type of built in concurrency managed database based on elivish data types might be worth considering to simplify sharing state between independent execution of related utilities (or multiple execution of a single utility).

8) I like your idea of exposing more TUI abilities. In addition to what you said, being able to create a status line or two while preserving the scrolling history of other commands would be helpful (and this would be potentially interesting in an interactive shell also). I like your rprompt.

Overall, I like the look of elvish and for some reason it seems more approachable to me (not a big fan of lisp) than the PowerShell style shells.


I'm impressed/jealous of engineering folks who can build nice, clean, elegant web sites for their projects. Do you all just know enough web design stuff to do this on your own? Or did you hire someone?


I take your comment as implying that https://elv.sh is nice, clean and elegant, and thank you for the compliment :)

I can't speak for other people, but I made it on my own and don't have any formal training in design.

With the risk of stating the obvious, you first have to realize that as a developer you can make a reasonably clean-looking website on your own. There are just a few basic ingredients: fonts, spacing, positioning, background shades, and rounded corners. You can do all of these from CSS and there is a lot of good resources for CSS today.

After that it's studying other websites, replicating the style you like, and a lot of trial and error. You can do a lot of experiments from the browser's dev tool before committing them into the stylesheet too. But at the end of the day, you have to put in some time. The layout of the current homepage was redone just a few months back and it took me (IIRC) 3 days to tweak everything to my satisfaction.


Thanks for the ideas, and yes it was a compliment :-)


Cute choice of website elv.sh using the top level domain for Saint Helena [1], which even mentions

> For the .sh file extension type, see shell script.

[1] https://en.wikipedia.org/wiki/.sh


It's funny how these tiny islands have played roles in military history. Saint Helena is famous for Napoleon's exile and death. Both SH and Ascension were important uboat staging bases during WW2, and RAF Ascension Island was an important airbase during WW2 and especially during the Falklands war.


I was expecting a programming language that was based on Tolkien's Elvish languages of Quenya or Sindarin (the way that some programming languages have been based on non-English languages) and although this isn't the case, I see in the list of modules for Elvish that someone has written a command to give the current date in Sindarin, so there's that.


Wow, this looks awesome and carefully designed! It even has an official VSCode plugin with a language server[0]. Well done, author!

[0] https://marketplace.visualstudio.com/items?itemName=elves.el...


So many better shells! I stay with bash because it's the standard, but it sure would be nice if everyone could switch at the same time.

I don't see infix math though, which is one thing I'd really like to have in a shell, although maybe that better done with a one letter alias to Python or the like.


The examples for the math functions (https://elv.sh/ref/math.html) include 1/2 as an input so infix math appears to be there (I'm undercaffeinated so haven't found the correct doc page to describe it, only proof of its existence, but y'know, it's a start ;)


Actually 1/2 is there because Elvish supports rational numbers, unfortunately there's no infix math. (Elvish supports arbitrary-precision integers and rationals.)


Bugger. Apologies for posting misinformation.

(at least I warned people I was undercaffeinated?)


Ha, no problem. The number syntax is documented in https://elv.sh/ref/language.html#number


This closure syntax, with the vertical bars around the parameter:

    peach {|h| ssh root@$h[name] $h[cmd] } $hosts
Does it harken back to some popular language? I first encountered it in nushell but now that I've seen it in elvish I'm wondering where it came from.



Which came from Ruby which came from Smalltalk.


It wasn't directly borrowed from any other language (https://news.ycombinator.com/item?id=40317577) but there's definitely something nice about the syntax that causes multiple languages to use it.

Elvish predates Nushell by quite a few years BTW :)


I had that backwards, perhaps they took inspiration from you :)


Ruby did it first, but it goes farther back at least to Smalltalk if not further.


Really nice shell! I'm giving it a shot. I appreciate that it's got a coherent design, a minimal footprint, and is easy to get up and running with. Might start migrating some of my test scripts from Bash to this given how clunky lists and looping are in Bash.


Elvish: what Sean Connery calls the King of Rock and Roll


Looked around a bit and didn't see anything about forks, does it have a wrapper for it? It's not clear from the introductory material how the background jobs work, if they can be IPC:d and foregrounded and so on.

It's one of the things that keeps me reaching for picolisp, the 'fork convenience function is quite nice for doing interactive parallel 'batching'.


So I should change my shell, have it deployed everywhere, and learn a new language so that I can change:

    for x in *.jpg; do
      gm convert $x ${x#.jpg}.png
    done
to

    for x [*.jpg] {
      gm convert $x (str:trim suffix $x .jpg).png
    }


After being a fish die-hard for like a decade I finally gave up and learned to embrace Bash for its ubiquity. I realized all I cared about in fish was the built-in autocomplete, colorized output, and history management, which I was able to bolt on in short order to Bash.

Now I use ble.sh [1] and Oh My Bash [2] and Atuin [3] and I love it.

This is really a field where I feel standardization is the better path. It's a similar feeling I get when I observe the vast array of notetaking apps I see made and think here is a place where it would be better to pick one FOSS solution and contribute.

[1] https://github.com/akinomyoga/ble.sh

[2] https://github.com/ohmybash/oh-my-bash

[3] https://atuin.sh/


> It's a similar feeling I get when I observe the vast array of notetaking apps I see made and think here is a place where it would be better to pick one FOSS solution and contribute.

I feel the opposite -- I use a commercial note-taking app for the same reason I use bash. It kinda sucks, but it's on all my devices, and the extra work imposed by the suckiness is more than made up for by familiarity and by not having to invest any energy to make it work seamlessly across my devices.


for note taking I've had best results with just markdown files and basic text editors (vi/vim/nvim, helix). At this point, actually one single notes.md file, and I can just lazily search through that to find what I'm looking for.


Assuming the first example is in Bash:

- You're not quoting your variables properly to prevent splitting and globbing.

- In case there are no jpg files in the working directory, Bash will put the pattern itself (*.jpg) into the $x variable. You need to explicitly check that the file in the variable actually exists before working on it.

Modern shells do not have these footguns.


> In case there are no jpg files in the working directory, Bash will put the pattern itself (*.jpg) into the $x variable. You need to explicitly check that the file in the variable actually exists before working on it.

Indeed that's one thing Elvish has better defaults that I forgot to mention in https://elv.sh/learn/scripting-case-studies.html#jpg-to-png...., and now I've added that, thanks :)


The latter can be avoided with “shopt -s failglob”.


Why the hostile tone? I don’t see anything on the website saying you should do it. You could, though, up to you. I doubt the authors had you in mind specifically when they wrote the tool.

They made something new and non-detrimental and are sharing it with the world. It’s fine if it’s not something you’re going to use. I won’t either, but I’m failing to see the point of ridiculing their effort.

Your example seems unfair, too. It’s not like that is the only use-case on the homepage.


The thing is, the first example doesn't handle many edge cases which normally arise and are a common source of bugs and security vulnerabilities. The second example doesn't suffer from those issues by design.

In other words, it's OK to type the first example on the command line and it'll work just fine (and if it won't, you'll be able to step in and fix). But running it as part of anything automated would be haphazard.

As I read this, the whole point is that you have something that feels quite familiar syntactically to a common shell, but sane. Kudos to the author!


At this point, I'd just use Tcl:

  foreach x [glob *.jpg] {
    exec gm convert $x [regsub {\.jpg$} $x {}].png
  }
(bonus, you can use `foreach x [glob *.jpg] y [glob *.png]` to iterate on more than one list at once)

The truth is: if you choose to use something rarer than a ten-leafed clover, you better have massively good reasons to do so. Otherwise, there are already other languages with good subprocess integration; pretty sure Guile would do the trick too.


Tcl is actually an inspiration for Elvish, and Elvish has a "command language" flavor too.

The "everything is a string" idea sadly turned out to not work that well for most people though, so Elvish has lists, maps, and first-class functions :)


Modern Tcl has all of these, you know? "Everything is a string" should actually be "everything has a string representation allowing for lossless roundtrip", but it's a bit less snappy; maybe you mean the lack of typing and I'd kind of agree with you here, though it's what makes Tcl's weird homoiconicity work.

Tcl lists are arrays (and kind of deques since https://core.tcl-lang.org/tips/doc/trunk/tip/625.md), dicts are the first-class maps we should have had since the beginning and apply allows to build closures around it.


> (bonus, you can use `foreach x [glob *.jpg] y [glob *.png]` to iterate on more than one list at once)

I don't know about Elvish, but globs in bash aren't part of the loop syntax, they're their own thing, so this also just works:

  for x in *.jpg *.png


This just concatenates the lists, in Tcl (or CL's loop), you can iterate on multiple lists in parallel. Like Python's zip, but cleaner since you don't need said zip.


I would invite you to read the explainer for this script: https://elv.sh/learn/scripting-case-studies.html#jpg-to-png....

Maybe you're not as traumatized by the thousand small cuts when writing traditional shell scripts as I, and that's fair :) However, I'd also invite you to read the rest of the examples, which go into the deeper advantages.

I'd also say that you don't have to "change my shell, have it deployed everywhere, and learn a new language" to start adopting Elvish! It's very easy to get Elvish (https://elv.sh/get/), and you can start using it on one machine, or for one script without "switching" 100%. Think of it as another tool you can use alongside whatever shell you are using (I'd also refer you to the other comment I posted: https://news.ycombinator.com/item?id=40317203).


Thanks for that succinct visual. Would be nice to have a side-by-side comparison like this for all the popular and up-and-coming shells. Really helps since the final choice is often influenced by style preference.


You can find this in the explainer linked from the example too :) https://elv.sh/learn/scripting-case-studies.html#jpg-to-png....

https://elv.sh/learn/tour.html also has a big list of syntax comparison between bash and Elvish.


Thanks, but I was thinking more along the lines of a single semi-complex script, like what https://todomvc.com/ does for selecting a framework.


So according to you, there should be no innovation, never?


No, but innovation should be major, not cosmetic.


I would invite you to read the rest of the explainers, which go into deeper differences: https://elv.sh/learn/scripting-case-studies.html

Re "cosmetic" - I'd agree that the extent syntax matters is more limited compared to semantics, but that limited extent can be a lot of the daily experience with a language! I've ported many bash scripts to Elvish and I still find it liberating to not have to write double quotes everywhere for my script to handle whitespaces correctly.


The biggest innovation here (shells centered on structured data rather than strings) comes from PowerShell. But PowerShell sucks as an interactive shell.

I see the basic concept for Elvish as PowerShell's language power, but with the more Unix-y sensibilities of traditional shells, plus, crucially, the human-friendly focus on rich built-ins for interactivity exemplified by fish.

I don't think a real-world implementation of that kind of idea is a 'merely cosmetic' innovation. There's real novelty in that synthesis. How to balance those inspirations is not obvious, and neither is how to fill the gaps between the big picture ideas and a usable tool.

Go use Elvish for a while and you'll see how much creativity has clearly gone into it. Hell, just browse the GitHub issues and you'll see.


The whole point of an interactive shell is cosmetic convenience.


It's not cosmetic in this case. As others have already pointed out, the elvish version handles a few minor but important special cases that bash does not handle.


and perhaps that's why today's shells are not very far from the shells 20 years ago.


I don't follow. How does the one explain the other?


The second example was more unfamiliar, especially with the bespoke `{|h|...}` syntax. But yes, the first example looks...the same as a bash for loop.


There are explainers linked from each of the examples - in this case https://elv.sh/learn/scripting-case-studies.html#update-serv.... Hopefully that clears up things for you!


> especially with the bespoke `{|h|...}` syntax.

It’s similar to Ruby.


And vaguely reminiscent of Smalltalk, which I'd guess is where Ruby got it from.


Elvish's lambda syntax used to be [arg]{ ... }. But since [arg] is also the syntax for lists, it can get confusing - so I decided to move the argument list inside { ... }. And going through all the metacharacters Elvish already had, | was the one that was meaningless at the start of the lambda body, so I settled on {|arg| ... }.

I only realized the similarity with Smalltalk after that. I did learn a little Smalltalk many years ago but completely forgot about it, but it's possible that the knowledge was always somewhere in my subconscious brain.


To be fair, all examples on the home page look kind of trivial in bash as well, which is why - to me - they seem a bit silly.

    var hosts = [[&name=a &cmd='apt update']
                 [&name=b &cmd='pacman -Syu']]
    # peach = "parallel each"
    peach {|h| ssh root@$h[name] $h[cmd] } $hosts
is

    hosts=( \
        "host_a" "apt update"  \
        "host_b" "pacman -Syu" \
    )
    printf "%s\n" "${hosts[@]}" | xargs -L2 bash -c 'echo ssh root@$0 -- $*'
and

    ~> var project = ~/project
    ~> rm -rf $projetc/bin
    compilation error: variable $projetc not found
is

    set -u
    project=~/project
    rm -rf $projetc/bin
    bash: projetc: unbound variable
Now of course, there are a lot of edge cases in bash, especially around escaping and quoting, which are not handled in my crude examples.

What annoys me with these new shells, is that they dont solve any issue of the real world.

Yes, your language is cute.

Yes it's safer and less error prone that bash, there's no denying that.

But it does not - and most likely will never - handle the trillion - arguably hacky - things that can are done in bash, because that would suddenly completely overbloat the language, multiply its complexity, etc.

Essentially that means it will always be some kind of niche toy with a couple of enthusiasts, while the rest of the world keep on sticking to bash, and overall nothing moved forward.

Now don't get me wrong, I'm all for writing toys. I also have hundreds of my own reimplementations of stuff just because it's fun to code, you learn stuff, etc. But I don't get the "I'm going to create a fancy website, build a community and post it on HN" vibe.

If you seriously think the shell scripting world need a refresher, then the real issue, and we all know it, is not the fanciness of the language. That's the fun part.

The real, actual work, is to provide a realistic path forward. Either by working on bash to improve its syntax to something more modern, maybe through `set` flags to keep backward compatibility. Or to write a transpiler to bash, but with safer and stronger semantics.

This is the actual path forward, and it's the _not fun_ part, it's grunt work, and nobody does it, meanwhile we can sit and use a shiny shell while complaining how bad and unsafe bash is.


While I don't agree with most of your analysis - in particular for the second example, I'd invite you to read its explainer that goes into much more depth (https://elv.sh/learn/scripting-case-studies.html#update-serv...) - I think you might be more interested in the Oil Shell project, which is trying to chart a smooth upgrade path from bash: https://www.oilshell.org

I think we simply can't say for sure which path is better for the future of shells, and I'm quite excited by the fact that different projects are exploring different directions. I will just stick to the path I find best and won't try to convert you :)


Is there a "checklist" for writing your own shell? Or a comprehensive guide?

This looks very cool, and I've been having a lot of inspiration to write my own shell, but I want to make it vaguely compatible with my system.

POSIX compatibility might be overkill for the start.


80% of the shell is just a normal interpreter. Crafting Interpreters (http://craftinginterpreters.com) is a pretty popular book for that.

The remaining parts are stuff about process and file semantics - you can find that in APUE, or really from reading manpages. You also need to learn the arcane VT100 escape sequences for the TUI, and there are plenty of articles for that too.


I actually have Crafting Interpreters on my shelf!

It looks like APUE might be the ticket to fill in some of my gaps though. Thank you for the suggestion.

Escape sequences should be fine (famous last words?).


There are so many cool shells out there — I would suggest studying the source code of any of the popular ones written in a modern high level typed language. That way navigating the code-base to understand how things are done will be easy. No point looking at old crusty codebases written in C.

Elvish is written in golang. I’m sure that’s going to be quite grokkable if you want to understand how a shell is written ?


> No point looking at old crusty codebases written in C.

I understand why someone might not want to start there, but I think that could be a bit short-sighted. I think people are far too quick to dismiss code that's old. Yeah, it may have a lot of warts (for a lot of reasons, some more valid than others), but that doe not negate the value of understanding how something was implemented.

I'm also not suggesting this would be easy. There are some very complicated C codebases out there. I'm just saying that I disagree that there's no point in examining them.


I actually have a really hard time just reading source code to understand it.

Even if it's heavily commented, I learn better from debate, trade off analysis, or failure analysis.

To put it simply, I like argue and break things.


Marketing slogan for the conference T-shirts: "Elvish is not dead" ?-)

You're welcome.


I really like the design of that webpage.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: