> It also turns out that getting a shell correct is a lot more experimentation and a lot less following what the textbooks say. In practice, things like ‘stdout’ and ‘stderr’ are used in a variety of ways, as are the exit codes output by programs. Our initial designs started with a stricter view of these ideas, and softened over time as we saw that the real world is a much fuzzier place than we realized.
Good point. Exit codes can be difficult. A non-zero error value may not be an error; it could indicate a type of success or be a warning or a result of a calculation or any number of things depending on the application.
At work we have a program that uses the exit code to encode three enums. Each digit of the decimal representation of the exit code corresponds to one of these enums.
It’s some of the most cursed code I’ve ever worked with.
(God bless anyone who ever used this program and got a set fault or sigint or sighup and therefore a bizarre result.)
In a redesigned shell, ideally there would be a richer way to describe the result of a program. Maybe "return an integer and consult the manual to see what it means" isn't the best way forward.
Personally, I think Result types from Rust/Haskell/Swift make a lot of sense -- a program either succeeds with some output, or fails with an explanation of why. By default, pipes stop piping if one command fails.
Plan9 returns an error string instead of an error integer with the empty string signifying success. This seems like a simple and useful improvement to me.
Do people use PowerShell for interactive use a lot?
As a Unix person my impression of PowerShell is that it’s more robust for scripting than the Unix shells, but that the Unix shells are more suitable for interactive use. And for anything of sufficient complexity and/or size I’d personally reach for either Python or I’d write a program in Rust.
I guess in the end it comes down to personal preference and what you are familiar with.
Incidentally, when I started at the university, when I was still using Windows, and PowerShell had recently come out I actually started with PowerShell and was getting comfortable with it. But we learned about Linux at the university and a friend I made at the university was showing me Linux stuff, and I started using Linux and FreeBSD instead of Windows. If it wasn’t for that then I’d probably have been a PowerShell person today.
PowerShell is underrated, but it's its own worst enemy, stubbornly insisting on LongForm-VerbNoun syntax for all but the most common commands that anyone familiar with the shell would expect. A few UI touchups and it could go substantially further, especially as MS continues quietly gutting the NT heritage out of Win10 and integrating more and more nix-like features, including full Linux kernel emulation, all so you can run Docker without a VM! What a world.
I continue to believe that within 10 years, Microsoft will have just switched entirely to Linux+WINE under the covers. :)
The long command names are really only something you use in scripts. Powershell is my main shell for both scripting and interaction and at least on my system it comes installed with tons of short aliases for common commands.
For example: Get-ChildItem was already aliased to both ls and gci on my system.
I use powershell full time and quite honestly I think it's better than bash. The main selling point for me was that I only need to learn posh and how it works vs having to learn 20 different utilities with varying UX.
The best example of this I think is ConvertFrom-Json vs something like jq. Jq's syntax is extremely difficult to learn, but with powershell I just built upon the knowledge I already had and got to use the same commands I use everywhere else.
Its totally funny (and lame) that people complain about its verbosity since its not true (verbosity is optional) and that typically shows that person wasn't involved at learning it at all and thus can be ignored.
Furthermore, there is an alias naming standard in posh, besides having all linux like names, they are usually named by first letter of verb and first and second word letter of noun (Get-ChildItem => gci; Get-Service => gsv; )
Then we have a parameter aliases, just use any unique subset of the its name ( -Computer => -C or -Co or -Com ... )
You can also customize those names with proxy cmdlets.
All in all, almost 100% of the time PowerShell sentence is way shorter then equivalent bash sentence.
Correct me if I'm wrong, but aren't exit codes an OS-level thing? That would be one hell of a redesign!
Not that I wouldn't absolutely love to have rich/structured return values, but that's already hard to do in a single-language system - even ignoring backwards compatibility, doing this in a traditional OS would require a level of cooperation I don't think the industry is capable of.
Marcel is another pipe-objects-instead-of-strings shell. It takes a different approach to shell/language unification, compared to nushell and other modern shells. Marcel exposes Python on the command line, e.g. to find files that changed in the last day:
ls -fr | select (f: now() - f.mtime < days(1))
ls pipes File objects to the select, and that's a Python function inside the parens.
Scripting is done in Python, using marcel's shell commands as functions, by importing the module marcel.api. So the examle above in Python would be:
from marcel.api import *
for file in (ls(file=True, recursive=True) |
select(lambda f: now() - f.mtime < days(1))):
print(file)
So it's the same shell command (ls ... | select ...), but expressed as Python functions, and the result is an iterator so that the command output can be used inside a for loop.
Thanks, I wasn't aware of that. I believe my comment still applies to nushell and a couple of others.
I like bash for simple commands, but hate the requirement to learn so many sublanguages for more sophisticated usage, (as in sed, awk, find, and others). I like Python for scripting, but the integration of shell commands is really not very good. I built marcel to fix both of these problems.
Nushell is the only shell I know of (other than fish) which uses threads. Threads are famously difficult in shells because of the fork/thread interaction.
How is Nushell able to use threads? For example how are subshells implemented?
Part of it could be due to using Rust as the implementation language. Rust has good, cross-platform abstractions over things like threads and processes. The language tends to make it harder to shoot yourself in the foot.
Would definitely like to hear from the authors of Nushell on how their language choice has held up over the course of the project.
A related issue is leaking fds into child processes. For example, Go locks around fork() to prevent racing with creating new fds (e.g. from pipe) [1]. Rust doesn't have any synchronization between fork and creating fds; I wonder whether/how this is addressed in nushell.
My guess it doesn't use fork, apart from spawning subprocesses use fork/exec combinations. The old fork idiom isn't exposed by Rusts standard libraries and also wouldn't be "safe" to use, since the basic expecatations of the language about how many things have access to a certain variable wouldn't hold up anymore.
One of my favorite, unexpected features of nushell so far is `$it` the implicit "iteration" variable. It makes sense to have something like this in conjunction with the 'each' command, which makes it very easy to loop over lists or tables.
But $it is still useful in the absence of 'each'.
For instance:
dirname is a useful tool but you can't pipe to it (at least not the GNU version), it expects a string parameter. We can still easily plug it into nushell pipelines though, thanks to $it, which is this case is basically turning stdin into a string.
Since dirname won't let us do
which nu | get path | dirname
we can instead do
which nu | get path | dirname $it
If I wanted to do this in bash, I'd have to go through some annoying (but common) machinations in order to convert stdin into a text string to pass to dirname.
The equivalent is called `textview` which is a built-in which tries to be a bit more intelligent than `less` with regard to file-types.
The default viewer, which sort of runs at the end of every pipeline is called `autoview`.
Now.. autoview should be calling textview in the cases where the pipeline detects a large text value. It is possible that you're not exactly running a pipeline.
For instance:
If you run:
cat big.log
it is not running a pipeline, just an external command.
If you run:
open big.log
you're invoking nushell's mechanism for creating a pipeline sourced by the contents of big.log. You should also notice that textview is invoked, because there should be a pager.
Alternatively, you can choose to create a pipeline by pipe-ing the output of cat big.log into something.
If you pipe it to textview you should see the same result:
The command that I was trying to use was 'ls', which doesn't seem to play with textview when I try it out 'ls | textview' (just no output at all). textview does work for me with files, as in your example.
reading only this post, is nushell just an implicit awk after each pipe, that already know the output format of a few common programs? or something more than that?
I looked at the book, currently it is nowhere close to powershell.
As far as i can tell no way to define any function/commands(you have to write plugins in another language, make an executable??). It supports pipeline, has a large amounts of built-in operators/commands(probably enough to be usable as a shell) and built-in parsers for a few formats(how does one write support for another data format?). Maybe in future it will address these questions.
> Looking at Nu today, you can see some common parts of languages like `if` or `open`, but it doesn’t yet feel like there’s enough syntax to build up full programs. You can’t define your own commands, your own variables, and you can’t build out a project across multiple files. We’re working to address all of these limitations so that Nu can function not only for one-liners, but also for much more.
It is quite a bit more in-depth than that.. It really is more of a structured data pipeline in a programming environment. It's more like Spark than Awk.
There are bulti-in methods like `parse` and `split`, `format` which can provide awk-like behavior. However, there are many other built-in methods which operate on tables, floats, vectors and integers.
Good point. Exit codes can be difficult. A non-zero error value may not be an error; it could indicate a type of success or be a warning or a result of a calculation or any number of things depending on the application.