Category: Software

Why Nushell?

We can do better than POSIX

I work on a command-line shell called Nushell (Nu for short) with some internet friends, and I think it’s pretty cool. To convince you that it’s cool (or at least worth a try), here’s a whirlwind tour.

Basic Querying

Let’s start by taking a look around the filesystem. We’ll use ls to take a look at the files in /usr/bin:

Windows UI in 2022

Things are weird.

Like many other people, I unexpectedly found myself stuck at home without much to do in early 2020. To stay sane, I set about answering a question I’d had for a while: what’s the deal with native GUI frameworks on Windows these days?

It’s rarely obvious which of Microsoft’s several supported technologies is the best choice for a new project, and Windows doesn’t have the same culture of idiomatic+consistent native GUIs as macOS. After months of obsessive escapism focus I emerged with a decent understanding of the problem space; let’s start with an overview of the technologies in use today:

Win32

This is kind of a catch-all term for the old-school way to build a Windows application using arcane, less-than-ergonomic C APIs. This is unpleasant and your application will look ugly, but one big advantage is that the Win32 APIs will live forever and they underpin all the other UI frameworks.

It’s well worth your time to learn a bit of this (read Charles Petzold’s book ), but it’s rare to see people building pure-Win32 GUIs these days.

Say you want to host some files in an S3 bucket, under your own custom subdomain with nice short HTTPS URLs. For example, you own foo.com and you want files to be accessible at URLs like https://files.foo.com/bar.txt.

This is a lot more complex than it should be! It involves configuring 3 separate AWS services and I’m already forgetting the boring details, so let’s write them down for future reference.

cloud
Cloud is the future… wait, 3 separate AWS services?
Reilly
YEP.
expressionless

Creating the S3 bucket

Naming is important here - the S3 bucket must have the same name as the subdomain it will be accessed at. Open up S3 in the AWS console, and:

  1. Create a new bucket named files.foo.com.
  2. Disable “Block all public access”.
  3. Under the bucket’s Permissions tab, add a bucket policy to make all objects public by default (replace files.foo.com with the name of your bucket):
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AddPerm",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::files.foo.com/*"
        }
    ]
}

Certificate Creation+Config

Next up, we need to create a certificate in AWS Certificate Manager.

Hot Tip
Certificates must be created in the us-east-1 region to work properly with CloudFront. Learn from my mistake, make sure you’re in the right region when performing this step.

Recent Nushell/Rust Work

SQLite, file watcher, windows-rs

I’ve joined the Nushell core team. This doesn’t really change what I’m doing day-to-day, but it makes my work on Nu feel a little more official 🙂.

SQLite Support

This is the biggest feature I’ve implemented so far:

I’m pretty proud of how this turned out; it’s very convenient to be able to browse SQLite databases in your shell and interact with them the same way you would any other data source. Nu is often-but-not-always smart enough to avoid unnecessary work when loading things from the database; there’s still some work to do here and it will probably involve rearchitecting how Nushell queries data.

File watcher

I also implemented a watch command that runs arbitrary Nu code in response to file changes. Nothing groundbreaking, but I find myself needing this kind of low-key automation all the time: run tests when code changes, restart a development server, log changes in a directory, etc. I think the ability to respond to file changes should be a more widely available primitive, and now it is.

Rust for Windows

Against all odds, I somehow got sucked back into Windows development. I spent a solid week helping one of Nushell’s dependencies do a big upgrade of their Windows functionality. This required a deep dive into the current state of calling Windows APIs from Rust, and… it’s a mixed bag.

I used the windows crate which is maintained by Microsoft. It’s an automatically generated set of Rust bindings for Windows APIs, which is both good (very comprehensive, always kept up to date) and bad (some rough edges that might be solved in a handmade solution like winapi). The crate is actively being worked on and it frequently has breaking changes; this means documentation is a little scarce and often out of date. Overall I was impressed and I think the crate has a bright future . But until it settles down a bit, expect some growing pains.

I’ve been using Rust full time for the last month and a bit while contributing to Nushell (more on that later). A lot has changed since I first tried Rust in 2019 and this is my first time working on a big Rust project. Here are some thoughts on the language while they’re still fresh in my head.

Compile times and feedback loops

Rust’s compile times are notoriously slow. Rust development was slow enough on my laptop that I finally gave up on mobile computing and bought a desktop with a top-of-the line CPU (12900K). Along the way I switched from Windows to Linux (more on that later) and started using the mold linker, and now… things are OK!

I’m able to do incremental builds of Nushell (a huge project) in a second or 2, and a full debug build takes 25s. For smaller projects, incremental builds are nearly instant. There’s certainly room to improve here, and the development experience is not great on average hardware, but… this works for me.

Another thing to consider is that the typical Rust feedback loop is tighter than you might expect from the slow compile times. The Rust compiler catches a lot of bugs before a full build needs to happen, and that reduces the need to do a full build and try things out.

Complexity + monotony

Rust is not a simple language. In total I’ve spent nearly 3 months working mostly in Rust, and the language still has a lot of corners that I don’t have a solid grasp on. To improve on this I’m going to need to branch out from Nushell and write a lot of little tools for myself.

Despite the complexity, I’ve found that writing Rust is sometimes a bit… braindead? The type system is very expressive and the compiler catches a ton of errors, so I spend 25% of my time thinking real hard and 75% painting by numbers to make the compiler happy. I can’t quite decide how I feel about this style of development, it can be a little tedious but it also makes for a better end product.

I (sometimes) want a higher-level Rust

Rust has a lot of great things going for it; the tooling, community, package ecosystem, compiler, and syntax are all fantastic. But the focus on systems programming does mean that Rust isn’t quite as ergonomic as it could be for many use cases.

Sometimes I just want a garbage collector! Sometimes I’d be perfectly happy for Rust to implicitly allocate memory if it makes my code work (for example: converting from a &str to a String)! I don’t know if that will ever be possible in standard Rust, but… maybe there’s room for a Rust variant intended for higher-level use cases.

On the other hand, the ability to go as low as you want is great. It’s nice to work in a language with a very “high ceiling”; no matter where your Rust project goes, you won’t have to switch to C or C++.

headshot

Cities & Code

Top Categories

View all categories