【分享】NixOS折腾记录(一)Fcitx5-rime+Emacs-rime

折腾原因,系统配置完fcitx5后于emacs中配置emacs-rime,在配置中定义rime-share-data-dir的值为 ~/.local/share/fcitx5/rime (根据帖子求教如何在nixos下安装emacs rime - #21,来自 rua )却无法正常输入,经nixos群组群友提醒,查看tmp下emacs-rime的报错日志 ,发现存在文件缺失,即rime-share-data-dir的值我定义错了, ~/.local/share/fcitx5/rime 应该是用户目录。

接着查看emacs-rime源码 emacs-rime/rime.el at 1b70d9cfbac9b11a934007f103b1abc9a034268f · DogLooksGood/emacs-rime · GitHub ,其在xdg-data-dir搜索关键词rime-data从而获取rime-share-data-dir的值,遂明白需要给rime-share-data-dir定义一个存在输入方案的目录。

NixOS的部分配置如下

  i18n.inputMethod = {
    enable = true;
    type = "fcitx5";
    fcitx5.addons = with pkgs; [
      (fcitx5-rime.override {
        rimeDataPkgs = [
          rime-data
          rime-ice
#        ... 其他方案
        ];
      })
      fcitx5-gtk
      kdePackages.fcitx5-qt
      fcitx5-configtool     # 配置工具
    ];
  };
}

以上配置代码,nix会将rimeDataPkgs内的方案打包,最终输出到/nix/store/-fcitx5-with-addons/share/rime-data和/nix/store/-fcitx5-rime-5.1.11/share/rime-data下,谁先谁后我没搞清楚,反正两个里面都有,希望大佬研究看一下。

搞清楚这个合并输入方案的rime-data在那个位置后,就尝试通过nix命令获取目录,但在使用

 nix eval --raw nixpkgs#fcitx5-with-addons.outPath
 nix eval --raw nixpkgs#fcitx5-rime.outPath

这两条命令时,发现sha256的值和/nix/store下正在使用的包的值的对不上,原因是用到了override输入不同导致输出的sha256不同。

毕竟不能每次更新都去配置里换一下sha256的值,找AI问了这种情况该如何获取fcitx5-with-addons和fcitx5-rime包的位置信息。

AI给出的解答是

❯ nix-store --query --requisites $(which fcitx5) | grep fcitx5-rime
/nix/store/ylb2hif7c4kzgfxn9s5zaqxq1gangsfh-fcitx5-rime-5.1.11
share/fcitx5/rime
❯ nix-store --query --requisites $(which fcitx5) | grep fcitx5-with-addons
/nix/store/jb33yk766zjwmmx3hqj21niagf6npbdb-fcitx5-with-addons-5.1.14
或
❯ nix path-info -r $(which fcitx5) | grep fcitx5-rime
/nix/store/ylb2hif7c4kzgfxn9s5zaqxq1gangsfh-fcitx5-rime-5.1.11
share/fcitx5/rime
❯ nix path-info -r $(which fcitx5) | grep fcitx5-with-addons
/nix/store/jb33yk766zjwmmx3hqj21niagf6npbdb-fcitx5-with-addons-5.1.14

这样至少是能获取到当前正在使用的rime-data的目录了,利用home-manager将其设置为环境变量,赋值给emacs中的rime-share-data-dir,最后实现emacs-rime正常输入。

AI也给出下述方案

{ config, pkgs, ... }:

let
  myFcitx5Rime = pkgs.fcitx5-rime.override {
    rimeDataPkgs = [ pkgs.rime-data pkgs.rime-ice ];
  };
in
{
  i18n.inputMethod = {
    enabled = "fcitx5";
    fcitx5.addons = with pkgs; [
      myFcitx5Rime
      fcitx5-gtk
      kdePackages.fcitx5-qt
      fcitx5-configtool
    ];
  };

  home.sessionVariables = {
    FCITX5_RIME_PATH = "${myFcitx5Rime}";
    # 方便调试和脚本使用
    FCITX5_RIME_SHARE = "${myFcitx5Rime}/share/rime-data";
  };
}

直接引用包即可设置环境变量了。

最后想问问除了AI给出的这种查询包(包被override什么的)位置的命令,有没有更好些、简易的命令。

nix-store --query --requisites $(which fcitx5) | grep fcitx5-rime

不建议用这种方法。刚开始用 nixos 时,我也是类似方式来解决一些软件查找问题的,但是当你 nix-store 里有多个版本的 nixos 树时,这样就会找到多个结果,而你没办法很简单的去确认出哪一个是你当前在用的。如果你还有本地 nixpkgs 在各个分支做测试,那这里还会有不与 nixos profile 产生依赖关系的一些结果。进一步,你并不能保证这些目录什么时候被 gc,gc 发生后你环境变量是否需要更新。

最后想问问除了AI给出的这种查询包(包被override什么的)位置的命令,有没有更好些、简易的命令。

下面那种设置就是一种相对好的方法。因为系统内的软件路径就应该在生成时确认好,不应该在生成后再去查找(这同时也涉及到 gc 的工作方式,路径写入文件内可以避免 gc)。但我并不觉得设置成环境变量是一个好的解决方式,应该直接将配置写入一个你预定要读取的 elisp 文件里,这样可以避免污染其它运行的软件。假如,你 emacs-rime 和 fcitx5-rime 要用不同的 rime 配置路径,或是你存在多个路径,有一些想要切换的需要。 nixpkgs 里的 emacs with packages 也是这样做的,把路径写到 site-start.el 里,emacs 会自己去读这个文件,从而把路径全部加载进来。

如果是为了调试去查找当前系统树内的一些依赖情况,可以通过 /nix/var/nix/profiles 得知当前系统树的 store,然后用 nix-store --query 配合 --tree--graph--referrers--references 来做分析。还有想 nix-tree 这样的工具来看依赖树。

1 个赞

意思是利用nix来把需要配置的路径写入site-start.el这个文件(或其他会被require的el文件)中吗?这样确实不会污染环境变量,我会去试试。感谢分享。

呃,我是说 nixpkgs 里是用 site-start.el 来做这件事。在用户层面的配置不用去写这个文件,你可以写到你自己的文件里,比如 custom-file 这种。

了解了 :rose:,zsbd

我来提供一个alternative:如果你给你的Emacs配置文件写了Nix derivation,你可以使用Nix derivation的patch机制,对源代码进行修改,从而实现平台相关代码与核心功能代码分离。(这个patch机制被引入的主要原因是NixOS不遵守FHS规范,但有的软件默认系统应该遵守FHS规范,所以要修改其源代码)