Ignore URLs and Acroynms While Spell-checking Vim

Today’s post is a short one that I have incorporated into Writing With Vim and will publish when I add a few more changes.

When Vim’s spell check is enabled, words that are not known to be good are highlighted as incorrect. This is the behavior that we want generally. However, there are certain types of text that are commonly marked as incorrect, and it can be tedious or impossible to constantly add them to your dictionary.

One example would be URLs. These are marked as incorrect by Vim by default, but it would be nice to just tell Vim to ignore them from the spell check so you can navigate spelling errors more quickly and to reduce the amount of noise on the screen. You can accomplish this with:

 " Don't mark URL-like things as spelling errors
 syn match UrlNoSpell '\w\+:\/\/[^[:space:]]\+' contains=@NoSpell

Here, we are defining a new syntax highlighting group called UrlNoSpell (could be called whatever you want), and when text matches the pattern, we mark it with the special highlight group called @NoSpell.

The pattern says to skip checking the spelling of any string which has word characters ([a-zA-Z0-9]) before a :// until a space character is encountered. So any string starting with http://, https://, ftp://, or even anything:// would qualify as a match. There may be things that aren’t true URLs that are matched with this pattern, but it should cover most cases and lead to few false negatives.

When I looked through my spellfile, I saw many acronyms or abbreviations. Things like “AWS”, “B2B”, “CEOs”, “HL7”, “MP3”, “PDF”, and so forth. I removed all of these from the spellfile with the following command:

 " Don't count acronyms / abbreviations as spelling errors
 " (all upper-case letters, at least three characters)
 " Also will not count acronym with 's' at the end a spelling error
 " Also will not count numbers that are part of this
 " Recognizes the following as correct:
 syn match AcronymNoSpell '\<\(\u\|\d\)\{3,}s\?\>' contains=@NoSpell

This function works similarly to the previous one, except the pattern is different. The pattern says: if we have an entire word composed of three or more characters that are all either uppercase letters or digits, possibly followed by “s” (as in “CEOs”), then mark this word as good. Again, while this could lead to false negatives (“ZARBLATZZZZ” is marked as good, for instance), it might be something to consider for your spell function.

I recommend adding these to your writing function and they will be enabled whenever you are in a writing mood.

Running Old Programs In The Browser

I did my first programming in Applesoft BASIC on the Apple IIc, and then I did quite a bit in middle school and early high school in QBasic on a 486 machine.

I’ve been in a bit of an archival kick lately. I recently started a small project of getting some data off of my Apple IIc disks, which is going well. I thought: maybe there is a way to get my old QBasic programs running as well.

QBasic ran under MS-DOS, the command-line interface of pre-Windows and early Windows computers. You can see a more modern version by typing cmd at the Windows program. I wanted to get a way that I could look at my old programs and to preserve and distribute them to others.

I looked around for a QBasic emulator, and except for the well-known and battle-tested DOSBox DOS emulator, could only find a partially-completed QBasic interpreter written in JavaScript. It didn’t have graphics mode, and many of the programs that I wrote used this.

Archive.org has a huge collection of DOS games. This is great for preserving old software. You can even play old games, although any game saves won’t persist between page reloads1. The DOS collection runs on em-dosbox, which compiles the DOSBox DOS emulator from C++ to Javascript using emscripten. Fortunately, all of this is open source.

I was able to get a copy of the QBasic executable and program by digging through archive.org’s copy of the Microsoft website, extracting a self-inflating executable in a Windows virtual machine, then copying that file over to my Mac. Then I could copy my files in the right hierarchy and run a command to compile a directory with of the executable and BASIC programs to something that could be run in the browser.

If you want to mess around with the programs right now, you can skip to the bottom of the post.

The tree structure that I had looked roughly like:

...
├── src
│   ├── dosbox.html
│   ├── dosbox.html.mem
│   ├── dosbox.js
│   ├── myqb
│   │   ├── QBASIC
│   │   │   ├── BASIC
│   │   │   │   ├── ...
│   │   │   ├── ...
│   │   ├── QBASIC.HLP
│   │   ├── qbasic.data
│   │   ├── qbasic.exe
│   │   └── qbasic.html
│   ├── packager.py
│   ├── qbasic.data
│   ├── qbasic.html
│   └── ...
├── ...

The command to compile it was:

$ ./packager.py qbasic myqb qbasic.exe

The second argument specifies where all of the files are (where C:\ is mounted). The last argument is which executable to run when DOSBox starts up. The first argument is the name of the .html and associated .data file that will be generated.

You need to copy the following files to be able to host it standalone:

  • dosbox.html.mem
  • dosbox.js
  • qbasic.data (or whatever your .data file is called)
  • qbasic.html (or whatever your .html file is called)

The files in, say, myqb, aren’t actually needed since they are compiled to the .data file when you run the packager program.

The programs

The QBasic programs are located here.

The DOSBox emulator will load when you go to that page and immediately run QBasic. To load a program, File, Open and navigate under the QBASIC directory. (Yes, the files back then needed to be in 8.3 format.) Under each folder is a set of programs and related assets.

There are a couple of potential issues with running the programs.

One is that some of the programs relied on me pressing Ctrl + Break and most keyboards today don’t have the Break key. Plus, I think there are some issues with how DOSBox handles the Ctrl+Break combo normally, which is likely only exacerbated when running inside of a browser.

The other is that I originally had them in different places on my drives (hard and floppy) so the paths to certain assets might not be hooked up entirely correctly. But at least it is up there in some form.

Parting thoughts

If you would have asked me if I would be running programs that used all of the resources of the computer at the time in the web browser of a future computer, I’m not sure that I would have believed you. But, if exponential increases in hardware efficiency continue, the things that are most taxing today might be trivial in the future. Everything you are currently running on your computer might be emulated in a chat client in the future. :)

I may write up some of the programs in an index up there, but it might be a while before I get to it. Until then, feel free to poke around!


  1. There is an open issue related to the ability to persist disk changes between page reloads. 

Deciding From Multiple Open-Source Alternatives

In a Slack organization that I am a part of, someone asked:

Has anyone ever heard of anything that takes Github repos and assigns them some sort of “reliability score”? Something that takes stars, commit frequency, PRs, open/closed issue ratio, issue closing time, etc. into account and gives them a score? It would be really nice for choosing between two or three repos that do similar things.

I had some thoughts on this since it is something that I have done in the past, and took them and extended for this post.

Existing alternatives

The Ruby Toolbox tries to give a rough score for ruby gems based on the features above, and it gets most of the way there. It provides a good overview for classes of gems to get a sense of how well maintained they are. Usually when I am trying to find a gem that does something, I start here. Over time you get a sense of a language’s ecosystem and this is less valuable, but it is still useful for finding new gems that might do that thing better.

Personal heuristics

I usually look at some combination of the following to determine whether a package or library is worth using:

  • Does it purport to do what I need done?
  • Does it have documentation?
  • How many people have starred / forked the repo?
  • How many issues are outstanding?
  • Are there many open / ignored pull requests
  • Does it have tests?
  • Who is the maintainer of the library?

It doesn’t need to score highly on every metric, but more positive signals generally make me more confident in the decision.

More general considerations

To me, choosing an open source library comes down to cost of change. If it would take only a few hours to switch to the other library if one of them proves to be unmaintained or unsuited for the task at hand, then I would just pick one and proceed with implementing it. If it is something that would be very expensive (in terms of time or money), then it is a decision that should be considered more closely.

For example, the other day we tried a library on Github that didn’t have any stars. It seemed like it might get the job done and it was for a minor piece of functionality. Something that was more critical might demand a closer look.

If I am worried about committing to one over the other I sometimes try to build an adapter layer to be able to change which library we use seamlessly. Basically taking a bit of time to increase optionality in the future, with a bit of last responsible moment thrown in there as well. If you defer the decision on what database to use and build an adapter layer, you can switch databases much more easily in the future. There are some similar thoughts at:

Another approach is to try a spike of both and then using the knowledge that you gain to make a decision. So if you learn that one is easier to work with or fits your domain better or is faster, then you can use that knowledge. Also, you buy yourself hours or days of additional information to watch the activity on the repo. Then at worst you have one working implementation if you did it in serial and were happy after the first one, or two if you were unhappy or did them in parallel.

Similarly, Martin Fowler writes:

…one of the main source of complexity is the irreversibility of decisions. If you can easily change your decisions, this means it’s less important to get them right - which makes your life much simpler. The consequence for evolutionary design is that designers need to think about how they can avoid irreversibility in their decisions. Rather than trying to get the right decision now, look for a way to either put off the decision until later (when you’ll have more information) or make the decision in such a way that you’ll be able to reverse it later on without too much difficulty.

What this implies for my projects

Of course, the implication for any open source projects that I maintain is that to provide the most value to others, they should clearly state what the project’s function is. They should be documented, and the issues and pull requests should be reasonably gardened. And so forth.

Mac Karabiner Key Remaps I Use

Karabiner (formerly KeyRemap4MacBook) is a tool that lets you remap certain keys on your keyboard. I find this useful as a developer and someone who writes words in a few ways.

Mega Fast Key Repeats

When I pair with someone for the first time or give a presentation, they usually ask “how are you moving the cursor so fast?” I use Karabiner to crank up the cursor speed. This is most useful for navigating quickly between letters, words, and sentences. Also, it’s useful for quickly killing characters. At first the cursor seems to be flying around, but soon you gain control and can’t imagine working another way.

My current settings (see the “Key Repeat” tab) are for a “delay until repeat” of 250 milliseconds and a “key repeat” of 10 milliseconds. Any shorter of delay until repeat causes me to add extra chaarractersss when I don’t intend to do so. Similarly, 10 milliseconds of key repeat allows me to be pretty precise in cursor placement without sacrificing nearly top speed.

Try it for a week and I’d bet that you won’t go back to slow repeats.

Caps Lock -> Escape

I wrote about remapping caps lock to escape a long time ago, and my thoughts on it have not changed much. If anything, my muscle memory has made it more indispensable. The Macbook keyboard already has a control and alt on the left side, so I’m not sure why you would remap caps lock to those.

The current best way to remap it is to use Karabiner, which has it as an option (just search “caps”.) It works everywhere flawlessly, so there is not much more to say.

Emacs / Readline Shortcuts

Emacs and readline (bash, zsh, etc.) use an interesting set of meta (alt) and control commands to help you navigate around. You probably already use some of the built-in keyboard shortcuts for editing text. For example:

  • Ctrl+a to move to the beginning of the current line
  • Ctrl+e to move to the end of the current line
  • Ctrl+k to kill to the end of the line without copying to clipboard
  • Ctrl+b to move one character backward
  • Ctrl+f to move one character forward
  • Alt+backspace to delete word backward

If you’re a command-line or Emacs junkie, you might want more power or consistency. Plus, by making the behavior system-wide,you’ll make those muscle memories stronger. There are some Karabiner settings that emulate these behaviors:

  • Alt+b to move to previous word
  • Alt+f to move to next word
  • Alt+d to delete word forward
  • Ctrl+d to delete character forward
  • Ctrl+u to delete to the beginning of the line (copying to clipboard if you want)

You can also change Ctrl+k to copy the contents you killed to the clipboard. There are a ton of other Emacs commands but I don’t use it heavily enough to want to use these bindings. Some of the alt command remaps will overwrite the default Mac insertions (Alt+f usually inserts the “ƒ” character, for example), but I don’t use them often enough to justify keeping them around.

To find these settings, look under the “Emacs Mode” section of the main “Change Key” tab. I was digging around and saw this, and it has made me much more effective at moving around.

I primarily use Vim for writing other prose so it doesn’t help there, but I write a non-trivial amount of words in Slack and email. After making these changes I find that my editing speed in those programs is much faster and more intuitive. Also my readline editing speed and accuracy are up as well.

Hope this helped!

Hope this post helped you squeeze a little more power out of your keyboard. I’d love to hear any keyboard hacks you use that you get value out of. Leave a comment!

For Higher Productivity, Call Your Shots

There is a famous 1932 World Series game that legendary baseball player Babe Ruth played in. In the game, he may or may not have pointed to the bleachers before hitting a critical home run, which intrigues fans to this day. There’s something compelling about the idea of calling your shot, or saying what you are going to do and then doing it.

Picture of Babe Ruth

Calling your shots

My productivity advice is to call your shots every day you sit down to work.

At the beginning of each day, publicly state what you’re going to accomplish, and then update the list throughout the day. Make a list of the three or so most important things you are going to accomplish. If they aren’t important, why are you doing them? Ideally, you can tie these back to company or team objectives.

Here’s an example of what I might set out to do during a day. I usually post this to Slack in an appropriate channel, but you can use the best communication method for your team:

2016-02-02

[√] Fix forward-progress onboarding issue when there is a 500
[√] Sign up for Salesforce backups { OKR: Salesforce }
[√] Work with KP to test out a Salesforce email sending to Mandrill test environment

Blockers: need help figuring out why the PDFs are not generating and updated TOS/ROI at on some Salesforce accounts.

Headed to the Indy Vim meetup tonight, where I’ll be presenting on “using text objects and surround.vim effectively”.

I try to update the task list throughout the day for:

  • new work that I didn’t expect to take on
  • things that I decided were not as important as I thought they were
  • tasks other team members took on

When you get to the end of the day, I reflect on why I did or did not hit the goals that I set. If I hit my goals, I usually feel pretty satisfied with the effort that I put in. I’ll evaluate if I set the bar too low, and adjust accordingly the next day.

There could be many reasons that I miss goals. Maybe I was busy with other things. Maybe the tasks were harder than expected. It could be that the tasks were too easy, and were not enough of a challenge. I could have been prone to distractions. The tasks could have been poorly defined. I could have gotten too focused on one of the tasks and neglected the others. Whatever the issue, I try to address the root cause so it doesn’t hinder me again.

Throughout the day and at the end of the day, I update what I have done. I try to mark when tasks are related to a company or team objective (OKR) so that it’s more clear what it relates to or what the value is.

Why is this useful?

For me, the largest benefit is accountability. Did I set out to do meaningful tasks, and did I do them?

I find that the days where I am fuzzy on what I am going to do are the least productive. I can mentally justify any level of achievement when I haven’t written down what I want to do before the day begins. The day fritters away, and while I like to say that it was unavoidable, it was likely under my control. Most people are not going to call you out when you’ve had an off day, so it is your responsibility to try to communicate expectations to hold yourself accountable.

Focusing on just a handful of things greatly improves my concentration. When everything is a priority, nothing is. By creating a short list at the beginning of the day and trying to get those things done first, I reduce the amount of time wasted figuring out what to work on next.

Another benefit of this approach is broadcasting to your team what you are planning on doing. There will be less stepping on toes. You might get input from a team member before you work on it that there is some prior work or thinking on this tasks, or that they have shifted in priority.

If the whole team does this at the beginning of their days, your team can have asynchronous and remote standups instead of needing to be in the same room at the same time. It fosters a greater sense of accountability and understanding what everyone is working on.

Selfishly, calling your shots and hitting them is a great way to build your reputation as someone who gets meaningful things done on a regular cadence. People will trust that you will do what you say you will do. Sometimes it is difficult to understand what the people you work with are doing. By broadcasting what you are getting done, you make it easier for others to understand and give you credit for the things that you do.

Meetings are not accomplishments

Meetings are not accomplishments, but they might affect how many things I accomplish. I don’t list them on my daily update, but I take them into account when forecasting for the day. At this point in my career at least, I’d rather focus on output over sitting in a room. There are often more productive ways to make decisions than having meetings. (Thanks to Jim Brown for hammering on this idea when we worked together at Haven.)

Modifications

It takes time to consider what you will realistically get done each day and communicate it to your team. You may decide do this planning the night before instead of first thing in the morning to save time. I find that this helps me get excited about the tasks that I set out to achieve, to think about them while heading into work, and that I more often hit the ground running when I start.

If you haven’t done this much or are early in your career, you might not be calibrated. Keep practicing and I can assure you that you will get better at it. You might choose to do this in private for a little while, but I recommend posting it after the first few times to try to get more accountability. Your estimates will improve when you write them down to “commit” to them.

While you might miss your targets a little, by continuing to strive to plan and accomplish a few key items per day, you will have far greater total output. Instead of having monthly or weekly feedback loops, we shorten it to a day.