yep, more dotfiles
1{ config 2, lib 3, pkgs 4, ... 5}: 6 7let 8 cfg = config.programs.xcompose; 9in 10{ 11 options.programs.xcompose = with lib; { 12 enable = mkEnableOption "XCompose keyboard configuration"; 13 14 loadConfigInEnv = mkOption { 15 description = '' 16 Load the XCompose file by passing the `XCOMPOSEFILE` environment variable instead of linking to ~/.XCompose. 17 18 That is nice to avoid cluttering the HOME directory, it's preferable to disable it when experimenting 19 with your compose config to reload faster than having to reload your VM 20 ''; 21 default = true; 22 type = types.bool; 23 }; 24 25 includeLocaleCompose = mkOption { 26 description = "Whether to include the base libX11 locale compose file"; 27 default = false; 28 type = types.bool; 29 }; 30 31 sequences = mkOption { 32 description = '' 33 Shapeless tree of macros 34 - Keys name can be easily found with wev (or xev) 35 - https://www.compart.com/en/unicode Lists all Unicode characters 36 ''; 37 default = { }; 38 example = { 39 Multi_key = { 40 "g" = { 41 a = "α"; 42 b = "β"; 43 }; 44 }; 45 }; 46 type = types.anything; 47 }; 48 49 extraConfig = mkOption { 50 description = '' 51 Unmanaged xcompose sequences and directives 52 ''; 53 default = ""; 54 example = '' 55 <Multi_key> <Multi_key> <a> <5> : "٥" 56 ''; 57 type = types.lines; 58 }; 59 }; 60 61 config = 62 with lib; 63 let 64 comboListToString = foldl (acc: val: acc + "<${val}> ") ""; 65 sanitizeComboResult = escape [ ''"'' ]; 66 67 comboSetToList = ip: flatten (mapAttrsToList 68 (name: value: 69 if isAttrs value then 70 let vs = comboSetToList value; 71 in 72 map ({ combo, value }: { combo = [ name ] ++ combo; inherit value; }) vs 73 else if isString value then 74 { combo = [ name ]; inherit value; } 75 else throw "combo value must be a string" 76 ) 77 ip); 78 complexListToSimple = map ({ combo, value }: { combo = comboListToString combo; value = sanitizeComboResult value; }); 79 toComposeFile = foldl (acc: val: acc + "${val.combo}: \"${val.value}\"\n") ""; 80 81 processComposeSet = set: toComposeFile (complexListToSimple (comboSetToList set)); 82 83 # TODO: see if include changes if put after compose declarations 84 composeFile = pkgs.writeText "XCompose" '' 85 ${optionalString cfg.includeLocaleCompose "include \"%L\""} 86 ${processComposeSet cfg.sequences} 87 ${cfg.extraConfig} 88 ''; 89 in 90 mkIf cfg.enable { 91 home.sessionVariables = mkIf cfg.loadConfigInEnv { XCOMPOSEFILE = composeFile; }; 92 home.file = mkIf (!cfg.loadConfigInEnv) { ".XCompose".source = composeFile; }; 93 }; 94}