Vi Daily Driver

Motivation

It would be really cool to have Neovim work like Foam and get away from VSCode. I was partially inspired by Cool desktops don’t change 😎. The article worried me about the collapse of Atom and what that might mean for VSCode.

Caveats

I used Neovim and it is aliased to vi on my system. I’m not confusing the various projects (Neovim, Vim, vi, ed). vi is just very satisfying to type.

Status

Partial success. I have learned a lot about Neovim during this configuration process. I’ve also learned a lot about myself and what I value (as I’m getting older). There is a ton of setup required to get a Neovim installation to be ergonomic. I just wasn’t that interested in all that work this time.

I found manipulating Neovim’s configuration files to be very challenging. I was building the airplane while flying it and I had to reload configurations very frequently. That’s not to say that I wasn’t able to accomplish that, but it never even started to feel organic in the scope of this 2 week project. I became more proficient with vim-style navigation for plaintext, but navigating code always seemed to have sharp edges.

I think learning Neovim is an unemployment project. I find the burden of wrestling with my text editor too much when I just want to get work done. Not that it wouldn’t be valuable to learn, just that I’m already learning other stuff daily.

Wins

Neovim works really well for editing files quickly.
I noticed this specifically when editing some Terraform today. rg for the thing I know exists in the codebase, vi said file, / to that line, 3yyP, :%s/existingUser/newUser/g, :wq!, tf apply. Done. I’m out of the file and on my way.

Neovim feels better on the laptop.
The keys are easier to reach and the trackpad/touchpoint are really not nice to use.

Search and replace is the best.
VSCode has excellent functionality here, but it’s not as good as Neovim. It is succinct and easily scoped to the whole file or selections.

Losses

Refamiliarizing myself with a codebase that I haven’t touched in a while.
I know that the .circleci/config.yaml file has a reference to the script, but now I need to learn how to use Neovim both to navigate to that file, and search the codebase for calls to that file. Yes, I could spend the time to learn those two things and I would be better off for it, but I was tired of fighting the editor in that moment. Not to say that VSCode has a good tool for this, but rg and fd on the command line result in clickable links that open the necessary files in tabs in VSCode.

VSCode feels better at my workstation.
I have a great mouse and keyboard that I’ve found over years of selection (20+ mechanical keyboards and 5+ ‘gaming’ mice to result in using the same two for the last 5 years. I think I got to the end.). Typing is fun. Clicking on videos is fun. I don’t really get ’no distractions, never leave the home row’ thing anymore.

I find it challenging to remember what a given plugin gives me.
I don’t think this is a problem unique to Neovim, but I have to admit that the VSCode marketplace makes remembering the value proposition of a given extension much easier. You can just jump to the marketplace page and now you’re looking at the readme on GitHub (readme quality cannot be counted against VSCode). I suppose I have to just take better notes about what a given plugin accomplishes.

With VSCode I can have two tabs open side-by-side, and drag code from one in to the other.
In Neovim, that operation looks like this ;;[find file]<CR><C-w><C-w>[find file]<C-v>/code<S-v>jjjjjjd<C-w><C-w>/placeP. Admittedly, I’m probably not doing that in the best way, but there is still a learning barrier there. I guess you really need the muscle memory.

Requirements

For this project, I made a list of requirements that I wanted to accomplish with Neovim. I think this list is the most valuable thing to come out of the project. I’ve isolated all the things I want in a daily-drive text editor just by virtue of having the blank canvas of Neovim. I’m pretty tired of working on the configuration now, but if I get the bug again in the future, I can start with this. Even better, I can write my own tools to solve these things on the command line and never touch a text editor…

  • Learning the Keybindings

    • I don’t think you can every really check this one off…
  • Repeatable Installation

    • The key to this was starting from scratch. I wanted a blank canvas that I could fill with plugins and keep track of why I was including them in this installation.
    • packer.nvim seems to be the Neovim package manager of choice.
    • I had issues with the AUR package, so I went with the clone method in the documentation.
    • I had some confusion as to what to put in my ~/.config/nvim/init.lua file. This was the document that worked for me.
    • I was able to do the installation on Arch and Mac with relative ease after that.
  • Mac / Linux compatibility

    • This was surprisingly easy, the only hurdle was fzf, but I was able to solve that.
  • Plugin Selection

    • I started with this list list.
    • This is a good resource to start with, but I think that it was challenging to pick things that I wanted to use out of the list.
    • I found that emulating features that I wanted was an easier way to wrap my head around what needed to be installed.
  • Automatic tables

    • I have not completed this, but godlygeek/tabular seems like a good candidate to solve this issue.
  • Foam Features

    • I found zk which enables many of the features in Foam that I care about.
      • Tag explorer
        • ;zt
      • New file with front matter
        • ;zn
        • Sentence Case Title converted to kebab-case-title.md on creation of file.
      • Back/link Explorer
        • ;zb & ;zl
    • Links
      • This was the big deal breaker for me. Foam has the ability to automatically generate Markdown-compatible link references when you use [[wikilink-style-links]].
      • I could not find that functionality anywhere in the Neo/vim ecosystem.
  • Fenced code block syntax highlighting

    • This is accomplished with vim-markdown, I believe.

      this: that
      other: something
      mine:
        - yours
      
      {
        "key": 3
      }
      
      import "fmt"
      
      func mine()(err error){
        return nil
      }
      
  • File navigation

    • Reorganization
    • These are accomplished with kyazdani42/nvim-tree.lua.
    • ;; is mapped to display the navigator.
    • Notably, Foam is capable of rewriting Markdown-compatibility links on file save. You can move files around and Foam takes care of updating the relative links in the background. This is an absolute killer feature for me because it reduces the mental burden of linking documents, which is the key to a successful Zettelkasten.
    • I had to turn on set splitright and set splitbelow to get the windows to appear in a sensible place.
  • Markdown preview

    • There are many tools available for this, but the really cool one is using my pan script to generate the HTML version of the current file and open it in the browser.
    • I mapped that operation to <Leader>h.
    • That’s a big win for Neovim, I didn’t have to muck around with Javascript to get that done.
    • This answer really helped me.
  • Markdown Lint

    • I found a helpful article on the subject.
    • Also, a crazy resource in lyz-code.
    • Accomplished with mfussenegger/nvim-lint and npm install -g markdownlint-cli. (markdownlint-cli package in NPM).
    • I’m not the biggest fan of this pattern, but I can’t count it against Neovim because VSCode is JS all the way down.
    • I’m not really sure how to get it to respect .markdownlint.json files in the directory hierarchy like VSCode does.
  • Insert Date String

    • That’s a fun one <Leader>i maps to \"=strftime(\"%FT%T%z\")<CR>PA<CR><Esc>.
  • Automatically Wrap Selection with Markdown link and Clipboard Contents

    • I didn’t inspect the clipboard, but I did write some bindings to wrap a word or selection with a Markdown link and the contents of the clipboard.
    • If over a word, wrap the word with the clipboard contents: <Leader>l.
    • Visually select an area and link that: <Leader>l (also).
  • Automatic Markdown Bullets and Indentation Keybindings

    • This is accomplished with dkarter/bullets.vim.
    • C-t to indent in insert mode.
    • C-d to outdent in insert mode.
  • Paste an image from the clipboard

    • Accomplished with ekickx/clipboard-image.nvim.
    • <Leader>p with an image on the clipboard.
    • I’m pretty impressed that this worked, it would have been a deal-breaker feature for me if I couldn’t find a solution.
  • Spelling

    • lewis6991/spellsitter.nvim
    • This works but I’m not particularly happy with it. Navigating to spelling mistakes feels clunky, and the detection catches things like T22 in timestamps like: 2022-06-28T22:17:46-07:00
    • You can find the next error with ]s and fix it from a list with z= or add it to the custom dictionary with zg.
    • Composing those commands, [s1z= lets you: “Search for the previous spelling mistake, and correct it with the first in the list of possible corrections.”
    • The words are added to ~/.config/nvim/spell/en.utf-8.add and it is pretty easy to port over the custom dictionary that I set up for VSCode.
    • I don’t think that you can ‘ignore’ words like you can with VSCode. I would like a separate list of ignored words that do not collude my actual custom dictionary.
  • Colors

    • marko-cerovac/material.nvim is the color theme I chose.
    • nvim-lualine/lualine.nvim is the status line that looks good and comes with its own colors.
    • Each of these have theme choices and seem to be nice and easy to configure with Neovim.
    • I don’t want to dick around too much with color configurations.
    • This looks pretty good and meets my requirements.
  • Tabs

    • akinsho/bufferline.nvim is great.
    • Makes it look like you have ’tabs’ in VSCode.
    • Neovim has the concept of tabs, but they’re a little different.
    • Tabs are collections of windows and a window is a view in to a buffer.
    • Buffers are just the in-memory content of a file, it has to be written to a given file.
    • <Leader>b to pick a buffer given a selection of letters.
    • <Leader>c to close said buffer.
  • Zettelkasten

    • I just found zk and it really makes templating new notes easy.

    • You can integrate it with Neovim too with zk-nvim.

    • When you add it to your Zettelkasten, it makes a SQLite database that enables searching of tags, links, and content.

    • ;zn to make a new file with a Sentence Case Title that generates a file named sentence-case-title.md. Same for the command line:

      # New note with a title
      zk new -t 'This is a Pretty title ready to be Slugified'
      
    • This is a very nice accelerator for making notes, especially journal notes. I think I like it better than using VSCode because I can get to it from the command line.

    • Either way, I will be keeping zk because it does not conflict with Foam, one of the benefits of Markdown notes.

Challenges

I’ve been having some challenges with my GPG setup on both platforms. I found a template plugins.lua file that will automatically install the plugins on :w.

In Arch, this causes pinentry to fire for every plugin. The caching mechanism for credentials does not seem to work. I have not looked for a solution.

On the Mac, GPG is crazy slow. I think that’s really an issue with Rosetta. I got my M1 for work right when it came out and Rosetta was the only option for a lot of apps. If I redid that laptop, I would not use Rosetta. Again, I don’t really have a better solution.

Because I doubt that I’ll be tinkering with Neovim for a while, I wanted to document these two issues, but not do anything about them.