Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Nix Chad

Project Website


nix-chad logo

An opinionated macOS setup focused on software development.

Features

Firefox

discoverable key mappings

After pressing ? key a window enumerating all contextual key mappings appears.

Neovim

programming/configuration languages support

nvim dhall example screenshot

languageactionscompletiondiagnosticsformattinghighlighting
bash
dhall
docker
GitHub Actions workflow
html
java
json
javascript
lua
markdown
nix
purescript
python
typescript
yaml

discoverable key mappings

After pressing \ key a window enumerating all key mappings appears. The same window shows when user starts but does not finish a key sequence which has some action assigned to it.

Prerequisites

Configuration

Initializing from a template

Run from a directory of your choice:

nix flake init --template github:mstream/nix-chad/main#default

Tweaking

Update any config entries to your liking, like in this example.

Applying

After any change to configuration, run from the directory where flake.nix file resides:

nix run .#switch

Warning

While it is easy to roll back unwanted/broken configuration by either reverting your configuration changes or using a different nix-chad flake revision, there are some classes of misconfigurations that are more difficult to undo.

One of them is one that results in an error during ZSH shell initialization. If that results in, e.g. PATH environmental variable not being properly set, you may lose easy access to your binaries.

In this situation, to recover back to working state, you may need to:

  • switch to Bash using an absolute binary path
  • use GUI tools (maybe enough to edit but not enough to rebuild Nix configuration)
  • set PATH environmental variable manually (requires knowledge about Nix)
  • install needed binaries without nix (an overkill just for recovery)
  • using absolute nix store paths (very fiddly)

None of these options are convenient and most of them require relatively broad administrative knowledge. Thus, after every switch, it is highly recommended to:

  • leave current shell session open
  • create a new one,
  • observe if initialization scripts do not produce any errors,
  • and if so, use the previous session to fix the issues

Updating

To stay up-to-date witch changes to Nix Chad, run periodically:

nix flake update

chad.browser.bookmarks

Browser bookmarks.

Type: (list of ((bookmark submodule) or (directory submodule))) or (attribute set of ((bookmark submodule) or (directory submodule))) convertible to it

Default: [ ]

Example:

[
  {
    bookmarks = [
      {
        keyword = "nixpkgs";
        name = "NixOS Search - Packages";
        tags = [
          "nix"
        ];
        url = "https://search.nixos.org/packages";
      }
    ];
    name = "Nix sites";
    toolbar = true;
  }
  {
    title = "Nix Chad";
    url = "https://github.com/mstream/nix-chad";
  }
]

Declared by:

chad.browser.extraExtensions

Additional Firefox extensions to be installed for the user.

Type: null or (function that evaluates to a(n) list of package)

Default: null

Example:

exts: with exts; [ grammarly ];

Declared by:

chad.editor.documentWidth

Ideal maximum document’s width measured in number of characters.

Type: signed integer

Default: 72

Declared by:

chad.editor.keyMappings.categorized.close.suffixes.currentBuffer

close the current buffer

Type: string

Default: "bc"

Declared by:

chad.editor.keyMappings.categorized.comment.suffixes.addEndOfLine

add at the end of line

Type: string

Default: "lA"

Declared by:

chad.editor.keyMappings.categorized.comment.suffixes.addLineAbove

add line above

Type: string

Default: "lO"

Declared by:

chad.editor.keyMappings.categorized.comment.suffixes.addLineBelow

add line below

Type: string

Default: "lo"

Declared by:

chad.editor.keyMappings.categorized.comment.suffixes.block

block operator-pending

Type: string

Default: "b"

Declared by:

chad.editor.keyMappings.categorized.comment.suffixes.line

line operator-pending

Type: string

Default: "l"

Declared by:

chad.editor.keyMappings.categorized.comment.suffixes.toggleBlock

toggle block

Type: string

Default: "tb"

Declared by:

chad.editor.keyMappings.categorized.comment.suffixes.toggleLine

toggle line

Type: string

Default: "tl"

Declared by:

chad.editor.keyMappings.categorized.debug.suffixes.toggleDiagnosticsWindow

toggle diagnostics window

Type: string

Default: "x"

Declared by:

chad.editor.keyMappings.categorized.find.suffixes.codeDefinitions

code definitions

Type: string

Default: "cd"

Declared by:

chad.editor.keyMappings.categorized.find.suffixes.codeImplementations

code implementations

Type: string

Default: "ci"

Declared by:

chad.editor.keyMappings.categorized.find.suffixes.codeReferences

code references

Type: string

Default: "cr"

Declared by:

chad.editor.keyMappings.categorized.find.suffixes.codeTypeDefinitions

code type definitions

Type: string

Default: "ct"

Declared by:

chad.editor.keyMappings.categorized.find.suffixes.files

files

Type: string

Default: "f"

Declared by:

chad.editor.keyMappings.categorized.find.suffixes.gitBranches

Git branches

Type: string

Default: "gb"

Declared by:

chad.editor.keyMappings.categorized.find.suffixes.gitCommits

Git commits

Type: string

Default: "gc"

Declared by:

chad.editor.keyMappings.categorized.find.suffixes.gitLocalChanges

Git local changes

Type: string

Default: "gl"

Declared by:

chad.editor.keyMappings.categorized.find.suffixes.gitStash

Git stashed changes

Type: string

Default: "gs"

Declared by:

chad.editor.keyMappings.categorized.find.suffixes.implementations

implementations

Type: string

Default: "i"

Declared by:

chad.editor.keyMappings.categorized.find.suffixes.vimBuffers

Vim buffers

Type: string

Default: "vb"

Declared by:

chad.editor.keyMappings.categorized.find.suffixes.vimCommands

Vim commands

Type: string

Default: "vc"

Declared by:

chad.editor.keyMappings.categorized.find.suffixes.vimHelp

Vim help topics

Type: string

Default: "vh"

Declared by:

chad.editor.keyMappings.categorized.find.suffixes.words

words across files

Type: string

Default: "w"

Declared by:

chad.editor.keyMappings.categorized.goTo.suffixes.declaration

declaration

Type: string

Default: "D"

Declared by:

chad.editor.keyMappings.categorized.goTo.suffixes.definition

definition

Type: string

Default: "d"

Declared by:

chad.editor.keyMappings.categorized.goTo.suffixes.implementation

implementation

Type: string

Default: "i"

Declared by:

chad.editor.keyMappings.categorized.goTo.suffixes.nextProblem

next problem

Type: string

Default: "]"

Declared by:

chad.editor.keyMappings.categorized.goTo.suffixes.previousProblem

previous problem

Type: string

Default: "["

Declared by:

chad.editor.keyMappings.categorized.refactor.suffixes.action

action

Type: string

Default: "a"

Declared by:

chad.editor.keyMappings.categorized.refactor.suffixes.format

format

Type: string

Default: "f"

Declared by:

chad.editor.keyMappings.categorized.refactor.suffixes.name

name

Type: string

Default: "n"

Declared by:

chad.editor.keyMappings.categorized.select.suffixes.decrement

decrement selection

Type: string

Default: "d"

Declared by:

chad.editor.keyMappings.categorized.select.suffixes.increment

increment selection

Type: string

Default: "i"

Declared by:

chad.editor.keyMappings.categorized.select.suffixes.initialize

initialize selection

Type: string

Default: "s"

Declared by:

chad.editor.keyMappings.uncategorized.cancel

Cancel current selection or mode

Type: string

Default: "<ESC>"

Declared by:

chad.editor.keyMappings.uncategorized.confirm

Confirm current selection

Type: string

Default: "<CR>"

Declared by:

chad.editor.keyMappings.uncategorized.moveToBottomWindow

Move to window on the bottom

Type: string

Default: "<C-j>"

Declared by:

chad.editor.keyMappings.uncategorized.moveToLeftWindow

Move to window on the left

Type: string

Default: "<C-h>"

Declared by:

chad.editor.keyMappings.uncategorized.moveToRightWindow

Move to window on the right

Type: string

Default: "<C-l>"

Declared by:

chad.editor.keyMappings.uncategorized.moveToTopWindow

Move to window on the top

Type: string

Default: "<C-k>"

Declared by:

chad.editor.keyMappings.uncategorized.scrollDown

Scroll content down (half a page)

Type: string

Default: "<C-d>"

Declared by:

chad.editor.keyMappings.uncategorized.scrollDownFullPage

Scroll content down (full page)

Type: string

Default: "<C-f>"

Declared by:

chad.editor.keyMappings.uncategorized.scrollUp

Scroll content up (half a page)

Type: string

Default: "<C-u>"

Declared by:

chad.editor.keyMappings.uncategorized.scrollUpFullPage

Scroll content up (full page)

Type: string

Default: "<C-b>"

Declared by:

chad.editor.keyMappings.uncategorized.selectNext

Select next item on a list

Type: string

Default: "<C-n>"

Declared by:

chad.editor.keyMappings.uncategorized.selectPrevious

Select previous item on a list

Type: string

Default: "<C-p>"

Declared by:

chad.editor.keyMappings.uncategorized.showKeyMappings

Show key mappings

Type: string

Default: "\\"

Declared by:

chad.editor.keyMappings.uncategorized.showSymbolInfo

Show information about the symbol under the cursor

Type: string

Default: "K"

Declared by:

chad.editor.keyMappings.uncategorized.switchToNextTab

switch to next tab

Type: string

Default: "<TAB>"

Declared by:

chad.editor.keyMappings.uncategorized.switchToPreviousTab

switch to previous tab

Type: string

Default: "<S-TAB>"

Declared by:

chad.editor.lineNumbering

Absolute: line numbers counted from the beginning of the document Relative: line numbers counted from the current cursor position

Type: one of “absolute”, “relative”

Default: "relative"

Declared by:

chad.editor.tabWidth

Tabulation width measured in number of characters.

Type: signed integer

Default: 2

Declared by:

chad.extraPackages

Additional nixpkgs packages to be accessible for the user.

Type: null or (function that evaluates to a(n) list of package)

Default: null

Example:

pkgs: with pkgs; [ cowsay ];

Declared by:

chad.fontSize

A desired font size in tools that have means to set it fixed.

Type: signed integer

Default: 12

Example: 16

Declared by:

chad.git.alternativeGitIdentities

Alternative Git identities for selected repositories.

Type: list of (submodule)

Default: [ ]

Example:

[
  {
    repositoryUrl = "git@github.com:somecompany/**";
    sshKeyPath = "~/.ssh/work_id_rsa";
    userEmail = "me@somecompany.com";
  }
]

Declared by:

chad.git.alternativeGitIdentities.*.repositoryUrl

Git repository URL.

Type: string

Declared by:

chad.git.alternativeGitIdentities.*.sshKeyPath

Path to a SSH private key.

Type: string

Declared by:

chad.git.alternativeGitIdentities.*.userEmail

Key.

Type: string

Declared by:

chad.gpg.defaultKey

An ID of a key to be used for GPG signing by default. This is expected to be different for individuals. The key is not part of this repository and has to be provided manually.

Type: null or string

Default: null

Example: "BE318F09150F6CB0724FFEC0319EE1D7FC029354"

Declared by:

chad.initialSetup

Should be enabled when the switch is run for the first time

Type: boolean

Default: false

Declared by:

chad.keyboard.disableKeyRepeat

Holding keys does not make characters being typed repeatedly.

Type: boolean

Default: true

Declared by:

chad.keyboard.remapCapsLock

Treat Caps Lock key as Escape key.

Type: boolean

Default: true

Declared by:

chad.keyboard.remapLeftArrow

Treat Left Arrow key as Right Control key.

Type: boolean

Default: false

Declared by:

chad.keyboard.shortcuts

A set of macOS desktop-level shortcuts.

Type: attribute set of (submodule) (read only)

Default:

{
  screenshot = {
    modifierKeys = [
      "command"
      "shift"
    ];
    otherKey = "S";
  };
}

Declared by:

chad.keyboard.shortcuts.<name>.modifierKeys

A list of modifier keys.

Type: list of (one of “command”, “control”, “option”, “shift”) (read only)

Example:

[
  "command"
  "shift"
]

Declared by:

chad.keyboard.shortcuts.<name>.otherKey

A non-modifier key.

Type: one of “0”, “1”, “2”, “3”, “4”, “5”, “6”, “7”, “8”, “9”, “A”, “B”, “C”, “D”, “E”, “F”, “G”, “H”, “I”, “J”, “K”, “L”, “M”, “N”, “O”, “P”, “Q”, “R”, “S”, “T”, “U”, “V”, “W”, “X”, “Y”, “Z” (read only)

Example: "S"

Declared by:

chad.manageWindows.enable

Keep windows occupy maximum available share of space on desktop. Uses own emulation of multiple desktops/spaces.

Type: boolean

Default: false

Declared by:

chad.manageWindows.exclusions

List of application names for which automatic window management should not be performed. It can be figured out using this command:

  yabai -m query --windows

Type: list of (submodule)

Default: [ ]

Example:

[
  {
    app = "^Discord$";
    title = ".*Dialog$";
  }
]

Declared by:

chad.manageWindows.exclusions.*.app

Regex for application name.

Type: string

Example: "^Discord$"

Declared by:

chad.manageWindows.exclusions.*.title

Regex for window title.

Type: string

Default: ".*"

Example: ".*Dialog$"

Declared by:

chad.mouse.naturalScrollDirection

Should content scroll opposite to the swipe/roll direction.

Type: boolean

Default: true

Declared by:

chad.software.openSourceOnly

Restricts software to Open Source only.

Type: boolean

Default: true

Declared by:

chad.terminal.abbreviations.enable

Enables expandable command abbreviations.

Type: boolean

Default: true

Declared by:

chad.terminal.abbreviations.extraAbbreviations

An attribute set that maps aliases (the top level attribute names in this option) to abbreviations. Abbreviations are expanded with the longer phrase after they are entered.

Type: attribute set of string

Default: { }

Example:

{
  gco = "git checkout";
  l = "less";
}

Declared by:

chad.terminal.keyBindings

Additional key bindings for terminal emulator.

Type: list of (submodule)

Default: [ ]

Example:

[
  {
    chars = "\\u000c";
    key = "K";
    mods = "Control";
  }
]

Declared by:

chad.terminal.keyBindings.*.chars

Substitution.

Type: string

Declared by:

chad.terminal.keyBindings.*.key

Key.

Type: string

Declared by:

chad.terminal.keyBindings.*.mods

Modifier key(s).

Type: string

Declared by:

chad.terminal.zshInitExtra

Additional initialization for ZSH sessions.

Type: strings concatenated with “\n”

Default: ""

Example:

''
  export VAR1=val1  
  export VAR2=val2
''

Declared by:

chad.user.email

User’s e-mail address.

Type: string

Example: "bob@example.com"

Declared by:

chad.user.homeDirectories

A list of desirect directories to be created in the home directory of the user. It is up to the user to provide the contents of these directories.

Type: list of string

Default: [ ]

Example:

[
  "Development/exercises"
  "Development/presentations"
  "Development/projects"
]

Declared by:

chad.user.name

User’s name.

Type: string

Example: "bob"

Declared by:

Terminal Workspace (Zellij)

Switch to Scroll mode - Esc

Switch to Search mode - Enter

Normal

Switch to Pane mode - Ctrl a

Switch to Scroll mode - Ctrl s

Switch to Tab mode - Ctrl t

Pane

Close currently focused pane - x

Move focus to a pane to the left - j

Move focus to a pane to the left - h

Move focus to a pane to the right - l

Move focus to a pane to the left - k

Create a new pane - n

Toggle frames rendering for panes - z

Toggle fullscreen mode of the focused pane - f

Scroll

Scroll down by half a page - d

Scroll up by half a page - u

Scroll down by a single line - j

Scroll up by a single line - k

Switch to Enter Search mode - s

Scroll down by half a page - d

Scroll up by half a page - u

Go to the next matched word - n

Go to the previous matched word - p

Toggle word match case sensitivity - c

Tab

Break the focused pane into a new tab - b

Close the current tab - x

Switch to tab under index of 1 - 1

Switch to tab under index of 2 - 2

Switch to tab under index of 3 - 3

Switch to tab under index of 4 - 4

Switch to tab under index of 5 - 5

Switch to tab under index of 6 - 6

Switch to tab under index of 7 - 7

Switch to tab under index of 8 - 8

Switch to tab under index of 9 - 9

Create a new tab - n

Switch between two most recently used tabs - Tab

Shared

Close currently focused pane - Alt x

Move focus to a pane to the left - Alt j

Move focus to a pane to the left - Alt h

Move focus to a pane to the right - Alt l

Move focus to a pane to the left - Alt k

Create a new pane - Alt n

Toggle frames rendering for panes - Alt z

Toggle fullscreen mode of the focused pane - Alt f

Editor (NeoVim)

Closing things

close the current buffer - <leader>xbc

Commenting things

add at the end of line - <leader>/lA

add line above - <leader>/lO

add line below - <leader>/lo

block operator-pending - <leader>/b

line operator-pending - <leader>/l

toggle block - <leader>/tb

toggle line - <leader>/tl

Debug code

toggle diagnostics window - <leader>dx

Finding things

code definitions - <leader>fcd

code implementations - <leader>fci

code references - <leader>fcr

code type definitions - <leader>fct

files - <leader>ff

Git branches - <leader>fgb

Git commits - <leader>fgc

Git local changes - <leader>fgl

Git stashed changes - <leader>fgs

implementations - <leader>fi

Vim buffers - <leader>fvb

Vim commands - <leader>fvc

Vim help topics - <leader>fvh

words across files - <leader>fw

Moving cursor to places

declaration - <leader>gD

definition - <leader>gd

implementation - <leader>gi

next problem - <leader>g]

previous problem - <leader>g[

Refactoring code

action - <leader>ra

format - <leader>rf

name - <leader>rn

Selecting text

decrement selection - <leader>sd

increment selection - <leader>si

initialize selection - <leader>ss

Miscellaneous

Cancel current selection or mode - <ESC>

Confirm current selection - <CR>

Move to window on the bottom - <C-j>

Move to window on the left - <C-h>

Move to window on the right - <C-l>

Move to window on the top - <C-k>

Scroll content down (half a page) - <C-d>

Scroll content down (full page) - <C-f>

Scroll content up (half a page) - <C-u>

Scroll content up (full page) - <C-b>

Select next item on a list - <C-n>

Select previous item on a list - <C-p>

Show key mappings - \

Show information about the symbol under the cursor - K

switch to next tab - <TAB>

switch to previous tab - <S-TAB>

For Developers

Flake inputs

Choosing version

Since this project uses flake-parts partitions module, flake inputs are stored separately per each partition. This introduces possibility of using different versions of inputs when evaluating different flake output attributes. This is possible even when inputs share a reference to the same branch. This is because commit revision is being resolved and stored in the repo at the time of running nix flake lock command, and this may happen at different times. In order to guarantee that they share the same versions, use these rules:

  1. If the input repository uses tags - use them.
  2. If the input repository does not use tags - use commit hashes.
  3. For nixpkgs use commit hashes from the branch which is appropriate for this project, namely nixpkgs-{NIXOS_RELEASE_VERSION}-darwin.
  4. For home-manager use commit hashes from the branch which corresponds to the nixpkgs version, namely release-${NIXOS_RELEASE_VERSION}.
  5. For nix-darwin use commit hashes from the branch which corresponds to the nixpkgs version, namely nix-darwin-${NIXOS_RELEASE_VERSION}.
  6. For nixvim use commit hashes from the branch which corresponds to the nixpkgs version, namely nixos-${NIXOS_RELEASE_VERSION}.

Control version of transitive dependencies

For each input of a flake type, identify its dependencies, define them as this project's inputs and make them being used by the input with the help of inputs.{NAME_OF_TRANSITIVE_INPUT}.follows property.

Chad Library

attribute sets

lib.attrsets.generate

Generate an attribute set from a list of values

Example

generate ["a" "b" "c"] (v: {"${v}1"=v;"${v}2"=v;})
=>
{a1="a";a2="a";b1="b";b2="b";c1="c";c2="c";}

Type

generate :: [Any] -> (Any -> AttrSet) -> AttrSet

Arguments

values : List of values

generator : A function transforming a single value into an attribute set

lib.attrsets.merge

Deep merge two attribute sets

Example

merge {a="a";c={c1="c1";}} {b="b";c={c2="c2";}}
=>
{a="a";b="b";c={c1="c1";c2="c2";}}

Type

merge :: AttrSet -> AttrSet -> AttrSet

Arguments

left : Left attribute set

right : Right attribute set

bash code generation helpers

lib.bash.catchErrorExec

Generate bash code which executes a sequence of commands and stores their standard output and return code in cmd_out and cmd_ret variables.

Example

catchErrorExec ["foo" "bar" "baz"]
=>
"set +e;cmd_out=$(foo bar baz 2>&1);cmd_ret=$?;set -e"

Type

catchErrorExec :: [String] -> String

Arguments

commands : List of commands to be executed

lib.bash.command

Generate bash code representing program invocation command

Example

command {flags=["foo"];parameters={bar="baz";};program="qux";}
=>
"qux --foo --bar baz"

Type

options :: AttrSet -> String

Arguments

config : Configuration including flags and parameters and program path

lib.bash.echoError

Generate bash code printing a message into standard error stream

Example

echoError "foo bar"
=>
"echo \"foo bar\" >&2"

Type

echoError :: String -> String

Arguments

message : Message to be printed

lib.bash.matchPattern

Generate bash code which matches a text against a pattern

Example

matchPattern {pattern="a([[:lower:]])c?";text="ab";}
=>
"[p \"ab\" =~ a([[:lower:]])c? ]]"

Type

echoError :: AttrSet -> String

Arguments

config : Configuration including pattern and text

lib.bash.options

Generate bash code representing command options

Example

options {flags=["foo"];parameters={bar="baz";};}
=>
"--foo --bar baz"

Type

options :: AttrSet -> String

Arguments

config : Configuration including flags and parameters

various constants

enumerations

functions

KDL file format utils

lib.kdl.key

Generate a key with given name and arguments

Example

key {name="foo";args=["bar" 123];}
=>
"foo \"bar\" 123"

Type

key :: AttrSet -> String

Arguments

config : Config containing name and arguments

lists manipulation

lua code generation helpers

markdown code generation helpers

nix CLI bash command generation helpers

macOS keyboard shortcuts configuration support

strings manipulation

lib.strings.camelToKebabCase

Convert camel-case string to kebab-case string

Example

camelToKebabCase "fooBar"
=>
"foo-bar"

Type

camelToKebabCase :: String -> String

Arguments

input : Input string

lib.strings.camelToSnakeCase

Convert camel-case string to snake-case string

Example

camelToSnakeCase "fooBar"
=>
"foo_bar"

Type

camelToSnakeCase :: String -> String

Arguments

input : Input string