WIP on cli renassance.

This commit is contained in:
Gabe Venberg 2024-03-14 13:03:31 -05:00
parent 7912b0fd37
commit 11424579e4
2 changed files with 173 additions and 70 deletions

View file

@ -4,58 +4,80 @@ date = 2024-03-04T12:20:02-06:00
draft = true
+++
<!--
btop, 2021, c++
bat, 2018, rust
helix, 2020, rust
zoxide, 2020, rust
starship, 2019, rust
difftastic, 2018, rust
git-delta, 2019, rust
nushell, 2018, rust
hyperfine, 2018, rust
sd, 2018, rust
tre, 2019, rust
typst, 2019, rust
yazi, 2024, rust
fd, 2017, rust
ripgrep, 2016, rust
ast-grep, 2022, rust
pueue, 2015, rust
diskonaut, 2020, rust
broot, 2018, rust
just, 2016, rust
zellij, 2020, rust
scc, 2018, go
fzf, 2013, go
lazygit, 2018, go
grex, 2019, rust
micro, 2016, go
oh-my-posh, 2019, go
nnn, 2016, c
qalculate, 2016, c++
eza/exa, 2014, rust
lsd, 2018, rust
neovim, 2015, c
cat, cd, rm, cp, man was included in the first version of unix, in 1971
ls specifically can trace its history to 1961 (https://tldp.org/LDP/LG/issue48/fischer.html)
vi was made in 1976
sed in 1974
awk in 1985
grep in 1973
bc in 1975
diff in 1974
make in 1976
vim in 1991
ssh in 1995
midnight commander in 1994
screen in 1987
tmux in 2007
rust 1.0 in 2015
tool,link,year,language
ls,,1961,c
cat,,1971,c
cd,,1971,c
cp,,1971,c
man,,1971,c
rm,,1971,c
grep,,1973,c
diff,,1974,c
sed,,1974,c
bc,,1975,c
make,,1976,c
vi,,1976,c
awk,,1985,c
screen,,1987,c
vim,https://www.vim.org/,1991,c
midnight commander,,1994,c
ssh,,1995,c
fossil,https://fossil-scm.org/home/doc/trunk/www/index.wiki,2006,c
tmux,https://github.com/tmux/tmux,2007,c
git,https://git-scm.com/,2008,c
go 1.0,https://go.dev/,2012,go
fzf,https://github.com/junegunn/fzf,2013,go
eza/exa,https://github.com/eza-community/eza,2014,rust
neovim,https://neovim.io/,2015,c
pueue,https://github.com/Nukesor/pueue,2015,rust
rust 1.0,https://www.rust-lang.org/,2015,rust
just,https://github.com/casey/just,2016,rust
micro,https://micro-editor.github.io/,2016,go
nnn,https://github.com/jarun/nnn,2016,c
ripgrep,https://github.com/BurntSushi/ripgrep,2016,rust
fd,https://github.com/sharkdp/fd,2017,rust
bat,https://github.com/sharkdp/bat,2018,rust
broot,https://dystroy.org/broot/,2018,rust
difftastic,https://difftastic.wilfred.me.uk/,2018,rust
hyperfine,https://github.com/sharkdp/hyperfine,2018,rust
lazygit,https://github.com/jesseduffield/lazygit,2018,go
lsd,https://github.com/lsd-rs/lsd,2018,rust
nushell,https://www.nushell.sh/,2018,rust
scc,https://github.com/boyter/scc,2018,go
sd,https://github.com/chmln/sd,2018,rust
git-delta,https://github.com/dandavison/delta,2019,rust
grex,https://github.com/pemistahl/grex,2019,rust
starship,https://starship.rs/,2019,rust
tre,https://github.com/dduan/tre,2019,rust
typst,https://typst.app/,2019,rust
diskonaut,https://github.com/imsnif/diskonaut,2020,rust
helix,https://helix-editor.com/,2020,rust
pijul,https://pijul.org/,2020,rust
zellij,https://zellij.dev/,2020,rust
zoxide,https://github.com/ajeetdsouza/zoxide,2020,rust
btop,https://github.com/aristocratos/btop,2021,c++
ast-grep,https://github.com/ast-grep/ast-grep,2022,rust
yazi,https://github.com/sxyazi/yazi,2024,rust
-->
Id like to talk about a trend Ive seen these past few years, where people are rewriting core CLI tools,
why I think this trend is a good thing, and why I think this trend might be happening.
<!--
open tmp.csv |
sort-by year tool |
update tool {|i| if ($i.link != "") {$"[($i.tool)]\(($i.link)\)"} else {$i.tool}} |
select tool year language |
to md |
xsel -bi
-->
<!--
ls specifically can trace its history to 1961
-->
Take a look at this [table](#appendix-the-tools) at the bottom of the page. Ill
wait. Notice the relative scarcity between ~1995 and ~2015? Id like to talk
about a trend Ive seen these past few years, where people are rewriting and
rethinking staples of the CLI, why I think this trend is a good thing, and why I
think this trend might be happening.
## History
@ -86,20 +108,38 @@ the way that error messages can teach,
the value of a good out of the box experience,
and the value of documentation that is easy to find and digest.
## The new tools
## Exploration of the solution space
These changes to the environment surrounding CLI apps has, in recent years,
These changes to the environment surrounding CLI apps has in recent years,
led to a resurgence in development of command line utilities.
Instead of just developing tools that dont exist,
Instead of just developing completely new tools,
Ive noticed that people are rethinking and reinventing tools that have existed since the early days of Unix.
## Exploration of the design space
## The lessons learned from the past
A large amount of the innovation in the area, I think, can be attributed to
lessons that have been learned in 50 years of using software; sharp edges we
have repeatedly cut ourselves on, unintuitive interfaces that repeatedly trip us
up, and growing frustration at the limitations that maintaining decades of
backwards compatibility imposes on our tools.
These lessons have been gathering in the collective conciousness, through
cheatsheets, guides, and FAQs; resources to guide us through esoteric error
messages, complex configurations, and dozens upon dozens of flags.
Id like to go over a couple of the more prominent lessons that I feel terminal
tools have learned in the past several decades.
### A good out of the box experience
While configurability is great, one should not need to learn a new configuration
language and dozens or hundreds of options to get a usable piece of software.
Configuration should be for customization, not setup.
One of the earliest examples of this principle may be the fish shell.
Both zsh and
<!-- look at helix compared to (neo)vim-->
<!-- look at zsh compared to fish?-->
### Friendly error messages
@ -127,3 +167,65 @@ Ive noticed that people are rethinking and reinventing tools that have existed s
<!-- rusts clap and gos cobra-->
## Appendix: the tools
This is an extremely unscientific table of command line tools that I have tried,
have used, or currently use. It is assuredly incomplete, but *should* be broadly
representative. The date data has been gathered from the first git commit where
available, wikipedia otherwise, and sorting is by year first, then alphabetical.
|tool|year|language|
|-|-|-|
|ls|1961|c|
|cat|1971|c|
|cd|1971|c|
|cp|1971|c|
|man|1971|c|
|rm|1971|c|
|grep|1973|c|
|diff|1974|c|
|sed|1974|c|
|bc|1975|c|
|make|1976|c|
|vi|1976|c|
|awk|1985|c|
|screen|1987|c|
|[vim](https://www.vim.org/)|1991|c|
|midnight commander|1994|c|
|ssh|1995|c|
|[fossil](https://fossil-scm.org/home/doc/trunk/www/index.wiki)|2006|c|
|[tmux](https://github.com/tmux/tmux)|2007|c|
|[git](https://git-scm.com/)|2008|c|
|[go 1.0](https://go.dev/)|2012|go|
|[fzf](https://github.com/junegunn/fzf)|2013|go|
|[eza/exa](https://github.com/eza-community/eza)|2014|rust|
|[neovim](https://neovim.io/)|2015|c|
|[pueue](https://github.com/Nukesor/pueue)|2015|rust|
|[rust 1.0](https://www.rust-lang.org/)|2015|rust|
|[just](https://github.com/casey/just)|2016|rust|
|[micro](https://micro-editor.github.io/)|2016|go|
|[nnn](https://github.com/jarun/nnn)|2016|c|
|[ripgrep](https://github.com/BurntSushi/ripgrep)|2016|rust|
|[fd](https://github.com/sharkdp/fd)|2017|rust|
|[bat](https://github.com/sharkdp/bat)|2018|rust|
|[broot](https://dystroy.org/broot/)|2018|rust|
|[difftastic](https://difftastic.wilfred.me.uk/)|2018|rust|
|[hyperfine](https://github.com/sharkdp/hyperfine)|2018|rust|
|[lazygit](https://github.com/jesseduffield/lazygit)|2018|go|
|[lsd](https://github.com/lsd-rs/lsd)|2018|rust|
|[nushell](https://www.nushell.sh/)|2018|rust|
|[scc](https://github.com/boyter/scc)|2018|go|
|[sd](https://github.com/chmln/sd)|2018|rust|
|[git-delta](https://github.com/dandavison/delta)|2019|rust|
|[grex](https://github.com/pemistahl/grex)|2019|rust|
|[starship](https://starship.rs/)|2019|rust|
|[tre](https://github.com/dduan/tre)|2019|rust|
|[typst](https://typst.app/)|2019|rust|
|[diskonaut](https://github.com/imsnif/diskonaut)|2020|rust|
|[helix](https://helix-editor.com/)|2020|rust|
|[pijul](https://pijul.org/)|2020|rust|
|[zellij](https://zellij.dev/)|2020|rust|
|[zoxide](https://github.com/ajeetdsouza/zoxide)|2020|rust|
|[btop](https://github.com/aristocratos/btop)|2021|c++|
|[ast-grep](https://github.com/ast-grep/ast-grep)|2022|rust|
|[yazi](https://github.com/sxyazi/yazi)|2024|rust|

View file

@ -3,24 +3,24 @@ title = "Nushell first impressions"
date = 2024-03-01T11:34:04-06:00
+++
Ive been trying out a bunch of new shell utilities lately,
switching up my shell, terminal multiplexer, and even experimenting with my editor.
Today, Id like to focus on my experiments with my shell.
Ive been experimenting with the tools I use on a regular basis lately -- switching
up my shell, terminal multiplexer, and even trying out other editors. Today,
Id like to focus on my experiments with my shell.
## My old setup
Before this, I had been using a minimal zsh setup for a long time,
with only built in features and a handmade prompt.
Zsh is a good shell, probably one of the best posix shells out there,
and I still use it when a posix shell is needed.
Zsh is a good shell, probably one of the best POSIX shells out there,
and I still use it when a POSIX shell is needed.
However, I got tired of the endless footguns that posix shell scripting imposes,
However, I got tired of the endless footguns that POSIX shell scripting imposes,
easy to make errors around quoting, word splitting, and escaping,
the sort of thing that makes [shellcheck](https://www.shellcheck.net/) necessary.
I played around with fish for a few days,
but it had many of the same fundamental design choices, mainly, being 'stringly typed',
that made posix shells such a displeasure to work with.
that made POSIX shells such a displeasure to work with.
## A Nu shell
@ -95,7 +95,7 @@ explanatory comments.
## Parsing non-nu tools
But what if our tool/text file isnt in a format nushell understands?
Thankfully, for most formats, parsing is relatively straightforward.
Thankfully, for most formats parsing is relatively straightforward.
Lets take this NGINX server log, for example (not a log of real traffic, just a
sample log I found)
@ -108,8 +108,7 @@ sample log I found)
{{</highlight>}}
We can parse it into a nu table like so (each line has a comment explaining what
it does, for those unfamiliar with the nushell language):
We can parse it into a nu table like so:
{{<highlight sh>}}
open access.log |
@ -122,9 +121,10 @@ update time {into datetime -f '%d/%b/%Y:%T %z'} |
# parse into proper integer
update bytes_sent {into int}
{{</highlight>}}
(each line has a comment explaining what it does, for those unfamiliar with the nushell language)
Now that we have it in nushell tables, we can bring all of nushells tools to
bear on the data. We could, for example, plot a histogram of the most common
bear on the data. For example, we could plot a histogram of the most common
ips, just by piping the whole thing into `histogram ip`. We could easily
calculate the average bytes sent per request. We could group the records by the
day or hour they happened, and analyze each of those groups independently. And
@ -135,7 +135,7 @@ While it would be a pretty long one liner if we decided to put it in a single
line, its still quite easy and straightforward to write.
Most log formats and command outputs are similarly straightforward.
## Defining custom commands, with built in arg parsing
## Defining custom commands, with built-in arg parsing
Nushell has a feature called Custom Commands, which fill the same purpose as
functions in other shells/programming languages, but are a bit more featurefull
@ -278,7 +278,7 @@ echo "$i / 1000" | bc
done
{{</highlight>}}
This gets the sizes of all the files in kib. But what if we typo something?
This gets the sizes of all the files in KiB. But what if we typo something?
{{<highlight sh "linenos=false">}}
$ for i in $(ls -l | tr -s " " | cut --fields=6 --delimiter=" "); do
@ -367,8 +367,9 @@ to make 'scripts' that are integrated with the rest of nushell.
## So, overall, is it worth it?
Nushell is certainly an interesting project, and I will almost certainly be
Nushell is certainly an promising project, and I will almost certainly be
continuing to use it as my daily shell. It cant do everything, but dropping into
zsh for a task or two every once in a while isnt that big a deal for me, and
having access to such a powerful shell by default has made other tasks much
easier for me.
easier for me. If you regularly use pipelines in your default shell, consider
giving Nushell a try.