Skip to content

Commit 88f62b5

Browse files
committed
use ansi escape codes for command output
1 parent f30ba23 commit 88f62b5

File tree

1 file changed

+151
-123
lines changed

1 file changed

+151
-123
lines changed

blog/2025-09-02-nushell_0_107_0.md

Lines changed: 151 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -67,27 +67,31 @@ Previously, `find` would always split multi-line input strings, making it imposs
6767

6868
Before:
6969

70-
```nu
71-
"hello\nworld" | find -mr 'lo\swo'
72-
# => no output
70+
```ansi
71+
> "hello\nworld" | find -mr 'lo\swo'
72+
╭────────────╮
73+
│ empty list │
74+
╰────────────╯
7375
```
7476

7577
After:
7678

77-
```nu
78-
"hello\nworld" | find -mr 'lo\swo'
79-
# => hello
80-
# => world
79+
```ansi
80+
[38;5;14m> [32m"hello\nworld"[39m [1m[35m|[22m[39m [1m[36mfind[22m[39m [1m[34m-mr[22m[39m [32m'lo\swo'[39m
81+
hel[41mlo
82+
wo[49mrl[0m
8183
```
8284

8385
### `random dice` moved to `std`
8486

8587
The `random dice` command has been rewritten in Nushell and moved to the standard library. The `random dice` built-in is still available with a deprecation error, but will be removed in 0.108. The new command can be used as follows:
8688

87-
```nushell
88-
use std/random
89-
90-
random dice
89+
```ansi
90+
> use std/random
91+
> random dice
92+
╭───┬───╮
93+
│ 0 │ 6 │
94+
╰───┴───╯
9195
```
9296

9397
It's behavior, parameters, and defaults are the same.
@@ -97,16 +101,21 @@ It's behavior, parameters, and defaults are the same.
97101
When `null` is passed to the `each` command, it now returns `null` instead of passing `null` to the closure.
98102
For example, before this change:
99103

100-
```nu
101-
→ null | each { "something" }
102-
something
104+
```ansi
105+
> null | each { "something" } | describe
106+
string
107+
> null | each { "something" }
108+
something
109+
>
103110
```
104111

105112
But after this change:
106113

107-
```nu
108-
→ null | each { "something" }
109-
null
114+
```ansi
115+
> null | each { "something" } | describe
116+
nothing
117+
> null | each { "something" }
118+
>
110119
```
111120

112121
### Execution Order of Hooks Changed: `env_change` _before_ `pre_prompt`
@@ -134,12 +143,12 @@ open -r tests/fixtures/formats/jt.xml
134143

135144
Before this change, this would return:
136145

137-
```
138-
╭───┬─────────╮
139-
# │ false()
146+
```ansi
147+
[37m╭───┬─────────╮
148+
[39m [1m[32m#[22m[39m [37m│[39m [1m[32mfalse()[22m[39m [37m
140149
├───┼─────────┤
141-
0 │ false
142-
╰───┴─────────╯
150+
[39m [1m[32m0[22m[39m [37m│[39m [96mfalse[39m [37m
151+
╰───┴─────────╯[0m
143152
```
144153

145154
Now, this will just return `false`.
@@ -178,23 +187,23 @@ open -r tests/fixtures/formats/jt.xml
178187

179188
While the most popular architectures use little endian, many people are used to reading binary numbers as little endian. However, until now, if you were in a little endian system, you would get:
180189

181-
```nushell
182-
~> 258 | format bits
183-
00000010 00000001
190+
```ansi
191+
[38;5;14m> [1m[35m258[22m[39m [1m[35m|[22m[39m [1m[36mformat bits[22m[39m
192+
00000010 00000001[0m
184193
```
185194

186195
If you copied and pasted that as a number, you would get a surprising result:
187196

188-
```nushell
189-
~> 0b00000010_00000001
190-
513
197+
```ansi
198+
[38;5;14m> [1m[35m0b00000010_00000001[22m[39m
199+
513[0m
191200
```
192201

193202
Now, `format bits` always formats in big endian:
194203

195-
```nushell
196-
~> 258 | format bits
197-
00000001 00000010
204+
```ansi
205+
[38;5;14m> [1m[35m258[22m[39m [1m[35m|[22m[39m [1m[36mformat bits[22m[39m
206+
00000001 00000010[0m
198207
```
199208

200209
### Add active column to `overlay list`
@@ -275,60 +284,76 @@ The `stor create/insert/open` and `query db` commands now support JSON and JSONB
275284

276285
Here's an example of storing a simple table inside a `stor` database, and retrieving it as structured data with `query db`:
277286

278-
```nushell
287+
```ansi
279288
# create a table named my_table with a JSON column named data
280-
stor create -t my_table -c {data: json}
289+
> stor create -t my_table -c {data: json}
290+
╭──────────┬────────────────╮
291+
│ my_table │ [list 0 items] │
292+
╰──────────┴────────────────╯
281293
282294
# inset a row into the data column containing a table
283-
{data: [1 2 3]} | stor insert -t my_table
295+
> {data: [1 2 3]} | stor insert -t my_table
296+
╭──────────┬───────────────────╮
297+
│ │ ╭───┬───────────╮ │
298+
│ my_table │ │ # │ data │ │
299+
│ │ ├───┼───────────┤ │
300+
│ │ │ 0 │ ╭───┬───╮ │ │
301+
│ │ │ │ │ 0 │ 1 │ │ │
302+
│ │ │ │ │ 1 │ 2 │ │ │
303+
│ │ │ │ │ 2 │ 3 │ │ │
304+
│ │ │ │ ╰───┴───╯ │ │
305+
│ │ ╰───┴───────────╯ │
306+
╰──────────┴───────────────────╯
284307
285308
# retrieve the data column from the table as structured data
286-
stor open | query db "select data from my_table"
287-
# => ╭───┬───────────╮
288-
# => │ #data
289-
# => ├───┼───────────┤
290-
# => │ 0 │ ╭───┬───╮ │
291-
# => │ │ │ 0 │ 1 │ │
292-
# => │ │ │ 1 │ 2 │ │
293-
# => │ │ │ 2 │ 3 │ │
294-
# => │ │ ╰───┴───╯ │
295-
# => ╰───┴───────────╯
309+
[38;5;14m> [1m[36mstor open[22m[39m [1m[35m|[22m[39m [1m[36mquery db[22m[39m [32m"select data from my_table"[39m
310+
╭───┬───────────╮
311+
│ [1m[32m#[22m[39m[1m[32mdata[22m[39m
312+
├───┼───────────┤
313+
│ [1m[32m0[22m[39m │ ╭───┬───╮ │
314+
│ │ │ [1m[32m0[22m[39m │ 1 │ │
315+
│ │ │ [1m[32m1[22m[39m │ 2 │ │
316+
│ │ │ [1m[32m2[22m[39m │ 3 │ │
317+
│ │ ╰───┴───╯ │
318+
╰───┴───────────╯[0m
296319
```
297320

298321
### New `random choice` command in `std-rfc`
299322

300323
The `random choice` command has been added as a new candidate for our standard library. This command can randomly sample a number of elements from a list:
301324

302-
```nushell
303-
use std-rfc/random
304-
[1 2 3 4 5] | random choice 2
305-
# => ╭───┬───╮
306-
# => │ 03
307-
# => │ 12
308-
# => ╰───┴───╯
325+
```ansi
326+
[38;5;14m> [1m[36muse[22m[39m [32mstd-rfc/random[38;5;14m
327+
> [1m[36m[[35m1[36m [35m2[36m [35m3[36m [35m4[36m [35m5[36m][22m[39m [1m[35m|[22m[39m [1m[36mrandom choice[22m[39m [1m[35m2[22m[39m
328+
╭───┬───╮
329+
│ [1m[32m0[22m[39m1
330+
│ [1m[32m1[22m[39m3
331+
╰───┴───╯[0m
309332
```
310333

311334
### Add `str align` to `std-rfc/str`
312335

313336
The `std-rfc/str` module has new command in this release, `str align`. This command will look for a substring (such as a delimiter), and add padding so that it is in the same column in all lines. It can also take a range to only align any number of lines.
314337

315-
```nushell
316-
[ "one = 1", "two = 2", "three = 3", "four = 4", "five = 5" ] | str align '='
317-
# => one = 1
318-
# => two = 2
319-
# => three = 3
320-
# => four = 4
321-
# => five = 5
338+
```ansi
339+
> use std-rfc/str
340+
> [ "one = 1", "two = 2", "three = 3", "four = 4", "five = 5" ] | str align '='
341+
one = 1
342+
two = 2
343+
three = 3
344+
four = 4
345+
five = 5
322346
```
323347

324348
### Spread `null` into collections or arguments
325349

326350
`null` values can be used with the spread operator (`...`), behaving as if they were empty lists or records (whichever is appropriate for its place)
327351

328-
```nushell
329-
[ 1 2 ...(null) ] == [ 1 2 ]
330-
331-
{ a:1 b:2 ...(null) } == { a:1 b:2 }
352+
```ansi
353+
> [ 1 2 ...(null) ] == [ 1 2 ]
354+
true
355+
> { a:1 b:2 ...(null) } == { a:1 b:2 }
356+
true
332357
```
333358

334359
### `get`, `select`, `reject` can `--ignore-case` of cell-path
@@ -371,13 +396,13 @@ If you're using any of the `--output-*` switches, and want `string_value` column
371396

372397
Previously, converting values to `binary` with `into binary` could only do so in the native endianness of your platform. Using native endianness is still the default, but with the `--endian` flag, you get to choose:
373398

374-
```nushell
375-
258 | into binary --endian little
376-
# => Length: 8 (0x8) bytes | printable whitespace ascii_other non_ascii
377-
# => 00000000: 02 01 00 00 00 00 00 00
378-
258 | into binary --endian big
379-
# => Length: 8 (0x8) bytes | printable whitespace ascii_other non_ascii
380-
# => 00000000: 00 00 00 00 00 00 01 02
399+
```ansi
400+
[38;5;14m> [1m[35m258[22m[39m [1m[35m|[22m[39m [1m[36minto binary[22m[39m [1m[34m--endian[22m[39m [32mlittle[39m
401+
Length: 8 (0x8) bytes | [1m[36mprintable [32mwhitespace [35mascii_other [33mnon_ascii[22m[36m
402+
00000000[39m: [1m[35m02[22m[39m [1m[35m01[22m[39m [38;5;242m00[39m [38;5;242m00[39m [38;5;242m00[39m [38;5;242m00[39m [38;5;242m00[39m [38;5;242m00[39m [1m[35m••[22m[38;5;242m000000[38;5;14m
403+
> [1m[35m258[22m[39m [1m[35m|[22m[39m [1m[36minto binary[22m[39m [1m[34m--endian[22m[39m [32mbig[39m
404+
Length: 8 (0x8) bytes | [1m[36mprintable [32mwhitespace [35mascii_other [33mnon_ascii[22m[36m
405+
00000000[39m: [38;5;242m00[39m [38;5;242m00[39m [38;5;242m00[39m [38;5;242m00[39m [38;5;242m00[39m [38;5;242m00[39m [1m[35m01[22m[39m [1m[35m02[22m[39m [38;5;242m000000[1m[35m••[0m
381406
```
382407

383408
Note that this only affects `int`, `float`, `filesize`, `bool` and `duration` (i.e. it does not affect `string`s, `date`s and `binary`). Likewise, only the individual elements in `table`s and `record`s are affected (not the `table` or `record` itself)
@@ -402,12 +427,12 @@ Note that this only affects `int`, `float`, `filesize`, `bool` and `duration` (i
402427
403428
The `http` subcommands can now maintain a list of redirects when using the `--full` flag. This will be stored in a new `urls` column:
404429

405-
```nushell
406-
http get --full http://nushell.sh | get urls
407-
# => ╭───┬────────────────────────╮
408-
# => │ 0 │ http://nushell.sh/ │
409-
# => │ 1 │ http://www.nushell.sh/ │
410-
# => ╰───┴────────────────────────╯
430+
```ansi
431+
[38;5;14m> [1m[36mhttp get[22m[39m [1m[34m--full[22m[39m [32mhttp://nushell.sh[39m [1m[35m|[22m[39m [1m[36mget[22m[39m [32murls[39m
432+
╭───┬────────────────────────╮
433+
│ [1m[32m0[22m[39m │ http://nushell.sh/ │
434+
│ [1m[32m1[22m[39m │ http://www.nushell.sh/ │
435+
╰───┴────────────────────────╯[0m
411436
```
412437

413438
> TODO(release-notes): make sure the callout below is in the correct format for the blog
@@ -481,41 +506,46 @@ http get --full --allow-errors http://localhost:1234
481506

482507
Previously, the help text for a missing flag would list all of them, which could get verbose on a single line:
483508

484-
```nushell
485-
~> ls --full-path
486-
Error: nu::parser::unknown_flag
487-
488-
× The `ls` command doesn't have flag `full-path`.
489-
╭─[entry #8:1:4]
490-
1 │ ls --full-path
491-
· ─────┬─────
492-
· ╰── unknown flag
493-
╰────
494-
help: Available flags: --help(-h), --all(-a), --long(-l), --short-names(-s), --full-paths(-f), --du(-d), --directory(-D), --mime-type(-m), --threads(-t). Use
495-
`--help` for more information.
509+
```ansi
510+
[38;5;14m> [1m[36mls[22m[39m [1m[34m--full-path[22m[39m
511+
Error: [31mnu::parser::unknown_flag
512+
[39m
513+
[31m×[39m The `ls` command doesn't have flag `full-path`.
514+
╭─[[1m[4m[36mentry #26:1:4[22m[24m[39m]
515+
[2m1[22m │ ls --full-path
516+
· [1m[35m ─────┬─────[22m[39m
517+
· [1m[35m╰── unknown flag[22m[39m
518+
╰────[36m
519+
help: [39mAvailable flags: --help(-h), --all(-a), --long(-l), --short-names(-s), --full-paths(-f), --du(-d),
520+
--directory(-D), --mime-type(-m), --threads(-t). Use `--help` for more information.[0m
496521
```
497522

498523
The new error message only suggests the closest flag:
499524

500-
```nushell
501-
> ls --full-path
502-
Error: nu::parser::unknown_flag
503-
504-
× The `ls` command doesn't have flag `full-path`.
505-
╭─[entry #23:1:4]
506-
1 │ ls --full-path
507-
· ─────┬─────
508-
· ╰── unknown flag
509-
╰────
510-
help: Did you mean: `--full-paths`?
525+
```ansi
526+
[38;5;14m> [1m[36mls[22m[39m [1m[34m--full-path[22m[39m
527+
Error: [31mnu::parser::unknown_flag
528+
[39m
529+
[31m×[39m The `ls` command doesn't have flag `full-path`.
530+
╭─[[1m[4m[36mentry #45:1:4[22m[24m[39m]
531+
[2m1[22m │ ls --full-path
532+
· [1m[35m ─────┬─────[22m[39m
533+
· [1m[35m╰── unknown flag[22m[39m
534+
╰────[36m
535+
help: [39mDid you mean: `--full-paths`?[0m
511536
```
512537

513538
### Improved default color theme
514539

515540
We changed the default theme to use the ANSI default color (`39m`) instead of white (`37m`).
516541
This finally makes the default theme usable in the context of light terminal color settings. On dark terminal palettes this change should have no impact.
517542

518-
<img width="1351" height="507" alt="Comparison of white vs default color on Solarized Light theme" src="https://github.com/user-attachments/assets/db80fe07-0cea-4a4b-ba14-e6a31f29cfe1" />
543+
Comparison of white vs default color on Solarized Light theme, before and after:
544+
545+
<p align="center">
546+
<img src="https://gist.githubusercontent.com/Bahex/08c6b780df1685ea3fa2c472e6d9b7d5/raw/705b102ccdef4faef48f0f1c2a9a5723858b1ccb/theme-before.svg" width="50%" />
547+
<img src="https://gist.githubusercontent.com/Bahex/08c6b780df1685ea3fa2c472e6d9b7d5/raw/705b102ccdef4faef48f0f1c2a9a5723858b1ccb/theme-after.svg" width="50%" />
548+
</p>
519549

520550
### Reset content type for commands returning partial input
521551

@@ -626,34 +656,32 @@ internal-alias; external-alias; unresolvable-alias
626656

627657
Previously `detect columns` created records (rows) with duplicate key names under some circumstances. The resulting table behaved inconsistently with different commands:
628658

629-
```nushell
630-
let data = "meooooow cat\nkitty kitty woof"
631-
$data | detect columns
632-
# => ╭───┬──────────┬───────╮
633-
# => │ # │ meooooow │ cat │
634-
# => ├───┼──────────┼───────┤
635-
# => │ 0 │ kitty │ kitty │
636-
# => ╰───┴──────────┴───────╯
637-
638-
$data | detect columns | get 0.cat
639-
# => woof
659+
```ansi
660+
> let data = "meooooow cat\nkitty kitty woof"
661+
> $data | detect columns
662+
╭───┬──────────┬───────╮
663+
│ # │ meooooow │ cat │
664+
├───┼──────────┼───────┤
665+
│ 0 │ kitty │ kitty │
666+
╰───┴──────────┴───────╯
667+
> $data | detect columns | get 0.cat
668+
woof
640669
```
641670

642671
Now, this will result in an error suggesting using `detect columns --guess` or `parse`:
643672

644-
```nushell
645-
let data = "meooooow cat\nkitty kitty woof"
646-
$data | detect columns
647-
# => Error: nu::shell::failed_to_detect_columns
648-
# =>
649-
# => × Failed to detect columns
650-
# => ╭─[entry #2:3:1]
651-
# => 2 │
652-
# => 3 │ $data | detect columns
653-
# => · ──┬── ───────┬──────
654-
# => · │ ╰── tried to detect columns here
655-
# => · ╰── value coming from here
656-
# => ╰────
673+
```ansi
674+
> let data = "meooooow cat\nkitty kitty woof"
675+
> $data | detect columns
676+
Error: nu::shell::failed_to_detect_columns
677+

678+
× Failed to detect columns
679+
╭─[entry #48:1:1]
680+
1 │ $data | detect columns
681+
· ──┬── ───────┬──────
682+
· │ ╰── tried to detect columns here
683+
· ╰── value coming from here
684+
╰────
657685
```
658686

659687
### Improve errors for subcommands without a corresponding parent command

0 commit comments

Comments
 (0)