rockyourcode

Subscribe
Archives
September 28, 2022

rockyourcode: TIL About GNU Stow to Manage Dotfiles, Helix Editor – 90% of Neovim With Kakoune, Setting Up a Modern Preact Application With Typescript, Vite and Vitest

Hello 👋! Thanks for subscribing.

Here are my latest articles:

TIL About GNU Stow to Manage Dotfiles

Published on: 2022-09-26

tags: DevTools, TIL

Today I learned about the tool GNU Stow, a free program that helps with managing symbolic links on your system.

What does that even mean?

I store my user configuration in a dotfile.
Using Git, I can synchronize my settings across different machines.
Now I have a backup, even if I lose my computer, or it breaks.

So far, I’ve used symlinks to create a link on my machine to the central git repository.

But I learned about a great utility called GNU Stow that helps with managing dotfiles. Stow makes neat symbolic links in the right location.

You can easily pick and choose which configurations you want to sync.

So, let’s say your dotfiles repository looks like this:

$ tree -a ~/dotfiles
.
├── bash
│   ├── .bashrc
│   └── .bash_profile
├── kitty
│   └── .config
│       └── kitty
│           └── kitty.conf
└── vim
    └── .vimrc

Then you can use stow like this:

stow bash
stow kitty
stow vim

Links

You can find detailed explanations here:

  • Managing dotfiles with GNU stow
  • Using GNU Stow to manage your dotfiles

Thanks to Sandra Parsick and Georg Berky for introducing me to this tool.


Helix Editor – 90% of Neovim With Kakoune

Published on: 2022-09-22

tags: DevTools, Vim

I’ve spend too many hours setting up the recent NeoVim features (since v0.5): tree-sitter, nvim-lsp, nvim-cmp.

Why?
NeoVim’s parser tool tree-sitter offers a better integration of language servers, syntax highlighting and auto-completion.

The Problem

Vim and NeoVim are great.
However, I put a lot of effort into customizing these editors to my liking, so that I could comfortably use them for coding.

In fact, my configuration has become more complicated over the years.

Migrating my Vim configuration to take advantage of tree-sitter was an exercise in frustration.

Better Than (Neo)Vim?

By chance I stumbled upon a review of Rust text editors on lobste.rs.

The article favorably mentions Helix, a modal text editor inspired by Vim and Kakoune.
Other commentators also seemed taken with this new text editor.

helix text editor

I gave Helix a try and I am pleasantly surprised.

Helix is a fully-fledged text editor that comes with wonderful capabilities out of the box.
For example, you get a fuzzy file finder, language server integration, a vim-surround-like plugin and great editor themes for free.

In the end, Helix offers almost everything I need from a terminal-based text editor with zero config.

After wasting hours of my free time on tweaking NeoVim, Helix’s sane defaults and inbuilt features blew me out of the water.

Kakoune – Why!?

Helix has one advantage over Vim/NeoVim - multiple cursors. This features makes text editing a smoother experience.

Multiple cursors come from Kakoune, a text editor I never heard of.

Vim’s core editing model revolves around verbs and (text) objects. For example, to delete a word, you type dw, like in a natural language like English.

Kakoune turns this model on its head: in Kakoune, you always select text objects first, then operate on them with words.

Helix uses the same model as Kakoune.
The idea is that you always start by making a selection first (that way it’s interactive and you see that you selected the right thing), then you operate on it.

I’m not sure if I can forego my muscle memory and retrain myself to use the “Kakoune” way. For me, it feels incredibly awkward.

I am also missing some commands in normal mode.
For example, I can easily move or copy lines to other locations in the file without having to make a selection and without leaving normal mode.
This is a clash with Kakoune’s/Helix’s philosophy.

What I am missing most is ci (for change inside).
I often use this command to change text in brackets (ci{), single quotes (ci') or other text objects.

Now What?

Helix is in active development.
But even so, the editor is already usable. Because it is written in Rust, it’s fast and stable.

The maintainers plan a plugin system with WebAssembly, which would be a big milestone for the project.

All in all, Helix looks like a valid alternative to Vim/NeoVim if you like modal editors.

My Configuration

Here is my complete configuration file:

theme = "nord"

[editor.cursor-shape]
insert = "bar"
normal = "block"
select = "underline"

[editor.statusline]
left = ["mode", "diagnostics"]
center = ["file-name"]
right = ["selections", "file-type", "file-encoding", "position-percentage", "position"]

[keys.normal]
g = { a = "code_action", o = "goto_last_accessed_file" }
"ret" = ["move_line_down", "goto_first_nonwhitespace"] # Maps the enter key to move to start of next line
X = "extend_line_above"
D = "delete_char_backward"

[keys.insert]
C-space = "completion"
# Move cursor in insert mode
A-h = "move_char_left"
A-j = "move_line_down"
A-k = "move_line_up"
A-l = "move_char_right"
A-o = "open_below"
A-O = "open_above"

It adds a default theme, a few convenience key mappings plus some customization around the status-line and the cursor.

In comparison, here is my code for the status-line in Vim/NeoVim alone – which is (more or less) a three-liner in Helix.

Links

  • Helix
  • Kakoune
  • Reviewing some new Rust text editors

Setting Up a Modern Preact Application With Typescript, Vite and Vitest

Published on: 2022-09-19

tags: TypeScript, React.js, Preact.js, Testing

Wiring up a TypeScript environment with Preact, Vite and Vitest and vitest-dom

I have heard good things about Vite and Vitest. When I gave them a test-drive, I stumbled over some minor annoyances in getting the whole suite running.

I’m writing down the steps I took, maybe they help you.

The article is basically a re-write of a blog post by Tomoki Miyaci adjusted to my needs.

Tooling:

  • TypeScript
  • Vite
  • Vitest (with vitest-dom)
  • Preact
  • Prettier
  • ESLint
  • husky & lint-staged
  • commitlint

All my commands use pnpm, feel free to replace them with npm or yarn.

Vite

pnpm create vite <project-name> --template preact-ts
cd <project-name>
pnpm install

ESLint & prettier

pnpm i -D eslint eslint-config-prettier \
          prettier \
          @typescript-eslint/parser

Create a new file called .eslintrc with the following content:

{
  "env": {
    "browser": true,
    "es2021": true
  },
  "extends": ["eslint:recommended", "preact", "prettier"],
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "ecmaFeatures": {
      "jsx": true
    },
    "ecmaVersion": "latest",
    "sourceType": "module"
  },
  "settings": {
    "jest": {
      "version": 27
    }
  },
  "ignorePatterns": ["*.d.ts"],
  "rules": {}
}

One wrinkle was the Jest settings option. I know I wanted to use Vite, but eslint needs to know the Jest version for some of its tests.

Prettier configuration (.prettierrc), adjust to your needs:

{
  "trailingComma": "es5",
  "semi": false,
  "singleQuote": true
}

Let’s adjust package.json:

{
  "scripts": {
    "lint:fix": "eslint --fix --ext .ts,tsx --ignore-path .gitignore .",
    "prettier:write": "prettier -u -w --ignore-path .gitignore \"*.{ts,tsx,css,html}\"",
}

husky & lint-staged

Configure lint-staged inside package.json:

{
  "lint-staged": {
    "*.{ts,tsx}": ["pnpm run lint:fix", "pnpm run prettier:write"],
    "*.{html,css,js,json}": "pnpm run prettier:write"
  }
}

We run ESLint and prettier on TypeScript files in sequential order. For other files, prettier suffices.

Now we need husky.

We initialize it with a script:

pnpm dlx husky-init && pnpm install

The above command will setup the tool and create the necessary files and hooks.

The default hook runs before committing the files to the staging area.
You can find it under .husky/pre-commit:

#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

pnpm exec lint-staged
## if you want to run your tests before commiting,
## uncomment next line
# pnpm exec vitest run

commitlint

commitlint checks if your commit messages meet the conventional commit format.

Example:

chore: run tests on travis ci

I personally find it quite useful to enforce a uniform commit style.
commitlint pairs well with husky.

pnpm add -D @commitlint/{config-conventional,cli}

Let’s add a configuration file (.commitlintrc.json):

{
  "extends": ["@commitlint/config-conventional"]
}

Now we need a hook for husky. Run the following command in your terminal:

pnpm dlx husky add \
  .husky/commit-msg 'pnpm exec commitlint --edit'

Vitest

Installation:

pnpm add -D vitest vitest-dom happy-dom

vitest-dom extends the standard Jest matchers with convenient methods like .toBeDisabled.
Now you can write tests that assert on the state of the DOM.
The package is a fork of @testing-library/jest-dom.

Configuring vitest with the .vite.config.ts:

/// <reference types="vitest" />
import { fileURLToPath } from 'url'
import { defineConfig } from 'vite'
import preact from '@preact/preset-vite'

// https://vitejs.dev/config/
export default defineConfig({
  define: {
    'import.meta.vitest': 'undefined',
  },
  plugins: [preact()],
  test: {
    environment: 'happy-dom',
    setupFiles: ['./__test__/test-setup.ts'],
    includeSource: ['src/**/*.{ts,tsx}'],
    coverage: {
      reporter: ['text-summary', 'text'],
    },
    mockReset: true,
    restoreMocks: true,
  },
})

The code section import.meta.vitest allows you to run tests within your source code.

For my test setup I’ve made a separate __test__ folder with a file called test-setup.ts:

import 'vitest-dom/extend-expect'
import * as domMatchers from 'vitest-dom/matchers'
import { expect } from 'vitest'

expect.extend(domMatchers)

Here I add the vitest-dom extra matchers. You can add more setup logic if needed.

Sources

  • Building a Typescript Environment for Preact with Vite
  • Diving Into Husky and lint-staged

Thank you for reading my blog.

Don’t hesitate to reach out via email or Twitter!

Don't miss what's next. Subscribe to rockyourcode:
GitHub X
This email brought to you by Buttondown, the easiest way to start and grow your newsletter.