From 6d1f834ca63700604a96d8c38aa8ac272d95071a Mon Sep 17 00:00:00 2001 From: awwpotato <153149335+awwpotato@users.noreply.github.com> Date: Wed, 23 Apr 2025 09:51:43 -0700 Subject: [PATCH] fcitx5: add upstream options (#6892) --- modules/i18n/input-method/fcitx5.nix | 195 ++++++++++++++---- tests/modules/i18n/input-method/default.nix | 4 +- .../input-method/fcitx5-configuration.nix | 37 ---- .../i18n/input-method/fcitx5/classicui.conf | 2 + tests/modules/i18n/input-method/fcitx5/config | 20 ++ .../input-method/fcitx5/configuration.nix | 83 ++++++++ .../old-enable.nix} | 0 .../modules/i18n/input-method/fcitx5/profile | 15 ++ 8 files changed, 281 insertions(+), 75 deletions(-) delete mode 100644 tests/modules/i18n/input-method/fcitx5-configuration.nix create mode 100644 tests/modules/i18n/input-method/fcitx5/classicui.conf create mode 100644 tests/modules/i18n/input-method/fcitx5/config create mode 100644 tests/modules/i18n/input-method/fcitx5/configuration.nix rename tests/modules/i18n/input-method/{old-fcitx5-enable.nix => fcitx5/old-enable.nix} (100%) create mode 100644 tests/modules/i18n/input-method/fcitx5/profile diff --git a/modules/i18n/input-method/fcitx5.nix b/modules/i18n/input-method/fcitx5.nix index 0e8902f1a..a710dc49f 100644 --- a/modules/i18n/input-method/fcitx5.nix +++ b/modules/i18n/input-method/fcitx5.nix @@ -8,6 +8,8 @@ let im = config.i18n.inputMethod; cfg = im.fcitx5; fcitx5Package = cfg.fcitx5-with-addons.override { inherit (cfg) addons; }; + iniFormat = pkgs.formats.ini { }; + iniGlobalFormat = pkgs.formats.iniWithGlobalSection { }; in { options = { @@ -38,11 +40,96 @@ in ''; }; - classicUiConfig = lib.mkOption { - type = with lib.types; either path lines; - default = ""; + quickPhrase = lib.mkOption { + type = with lib.types; attrsOf str; + default = { }; + example = lib.literalExpression '' + { + smile = "(・∀・)"; + angry = "( ̄ー ̄)"; + } + ''; + description = "Quick phrases."; + }; + + quickPhraseFiles = lib.mkOption { + type = with lib.types; attrsOf path; + default = { }; + example = lib.literalExpression '' + { + words = ./words.mb; + numbers = ./numbers.mb; + } + ''; + description = "Quick phrase files."; + }; + + settings = { + globalOptions = lib.mkOption { + type = lib.types.submodule { + freeformType = iniFormat.type; + }; + default = { }; + description = '' + The global options in `config` file in ini format. + ''; + example = lib.literalExpression '' + { + Behavior = { + ActiveByDefault = false; + }; + Hotkey = { + EnumerateWithTriggerKeys = true; + EnumerateSkipFirst = false; + ModifierOnlyKeyTimeout = 250; + }; + } + ''; + }; + inputMethod = lib.mkOption { + type = lib.types.submodule { + freeformType = iniFormat.type; + }; + default = { }; + description = '' + The input method configure in `profile` file in ini format. + ''; + example = lib.literalExpression '' + { + GroupOrder."0" = "Default"; + "Groups/0" = { + Name = "Default"; + "Default Layout" = "us"; + DefaultIM = "pinyin"; + }; + "Groups/0/Items/0".Name = "keyboard-us"; + "Groups/0/Items/1".Name = "pinyin"; + } + ''; + }; + addons = lib.mkOption { + type = with lib.types; (attrsOf iniGlobalFormat.type); + default = { }; + description = '' + The addon configures in `conf` folder in ini format with global sections. + Each item is written to the corresponding file. + ''; + example = lib.literalExpression '' + { + classicui.globalSection.Theme = "example"; + pinyin.globalSection.EmojiEnabled = "True"; + } + ''; + }; + }; + + ignoreUserConfig = lib.mkOption { + type = lib.types.bool; + default = false; description = '' - Configuration to be written to {file}`$XDG_DATA_HOME/fcitx5/conf/classicui.conf` + Ignore the user configures. **Warning**: When this is enabled, the + user config files are totally ignored and the user dict can't be saved + and loaded. ''; }; @@ -52,7 +139,13 @@ in lazyAttrsOf (submodule { options = { theme = lib.mkOption { - type = with lib.types; nullOr (either lines path); + type = + with lib.types; + nullOr (oneOf [ + iniFormat.type + lines + path + ]); default = null; description = '' The `theme.conf` file of the theme. @@ -83,7 +176,27 @@ in }; config = lib.mkIf (im.enable && im.type == "fcitx5") { - i18n.inputMethod.package = fcitx5Package; + i18n.inputMethod = { + package = fcitx5Package; + + fcitx5.addons = + lib.optionals (cfg.quickPhrase != { }) [ + (pkgs.writeTextDir "share/fcitx5/data/QuickPhrase.mb" ( + lib.concatStringsSep "\n" ( + lib.mapAttrsToList ( + name: value: "${name} ${builtins.replaceStrings [ "\\" "\n" ] [ "\\\\" "\\n" ] value}" + ) cfg.quickPhrase + ) + )) + ] + ++ lib.optionals (cfg.quickPhraseFiles != { }) [ + (pkgs.linkFarm "quickPhraseFiles" ( + lib.mapAttrs' ( + name: value: lib.nameValuePair ("share/fcitx5/data/quickphrase.d/${name}.mb") value + ) cfg.quickPhraseFiles + )) + ]; + }; home = { sessionVariables = @@ -95,42 +208,52 @@ in // lib.optionalAttrs (!cfg.waylandFrontend) { GTK_IM_MODULE = "fcitx"; QT_IM_MODULE = "fcitx"; + } + // lib.optionalAttrs cfg.ignoreUserConfig { + SKIP_FCITX_USER_PATH = "1"; }; sessionSearchVariables.QT_PLUGIN_PATH = [ "${fcitx5Package}/${pkgs.qt6.qtbase.qtPluginPrefix}" ]; }; - xdg = lib.mkMerge ( - [ - (lib.mkIf (cfg.classicUiConfig != "") { - dataFile."fcitx5/conf/classicui.conf".source = ( - if builtins.isPath cfg.classicUiConfig || lib.isStorePath cfg.classicUiConfig then - cfg.classicUiConfig + xdg = { + configFile = + let + optionalFile = + p: f: v: + lib.optionalAttrs (v != { }) { + "fcitx5/${p}".source = f v; + }; + in + lib.attrsets.mergeAttrsList [ + (optionalFile "config" iniFormat.generate cfg.settings.globalOptions) + (optionalFile "profile" iniFormat.generate cfg.settings.inputMethod) + (lib.concatMapAttrs ( + name: value: optionalFile "conf/${name}.conf" iniGlobalFormat.generate value + ) cfg.settings.addons) + ]; + dataFile = lib.concatMapAttrs ( + name: attrs: + let + nullableFile = + n: maybeNull: source: + lib.nameValuePair "fcitx5/themes/${name}/${n}" (lib.mkIf (maybeNull != null) { inherit source; }); + simpleFile = n: v: nullableFile n v v; + in + builtins.listToAttrs [ + (simpleFile "highlight.svg" attrs.highlightImage) + (simpleFile "panel.svg" attrs.panelImage) + (nullableFile "theme.conf" attrs.theme ( + if builtins.isPath attrs.theme || lib.isStorePath attrs.theme then + attrs.theme + else if builtins.isString attrs.theme then + pkgs.writeText "fcitx5-theme.conf" attrs.theme else - pkgs.writeText "fcitx5-classicui.conf" cfg.classicUiConfig - ); - }) - ] - ++ lib.mapAttrsToList (name: attrs: { - dataFile = - let - nullableFile = - n: maybeNull: source: - lib.nameValuePair "fcitx5/themes/${name}/${n}" (lib.mkIf (maybeNull != null) { inherit source; }); - simpleFile = n: v: nullableFile n v v; - in - builtins.listToAttrs [ - (simpleFile "highlight.svg" attrs.highlightImage) - (simpleFile "panel.svg" attrs.panelImage) - (nullableFile "theme.conf" attrs.theme ( - if builtins.isPath attrs.theme || lib.isStorePath attrs.theme then - attrs.theme - else - pkgs.writeText "fcitx5-theme.conf" attrs.theme - )) - ]; - }) cfg.themes - ); + iniFormat.generate attrs.theme + )) + ] + ) cfg.themes; + }; systemd.user.services.fcitx5-daemon = { Unit = { diff --git a/tests/modules/i18n/input-method/default.nix b/tests/modules/i18n/input-method/default.nix index 4548971aa..0db866cfa 100644 --- a/tests/modules/i18n/input-method/default.nix +++ b/tests/modules/i18n/input-method/default.nix @@ -1,5 +1,5 @@ { - input-method-fcitx5-configuration = ./fcitx5-configuration.nix; - input-method-fcitx5-old-enable = ./fcitx5-configuration.nix; + input-method-fcitx5-configuration = ./fcitx5/configuration.nix; + input-method-fcitx5-old-enable = ./fcitx5/old-enable.nix; input-method-kime-configuration = ./kime-configuration.nix; } diff --git a/tests/modules/i18n/input-method/fcitx5-configuration.nix b/tests/modules/i18n/input-method/fcitx5-configuration.nix deleted file mode 100644 index 614188b8e..000000000 --- a/tests/modules/i18n/input-method/fcitx5-configuration.nix +++ /dev/null @@ -1,37 +0,0 @@ -{ - config, - lib, - realPkgs, - ... -}: - -lib.mkIf config.test.enableBig { - i18n.inputMethod = { - enable = true; - type = "fcitx5"; - fcitx5 = { - waylandFrontend = true; - themes.example = { - theme = '' - [Metadata] - Name=example - Version=0.1 - Author=home-manager - Description=Theme for testing - ScaleWithDPI=True - ''; - }; - classicUiConfig = "Theme=example"; - }; - }; - - _module.args.pkgs = lib.mkForce realPkgs; - - nmt.script = '' - assertFileExists home-files/.config/systemd/user/fcitx5-daemon.service - assertFileExists home-files/.local/share/fcitx5/themes/example/theme.conf - assertFileExists home-files/.local/share/fcitx5/conf/classicui.conf - assertFileNotRegex home-path/etc/profile.d/hm-session-vars.sh 'GTK_IM_MODULE' - assertFileNotRegex home-path/etc/profile.d/hm-session-vars.sh 'QT_IM_MODULE' - ''; -} diff --git a/tests/modules/i18n/input-method/fcitx5/classicui.conf b/tests/modules/i18n/input-method/fcitx5/classicui.conf new file mode 100644 index 000000000..ede514871 --- /dev/null +++ b/tests/modules/i18n/input-method/fcitx5/classicui.conf @@ -0,0 +1,2 @@ +Theme=example + diff --git a/tests/modules/i18n/input-method/fcitx5/config b/tests/modules/i18n/input-method/fcitx5/config new file mode 100644 index 000000000..ed8c650ec --- /dev/null +++ b/tests/modules/i18n/input-method/fcitx5/config @@ -0,0 +1,20 @@ +[Behavior] +ActiveByDefault=false +AllowInputMethodForPassword=false +AutoSavePeriod=30 +CompactInputMethodInformation=true +DefaultPageSize=5 +OverrideXkbOption=false +PreeditEnabledByDefault=true +PreloadInputMethod=true +ShareInputState=No +ShowFirstInputMethodInformation=true +ShowInputMethodInformation=true +ShowPreeditForPassword=false +resetStateWhenFocusIn=No +showInputMethodInformationWhenFocusIn=false + +[Hotkey] +EnumerateSkipFirst=false +EnumerateWithTriggerKeys=true +ModifierOnlyKeyTimeout=250 diff --git a/tests/modules/i18n/input-method/fcitx5/configuration.nix b/tests/modules/i18n/input-method/fcitx5/configuration.nix new file mode 100644 index 000000000..bf7175dc3 --- /dev/null +++ b/tests/modules/i18n/input-method/fcitx5/configuration.nix @@ -0,0 +1,83 @@ +{ + config, + lib, + realPkgs, + ... +}: + +lib.mkIf config.test.enableBig { + i18n.inputMethod = { + enable = true; + type = "fcitx5"; + fcitx5 = { + waylandFrontend = true; + settings = { + globalOptions = { + Behavior = { + ActiveByDefault = false; + resetStateWhenFocusIn = "No"; + ShareInputState = "No"; + PreeditEnabledByDefault = true; + ShowInputMethodInformation = true; + showInputMethodInformationWhenFocusIn = false; + CompactInputMethodInformation = true; + ShowFirstInputMethodInformation = true; + DefaultPageSize = 5; + OverrideXkbOption = false; + PreloadInputMethod = true; + AllowInputMethodForPassword = false; + ShowPreeditForPassword = false; + AutoSavePeriod = 30; + }; + Hotkey = { + EnumerateWithTriggerKeys = true; + EnumerateSkipFirst = false; + ModifierOnlyKeyTimeout = 250; + }; + }; + inputMethod = { + GroupOrder."0" = "Default"; + "Groups/0" = { + Name = "Default"; + "Default Layout" = "us"; + DefaultIM = "pinyin"; + }; + "Groups/0/Items/0" = { + Name = "keyboard-us"; + Layout = null; + }; + "Groups/0/Items/1" = { + Name = "pinyin"; + Layout = null; + }; + }; + addons.classicui.globalSection.Theme = "example"; + }; + themes.example = { + theme = '' + [Metadata] + Name=example + Version=0.1 + Author=home-manager + Description=Theme for testing + ScaleWithDPI=True + ''; + }; + }; + }; + + _module.args.pkgs = lib.mkForce realPkgs; + + nmt.script = '' + assertFileExists home-files/.config/systemd/user/fcitx5-daemon.service + assertFileExists home-files/.config/fcitx5/config + assertFileContent home-files/.config/fcitx5/config ${./config} + assertFileExists home-files/.config/fcitx5/profile + assertFileContent home-files/.config/fcitx5/profile ${./profile} + assertFileExists home-files/.config/fcitx5/conf/classicui.conf + assertFileContent home-files/.config/fcitx5/conf/classicui.conf ${./classicui.conf} + assertFileExists home-files/.local/share/fcitx5/themes/example/theme.conf + assertFileNotRegex home-path/etc/profile.d/hm-session-vars.sh 'GTK_IM_MODULE' + assertFileNotRegex home-path/etc/profile.d/hm-session-vars.sh 'QT_IM_MODULE' + ''; +} diff --git a/tests/modules/i18n/input-method/old-fcitx5-enable.nix b/tests/modules/i18n/input-method/fcitx5/old-enable.nix similarity index 100% rename from tests/modules/i18n/input-method/old-fcitx5-enable.nix rename to tests/modules/i18n/input-method/fcitx5/old-enable.nix diff --git a/tests/modules/i18n/input-method/fcitx5/profile b/tests/modules/i18n/input-method/fcitx5/profile new file mode 100644 index 000000000..4b441970a --- /dev/null +++ b/tests/modules/i18n/input-method/fcitx5/profile @@ -0,0 +1,15 @@ +[GroupOrder] +0=Default + +[Groups/0] +Default Layout=us +DefaultIM=pinyin +Name=Default + +[Groups/0/Items/0] +Layout=null +Name=keyboard-us + +[Groups/0/Items/1] +Layout=null +Name=pinyin