nix: rewrite nix flake from ground up and introduce home-manager module (#44)

* rewrite nix flake and move default package

* revert: remove .envrc

* feat: create home-manager module

big W

* fix: properly parse null for config.plugins

* build plugins from template derivation

* build plugins from template derivation

* cache each plugin individually

* pass name and derivation to template derivation

* fix: rework the devShell

* fix: add missing flake-parts input

* feat: make anyrun not build plugins

it only builds plugins on the anyrun-with-all-plugins package

* chore: write documentation about HM module

* fix: specify pname for plugins

* nix: flake-parts follows nixpkgs

* nix: formatting via alejandra

---------

Co-authored-by: n3oney <neo@neoney.dev>
This commit is contained in:
NotAShelf
2023-06-21 18:49:10 +03:00
committed by GitHub
parent eeb151a542
commit 099e1a08fd
7 changed files with 512 additions and 84 deletions

View File

@@ -17,7 +17,14 @@ jobs:
matrix: matrix:
package: package:
- anyrun - anyrun
- defaultPackage - applications
- dictionary
- kidex
- randr
- rink
- shell
- stdin
- symbols
steps: steps:
- uses: easimon/maximize-build-space@v6 - uses: easimon/maximize-build-space@v6
with: with:

View File

@@ -50,16 +50,11 @@ You can use the flake:
}; };
outputs = { self, nixpkgs, anyrun }: let outputs = { self, nixpkgs, anyrun }: let
pkgs = import nixpkgs {
system = system;
overlays = [anyrun.overlay];
allowUnfree = true;
};
in { in {
nixosConfigurations.HOSTNAME = nixpkgs.lib.nixosSystem { nixosConfigurations.HOSTNAME = nixpkgs.lib.nixosSystem {
# ... # ...
system.packages = [ pkgs.anyrun ]; system.packages = [ anyrun.packages.${system}.anyrun ];
# ... # ...
}; };
@@ -67,6 +62,61 @@ You can use the flake:
} }
``` ```
The flake provides multiple packages:
- anyrun (default) - just the anyrun binary
- anyrun-with-all-plugins - anyrun and all builtin plugins
- applications - the applications plugin
- dictionary - the dictionary plugin
- kidex - the kidex plugin
- randr - the randr plugin
- rink - the rink plugin
- shell - the shell plugin
- stdin - the stdin plugin
- symbols - the symbols plugin
- translate - the translate plugin
#### home-manager module
We have a home-manager module available at `homeManagerModules.default`. You use it like this:
```nix
{
programs.anyrun = {
enable = true;
config = {
plugins = [
# An array of all the plugins you want, which either can be paths to the .so files, or their packages
inputs.anyrun.packages.${pkgs.system}.applications
./some_plugin.so
"${inputs.anyrun.packages.${pkgs.system}.anyrun-with-all-plugins}/lib/kidex"
];
width = { fraction = 0.3; };
position = "top";
verticalOffset = { absolute = 0; };
hideIcons = false;
ignoreExclusiveZones = false;
layer = "overlay";
hidePluginInfo = false;
closeOnClick = false;
showResultsImmediately = false;
maxEntries = null;
};
extraCss = ''
.some_class {
background: red;
}
'';
extraConfigFiles."some-plugin.ron".text = ''
Config(
// for any other plugin
// this file will be put in ~/.config/anyrun/some-plugin.ron
// refer to docs of xdg.configFile for available options
)
'';
};
}
```
You might also want to use the binary cache to avoid building locally. You might also want to use the binary cache to avoid building locally.
```nix ```nix

29
flake.lock generated
View File

@@ -1,23 +1,44 @@
{ {
"nodes": { "nodes": {
"flake-parts": {
"inputs": {
"nixpkgs-lib": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1685662779,
"narHash": "sha256-cKDDciXGpMEjP1n6HlzKinN0H+oLmNpgeCTzYnsA2po=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "71fb97f0d875fd4de4994dfb849f2c75e17eb6c3",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1682960002, "lastModified": 1685655444,
"narHash": "sha256-5Zjh4pT3lAjFGN1gVrjqj1LLJHKCAlGdLD8raU7oEMc=", "narHash": "sha256-6EujQNAeaUkWvpEZZcVF8qSfQrNVWFNNGbUJxv/A5a8=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "8670e496ffd093b60e74e7fa53526aa5920d09eb", "rev": "e635192892f5abbc2289eaac3a73cdb249abaefd",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "NixOS", "owner": "NixOS",
"ref": "nixpkgs-unstable", "ref": "nixos-unstable",
"repo": "nixpkgs", "repo": "nixpkgs",
"type": "github" "type": "github"
} }
}, },
"root": { "root": {
"inputs": { "inputs": {
"flake-parts": "flake-parts",
"nixpkgs": "nixpkgs" "nixpkgs": "nixpkgs"
} }
} }

185
flake.nix
View File

@@ -2,71 +2,126 @@
description = "A wayland native, highly customizable runner."; description = "A wayland native, highly customizable runner.";
inputs = { inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
}; flake-parts = {
url = "github:hercules-ci/flake-parts";
outputs = { inputs.nixpkgs-lib.follows = "nixpkgs";
self,
nixpkgs,
}: let
cargoToml = builtins.fromTOML (builtins.readFile ./anyrun/Cargo.toml);
supportedSystems = ["x86_64-linux" "aarch64-linux"];
forAllSystems = f: nixpkgs.lib.genAttrs supportedSystems (system: f system);
in {
overlay = final: prev: {
"${cargoToml.package.name}" = final.callPackage ./. {};
}; };
packages = forAllSystems (system: let
pkgs = import nixpkgs {
inherit system;
overlays = [self.overlay];
};
in {
"${cargoToml.package.name}" = pkgs."${cargoToml.package.name}";
});
defaultPackage = forAllSystems (system:
(import nixpkgs {
inherit system;
overlays = [self.overlay];
})
."${cargoToml.package.name}");
checks = forAllSystems (system: let
pkgs = import nixpkgs {
inherit system;
overlays = [
self.overlay
];
};
in {
format =
pkgs.runCommand "check-format"
{
buildInputs = with pkgs; [rustfmt cargo];
} ''
${pkgs.rustfmt}/bin/cargo-fmt fmt --manifest-path ${./anyrun}/Cargo.toml -- --check
${pkgs.nixpkgs-fmt}/bin/nixpkgs-fmt --check ${./anyrun}
touch $out # it worked!
'';
"${cargoToml.package.name}" = pkgs."${cargoToml.package.name}";
});
devShell = forAllSystems (system: let
pkgs = import nixpkgs {
inherit system;
overlays = [self.overlay];
};
in
pkgs.mkShell {
inputsFrom = [
pkgs."${cargoToml.package.name}"
];
buildInputs = with pkgs; [
rustfmt
nixpkgs-fmt
];
LIBCLANG_PATH = "${pkgs.llvmPackages.libclang.lib}/lib";
});
}; };
outputs = inputs @ {flake-parts, ...}:
flake-parts.lib.mkFlake {inherit inputs;} {
systems = ["x86_64-linux" "aarch64-linux"];
perSystem = {
config,
self',
inputs',
pkgs,
system,
...
}: let
inherit (inputs.nixpkgs) lib;
inherit (lib) getExe;
in {
# provide the formatter for nix fmt
formatter = pkgs.alejandra;
devShells.default = pkgs.mkShell {
inputsFrom = builtins.attrValues self'.packages;
packages = with pkgs; [
alejandra # nix formatter
rustfmt # rust formatter
statix # lints and suggestions
deadnix # clean up unused nix code
rustc # rust compiler
gcc
cargo # rust package manager
clippy # opinionated rust formatter
];
};
packages = let
lockFile = ./Cargo.lock;
in rec {
anyrun = pkgs.callPackage ./nix/default.nix {inherit inputs lockFile;};
# alias nix build .# to anyrun
default = anyrun;
anyrun-with-all-plugins = pkgs.callPackage ./nix/default.nix {
inherit inputs lockFile;
dontBuildPlugins = false;
};
# expose each plugin as a package
applications = pkgs.callPackage ./nix/plugins/default.nix {
inherit inputs lockFile;
name = "applications";
};
dictionary = pkgs.callPackage ./nix/plugins/default.nix {
inherit inputs lockFile;
name = "dictionary";
};
kidex = pkgs.callPackage ./nix/plugins/default.nix {
inherit inputs lockFile;
name = "kidex";
};
randr = pkgs.callPackage ./nix/plugins/default.nix {
inherit inputs lockFile;
name = "randr";
};
rink = pkgs.callPackage ./nix/plugins/default.nix {
inherit inputs lockFile;
name = "rink";
};
shell = pkgs.callPackage ./nix/plugins/default.nix {
inherit inputs lockFile;
name = "shell";
};
stdin = pkgs.callPackage ./nix/plugins/default.nix {
inherit inputs lockFile;
name = "stdin";
};
symbols = pkgs.callPackage ./nix/plugins/default.nix {
inherit inputs lockFile;
name = "symbols";
};
translate = pkgs.callPackage ./nix/plugins/default.nix {
inherit inputs lockFile;
name = "translate";
};
};
checks = {
format =
pkgs.runCommand "check-format" {
buildInputs = with pkgs; [
rustfmt
cargo
];
} ''
${pkgs.rustfmt}/bin/cargo-fmt fmt --manifest-path ./anyrun/Cargo.toml -- --check
${getExe pkgs.alejandra} --check ./
touch $out # it worked!
'';
"anyrun-format-check" = self'.packages.anyrun;
};
};
flake = _: {
# TODO: Make a NixOS module
nixosModules.default = null;
homeManagerModules.default = import ./nix/hm-module.nix inputs.self;
};
};
} }

View File

@@ -1,4 +1,3 @@
# default.nix
{ {
lib, lib,
glib, glib,
@@ -12,11 +11,18 @@
rustfmt, rustfmt,
cargo, cargo,
rustc, rustc,
lockFile,
dontBuildPlugins ? true,
...
}: let }: let
cargoToml = builtins.fromTOML (builtins.readFile ./anyrun/Cargo.toml); cargoToml = builtins.fromTOML (builtins.readFile ../anyrun/Cargo.toml);
in in
rustPlatform.buildRustPackage { rustPlatform.buildRustPackage rec {
src = ./.; name = cargoToml.package.name;
pname = "anyrun";
#inherit version;
src = ../.;
buildInputs = [ buildInputs = [
pkg-config pkg-config
@@ -28,7 +34,7 @@ in
]; ];
cargoLock = { cargoLock = {
lockFile = ./Cargo.lock; lockFile = lockFile;
}; };
checkInputs = [cargo rustc]; checkInputs = [cargo rustc];
@@ -41,14 +47,16 @@ in
cargo cargo
]; ];
cargoBuildFlags =
if dontBuildPlugins
then ["-p ${name}"]
else [];
doCheck = true; doCheck = true;
CARGO_BUILD_INCREMENTAL = "false"; CARGO_BUILD_INCREMENTAL = "false";
RUST_BACKTRACE = "full"; RUST_BACKTRACE = "full";
copyLibs = true; copyLibs = true;
name = cargoToml.package.name;
version = cargoToml.package.version;
postInstall = '' postInstall = ''
wrapProgram $out/bin/anyrun \ wrapProgram $out/bin/anyrun \
--set GDK_PIXBUF_MODULE_FILE "$(echo ${librsvg.out}/lib/gdk-pixbuf-2.0/*/loaders.cache)" \ --set GDK_PIXBUF_MODULE_FILE "$(echo ${librsvg.out}/lib/gdk-pixbuf-2.0/*/loaders.cache)" \
@@ -66,6 +74,10 @@ in
githubId = 30625554; githubId = 30625554;
name = "Michał Minarowski"; name = "Michał Minarowski";
} }
{
email = "raf@notashelf.dev";
github = "NotAShelf";
}
]; ];
}; };
} }

234
nix/hm-module.nix Normal file
View File

@@ -0,0 +1,234 @@
self: {
config,
pkgs,
lib,
hm,
...
}: let
cfg = config.programs.anyrun;
defaultPackage = self.packages.${pkgs.stdenv.hostPlatform.system}.default;
in {
meta.maintainers = with lib.maintainers; [n3oney NotAShelf];
options.programs.anyrun = with lib; {
enable = mkEnableOption "anyrun";
package = mkOption {
type = with types; nullOr package;
default = defaultPackage;
defaultText = lib.literalExpression ''
anyrun.packages.''${pkgs.stdenv.hostPlatform.system}.default
'';
description = mdDoc ''
Anyrun package to use. Defaults to the one provided by the flake.
'';
};
config = let
mkNumericOption = {
default,
description,
...
}:
with types;
mkOption {
inherit default description;
example = ''
{ absolute = 200; };
or
{ fraction = 0.4; };
'';
type = submodule {
options = {
absolute = mkOption {
type = nullOr int;
default = null;
};
fraction = mkOption {
type = nullOr float;
default = null;
};
};
};
};
numericInfo = ''
This is a numeric option - pass either `{ absolute = int; };` or `{ fraction = float; };`.
when using `absolute` it sets the absolute value in pixels,
when using `fraction`, it sets a fraction of the width or height of the full screen (depends on exclusive zones and the settings related to them) window
'';
in {
plugins = mkOption {
type = with types; nullOr (listOf (either package str));
default = null;
description = mdDoc ''
List of anyrun plugins to use. Can either be packages, absolute plugin paths, or strings.
'';
};
width = mkNumericOption {
default.absolute = 800;
description = mdDoc ''
How wide the input box and results are.
${numericInfo}
'';
};
position = mkOption {
type = with types; enum ["top" "center"];
default = "top";
description = "Where Anyrun is located on the screen (top or center)";
};
verticalOffset = mkNumericOption {
default.absolute = 0;
description = ''
How much the runner is shifted vertically.
${numericInfo}
'';
};
hideIcons = mkOption {
type = types.bool;
default = false;
description = "Hide match and plugin info icons";
};
ignoreExclusiveZones = mkOption {
type = types.bool;
default = false;
description = "ignore exclusive zones, eg. Waybar";
};
layer = mkOption {
type = with types; enum ["background" "bottom" "top" "overlay"];
default = "overlay";
description = "Layer shell layer (background, bottom, top or overlay)";
};
hidePluginInfo = mkOption {
type = types.bool;
default = false;
description = "Hide the plugin info panel";
};
closeOnClick = mkOption {
type = types.bool;
default = false;
description = "Close window when a click outside the main box is received";
};
showResultsImmediately = mkOption {
type = types.bool;
default = false;
description = "Show search results immediately when Anyrun starts";
};
maxEntries = mkOption {
type = with types; nullOr int;
default = null;
description = "Limit amount of entries shown in total";
};
};
extraCss = lib.mkOption {
type = lib.types.nullOr lib.types.lines;
default = "";
description = mdDoc ''
Extra CSS lines to add to {file}`~/.config/anyrun/style.css`.
'';
};
extraConfigFiles = lib.mkOption {
# unfortunately HM doesn't really export the type for files, but hopefully
# hm will throw errors if the options are wrong here, so I'm being *very* loose
type = lib.types.attrs;
default = {};
description = mdDoc ''
Extra files to put in `~/.config/anyrun`, a wrapper over `xdg.configFile`.
'';
example = ''
programs.anyrun.extraConfigFiles."plugin-name.ron".text = '''
Config(
some_option: true,
)
'''
'';
};
};
config = lib.mkIf cfg.enable (let
assertNumeric = numeric: {
assertion = !((numeric ? absolute && numeric.absolute != null) && (numeric ? fraction && numeric.fraction != null));
message = "Invalid numeric definition, you can only specify one of absolute or fraction.";
};
stringifyNumeric = numeric:
if (numeric ? absolute && numeric.absolute != null)
then "Absolute(${builtins.toString numeric.absolute})"
else "Fraction(${builtins.toString numeric.fraction})";
capitalize = string:
lib.toUpper (builtins.substring 0 1 string) + lib.toLower (builtins.substring 1 ((builtins.stringLength string) - 1) string);
parsedPlugins =
if cfg.config.plugins == null
then []
else
builtins.map (entry:
if lib.types.package.check entry
then "${entry}/lib/lib${lib.replaceStrings ["-"] ["_"] entry.pname}.so"
else entry)
cfg.config.plugins;
in {
assertions = [(assertNumeric cfg.config.width) (assertNumeric cfg.config.verticalOffset)];
warnings =
if cfg.config.plugins == null
then [
''
You haven't enabled any plugins. Anyrun will not show any results, unless you specify plugins with the --override-plugins flag.
Add plugins to programs.anyrun.config.plugins, or set it to [] to silence the warning.
''
]
else [];
home.packages = lib.optional (cfg.package != null) cfg.package;
xdg.configFile = lib.mkMerge [
(lib.mapAttrs'
(name: value: lib.nameValuePair ("anyrun/" + name) value)
cfg.extraConfigFiles)
{
"anyrun/config.ron".text = ''
Config(
width: ${stringifyNumeric cfg.config.width},
position: ${capitalize cfg.config.position},
vertical_offset: ${stringifyNumeric cfg.config.verticalOffset},
hide_icons: ${lib.boolToString cfg.config.hideIcons},
ignore_exclusive_zones: ${lib.boolToString cfg.config.ignoreExclusiveZones},
layer: ${capitalize cfg.config.layer},
hide_plugin_info: ${lib.boolToString cfg.config.hidePluginInfo},
close_on_click: ${lib.boolToString cfg.config.closeOnClick},
show_results_immediately: ${lib.boolToString cfg.config.showResultsImmediately},
max_entries: ${
if cfg.config.maxEntries == null
then "None"
else builtins.toString cfg.config.maxEntries
},
plugins: ${builtins.toJSON parsedPlugins},
)
'';
}
{
"anyrun/style.css" = lib.mkIf (cfg.extraCss != null) {
text = cfg.extraCss;
};
}
];
});
}

49
nix/plugins/default.nix Normal file
View File

@@ -0,0 +1,49 @@
{
lib,
glib,
makeWrapper,
rustPlatform,
atk,
gtk3,
gtk-layer-shell,
pkg-config,
librsvg,
inputs,
name,
lockFile,
...
}: let
cargoToml = builtins.fromTOML (builtins.readFile ../../plugins/${name}/Cargo.toml);
in
rustPlatform.buildRustPackage {
pname = name;
name = cargoToml.package.name;
src = "${inputs.self}";
cargoLock.lockFile = lockFile;
buildInputs = [
glib
atk
gtk3
librsvg
gtk-layer-shell
];
nativeBuildInputs = [
pkg-config
makeWrapper
];
doCheck = true;
CARGO_BUILD_INCREMENTAL = "false";
RUST_BACKTRACE = "full";
copyLibs = true;
cargoBuildFlags = ["-p ${name}"];
meta = with lib; {
description = "The ${name} plugin for Anyrun";
homepage = "https://github.com/Kirottu/anyrun";
license = with licenses; [gpl3];
};
}