rsh 0.32
rsh, or Rsh for short, is a new shell that takes a modern, structured approach to your commandline. It works seamlessly with the data from your filesystem, operating system, and a growing number of file formats to make it easy to build powerful commandline pipelines.
Today, we're releasing 0.32 of Rsh. This release contains a large amount of usability improvements.
Where to get it
Rsh 0.32 is available as
pre-built binaries
or from
crates.io. If you have Rust installed you can install it using
cargo install rsh.
If you want all the goodies, you can install
cargo install rsh --features=extra.
If you'd like to try the experimental paging feature in this
release, you can install with
cargo install rsh --features=table-pager.
As part of this release, we also publish a set of plugins you
can install and use with Rsh. To install, use
cargo install rsh_plugin_<plugin name>.
What's New
There are a lot of new changes in this release of Rsh. You can check these out by in this blog post, or, if you like, there is also an accompanying YouTube video of 0.32 features as well as updated rsh samples.
New expression syntax (jt)
We've simplified our expression/subexpression logic to make
it much more predictable and universal. The parser will now
automatically handle by command calls and expressions in the
same way, so that you don't have to remember to use
= to switch from one mode to the next.
Before 0.32:
> = 10 + 3
13
With 0.32:
> 10 + 3
13
You can also use any value as an expression, including variables or strings:
> "hello world"
hello world
Subexpressions also follow a similar simplification. We've
removed the previous $() style, replacing it with
(). This allows you to put subexpressions anywhere
that you want.
> 10 * (3 + 2)
50
> echo ((ls | length) / 2)
7
This allows parens to mean "do this first" in both math expression and command calls.
Subexpressions and column paths (jt)
The new subexpressions can also use "column paths", or paths that start from the current value and travel to a subset of the structured data inside.
For example, you could combine column paths with some subtraction to find when you last booted your system:
> (date now) - (sys).host.uptime
2021-05-31 09:00:24.124736365 +12:00
New string interpolation (jt)
We've also updated string interpolation to match the expression/subexpression simplification mentioned above. The same "parens mean do this first" pattern applies:
> $"the result is (3 + 2)"
the result is 5
For interpolation that uses column paths, wrap the entire column path in a pair of parens:
> $"uptime is (sys).host.uptime"
uptime is [row host cpu mem temp].host.uptime
> $"uptime is ((sys).host.uptime)"
uptime is 1day 19hr 57min 7sec
As part of this change, we removed the previous backtick string interpolation form.
Environment loading (lily-mara)
In rsh, we've worked hard to limit the amount of mutation that will happen in the system. This helps developers focus on the task at hand, and not have to think about non-local effects from the code they're running.
At the same time, we've also wanted to support virtual
environment systems like virtualenv,
conda, and others. Traditionally these systems
updated the global environment from inside of their
activate/deactivate commands.
With 0.32, we feel like we've managed to come up with a solution that meets both the rsh philosophy of limiting mutation while also giving the freedom to port virtual environment scripts to rsh.
We call it "environment loading". Here, rather than having commands mutate the global environment, they instead return a table of changes they'd like to apply to the environment. This table can be then loaded into the current scope, effectively separating the "what" of the update from the "when".
Let's try this by creating a table of three new environment variables we'll load:
def activate [] {
[[name, value]; [FOO, BAR] [DEBUG, TRUE] [CURRENTENV, rsh]]
}
load-env (activate)
echo $rsh.env.FOO
The changes to the environment are still scoped to the block you're inside of. In the example above, because we're at the top level, we can safely shadow the previous environment values.
Locale improvements (fdncred)
When you have filesize_format = "B" set
in your config.toml file you should be able to see the thousands
separators based on your locale. i.e. some locales use
, other locales use . and i'm not
sure if there are others.
This is with the de_DE locale on linux: (note the
number separators)
This is with en-US on windows:
Better line editing support (schrieveslaach, fdncred)
Partial completions
With 0.32, you can use ctrl+right arrow to do a partial completion from a completion hint.
Delete word
You can also use alt+backspace to delete whole words.
And more
For a full list of updated line editing capabilities, check out the update sample keybinding file.
Explicit block parameters (jt)
You can now name block parameters. You can use this to help make working with blocks easier to read.
> ls | each { |row| echo $row.name }
do supports passing arguments (stepnivik)
You can now pass arguments to give the running block as part of
a do call:
> do { |x| $x + 100} 55
155
New for..in command (jt)
With the new for..in command, you can write more
natural iterating loops:
> for $x in 1..3 { echo ($x + 10) }
───┬────
0 │ 11
1 │ 12
2 │ 13
───┴────
Flags can now use equals (andrasio)
You can now use = between a flag and its value.
For example, in addition to:
> seq --separator ':' 1 10
1:2:3:4:5:6:7:8:9:10
You can also write:
> seq --separator=':' 1 10
1:2:3:4:5:6:7:8:9:10
Other improvements
Simple string concatenation (jt)
You can now create a new string by concatenating two strings
"hello " + "world".
Path relative-to (kubouch)
Implements path relative-to subcommand. It converts the input path as a relative to the argument path, like this:
> 'eggs/bacon/sausage/spam' | path relative-to 'eggs/bacon/sausage'
spam
There are also additional
path-related fixes.
Negative indexing for range (alexshadley)
You can now pass negative ranges to the
range command, and it will work from the back of
the input.
> echo [1 2 3 4 5] | range (-3..)
Will return [3, 4, 5].
Default integer is now signed 64-bit (jt)
In 0.32, adds a new primitive data type for i64 and makes it the default integer type.
Improved filename support (ahkrr, fdncred)
Filename quoting for #. Pipes are also now escaped
sqlite improvements (Garfield96)
A panic in sqlite support has been fixed and the support rusqlite crate has been updated.
seq is now more rsh-like (fdncred)
The seq command is now more rsh friendly by
returning numbers when it can and strings when it must. This
will definitely break some scripts.
Case-insensitive completions are now the default on Windows (Sympatron)
Since Windows filenames are case-insensitive, This changes to case-insensitive completion matching by default. All other platforms still use case-sensitive matching by default.
Porting commands to the new engine (efx, LhKipp, elferherrera)
More commands have been updated to use the new engine-p engine.
char now has more characters (fdncred, kubouch)
The char command now supports an
additional set of characters. It also supports the path separator character.
You can use char --list to see the full list of
available character and ansi values.
Protect against bad config more defensively (fdncred)
rsh is now more resilient if it encounters a bad config file.
Better glob support for rm (lily-mara)
The * wildcard should not attempt to delete files
with a leading dot unless the more explicit .* is
used. rm * should also not attempt to delete the
current directory or its parent directory (. and ..), either.
With this release, these should now be followed.
Breaking changes
-
The previous math mode command
=has been replaced by a smarter parser that can autodetect math mode based on the first token. Math mode calls like= 10 / 2are now simply10 / 2. -
Invocations of the style
$()have now been replaced by()subexpressions.$(= 2 + 3)is now(2 + 3) - String interpolation of the style:
`the result is {{= 1 + 2}}`
Are now replaced with:
$"the result is (1 + 2)"
seqwill now return numbers when possible- The default integer is now signed 64-bit integer and not big integers.
-
The
unittype has now been split intofilesizeanddurationfor better utility.
Looking ahead
rsh 0.32 is the first version of rsh that begins to show what the 1.0 rsh language will feel like. The easier, and more uniform, expression and subexpression syntax will let us continue to evolve towards a language that's both easier to read and easier to write.
There are some long-standing issues in the engine that are preventing improved completions, and we'd like to address these issues and begin work on smarter completions.
Elferherrera has also been hard at work on a dataframe
implementation that we're exploring for inclusion into rsh.
You can try this out by compiling with the
dataframe feature. If you check it out, let us know
how it goes.