lf: add module

Adds 'programs.lf', configuration managment for lf, a terminal file
manager.

PR #1174
This commit is contained in:
Owen McGrath 2020-04-18 13:22:09 -05:00 committed by Robert Helgesson
parent cb17f1ede2
commit 2f2a4396c6
No known key found for this signature in database
GPG key ID: 36BDAA14C2797E89
9 changed files with 383 additions and 0 deletions

3
.github/CODEOWNERS vendored
View file

@ -52,6 +52,9 @@
/modules/programs/lesspipe.nix @rycee
/modules/programs/lf.nix @owm111
/tests/modules/programs/lf @owm111
/modules/programs/lieer.nix @tadfisher
/modules/programs/lsd.nix @marsam

View file

@ -1474,6 +1474,13 @@ in
A new module is available: 'services.mako'
'';
}
{
time = "2020-04-23T19:45:26+00:00";
message = ''
A new module is available: 'programs.lf'
'';
}
];
};
}

View file

@ -76,6 +76,7 @@ let
(loadModule ./programs/keychain.nix { })
(loadModule ./programs/kitty.nix { })
(loadModule ./programs/lesspipe.nix { })
(loadModule ./programs/lf.nix { })
(loadModule ./programs/lsd.nix { })
(loadModule ./programs/man.nix { })
(loadModule ./programs/matplotlib.nix { })

219
modules/programs/lf.nix Normal file
View file

@ -0,0 +1,219 @@
{ 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.
<informaltable frame="none"><tgroup cols="1"><tbody>
${concatStringsSep "\n" (mapAttrsToList (n: v: ''
<row>
<entry><varname>${n}</varname></entry>
<entry>${v.description}</entry>
</row>
'') knownSettings)}
</tbody></tgroup></informaltable>
See the lf documentation for detailed descriptions of these options.
Note, use <varname>previewer</varname> to set lf's
<varname>previewer</varname> option, and
<varname>extraConfig</varname> 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 ''{ "<c-g>" = "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
<varname>previewer</varname> option.
'';
};
previewer.keybinding = mkOption {
type = with types; nullOr str;
default = null;
example = "i";
description = ''
Key to bind to the script at <varname>previewer.source</varname> 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}
'';
};
}

View file

@ -33,6 +33,7 @@ import nmt {
./modules/programs/git
./modules/programs/gpg
./modules/programs/kakoune
./modules/programs/lf
./modules/programs/lieer
./modules/programs/mbsync
./modules/programs/neomutt

View file

@ -0,0 +1,86 @@
{ config, lib, pkgs, ... }:
with lib;
let
pvScript = builtins.toFile "pv.sh" "cat $1";
expected = builtins.toFile "settings-expected" ''
set icons
set noignorecase
set ratios "2:2:3"
set tabstop 4
cmd added :echo "foo"
cmd multiline :{{
push gg
echo "bar"
push i
}}
cmd removed
map aa should-be-added
map ab
cmap <c-a> should-be-added
cmap <c-b>
set previewer ${pvScript}
map i ${"$"}${pvScript} "$f" | less -R
# More config...
'';
in {
config = {
programs.lf = {
enable = true;
cmdKeybindings = {
"<c-a>" = "should-be-added";
"<c-b>" = null;
};
commands = {
added = '':echo "foo"'';
removed = null;
multiline = ''
:{{
push gg
echo "bar"
push i
}}'';
};
extraConfig = ''
# More config...
'';
keybindings = {
aa = "should-be-added";
ab = null;
};
previewer = {
keybinding = "i";
source = pvScript;
};
settings = {
ignorecase = false;
icons = true;
tabstop = 4;
ratios = "2:2:3";
};
};
nixpkgs.overlays =
[ (self: super: { lf = pkgs.writeScriptBin "dummy-lf" ""; }) ];
nmt.script = ''
assertFileExists home-files/.config/lf/lfrc
assertFileContent home-files/.config/lf/lfrc ${expected}
'';
};
}

View file

@ -0,0 +1,5 @@
{
lf-all-options = ./all-options.nix;
lf-minimal-options = ./minimal-options.nix;
lf-no-pv-keybind = ./no-pv-keybind.nix;
}

View file

@ -0,0 +1,18 @@
{ config, lib, pkgs, ... }:
with lib;
let expected = builtins.toFile "settings-expected" "\n\n\n\n\n\n\n\n\n\n\n";
in {
config = {
programs.lf = { enable = true; };
nixpkgs.overlays =
[ (self: super: { lf = pkgs.writeScriptBin "dummy-lf" ""; }) ];
nmt.script = ''
assertFileExists home-files/.config/lf/lfrc
assertFileContent home-files/.config/lf/lfrc ${expected}
'';
};
}

View file

@ -0,0 +1,43 @@
{ config, lib, pkgs, ... }:
with lib;
let
pvScript = builtins.toFile "pv.sh" "cat $1";
expected = builtins.toFile "settings-expected" ''
set previewer ${pvScript}
# More config...
'';
in {
config = {
programs.lf = {
enable = true;
extraConfig = ''
# More config...
'';
previewer = { source = pvScript; };
};
nixpkgs.overlays =
[ (self: super: { lf = pkgs.writeScriptBin "dummy-lf" ""; }) ];
nmt.script = ''
assertFileExists home-files/.config/lf/lfrc
assertFileContent home-files/.config/lf/lfrc ${expected}
'';
};
}