11 ms·
Elvish, expressive programming language and a versatile interactive shell
- tromp 2y agoCute 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 https://en.wikipedia.org/wiki/.sh
- 8372049 2y agoIt'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.
- voidUpdate 2y agoElvish: what Sean Connery calls the King of Rock and Roll
- Galanwe 2y agoSo 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 }
- n0n0n4t0r 2y agoSo according to you, there should be no innovation, never?
- Galanwe 2y agoNo, but innovation should be major, not cosmetic.
- otabdeveloper4 2y agoThe whole point of an interactive shell is cosmetic convenience.
- yoavm 2y agoand perhaps that's why today's shells are not very far from the shells 20 years ago.
- pxc 2y agoI don't follow. How does the one explain the other?
- mrln 2y agoIt'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.
- xiaq 2y agoI would invite you to read the rest of the explainers, which go into deeper differences: https://elv.sh/learn/scripting-case-studies.html 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.
- pxc 2y agoThe 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.
- emptysongglass 2y agoAfter 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 https://github.com/akinomyoga/ble.sh [2] https://github.com/ohmybash/oh-my-bash https://github.com/ohmybash/oh-my-bash [3] https://atuin.sh/ https://atuin.sh/
- dkarl 2y ago> 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.
- achenet 2y agofor 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.
- noobermin 2y agoThe second example was more unfamiliar, especially with the bespoke `{|h|...}` syntax. But yes, the first example looks...the same as a bash for loop.
- latexr 2y ago> especially with the bespoke `{|h|...}` syntax. It’s similar to Ruby.
- cess11 2y agoAnd vaguely reminiscent of Smalltalk, which I'd guess is where Ruby got it from.
- xiaq 2y agoElvish'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.
- xiaq 2y agoThere are explainers linked from each of the examples - in this case https://elv.sh/learn/scripting-case-studies.html#update-servers-in-parallel.elv https://elv.sh/learn/scripting-case-studies.html#update-serv.... Hopefully that clears up things for you!
- Galanwe 2y agoTo 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.
- latexr 2y agoWhy 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.
- BoingBoomTschak 2y agoAt 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.
- xiaq 2y agoTcl 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 :)
- BoingBoomTschak 2y agoModern 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 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.
- Izkata 2y ago> (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
- BoingBoomTschak 2y agoThis 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.
- hxelk1 2y agoThe 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!
- deleted 2y ago[deleted]
- frankjr 2y agoAssuming 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.
- teddyh 2y agoThe latter can be avoided with “shopt -s failglob”.
- xiaq 2y ago> 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.elv https://elv.sh/learn/scripting-case-studies.html#jpg-to-png...., and now I've added that, thanks :)
- xiaq 2y agoI would invite you to read the explainer for this script: https://elv.sh/learn/scripting-case-studies.html#jpg-to-png.elv 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/ 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 https://news.ycombinator.com/item?id=40317203).
- mrbluecoat 2y agoThanks 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.
- xiaq 2y agoYou can find this in the explainer linked from the example too :) https://elv.sh/learn/scripting-case-studies.html#jpg-to-png.elv https://elv.sh/learn/scripting-case-studies.html#jpg-to-png.... https://elv.sh/learn/tour.html https://elv.sh/learn/tour.html also has a big list of syntax comparison between bash and Elvish.
- mrbluecoat 2y agoThanks, but I was thinking more along the lines of a single semi-complex script, like what https://todomvc.com/ https://todomvc.com/ does for selecting a framework.
- deleted 2y ago[deleted]
- cess11 2y agoLooked 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'.
- sidkshatriya 2y agoI 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.
- xiaq 2y agoHey, 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 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/ https://elv.sh/ref/) :)
- sidkshatriya 2y agoThe 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 !
- mst 2y agoI'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 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 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.
- noobermin 2y agoSo, 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.
- xiaq 2y ago> 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.elv https://elv.sh/learn/scripting-case-studies.html#jpg-to-png....).
- saurik 2y ago# is to the left of $ and removes the prefix. % is to the right of $ and removes the suffix.
- SpaghettiCthulu 2y agoI, like the person you replied to, will surely remember it for good thanks to your reminder.
- saurik 2y agoI 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.
- xiaq 2y agoAuthor of Elvish here, glad to see it's on the homepage again :) AMA.
- grzracz 2y agoWhat'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.
- sidkshatriya 2y agoBash 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” !
- xgdgsc 2y agoWhen I see a language with `var` to declare variables, I think I would just use julia as https://github.com/ninjaaron/administrative-scripting-with-julia https://github.com/ninjaaron/administrative-scripting-with-j...
- xiaq 2y agoI 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.
- eternityforest 2y agoSo 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.
- mst 2y agoThe examples for the math functions (https://elv.sh/ref/math.html 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 ;)
- xiaq 2y agoActually 1/2 is there because Elvish supports rational numbers, unfortunately there's no infix math. (Elvish supports arbitrary-precision integers and rationals.)
- aeonik 2y agoIs 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.
- sidkshatriya 2y agoThere 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 ?
- aeonik 2y agoI 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.
- nocman 2y ago> 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.
- xiaq 2y ago80% of the shell is just a normal interpreter. Crafting Interpreters (http://craftinginterpreters.com 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.
- jhbadger 2y agoI 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.
- haolez 2y agoWow, 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.elvish https://marketplace.visualstudio.com/items?itemName=elves.el...
- lebuffon 2y agoMarketing slogan for the conference T-shirts: "Elvish is not dead" ?-) You're welcome.
- d_burfoot 2y agoI'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?
- xiaq 2y agoI take your comment as implying that https://elv.sh 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.
- d_burfoot 2y agoThanks for the ideas, and yes it was a compliment :-)
- __MatrixMan__ 2y agoThis 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.
- svieira 2y agoRuby did it first, but it goes farther back at least to Smalltalk if not further.
- xiaq 2y agoIt wasn't directly borrowed from any other language (https://news.ycombinator.com/item?id=40317577 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 :)
- __MatrixMan__ 2y agoI had that backwards, perhaps they took inspiration from you :)
- sestep 2y agoRust uses the same syntax: https://doc.rust-lang.org/book/ch13-01-closures.html https://doc.rust-lang.org/book/ch13-01-closures.html
- steveklabnik 2y agoWhich came from Ruby which came from Smalltalk.
- netbioserror 2y agoReally 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.
- hot_gril 2y agoI really like the design of that webpage.