{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.programs.lf;
knownSettings = {
anchorfind = types.bool;
color256 = types.bool;
dircounts = types.bool;
dirfirst = types.bool;
drawbox = types.bool;
globsearch = types.bool;
icons = types.bool;
hidden = types.bool;
ignorecase = types.bool;
ignoredia = types.bool;
incsearch = types.bool;
preview = types.bool;
reverse = types.bool;
smartcase = types.bool;
smartdia = types.bool;
wrapscan = types.bool;
wrapscroll = types.bool;
number = types.bool;
relativenumber = types.bool;
findlen = types.int;
period = types.int;
scrolloff = types.int;
tabstop = types.int;
errorfmt = types.str;
filesep = types.str;
ifs = types.str;
promptfmt = types.str;
shell = types.str;
sortby = types.str;
timefmt = types.str;
ratios = types.str;
info = types.str;
shellopts = types.str;
};
lfSettingsType = types.submodule {
options = let
opt = name: type:
mkOption {
type = types.nullOr type;
default = null;
visible = false;
};
in mapAttrs opt knownSettings;
};
in {
meta.maintainers = [{ github = "owm111"; }];
options = {
programs.lf = {
enable = mkEnableOption "lf";
settings = mkOption {
type = lfSettingsType;
default = { };
example = {
tabstop = 4;
number = true;
ratios = "1:1:2";
};
description = ''
An attribute set of lf settings. The attribute names and corresponding
values must be among the following supported options.
${concatStringsSep "\n" (mapAttrsToList (n: v: ''
${n}
${v.description}
'') knownSettings)}
See the lf documentation for detailed descriptions of these options.
Note, use previewer to set lf's
previewer option, and
extraConfig for any other option not listed above.
All string options are quoted with double quotes.
'';
};
commands = mkOption {
type = with types; attrsOf (nullOr str);
default = { };
example = {
get-mime-type = ''%xdg-mime query filetype "$f"'';
open = "$$OPENER $f";
};
description = ''
Commands to declare. Commands set to null or an empty string are
deleted.
'';
};
keybindings = mkOption {
type = with types; attrsOf (nullOr str);
default = { };
example = {
gh = "cd ~";
D = "trash";
i = "$less $f";
U = "!du -sh";
gg = null;
};
description =
"Keys to bind. Keys set to null or an empty string are deleted.";
};
cmdKeybindings = mkOption {
type = with types; attrsOf (nullOr str);
default = { };
example = literalExample ''{ "" = "cmd-escape"; }'';
description = ''
Keys to bind to command line commands which can only be one of the
builtin commands. Keys set to null or an empty string are deleted.
'';
};
previewer.source = mkOption {
type = with types; nullOr path;
default = null;
example = literalExample ''
pkgs.writeShellScript "pv.sh" '''
#!/bin/sh
case "$1" in
*.tar*) tar tf "$1";;
*.zip) unzip -l "$1";;
*.rar) unrar l "$1";;
*.7z) 7z l "$1";;
*.pdf) pdftotext "$1" -;;
*) highlight -O ansi "$1" || cat "$1";;
esac
'''
'';
description = ''
Script or executable to use to preview files. Sets lf's
previewer option.
'';
};
previewer.keybinding = mkOption {
type = with types; nullOr str;
default = null;
example = "i";
description = ''
Key to bind to the script at previewer.source and
pipe through less. Setting to null will not bind any key.
'';
};
extraConfig = mkOption {
type = types.lines;
default = "";
example = ''
$mkdir -p ~/.trash
'';
description = "Custom lfrc lines.";
};
};
};
config = mkIf cfg.enable {
home.packages = [ pkgs.lf ];
xdg.configFile."lf/lfrc".text = let
fmtSetting = k: v:
optionalString (v != null) "set ${
if isBool v then
"${optionalString (!v) "no"}${k}"
else
"${k} ${if isInt v then toString v else ''"${v}"''}"
}";
settingsStr = concatStringsSep "\n" (filter (x: x != "")
(mapAttrsToList fmtSetting
(builtins.intersectAttrs knownSettings cfg.settings)));
fmtCmdMap = before: k: v:
"${before} ${k}${optionalString (v != null && v != "") " ${v}"}";
fmtCmd = fmtCmdMap "cmd";
fmtMap = fmtCmdMap "map";
fmtCmap = fmtCmdMap "cmap";
commandsStr = concatStringsSep "\n" (mapAttrsToList fmtCmd cfg.commands);
keybindingsStr =
concatStringsSep "\n" (mapAttrsToList fmtMap cfg.keybindings);
cmdKeybindingsStr =
concatStringsSep "\n" (mapAttrsToList fmtCmap cfg.cmdKeybindings);
previewerStr = optionalString (cfg.previewer.source != null) ''
set previewer ${cfg.previewer.source}
${optionalString (cfg.previewer.keybinding != null) ''
map ${cfg.previewer.keybinding} ''$${cfg.previewer.source} "$f" | less -R
''}
'';
in ''
${settingsStr}
${commandsStr}
${keybindingsStr}
${cmdKeybindingsStr}
${previewerStr}
${cfg.extraConfig}
'';
};
}