OrgとNixによる文芸的設定集
Table of Contents
1. About
2. Philosophy
2.1. Literate Configuration
Nix is declarative. Reading a Nix expression reveals what the system should become, and Nix itself handles how to get there. But neither the code nor the build system captures why a particular configuration exists, or why alternatives were rejected.
Why was fish chosen over zsh or bash? Why does the desktop profile enable this specific set of services? Why was a particular package pinned to an older version? The code shows the decision, but not the reasoning behind it. Without this context, future changes risk undoing intentional tradeoffs or repeating previously rejected approaches.
This repository uses literate programming to preserve intent. Configuration lives in Org mode documents where prose surrounds code. Each decision—from high-level architecture to individual package overrides—is accompanied by its rationale: why this approach was chosen, and why alternatives were not.
Configurations are documented with the problem that motivated them, the alternatives considered, and the reasoning behind the final choice. For temporary workarounds, the conditions for removal are also noted.
3. 設定
3.1. Flake
This flake manages NixOS, nix-darwin, and home-manager configurations for multiple machines across different platforms (macOS, Linux, Android). It uses flake-parts for modular organization and includes tooling for development, code formatting, and pre-commit hooks.
{
description = "dotfiles";
inputs = {
# Core
nixpkgs.url = "git+https://github.com/nixos/nixpkgs?shallow=1&ref=nixos-unstable-small";
# "github:NixOS/nixpkgs/trick-renovate-into-working"
nixpkgs-stable.url = "git+https://github.com/nixos/nixpkgs?shallow=1&ref=nixos-25.05";
# Flake Infrastructure
flake-parts = {
url = "github:hercules-ci/flake-parts";
inputs.nixpkgs-lib.follows = "nixpkgs";
};
# Transitive Dependencies
flake-utils.url = "github:numtide/flake-utils";
# System Configuration
darwin = {
url = "github:nix-darwin/nix-darwin";
inputs.nixpkgs.follows = "nixpkgs";
};
home-manager = {
url = "github:nix-community/home-manager";
inputs.nixpkgs.follows = "nixpkgs";
};
nixos-wsl = {
url = "github:nix-community/nixos-wsl";
inputs.flake-compat.follows = "";
inputs.nixpkgs.follows = "nixpkgs";
};
nix-on-droid = {
url = "github:nix-community/nix-on-droid";
inputs.home-manager.follows = "home-manager";
inputs.nix-formatter-pack.follows = "";
inputs.nixpkgs-docs.follows = "nixpkgs";
inputs.nixpkgs-for-bootstrap.follows = "nixpkgs";
inputs.nixpkgs.follows = "nixpkgs";
inputs.nmd.follows = "";
};
disko = {
url = "github:nix-community/disko";
inputs.nixpkgs.follows = "nixpkgs";
};
impermanence.url = "github:nix-community/impermanence";
lanzaboote = {
url = "github:nix-community/lanzaboote";
inputs.nixpkgs.follows = "nixpkgs";
inputs.pre-commit.follows = "git-hooks";
};
nixos-facter-modules.url = "github:numtide/nixos-facter-modules";
# Infrastructure
comin = {
url = "github:nlewo/comin";
inputs.nixpkgs.follows = "nixpkgs";
};
sops-nix = {
url = "github:Mic92/sops-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
tsnsrv = {
url = "github:boinkor-net/tsnsrv";
inputs.flake-parts.follows = "flake-parts";
inputs.nixpkgs.follows = "nixpkgs";
};
# Development Tools
git-hooks = {
url = "github:cachix/git-hooks.nix";
inputs.flake-compat.follows = "";
inputs.gitignore.follows = "";
inputs.nixpkgs.follows = "nixpkgs";
};
treefmt-nix = {
url = "github:numtide/treefmt-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
# Desktop & Theming
nix-colors = {
url = "github:misterio77/nix-colors";
inputs.nixpkgs-lib.follows = "nixpkgs";
};
nix-wallpaper = {
url = "github:natsukium/nix-wallpaper/custom-logo";
inputs.flake-utils.follows = "flake-utils";
inputs.nixpkgs.follows = "nixpkgs";
inputs.pre-commit-hooks.follows = "git-hooks";
};
# Applications
brew-api = {
url = "github:BatteredBunny/brew-api";
flake = false;
};
brew-nix = {
url = "github:BatteredBunny/brew-nix";
inputs.brew-api.follows = "brew-api";
inputs.nix-darwin.follows = "darwin";
inputs.nixpkgs.follows = "nixpkgs";
};
claude-desktop = {
url = "github:k3d3/claude-desktop-linux-flake";
inputs.flake-utils.follows = "flake-utils";
inputs.nixpkgs.follows = "nixpkgs";
};
edgepkgs = {
url = "github:natsukium/edgepkgs";
inputs.nixpkgs.follows = "nixpkgs";
};
emacs-overlay = {
url = "github:nix-community/emacs-overlay";
inputs.nixpkgs-stable.follows = "nixpkgs-stable";
inputs.nixpkgs.follows = "nixpkgs";
};
firefox-addons = {
url = "gitlab:rycee/nur-expressions?dir=pkgs/firefox-addons";
inputs.nixpkgs.follows = "nixpkgs";
};
mcp-servers = {
url = "github:natsukium/mcp-servers-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
niri-flake = {
url = "github:sodiboo/niri-flake";
inputs.niri-stable.follows = "";
inputs.niri-unstable.follows = "";
inputs.nixpkgs-stable.follows = "nixpkgs-stable";
inputs.nixpkgs.follows = "nixpkgs";
inputs.xwayland-satellite-stable.follows = "";
inputs.xwayland-satellite-unstable.follows = "";
};
nur-packages = {
url = "github:natsukium/nur-packages";
inputs.nixpkgs.follows = "nixpkgs";
};
zen-browser = {
url = "github:0xc000022070/zen-browser-flake";
inputs.nixpkgs.follows = "nixpkgs";
inputs.home-manager.follows = "home-manager";
};
};
nixConfig = {
extra-substituters = [
"https://natsukium.cachix.org"
"https://nix-community.cachix.org"
];
extra-trusted-public-keys = [
"natsukium.cachix.org-1:STD7ru7/5+KJX21m2yuDlgV6PnZP/v5VZWAJ8DZdMlI="
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
];
};
outputs =
{ self, flake-parts, ... }@inputs:
flake-parts.lib.mkFlake { inherit inputs; } {
systems = [
"x86_64-linux"
"aarch64-linux"
"aarch64-darwin"
];
imports = [
./flake-module.nix
inputs.git-hooks.flakeModule
inputs.treefmt-nix.flakeModule
];
hosts = {
# main laptop (m1 macbook air)
katavi = {
system = "aarch64-darwin";
};
# build server (m1 mac mini)
mikumi = {
system = "aarch64-darwin";
};
# laptop for work (m4 macbook pro)
work = {
system = "aarch64-darwin";
};
# main desktop (intel core i5-12400F)
kilimanjaro = {
system = "x86_64-linux";
};
# WSL (dualboot with kilimanjaro)
arusha = {
system = "x86_64-linux";
};
# main server (intel N100)
manyara = {
system = "x86_64-linux";
};
# build server (OCI A1 Flex)
serengeti = {
system = "aarch64-linux";
};
# build server (Ryzen 9 9950X)
tarangire = {
system = "x86_64-linux";
};
# phone (pixel 7a)
android = {
system = "aarch64-linux";
platform = "android";
};
};
flake = {
overlays = import ./overlays { inherit inputs; };
templates = import ./templates;
};
perSystem =
{
self',
config,
pkgs,
system,
...
}:
{
_module.args.pkgs = import self.inputs.nixpkgs {
inherit system;
config.allowUnfree = true;
overlays = [ self.inputs.nur-packages.overlays.default ] ++ builtins.attrValues self.overlays;
};
checks = import ./tests {
inherit (self.inputs) nixpkgs;
inherit pkgs;
};
packages = {
fastfetch = pkgs.callPackage ./pkgs/fastfetch { };
neovim = pkgs.callPackage ./pkgs/neovim-with-config { };
po4a_0_74 = (
pkgs.po4a.overrideAttrs (oldAttrs: {
version = "0.74";
src = pkgs.fetchurl {
url = "https://github.com/mquinson/po4a/releases/download/v0.74/po4a-0.74.tar.gz";
hash = "sha256-JfwyPyuje71Iw68Ov0mVJkSw5GgmH5hjPpEhmoOP58I=";
};
patches = [ ];
nativeBuildInputs = oldAttrs.nativeBuildInputs ++ [ pkgs.libxml2 ];
doCheck = false;
})
);
html =
with pkgs;
let
org-html-themes = fetchurl {
url = "https://raw.githubusercontent.com/fniessen/org-html-themes/b3898f4c5b09b3365fd93fd1566f46ecd0a8911f/org/theme-readtheorg.setup";
hash = "sha256-+5gy+S6NcuvlV61fudbCNoCKmSrCdA9P5CHeGKlDrSM=";
};
org-to-html = writeScript "org-to-html.el" ''
(require 'org)
(require 'htmlize)
(find-file "README.org")
(org-html-export-to-html)
(find-file "README.ja.org")
(org-html-export-to-html)
'';
in
stdenvNoCC.mkDerivation {
name = "dotfiles";
src = lib.cleanSource ./.;
postPatch = ''
substituteInPlace README.org \
--replace-fail "https://fniessen.github.io/org-html-themes/org/theme-readtheorg.setup" "${org-html-themes}"
'';
nativeBuildInputs = [
(emacs.pkgs.withPackages (epkgs: [ epkgs.htmlize ]))
gettext
self'.packages.po4a_0_74
];
buildPhase = ''
runHook preBuild
po4a po4a.cfg
emacs --batch -l ${org-to-html}
runHook postBuild
'';
installPhase = ''
runHook preInstall
install -Dm644 README.html $out/index.html
install -Dm644 README.ja.html $out/ja/index.html
runHook postInstall
'';
};
};
pre-commit = {
check.enable = true;
settings = {
src = ./.;
hooks = {
actionlint.enable = true;
biome.enable = true;
lua-ls.enable = false;
nil.enable = true;
shellcheck.enable = true;
treefmt.enable = true;
typos = {
enable = true;
excludes = [
"homes/shared/gpg/keys.txt"
"secrets.yaml"
"secrets/default.yaml"
"systems/nixos/tarangire/facter.json"
"systems/shared/hercules-ci/binary-caches.json"
];
settings.configPath = "typos.toml";
};
yamllint = {
enable = true;
excludes = [
"secrets/default.yaml"
"secrets.yaml"
];
settings.configData = "{rules: {document-start: {present: false}}}";
};
# Prefixed with "00-" to ensure this hook runs before all other hooks
# (hooks are sorted alphabetically when no explicit before/after is specified)
"00-check-org-tangle" = {
enable = true;
name = "check-org-tangle";
description = "Verify org files are tangled and synchronized";
entry =
let
checkScript = pkgs.writeShellScript "check-org-tangle" ''
set -euo pipefail
${pkgs.gnumake}/bin/make -B tangle
# Check for differences using git diff
changed=$(${pkgs.git}/bin/git diff --name-only)
if [ -n "$changed" ]; then
echo "Org files were out of sync and have been auto-tangled."
echo "Changed files:"
echo "$changed"
echo ""
echo "Please stage the changes and commit again:"
echo " git add $changed"
exit 1
fi
exit 0
'';
in
"${checkScript}";
files = "\\.org$";
pass_filenames = false;
};
};
};
};
treefmt = {
projectRootFile = "flake.nix";
programs = {
biome.enable = true;
nixfmt.enable = true;
shfmt.enable = true;
stylua.enable = true;
taplo.enable = true;
terraform.enable = true;
yamlfmt.enable = true;
};
};
devShells = {
default = pkgs.mkShell {
packages = with pkgs; [
gettext
nix-fast-build
self'.packages.po4a_0_74
sops
ssh-to-age
(terraform.withPlugins (p: [
p.carlpett_sops
p.cloudflare_cloudflare
p.determinatesystems_hydra
p.hashicorp_aws
p.hashicorp_external
p.hashicorp_null
p.integrations_github
p.oracle_oci
]))
];
shellHook = config.pre-commit.installationScript + ''
echo "Syncing CLAUDE.md..."
make CLAUDE.md >/dev/null 2>&1 || echo "Warning: Failed to generate CLAUDE.md"
'';
};
};
};
};
}
3.1.1. Inputs
External flake dependencies.
To minimize evaluation time caused by dependency graph bloat, almost all flakes are configured to follow the same nixpkgs and other common inputs wherever possible.
- Core
- nixpkgs
https://github.com/NixOS/nixpkgs
Nix Packages collection & NixOS
The primary package set. Using
nixos-unstable-smallinstead ofnixos-unstablefor faster channel updates. The-smallvariant skips some less critical CI tests, allowing new package versions to propagate faster while maintaining stability for core packages.For channel selection guidance, see https://nix.dev/concepts/faq.html#which-channel-branch-should-i-use
Channel status can be checked at https://status.nixos.org/
Using
git+https://withshallow=1instead ofgithub:for slightly faster file extraction on large repositories like nixpkgs.nixpkgs.url = "git+https://github.com/nixos/nixpkgs?shallow=1&ref=nixos-unstable-small";
The commented-out line is a workaround for Renovate, which cannot parse certain flake input formats. See https://github.com/renovatebot/renovate/issues/29721
# "github:NixOS/nixpkgs/trick-renovate-into-working"
- nixpkgs-stable
Provides stable packages when unstable has build failures or regressions. Mainly used by the
stableoverlay (see overlays/configuration.org) for packages that are broken in unstable.nixpkgs-stable.url = "git+https://github.com/nixos/nixpkgs?shallow=1&ref=nixos-25.05";
- nixpkgs
- Flake Infrastructure
- flake-parts
https://github.com/hercules-ci/flake-parts
Simplify Nix Flakes with the module system
Framework for organizing flake outputs. Provides module system for flakes, making complex configurations more maintainable through separation of concerns.
flake-parts = { url = "github:hercules-ci/flake-parts"; inputs.nixpkgs-lib.follows = "nixpkgs"; };
- flake-parts
- Transitive Dependencies
- flake-utils
https://github.com/numtide/flake-utils
Pure Nix flake utility functions
Common flake utilities. Only used transitively via
followsto unify the flake-utils version across inputs that depend on it.flake-utils.url = "github:numtide/flake-utils";
- flake-utils
- System Configuration
- darwin
https://github.com/nix-darwin/nix-darwin
Manage your macOS using Nix
nix-darwin provides NixOS-style system configuration for macOS. Essential for managing macOS system settings, launchd services, and Homebrew declaratively.
darwin = { url = "github:nix-darwin/nix-darwin"; inputs.nixpkgs.follows = "nixpkgs"; }; - home-manager
https://github.com/nix-community/home-manager
Manage a user environment using Nix
User environment management. Manages dotfiles, user services, and per-user packages declaratively. The backbone of user-level configuration in this repository.
home-manager = { url = "github:nix-community/home-manager"; inputs.nixpkgs.follows = "nixpkgs"; }; - nixos-wsl
https://github.com/nix-community/nixos-wsl
NixOS on WSL
NixOS on Windows Subsystem for Linux. Provides NixOS experience within WSL2, useful for Windows machines that need Linux development environments.
nixos-wsl = { url = "github:nix-community/nixos-wsl"; inputs.flake-compat.follows = ""; inputs.nixpkgs.follows = "nixpkgs"; }; - nix-on-droid
https://github.com/nix-community/nix-on-droid
Nix-enabled environment for your Android device.
Nix environment for Android via Termux. Enables the same declarative configuration approach on mobile devices.
nix-on-droid = { url = "github:nix-community/nix-on-droid"; inputs.home-manager.follows = "home-manager"; inputs.nix-formatter-pack.follows = ""; inputs.nixpkgs-docs.follows = "nixpkgs"; inputs.nixpkgs-for-bootstrap.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs"; inputs.nmd.follows = ""; }; - disko
https://github.com/nix-community/disko
Declarative disk partitioning and formatting using nix
Used for reproducible NixOS installations with automated partition layout, filesystem creation, and encryption setup.
disko = { url = "github:nix-community/disko"; inputs.nixpkgs.follows = "nixpkgs"; }; - impermanence
https://github.com/nix-community/impermanence
Modules to help you handle persistent state on systems with ephemeral root storage
Manages stateful paths on systems with ephemeral root filesystems. Used with btrfs snapshots to ensure only explicitly declared state persists across reboots.
impermanence.url = "github:nix-community/impermanence";
- lanzaboote
https://github.com/nix-community/lanzaboote
Secure Boot for NixOS
Signs boot components with custom keys, enabling Secure Boot on NixOS machines.
lanzaboote = { url = "github:nix-community/lanzaboote"; inputs.nixpkgs.follows = "nixpkgs"; inputs.pre-commit.follows = "git-hooks"; }; - nixos-facter-modules
https://github.com/numtide/nixos-facter-modules
A series of NixOS modules to be used in conjunction with nixos-facter
Hardware detection for NixOS. Automatically generates hardware configuration based on detected hardware, simplifying initial system setup.
nixos-facter-modules.url = "github:numtide/nixos-facter-modules";
- darwin
- Infrastructure
- comin
https://github.com/nlewo/comin
GitOps For NixOS Machines
Automatically deploys configuration changes when pushed to the repository, enabling continuous deployment for servers without manual
nixos-rebuild switch.comin = { url = "github:nlewo/comin"; inputs.nixpkgs.follows = "nixpkgs"; }; - sops-nix
https://github.com/Mic92/sops-nix
Atomic secret provisioning for NixOS based on sops
Secrets management using Mozilla SOPS. Encrypts secrets in the repository that are decrypted at activation time using age keys.
sops-nix = { url = "github:Mic92/sops-nix"; inputs.nixpkgs.follows = "nixpkgs"; }; - tsnsrv
https://github.com/boinkor-net/tsnsrv
A reverse proxy that exposes services on your tailnet (as their own tailscale participants)
Tailscale service proxy. Exposes local services to the Tailscale network with automatic HTTPS certificates.
tsnsrv = { url = "github:boinkor-net/tsnsrv"; inputs.flake-parts.follows = "flake-parts"; inputs.nixpkgs.follows = "nixpkgs"; };
- comin
- Development Tools
- git-hooks
https://github.com/cachix/git-hooks.nix
Seamless integration of pre-commit.com git hooks with Nix.
Pre-commit hooks as Nix derivations. Ensures code quality checks run consistently across all development environments without requiring global tool installation.
Inputs that don't affect this flake are removed to prevent lockfile bloat.
git-hooks = { url = "github:cachix/git-hooks.nix"; inputs.flake-compat.follows = ""; inputs.gitignore.follows = ""; inputs.nixpkgs.follows = "nixpkgs"; }; - treefmt-nix
https://github.com/numtide/treefmt-nix
treefmt nix configuration
Unified code formatter configuration. Runs multiple formatters (nixfmt, shfmt, etc.) through a single interface, ensuring consistent formatting across the repository.
treefmt-nix = { url = "github:numtide/treefmt-nix"; inputs.nixpkgs.follows = "nixpkgs"; };
- git-hooks
- Desktop & Theming
- nix-colors
https://github.com/misterio77/nix-colors
Modules and schemes to make theming with Nix awesome.
Base16 color scheme framework for Nix. Provides consistent theming across applications through a single color scheme definition.
nix-colors = { url = "github:misterio77/nix-colors"; inputs.nixpkgs-lib.follows = "nixpkgs"; }; - nix-wallpaper
https://github.com/natsukium/nix-wallpaper
A configurable wallpaper for nix systems
Generates Nix logo wallpapers. Using a custom branch (
custom-logo) that supports additional logo variants.nix-wallpaper = { url = "github:natsukium/nix-wallpaper/custom-logo"; inputs.flake-utils.follows = "flake-utils"; inputs.nixpkgs.follows = "nixpkgs"; inputs.pre-commit-hooks.follows = "git-hooks"; };
- nix-colors
- Applications
- brew-nix
https://github.com/BatteredBunny/brew-nix
Experimental nix expression to package all MacOS casks from homebrew automatically
Provides Homebrew casks as Nix packages for darwin. Useful for proprietary macOS applications not available in nixpkgs.
The
brew-apiinput is marked as non-flake because it's just a data source (JSON API dump from Homebrew's API).brew-api = { url = "github:BatteredBunny/brew-api"; flake = false; }; brew-nix = { url = "github:BatteredBunny/brew-nix"; inputs.brew-api.follows = "brew-api"; inputs.nix-darwin.follows = "darwin"; inputs.nixpkgs.follows = "nixpkgs"; }; - claude-desktop
https://github.com/k3d3/claude-desktop-linux-flake
Nix Flake for Claude Desktop on Linux
Provides Claude Desktop for Linux. Using a community flake since Anthropic doesn't officially support Linux yet.
claude-desktop = { url = "github:k3d3/claude-desktop-linux-flake"; inputs.flake-utils.follows = "flake-utils"; inputs.nixpkgs.follows = "nixpkgs"; }; - edgepkgs
https://github.com/natsukium/edgepkgs
Personal repository for bleeding-edge packages. Contains packages not yet in nixpkgs, those requiring modifications, or packages that wouldn't be accepted upstream (e.g., niche or experimental software).
edgepkgs = { url = "github:natsukium/edgepkgs"; inputs.nixpkgs.follows = "nixpkgs"; }; - emacs-overlay
https://github.com/nix-community/emacs-overlay
Bleeding edge emacs overlay
Provides latest Emacs builds including native compilation and pure GTK variants. Also includes MELPA packages updated more frequently than nixpkgs. Mainly used for the utility that parses org files and automatically configures dependency packages.
emacs-overlay = { url = "github:nix-community/emacs-overlay"; inputs.nixpkgs-stable.follows = "nixpkgs-stable"; inputs.nixpkgs.follows = "nixpkgs"; }; - firefox-addons
https://gitlab.com/rycee/nur-expressions
A few Nix expressions suitable for inclusion in Nix User Repository
Firefox/browser extensions packaged for Nix. Allows declarative browser extension management through home-manager.
firefox-addons = { url = "gitlab:rycee/nur-expressions?dir=pkgs/firefox-addons"; inputs.nixpkgs.follows = "nixpkgs"; }; - mcp-servers
https://github.com/natsukium/mcp-servers-nix
A Nix-based configuration framework for Model Control Protocol (MCP) servers with ready-to-use packages.
Provides both a configuration framework and packaged MCP servers for Nix. Used with Claude Code and other MCP-compatible AI assistants.
mcp-servers = { url = "github:natsukium/mcp-servers-nix"; inputs.nixpkgs.follows = "nixpkgs"; }; - niri-flake
https://github.com/sodiboo/niri-flake
Nix-native configuration for niri
Niri is a scrollable-tiling Wayland compositor. This flake provides the compositor and related modules for NixOS/home-manager integration.
niri-flake = { url = "github:sodiboo/niri-flake"; inputs.niri-stable.follows = ""; inputs.niri-unstable.follows = ""; inputs.nixpkgs-stable.follows = "nixpkgs-stable"; inputs.nixpkgs.follows = "nixpkgs"; inputs.xwayland-satellite-stable.follows = ""; inputs.xwayland-satellite-unstable.follows = ""; }; - nur-packages
https://github.com/natsukium/nur-packages
Personal NUR (Nix User Repository). Contains packages maintained personally that are either too niche for nixpkgs or require customizations.
nur-packages = { url = "github:natsukium/nur-packages"; inputs.nixpkgs.follows = "nixpkgs"; }; - zen-browser
https://github.com/0xc000022070/zen-browser-flake
Community-driven Nix Flake for the Zen browser
Firefox-based browser focused on privacy. Community flake providing Nix packaging with home-manager integration.
zen-browser = { url = "github:0xc000022070/zen-browser-flake"; inputs.nixpkgs.follows = "nixpkgs"; inputs.home-manager.follows = "home-manager"; };
- brew-nix
3.1.2. Nix Config
Nix settings used by this flake. While these settings are already configured on all managed machines, documenting them here helps with initial setup and allows others to use this flake.
For detailed documentation on each setting, see https://nix.dev/manual/nix/latest/command-ref/conf-file.html
Note: flake.nix uses a restricted subset of the Nix language that prevents code reuse
(see https://github.com/NixOS/nix/issues/4945). The values below are currently hardcoded in
this section. Once machine configurations are migrated to org-mode, noweb references will
allow sharing these values across both the flake and machine-specific settings.
- Binary Caches
Binary cache (substituter) configuration for building this flake. While optional, configuring these caches significantly reduces build times by downloading pre-built binaries instead of compiling from source.
Using
extra-substitutersandextra-trusted-public-keysinstead ofsubstitutersandtrusted-public-keysensures this flake's cache configuration is additive rather than replacing the user's existing settings. This respects any caches the user has already configured in theirnix.confor system configuration.extra-substituters = [ "https://natsukium.cachix.org" "https://nix-community.cachix.org" ]; extra-trusted-public-keys = [ "natsukium.cachix.org-1:STD7ru7/5+KJX21m2yuDlgV6PnZP/v5VZWAJ8DZdMlI=" "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" ];
- nix-community.cachix.org
Community binary cache, primarily used for CUDA-related packages. Since November 2024, CUDA binaries are distributed under the nix-community namespace. Build status can be monitored at https://hydra.nix-community.org/project/nixpkgs
For more details, see https://discourse.nixos.org/t/cuda-cache-for-nix-community/56038
Alternatively, Flox's binary cache can be used for CUDA packages. As of September 2025, Flox has partnered with NVIDIA to obtain redistribution rights. See https://discourse.nixos.org/t/nix-flox-nvidia-opening-up-cuda-redistribution-on-nix/69189
- natsukium.cachix.org
Personal binary cache containing outputs from this flake. Packages not available in the official
cache.nixos.orgornix-community.cachix.orgare built on GitHub Actions and pushed here.
- nix-community.cachix.org
3.1.3. Rest of Flake
outputs =
{ self, flake-parts, ... }@inputs:
flake-parts.lib.mkFlake { inherit inputs; } {
systems = [
"x86_64-linux"
"aarch64-linux"
"aarch64-darwin"
];
imports = [
./flake-module.nix
inputs.git-hooks.flakeModule
inputs.treefmt-nix.flakeModule
];
hosts = {
# main laptop (m1 macbook air)
katavi = {
system = "aarch64-darwin";
};
# build server (m1 mac mini)
mikumi = {
system = "aarch64-darwin";
};
# laptop for work (m4 macbook pro)
work = {
system = "aarch64-darwin";
};
# main desktop (intel core i5-12400F)
kilimanjaro = {
system = "x86_64-linux";
};
# WSL (dualboot with kilimanjaro)
arusha = {
system = "x86_64-linux";
};
# main server (intel N100)
manyara = {
system = "x86_64-linux";
};
# build server (OCI A1 Flex)
serengeti = {
system = "aarch64-linux";
};
# build server (Ryzen 9 9950X)
tarangire = {
system = "x86_64-linux";
};
# phone (pixel 7a)
android = {
system = "aarch64-linux";
platform = "android";
};
};
flake = {
overlays = import ./overlays { inherit inputs; };
templates = import ./templates;
};
perSystem =
{
self',
config,
pkgs,
system,
...
}:
{
_module.args.pkgs = import self.inputs.nixpkgs {
inherit system;
config.allowUnfree = true;
overlays = [ self.inputs.nur-packages.overlays.default ] ++ builtins.attrValues self.overlays;
};
checks = import ./tests {
inherit (self.inputs) nixpkgs;
inherit pkgs;
};
packages = {
fastfetch = pkgs.callPackage ./pkgs/fastfetch { };
neovim = pkgs.callPackage ./pkgs/neovim-with-config { };
po4a_0_74 = (
pkgs.po4a.overrideAttrs (oldAttrs: {
version = "0.74";
src = pkgs.fetchurl {
url = "https://github.com/mquinson/po4a/releases/download/v0.74/po4a-0.74.tar.gz";
hash = "sha256-JfwyPyuje71Iw68Ov0mVJkSw5GgmH5hjPpEhmoOP58I=";
};
patches = [ ];
nativeBuildInputs = oldAttrs.nativeBuildInputs ++ [ pkgs.libxml2 ];
doCheck = false;
})
);
html =
with pkgs;
let
org-html-themes = fetchurl {
url = "https://raw.githubusercontent.com/fniessen/org-html-themes/b3898f4c5b09b3365fd93fd1566f46ecd0a8911f/org/theme-readtheorg.setup";
hash = "sha256-+5gy+S6NcuvlV61fudbCNoCKmSrCdA9P5CHeGKlDrSM=";
};
org-to-html = writeScript "org-to-html.el" ''
(require 'org)
(require 'htmlize)
(find-file "README.org")
(org-html-export-to-html)
(find-file "README.ja.org")
(org-html-export-to-html)
'';
in
stdenvNoCC.mkDerivation {
name = "dotfiles";
src = lib.cleanSource ./.;
postPatch = ''
substituteInPlace README.org \
--replace-fail "https://fniessen.github.io/org-html-themes/org/theme-readtheorg.setup" "${org-html-themes}"
'';
nativeBuildInputs = [
(emacs.pkgs.withPackages (epkgs: [ epkgs.htmlize ]))
gettext
self'.packages.po4a_0_74
];
buildPhase = ''
runHook preBuild
po4a po4a.cfg
emacs --batch -l ${org-to-html}
runHook postBuild
'';
installPhase = ''
runHook preInstall
install -Dm644 README.html $out/index.html
install -Dm644 README.ja.html $out/ja/index.html
runHook postInstall
'';
};
};
pre-commit = {
check.enable = true;
settings = {
src = ./.;
hooks = {
actionlint.enable = true;
biome.enable = true;
lua-ls.enable = false;
nil.enable = true;
shellcheck.enable = true;
treefmt.enable = true;
typos = {
enable = true;
excludes = [
"homes/shared/gpg/keys.txt"
"secrets.yaml"
"secrets/default.yaml"
"systems/nixos/tarangire/facter.json"
"systems/shared/hercules-ci/binary-caches.json"
];
settings.configPath = "typos.toml";
};
yamllint = {
enable = true;
excludes = [
"secrets/default.yaml"
"secrets.yaml"
];
settings.configData = "{rules: {document-start: {present: false}}}";
};
# Prefixed with "00-" to ensure this hook runs before all other hooks
# (hooks are sorted alphabetically when no explicit before/after is specified)
"00-check-org-tangle" = {
enable = true;
name = "check-org-tangle";
description = "Verify org files are tangled and synchronized";
entry =
let
checkScript = pkgs.writeShellScript "check-org-tangle" ''
set -euo pipefail
${pkgs.gnumake}/bin/make -B tangle
# Check for differences using git diff
changed=$(${pkgs.git}/bin/git diff --name-only)
if [ -n "$changed" ]; then
echo "Org files were out of sync and have been auto-tangled."
echo "Changed files:"
echo "$changed"
echo ""
echo "Please stage the changes and commit again:"
echo " git add $changed"
exit 1
fi
exit 0
'';
in
"${checkScript}";
files = "\\.org$";
pass_filenames = false;
};
};
};
};
treefmt = {
projectRootFile = "flake.nix";
programs = {
biome.enable = true;
nixfmt.enable = true;
shfmt.enable = true;
stylua.enable = true;
taplo.enable = true;
terraform.enable = true;
yamlfmt.enable = true;
};
};
devShells = {
default = pkgs.mkShell {
packages = with pkgs; [
gettext
nix-fast-build
self'.packages.po4a_0_74
sops
ssh-to-age
(terraform.withPlugins (p: [
p.carlpett_sops
p.cloudflare_cloudflare
p.determinatesystems_hydra
p.hashicorp_aws
p.hashicorp_external
p.hashicorp_null
p.integrations_github
p.oracle_oci
]))
];
shellHook = config.pre-commit.installationScript + ''
echo "Syncing CLAUDE.md..."
make CLAUDE.md >/dev/null 2>&1 || echo "Warning: Failed to generate CLAUDE.md"
'';
};
};
};
};
3.2. Overlays
3.2.1. Overview
This file defines nixpkgs overlays for patching broken packages, pinning specific versions, and adding local workarounds. Each overlay modifies the package set to address issues that would otherwise block the system build or cause runtime problems.
For details on overlay mechanics (final: prev: pattern, composition order, etc.),
see nixpkgs overlay documentation.
Overlays are organized into four categories based on their purpose and expected lifetime:
- stable: Packages fetched from nixpkgs-stable when broken in unstable and the fix would trigger excessive rebuilds or is too complex to patch locally.
- temporary-fix: Local overrides (e.g., disabling tests) that don't require a different nixpkgs version. Remove once fixed upstream.
- pre-release: Alpha, beta, or pre-release packages for testing before they land in nixpkgs.
- patches: Workarounds not suitable for upstream contribution (e.g., locale-specific fixes, local tooling shims). Expected to remain indefinitely.
{ inputs }:
{
stable = final: prev: {
inherit (inputs.nixpkgs-stable.legacyPackages.${final.stdenv.hostPlatform.system})
hercules-ci-agent
;
};
temporary-fix = final: prev: {
python313 = prev.python313.override {
packageOverrides = pyfinal: pyprev: {
rapidocr-onnxruntime = pyprev.rapidocr-onnxruntime.overridePythonAttrs (_: {
doCheck = false;
});
lxml-html-clean = pyprev.lxml-html-clean.overridePythonAttrs (_: {
doCheck = false;
});
};
};
};
pre-release = final: prev: { };
patches = final: prev: {
gh-dash =
(final.writeShellApplication {
name = "gh-dash";
text = ''
LANG=C.UTF-8 ${final.lib.getExe prev.gh-dash} "$@"
'';
}).overrideAttrs
{ pname = "gh-dash"; };
inherit (final.callPackage ../pkgs/mkShim { }) mkShim commandLineToolsShim;
};
}
- stable
Fetch packages from nixpkgs-stable when broken in unstable. This includes cases where the upstream fix would trigger excessive rebuilds, or where the issue is too complex to patch locally.
stable = final: prev: { inherit (inputs.nixpkgs-stable.legacyPackages.${final.stdenv.hostPlatform.system}) hercules-ci-agent ; };- hercules-ci-agent
Build is broken on darwin in nixpkgs-unstable due to a dependency issue. A fix is proposed in NixOS/nixpkgs#463879, but as of 2025-11-30, the PR targets the staging branch and is still under review.
Cherry-picking this fix locally isn't practical because the PR touches core darwin infrastructure, which would trigger rebuilds of numerous packages. Using the stable branch package avoids this rebuild cascade while we wait for the fix to land in master.
Remove this override once the PR is merged and propagates to the master branch.
hercules-ci-agent
- hercules-ci-agent
- temporary-fix
Local overrides for packages that build but have failing tests or minor issues. Unlike the
stableoverlay, these don't require fetching packages from a different nixpkgs branch. We simply override specific attributes (likedoCheck) on the existing packages. Remove these overrides once the issues are fixed upstream.temporary-fix = final: prev: { python313 = prev.python313.override { packageOverrides = pyfinal: pyprev: { rapidocr-onnxruntime = pyprev.rapidocr-onnxruntime.overridePythonAttrs (_: { doCheck = false; }); lxml-html-clean = pyprev.lxml-html-clean.overridePythonAttrs (_: { doCheck = false; }); }; }; };- Python313 package set
Override problematic Python packages using
packageOverrides.Python packages in nixpkgs form an interconnected dependency graph. The
packageOverridesmechanism ensures that when a package is overridden, all dependent packages automatically see the modified version. This is essential for consistency—a direct overlay override (e.g.,python313Packages.foo = ...) would only affect top-level access, leaving internal dependencies using the original broken version.See nixpkgs Python documentation for details.
python313 = prev.python313.override { packageOverrides = pyfinal: pyprev: { rapidocr-onnxruntime = pyprev.rapidocr-onnxruntime.overridePythonAttrs (_: { doCheck = false; }); lxml-html-clean = pyprev.lxml-html-clean.overridePythonAttrs (_: { doCheck = false; }); }; };- rapidocr-onnxruntime
The test suite causes a segmentation fault during execution. The root cause is still under investigation.
This package is pulled in as a transitive dependency. Runtime functionality has been verified to work correctly in actual use, so disabling the test suite is a safe workaround.
rapidocr-onnxruntime = pyprev.rapidocr-onnxruntime.overridePythonAttrs (_: { doCheck = false; }); - lxml-html-clean
Tests fail due to breaking changes in libxml2 2.14, which modified how certain DOM operations handle whitespace and entity encoding. These changes cause test assertions to fail even though the actual HTML cleaning functionality works correctly.
Tracked upstream in fedora-python/lxml_html_clean#24. Remove this override once the test suite is updated for libxml2 2.14 compatibility.
lxml-html-clean = pyprev.lxml-html-clean.overridePythonAttrs (_: { doCheck = false; });
- rapidocr-onnxruntime
- Python313 package set
- pre-release
Overlay for testing alpha, beta, or pre-release versions of packages before they land in nixpkgs. Useful for evaluating release candidates, nightly builds, or packages pending upstream review. Once a package is available in nixpkgs, remove it from this overlay.
pre-release = final: prev: { }; - patches
Workarounds that are not suitable for upstream contribution.
These patches address issues that upstream would likely not accept—either because they are specific to this configuration (e.g., locale settings), bypass intended behavior, or solve problems in unconventional ways. Unlike
temporary-fix, these are expected to remain indefinitely.patches = final: prev: { gh-dash = (final.writeShellApplication { name = "gh-dash"; text = '' LANG=C.UTF-8 ${final.lib.getExe prev.gh-dash} "$@" ''; }).overrideAttrs { pname = "gh-dash"; }; inherit (final.callPackage ../pkgs/mkShim { }) mkShim commandLineToolsShim; };- gh-dash
The preview pane renders incorrectly when
LANG=ja_JP.UTF-8is set. The issue stems from gh-dash's terminal width calculation, which miscounts the display width of certain UTF-8 characters (particularly CJK characters and some emoji). This causes text wrapping and alignment to break.Setting
LANG=C.UTF-8forces ASCII-compatible width calculations while preserving UTF-8 encoding support, which fixes the rendering issue. We usewriteShellApplicationto create a wrapper that sets this environment variable before invoking the real binary.Reported upstream in dlvhdr/gh-dash#316.
gh-dash = (final.writeShellApplication { name = "gh-dash"; text = '' LANG=C.UTF-8 ${final.lib.getExe prev.gh-dash} "$@" ''; }).overrideAttrs { pname = "gh-dash"; }; - mkShim
Shim utility for providing stub implementations of macOS Command Line Tools.
On darwin systems without Xcode Command Line Tools installed, invoking commands like
ccorpython3triggers an annoying system popup prompting installation. These shims intercept such calls and either delegate to Nix-provided tools or return appropriate exit codes, suppressing the popup and preventing spurious build failures.See pkgs/mkShim for the implementation details and list of shimmed commands.
inherit (final.callPackage ../pkgs/mkShim { }) mkShim commandLineToolsShim;
- gh-dash
3.3. Emacs
3.3.1. early-init.org
3.3.2. init.org
- basic
(set-face-attribute 'default nil :family "Liga HackGen Console NF" :height 140) (add-to-list 'default-frame-alist '(undecorated-round . t)) (use-package doom-themes :ensure t :config (load-theme 'doom-nord :no-confirm))Enable visual-line-mode globally instead of using auto-fill-mode here to preserve logical line structure while still wrapping long lines visually for better readability without modifying the actual file.
(visual-line-mode 1)
Highlight the cursor line.
(global-hl-line-mode 1)
- Darwin
macOSでは環境変数($PATH など)を読み込めないためexec-path-from-shellを使ったワークアランウドが必要。 emacs-plusではEmacsのInfo.plistにPATHを挿入しており、そのパッチを当てればこのパッケージは不要となるかもしれない。
(use-package exec-path-from-shell :ensure t :config (when (memq window-system '(mac ns x)) (exec-path-from-shell-initialize)))
- Darwin
- UI
- minibuffer
Referring to https://protesilaos.com/codelog/2024-11-28-basic-emacs-configuration/
(use-package vertico :ensure t :hook (after-init . vertico-mode))
(use-package marginalia :ensure t :hook (after-init . marginalia-mode))
(use-package orderless :ensure t :config (setq completion-styles '(orderless basic)) (setq completion-category-defaults nil) (setq completion-category-overrides nil))
The built-in savehist package keeps a record of user inputs and stores them across sessions. Thus, the user will always see their latest choices closer to the top (such as with M-x).
(use-package savehist :ensure nil ; it is built-in :hook (after-init . savehist-mode))
(use-package corfu :ensure t :hook (after-init . global-corfu-mode) :bind (:map corfu-map ("<tab>" . corfu-complete)) :config (setq tab-always-indent 'complete) (setq corfu-preview-current nil) (setq corfu-min-width 20) (setq corfu-popupinfo-delay '(1.25 . 0.5)) (corfu-popupinfo-mode 1) ; shows documentation after `corfu-popupinfo-delay' ;; Sort by input history (no need to modify `corfu-sort-function'). (with-eval-after-load 'savehist (corfu-history-mode 1) (add-to-list 'savehist-additional-variables 'corfu-history)))
- embark
(use-package embark :ensure t :bind (("C-." . embark-act) ;; pick some comfortable binding ("C-;" . embark-dwim) ;; good alternative: M-. ("C-h B" . embark-bindings)) ;; alternative for `describe-bindings' :init ;; Optionally replace the key help with a completing-read interface (setq prefix-help-command #'embark-prefix-help-command) ;; Show the Embark target at point via Eldoc. You may adjust the ;; Eldoc strategy, if you want to see the documentation from ;; multiple providers. Beware that using this can be a little ;; jarring since the message shown in the minibuffer can be more ;; than one line, causing the modeline to move up and down: ;; (add-hook 'eldoc-documentation-functions #'embark-eldoc-first-target) ;; (setq eldoc-documentation-strategy #'eldoc-documentation-compose-eagerly) ;; Add Embark to the mouse context menu. Also enable `context-menu-mode'. ;; (context-menu-mode 1) ;; (add-hook 'context-menu-functions #'embark-context-menu 100) :config ;; Hide the mode line of the Embark live/completions buffers (add-to-list 'display-buffer-alist '("\\`\\*Embark Collect \\(Live\\|Completions\\)\\*" nil (window-parameters (mode-line-format . none)))))
- embark
- version control system
- language support
- Markdown
https://github.com/jrblevin/markdown-mode
markdown-mode is a major mode for editing Markdown-formatted text.
(use-package markdown-mode :ensure t :mode ("README\\.md\\'" . gfm-mode) :init (setq markdown-command "multimarkdown") :bind (:map markdown-mode-map ("C-c C-e" . markdown-do)))
- Nix
https://github.com/NixOS/nix-mode
An Emacs major mode for editing Nix expressions.
(use-package nix-mode :ensure t :mode "\\.nix\\'")
- PO
po-mode is Emacs's major mode for editing GNU gettext PO (Portable Object) files. PO files store translations for software internationalization.
Editing PO files as plain text is error-prone because the format has strict requirements for escaping and structure. po-mode provides structured navigation between entries, automatic validation, and prevents common formatting errors.
- Common Operations
PO mode is not derived from text mode. The buffer is read-only and has its own keymap, so standard text editing commands do not work directly. Translations must be edited through the subedit buffer (
RET).- Main Commands
Commands for file operations, validation, and general PO mode management.
Key Function Description _po-undoUndo last modification qpo-confirm-and-quitQuit with confirmation ?hpo-helpShow help about PO mode Use or
qto quit instead ofC-x k(kill-buffer), as they properly handle unsaved changes and warn about untranslated entries.See Main PO mode Commands for more details.
- Entry Positioning
Commands for navigating between entries in the PO file.
Key Function Description npo-next-entryMove to next entry ppo-previous-entryMove to previous entry <po-first-entryMove to first entry >po-last-entryMove to last entry See Entry Positioning for more details.
- Modifying Translations
Commands for editing translation strings. Press
RETto open a subedit buffer where standard Emacs editing works normally.Key Function Description RETpo-edit-msgstrOpen subedit buffer for editing C-c C-cpo-subedit-exitFinish editing and apply changes C-c C-kpo-subedit-abortAbort editing and discard changes DELpo-fade-out-entryDelete the translation See Modifying Translations for more details.
- Main Commands
- Configuration
(use-package po-mode :ensure t)
The following configuration is based on Completing GNU gettext Installation.
This registers
.pofiles and files containing.po.in their name to automatically activate PO mode.(setq auto-mode-alist (cons '("\\.po\\'\\|\\.po\\." . po-mode) auto-mode-alist)) (autoload 'po-mode "po-mode" "Major mode for translators to edit PO files" t)
This enables automatic detection of the coding system for PO files, which allows Emacs to display international characters correctly.
(modify-coding-system-alist 'file "\\.po\\'\\|\\.po\\." 'po-find-file-coding-system) (autoload 'po-find-file-coding-system "po-mode")
- Common Operations
- Markdown
- org
- Semantic Line Breaks
Semantic Line Breaks (SemBr) is a writing convention where line breaks are placed at logical boundaries in sentences, such as after punctuation marks or between phrases. This makes diffs more meaningful in version control and improves readability without affecting the rendered output.
The recommended line length is around 80 characters. I set this as an upper limit in the editor to prevent lines from becoming unnecessarily long.
(add-hook 'text-mode-hook (lambda () (auto-fill-mode 1) (setq fill-column 80))) - org-capture
(global-set-key (kbd "C-c c") 'org-capture) (setq org-root "~/dropbox/org/") (setq org-capture-templates `(("t" "Todo" entry (file+headline ,(concat org-root "todo.org") "Tasks") "* TODO %?\n %i\n %a") ("j" "Journal" entry (file+olp+datetree ,(concat org-root "journal.org")) "* %U\n%?\n %i\n %a") ("f" "Fleeting" entry (file ,(concat org-root "fleeting.org")) "* %?\n %U\n %i\n %a")))
- org-agenda
(global-set-key (kbd "C-c a") 'org-agenda) (setq org-agenda-files '("~/dropbox/org"))
- org-roam
(use-package org-roam :ensure t :custom (org-roam-directory "~/dropbox/org-roam") (org-roam-db-location "~/.local/share/org-roam.db") :bind (("C-c n l" . org-roam-buffer-toggle) ("C-c n f" . org-roam-node-find) ("C-c n g" . org-roam-graph) ("C-c n i" . org-roam-node-insert) ("C-c n c" . org-roam-capture) ("C-c n j" . org-roam-dailies-capture-today)) :config (setq org-roam-capture-templates '(("p" "permanent" plain "%?" :target (file+head "permanent/${slug}.org" "#+title: ${title}\n") :unnarrowed t) ("l" "literature" plain "%?" :target (file+head "literature/${title}.org" "#+title: ${title}\n") :unnarrowed t))) (setq org-roam-node-display-template (concat "${title:*} " (propertize "${tags:10}" 'face 'org-tag))) (org-roam-db-autosync-mode) (require 'org-roam-protocol) )
- htmlize
Used when converting Org files to HTML with syntax highlighting for code blocks.
C-c C-e h hexports the current Org buffer to HTML.(use-package htmlize :ensure t)
- Semantic Line Breaks
- misc
- vundo
(use-package vundo :ensure t :bind (("C-x u" . vundo)) :config (setq vundo-glyph-alist vundo-unicode-symbols))
- consult
;; Example configuration for Consult (use-package consult :ensure t ;; Replace bindings. Lazily loaded by `use-package'. :bind (;; C-c bindings in `mode-specific-map' ("C-c M-x" . consult-mode-command) ("C-c h" . consult-history) ("C-c k" . consult-kmacro) ("C-c m" . consult-man) ("C-c i" . consult-info) ([remap Info-search] . consult-info) ;; C-x bindings in `ctl-x-map' ("C-x M-:" . consult-complex-command) ;; orig. repeat-complex-command ("C-x b" . consult-buffer) ;; orig. switch-to-buffer ("C-x 4 b" . consult-buffer-other-window) ;; orig. switch-to-buffer-other-window ("C-x 5 b" . consult-buffer-other-frame) ;; orig. switch-to-buffer-other-frame ("C-x t b" . consult-buffer-other-tab) ;; orig. switch-to-buffer-other-tab ("C-x r b" . consult-bookmark) ;; orig. bookmark-jump ("C-x p b" . consult-project-buffer) ;; orig. project-switch-to-buffer ;; Custom M-# bindings for fast register access ("M-#" . consult-register-load) ("M-'" . consult-register-store) ;; orig. abbrev-prefix-mark (unrelated) ("C-M-#" . consult-register) ;; Other custom bindings ("M-y" . consult-yank-pop) ;; orig. yank-pop ;; M-g bindings in `goto-map' ("M-g e" . consult-compile-error) ("M-g f" . consult-flymake) ;; Alternative: consult-flycheck ("M-g g" . consult-goto-line) ;; orig. goto-line ("M-g M-g" . consult-goto-line) ;; orig. goto-line ("M-g o" . consult-outline) ;; Alternative: consult-org-heading ("M-g m" . consult-mark) ("M-g k" . consult-global-mark) ("M-g i" . consult-imenu) ("M-g I" . consult-imenu-multi) ;; M-s bindings in `search-map' ("M-s d" . consult-find) ;; Alternative: consult-fd ("M-s c" . consult-locate) ("M-s g" . consult-grep) ("M-s G" . consult-git-grep) ("M-s r" . consult-ripgrep) ("M-s l" . consult-line) ("M-s L" . consult-line-multi) ("M-s k" . consult-keep-lines) ("M-s u" . consult-focus-lines) ;; Isearch integration ("M-s e" . consult-isearch-history) :map isearch-mode-map ("M-e" . consult-isearch-history) ;; orig. isearch-edit-string ("M-s e" . consult-isearch-history) ;; orig. isearch-edit-string ("M-s l" . consult-line) ;; needed by consult-line to detect isearch ("M-s L" . consult-line-multi) ;; needed by consult-line to detect isearch ;; Minibuffer history :map minibuffer-local-map ("M-s" . consult-history) ;; orig. next-matching-history-element ("M-r" . consult-history)) ;; orig. previous-matching-history-element ;; Enable automatic preview at point in the *Completions* buffer. This is ;; relevant when you use the default completion UI. :hook (completion-list-mode . consult-preview-at-point-mode) ;; The :init configuration is always executed (Not lazy) :init ;; Tweak the register preview for `consult-register-load', ;; `consult-register-store' and the built-in commands. This improves the ;; register formatting, adds thin separator lines, register sorting and hides ;; the window mode line. (advice-add #'register-preview :override #'consult-register-window) (setq register-preview-delay 0.5) ;; Use Consult to select xref locations with preview (setq xref-show-xrefs-function #'consult-xref xref-show-definitions-function #'consult-xref) ;; Configure other variables and modes in the :config section, ;; after lazily loading the package. :config ;; Optionally configure preview. The default value ;; is 'any, such that any key triggers the preview. ;; (setq consult-preview-key 'any) ;; (setq consult-preview-key "M-.") ;; (setq consult-preview-key '("S-<down>" "S-<up>")) ;; For some commands and buffer sources it is useful to configure the ;; :preview-key on a per-command basis using the `consult-customize' macro. (consult-customize consult-theme :preview-key '(:debounce 0.2 any) consult-ripgrep consult-git-grep consult-grep consult-man consult-bookmark consult-recent-file consult-xref consult--source-bookmark consult--source-file-register consult--source-recent-file consult--source-project-recent-file ;; :preview-key "M-." :preview-key '(:debounce 0.4 any)) ;; Optionally configure the narrowing key. ;; Both < and C-+ work reasonably well. (setq consult-narrow-key "<") ;; "C-+" ;; Optionally make narrowing help available in the minibuffer. ;; You may want to use `embark-prefix-help-command' or which-key instead. ;; (keymap-set consult-narrow-map (concat consult-narrow-key " ?") #'consult-narrow-help) )
;; Consult users will also want the embark-consult package. (use-package embark-consult :ensure t ; only need to install it, embark loads it after consult if found :hook (embark-collect-mode . consult-preview-at-point-mode))
- Others
(which-key-mode) (setq-default indent-tabs-mode nil) (require 'org-tempo) (org-babel-do-load-languages 'org-babel-load-languages '((shell . t))) (setq org-src-preserve-indentation t)
- project.el
Register all repositories cloned by ghq (https://github.com/x-motemen/ghq) as projects.
Specifically, directories under
~/src/$ACCOUNT/$VCS_HOST/$OWNER/$REPO.(defun my/sync-project-list () "Find all projects under ~/src and synchronize the project-list-file." (interactive) (let* (;; 1. Retrieve directory list as a string using find command (command (format "find %s -mindepth 4 -maxdepth 4 -type d" (expand-file-name "~/src"))) (dir-list-string (shell-command-to-string command)) ;; 2. Split string by newlines and exclude empty lines to create a list (dirs (split-string dir-list-string "\n" t))) ;; 3. Build file contents in a temporary buffer (with-temp-buffer (insert ";;; -*- lisp-data -*-\n") (insert "(\n") (dolist (dir dirs) (insert (format " (\"%s/\")\n" dir))) (insert ")\n") ;; 4. Write the built contents to file (write-file project-list-file)))) (my/sync-project-list)
- project.el
- vundo
4. Development
4.1. 翻訳
このプロジェクトでは翻訳にpo4aを使っています。
4.1.1. 必要なソフトウェア
- gettext
- po4a >= 0.74 (Org modeを扱うために必要)
4.1.2. 翻訳作業
- po4aを設定する
対象となる言語、生成するpoファイルを置くディレクトリ、それから翻訳対象のドキュメントを以下のように設定します。=-k 0=というオプションは翻訳が不完全な場合でも翻訳されたファイルを出力するものです。(デフォルトでは80%以上翻訳されているときのみ出力されます。)
[po4a_langs] ja [po4a_paths] po/dotfiles.pot $lang:po/$lang.po [type: org] README.org $lang:README.$lang.org opt:"-k 0" [type: org] configuration.org $lang:configuration.$lang.org opt:"-k 0" [type: org] applications/emacs/init.org $lang:applications/emacs/init.$lang.org opt:"-k 0" [type: org] applications/emacs/early-init.org $lang:applications/emacs/early-init.$lang.org opt:"-k 0"
=po4a.cfg=について、詳しくは=man po4a=を参照してください。
- poを生成/更新する
ドキュメントを更新したら、次のコマンドでpoファイルを更新する必要があります。このコマンドはテンプレート(pot)と各言語に対応したpoを=po4a.cfg=で設定したパスに生成します。
po4a --no-translations po4a.cfg
- 翻訳する
対象となる言語のpoをpoエディタで編集します。Emacsのpo-modeやpoedit、GNOMEのGtranslator、KDEのLokalizeが有名です。
- 翻訳ファイルを生成/更新する
翻訳が終わったら次のコマンドでファイルを生成します。このときpoも更新されるため、実運用上はこのコマンドを実行するだけで良いでしょう。
po4a po4a.cfg