Hacker News new | ask | show | jobs
by chrash 490 days ago
nushell does this by default, sort of. it will show you autocompletes that are relevant to the current directory and will fallback to history more generally.

i’m a huge nushell fan. if you can stand a non POSIX shell, it’s great for working with any kind of structured data and has a sane mostly FP scripting language

2 comments

When I first switched to nushell as my daily driver, I spent a lot of time integrating fzf in various creative ways, which was a fine learning exercise I guess.

But once I realized that the auto complete was sensitive to my cwd, I've since been using my fzf bindings less and less.

I'm very happy I made the switch, for this and many other reasons.

What’s it give you that is significant?
I bet yash is great, sorry for distracting from the topic, but since you asked...

It's not one killer feature, but it's a lot of small things that add up to this feeling that POSIX shells are stuck in a rut and that a better world is possible.

I'm going to use docker output as an example. I know that you can ask docker for json and then use jq, but let's pretend that what you're working with isn't so friendly as docker. Here's the output of "docker ps", a string:

    CONTAINER ID   IMAGE            COMMAND                  CREATED       STATUS       PORTS                   
    786fc8348b7a   postgres:12.6    "docker-entrypoint.s…"   9 hours ago   Up 9 hours   127.0.0.1:5432->5432/tcp
I'm not proud of it, but I used to write bash scripts which looked like this:

    line=$(docker ps | grep postgres)
    echo $line | awk '{print $2}'
    echo $line | awk -F 'ago' '{print $2}' | sed 's/hours.*/hours/'
to get output like this

    postgres:12.6
    Up 9 hours
In nushell, that's this (notice that it gets the whitespace right, which is more than I can say for awk).

     $ docker ps | detect columns --guess | where ($it.IMAGE =~ postgres) | select IMAGE STATUS

    ╭───┬───────────────┬────────────╮
    │ # │     IMAGE     │   STATUS   │
    ├───┼───────────────┼────────────┤
    │ 0 │ postgres:12.6 │ Up 9 hours │
    ╰───┴───────────────┴────────────╯
This the part where somebody says "powershell does that too", but check out this stackoverflow post on just how that might be done: https://stackoverflow.com/questions/47335781/extract-columns... It's not exactly wow material.

Powershell feels to me like it's made by people who want all data to be structured, and who expect the app to do the work of structuring it for them. nushell feels like it's made by people who understand that text is king, and who are willing to attempt taming that beast as-is.

Plus there are a lot of batteries-included things that just feel nicer. Like if you want to make an http post request, the command is "http post". Of course you can still use curl, but I feel like this is so much more readable:

      $ let token = "REDACTED"
      ( http post
          -H {Circle-Token : $token}
          --content-type application/json
          "https://circleci.com/api/v2/project/gh/job/myproject/pipeline"
          {  branch: "main",  parameters:  { action: "dothething" }}
      )
The built in help is excellent (try "help http post"), and the error messages are very pleasant:

    $ 5 + "5"

    Error: nu::parser::unsupported_operation
    × addition is not supported between int and string.
       ╭─[entry #208:1:1]
     1 │ 5 + "5"
       · ┬ ┬ ─┬─
       · │ │  ╰── string
       · │ ╰── doesn't support these values
       · ╰── int
       ╰────
I dunno, it's just nice. I'd be much happier teaching a bunch of scientists to use nushell than I am when teaching them to use bash. When I try to do the latter I feel like I just stepped out of a time warp from the 60's and they think I'm here to punish them.
That "detect columns" piping stuff looks very nice, though it looks like this is something that could be implemented extrashellularly (as discrete "detect" and "where" binaries)?
Eh, yes and no. There's nothing stopping a cohort of programs from adopting some standard and using it among themselves such that the binary values that are traveling across the pipes are interpreted by the recipient as having some type, and then if the reader of your pipe is a tty then you draw a pretty picture for the user, which gets you much of the way there in principle.

But as far as I know there's no portable way to write a program which can uncover enough of the pipeline to print an error message that spans multiple stages. So you get output from potentially many of them and you have to figure out who is complaining.

I'm not intimate with the implementation but it feels like nushell commands are compiled, so there's much less deduction necessary to just tell the user what is wrong in a way that considers the whole command instead of just one stage of the pipeline.

I haven't spent much time with the plugin interface yet, but the idea is that programs can register their input and output types with the shell if they want nushell to treat them like it does it's builtins. Its an extra step up front, but it seems like less of a mess than trying to coordinate types been programs without having a common touch point for them.

Box-drawing characters can make output look nice, for sure.
True, but the more interesting bit is that the shell understands the structure of the data. The boxes are just how it communicates that.
What do you love about it? How would you demonstrate to a friend its value?
well, it’s a few things. a lot of it comes down to reading structured data and scripting. i will often stream logs from k8s or when running a service locally that outputs JSON, and nushell can parse the logs for readability or to find a particular field. i mean, that’s nothing jq couldn’t do. but having an integrated experience based more on readability makes things nice. also when i say scripting i mean actual real functions. you can define a command complete with parsed documented arguments as if you’re using argparse or clap, and it also supports completions. so when i go to sign into the company VPN i have a lil function that grabs my credentials and takes an argument that is one of several providers my company uses, which i can autocomplete with tab because i’ve written a simple completion helper (literally a function that returns a list). it’s documentation as code, and i push all these helpers up to my company git repo so when someone asks me how to do something i have workable readable examples. if you’ve ever wanted a real programming language (like Python) as your shell, i think this is worth a shot.