devenv.nix
1# devkit — shared devenv module: personal tools + the customized interactive
2# bash environment.
3#
4# Consumers import this from their devenv.yaml:
5#
6# inputs:
7# devkit:
8# url: path:../devkit # or git+https://git.kilimanjaro.io/devenv-base
9# flake: false
10# # devenv#2205: an imported input's devenv.yaml is NOT evaluated, so each
11# # consumer must declare the tool inputs its own config here.
12# bug: { url: git+https://git.kilimanjaro.io/bug }
13# local-code-review: { url: git+https://git.kilimanjaro.io/local-code-review }
14# secrets: { url: git+https://git.kilimanjaro.io/secrets }
15# imports:
16# - devkit
17#
18# Each tool is added automatically when its input is declared. Disable one with
19# e.g. `devkit.bug.enable = false` (a project that ships its own wrapper).
20#
21# Changes to this file are picked up on the next `devenv shell` (path inputs,
22# devenv 2.2+). Once promoted to a git input, consumers pull them with
23# `devenv update devkit`.
24{ pkgs, lib, config, inputs, ... }:
25
26let
27 cfg = config.devkit;
28 hasInput = name: lib.hasAttr name inputs;
29in
30
31{
32 options.devkit = {
33 enable = lib.mkOption {
34 type = lib.types.bool;
35 default = true;
36 description = "Add the devkit toolchain and customized bash environment.";
37 };
38 bug.enable = lib.mkOption {
39 type = lib.types.bool;
40 default = hasInput "bug";
41 description = "Add the `bug` CLI (set false if the project ships its own wrapper).";
42 };
43 local-code-review.enable = lib.mkOption {
44 type = lib.types.bool;
45 default = hasInput "local-code-review";
46 description = "Add the `lcr` CLI.";
47 };
48 secrets.enable = lib.mkOption {
49 type = lib.types.bool;
50 default = hasInput "secrets";
51 description = "Add the `secrets` CLI.";
52 };
53 };
54
55 config = lib.mkIf cfg.enable {
56 packages = [
57 # toolchain the interactive bash environment needs
58 pkgs.bash
59 pkgs.bash-completion
60 pkgs.bashInteractive
61 pkgs.jujutsu
62 ]
63 # tools; the inputs are declared by the consumer (see header), so only add
64 # each one when it is present and not explicitly disabled.
65 ++ lib.optional cfg.bug.enable (inputs.bug.packages.${pkgs.system}.bug)
66 ++ lib.optional cfg.local-code-review.enable (inputs.local-code-review.packages.${pkgs.system}.default)
67 ++ lib.optional cfg.secrets.enable (inputs.secrets.packages.${pkgs.system}.default);
68
69 # The customized bash environment. It is `types.lines`, so each project's
70 # own enterShell is concatenated onto this.
71 enterShell = ''
72 # Interactive shells only: `devenv shell -- <cmd>` has no line editing,
73 # and bind warns there.
74 if [[ $- == *i* ]]; then
75 # Configure bash with fish-like features
76 bind 'set completion-ignore-case on' # Case-insensitive completion
77 bind 'set show-all-if-ambiguous on' # Show all completions on first tab
78 bind 'set menu-complete-display-prefix on'
79 bind 'TAB:menu-complete' # Tab cycles through completions
80 bind '"\e[A":history-search-backward' # Up arrow searches history
81 bind '"\e[B":history-search-forward' # Down arrow searches history
82 bind 'set colored-completion-prefix on' # Color the completion prefix
83 bind 'set colored-stats on' # Color the completion stats
84
85 # Enable bash-completion if available
86 if [ -f ${pkgs.bash-completion}/etc/profile.d/bash_completion.sh ]; then
87 source ${pkgs.bash-completion}/etc/profile.d/bash_completion.sh
88 fi
89
90 # Better directory navigation
91 shopt -s autocd 2>/dev/null # Type directory name to cd
92 shopt -s dirspell 2>/dev/null # Correct spelling of dir names
93 shopt -s cdspell 2>/dev/null # Correct spelling of cd args
94
95 # Enable ** globbing for recursive directory matching
96 shopt -s globstar 2>/dev/null
97 fi
98 '';
99 };
100}