Introduction


This repo uses Lilac to extract the code/configuration from Org files. Not all parts have been migrated over to use Lilac yet, and until that's done there will be many incomplete sections in the docs.

Warning: I will force-push to this repo rather frequently. Sorry!

1 Installation

Each subdirectory is responsible for one component, and is also the name of a build rule in the Makefile.

E.g., to set up Emacs and Vim configurations, do:

make emacs vim

2 Known Issues

3 Build system

3.1 Lilac project configuration

🎯 doc/.lilac.json
{
    "name": "Linus Arver's Dotfiles",
    "homepage": "https://git.sr.ht/~listx/syscfg",
    "repo": "https://git.sr.ht/~listx/syscfg",
    "version": "",
    "nonTangledPathspecs": [ 1
        ":(exclude,top).gitmodules",
        ":(exclude,top).lilac.json",
        ":(exclude,top)README.md",
        ":(exclude,top)LICENSE",
        ":(exclude,top)clojure",
        ":(exclude,top)doc/*.org",
        ":(exclude,top)emacs/doom-cfg/snippets/.gitkeep",
        ":(exclude,top)emacs/doom-upstream",
        ":(exclude,top)Cargo.lock",
        ":(exclude,top)gpg",
        ":(exclude,top)jj",
        ":(exclude,top)jjui",
        ":(exclude,top)karabiner",
        ":(exclude,top)lesskey",
        ":(exclude,top)melby",
        ":(exclude,top)mpd",
        ":(exclude,top)mpv",
        ":(exclude,top)nix",
        ":(exclude,top)nixos",
        ":(exclude,top)nixpkgs",
        ":(exclude,top)notmuch",
        ":(exclude,top)nvim",
        ":(exclude,top)openvpn",
        ":(exclude,top)pulse",
        ":(exclude,top)qutebrowser",
        ":(exclude,top)rtorrent",
        ":(exclude,top)ssh",
        ":(exclude,top)terminfo",
        ":(exclude,top)tig",
        ":(exclude,top)tmux",
        ":(exclude,top)vimpc",
        ":(exclude,top)wezterm",
        ":(exclude,top)nixos",
        ":(exclude,top)script",
        ":(exclude,top)uim",
        ":(exclude,top)vim",
        ":(exclude,top)xmonad",
        ":(exclude,top)xorg",
        ":(exclude,top)zathura",
        ":(exclude,top)zsh"
    ]
}

Currently we exclude most paths in 1, because we haven't migrated existing code to literate style yet.

3.2 Literate Makefile

The literate programming configuration is inside the doc folder. It houses all Org files which we feed into Lilac to tangle the code and also weave HTML output.

🎯 doc/Makefile
org_files := $(shell find . -type f -name "*.org")

obj_files := $(org_files:%.org=%.lobj)

archive_file := syscfg.larc

all: tangle weave lint
.PHONY: all

$(obj_files) &: $(org_files)
	lilac compile $?
	touch $(obj_files)

$(archive_file): $(obj_files)
	lilac archive $^ --out-file $@

tangle: $(archive_file)
	lilac tangle $< --out-dir ..
	touch tangle

weave: $(archive_file)
	lilac weave $< --out-dir .. --root-relative-prefix "/syscfg" --write-css --write-js
	touch weave

lint: $(archive_file)
	cd .. && lilac lint doc/$<
	prek run --all-files
	touch lint

gitconfig:
	cd .. && git config diff.orderfile .git-orderfile
.PHONY: gitconfig

update:
	cd .. && niv update nixpkgs --branch Nixpkgs version
.PHONY: update

clean:
	rm -rf \
		$(archive_file) \
		$(obj_files)
.PHONY: clean
Nixpkgs version
nixos-25.11

3.3 Makefile for installing dotfiles

🎯 Makefile
# Configuration directory.
C := $(shell pwd)
# Home directory.
H := ${HOME}
# Platform. E.g., "Darwin", "Linux".
P := $(shell uname)
# Long hostname, without the trailing domain name, if any.
T := $(shell hostname | cut -d. -f1)
# Short (custom) hostname.
S := $(shell cat ${H}/.hostname-short)

# Add the -n flag for directories, as otherwise, stray symlinks will be created
# inside the C (config) directory itself.

Makefile-bash
Makefile-clojure
Makefile-emacs
Makefile-git
gpg:
	ln -fns ${C}/gpg                                    ${H}/.gnupg
	ln -fs ${C}/gpg/gpg-agent.nixos.conf                ${H}/.gnupg/gpg-agent.conf
jj:
	ln -fns ${C}/jj                                     ${H}/.config/jj
jjui:
	ln -fns ${C}/jjui                                   ${H}/.config/jjui
karabiner:
	mkdir -p ${H}/.config/karabiner
	ln -fns ${C}/karabiner/karabiner.json               ${H}/.config/karabiner
lesskey:
	ln -fs ${C}/lesskey/cfg                             ${H}/.lesskey
	lesskey
melby:
	ln -fns ${C}/melby                                   ${H}/.melby
	set -e && \
		melby_location=$$(readlink $$(which melbyd)) && \
		cp -f $${melby_location%/bin/melbyd}/share/melby/sample/* ${H}/.melby
mpd:
	ln -fns ${C}/mpd                                    ${H}/.config/mpd
mpv:
	ln -fns ${C}/mpv                                    ${H}/.config/mpv
ifeq ('${T}','k0')
	ln -fs mpv.${T}.conf                                mpv/mpv.conf
else ifeq ('${P}','Darwin')
	ln -fs mpv.osx.conf                                 mpv/mpv.conf
else
	ln -fs mpv.linux.conf                               mpv/mpv.conf
endif
nix:
	ln -fns ${C}/nix                                    ${H}/.config/nix
nixos:
ifeq ('${T}','w0')
	ln -fs ${C}/nixos/${T}/configuration.nix            /etc/nixos
	ln -fs ${C}/nixos/${T}/syschdemd.nix                /etc/nixos
	ln -fs ${C}/nixos/${T}/syschdemd.sh                 /etc/nixos
	ln -fs ${C}/nixos/${T}/wsl.conf                     /etc/nixos
	ln -fs ${C}/nixos/${T}/hosts                        /etc
	cp -f ${C}/nixos/${T}/resolv.conf                   /etc
else
	ln -fs ${C}/nixos/${T}/configuration.nix            /etc/nixos
	ln -fs ${C}/nixos/${T}/hardware-configuration.nix   /etc/nixos
endif
nixpkgs:
	ln -fns ${C}/nixpkgs                                ${H}/.nixpkgs
notmuch:
	ln -fs ${C}/notmuch/notmuch-config                  ${H}/.notmuch-config
nvim:
	ln -fns ${C}/nvim                                   ${H}/.config/nvim
pulse:
	rm -rf ${H}/.config/pulse
	rm -rf ${H}/.pulse
	mkdir -p ${H}/.config/pulse
	mkdir ${H}/.pulse
ifeq ('${T}','k0')
	cp ${C}/pulse/daemon.conf.k0                        ${H}/.config/pulse/daemon.conf
	cp ${C}/pulse/default.pa.k0                         ${H}/.pulse/default.pa
else
	cp ${C}/pulse/default.pa                            ${H}/.pulse/default.pa
endif
qutebrowser:
ifeq ('${P}','Darwin')
	ln -fns ${C}/qutebrowser                            ${H}/.qutebrowser
else
	ln -fns ${C}/qutebrowser                            ${H}/.config
endif
rtorrent:
	ln -fs ${C}/rtorrent/cfg                            ${H}/.rtorrent.rc
ssh:
ifeq ($(wildcard ~/.ssh/.),)
	ln -fns ${C}/ssh                                    ${H}/.ssh
endif
	ln -fs ${C}/ssh/config.home.conf                    ${H}/.ssh/config
terminfo:
	git -C ${C} submodule update --init ${C}/wezterm/upstream
	tic -x -o ~/.terminfo ${C}/wezterm/upstream/termwiz/data/wezterm.terminfo
	tic -x -o ~/.terminfo ${C}/terminfo/xterm-24bit.terminfo
tig:
	ln -fs ${C}/tig/.tigrc                              ${H}
tmux:
	ln -fs ${C}/tmux/.tmux.conf                         ${H}/.tmux.conf
	ln -fns ${C}/tmux                                   ${H}/.tmux
uim:
	ln -fns ${C}/uim/.uim                               ${H}/.uim
	ln -fns ${C}/uim                                    ${H}/.uim.d
vim:
	ln -fns ${C}/vim                                    ${H}/.vim
	ln -fs ${C}/vim/cfg                                 ${H}/.vimrc
	ln -fs ${C}/vim/cfg                                 ${H}/.gvimrc
vimpc:
	ln -fs ${C}/vimpc/.vimpcrc                          ${H}
wezterm:
	ln -fs ${C}/wezterm/.wezterm.lua                    ${H}
xmonad:
	ln -fns ${C}/xmonad                                 ${H}/.xmonad
	# xsession is relied on by NixOS hosts that use xmonad (basically the
	# default) to start xmonad.
	ln -fs ${C}/xmonad/.xsession                        ${H}/.xsession
zathura:
	ln -fns ${C}/zathura                                ${H}/.config/zathura
zsh:
	ln -fns ${C}/zsh                                    ${H}/.zsh
	ln -fs ${C}/zsh/.zshenv                             ${H}
	ln -fs ${C}/zsh/.zshrc                              ${H}
	test -f ${C}/zsh/zprofile-${T} \
		&& ln -fs ${C}/zsh/zprofile-${T}                ${H}/.zprofile || true
	test -f ${C}/zsh/zprofile-${S} \
		&& ln -fs ${C}/zsh/zprofile-${S}                ${H}/.zprofile || true
	test -f ${C}/zsh/zlogin-${T} \
		&& ln -fs ${C}/zsh/zlogin-${T}                  ${H}/.zlogin || true
	mkdir -p ${H}/.zsh-untracked
	git -C ${C} submodule update --init ${C}/zsh/zcomet-upstream
	mkdir -p ${C}/zsh/zcomet
	ln -fns ${C}/zsh/zcomet                             ${H}/.zcomet

.PHONY: \
	bash \
	clojure \
	emacs \
	git \
	gpg \
	jj \
	jjui \
	karabiner \
	lesskey \
	melby \
	mpd \
	mpv \
	nix \
	nixos \
	nixpkgs \
	notmuch \
	nvim \
	pulse \
	qutebrowser \
	rtorrent \
	ssh \
	terminfo \
	tig \
	tmux \
	uim \
	vim \
	vimpc \
	wezterm \
	xmonad \
	xorg \
	zathura \
	zsh

3.4 Dependencies via Nix

🎯 shell.nix
let
  sources = import ./nix/sources.nix;
  rust-overlay = import sources.rust-overlay;
  pkgs = import sources.nixpkgs {
    overlays = [ rust-overlay ];
  };
  rustToolchain = pkgs.rust-bin.stable.latest.default.override {
    extensions = [ "rust-src" "rust-analyzer" "clippy" ];
  };
  git-hooks = import sources."git-hooks.nix";

  # 3. Configure the pre-commit checks
  pre-commit-check = git-hooks.run {
    src = ./.;
    hooks = {
      shellcheck = {
        enable = true;
        excludes = [
          "script/aex.sh"
          "nixos/w0/syschdemd.sh"
          "\\.(zsh|zshrc|zprofile|zshenv)$"
          "zsh/*"
        ];
      };
      editorconfig-checker.enable = true;
      clippy = {
        enable = true;
        package = rustToolchain;
      };
    };
    package = pkgs.prek;
  };
in
pkgs.mkShell {
  name = "syscfg-dev-shell";

  buildInputs = with pkgs; [
    editorconfig-checker
    pikchr
    shellcheck
    nixfmt
    niv
    ormolu
    parinfer-rust
    shfmt
    vale
    pkgs.prek

    rustToolchain
  ] ++ pre-commit-check.enabledPackages;

  nativeBuildInputs = with pkgs; [
    pkg-config
    gcc
  ];
  propagatedBuildInputs = with pkgs; [
    openssl
    zlib
  ];

  shellHook = ''
    echo -e "\n$(tput setaf 4)"
    echo Syscfg | ${pkgs.figlet}/bin/figlet
    echo -e "$(tput sgr0)\n"
    echo "Using nixpkgs commit: ${sources.nixpkgs.rev} ${pkgs.lib.version}"
    echo "Rust compiler profile: $(rustc --version)"
    echo
    ${pre-commit-check.shellHook}
  '';
}

The pre-commit-check.shellHook generates the YAML at .pre-commit-config.yaml for us.

🎯 .envrc
use nix

4 Other project settings

4.1 .gitignore file

🎯 .gitignore
*#
*.aes
*.backup
.clj-kondo
.direnv
*.elc
*.log
*.hi
.lsp
.nrepl-port
*.o
*.pyc
*.swp
*.DS_Store
*~
*.zwc
cache
cmus/*
emacs/doom-cfg/custom.el
emacs/spell-fu/*.data
emacs/spell-fu/*.txt
gpg
karabiner/assets
karabiner/automatic_backups
lh/target
melby/*
mpv/mpv.conf
nvim/.netrwhist
openvpn/*.ovpn
qutebrowser/autoconfig.yml
qutebrowser/bookmarks
qutebrowser/quickmarks
qutebrowser/qsettings
ssh/*
target/
tmux/resurrect
vim/.VimballRecord
vim/.netrwhist
vim/colors
vim/sessions
wezterm/upstream
xmonad/.cabal-sandbox
xmonad/cabal.sandbox.config
xmonad/dist
xmonad/dist-newstyle
xmonad/.stack-work
xmonad/xmonad
xmonad/xmonad-x86_64-linux
xmonad/xmonad.errors
xmonad/xmonad.state
xmonad/xmonad-session-rc
zsh/zcomet

!.gitattributes
!.git-orderfile
*.lobj
*.larc
*.html
*.js
*.css
lint
tangle
weave
.pre-commit-config.yaml

4.2 Git attributes

🎯 .gitattributes
*.html -diff
doc/css/default.css -diff
doc/js/lilac.js -diff

4.3 Git orderfile

Make git-diff show the Org files first.

git-orderfile
🎯 .git-orderfile
# Org files
doc/index.org
*.org

4.4 .rgignore file

🎯 .rgignore
bash/
clojure/
emacs/doom-upstream
zsh/zcomet-upstream

4.5 EditorConfig

🎯 .editorconfig
root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

[*.{sh},Makefile]
indent_style = tab
tab_width = 8

[qutebrowser.conf]
trim_trailing_whitespace = false

[zsh/.zshrc]
end_of_line = unset

[COMMIT_EDITMSG]
max_line_length = 72

5 Plan

5.1 TODO pre-commit: add spellchecker (vale) to linter

5.2 TODO pre-commit: add formatter linter for emacs lisp

5.3 TODO pre-commit: add ormolu formatter for Haskell

5.4 TODO pre-commit: add nixfmt formatter to linter

5.5 TODO migrate everything (at least superficially) to lilac

This basically means chipping away at 1 to make it much leaner. That is, the only reason that section is so long is because most of those paths are not tangled from Org files.

Page metrics

Tangled files (10)

  1. .editorconfig
  2. .envrc
  3. .git-orderfile
  4. .gitattributes
  5. .gitignore
  6. .rgignore
  7. Makefile
  8. doc/.lilac.json
  9. doc/Makefile
  10. shell.nix

Named cells (2)

  1. Nixpkgs version
  2. git-orderfile