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:
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.
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
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
Thank you for reading my blog.