finished nushell post

This commit is contained in:
Gabe Venberg 2024-03-12 15:22:36 -05:00
parent 48894db4a6
commit 9428a36240

View file

@ -1,7 +1,6 @@
+++ +++
title = "Nushell first impressions" title = "Nushell first impressions"
date = 2024-03-01T11:34:04-06:00 date = 2024-03-01T11:34:04-06:00
draft = true
+++ +++
Ive been trying out a bunch of new shell utilities lately, Ive been trying out a bunch of new shell utilities lately,
@ -59,7 +58,7 @@ Some examples of things that nushell enables with this structured data passing
through pipelines includes: through pipelines includes:
{{<highlight sh>}} {{<highlight sh>}}
# show all files recurisively that were modified in the last week # show all files recursively that were modified in the last week
ls **/* | where modified > ( ls **/* | where modified > (
# create timestamp from relative human readable string. # create timestamp from relative human readable string.
'1 week ago' | into datetime '1 week ago' | into datetime
@ -147,7 +146,7 @@ they take.
{{<highlight sh>}} {{<highlight sh>}}
def recently-modified [cutoff] { def recently-modified [cutoff] {
# show all files recurisively that were modified after a specified cutoff # show all files recursively that were modified after a specified cutoff
# show all files recurisively that were modified after a specified cutoff # show all files recurisively that were modified after a specified cutoff
ls **/* | where modified > ( ls **/* | where modified > (
# create timestamp from input # create timestamp from input
@ -160,7 +159,7 @@ You can optionally give the arguments a type
{{<highlight sh>}} {{<highlight sh>}}
def recently-modified [cutoff: string] { def recently-modified [cutoff: string] {
# show all files recurisively that were modified after a specified cutoff # show all files recursively that were modified after a specified cutoff
# show all files recurisively that were modified after a specified cutoff # show all files recurisively that were modified after a specified cutoff
ls **/* | where modified > ( ls **/* | where modified > (
# create timestamp from input # create timestamp from input
@ -174,7 +173,7 @@ with a type specification)
{{<highlight sh>}} {{<highlight sh>}}
def recently-modified [cutoff = '1 week ago'] { def recently-modified [cutoff = '1 week ago'] {
# show all files recurisively that were modified after a specified cutoff # show all files recursively that were modified after a specified cutoff
ls **/* | where modified > ( ls **/* | where modified > (
# create timestamp from input # create timestamp from input
$cutoff | into datetime $cutoff | into datetime
@ -189,13 +188,13 @@ absence)
{{<highlight sh>}} {{<highlight sh>}}
def recently-modified [cutoff: string = '1 week ago' --older-than (-o)] { def recently-modified [cutoff: string = '1 week ago' --older-than (-o)] {
if $older_than { if $older_than {
# show all files recurisively that were modified after a specified cutoff # show all files recursively that were modified after a specified cutoff
ls **/* | where modified > ( ls **/* | where modified > (
# create timestamp from input # create timestamp from input
$cutoff | into datetime $cutoff | into datetime
) )
} else { } else {
# show all files recurisively that were modified before a specified cutoff # show all files recursively that were modified before a specified cutoff
ls **/* | where modified < ( ls **/* | where modified < (
# create timestamp from input # create timestamp from input
$cutoff | into datetime $cutoff | into datetime
@ -209,7 +208,7 @@ arguments.
{{<highlight sh>}} {{<highlight sh>}}
def recently-modified [--cutoff = '1 week ago' ...paths] { def recently-modified [--cutoff = '1 week ago' ...paths] {
for $path in $paths { for $path in $paths {
# show all files recurisively that were modified after a specified cutoff # show all files recursively that were modified after a specified cutoff
ls $path | where modified > ( ls $path | where modified > (
# create timestamp from input # create timestamp from input
$cutoff | into datetime $cutoff | into datetime
@ -228,7 +227,7 @@ def recently-modified [
...paths # paths to consider ...paths # paths to consider
] { ] {
for $path in $paths { for $path in $paths {
# show all files recurisively that were modified after a specified cutoff # show all files recursively that were modified after a specified cutoff
ls $path | where modified > ( ls $path | where modified > (
# create timestamp from input # create timestamp from input
$cutoff | into datetime $cutoff | into datetime
@ -271,8 +270,56 @@ but easy in POSIX shells.
## Error messages ## Error messages
Nushell brings with it great, self explanatory error messages. Nushell brings with it great error messages that explain where the error
For example, if we do this: occurred. In bash, if we have a loop like:
{{<highlight sh "linenos=false">}}
$ for i in $(ls -l | tr -s " " | cut --fields=5 --delimiter=" "); do
echo "$i / 1000" | bc
done
{{</highlight>}}
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
echo "$i / 1000" | bc
done
(standard_in) 1: syntax error
(standard_in) 1: syntax error
(standard_in) 1: syntax error
(standard_in) 1: syntax error
(standard_in) 1: syntax error
(standard_in) 1: syntax error
(standard_in) 1: syntax error
(standard_in) 1: syntax error
(standard_in) 1: syntax error
{{</highlight>}}
This error tells you nothing about what went wrong, and your only option is to
start print debugging.
The equivalent in nushell would be:
{{<highlight sh "linenos=false">}}
> ls | get size | each {|item| $item / 1000}
{{</highlight>}}
If we typo the size column, we get a nice error telling us exactly what we got
wrong, and where in the pipeline the error and value originated. Much better.
{{<highlight sh "linenos=false">}}
> ls | get szie | each {|item| $item / 1000}
Error: nu::shell::column_not_found
× Cannot find column
╭─[entry #1:1:1]
1 │ ls | get szie | each {|item| $item / 1000}
· ─┬ ──┬─
· │ ╰── cannot find column 'szie'
· ╰── value originates here
╰────
{{</highlight>}}
## Whats not there yet ## Whats not there yet
@ -289,4 +336,39 @@ invoking them from within nu treats them as external commands,
meaning they take in and pass out plain text, meaning they take in and pass out plain text,
rather than the structured data that you would get with a proper custom command rather than the structured data that you would get with a proper custom command
or nu builtin. or nu builtin.
//explain the best workaround. The best workaround Ive found so far is instead of making scripts that you run
directly, you define a custom command in the script file, `use` that file, and
then run the custom command, like this:
{{<highlight sh>}}
# recently-modified.nu
# display recently modified files
def recently-modified [
--cutoff = '1 week ago' # cutoff to be considered 'recently modified'
...paths # paths to consider
] {
for $path in $paths {
# show all files recursively that were modified after a specified cutoff
ls $path | where modified > (
# create timestamp from input
$cutoff | into datetime
)
}
}
{{</highlight>}}
{{<highlight sh "linenos=false">}}
> use recently-modified.sh
> recently-modifiued --cutoff '2 weeks ago' ./
{{</highlight>}}
Its certainly not the most ergonomic, but seems to be the best way at the moment
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
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.