Emulating Xmonad in Javascript - Part 5
Tags: dx, terminal, ansi, nomad
Published: 2020-03-03 21:47:04

---
title: Emulating Xmonad in Javascript - Part 5
published: true
description: An update on my terminal adventures
tags: dx, terminal, ansi, nomad
---

It's a whole year since I first started developing nomad! I recently made some changes that I thought were worth highlighting with a blog, so here it is!

![](https://pbs.twimg.com/media/ESI4XXRXsAIpOWy?format=jpg&name=4096x4096)

## New control sequence parsing

I decided to reimplement the logic that nomad uses to parse control sequences from program output. This meant ditching a few regex sequences that were mostly created through trial and error and replacing them with something that consumes control sequences character-by-character, checking against a list of known sequences.

Now when I say "known", I mean documented by some folks who very much appreciate the importance of this weird language known as ANSI. I copied a bunch of documentation from a great resource on these sequences that can be found here: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html

The code in question can be found here: https://github.com/lukebarnard1/nomad-term/blob/0fd7f1c8b60b6d319c0283a9d63fd6ee961495c6/ctlseqs.js

Essentially what it does is it takes a bunch of templates that look a bit like the documentation in the above resource:

```
CSI Pm m
```

and creates a function that will match a given input string to this particular sequence if the string is a _prefix_ of it.

I opted to not optimise this code too much so that I could focus on being confident that the matches were valid and that the outputs were restricted. After all, sending all of your program output through one program should require a high level of scrutiny.

There are definitely some more optimisations to be made here - for example, most sequences start with a CSI (Control Sequence Initiator) of `ESC[` followed by a sequence of digits and semi-colons. One potential optimisation here could be to consume a series of characters matching `[0-9;]` without even testing against any individual sequences. I'll be making these optimisations soon!

Changing the parsing of control sequences also meant changing the internal representation of them, which required changes to the (sub)terminal implementation itself. The integration tests I had written were fairly useful but it turns out they may have recorded an incorrect snapshot before, so the actual output wasn't totally useful...

I still haven't gotten around to writing my dream unit tests of "start with an empty terminal, following these control sequences expect state to have updated in this way". I'll get around to do it! I think this would be a great candidate for some test-driven development of more separate updating of different terminal state.

Let's just say there's a lot of work left over for a rainy day.

## New help screen

I showed nomad to my boss and he let me know that when he run nomad, it was "blocked". When he showed me what he meant it was clear that nomad was doing a poor job at giving the user an idea of how to control it! So I decided to make the controls a lot more accessible.

![Nomad's little help dialog](https://dev-to-uploads.s3.amazonaws.com/i/rhzjeujdejfktmkkfu8i.png)

![Nomad's big help dialog](https://dev-to-uploads.s3.amazonaws.com/i/pishv7pwuysnokrjsdf5.png)

So there it is, a preview of the help box that follows you around when using nomad.

## Try it!!

You got this far, why not [try nomad out](https://github.com/lukebarnard1/nomad-term)! Bear in mind that all of everything you type goes through nomad and everything a program sends to stdout also goes through nomad and is stored in memory. This is true of your _actual_ terminal (e.g. `gnome-terminal`, `Terminal.app` etc.) but they're used by the whole world.

The repo is here: https://github.com/lukebarnard1/nomad-term :)