There's a lot of cool things i feel like terminals and/or shells could do.
I think i've read about nushell before, but never bothered to try it out. I rediscovered it today and there's a lot of good stuff there. I think i also saw warp terminal a while back, and thought "why is every other terminal window just a text grid, we can do so much more".
So here's some stuff i've been thinking about:
- if a command output gets really long, it would be nice if it made itself a little scrollable window, instead of making the commands you typed before that end up way further up, or worse, past the scrollback limit. searching within that output is an obvious feature, and maybe filtering by what's stdout and stderr.
- nushell has structured data, instead of everything being a string. this is
very nice. i misunderstood an example on their page, and thought it was
possible to open a sub-field of data in a text-editor and manipulate it
directly. so that would be kinda cool
- relatedly, i see the
explore
command (which is like a table pager) has a keyboard shortcut for transposing a table. it can also pipe the current data into a nushell command. it would be cool if you could also edit/add/delete data here, and export it further (like to a variable in your current context) - something i'm also thinking about is: do we really need pagers? what if the output of a command just came out as normal, maybe with a scrollable box if it gets too long, and then you can just click it (or some other kb-only option too) to expand and read through. i guess the terminal sort of becomes a pager in this situation
- relatedly, i see the
- what if prompts weren't just text, but clickable/interactable
- like clicking the git branch symbol opening a dropdown where you can just switch to a new branch like that.
- or a transient prompt that doesn't just completely disappear when the previous command finishes, but allows you to go back up to it and inspect the data again. like how long the command took to run, or its exit status
- maybe hovering or holding some key could expand info. like by default it shows git branch, and then hovering expands it to also show changes or stashes or whatever
- what if they animated. like the git module sliding out when you cd into a git repo
- i was toying with the idea of having a shell/terminal in one, but after more thinking i don't really think it's the best idea. you could rather have a shell and terminal that talk to eachother with ansi escape codes or something, and then the shell could still do cool stuff even in a different terminal. but the terminal could provide support for stuff like "make a scrollable textbox" or "display a table", and the shell could use this if available, and fall back to making an ascii-art table or whatever if it's in a different terminal.
- when running a long pipeline, it can be hard to know exactly what happened,
since you can't see the intermediate values. it would be cool if, after the
pipeline is done, you could see the values at every intermediate step. and
there could be a summary of what actually happened. like if you did (nushell
syntax)
ls | cp $in.0.name newfile.txt
, there could be a way to access a summary that tells you thatcp
successfully copiedmyfile.txt
intonewfile.txt
.
shower thoughts time
okay, so what should actually be the responsibility of the shell, and what should be the responsibility of the terminal? shells are usually responsible for making the prompts, including styling, content, functionality, etc. I believe this is not the case in warp. there's an option to either use the shell's builtin prompt, or it lets you make your own which is rendered by warp itself.
what about warp's "blocks"? in warp's case, it's the terminal. well, basically any feature warp has is done by the terminal, because warp is the terminal, and you just plug your existing shell in there. but in this utopian future we're imagining, whose responsibility is it to make these blocks? you could argue it's the shell, because that's what controls when commands are run, so it can say to start a new block when a command finishes, for example. on the other hand, the blocks are a part of the terminal's ui. i could maybe see the shell's job becoming very complicated if it has to manage all this UI state, and communicate with the terminal about what to do with it. a lot easier for the shell to say "command's done" and "command's about to be executed", which is how warp works, as far as i've understood. though, i guess programs like tmux already manage all their own ui state, so maybe it's not so farfetched to ask a shell to do the same. i think i'm personally leaning in the direction of it being the shell's responsibility to render these blocks, and you'd configure your shell's options if you wanted the blocks to spawn bottom-to-top instead of top-to-bottom, for example.
so, the terminal basically becomes this blank canvas for the shell to do its thing with (like it always has been), except the shell has a lot more flexibility in what it can ask the terminal to render, instead of just plain text.
next question, what should that be? you'd want to support a couple different things. blocks, prompts, data structure visualizations (like nushell's tables, for example). the terminal would send events to the shell if you click on a prompt segment, allowing the shell to maybe render a popup-menu where you can do something useful, like change git branch. you'd also want the flexibility to make a little search box in the popup. should this be a primitive too? if not, you don't want it to be too complex either i think, because then the shell has to send over a lot of data, and the terminal has to interpret it and render it per the shell's instructions. you probably want to be somewhere inbetween "i'm running a command now, you go figure what you wanna do with that" (warp's current model) and "draw a quad here, then render this text here, then draw another quad, then …". i guess current normal terminals are quite close to the latter, where shells just say "render this text", sprinkled with some ansi escape codes for colors and cursor management. or maybe this is not a spectrum, but two distinct possibilities, and the actual spectrum is how "advanced" the render interface is, where text is the least advanced and raw render calls are the most advanced. and you wanna find a sweet spot inbetween there.
get your pitchforks ready
...what if it was javascript. "hey artemis, what the fuck", you might say. and i hear you, and i agree. but it's also something that like, exists. it's probably not the answer in the long run, but i feel like it could be a good starting point, letting you (me) focus on prototyping a neat shell. here's the pitch:
- the terminal is a tauri app (this is already what i started with a couple days ago, when i tried to prototype a terminal+shell in one)
- it starts off with a very empty html document, and spawns the shell process
- the document contains an event listener, which listens for keypresses and sends them along to the shell.
- the shell receives these keypresses, and is able to send javascript commands back to the terminal, which executes them, populating the document. (also practical i think, because i think i saw that tauri had a way to just run js code from rust. it's so easy! the world loves me)
the shell would probably start off with appending a prompt element to the empty document, and then a box for text to go in. when it receives a keypress, it adds that character to the end of that box. when it receives an enter press, it makes a new scrollable element which it dumps stdout and stderr of the process into, as well as sending further keypresses onwards to the running process's stdin. when the process exits, it makes a new prompt element and box, and prepares to get more user input.
cons?:
- this puts text management (selections, cursor movement, copy+paste) completely in the hands of the shell. i do believe this is mostly the case already anyway, so maybe that's fine. or maybe we want to be on the other side (which i think warp sits in currently), where the terminal is responsible for text editing, and just sends the whole command to the shell when it's ready. this also means that warp is responsible for syntax highlighting and autocompletions. but this is something i feel should be the shell's responsibility.
pros: i can prototype this without inventing a whole protocol for shell<->terminal communication