惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

小众软件
小众软件
N
News and Events Feed by Topic
A
About on SuperTechFans
aimingoo的专栏
aimingoo的专栏
The Cloudflare Blog
H
Heimdal Security Blog
Schneier on Security
Schneier on Security
Engineering at Meta
Engineering at Meta
Google Online Security Blog
Google Online Security Blog
宝玉的分享
宝玉的分享
AI
AI
The GitHub Blog
The GitHub Blog
MongoDB | Blog
MongoDB | Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
The Last Watchdog
The Last Watchdog
T
Troy Hunt's Blog
S
Security @ Cisco Blogs
H
Hacker News: Front Page
F
Fortinet All Blogs
博客园_首页
S
Secure Thoughts
N
News and Events Feed by Topic
P
Proofpoint News Feed
Microsoft Azure Blog
Microsoft Azure Blog
I
InfoQ
Spread Privacy
Spread Privacy
Hacker News - Newest:
Hacker News - Newest: "LLM"
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
C
Check Point Blog
Hugging Face - Blog
Hugging Face - Blog
Hacker News: Ask HN
Hacker News: Ask HN
C
CXSECURITY Database RSS Feed - CXSecurity.com
酷 壳 – CoolShell
酷 壳 – CoolShell
Stack Overflow Blog
Stack Overflow Blog
L
LINUX DO - 最新话题
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
S
Schneier on Security
Know Your Adversary
Know Your Adversary
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Scott Helme
Scott Helme
P
Privacy & Cybersecurity Law Blog
S
Securelist
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
O
OpenAI News
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
PCI Perspectives
PCI Perspectives
L
LangChain Blog
雷峰网
雷峰网
Security Archives - TechRepublic
Security Archives - TechRepublic
V2EX - 技术
V2EX - 技术

Oskar Wickström

Coding on Paper Catching Typos on My Website with Browser Testing The Bombadil Terminal Experiment There and Back Again: From Quickstrom to Bombadil Computer Says No: Error Reporting for LTL A Year with the Daylight Computer Finding Bugs in a Coding Agent with Lightweight DST Machine: Learning; Human: Unlearning; How I Built “The Monospace Web” Statically Typed Functional Programming with Python 3.12 Specifying State Machines with Temporal Logic Clearing Weeds and Planting Trees Introducing Quickstrom: High-confidence browser testing The TodoMVC Showdown: Testing with WebCheck Time Travelling and Fixing Bugs with Property-Based Testing Property-Based Testing in a Screencast Editor, Case Study 3: Integration Testing Property-Based Testing in a Screencast Editor, Case Study 2: Video Scene Classification Property-Based Testing in a Screencast Editor, Case Study 1: Timeline Flattening Property-Based Testing in a Screencast Editor: Introduction Why I’m No Longer Taking Donations Writing a Screencast Video Editor in Haskell Declarative GTK+ Programming with Haskell Finite-State Machines, Part 2: Explicit Typed State Transitions Modeling with Haskell Data Types Motor: Finite-State Machines in Haskell Automating the Build of your Technical Presentation Tagless Final Encoding of a Test Language Hyper: Elegant Weapons for a More Civilized Page Taking a Step Back from Oden Custom Formatting in HTML and LaTeX Code Listings using Pandoc Paramount Color Scheme for Vim
A Flexible Minimalist Neovim for 2024
Oskar Wickström · 2024-08-12 · via Oskar Wickström

Neovim welcome screen

In the eternal search of a better text editor, I’ve recently gone back to Neovim. I’ve taken the time to configure it myself, with as few plugins and other cruft as possible. My goal is a minimalist editing experience, tailored for exactly those tasks that I do regularly, and nothing more. In this post, I’ll give a brief tour of my setup and its motivations.

Over the years, I’ve been through a bunch of editors. Here are most of them, in roughly chronological order:

  • Adobe Dreamweaver
  • Sublime Text
  • Atom
  • Vim/Neovim
  • IntelliJ IDEA
  • VS Code
  • Emacs

The majority were used specifically for the work I was doing at the time. VS Code for web development, IntelliJ IDEA for JVM languages, Emacs for Lisps. Vim and Emacs have been the most generally applicable, and the ones that I’ve enjoyed the most.

I’ve also evaluated Zed recently, but it hasn’t quite stuck. The start-up time and responsiveness is impressive. However, it seems to insist on being a global application. I want my editor to be local to each project, with the correct PATH from direnv, and I want multiple isolated instances to run simultaneously. Maybe I’ll revisit it later.

Returning to Neovim

Yeah, so I’m back in Neovim. I actually started with the LazyVim distribution based on recommendation. On the positive side, it got me motivated to use Neovim again. But I had some frustrations with the distribution.

The start-up time wasn’t great. I guess it did some lazy loading of plugins to speed things up, but the experience was still that of an IDE taking its time to get ready. Not the Neovim experience I was hoping for.

More importantly, it was full of distractions; popups, status messages, news, and plugins I didn’t need. I guess it takes a batteries-included approach. That might make sense for beginners and those just getting into Neovim, but I realized quickly that I wanted something different.

Supposedly I could strip things out, but instead I decided to start from scratch and build the editor I wanted. One that I understand. Joran Dirk Greef talks about two different types of artists, sculptors and painters, and this is an exercise in painting.

More concretely, my main goals are:

Plugins

I want to keep plugins to an absolute minimum. My editor is meant for coding and writing, and for what I work on right now. I might add or remove plugins and configuration over time, and that’s fine.

User interface

It should be as minimalist as I can make it. Visual distractions kept at a minimum. This includes busy colorschemes, which I find add little value. A basic set of typographical conventions in monochrome works well for me.

Start-up time

With the way I use Neovim, it needs to start fast. I quit and start it all the time, jumping between directories, working on different parts of the system or a project. Often I put it in the background with C-z, but not always. Making it faster seems to be mainly an exercise in minimizing plugins.

I have to mention Nix, you know?

I manage dotfiles and other personal configuration using Nix and home-manager. The Neovim configuration is no exception, so I’ll include some of the Nix bits as well.

The vim.nix module declares that I want Neovim installed and exposed as vim:

programs.neovim = {
  enable = true;
  vimAlias = true;
  ...
};

In that attribute set, there are two other important parts; the plugins list and the extraConfig.

Plugins

Let’s start with the plugins:

plugins = with pkgs.vimPlugins; [
  nvim-lspconfig
  (nvim-treesitter.withPlugins(p: [
    p.bash
    p.json
    p.lua
    p.markdown
    p.nix
    p.python
    p.rust
    p.zig
    p.vimdoc
  ]))
  conform-nvim
  neogit
  fzf-vim
];

Basically it’s five plugins, not counting the various treesitter parsers:

nvim-lspconfig
LSP is included in Neovim nowadays, but it doesn’t know about specific language servers. The lspconfig plugins helps with configuring Neovim for use with various servers.
nvim-treesitter
This provides better highlighting for Neovim. I’ve only included the languages I use right now. No nice-to-haves. I could probably remove this plugin, but I haven’t tried yet.
conform-nvim
Auto-formatting is useful and I don’t want to think about it. Of course, I could run :%!whatever-formatter, but I’d rather have the editor do it for me.
neogit
Magit was the reason I clung to Emacs for so long. Neogit is, for my purposes, a worthy replacement. It enabled me to finally make the switch.
fzf-vim
A wrapper around the awesome fzf fuzzy finder. I use :Files and :GFiles, as quick jump-to-file commands (think C-p in VS Code or Zed). They are bound to <Leader>ff and <Leader>gf, respectively. This might be another plugin I could do without, writing a small helper around fzf, or just making do with :find and **/ wildcards. On the other hand, I’m trying out :Buffers instead of stumbling around with :bnext and :bprev.

One great thing with the Nix setup is I don’t need a package manager in Neovim itself.

Batteries Are Included

Many things I don’t need plugins for. For instance, there are a ton of plugins for auto-completion, but Neovim has most of that built in, and I prefer triggering it manually:

  • File name completions with C-x C-f
  • Omnicomplete (rebound to C-Space in my case)
  • Buffer completions with C-x C-n
  • Spelling suggestions with C-x C-s or z=

I’ve tried various snippet engines many times, but not found them very useful. Most of my time is spent reading or modifying existing code, not churning out new boilerplate. Instead they tend to clutter the auto-completion list. Snippets might make more sense for things like HTML, but I don’t write HTML often, and in that case I’d prefer some emmet/zen-coding plugin.

You can get great mileage from learning how to use the Quickfix list. I’m no expert, but I prefer investing in composable primitives that I can reuse in different ways. Project-wide search-and-replace is such an example:

:grep whatever
:cfdo s/whatever/something else/g | update
:cfdo :bd

Here we search (:grep, which I’ve configured to use rg), substitute and save each file, and delete those buffers afterwards.

I also use :make and :compiler a lot. Neovim is cool.

Life in Monochrome

Maybe I’m just growing old, but I prefer a monochrome colorscheme. Right now I’m using the built-in quiet scheme with a few extra tweaks:

set termguicolors
set bg=dark
colorscheme quiet
highlight Keyword gui=bold
highlight Comment gui=italic
highlight Constant guifg=#999999
highlight NormalFloat guibg=#333333

It’s black-and-white, but keywords are bold, comments are darker and italic, and literals are light gray. Here’s how it looks with some Zig code:

Neovim in monochrome with the quiet colorscheme

Maybe I’m coming off as nostalgic or conservative, but I do find it more readable this way.

Another thing I’m going to try soon is writing on the Daylight Computer, hopefully in Neovim. Being comfortable with a monochrome colorscheme should come in handy.

The Full Configuration

My config uses a Vimscript entrypoint (extraConfig in the Nix code). This part is based on my near-immortal config from the good old Vim days. Early on, it calls vim.loader.enable() to improve startup time. I use Lua scripts for configuring the plugins and related keymap bindings. Maybe everything could be Lua, but I haven’t gotten that far yet. However, it’s nice to have the base config somewhat portable; I can just copy-paste it onto a server or some other temporary environment and have a decent /usr/bin/vim experience.

You’ll find the full configuration in nix.vim and the Lua bits inside the vim/ directory.

That’s about it! I’m really happy with how fast and minimalistic it is. It starts in just above 100ms. And I can understand all of my configuration (even if I don’t understand all of Neovim.) Perhaps I’ve spent more time on it than I’ve saved, but at least I’m happy so far.

I’m writing and publishing this on my birthday. What a treat to find time to blog on such an occasion!