Add Nix flake with NixOS and home-manager modules - #115
Conversation
|
|
||
| # IBus reads components from this list only; keep the distro default so | ||
| # the other engines do not disappear. | ||
| home.sessionVariables.IBUS_COMPONENT_PATH = "${cfg.ibus.package}/share/ibus/component:${pkgs.ibus}/share/ibus/component"; |
There was a problem hiding this comment.
This replaces IBUS_COMPONENT_PATH with only Entropy and the base IBus directories, which can hide other engines installed in the user profile.
Could we prepend Entropy's component directory while preserving the existing path?
There was a problem hiding this comment.
Addressed — the module now prepends through home.sessionSearchVariables.IBUS_COMPONENT_PATH, so Entropy and the base IBus directories go in front and whatever was already on the path is kept. Thanks for catching it.
Use home.sessionSearchVariables so other IBus engines that also rely on IBUS_COMPONENT_PATH keep working instead of being hidden. Addresses review comment on PR ergohaven#115.
Use home.sessionSearchVariables so other IBus engines that also rely on IBUS_COMPONENT_PATH keep working instead of being hidden. Addresses review comment on PR ergohaven#115.
|
The core Nix packaging is still relevant, so I am keeping this PR open. Please update it against current Entropy: Universal Symbols are now native RMK actions gated by firmware capability; IBus remains only for Text Expander. The README and module options still describe IBus as serving Universal Symbols, which is now stale. |
Use home.sessionSearchVariables so other IBus engines that also rely on IBUS_COMPONENT_PATH keep working instead of being hidden. Addresses review comment on PR ergohaven#115.
|
Updated and rebased onto
One thing I could not confirm from the repository, so please correct me if I am looking in the wrong place: on Related: the upstream "Linux IBus Backend" section (README, above the NixOS one) still says IBus serves Universal Symbols. I left it untouched to keep this PR scoped to the Nix bits, but I am happy to update it here if you would rather have both in one go. |
Use home.sessionSearchVariables so other IBus engines that also rely on IBUS_COMPONENT_PATH keep working instead of being hidden. Addresses review comment on PR ergohaven#115.
|
Rebased onto My earlier question is moot — One new thing worth flagging: nixpkgs has picked up Entropy on its own — Separately, and independently of this PR: the nixpkgs module is currently broken. Happy to send that one-line fix, along with a 0.3.2 bump, to nixpkgs if that is useful. |
kissetfall
left a comment
There was a problem hiding this comment.
Thanks for the contribution. The core Nix packaging is useful, but the following changes are required before merge:
- Make the IBus integration opt-in in both modules (default false). Enabling Entropy alone must not enable or select a system-wide input method.
- Do not set the system-wide input method merely because the app is enabled. Require an explicit IBus choice, and warn or document when the active input method is not IBus.
- Align the integration and documentation with the current Text Expander implementation. Entropy should recognize the declaratively installed engine instead of telling users to ignore an incorrect installation state; the documented input-source names must match the actual Entropy Text Expander names; and the stale Universal Symbols package description should be removed.
- Add automated Nix coverage: nix flake check, builds of both packages, and a NixOS module evaluation. The existing Build workflow does not validate the flake.
- Clarify and test coexistence with the Entropy module now shipped by nixpkgs. If this module intentionally supersedes it, keep that behavior explicit and covered so we do not maintain two silently conflicting sources of truth.
Please rebase onto current main after addressing these points.
Use home.sessionSearchVariables so other IBus engines that also rely on IBUS_COMPONENT_PATH keep working instead of being hidden. Addresses review comment on PR ergohaven#115.
|
Thanks — all five points are addressed, rebased onto 1. IBus is opt-in. 2. No input method is chosen for you. The module no longer sets 3. Aligned with the current Text Expander implementation. Entropy now recognises an engine registered outside 4. Automated Nix coverage. New 5. Coexistence with the nixpkgs module, explicit and tested. This module deliberately supersedes Local run: One thing you may want to know regardless of this PR: the nixpkgs module is broken today. |
| description = "The Entropy package to use."; | ||
| }; | ||
|
|
||
| group = lib.mkOption { |
There was a problem hiding this comment.
Thanks for making the access group configurable!
Could we either create the selected group or explicitly validate/document that it must already exist?
A custom value can evaluate and reach the udev rule without a corresponding group, leaving the hidraw device inaccessible.
There was a problem hiding this comment.
Now created by the module: users.groups.${cfg.group} = { }. A no-op for the default input (its gid 174 is kept) and works for any custom value; covered in nix/checks.nix.
| "${pkgs.ibus}/share/ibus/component" | ||
| ]; | ||
|
|
||
| # IBus caches the registry — after switching generations run |
There was a problem hiding this comment.
One lifecycle gap: after a Home Manager switch, Entropy sees the new engine and hides its recovery actions, while the running IBus daemon can still use its old registry.
Could we surface the required IBus restart in the user-facing guidance, or keep a safe recovery path until it reloads?
There was a problem hiding this comment.
Good catch — hiding the install actions closed the only recovery path.
Entropy now shows Reload IBus registry in their place when the engine is registered outside $XDG_DATA_HOME: it reruns ibus write-cache and restarts the daemon, writing nothing. The README and the module comment point at it.
Use home.sessionSearchVariables so other IBus engines that also rely on IBUS_COMPONENT_PATH keep working instead of being hidden. Addresses review comment on PR ergohaven#115.
|
Rebased onto |
|
Self-review caught three problems in my own detection code, now fixed: it scanned the component directories on every frame, a user install could be misread as a system one (XDG_DATA_DIRS often contains paths under $HOME), and a user copy next to a system registration lost its uninstall action. User and system presence are tracked separately now, the result is cached, and the daemon reload runs off the UI thread. Also: the group check no longer hardcodes gid 174, and the CI build step names its outputs instead of relying on Sorry for the number of pushes on this one — embarrassing for what started as a packaging PR. |
Use home.sessionSearchVariables so other IBus engines that also rely on IBUS_COMPONENT_PATH keep working instead of being hidden. Addresses review comment on PR ergohaven#115.
Use home.sessionSearchVariables so other IBus engines that also rely on IBUS_COMPONENT_PATH keep working instead of being hidden. Addresses review comment on PR ergohaven#115.
kissetfall
left a comment
There was a problem hiding this comment.
Thanks — the five points from the previous review appear to be addressed. One runtime-state issue remains before merge.
EntropyApp::ibus_registration caches the first component-directory scan indefinitely. A NixOS/home-manager rebuild can add or remove the system component while Entropy is still running; if the setup page was opened before that rebuild, the cached system: false value remains and the documented Reload IBus registry action never appears until the app is restarted or an in-app setup action happens.
Please make externally managed registration changes observable without restarting Entropy (for example, rescan on page entry/focus, use a bounded refresh interval, or invalidate from a cheap directory fingerprint) and add regression coverage for an external registration change. Please also route the two new reload failure prefixes/statuses through i18n instead of showing hard-coded English in the Russian UI.
After that, please rebase the remaining one commit onto current main. A synthetic merge passed 570/570 Rust tests, i18n, and Clippy locally, but both GitHub workflows are still action_required; the Build and Nix jobs need maintainer approval and must be green before merge.
Use home.sessionSearchVariables so other IBus engines that also rely on IBUS_COMPONENT_PATH keep working instead of being hidden. Addresses review comment on PR ergohaven#115.
Packages Entropy for Nix and covers the two setup steps that cannot work on NixOS: the in-app "Install Vial udev rules" action writes to /etc/udev/rules.d, which is wiped on the next activation, and "Install IBus" copies the engine into ~/.local/share, which IBus never reads because ibus-with-plugins pins IBUS_COMPONENT_PATH to its own store path. Both are handled declaratively by the NixOS module instead. The IBus engine ships as its own package: the bundled python3 script is wrapped with PyGObject and the IBus typelib, since its `env python3` shebang would otherwise find an interpreter without the gi bindings. Notes on the package: hidapi is built with the linux-native-basic-udev feature, so neither libudev nor libhidapi is needed; gtk3 is required by rfd for file dialogs, not by the app itself; TLS comes from rustls, so openssl is unused. X11, Wayland and GL are dlopened at runtime and are passed through LD_LIBRARY_PATH rather than buildInputs alone. The desktop entry and icon are generated here, reusing the artwork from scripts/build_linux_appimage.sh, as the repository ships neither.
Use home.sessionSearchVariables so other IBus engines that also rely on IBUS_COMPONENT_PATH keep working instead of being hidden. Addresses review comment on PR ergohaven#115.
Upstream main now depends on the git-sourced rmk-config crate, which cargoLock.lockFile can't vendor without an explicit hash.
Universal Symbols are native RMK key actions gated by firmware capability, so the IBus engine only matters for Text Expander on Wayland. Also fix the input source name to match the component (Entropy Symbols).
nixpkgs now ships nixos/modules/programs/ergohaven-entropy.nix, which declares the same programs.entropy.enable option. Importing this flake's module alongside it aborts evaluation with "already declared", so disable the nixpkgs one and keep this module authoritative.
linux_vial_udev_rules_installed() only looks at 59-vial.rules under /etc, /run, /usr/lib and /lib, so a rule fed through services.udev.extraRules — which NixOS merges into 99-local.rules — left the app reporting the rule as missing and nagging on every device scan. Ship it as a package under services.udev.packages so it lands as /etc/udev/rules.d/59-vial.rules.
The setup screen offered "Install IBus" unconditionally, even where the engine is already registered outside the user's data directory — by a distribution package or a declarative setup such as the NixOS module. Pressing it there does not fix anything, it just drops an unmanaged copy of the engine beside the managed one. Look the component up the way IBus does — IBUS_COMPONENT_PATH first, then every XDG_DATA_DIRS entry — and replace the install/uninstall actions with a note when the registration is not ours to change. A user-local install keeps the old behaviour.
Enabling a keyboard configurator must not decide what input method the machine runs. programs.entropy.ibus.enable now defaults to false in both modules, and the NixOS one no longer sets i18n.inputMethod.enable or .type: it only appends the engine to i18n.inputMethod.ibus.engines and warns when the active input method is not IBus, in which case the engine would never be loaded anyway.
nix flake check had nothing to check. Add an evaluation of the module on a throwaway machine asserting that enable installs the app and the Vial rule, that it touches no input method on its own, that ibus.enable registers the engine and warns when IBus is not the active input method, and that this module — not the one nixpkgs ships for pkgs.ergohaven-entropy — is the one that wins. Also drop the stale Universal Symbols mention from the engine's description: symbols are native RMK actions now, the engine only backs Text Expander.
The Build workflow compiles with cargo and apt dependencies, so a broken flake reaches main unnoticed. Check formatting, evaluate the NixOS module, build both packages, run the engine's dependency self-check and nix flake check on every pull request.
Describe programs.entropy.ibus as opt-in next to an explicit i18n.inputMethod choice, name the input sources as they actually appear (Entropy Text Expander, plus the layout variants), drop the advice to ignore the install button now that Entropy detects a system-registered engine, and state that this module deliberately supersedes the Entropy module in nixpkgs.
A udev rule naming a group that does not exist installs fine and then leaves the device unreachable, which is exactly the failure the group option is meant to prevent. Declare the group so any value works out of the box; for groups NixOS already ships, such as the default "input", this is a no-op that keeps their well-known gid.
A declarative install puts the engine in place while the running daemon still serves the registry it read at startup, so the layouts are missing until it reloads — and with the install actions hidden there was nothing left in the UI to recover with. Offer "Reload IBus registry" instead, which reruns write-cache and restarts the daemon without writing anything.
Note that programs.entropy.group is created and needs members, and that a daemon started before the rebuild keeps serving its old registry until it is reloaded.
Three problems with the detection added in 3646037: - it ran on every frame of the setup page, scanning the component directories and reading every XML in them; the result is now cached and invalidated by the actions that can change it; - XDG_DATA_DIRS routinely carries paths inside $HOME, so a user install could be reported as a system one, hiding the action that removes it. The user directory is now filtered out of both lookup paths; - a user copy alongside a system registration left no way to remove it. User and system presence are tracked separately, so the uninstall action stays available for the copy it can actually delete. The reload also moved off the UI thread — restarting the daemon can take a while and can hang.
Compare the input group against ids.gids.input instead of a hardcoded 174, drop the bootloader and filesystem stubs the evaluation never needed, name the build outputs explicitly rather than relying on result-1 ordering, and fix a stale sentence about the install action disappearing.
The setup page scanned the component directories once and kept the answer for the lifetime of the process, invalidating it only after an action of its own. A rebuild that registers or drops the engine happens outside the app, so a page opened before it kept showing the old state — and with it either an install action that would only add an unmanaged copy, or no reload action at all. Move the cache into linux_setup as IbusRegistrationCache with a two second refresh window, keep the explicit invalidation for our own actions, and ask for a repaint once the window elapses so an idle page still catches up. The scan is injectable, so the tests cover a registration appearing and disappearing behind the app's back.
Both failure paths of the reload action built their status message in English, so a Russian UI showed "IBus reload failed: ..." verbatim.
|
Both points fixed, rebased onto Registration refresh. The cache moved out of the UI into i18n. Both reload failure paths now go through the catalogs ( 576 tests pass, |
Adds a Nix flake so Entropy can be installed and developed on NixOS.
Two of the Linux setup steps documented in the README cannot work there, and the flake handles both declaratively:
linux/udev/install-vial-rules.shwrites/etc/udev/rules.d/59-vial.rules, which NixOS discards on the next activation. The NixOS module emits the same two rules throughservices.udev.linux/ibus/install-user.shinstalls into~/.local/share/ibus/component, but on NixOSibus-with-pluginspinsIBUS_COMPONENT_PATHto its own store path with--set, so nothing outside it is ever loaded. The module registers the engine throughi18n.inputMethod.ibus.engines, which is the only path IBus honours.The engine is a separate package: the bundled python3 script is wrapped with PyGObject and the IBus typelib, because its
#!/usr/bin/env python3shebang would otherwise resolve to an interpreter without thegibindings. Its--entropy-checkpasses.What's included
packages.<system>.entropypackages.<system>.entropy-ibus-enginenixosModules.defaulthomeManagerModules.defaultdevShells.<system>.defaultx86_64-linuxandaarch64-linux. Usage is documented in a new## NixOSsection in the README.Packaging notes
A few things that differ from what the CI installs, in case they are useful beyond this PR:
hidapiis built with thelinux-native-basic-udevfeature, which resolves to the pure-Rustbasic-udevcrate — neitherlibudevnorlibhidapiis actually needed to build.gtk3is needed byrfdfor file dialogs, not by the app itself (gtk-sysappears inCargo.lock).ureq, solibsslis unused.LD_LIBRARY_PATHin the wrapper rather than throughbuildInputsalone.scripts/build_linux_appimage.sh.Verification
nix build .#entropy .#entropy-ibus-engine— both build,cargo testruns as part of the package build and passeslddreports no missing librariespkgs.ibus-with-plugins.override { plugins = [ engine ]; }builds, i.e. the engine is accepted as an IBus engineprograms.entropy.enable = trueyields the expected udev rules and engine registration, with no warningsnix flake checkpassesTwo decisions worth a second opinion
programs.entropy.ibus.enabledefaults totrueand setsi18n.inputMethod.enable/typeviamkDefault, so enabling Entropy turns IBus on for the whole system. That may be more than you want as a default — happy to flip it tofalse.nixos-unstable, and the flake uses the current package names (libx11rather thanxorg.libX11), so it will not evaluate on 25.05. If stable support matters, the old attribute paths can be restored.flake.lockis committed, as is usual for an application flake, so builds are reproducible. It will need an occasionalnix flake update.