diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 1241b106c..e8ea43178 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -92,6 +92,9 @@
/modules/programs/go.nix @rvolosatovs
+/modules/programs/helix.nix @Philipp-M
+/tests/modules/programs/helix @Philipp-M
+
/modules/programs/hexchat.nix @thiagokokada
/tests/modules/programs/hexchat @thiagokokada
diff --git a/modules/lib/maintainers.nix b/modules/lib/maintainers.nix
index 105edf073..2ed3a8462 100644
--- a/modules/lib/maintainers.nix
+++ b/modules/lib/maintainers.nix
@@ -169,4 +169,10 @@
github = "pltanton";
githubId = 4561823;
};
+ Philipp-M = {
+ email = "philipp@mildenberger.me";
+ github = "Philipp-M";
+ githubId = 9267430;
+ name = "Philipp Mildenberger";
+ };
}
diff --git a/modules/misc/news.nix b/modules/misc/news.nix
index c7ee326c5..2fb665fe7 100644
--- a/modules/misc/news.nix
+++ b/modules/misc/news.nix
@@ -2351,6 +2351,13 @@ in
A new module is available: 'programs.sagemath'.
'';
}
+
+ {
+ time = "2022-01-22T14:36:25+00:00";
+ message = ''
+ A new module is available: 'programs.helix'.
+ '';
+ }
];
};
}
diff --git a/modules/modules.nix b/modules/modules.nix
index 2b2f78790..3cd72e2bb 100644
--- a/modules/modules.nix
+++ b/modules/modules.nix
@@ -72,6 +72,7 @@ let
./programs/gnome-terminal.nix
./programs/go.nix
./programs/gpg.nix
+ ./programs/helix.nix
./programs/hexchat.nix
./programs/himalaya.nix
./programs/home-manager.nix
diff --git a/modules/programs/helix.nix b/modules/programs/helix.nix
new file mode 100644
index 000000000..9d06b65c8
--- /dev/null
+++ b/modules/programs/helix.nix
@@ -0,0 +1,151 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.programs.helix;
+ tomlFormat = pkgs.formats.toml { };
+in {
+ meta.maintainers = [ hm.maintainers.Philipp-M ];
+
+ options.programs.helix = {
+ enable = mkEnableOption "helix text editor";
+
+ package = mkOption {
+ type = types.package;
+ default = pkgs.helix;
+ defaultText = literalExpression "pkgs.helix";
+ description = "The package to use for helix.";
+ };
+
+ settings = mkOption {
+ type = tomlFormat.type;
+ default = { };
+ example = literalExpression ''
+ {
+ theme = "base16";
+ lsp.display-messages = true;
+ keys.normal = {
+ space.space = "file_picker";
+ space.w = ":w";
+ space.q = ":q";
+ };
+ }
+ '';
+ description = ''
+ Configuration written to
+ $XDG_CONFIG_HOME/helix/config.toml.
+
+ See
+ for the full list of options.
+ '';
+ };
+
+ languages = mkOption {
+ type = types.listOf tomlFormat.type;
+ default = [ ];
+ example = [{
+ name = "rust";
+ auto-format = false;
+ }];
+ description = ''
+ Language specific configuration at
+ $XDG_CONFIG_HOME/helix/languages.toml.
+
+ See
+ for more information.
+ '';
+ };
+
+ themes = mkOption {
+ type = types.attrsOf tomlFormat.type;
+ default = { };
+ example = literalExpression ''
+ {
+ base16 = let
+ transparent = "none";
+ gray = "#665c54";
+ dark-gray = "#3c3836";
+ white = "#fbf1c7";
+ black = "#282828";
+ red = "#fb4934";
+ green = "#b8bb26";
+ yellow = "#fabd2f";
+ orange = "#fe8019";
+ blue = "#83a598";
+ magenta = "#d3869b";
+ cyan = "#8ec07c";
+ in {
+ "ui.menu" = transparent;
+ "ui.menu.selected" = { modifiers = [ "reversed" ]; };
+ "ui.linenr" = { fg = gray; bg = dark-gray; };
+ "ui.popup" = { modifiers = [ "reversed" ]; };
+ "ui.linenr.selected" = { fg = white; bg = black; modifiers = [ "bold" ]; };
+ "ui.selection" = { fg = black; bg = blue; };
+ "ui.selection.primary" = { modifiers = [ "reversed" ]; };
+ "comment" = { fg = gray; };
+ "ui.statusline" = { fg = white; bg = dark-gray; };
+ "ui.statusline.inactive" = { fg = dark-gray; bg = white; };
+ "ui.help" = { fg = dark-gray; bg = white; };
+ "ui.cursor" = { modifiers = [ "reversed" ]; };
+ "variable" = red;
+ "variable.builtin" = orange;
+ "constant.numeric" = orange;
+ "constant" = orange;
+ "attributes" = yellow;
+ "type" = yellow;
+ "ui.cursor.match" = { fg = yellow; modifiers = [ "underlined" ]; };
+ "string" = green;
+ "variable.other.member" = red;
+ "constant.character.escape" = cyan;
+ "function" = blue;
+ "constructor" = blue;
+ "special" = blue;
+ "keyword" = magenta;
+ "label" = magenta;
+ "namespace" = blue;
+ "diff.plus" = green;
+ "diff.delta" = yellow;
+ "diff.minus" = red;
+ "diagnostic" = { modifiers = [ "underlined" ]; };
+ "ui.gutter" = { bg = black; };
+ "info" = blue;
+ "hint" = dark-gray;
+ "debug" = dark-gray;
+ "warning" = yellow;
+ "error" = red;
+ };
+ }
+ '';
+ description = ''
+ Each theme is written to
+ $XDG_CONFIG_HOME/helix/themes/theme-name.toml.
+ Where the name of each attribute is the theme-name (in the example "base16").
+
+ See
+ for the full list of options.
+ '';
+ };
+ };
+
+ config = mkIf cfg.enable {
+ home.packages = [ cfg.package ];
+
+ xdg.configFile = let
+ settings = {
+ "helix/config.toml" = mkIf (cfg.settings != { }) {
+ source = tomlFormat.generate "helix-config" cfg.settings;
+ };
+ "helix/languages.toml" = mkIf (cfg.languages != [ ]) {
+ source =
+ tomlFormat.generate "helix-config" { language = cfg.languages; };
+ };
+ };
+
+ themes = (mapAttrs' (n: v:
+ nameValuePair "helix/themes/${n}.toml" {
+ source = tomlFormat.generate "helix-theme-${n}" v;
+ }) cfg.themes);
+ in settings // themes;
+ };
+}
diff --git a/tests/default.nix b/tests/default.nix
index 89361a29c..1bd8ff297 100644
--- a/tests/default.nix
+++ b/tests/default.nix
@@ -64,6 +64,7 @@ import nmt {
./modules/programs/gh
./modules/programs/git
./modules/programs/gpg
+ ./modules/programs/helix
./modules/programs/himalaya
./modules/programs/htop
./modules/programs/i3status
diff --git a/tests/modules/programs/helix/default.nix b/tests/modules/programs/helix/default.nix
new file mode 100644
index 000000000..77172c708
--- /dev/null
+++ b/tests/modules/programs/helix/default.nix
@@ -0,0 +1 @@
+{ helix-example-settings = ./example-settings.nix; }
diff --git a/tests/modules/programs/helix/example-settings.nix b/tests/modules/programs/helix/example-settings.nix
new file mode 100644
index 000000000..ed0b4713b
--- /dev/null
+++ b/tests/modules/programs/helix/example-settings.nix
@@ -0,0 +1,118 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ config = {
+ programs.helix = {
+ enable = true;
+
+ settings = {
+ theme = "base16";
+ lsp.display-messages = true;
+ keys.normal = {
+ space.space = "file_picker";
+ space.w = ":w";
+ space.q = ":q";
+ };
+ };
+
+ languages = [{
+ name = "rust";
+ auto-format = false;
+ }];
+
+ themes = {
+ base16 = let
+ transparent = "none";
+ gray = "#665c54";
+ dark-gray = "#3c3836";
+ white = "#fbf1c7";
+ black = "#282828";
+ red = "#fb4934";
+ green = "#b8bb26";
+ yellow = "#fabd2f";
+ orange = "#fe8019";
+ blue = "#83a598";
+ magenta = "#d3869b";
+ cyan = "#8ec07c";
+ in {
+ "ui.menu" = transparent;
+ "ui.menu.selected" = { modifiers = [ "reversed" ]; };
+ "ui.linenr" = {
+ fg = gray;
+ bg = dark-gray;
+ };
+ "ui.popup" = { modifiers = [ "reversed" ]; };
+ "ui.linenr.selected" = {
+ fg = white;
+ bg = black;
+ modifiers = [ "bold" ];
+ };
+ "ui.selection" = {
+ fg = black;
+ bg = blue;
+ };
+ "ui.selection.primary" = { modifiers = [ "reversed" ]; };
+ "comment" = { fg = gray; };
+ "ui.statusline" = {
+ fg = white;
+ bg = dark-gray;
+ };
+ "ui.statusline.inactive" = {
+ fg = dark-gray;
+ bg = white;
+ };
+ "ui.help" = {
+ fg = dark-gray;
+ bg = white;
+ };
+ "ui.cursor" = { modifiers = [ "reversed" ]; };
+ "variable" = red;
+ "variable.builtin" = orange;
+ "constant.numeric" = orange;
+ "constant" = orange;
+ "attributes" = yellow;
+ "type" = yellow;
+ "ui.cursor.match" = {
+ fg = yellow;
+ modifiers = [ "underlined" ];
+ };
+ "string" = green;
+ "variable.other.member" = red;
+ "constant.character.escape" = cyan;
+ "function" = blue;
+ "constructor" = blue;
+ "special" = blue;
+ "keyword" = magenta;
+ "label" = magenta;
+ "namespace" = blue;
+ "diff.plus" = green;
+ "diff.delta" = yellow;
+ "diff.minus" = red;
+ "diagnostic" = { modifiers = [ "underlined" ]; };
+ "ui.gutter" = { bg = black; };
+ "info" = blue;
+ "hint" = dark-gray;
+ "debug" = dark-gray;
+ "warning" = yellow;
+ "error" = red;
+ };
+ };
+ };
+
+ test.stubs.helix = { };
+
+ nmt.script = ''
+ assertFileContent \
+ home-files/.config/helix/config.toml \
+ ${./settings-expected.toml}
+ assertFileContent \
+ home-files/.config/helix/languages.toml \
+ ${./languages-expected.toml}
+ assertFileContent \
+ home-files/.config/helix/themes/base16.toml \
+ ${./theme-base16-expected.toml}
+ '';
+ };
+}
diff --git a/tests/modules/programs/helix/languages-expected.toml b/tests/modules/programs/helix/languages-expected.toml
new file mode 100644
index 000000000..d3404397b
--- /dev/null
+++ b/tests/modules/programs/helix/languages-expected.toml
@@ -0,0 +1,3 @@
+[[language]]
+auto-format = false
+name = "rust"
diff --git a/tests/modules/programs/helix/settings-expected.toml b/tests/modules/programs/helix/settings-expected.toml
new file mode 100644
index 000000000..2d575aa63
--- /dev/null
+++ b/tests/modules/programs/helix/settings-expected.toml
@@ -0,0 +1,11 @@
+theme = "base16"
+
+[keys]
+[keys.normal]
+[keys.normal.space]
+q = ":q"
+space = "file_picker"
+w = ":w"
+
+[lsp]
+display-messages = true
diff --git a/tests/modules/programs/helix/theme-base16-expected.toml b/tests/modules/programs/helix/theme-base16-expected.toml
new file mode 100644
index 000000000..25d0bef0c
--- /dev/null
+++ b/tests/modules/programs/helix/theme-base16-expected.toml
@@ -0,0 +1,74 @@
+attributes = "#fabd2f"
+constant = "#fe8019"
+"constant.character.escape" = "#8ec07c"
+"constant.numeric" = "#fe8019"
+constructor = "#83a598"
+debug = "#3c3836"
+"diff.delta" = "#fabd2f"
+"diff.minus" = "#fb4934"
+"diff.plus" = "#b8bb26"
+error = "#fb4934"
+function = "#83a598"
+hint = "#3c3836"
+info = "#83a598"
+keyword = "#d3869b"
+label = "#d3869b"
+namespace = "#83a598"
+special = "#83a598"
+string = "#b8bb26"
+type = "#fabd2f"
+"ui.menu" = "none"
+variable = "#fb4934"
+"variable.builtin" = "#fe8019"
+"variable.other.member" = "#fb4934"
+warning = "#fabd2f"
+
+[comment]
+fg = "#665c54"
+
+[diagnostic]
+modifiers = ["underlined"]
+
+["ui.cursor"]
+modifiers = ["reversed"]
+
+["ui.cursor.match"]
+fg = "#fabd2f"
+modifiers = ["underlined"]
+
+["ui.gutter"]
+bg = "#282828"
+
+["ui.help"]
+bg = "#fbf1c7"
+fg = "#3c3836"
+
+["ui.linenr"]
+bg = "#3c3836"
+fg = "#665c54"
+
+["ui.linenr.selected"]
+bg = "#282828"
+fg = "#fbf1c7"
+modifiers = ["bold"]
+
+["ui.menu.selected"]
+modifiers = ["reversed"]
+
+["ui.popup"]
+modifiers = ["reversed"]
+
+["ui.selection"]
+bg = "#83a598"
+fg = "#282828"
+
+["ui.selection.primary"]
+modifiers = ["reversed"]
+
+["ui.statusline"]
+bg = "#3c3836"
+fg = "#fbf1c7"
+
+["ui.statusline.inactive"]
+bg = "#fbf1c7"
+fg = "#3c3836"