diff --git a/.envrc b/.envrc
index e483044..49bacf7 100644
--- a/.envrc
+++ b/.envrc
@@ -1,11 +1,10 @@
# update repo
if has jj; then
- jj git fetch --all-remotes
+ jj git fetch --all-remotes
elif has gix; then
- gix fetch
+ gix fetch
elif has git; then
- git fetch
+ git fetch
fi
-watch_file ./flake.{nix,lock} ./flake-modules/{default,devshells,overlays,nixvim-modules}.nix
use flake
diff --git a/.forgejo/workflows/check.yml b/.forgejo/workflows/check.yml
index 3199e04..adddf31 100644
--- a/.forgejo/workflows/check.yml
+++ b/.forgejo/workflows/check.yml
@@ -1,92 +1,58 @@
on:
push:
jobs:
- check-fmt:
+ check:
runs-on: nixos
- steps:
- - uses: https://git.salame.cl/actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- - run: nix --version
- - name: Run treefmt
- run: |
- nix build --print-build-logs ".#checks.$(nix eval --raw --impure --expr builtins.currentSystem).treefmt"
- build-package:
- runs-on: nixos
- needs: check-fmt
strategy:
matrix:
- package:
+ check:
+ - nvimDev
+ - nvimHeadless
+ - nvimNoBundledBins
+ - nvimNoLsp
+ - nvimNoTSGrammars
+ - treefmt
+ steps:
+ - uses: "https://git.salame.cl/actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683" # v4
+ - name: Run checks
+ run: |
+ nix --version
+ # shellcheck disable=SC2016
+ nix build --print-build-logs '.#checks.x86_64-linux.${{ matrix.check }}'
+ check-renovaterc:
+ runs-on: nixos
+ steps:
+ - uses: "https://git.salame.cl/actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683" # v4
+ - name: Validate renovaterc.json
+ run: |
+ nix --version
+ nix shell nixpkgs#renovate --command renovate-config-validator
+ build:
+ runs-on: nixos
+ needs: check
+ strategy:
+ matrix:
+ target:
- audiomenu
- docs
- - docs-home-markdown
- - docs-nixos-markdown
- - docs-nvim-markdown
- jpassmenu
+ - nixosConfigurations.vm.config.system.build.toplevel
- nvim
- - nvim-headless
- - nvim-no-lsps
- - nvim-no-ts
- - nvim-small
- - search
steps:
- uses: "https://git.salame.cl/actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683" # v4
- - run: nix --version
- name: Build target
- env:
- PACKAGE: ${{ matrix.package }}
run: |
+ nix --version
# shellcheck disable=SC2016
- nix build --print-build-logs ".#$PACKAGE"
- check-nvim:
- runs-on: nixos
- needs: build-package
- strategy:
- matrix:
- nvim:
- - nvim
- - nvim-headless
- - nvim-no-lsps
- - nvim-no-ts
- - nvim-small
- steps:
- - uses: "https://git.salame.cl/actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683" # v4
- - run: nix --version
- - name: Build target
- env:
- NVIM: ${{ matrix.nvim }}
- run: |
- nix build --print-build-logs ".#checks.$(nix eval --raw --impure --expr builtins.currentSystem).$NVIM"
- build-vm:
- runs-on: nixos
- needs:
- - build-package
- - check-nvim
- steps:
- - uses: "https://git.salame.cl/actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683" # v4
- - run: nix --version
- - name: Build VM configuration
- run: |
- nix build --print-build-logs '.#nixosConfigurations.vm.config.system.build.toplevel'
- build-hm:
- runs-on: nixos
- needs:
- - build-package
- - check-nvim
- steps:
- - uses: "https://git.salame.cl/actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683" # v4
- - run: nix --version
- - name: Build Home Manager configuration
- run: |
- nix build --print-build-logs '.#homeConfigurations.example.activationPackage'
+ nix build --print-build-logs '.#${{ matrix.target }}'
report-size:
runs-on: nixos
- needs:
- - build-vm
- - build-hm
+ needs: build
steps:
- uses: "https://git.salame.cl/actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683" # v4
- run: nix --version
- name: Create Size Report
- uses: "https://git.salame.cl/jalil/nix-flake-outputs-size@838f2050208b41c339803a1111608d7182bbda3e" # main
+ uses: "https://git.salame.cl/jalil/nix-flake-outputs-size@5c40a31e3e2ed0ea28f8ba68deca41d05fdf2e71" # main
with:
# Create a comment on the associated PR
comment-on-pr: ${{ github.ref_name != 'main' }}
diff --git a/.forgejo/workflows/renovate.yml b/.forgejo/workflows/renovate.yml
deleted file mode 100644
index ab1aac5..0000000
--- a/.forgejo/workflows/renovate.yml
+++ /dev/null
@@ -1,14 +0,0 @@
-on:
- push:
- paths:
- # only run if the renovate config changed
- - renovate.json
-jobs:
- check-renovaterc:
- runs-on: nixos
- steps:
- - uses: https://git.salame.cl/actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- - run: nix --version
- - name: Validate renovaterc.json
- run: |
- nix shell nixpkgs#renovate --command renovate-config-validator
diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml
index 1f8ead4..dd7df12 100644
--- a/.github/workflows/check.yml
+++ b/.github/workflows/check.yml
@@ -16,6 +16,7 @@ jobs:
with:
source-url: "https://install.lix.systems/lix/lix-installer-x86_64-linux"
diagnostic-endpoint: ""
+ - uses: DeterminateSystems/magic-nix-cache-action@6221693898146dc97e38ad0e013488a16477a4c4 # v9
- name: Run `nix flake check`
run: |
nix flake check --verbose --keep-going
@@ -24,6 +25,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
+ - uses: DeterminateSystems/magic-nix-cache-action@6221693898146dc97e38ad0e013488a16477a4c4 # v9
- uses: DeterminateSystems/nix-installer-action@v13
with:
source-url: "https://install.lix.systems/lix/lix-installer-x86_64-linux"
diff --git a/renovate.json b/.renovaterc.json
similarity index 83%
rename from renovate.json
rename to .renovaterc.json
index 86737e0..feb16d3 100644
--- a/renovate.json
+++ b/.renovaterc.json
@@ -13,6 +13,11 @@
"config:best-practices"
],
"nix": {
+ "fileMatch": [
+ "(^|/)flake\\.nix$"
+ ],
+ "commitMessageTopic": "nixpkgs",
+ "commitMessageExtra": "to {{newValue}}",
"enabled": true
},
"lockFileMaintenance": {
diff --git a/docs/book.toml b/docs/book.toml
index aa7e72e..d31b799 100644
--- a/docs/book.toml
+++ b/docs/book.toml
@@ -3,14 +3,8 @@ authors = ["Jalil David Salamé Messina"]
language = "en"
multilingual = false
src = "src"
-title = "Jalil's NixOS configuration modules"
-
-[build]
-create-missing = false
+title = "Jalil's NixOS configuration module"
[preprocessor.toc]
command = "mdbook-toc"
renderer = ["html"]
-
-[output.html]
-git-repository-url = "https://github.com/jalil-salame/configuration.nix"
diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md
index 48707f4..16ff37a 100644
--- a/docs/src/SUMMARY.md
+++ b/docs/src/SUMMARY.md
@@ -1,9 +1,6 @@
# Summary
-[Nix Based Configuration](./configuration-overview.md)
-
-- [NixOS Module Options](./nixos-options.md)
-- [Neovim Module Options](./nvim-options.md)
-- [Home Manager Module Options](./home-options.md)
-
-[Search](./search/index.html)
+- [Nix Based Configuration](./configuration-overview.md)
+ - [NixOS Module Options](./nixos-options.md)
+ - [Neovim Module Options](./nvim-options.md)
+ - [Home Manager Module Options](./home-options.md)
diff --git a/example-hm/home.nix b/example-hm/home.nix
deleted file mode 100644
index 4e86064..0000000
--- a/example-hm/home.nix
+++ /dev/null
@@ -1,70 +0,0 @@
-{
- lib,
- pkgs,
- config,
- ...
-}:
-{
- home = {
- homeDirectory = "/home/jdoe";
- stateVersion = "25.05";
- username = "jdoe";
- };
-
- jhome = {
- enable = true;
- dev = {
- enable = true;
- neovimAsManPager = true;
- rust.enable = true;
- };
- gui.enable = false;
- hostName = "example";
- user = {
- enable = true;
- defaultIdentity = {
- email = "jdoe@example.org";
- name = "John Doe";
- };
- };
- };
-
- programs = {
- # Switch to fish if bash is started interactively
- bash.initExtra = ''
- if [[ $(${pkgs.procps}/bin/ps --no-header --pid=$PPID --format=comm) != "fish" && -z ''${BASH_EXECUTION_STRING} ]]
- then
- shopt -q login_shell && LOGIN_OPTION='--login' || LOGIN_OPTION=""
- exec ${pkgs.fish}/bin/fish $LOGIN_OPTION
- fi
- '';
-
- # Enable zellij (tmux like terminal session manager)
- zellij.enable = lib.mkForce true;
- };
-
- nix = {
- package = pkgs.lix;
- gc = {
- automatic = true;
- frequency = "weekly";
- options = "--delete-older-than 30d";
- # run between 0 and 45min after boot if run was missed
- randomizedDelaySec = "45min";
- };
- settings = {
- # Add my personal binary cache to the mix (only for personal computers)
- extra-substituters = [ "https://cache.salame.cl" ];
- extra-trusted-public-keys = [ "cache.salame.cl:D+pBaoutwxja7qKGpju+CmM1LRbVmf2gqEQ/9c7qHrw=" ];
- auto-optimise-store = true;
- };
- };
-
- stylix = {
- image = config.jhome.gui.sway.background;
- base16Scheme = "${pkgs.base16-schemes}/share/themes/gruvbox-dark-hard.yaml";
- };
-
- # Let Home Manager install and manage itself.
- programs.home-manager.enable = true;
-}
diff --git a/example-vm/default.nix b/example-vm/default.nix
deleted file mode 100644
index ab7a40b..0000000
--- a/example-vm/default.nix
+++ /dev/null
@@ -1,41 +0,0 @@
-{
- imports = [ ./vm-config.nix ];
-
- time.timeZone = "Europe/Berlin";
- i18n.defaultLocale = "en_US.UTF-8";
- users.users.jdoe = {
- password = "example";
- isNormalUser = true;
- extraGroups = [
- "wheel"
- "video"
- "networkmanager"
- ];
- };
- home-manager.users.jdoe = {
- home = {
- username = "jdoe";
- homeDirectory = "/home/jdoe";
- stateVersion = "24.11";
- };
- jhome = {
- enable = true;
- gui.enable = true;
- dev = {
- enable = true;
- rust.enable = true;
- };
- };
- };
-
- # password is 'test' see module documentation for more options
- services.jupyter.password = "'sha1:1b961dc713fb:88483270a63e57d18d43cf337e629539de1436ba'";
- jconfig = {
- enable = true;
- dev = {
- enable = true;
- jupyter.enable = true;
- };
- gui.enable = true;
- };
-}
diff --git a/example-vm/vm-config.nix b/example-vm/vm-config.nix
deleted file mode 100644
index 67e38a7..0000000
--- a/example-vm/vm-config.nix
+++ /dev/null
@@ -1,36 +0,0 @@
-## Default QEMU guest config
-{
- services = {
- qemuGuest.enable = true;
- openssh.enable = true;
- };
-
- boot = {
- loader.systemd-boot.enable = true;
- initrd.availableKernelModules = [
- "xhci_pci"
- "ehci_pci"
- "ahci"
- "usbhid"
- "usb_storage"
- "sd_mod"
- "virtio_balloon"
- "virtio_blk"
- "virtio_pci"
- "virtio_ring"
- # "virtio_vga"
- "virtio_gpu"
- ];
- };
- fileSystems."/".device = "/dev/disk/by-label/nixos";
-
- # This value determines the NixOS release from which the default
- # settings for stateful data, like file locations and database versions
- # on your system were taken. It‘s perfectly fine and recommended to leave
- # this value at the release version of the first install of this system.
- # Before changing this value read the documentation for this option
- # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
- system.stateVersion = "24.11"; # Did you read the comment?
-
- nixpkgs.hostPlatform = "x86_64-linux";
-}
diff --git a/flake-modules/default.nix b/flake-modules/default.nix
index 1b806a6..050721e 100644
--- a/flake-modules/default.nix
+++ b/flake-modules/default.nix
@@ -1,21 +1,25 @@
{ inputs, ... }:
+let
+ overlays = builtins.attrValues inputs.self.overlays;
+in
{
imports = [
inputs.treefmt-nix.flakeModule
./devshells.nix
./docs.nix
- ./example-configs.nix
+ ./example-vm.nix
./nixos-modules.nix
- ./home-modules.nix
- ./nixvim-modules.nix
+ ./nvim.nix
./overlays.nix
- ../scripts
+ ./scripts.nix
];
perSystem =
{ system, ... }:
{
+ _module.args.pkgs = import inputs.nixpkgs { inherit system overlays; };
+
# Setup formatters
treefmt = {
projectRootFile = "flake.nix";
diff --git a/flake-modules/devshells.nix b/flake-modules/devshells.nix
index f9eeaa4..962c4bf 100644
--- a/flake-modules/devshells.nix
+++ b/flake-modules/devshells.nix
@@ -4,12 +4,8 @@ _: {
{
devShells.default = pkgs.mkShellNoCC {
buildInputs = [
- self'.packages.nvim
-
pkgs.just
- pkgs.nix-diff
- pkgs.nvd
- pkgs.uv
+ self'.packages.nvim
];
QEMU_OPTS_WL = "-enable-kvm -nodefaults -m 4G -cpu host -smp 4 -device virtio-gpu";
};
diff --git a/flake-modules/docs.nix b/flake-modules/docs.nix
index 594d592..cc85766 100644
--- a/flake-modules/docs.nix
+++ b/flake-modules/docs.nix
@@ -1,50 +1,45 @@
-{ lib, ... }:
+{ lib, inputs, ... }:
{
perSystem =
- { inputs', pkgs, ... }:
+ { pkgs, ... }:
{
packages =
let
filterVisible =
toplevelOption: option:
option // { visible = option.visible && builtins.elemAt option.loc 0 == toplevelOption; };
- genOptionsDoc =
- toplevelOption: module:
- pkgs.nixosOptionsDoc {
- inherit (lib.evalModules { modules = [ module ]; }) options;
- transformOptions = filterVisible toplevelOption;
+ home-eval = lib.evalModules {
+ modules = [ ../home/options.nix ];
+ specialArgs = {
+ inherit pkgs;
};
- mkScope = name: options: {
- inherit name;
- optionsJSON = "${options.optionsJSON}/share/doc/nixos/options.json";
- urlPrefix = "https://github.com/jalil-salame/configuration.nix/blob/main/";
};
- search = inputs'.nuschtosSearch.packages.mkMultiSearch {
- title = "Search Jalil's configuration.nix";
- baseHref = "/";
-
- scopes = [
- (mkScope "NixOS" nixos)
- (mkScope "Home-Manager" home)
- (mkScope "NixVIM" nvim)
- ];
- };
- home = genOptionsDoc "jhome" ../modules/hm/options.nix;
- nvim = genOptionsDoc "jhome" ../modules/nixvim/options.nix;
- nixos = genOptionsDoc "jconfig" ../modules/nixos/options.nix;
- nixos-markdown = nixos.optionsCommonMark;
- home-markdown = home.optionsCommonMark;
- nvim-markdown = nvim.optionsCommonMark;
+ nvim-eval = lib.evalModules { modules = [ ../nvim/options.nix ]; };
+ nixos-eval = lib.evalModules { modules = [ ../system/options.nix ]; };
+ home-markdown =
+ (pkgs.nixosOptionsDoc {
+ inherit (home-eval) options;
+ transformOptions = filterVisible "jhome";
+ }).optionsCommonMark;
+ nvim-markdown =
+ (pkgs.nixosOptionsDoc {
+ inherit (nvim-eval) options;
+ transformOptions = filterVisible "jhome";
+ }).optionsCommonMark;
+ nixos-markdown =
+ (pkgs.nixosOptionsDoc {
+ inherit (nixos-eval) options;
+ transformOptions = filterVisible "jconfig";
+ }).optionsCommonMark;
in
{
- inherit search;
docs-home-markdown = home-markdown;
docs-nixos-markdown = nixos-markdown;
docs-nvim-markdown = nvim-markdown;
# Documentation
docs = pkgs.stdenvNoCC.mkDerivation {
name = "nixos-configuration-book";
- src = ../docs;
+ src = inputs.self + "/docs";
patchPhase = ''
cleanup_md() {
@@ -57,9 +52,7 @@
cleanup_md ${home-markdown} >> ./src/home-options.md
cleanup_md ${nvim-markdown} >> ./src/nvim-options.md
cleanup_md ${nixos-markdown} >> ./src/nixos-options.md
- # link search site
- ln -s "${search.override { baseHref = "/configuration.nix/search/"; }}" ./src/search
- ''; # FIXME: only add the `/configuration.nix/` part for GH CI
+ '';
nativeBuildInputs = [ pkgs.mdbook-toc ];
buildPhase = "${pkgs.mdbook}/bin/mdbook build --dest-dir $out";
diff --git a/flake-modules/example-configs.nix b/flake-modules/example-configs.nix
deleted file mode 100644
index 362e36a..0000000
--- a/flake-modules/example-configs.nix
+++ /dev/null
@@ -1,33 +0,0 @@
-{ inputs, lib, ... }:
-{
- flake = {
- # Example vm configuration
- nixosConfigurations.vm = lib.nixosSystem {
- modules = [
- inputs.self.nixosModules.default
- ../example-vm # import vm configuration
- {
- nixpkgs = {
- overlays = builtins.attrValues inputs.self.overlays;
- config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [ "steam-unwrapped" ];
- };
- # pin nixpkgs to the one used by the system
- nix.registry.nixpkgs.flake = inputs.nixpkgs;
- }
- ];
- };
- homeConfigurations.example = inputs.home-manager.lib.homeManagerConfiguration {
- pkgs = inputs.nixpkgs.legacyPackages.x86_64-linux;
- modules = [
- inputs.self.homeModules.standalone
- ../example-hm/home.nix # import home-manager configuration
- {
- nixpkgs.overlays = [
- inputs.self.overlays.unstable
- inputs.lix-module.overlays.default
- ];
- }
- ];
- };
- };
-}
diff --git a/flake-modules/example-vm.nix b/flake-modules/example-vm.nix
new file mode 100644
index 0000000..a8ce4b3
--- /dev/null
+++ b/flake-modules/example-vm.nix
@@ -0,0 +1,55 @@
+{ inputs, lib, ... }:
+let
+ system = "x86_64-linux";
+ overlays = builtins.attrValues inputs.self.overlays;
+ config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [ "steam-unwrapped" ];
+ pkgs = import inputs.nixpkgs { inherit system overlays config; };
+in
+{
+ # Example vm configuration
+ flake.nixosConfigurations.vm = lib.nixosSystem {
+ inherit system pkgs;
+ modules = [
+ inputs.self.nixosModules.vm # import vm module
+ {
+ time.timeZone = "Europe/Berlin";
+ i18n.defaultLocale = "en_US.UTF-8";
+ users.users.jdoe = {
+ password = "example";
+ isNormalUser = true;
+ extraGroups = [
+ "wheel"
+ "video"
+ "networkmanager"
+ ];
+ };
+ home-manager.users.jdoe = {
+ home = {
+ username = "jdoe";
+ homeDirectory = "/home/jdoe";
+ };
+ jhome = {
+ enable = true;
+ gui.enable = true;
+ dev = {
+ enable = true;
+ rust.enable = true;
+ };
+ };
+ };
+ nix.registry.nixpkgs.flake = inputs.nixpkgs;
+ # password is 'test' see module documentation for more options
+ services.jupyter.password = "'sha1:1b961dc713fb:88483270a63e57d18d43cf337e629539de1436ba'";
+ jconfig = {
+ enable = true;
+ dev = {
+ enable = true;
+ jupyter.enable = true;
+ };
+ gui.enable = true;
+ };
+ }
+ ];
+ };
+
+}
diff --git a/flake-modules/home-modules.nix b/flake-modules/home-modules.nix
deleted file mode 100644
index 6c9ae51..0000000
--- a/flake-modules/home-modules.nix
+++ /dev/null
@@ -1,30 +0,0 @@
-{ self, inputs, ... }:
-{
- imports = [ inputs.home-manager.flakeModules.home-manager ];
-
- flake.homeModules =
- let
- defaultModules = [
- inputs.nixvim.homeModules.nixvim
- self.nixvimModules.homeManager
- ../modules/hm
- ];
- nixos = {
- imports = defaultModules;
- };
- standalone = {
- imports = defaultModules ++ [
- inputs.stylix.homeModules.stylix
- (
- { lib, config, ... }:
- lib.mkIf config.jhome.gui.enable {
- stylix.image = config.jhome.gui.sway.background;
- }
- )
- ];
- };
- in
- {
- inherit standalone nixos;
- };
-}
diff --git a/flake-modules/nixos-modules.nix b/flake-modules/nixos-modules.nix
index ef8355e..70fb0fb 100644
--- a/flake-modules/nixos-modules.nix
+++ b/flake-modules/nixos-modules.nix
@@ -1,29 +1,46 @@
-{
- self,
- inputs,
- lib,
- ...
-}:
+{ inputs, lib, ... }:
{
flake.nixosModules =
let
+ nvim-config = {
+ imports = [
+ inputs.nixvim.homeManagerModules.nixvim
+ ../nvim
+ ];
+ };
+ homeManagerModuleSandalone = import ../home {
+ inherit nvim-config;
+ inherit (inputs) stylix;
+ };
+ homeManagerModuleNixOS = import ../home { inherit nvim-config; };
nixosModule = {
imports = [
- inputs.stylix.nixosModules.stylix
+ (import ../system { inherit (inputs) stylix; })
+ inputs.niri.nixosModules.niri
inputs.home-manager.nixosModules.home-manager
- ../modules/nixos
] ++ lib.optional (inputs.lix-module != null) inputs.lix-module.nixosModules.default;
home-manager = {
useGlobalPkgs = true;
useUserPackages = true;
- sharedModules = [ self.homeModules.nixos ];
+ sharedModules = [ homeManagerModuleNixOS ];
};
# Pin nixpkgs
nix.registry.nixpkgs.flake = inputs.nixpkgs;
};
+
+ machines = [ "vm" ];
+ mkMachine = hostname: {
+ imports = [
+ nixosModule
+ (import (../machines + "/${hostname}"))
+ ];
+ home-manager.sharedModules = [ { jhome.hostName = hostname; } ];
+ };
+ machineModules = lib.genAttrs machines mkMachine;
in
{
default = nixosModule;
- inherit nixosModule;
- };
+ inherit nixosModule homeManagerModuleNixOS homeManagerModuleSandalone;
+ }
+ // machineModules;
}
diff --git a/flake-modules/nixvim-modules.nix b/flake-modules/nixvim-modules.nix
deleted file mode 100644
index b40b0dd..0000000
--- a/flake-modules/nixvim-modules.nix
+++ /dev/null
@@ -1,62 +0,0 @@
-{ self, inputs, ... }:
-{
- imports = [ inputs.nixvim.flakeModules.default ];
-
- nixvim = {
- packages.enable = true;
- checks.enable = false; # FIXME: borked due to nix-community/nixvim#3074
- };
-
- flake.nixvimModules =
- let
- module = ../modules/nixvim;
- in
- {
- standalone = "${module}/standalone.nix";
- homeManager = module;
- };
-
- perSystem =
- { system, ... }:
- let
- nvimModule = extraConfig: {
- inherit system;
- modules = [
- self.nixvimModules.standalone
- # FIXME: borked due to https://github.com/nix-community/nixvim/issues/3140
- # { performance.combinePlugins.enable = true; }
- extraConfig
- ];
- };
- modules = {
- nvim = nvimModule { };
- # Smaller derivations
- nvim-headless = nvimModule {
- jhome.nvim.dev.enable = false;
- jhome.nvim.reduceSize = true;
- };
- nvim-small = nvimModule {
- jhome.nvim.dev.bundleLSPs = false;
- };
- nvim-no-ts = nvimModule {
- jhome.nvim.dev.bundleGrammars = false;
- };
- nvim-no-lsps = nvimModule {
- jhome.nvim.dev = {
- bundleLSPs = false;
- bundleGrammars = false;
- };
- };
- };
- in
- {
- checks = builtins.mapAttrs (
- _name: module:
- inputs.nixvim.lib.${system}.check.mkTestDerivationFromNixvimModule {
- module.imports = module.modules;
- }
- ) modules;
-
- nixvimConfigurations = builtins.mapAttrs (_name: inputs.nixvim.lib.evalNixvim) modules;
- };
-}
diff --git a/flake-modules/nvim.nix b/flake-modules/nvim.nix
new file mode 100644
index 0000000..89832f3
--- /dev/null
+++ b/flake-modules/nvim.nix
@@ -0,0 +1,53 @@
+{ inputs, ... }:
+{
+ perSystem =
+ { lib, system, ... }:
+ let
+ nixvimLib = inputs.nixvim.lib.${system};
+ nixvim = inputs.nixvim.legacyPackages.${system};
+ testNvimModule = nixvimLib.check.mkTestDerivationFromNixvimModule;
+ nvimModule = extraConfig: {
+ pkgs = inputs.unstable.legacyPackages.${system};
+ module = {
+ imports = [ ../nvim/standalone.nix ];
+ config = lib.mkMerge [
+ { performance.combinePlugins.enable = true; }
+ extraConfig
+ ];
+ };
+ };
+ moduleDev = nvimModule { };
+ moduleHeadless = nvimModule {
+ jhome.nvim.dev.enable = false;
+ jhome.nvim.reduceSize = true;
+ };
+ moduleNoLsp = nvimModule { jhome.nvim.dev.bundleLSPs = false; };
+ moduleNoTSGrammars = nvimModule { jhome.nvim.dev.bundleGrammars = false; };
+ moduleNoBundledBins = nvimModule {
+ jhome.nvim.dev = {
+ bundleLSPs = false;
+ bundleGrammars = false;
+ };
+ };
+ in
+ {
+ # Check standalone nvim build
+ checks = {
+ nvimDev = testNvimModule moduleDev;
+ nvimHeadless = testNvimModule moduleHeadless;
+ nvimNoLsp = testNvimModule moduleNoLsp;
+ nvimNoTSGrammars = testNvimModule moduleNoTSGrammars;
+ nvimNoBundledBins = testNvimModule moduleNoBundledBins;
+ };
+
+ # Nvim standalone module
+ packages = {
+ nvim = nixvim.makeNixvimWithModule moduleDev;
+ # Smaller derivations
+ nvim-headless = nixvim.makeNixvimWithModule moduleHeadless;
+ nvim-small = nixvim.makeNixvimWithModule moduleNoBundledBins;
+ nvim-no-ts = nixvim.makeNixvimWithModule moduleNoTSGrammars;
+ nvim-no-lsps = nixvim.makeNixvimWithModule moduleNoLsp;
+ };
+ };
+}
diff --git a/flake-modules/scripts.nix b/flake-modules/scripts.nix
new file mode 100644
index 0000000..590f6a1
--- /dev/null
+++ b/flake-modules/scripts.nix
@@ -0,0 +1,14 @@
+let
+ scripts = import ../scripts;
+in
+{
+ # Add scripts to overlay
+ flake.overlays.scripts = final: prev: scripts final;
+
+ # Add scripts to packages
+ perSystem =
+ { pkgs, ... }:
+ {
+ packages = scripts pkgs;
+ };
+}
diff --git a/flake.lock b/flake.lock
index 1d6c7f2..5f95dd5 100644
--- a/flake.lock
+++ b/flake.lock
@@ -5,11 +5,11 @@
"fromYaml": "fromYaml"
},
"locked": {
- "lastModified": 1746562888,
- "narHash": "sha256-YgNJQyB5dQiwavdDFBMNKk1wyS77AtdgDk/VtU6wEaI=",
+ "lastModified": 1732200724,
+ "narHash": "sha256-+R1BH5wHhfnycySb7Sy5KbYEaTJZWm1h+LW1OtyhiTs=",
"owner": "SenchoPens",
"repo": "base16.nix",
- "rev": "806a1777a5db2a1ef9d5d6f493ef2381047f2b89",
+ "rev": "153d52373b0fb2d343592871009a286ec8837aec",
"type": "github"
},
"original": {
@@ -37,11 +37,11 @@
"base16-helix": {
"flake": false,
"locked": {
- "lastModified": 1748408240,
- "narHash": "sha256-9M2b1rMyMzJK0eusea0x3lyh3mu5nMeEDSc4RZkGm+g=",
+ "lastModified": 1736852337,
+ "narHash": "sha256-esD42YdgLlEh7koBrSqcT7p2fsMctPAcGl/+2sYJa2o=",
"owner": "tinted-theming",
"repo": "base16-helix",
- "rev": "6c711ab1a9db6f51e2f6887cc3345530b33e152e",
+ "rev": "03860521c40b0b9c04818f2218d9cc9efc21e7a5",
"type": "github"
},
"original": {
@@ -70,11 +70,11 @@
"firefox-gnome-theme": {
"flake": false,
"locked": {
- "lastModified": 1748383148,
- "narHash": "sha256-pGvD/RGuuPf/4oogsfeRaeMm6ipUIznI2QSILKjKzeA=",
+ "lastModified": 1739223196,
+ "narHash": "sha256-vAxN2f3rvl5q62gQQjZGVSvF93nAsOxntuFz+e/655w=",
"owner": "rafaelmardojai",
"repo": "firefox-gnome-theme",
- "rev": "4eb2714fbed2b80e234312611a947d6cb7d70caf",
+ "rev": "a89108e6272426f4eddd93ba17d0ea101c34fb21",
"type": "github"
},
"original": {
@@ -90,11 +90,11 @@
]
},
"locked": {
- "lastModified": 1751413152,
- "narHash": "sha256-Tyw1RjYEsp5scoigs1384gIg6e0GoBVjms4aXFfRssQ=",
+ "lastModified": 1741352980,
+ "narHash": "sha256-+u2UunDA4Cl5Fci3m7S643HzKmIDAe+fiXrLqYsR2fs=",
"owner": "hercules-ci",
"repo": "flake-parts",
- "rev": "77826244401ea9de6e3bac47c2db46005e1f30b5",
+ "rev": "f4330d22f1c5d2ba72d3d22df5597d123fdb60a9",
"type": "github"
},
"original": {
@@ -167,11 +167,11 @@
]
},
"locked": {
- "lastModified": 1750779888,
- "narHash": "sha256-wibppH3g/E2lxU43ZQHC5yA/7kIKLGxVEnsnVK1BtRg=",
+ "lastModified": 1737465171,
+ "narHash": "sha256-R10v2hoJRLq8jcL4syVFag7nIGE7m13qO48wRIukWNg=",
"owner": "cachix",
"repo": "git-hooks.nix",
- "rev": "16ec914f6fb6f599ce988427d9d94efddf25fe6d",
+ "rev": "9364dc02281ce2d37a1f55b6e51f7c0f65a75f17",
"type": "github"
},
"original": {
@@ -205,16 +205,16 @@
"gnome-shell": {
"flake": false,
"locked": {
- "lastModified": 1744584021,
- "narHash": "sha256-0RJ4mJzf+klKF4Fuoc8VN8dpQQtZnKksFmR2jhWE1Ew=",
+ "lastModified": 1732369855,
+ "narHash": "sha256-JhUWbcYPjHO3Xs3x9/Z9RuqXbcp5yhPluGjwsdE2GMg=",
"owner": "GNOME",
"repo": "gnome-shell",
- "rev": "52c517c8f6c199a1d6f5118fae500ef69ea845ae",
+ "rev": "dadd58f630eeea41d645ee225a63f719390829dc",
"type": "github"
},
"original": {
"owner": "GNOME",
- "ref": "48.1",
+ "ref": "47.2",
"repo": "gnome-shell",
"type": "github"
}
@@ -226,58 +226,32 @@
]
},
"locked": {
- "lastModified": 1751468302,
- "narHash": "sha256-tWosziZTT039x6PgEZUhzGlV8oLvdDmIgKTE8ESMaEA=",
+ "lastModified": 1739757849,
+ "narHash": "sha256-Gs076ot1YuAAsYVcyidLKUMIc4ooOaRGO0PqTY7sBzA=",
"owner": "nix-community",
"repo": "home-manager",
- "rev": "501cfec8277f931a9c9af9f23d3105c537faeafe",
+ "rev": "9d3d080aec2a35e05a15cedd281c2384767c2cfe",
"type": "github"
},
"original": {
"owner": "nix-community",
- "ref": "release-25.05",
+ "ref": "release-24.11",
"repo": "home-manager",
"type": "github"
}
},
- "ixx": {
- "inputs": {
- "flake-utils": [
- "nuschtosSearch",
- "flake-utils"
- ],
- "nixpkgs": [
- "nuschtosSearch",
- "nixpkgs"
- ]
- },
- "locked": {
- "lastModified": 1748294338,
- "narHash": "sha256-FVO01jdmUNArzBS7NmaktLdGA5qA3lUMJ4B7a05Iynw=",
- "owner": "NuschtOS",
- "repo": "ixx",
- "rev": "cc5f390f7caf265461d4aab37e98d2292ebbdb85",
- "type": "github"
- },
- "original": {
- "owner": "NuschtOS",
- "ref": "v0.0.8",
- "repo": "ixx",
- "type": "github"
- }
- },
"lix": {
"flake": false,
"locked": {
- "lastModified": 1751235704,
- "narHash": "sha256-J4ycLoXHPsoBoQtEXFCelL4xlq5pT8U9tNWNKm43+YI=",
- "rev": "1d7368585eebaa2c4bdbcb88fe600cfb2239b2c6",
+ "lastModified": 1737234286,
+ "narHash": "sha256-CCKIAE84dzkrnlxJCKFyffAxP3yfsOAbdvydUGqq24g=",
+ "rev": "2837da71ec1588c1187d2e554719b15904a46c8b",
"type": "tarball",
- "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/1d7368585eebaa2c4bdbcb88fe600cfb2239b2c6.tar.gz?rev=1d7368585eebaa2c4bdbcb88fe600cfb2239b2c6"
+ "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/2837da71ec1588c1187d2e554719b15904a46c8b.tar.gz?rev=2837da71ec1588c1187d2e554719b15904a46c8b"
},
"original": {
"type": "tarball",
- "url": "https://git.lix.systems/lix-project/lix/archive/release-2.93.tar.gz"
+ "url": "https://git.lix.systems/lix-project/lix/archive/2.92.0.tar.gz"
}
},
"lix-module": {
@@ -290,28 +264,91 @@
]
},
"locked": {
- "lastModified": 1751240025,
- "narHash": "sha256-SXUAlxpjPRkArRMHy5+Hdi+PiC+ND9yzzIjiaHmTvQU=",
- "rev": "8b1094356f4723d6e89d3f8a95b333ee16d9ab02",
+ "lastModified": 1737237494,
+ "narHash": "sha256-YMLrcBpf0TR5r/eaqm8lxzFPap2TxCor0ZGcK3a7+b8=",
+ "rev": "b90bf629bbd835e61f1317b99e12f8c831017006",
"type": "tarball",
- "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/8b1094356f4723d6e89d3f8a95b333ee16d9ab02.tar.gz?rev=8b1094356f4723d6e89d3f8a95b333ee16d9ab02"
+ "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/b90bf629bbd835e61f1317b99e12f8c831017006.tar.gz?rev=b90bf629bbd835e61f1317b99e12f8c831017006"
},
"original": {
"type": "tarball",
- "url": "https://git.lix.systems/lix-project/nixos-module/archive/release-2.93.tar.gz"
+ "url": "https://git.lix.systems/lix-project/nixos-module/archive/2.92.0.tar.gz"
+ }
+ },
+ "niri": {
+ "inputs": {
+ "niri-stable": "niri-stable",
+ "niri-unstable": [],
+ "nixpkgs": [
+ "nixpkgs"
+ ],
+ "nixpkgs-stable": [
+ "nixpkgs"
+ ],
+ "xwayland-satellite-stable": "xwayland-satellite-stable",
+ "xwayland-satellite-unstable": []
+ },
+ "locked": {
+ "lastModified": 1741686876,
+ "narHash": "sha256-Kt37Zm9YcQoe/aRVbPFydZcfwIrEAg/U+iz3FcxsOZs=",
+ "owner": "sodiboo",
+ "repo": "niri-flake",
+ "rev": "fa230971ab63885ba5666588a7b78f75f73d5a85",
+ "type": "github"
+ },
+ "original": {
+ "owner": "sodiboo",
+ "repo": "niri-flake",
+ "type": "github"
+ }
+ },
+ "niri-stable": {
+ "flake": false,
+ "locked": {
+ "lastModified": 1740117926,
+ "narHash": "sha256-mTTHA0RAaQcdYe+9A3Jx77cmmyLFHmRoZdd8RpWa+m8=",
+ "owner": "YaLTeR",
+ "repo": "niri",
+ "rev": "b94a5db8790339cf9134873d8b490be69e02ac71",
+ "type": "github"
+ },
+ "original": {
+ "owner": "YaLTeR",
+ "ref": "v25.02",
+ "repo": "niri",
+ "type": "github"
}
},
"nixpkgs": {
"locked": {
- "lastModified": 1751652329,
- "narHash": "sha256-QFeGjfEn4dxrsAKvDBBzJkdDzw360BC5lp9SUs3BNbY=",
- "rev": "7a732ed41ca0dd64b4b71b563ab9805a80a7d693",
- "type": "tarball",
- "url": "https://releases.nixos.org/nixos/25.05/nixos-25.05.805766.7a732ed41ca0/nixexprs.tar.xz?rev=7a732ed41ca0dd64b4b71b563ab9805a80a7d693"
+ "lastModified": 1741445498,
+ "narHash": "sha256-F5Em0iv/CxkN5mZ9hRn3vPknpoWdcdCyR0e4WklHwiE=",
+ "owner": "NixOS",
+ "repo": "nixpkgs",
+ "rev": "52e3095f6d812b91b22fb7ad0bfc1ab416453634",
+ "type": "github"
},
"original": {
- "type": "tarball",
- "url": "https://channels.nixos.org/nixos-25.05/nixexprs.tar.xz"
+ "owner": "NixOS",
+ "ref": "nixos-24.11",
+ "repo": "nixpkgs",
+ "type": "github"
+ }
+ },
+ "nixpkgs_2": {
+ "locked": {
+ "lastModified": 1738797219,
+ "narHash": "sha256-KRwX9Z1XavpgeSDVM/THdFd6uH8rNm/6R+7kIbGa+2s=",
+ "owner": "NixOS",
+ "repo": "nixpkgs",
+ "rev": "1da52dd49a127ad74486b135898da2cef8c62665",
+ "type": "github"
+ },
+ "original": {
+ "owner": "NixOS",
+ "ref": "nixpkgs-unstable",
+ "repo": "nixpkgs",
+ "type": "github"
}
},
"nixvim": {
@@ -319,20 +356,15 @@
"flake-parts": [
"flake-parts"
],
- "nixpkgs": [
- "unstable"
- ],
- "nuschtosSearch": [],
- "systems": [
- "systems"
- ]
+ "nixpkgs": "nixpkgs_2",
+ "nuschtosSearch": []
},
"locked": {
- "lastModified": 1751746175,
- "narHash": "sha256-6JABU+UMkaL4c+ZJRQYyFyIkm9ry1fOkhNQgSSjK5OM=",
+ "lastModified": 1741098523,
+ "narHash": "sha256-gXDSXDr6tAb+JgxGMvcEjKC9YO8tVOd8hMMZHJLyQ6Q=",
"owner": "nix-community",
"repo": "nixvim",
- "rev": "ef0fa015a8236241bdcc27f32e6a4aa537d96cf8",
+ "rev": "03065fd4708bfdf47dd541d655392a60daa25ded",
"type": "github"
},
"original": {
@@ -341,43 +373,21 @@
"type": "github"
}
},
- "nuschtosSearch": {
- "inputs": {
- "flake-utils": [
- "lix-module",
- "flake-utils"
- ],
- "ixx": "ixx",
- "nixpkgs": [
- "nixpkgs"
- ]
- },
- "locked": {
- "lastModified": 1749730855,
- "narHash": "sha256-L3x2nSlFkXkM6tQPLJP3oCBMIsRifhIDPMQQdHO5xWo=",
- "owner": "NuschtOS",
- "repo": "search",
- "rev": "8dfe5879dd009ff4742b668d9c699bc4b9761742",
- "type": "github"
- },
- "original": {
- "owner": "NuschtOS",
- "repo": "search",
- "type": "github"
- }
- },
"root": {
"inputs": {
"flake-parts": "flake-parts",
"home-manager": "home-manager",
"lix-module": "lix-module",
+ "niri": "niri",
"nixpkgs": "nixpkgs",
"nixvim": "nixvim",
- "nuschtosSearch": "nuschtosSearch",
"stylix": "stylix",
"systems": "systems",
"treefmt-nix": "treefmt-nix",
- "unstable": "unstable"
+ "unstable": [
+ "nixvim",
+ "nixpkgs"
+ ]
}
},
"stylix": {
@@ -388,8 +398,9 @@
"base16-vim": "base16-vim",
"firefox-gnome-theme": "firefox-gnome-theme",
"flake-compat": [],
- "flake-parts": [
- "flake-parts"
+ "flake-utils": [
+ "lix-module",
+ "flake-utils"
],
"git-hooks": "git-hooks",
"gnome-shell": "gnome-shell",
@@ -399,27 +410,24 @@
"nixpkgs": [
"nixpkgs"
],
- "nur": [],
"systems": [
"systems"
],
"tinted-foot": "tinted-foot",
"tinted-kitty": "tinted-kitty",
- "tinted-schemes": "tinted-schemes",
- "tinted-tmux": "tinted-tmux",
- "tinted-zed": "tinted-zed"
+ "tinted-tmux": "tinted-tmux"
},
"locked": {
- "lastModified": 1751658706,
- "narHash": "sha256-jqRbWjB8aH2qzq6nMQpwkzVBR4o9lNxAHFmRgGwnJ94=",
- "owner": "nix-community",
+ "lastModified": 1740520580,
+ "narHash": "sha256-QRlcA8rtfNdyKpBE+ptjiB9717Tzum4/sKBSbsyqL6k=",
+ "owner": "danth",
"repo": "stylix",
- "rev": "5dd301b72207d4fd8d8b929abd88ba1c486d1744",
+ "rev": "aaa2eb8956770c096f9c46fb163bb26602e20e56",
"type": "github"
},
"original": {
- "owner": "nix-community",
- "ref": "release-25.05",
+ "owner": "danth",
+ "ref": "release-24.11",
"repo": "stylix",
"type": "github"
}
@@ -459,43 +467,28 @@
"tinted-kitty": {
"flake": false,
"locked": {
- "lastModified": 1735730497,
- "narHash": "sha256-4KtB+FiUzIeK/4aHCKce3V9HwRvYaxX+F1edUrfgzb8=",
+ "lastModified": 1716423189,
+ "narHash": "sha256-2xF3sH7UIwegn+2gKzMpFi3pk5DlIlM18+vj17Uf82U=",
"owner": "tinted-theming",
"repo": "tinted-kitty",
- "rev": "de6f888497f2c6b2279361bfc790f164bfd0f3fa",
+ "rev": "eb39e141db14baef052893285df9f266df041ff8",
"type": "github"
},
"original": {
"owner": "tinted-theming",
"repo": "tinted-kitty",
- "type": "github"
- }
- },
- "tinted-schemes": {
- "flake": false,
- "locked": {
- "lastModified": 1750770351,
- "narHash": "sha256-LI+BnRoFNRa2ffbe3dcuIRYAUcGklBx0+EcFxlHj0SY=",
- "owner": "tinted-theming",
- "repo": "schemes",
- "rev": "5a775c6ffd6e6125947b393872cde95867d85a2a",
- "type": "github"
- },
- "original": {
- "owner": "tinted-theming",
- "repo": "schemes",
+ "rev": "eb39e141db14baef052893285df9f266df041ff8",
"type": "github"
}
},
"tinted-tmux": {
"flake": false,
"locked": {
- "lastModified": 1751159871,
- "narHash": "sha256-UOHBN1fgHIEzvPmdNMHaDvdRMgLmEJh2hNmDrp3d3LE=",
+ "lastModified": 1740272597,
+ "narHash": "sha256-/etfUV3HzAaLW3RSJVwUaW8ULbMn3v6wbTlXSKbcoWQ=",
"owner": "tinted-theming",
"repo": "tinted-tmux",
- "rev": "bded5e24407cec9d01bd47a317d15b9223a1546c",
+ "rev": "b6c7f46c8718cc484f2db8b485b06e2a98304cd0",
"type": "github"
},
"original": {
@@ -504,22 +497,6 @@
"type": "github"
}
},
- "tinted-zed": {
- "flake": false,
- "locked": {
- "lastModified": 1751158968,
- "narHash": "sha256-ksOyv7D3SRRtebpXxgpG4TK8gZSKFc4TIZpR+C98jX8=",
- "owner": "tinted-theming",
- "repo": "base16-zed",
- "rev": "86a470d94204f7652b906ab0d378e4231a5b3384",
- "type": "github"
- },
- "original": {
- "owner": "tinted-theming",
- "repo": "base16-zed",
- "type": "github"
- }
- },
"treefmt-nix": {
"inputs": {
"nixpkgs": [
@@ -527,11 +504,11 @@
]
},
"locked": {
- "lastModified": 1750931469,
- "narHash": "sha256-0IEdQB1nS+uViQw4k3VGUXntjkDp7aAlqcxdewb/hAc=",
+ "lastModified": 1739829690,
+ "narHash": "sha256-mL1szCeIsjh6Khn3nH2cYtwO5YXG6gBiTw1A30iGeDU=",
"owner": "numtide",
"repo": "treefmt-nix",
- "rev": "ac8e6f32e11e9c7f153823abc3ab007f2a65d3e1",
+ "rev": "3d0579f5cc93436052d94b73925b48973a104204",
"type": "github"
},
"original": {
@@ -540,17 +517,21 @@
"type": "github"
}
},
- "unstable": {
+ "xwayland-satellite-stable": {
+ "flake": false,
"locked": {
- "lastModified": 1751734347,
- "narHash": "sha256-EzgiAGp3yKKlpkjPRXL+sVhVNmp46lyq3BadLEqMeQM=",
- "rev": "5c724ed1388e53cc231ed98330a60eb2f7be4be3",
- "type": "tarball",
- "url": "https://releases.nixos.org/nixos/unstable/nixos-25.11pre824861.5c724ed1388e/nixexprs.tar.xz?rev=5c724ed1388e53cc231ed98330a60eb2f7be4be3"
+ "lastModified": 1739246919,
+ "narHash": "sha256-/hBM43/Gd0/tW+egrhlWgOIISeJxEs2uAOIYVpfDKeU=",
+ "owner": "Supreeeme",
+ "repo": "xwayland-satellite",
+ "rev": "44590a416d4a3e8220e19e29e0b6efe64a80315d",
+ "type": "github"
},
"original": {
- "type": "tarball",
- "url": "https://channels.nixos.org/nixos-unstable/nixexprs.tar.xz"
+ "owner": "Supreeeme",
+ "ref": "v0.5.1",
+ "repo": "xwayland-satellite",
+ "type": "github"
}
}
},
diff --git a/flake.nix b/flake.nix
index 795adef..1ad8772 100644
--- a/flake.nix
+++ b/flake.nix
@@ -8,11 +8,11 @@
# Flake inputs
inputs = {
- nixpkgs.url = "https://channels.nixos.org/nixos-25.05/nixexprs.tar.xz";
- unstable.url = "https://channels.nixos.org/nixos-unstable/nixexprs.tar.xz";
+ nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11";
+ unstable.follows = "nixvim/nixpkgs";
# Lix
lix-module = {
- url = "https://git.lix.systems/lix-project/nixos-module/archive/release-2.93.tar.gz";
+ url = "https://git.lix.systems/lix-project/nixos-module/archive/2.92.0.tar.gz";
inputs = {
nixpkgs.follows = "nixpkgs";
flake-utils.inputs.systems.follows = "systems";
@@ -20,16 +20,24 @@
};
# Modules
home-manager = {
- url = "github:nix-community/home-manager/release-25.05";
+ url = "github:nix-community/home-manager/release-24.11";
inputs.nixpkgs.follows = "nixpkgs";
};
- stylix = {
- url = "github:nix-community/stylix/release-25.05";
+ niri = {
+ url = "github:sodiboo/niri-flake";
inputs = {
nixpkgs.follows = "nixpkgs";
- flake-parts.follows = "flake-parts";
+ nixpkgs-stable.follows = "nixpkgs";
+ niri-unstable.follows = "";
+ xwayland-satellite-unstable.follows = "";
+ };
+ };
+ stylix = {
+ url = "github:danth/stylix/release-24.11";
+ inputs = {
+ nixpkgs.follows = "nixpkgs";
+ flake-utils.follows = "lix-module/flake-utils";
systems.follows = "systems";
- nur.follows = "";
home-manager.follows = "home-manager";
# disable optional inputs
@@ -40,8 +48,6 @@
url = "github:nix-community/nixvim";
inputs = {
flake-parts.follows = "flake-parts";
- systems.follows = "systems";
- nixpkgs.follows = "unstable";
# disable optional inputs
nuschtosSearch.follows = "";
};
@@ -50,19 +56,10 @@
url = "github:hercules-ci/flake-parts";
inputs.nixpkgs-lib.follows = "nixpkgs";
};
- # For the formatter (can be set to null)
treefmt-nix = {
url = "github:numtide/treefmt-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
- # For generating the docs (can be set to null)
- nuschtosSearch = {
- url = "github:NuschtOS/search";
- inputs = {
- nixpkgs.follows = "nixpkgs";
- flake-utils.follows = "lix-module/flake-utils";
- };
- };
# For deduplication
systems.url = "github:nix-systems/default";
};
diff --git a/home/default.nix b/home/default.nix
new file mode 100644
index 0000000..2a8e6a5
--- /dev/null
+++ b/home/default.nix
@@ -0,0 +1,231 @@
+{
+ nvim-config,
+ stylix ? null,
+}:
+{
+ config,
+ pkgs,
+ lib,
+ osConfig ? null,
+ ...
+}:
+let
+ cfg = config.jhome;
+ devcfg = cfg.dev;
+ # Query the osConfig for a setting. Return the default value if missing or in standalone mode
+ fromOs =
+ path: default: if osConfig == null then default else lib.attrsets.attrByPath path default osConfig;
+in
+{
+ imports =
+ [
+ nvim-config
+ ./options.nix
+ ./gui
+ ./users.nix
+ ]
+ ++ lib.optionals (stylix != null) [
+ stylix.homeManagerModules.stylix
+ { stylix.image = cfg.sway.background; }
+ ];
+
+ config = lib.mkMerge [
+ (lib.mkIf (cfg.enable && cfg.styling.enable) {
+ stylix = {
+ enable = true;
+ targets.nixvim.enable = false; # I prefer doing it myself
+ };
+ })
+ (lib.mkIf cfg.enable {
+ # Add gopass if pass is enabled
+ home.packages = lib.optional config.programs.password-store.enable pkgs.gopass;
+
+ nix.settings.use-xdg-base-directories = fromOs [
+ "nix"
+ "settings"
+ "use-xdg-base-directories"
+ ] true;
+ programs = {
+ # Better cat (bat)
+ bat = {
+ enable = true;
+ config = {
+ # Disable headers and numbers
+ style = "plain";
+ theme = lib.mkForce "gruvbox-dark";
+ };
+ };
+ # Direnv
+ direnv = {
+ enable = true;
+ nix-direnv.enable = true;
+ };
+ # ls replacement
+ eza = {
+ enable = true;
+ git = true;
+ icons = "auto";
+ };
+ # GnuPG
+ gpg = {
+ enable = true;
+ homedir = "${config.xdg.dataHome}/gnupg";
+ };
+ # Mail client
+ himalaya.enable = lib.mkDefault true;
+ # Password manager
+ password-store = {
+ enable = lib.mkDefault true;
+ package = pkgs.pass-nodmenu;
+ settings.PASSWORD_STORE_DIR = "${config.xdg.dataHome}/pass";
+ };
+ # SSH
+ ssh.enable = true;
+ # cd replacement
+ zoxide.enable = true;
+ # Shell
+ zsh = {
+ enable = true;
+ autosuggestion.enable = true;
+ enableCompletion = true;
+ autocd = true;
+ dotDir = ".config/zsh";
+ history.path = "${config.xdg.dataHome}/zsh/zsh_history";
+ syntaxHighlighting.enable = true;
+ };
+ };
+ services = {
+ # GPG Agent
+ gpg-agent = {
+ enable = true;
+ maxCacheTtl = 86400;
+ pinentryPackage = if config.jhome.gui.enable then pkgs.pinentry-qt else pkgs.pinentry-curses;
+ extraConfig = "allow-preset-passphrase";
+ };
+ # Spotifyd
+ spotifyd = {
+ inherit (config.jhome.gui) enable;
+ settings.global = {
+ device_name = config.jhome.hostName;
+ device_type = "computer";
+ backend = "pulseaudio";
+ zeroconf_port = 2020;
+ };
+ };
+ };
+ home = {
+ stateVersion = "22.11";
+ # Extra packages
+ # Extra variables
+ sessionVariables = {
+ CARGO_HOME = "${config.xdg.dataHome}/cargo";
+ RUSTUP_HOME = "${config.xdg.dataHome}/rustup";
+ GOPATH = "${config.xdg.dataHome}/go";
+ };
+ shellAliases = {
+ # Verbose Commands
+ cp = "cp --verbose";
+ ln = "ln --verbose";
+ mv = "mv --verbose";
+ mkdir = "mkdir --verbose";
+ rename = "rename --verbose";
+ rm = "rm --verbose";
+ # Add Color
+ grep = "grep --color=auto";
+ ip = "ip --color=auto";
+ # Use exa/eza
+ tree = "eza --tree";
+ };
+ };
+ # XDG directories
+ xdg = {
+ enable = true;
+ userDirs = {
+ enable = true;
+ createDirectories = true;
+ };
+ };
+ })
+ (lib.mkIf (cfg.enable && devcfg.enable) {
+ home = {
+ sessionVariables.MANPAGER = lib.optionalString devcfg.neovimAsManPager "nvim -c 'Man!' -o -";
+ packages = devcfg.extraPackages;
+ };
+ # Github CLI
+ programs = {
+ gh.enable = true;
+ gh-dash.enable = true;
+ # Git
+ git = {
+ enable = true;
+ difftastic = {
+ enable = true;
+ background = "dark";
+ };
+ lfs.enable = true;
+ extraConfig = {
+ # Add diff to the commit message editor
+ commit.verbose = true;
+ # Improve submodule diff
+ diff.submodule = "log";
+ # Set the default branch name for new branches
+ init.defaultBranch = "main";
+ # Better conflicts (also shows parent commit state)
+ merge.conflictStyle = "zdiff3";
+ # Do not create merge commits when pulling (rebase but abort on conflict)
+ pull.ff = "only";
+ # Use `--set-upstream` if the remote does not have the branch
+ push.autoSetupRemote = true;
+ rebase = {
+ # If there are uncommitted changes, stash them before rebasing
+ autoStash = true;
+ # If there are fixup! commits, squash them while rebasing
+ autoSquash = true;
+ };
+ # Enable ReReRe (Reuse Recovered Resolution) auto resolve previously resolved conflicts
+ rerere.enabled = true;
+ # Improve submodule status
+ status.submoduleSummary = true;
+ };
+ };
+ lazygit.enable = true;
+ # Jujutsu (alternative DVCS (git-compatible))
+ jujutsu = {
+ enable = true;
+ package = pkgs.unstable.jujutsu;
+ settings = {
+ ui.pager = "bat";
+ # mimic git commit --verbose by adding a diff
+ templates.draft_commit_description = ''
+ concat(
+ description,
+ surround(
+ "\nJJ: This commit contains the following changes:\n", "",
+ indent("JJ: ", diff.stat(72)),
+ ),
+ surround(
+ "\nJJ: Diff:\n", "",
+ indent("JJ: ", diff.git()),
+ ),
+ )
+ '';
+ };
+ };
+ };
+ })
+ (lib.mkIf (cfg.enable && devcfg.enable && devcfg.rust.enable) {
+ home.packages = [ pkgs.rustup ] ++ devcfg.rust.extraPackages;
+ # Background code checker (for Rust)
+ programs.bacon = {
+ enable = true;
+ settings = {
+ export = {
+ enabled = true;
+ path = ".bacon-locations";
+ line_format = "{kind} {path}:{line}:{column} {message}";
+ };
+ };
+ };
+ })
+ ];
+}
diff --git a/home/gui/default.nix b/home/gui/default.nix
new file mode 100644
index 0000000..07aa7d6
--- /dev/null
+++ b/home/gui/default.nix
@@ -0,0 +1,244 @@
+{
+ config,
+ lib,
+ pkgs,
+ osConfig ? null,
+ ...
+}:
+let
+ inherit (config) jhome;
+ flatpakEnabled = if osConfig != null then osConfig.services.flatpak.enable else false;
+ osSway = osConfig == null && !osConfig.programs.sway.enable;
+ swayPkg = if osSway then pkgs.sway else null;
+ cfg = jhome.gui;
+ cursor = {
+ package = pkgs.nordzy-cursor-theme;
+ name = "Nordzy-cursors";
+ };
+ iconTheme = {
+ name = "Papirus-Dark";
+ package = pkgs.papirus-icon-theme;
+ };
+in
+{
+ config = lib.mkIf (jhome.enable && cfg.enable) {
+ home.packages =
+ (with pkgs; [
+ webcord
+ ferdium
+ xournalpp
+ signal-desktop
+ pcmanfm
+ wl-clipboard
+ # Extra fonts
+ noto-fonts-cjk-sans # Chinese, Japanese and Korean characters
+ noto-fonts-cjk-serif # Chinese, Japanese and Korean characters
+ (nerdfonts.override { fonts = [ "NerdFontsSymbolsOnly" ]; })
+ ])
+ ++ lib.optional flatpakEnabled pkgs.flatpak;
+ fonts.fontconfig = {
+ enable = true;
+ defaultFonts = lib.mkIf config.jhome.styling.enable {
+ emoji = [ "Noto Color Emoji" ];
+ monospace = [
+ "JetBrains Mono"
+ "Symbols Nerd Font"
+ ];
+ serif = [
+ "Noto Serif"
+ "Symbols Nerd Font"
+ ];
+ sansSerif = [
+ "Noto Sans"
+ "Symbols Nerd Font"
+ ];
+ };
+ };
+ # Browser
+ programs = {
+ firefox.enable = true;
+ # Dynamic Menu
+ fuzzel = {
+ enable = true;
+ settings.main = lib.mkIf config.jhome.styling.enable {
+ icon-theme = "Papirus-Dark";
+ inherit (cfg) terminal;
+ layer = "overlay";
+ };
+ };
+ # Video player
+ mpv = {
+ enable = true;
+ scripts = builtins.attrValues { inherit (pkgs.mpvScripts) uosc thumbfast; };
+ };
+ # Text editor
+ nixvim.clipboard.providers.wl-copy.enable = lib.mkDefault true;
+ # Status bar
+ waybar = {
+ enable = true;
+ systemd.enable = true;
+ settings = lib.mkIf config.jhome.styling.enable (
+ import ./waybar-settings.nix { inherit config lib; }
+ );
+ style =
+ lib.optionalString config.jhome.styling.enable # css
+ ''
+ .modules-left #workspaces button {
+ border-bottom: 3px solid @base01;
+ }
+ .modules-left #workspaces button.persistent {
+ border-bottom: 3px solid transparent;
+ }
+ '';
+ };
+ # Terminal
+ wezterm = {
+ enable = cfg.terminal == "wezterm";
+ extraConfig =
+ lib.optionalString config.jhome.styling.enable # lua
+ ''
+ local wezterm = require("wezterm")
+
+ local config = wezterm.config_builder()
+
+ config.front_end = "WebGpu"
+ config.hide_tab_bar_if_only_one_tab = true
+ config.window_padding = { left = 1, right = 1, top = 1, bottom = 1 }
+
+ return config
+ '';
+ };
+ alacritty = {
+ enable = cfg.terminal == "alacritty";
+ settings = {
+ # hide mouse when typing, this ensures I don't have to move the mouse when it hides text
+ mouse.hide_when_typing = true;
+ # Start zellij when it is enabled
+ terminal.shell = lib.mkIf (config.jhome.dev.enable && config.programs.zellij.enable) {
+ program = "${lib.getExe config.programs.zellij.package}";
+ };
+ };
+ };
+ zellij.enable = cfg.terminal == "alacritty"; # alacritty has no terminal multiplexer built-in
+ # PDF reader
+ zathura.enable = true;
+ # Auto start sway
+ zsh.loginExtra =
+ lib.optionalString cfg.sway.autostart # sh
+ ''
+ # Start Sway on login to TTY 1
+ if [ "$TTY" = /dev/tty1 ]; then
+ exec sway
+ fi
+ '';
+ };
+ services = {
+ # Volume/Backlight control and notifications
+ avizo = {
+ enable = true;
+ settings.default = {
+ time = 0.8;
+ border-width = 0;
+ height = 176;
+ y-offset = 0.1;
+ block-spacing = 1;
+ };
+ };
+ # Sound tuning
+ easyeffects.enable = true;
+ # Auto configure displays
+ kanshi.enable = lib.mkDefault true;
+ # Notifications
+ mako = {
+ enable = true;
+ layer = "overlay";
+ borderRadius = 8;
+ defaultTimeout = 15000;
+ };
+ };
+
+ # Window Manager
+ programs.niri = {
+ package = pkgs.niri; # use nixpkgs' package instead of the flake's
+ settings = {
+ binds =
+ let
+ # Modifier key
+ mod = "Mod";
+ # Available workspaces (1..=9)
+ workspaces = lib.range 1 9;
+ # Run function for each workspace
+ perWorkspace = f: lib.mergeAttrsList (builtins.map f workspaces);
+ # alias for concatStringsSep
+ joinWith = lib.strings.concatStringsSep;
+ in
+ with config.lib.niri.actions;
+ {
+ # Open Terminal
+ "${mod}+Return".action.spawn =
+ if config.jhome.gui.terminal == "alacritty" then "alacritty" else config.jhome.gui.terminalCommand;
+ # Open menu
+ "${mod}+D".action =
+ spawn "${lib.getExe pkgs.fuzzel}" "--terminal"
+ "${joinWith " " config.jhome.gui.terminalCommand}";
+ # Close Window
+ "${mod}+Q".action = close-window;
+ # Fullscreen
+ "${mod}+F".action = fullscreen-window;
+ # Hotkey help menu
+ "${mod}+Shift+Slash".action = show-hotkey-overlay;
+ # Media Keys
+ "XF86AudioRaiseVolume" = {
+ action = spawn "${pkgs.avizo}/bin/volumectl" "up";
+ allow-when-locked = true;
+ };
+ "XF86AudioLowerVolume" = {
+ action = spawn "${pkgs.avizo}/bin/volumectl" "down";
+ allow-when-locked = true;
+ };
+ "XF86AudioMute" = {
+ action = spawn "${pkgs.avizo}/bin/volumectl" "toggle-mute";
+ allow-when-locked = true;
+ };
+ # FIXME: swaylock is missing so this doesn't work anyways
+ # Lock screen
+ # "XF86ScreenSaver".action = spawn "swaylock" "--image" "${cfg.background}";
+ # Screen brightness
+ "XF86MonBrightnessUp".action = spawn "${pkgs.avizo}/bin/lightctl" "up";
+ "XF86MonBrightnessDown".action = spawn "${pkgs.avizo}/bin/lightctl" "down";
+ }
+ // perWorkspace (workspace: {
+ # Focus workspace N
+ "${mod}+${builtins.toString workspace}".action = focus-workspace workspace;
+ });
+ };
+ };
+
+ # Set cursor style
+ stylix = lib.mkIf config.jhome.styling.enable { inherit cursor; };
+ home.pointerCursor = lib.mkIf config.jhome.styling.enable (
+ lib.mkDefault {
+ gtk.enable = true;
+ inherit (cursor) name package;
+ }
+ );
+ # Set Gtk theme
+ gtk = lib.mkIf config.jhome.styling.enable {
+ enable = true;
+ inherit iconTheme;
+ gtk3.extraConfig.gtk-application-prefer-dark-theme = 1;
+ gtk4.extraConfig.gtk-application-prefer-dark-theme = 1;
+ };
+ # Set Qt theme
+ qt = lib.mkIf config.jhome.styling.enable {
+ enable = true;
+ platformTheme.name = "gtk";
+ };
+
+ xdg.systemDirs.data = [
+ "/usr/share"
+ "/var/lib/flatpak/exports/share"
+ "${config.xdg.dataHome}/flatpak/exports/share"
+ ];
+ };
+}
diff --git a/home/gui/keybindings.nix b/home/gui/keybindings.nix
new file mode 100644
index 0000000..867be55
--- /dev/null
+++ b/home/gui/keybindings.nix
@@ -0,0 +1,118 @@
+{ pkgs, config }:
+let
+ cfg = config.jhome.gui.sway;
+ passmenu = "${pkgs.jpassmenu}/bin/jpassmenu";
+ selectAudio = "${pkgs.audiomenu}/bin/audiomenu";
+ swayconf = config.wayland.windowManager.sway.config;
+ mod = swayconf.modifier;
+ workspaces = map toString [
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+ ];
+ dirs =
+ map
+ (dir: {
+ key = swayconf.${dir};
+ arrow = dir;
+ direction = dir;
+ })
+ [
+ "up"
+ "down"
+ "left"
+ "right"
+ ];
+ joinKeys = builtins.concatStringsSep "+";
+ # Generate a keybind from a modifier prefix and a key
+ keycombo = prefix: key: joinKeys (prefix ++ [ key ]);
+ modKeybind = keycombo [ mod ];
+ modCtrlKeybind = keycombo [
+ mod
+ "Ctrl"
+ ];
+ modShiftKeybind = keycombo [
+ mod
+ "Shift"
+ ];
+ modCtrlShiftKeybind = keycombo [
+ mod
+ "Ctrl"
+ "Shift"
+ ];
+ dir2resize.up = "resize grow height";
+ dir2resize.down = "resize shrink height";
+ dir2resize.right = "resize grow width";
+ dir2resize.left = "resize shrink width";
+ # Bind a key combo to an action
+ genKeybind = prefix: action: key: { "${prefix key}" = "${action key}"; };
+ genKey =
+ prefix: action: genKeybind ({ key, ... }: prefix key) ({ direction, ... }: action direction);
+ genArrow =
+ prefix: action: genKeybind ({ arrow, ... }: prefix arrow) ({ direction, ... }: action direction);
+ genArrowAndKey =
+ prefix: action: key:
+ (genKey prefix action key) // (genArrow prefix action key);
+ # Move window
+ moveWindowKeybinds = map (genArrowAndKey modShiftKeybind (dir: "move ${dir}")) dirs;
+ # Focus window
+ focusWindowKeybinds = map (genArrowAndKey modKeybind (dir: "focus ${dir}")) dirs;
+ # Resize window
+ resizeWindowKeybinds = map (genArrowAndKey modCtrlKeybind (dir: dir2resize.${dir})) dirs;
+ # Move container to workspace
+ moveWorkspaceKeybindings = map (genKeybind modShiftKeybind (
+ number: "move container to workspace number ${number}"
+ )) workspaces;
+ # Focus workspace
+ focusWorkspaceKeybindings = map (genKeybind modKeybind (
+ number: "workspace number ${number}"
+ )) workspaces;
+ # Move container to Workspace and focus on it
+ moveFocusWorkspaceKeybindings = map (genKeybind modCtrlShiftKeybind (
+ number: "move container to workspace number ${number}; workspace number ${number}"
+ )) workspaces;
+in
+builtins.foldl' (l: r: l // r)
+ {
+ "${mod}+Return" = "exec ${swayconf.terminal}";
+ "${mod}+D" = "exec ${swayconf.menu}";
+ "${mod}+P" = "exec ${passmenu}";
+ "${mod}+Shift+P" = "exec ${passmenu} --type";
+ "${mod}+F2" = "exec qutebrowser";
+ "${mod}+Shift+Q" = "kill";
+ "${mod}+F" = "fullscreen toggle";
+ # Media Controls
+ "${mod}+F10" = "exec ${selectAudio} select-sink";
+ "${mod}+Shift+F10" = "exec ${selectAudio} select-source";
+ "XF86AudioRaiseVolume" = "exec ${pkgs.avizo}/bin/volumectl up";
+ "XF86AudioLowerVolume" = "exec ${pkgs.avizo}/bin/volumectl down";
+ "XF86AudioMute" = "exec ${pkgs.avizo}/bin/volumectl toggle-mute";
+ "XF86ScreenSaver" = "exec swaylock --image ${cfg.background}";
+ "XF86MonBrightnessUp" = "exec ${pkgs.avizo}/bin/lightctl up";
+ "XF86MonBrightnessDown" = "exec ${pkgs.avizo}/bin/lightctl down";
+ # Floating
+ "${mod}+Space" = "floating toggle";
+ "${mod}+Shift+Space" = "focus mode_toggle";
+ # Scratchpad
+ "${mod}+Minus" = "scratchpad show";
+ "${mod}+Shift+Minus" = "move scratchpad";
+ # Layout
+ "${mod}+e" = "layout toggle split";
+ # Session control
+ "${mod}+r" = "reload";
+ "${mod}+Shift+m" = "exit";
+ }
+ (
+ focusWindowKeybinds
+ ++ moveWindowKeybinds
+ ++ resizeWindowKeybinds
+ ++ focusWorkspaceKeybindings
+ ++ moveWorkspaceKeybindings
+ ++ moveFocusWorkspaceKeybindings
+ )
diff --git a/home/gui/sway-config.nix b/home/gui/sway-config.nix
new file mode 100644
index 0000000..f499f71
--- /dev/null
+++ b/home/gui/sway-config.nix
@@ -0,0 +1,95 @@
+{ config, pkgs }:
+let
+ cfg = config.jhome.gui.sway;
+ modifier = "Mod4";
+ termCmd = builtins.concatStringsSep " " config.jhome.gui.terminalCommand;
+ menu = "${pkgs.fuzzel}/bin/fuzzel --terminal '${termCmd}'";
+ # currently, there is some friction between sway and gtk:
+ # https://github.com/swaywm/sway/wiki/GTK-3-settings-on-Wayland
+ # the suggested way to set gtk settings is with gsettings
+ # for gsettings to work, we need to tell it where the schemas are
+ # using the XDG_DATA_DIR environment variable
+ # run at the end of sway config
+ configure-gtk =
+ let
+ schema = pkgs.gsettings-desktop-schemas;
+ datadir = "${schema}/share/gsettings-schemas/${schema.name}";
+ in
+ pkgs.writers.writeDashBin "configure-gtk" ''
+ export XDG_DATA_DIRS="${datadir}:$XDG_DATA_DIRS"
+
+ gnome_schema=org.gnome.desktop.interface
+ config="${config.xdg.configHome}/gtk-3.0/settings.ini"
+ if [ ! -f "$config" ]; then exit 1; fi
+ # Read settings from gtk3
+ gtk_theme="$(${pkgs.gnugrep}/bin/grep 'gtk-theme-name' "$config" | ${pkgs.gnused}/bin/sed 's/.*\s*=\s*//')"
+ icon_theme="$(${pkgs.gnugrep}/bin/grep 'gtk-icon-theme-name' "$config" | ${pkgs.gnused}/bin/sed 's/.*\s*=\s*//')"
+ cursor_theme="$(${pkgs.gnugrep}/bin/grep 'gtk-cursor-theme-name' "$config" | ${pkgs.gnused}/bin/sed 's/.*\s*=\s*//')"
+ font_name="$(grep 'gtk-font-name' "$config" | sed 's/.*\s*=\s*//')"
+ ${pkgs.glib}/bin/gsettings set "$gnome_schema" gtk-theme "$gtk_theme"
+ ${pkgs.glib}/bin/gsettings set "$gnome_schema" icon-theme "$icon_theme"
+ ${pkgs.glib}/bin/gsettings set "$gnome_schema" cursor-theme "$cursor_theme"
+ ${pkgs.glib}/bin/gsettings set "$gnome_schema" font-name "$font_name"
+ ${pkgs.glib}/bin/gsettings set "$gnome_schema" color-scheme prefer-dark
+ '';
+ cmdOnce = command: { inherit command; };
+ cmdAlways = command: {
+ inherit command;
+ always = true;
+ };
+in
+{
+ inherit (config.jhome.gui) terminal;
+ inherit modifier menu;
+ keybindings = import ./keybindings.nix { inherit config pkgs; };
+ # Appearance
+ bars = [ ]; # Waybar is started as a systemd service
+ gaps = {
+ smartGaps = true;
+ smartBorders = "on";
+ inner = 4;
+ };
+ output."*".bg = "${cfg.background} fill";
+ # Window Appearance
+ window = {
+ border = 2;
+ titlebar = false;
+ # Make certain windows floating
+ commands = [
+ {
+ command = "floating enable";
+ criteria.title = "zoom";
+ }
+ {
+ command = "floating enable";
+ criteria.class = "floating";
+ }
+ {
+ command = "floating enable";
+ criteria.app_id = "floating";
+ }
+ ];
+ };
+ # Startup scripts
+ startup =
+ [
+ (cmdAlways "${configure-gtk}/bin/configure-gtk")
+ ]
+ ++ (builtins.map cmdAlways cfg.exec.always)
+ ++ (builtins.map cmdOnce cfg.exec.once);
+ # Keyboard configuration
+ input."type:keyboard" = {
+ repeat_delay = "300";
+ repeat_rate = "50";
+ xkb_options = "caps:swapescape,compose:ralt";
+ xkb_numlock = "enabled";
+ };
+ # Touchpad
+ input."type:touchpad" = {
+ click_method = "clickfinger";
+ natural_scroll = "enabled";
+ scroll_method = "two_finger";
+ tap = "enabled";
+ tap_button_map = "lrm";
+ };
+}
diff --git a/home/gui/waybar-settings.nix b/home/gui/waybar-settings.nix
new file mode 100644
index 0000000..3fcf58c
--- /dev/null
+++ b/home/gui/waybar-settings.nix
@@ -0,0 +1,127 @@
+{ config, lib }:
+let
+ cfg = config.jhome.gui;
+in
+{
+ mainBar = {
+ layer = "top";
+ position = "top";
+ margin = "2 2 2 2";
+ # Choose the order of the modules
+ modules-left = [ "sway/workspaces" ];
+ modules-center = [ "clock" ];
+ modules-right =
+ [
+ "pulseaudio"
+ "backlight"
+ "battery"
+ "sway/language"
+ "memory"
+ ]
+ ++ lib.optional (cfg.tempInfo != null) "temperature"
+ ++ [ "tray" ];
+ "sway/workspaces" = {
+ disable-scroll = true;
+ persistent-workspaces = {
+ "1" = [ ];
+ "2" = [ ];
+ "3" = [ ];
+ "4" = [ ];
+ "5" = [ ];
+ "6" = [ ];
+ "7" = [ ];
+ "8" = [ ];
+ "9" = [ ];
+ };
+ };
+ "sway/language" = {
+ format = "{} ";
+ min-length = 5;
+ tooltip = false;
+ };
+ memory = {
+ format = "{used:0.1f}/{total:0.1f}GiB ";
+ interval = 3;
+ };
+ clock = {
+ timezone = "Europe/Berlin";
+ tooltip-format = "{:%Y %B}\n{calendar}";
+ format = "{:%a, %d %b, %H:%M}";
+ };
+ pulseaudio = {
+ reverse-scrolling = 1;
+ format = "{volume}% {icon} {format_source}";
+ format-bluetooth = "{volume}% {icon} {format_source}";
+ format-bluetooth-muted = "{volume}% {icon} {format_source}";
+ format-muted = "{volume}% {format_source}";
+ format-source = "{volume}% ";
+ format-source-muted = "{volume}% ";
+ format-icons = {
+ headphone = "";
+ hands-free = "";
+ headset = "";
+ phone = "";
+ portable = "";
+ car = "";
+ default = [
+ ""
+ ""
+ ""
+ ];
+ };
+ on-click = "pavucontrol";
+ min-length = 13;
+ };
+ temperature = lib.optionalAttrs (cfg.tempInfo != null) {
+ inherit (cfg.tempInfo) hwmon-path;
+ critical-threshold = 80;
+ format = "{temperatureC}°C {icon}";
+ format-icons = [
+ ""
+ ""
+ ""
+ ""
+ ""
+ ];
+ tooltip = false;
+ };
+ backlight = {
+ device = "intel_backlight";
+ format = "{percent}% {icon}";
+ format-icons = [
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ];
+ min-length = 7;
+ };
+ battery = {
+ states.warning = 30;
+ states.critical = 15;
+ format = "{capacity}% {icon}";
+ format-charging = "{capacity}% ";
+ format-plugged = "{capacity}% ";
+ format-alt = "{time} {icon}";
+ format-icons = [
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ];
+ };
+ tray = {
+ icon-size = 16;
+ spacing = 0;
+ };
+ };
+}
diff --git a/modules/hm/options.nix b/home/options.nix
similarity index 76%
rename from modules/hm/options.nix
rename to home/options.nix
index 811384a..24b09cc 100644
--- a/modules/hm/options.nix
+++ b/home/options.nix
@@ -78,13 +78,23 @@ let
example = "/sys/class/hwmon/hwmon2/temp1_input";
};
- sway.options = {
- enable = lib.mkEnableOption "sway" // {
+ windowManager.options = {
+ enable = lib.mkEnableOption "window manager" // {
default = fromConfig [
"gui"
- "sway"
+ "windowManager"
+ "enable"
] true;
};
+ windowManager = lib.mkOption {
+ description = "Which window manager to enable";
+ type = types.enum [ "niri" ];
+ default = fromConfig [
+ "gui"
+ "windowManager"
+ "windowManager"
+ ] "niri";
+ };
background = lib.mkOption {
description = "The wallpaper to use.";
type = types.path;
@@ -114,55 +124,60 @@ let
default = true;
example = false;
};
- exec = lib.mkOption {
- description = "Run commands when starting sway.";
- default = { };
- type = types.submodule {
- options = {
- once = lib.mkOption {
- description = "Programs to start only once (`exec`).";
- type = types.listOf types.str;
- default = [ ];
- example = [ "signal-desktop --start-in-tray" ];
- };
- always = lib.mkOption {
- description = "Programs to start whenever the config is sourced (`exec_always`).";
- type = types.listOf types.str;
- default = [ ];
- example = [ "signal-desktop --start-in-tray" ];
- };
- };
- };
- };
};
- gui.options = {
- enable = lib.mkEnableOption "GUI applications" // {
- default = fromConfig [
- "gui"
- "enable"
- ] false;
+ gui.options =
+ let
+ cfg = attrs.config.jhome.gui;
+ in
+ {
+ enable = lib.mkEnableOption "GUI applications" // {
+ default = fromConfig [
+ "gui"
+ "enable"
+ ] false;
+ };
+ tempInfo = lib.mkOption {
+ description = "Temperature info to display in the statusbar.";
+ default = null;
+ type = types.nullOr (types.submodule tempInfo);
+ };
+ windowManager = lib.mkOption {
+ description = "Window manager configuration.";
+ default = { };
+ type = types.submodule windowManager;
+ };
+ terminal = lib.mkOption {
+ description = "The terminal emulator to use.";
+ default = "alacritty";
+ example = "wezterm";
+ type = types.enum [
+ "wezterm"
+ "alacritty"
+ ];
+ };
+ terminalCommand = lib.mkOption {
+ description = "The command to run in order to start the terminal.";
+ default =
+ if cfg.terminal == "wezterm" then
+ [
+ "wezterm"
+ "start"
+ ]
+ else if cfg.terminal == "alacritty" then
+ [
+ "alacritty"
+ "-e"
+ ]
+ else
+ builtins.abort "no command configured for ${cfg.terminal}";
+ example = [
+ "wezterm"
+ "start"
+ ];
+ type = types.listOf types.str;
+ };
};
- tempInfo = lib.mkOption {
- description = "Temperature info to display in the statusbar.";
- default = null;
- type = types.nullOr (types.submodule tempInfo);
- };
- sway = lib.mkOption {
- description = "Sway window manager configuration.";
- default = { };
- type = types.submodule sway;
- };
- terminal = lib.mkOption {
- description = "The terminal emulator to use.";
- default = "alacritty";
- example = "wezterm";
- type = types.enum [
- "wezterm"
- "alacritty"
- ];
- };
- };
in
{
options.jhome = lib.mkOption {
@@ -198,6 +213,8 @@ in
[ "just" ] # just a command runner
[ "typos" ] # low false positive rate typo checker
[ "gcc" ] # GNU Compiler Collection
+ [ "git-absorb" ] # fixup! but automatic
+ [ "gitoxide" ] # git but RiiR
[ "man-pages" ] # gimme the man pages
[ "man-pages-posix" ] # I said gimme the man pages!!!
];
@@ -209,6 +226,8 @@ in
options.extraPackages = mkExtraPackagesOption "Rust" [
[ "cargo-insta" ] # snapshot testing
[ "cargo-nextest" ] # better testing harness
+ [ "cargo-udeps" ] # check for unused dependencies (requires nightly)
+ [ "cargo-watch" ] # watch for file changes and run commands
];
};
};
diff --git a/modules/hm/users.nix b/home/users.nix
similarity index 55%
rename from modules/hm/users.nix
rename to home/users.nix
index 702e60c..dc36346 100644
--- a/modules/hm/users.nix
+++ b/home/users.nix
@@ -4,12 +4,15 @@ let
inherit (cfg.defaultIdentity) signingKey;
cfg = jhome.user;
+ hasConfig = jhome.enable && cfg != null;
hasKey = signingKey != null;
+ gpgHome = config.programs.gpg.homedir;
+ unlockKey = hasConfig && cfg.gpg.unlockKeys != [ ];
in
{
- config = lib.mkIf (jhome.enable && cfg != null) {
- programs = {
- git = {
+ config = lib.mkMerge [
+ (lib.mkIf hasConfig {
+ programs.git = {
userName = cfg.defaultIdentity.name;
userEmail = cfg.defaultIdentity.email;
signing = lib.mkIf hasKey {
@@ -17,24 +20,22 @@ in
key = signingKey;
};
};
-
- jujutsu.settings = {
+ programs.jujutsu.settings = {
user = lib.mkIf (cfg.defaultIdentity != null) { inherit (cfg.defaultIdentity) name email; };
- git.sign-on-push = lib.mkDefault hasKey;
signing = lib.mkIf hasKey {
- behaviour = "own";
+ sign-all = true;
backend = "gpg";
key = signingKey;
};
};
- };
+ })
+ (lib.mkIf unlockKey {
+ xdg.configFile.pam-gnupg.text =
+ ''
+ ${gpgHome}
- xdg.configFile.pam-gnupg = lib.mkIf (cfg.gpg.unlockKeys != [ ]) {
- text = ''
- ${config.programs.gpg.homedir}
-
- ${lib.strings.concatLines cfg.gpg.unlockKeys}
- '';
- };
- };
+ ''
+ + (lib.strings.concatLines cfg.gpg.unlockKeys);
+ })
+ ];
}
diff --git a/justfile b/justfile
index 483e46c..a88bd00 100644
--- a/justfile
+++ b/justfile
@@ -3,29 +3,32 @@ default:
# Update a specific flake input
update input:
- nix flake lock --update-input "{{input}}" --commit-lock-file
+ nix flake lock --update-input {{input}} --commit-lock-file
build-vm:
- nixos-rebuild build-vm --fallback --flake .#vm --print-build-logs
+ nixos-rebuild build-vm --flake .#vm --print-build-logs
run-vm: build-vm
QEMU_OPTS="$QEMU_OPTS_WL" result/bin/run-nixos-vm
update-vim-plugins:
#!/bin/sh
- plugindir=./modules/nixvim/extraPlugins
+ # Use local nixpkgs if available
+ nixpkgs="$HOME/Dev/nixpkgs"
# copy nixpkgs from local checkout
- nixpkgs="$(mktemp -d)"
- cp -r /nix/var/nix/profiles/per-user/root/channels/nixos/nixpkgs/. "$nixpkgs"
- cd "$nixpkgs"
- git init .
- git add .
- git commit -m 'dummy commit'
- cd -
+ if [ ! -d "$nixpkgs" ]; then
+ nixpkgs="$(mktemp -d)"
+ cp -r /nix/var/nix/profiles/per-user/root/channels/nixos/nixpkgs/. "$nixpkgs"
+ cd "$nixpkgs"
+ git init .
+ git add .
+ git commit -m 'dummy commit'
+ cd -
+ fi
# update vim plugins
- nix run nixpkgs#vimPluginsUpdater -- --proc=1 --nixpkgs "$nixpkgs" --no-commit -i "$plugindir/plugins" -o "$plugindir/generated.nix" update
+ nix run nixpkgs#vimPluginsUpdater -- --proc=1 --nixpkgs "$nixpkgs" --no-commit -i ./nvim/extraPlugins/plugins -o ./nvim/extraPlugins/generated.nix update
# format the generated output
- nix fmt "$plugindir/generated.nix"
+ nix fmt ./nvim/extraPlugins/generated.nix
# Amend Update flake.lock PR
flake-pr:
diff --git a/machines/vm/default.nix b/machines/vm/default.nix
new file mode 100644
index 0000000..ced0faa
--- /dev/null
+++ b/machines/vm/default.nix
@@ -0,0 +1,31 @@
+{
+ services.qemuGuest.enable = true;
+
+ boot.initrd.availableKernelModules = [
+ "xhci_pci"
+ "ehci_pci"
+ "ahci"
+ "usbhid"
+ "usb_storage"
+ "sd_mod"
+ "virtio_balloon"
+ "virtio_blk"
+ "virtio_pci"
+ "virtio_ring"
+ # "virtio_vga"
+ "virtio_gpu"
+ ];
+ fileSystems."/".device = "/dev/disk/by-label/nixos";
+
+ boot.loader.systemd-boot.enable = true;
+
+ services.openssh.enable = true;
+
+ # This value determines the NixOS release from which the default
+ # settings for stateful data, like file locations and database versions
+ # on your system were taken. It‘s perfectly fine and recommended to leave
+ # this value at the release version of the first install of this system.
+ # Before changing this value read the documentation for this option
+ # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
+ system.stateVersion = "22.11"; # Did you read the comment?
+}
diff --git a/modules/hm/default.nix b/modules/hm/default.nix
deleted file mode 100644
index 2e5a8db..0000000
--- a/modules/hm/default.nix
+++ /dev/null
@@ -1,171 +0,0 @@
-{
- config,
- pkgs,
- lib,
- osConfig ? null,
- ...
-}:
-let
- cfg = config.jhome;
- devcfg = cfg.dev;
- # Query the osConfig for a setting. Return the default value if missing or in standalone mode
- fromOs =
- path: default: if osConfig == null then default else lib.attrsets.attrByPath path default osConfig;
-in
-{
- imports = [
- ./options.nix
- ./gui
- ./dev.nix
- ./users.nix
- ];
-
- config = lib.mkMerge [
- (lib.mkIf (cfg.enable && cfg.styling.enable) {
- stylix = {
- enable = true;
- targets.nixvim.enable = false; # I prefer styling it myself
- };
- })
- (lib.mkIf (cfg.enable && cfg.styling.enable && !cfg.gui.enable) {
- # Stylix disable graphical targets when no GUI is requested
- stylix.targets = {
- gtk.enable = false;
- qt.enable = false;
- gnome.enable = false;
- kde.enable = false;
- xresources.enable = false;
- };
- })
- (lib.mkIf cfg.enable {
- # Add gopass if pass is enabled
- home.packages = lib.optional config.programs.password-store.enable pkgs.gopass;
-
- nix = {
- # Run GC for Home Manager generations
- gc = {
- automatic = true;
- frequency = "weekly";
- options = "--delete-older-than 30d";
- # run between 0 and 45min after boot if run was missed
- randomizedDelaySec = "45min";
- };
-
- # Use XDG directories
- settings.use-xdg-base-directories = fromOs [
- "nix"
- "settings"
- "use-xdg-base-directories"
- ] true;
- };
-
- programs = {
- # Switch to fish if bash is started interactively
- bash.initExtra = ''
- if [[ $(${pkgs.procps}/bin/ps --no-header --pid=$PPID --format=comm) != "fish" && -z ''${BASH_EXECUTION_STRING} ]]
- then
- shopt -q login_shell && LOGIN_OPTION='--login' || LOGIN_OPTION=""
- exec ${pkgs.fish}/bin/fish $LOGIN_OPTION
- fi
- '';
- # Better cat (bat)
- bat = {
- enable = true;
- config = {
- # Disable headers and numbers
- style = "plain";
- theme = lib.mkForce "gruvbox-dark";
- };
- };
- # Direnv
- direnv = {
- enable = true;
- nix-direnv.enable = true;
- };
- # ls replacement
- eza = {
- enable = true;
- git = true;
- icons = "auto";
- };
- # Shell
- bash.enable = true; # ensure HM variables are passed to `bash` too (otherwise `jpassmenu` doesn't work)
- fish = {
- enable = true;
- preferAbbrs = true; # when defining an alias, prefer instead to define an abbreviation
- };
- # GnuPG
- gpg = {
- enable = true;
- homedir = "${config.xdg.dataHome}/gnupg";
- };
- # Mail client
- himalaya.enable = lib.mkDefault true;
- # Password manager
- password-store = {
- enable = lib.mkDefault true;
- package = pkgs.pass-nodmenu;
- settings.PASSWORD_STORE_DIR = "${config.xdg.dataHome}/pass";
- };
- # SSH
- ssh.enable = true;
- # cd replacement
- zoxide.enable = true;
- };
-
- services = {
- # GPG Agent
- gpg-agent = {
- enable = true;
- maxCacheTtl = 86400;
- pinentry.package = if config.jhome.gui.enable then pkgs.pinentry-qt else pkgs.pinentry-curses;
- extraConfig = "allow-preset-passphrase";
- };
- # Delete old generations (>month)
- home-manager.autoExpire.enable = true;
- # Spotifyd
- spotifyd = {
- inherit (config.jhome.gui) enable;
- settings.global = {
- device_name = config.jhome.hostName;
- device_type = "computer";
- backend = "pulseaudio";
- zeroconf_port = 2020;
- };
- };
- };
-
- home = {
- # Extra variables
- sessionVariables = {
- CARGO_HOME = "${config.xdg.dataHome}/cargo";
- RUSTUP_HOME = "${config.xdg.dataHome}/rustup";
- GOPATH = "${config.xdg.dataHome}/go";
- };
- shellAliases = {
- # Verbose Commands
- cp = "cp --verbose";
- ln = "ln --verbose";
- mv = "mv --verbose";
- mkdir = "mkdir --verbose";
- rename = "rename --verbose";
- rm = "rm --verbose";
- # Add Color
- grep = "grep --color=auto";
- ip = "ip --color=auto";
- # Use exa/eza
- tree = "eza --tree";
- };
- };
-
- # XDG directories
- xdg = {
- enable = true;
- userDirs = {
- enable = true;
- createDirectories = true;
- };
- };
- })
- ];
-}
diff --git a/modules/hm/dev.nix b/modules/hm/dev.nix
deleted file mode 100644
index afa3899..0000000
--- a/modules/hm/dev.nix
+++ /dev/null
@@ -1,178 +0,0 @@
-{
- pkgs,
- lib,
- config,
- ...
-}:
-let
- cfg = config.jhome.dev;
- nvimFormatters = builtins.mapAttrs (
- name: value: value.command
- ) config.programs.nixvim.plugins.conform-nvim.settings.formatters;
- jjFormatters =
- let
- ext_to_glob = ext: "glob:'**/*.${ext}'";
- exts = builtins.map ext_to_glob;
- in
- {
- fish = cmd: {
- command = [ cmd ];
- patterns = exts [ "fish" ];
- };
- clang_format = cmd: {
- command = [
- cmd
- "--assume-filename=$path"
- ];
- patterns = exts [
- "c"
- "cc"
- "cpp"
- "h"
- "hh"
- "hpp"
- ];
- };
- nixfmt = cmd: {
- command = [
- cmd
- "--filename=$path"
- ];
- patterns = exts [ "nix" ];
- };
- shfmt = cmd: {
- command = [
- cmd
- "--filename"
- "$path"
- "-"
- ];
- patterns = exts [
- "sh"
- "bash"
- ];
- };
- stylua = cmd: {
- command = [
- cmd
- "--stdin-filepath=$path"
- "-"
- ];
- patterns = exts [ "lua" ];
- };
- taplo = cmd: {
- command = [
- cmd
- "format"
- "--stdin-filepath=$path"
- "-"
- ];
- patterns = exts [ "toml" ];
- };
- yamlfmt = cmd: {
- command = [
- cmd
- "-in"
- ];
- patterns = exts [
- "yaml"
- "yml"
- ];
- };
- };
-in
-{
- config =
- lib.flip lib.pipe
- [
- lib.mkMerge
- (lib.mkIf (config.jhome.enable && cfg.enable))
- ]
- [
- (lib.mkIf cfg.rust.enable {
- home.packages = [ pkgs.rustup ] ++ cfg.rust.extraPackages;
- })
- {
- home = {
- sessionVariables.MANPAGER = lib.optionalString cfg.neovimAsManPager "nvim -c 'Man!' -o -";
- packages = cfg.extraPackages;
- };
-
- # Github CLI
- programs = {
- gh.enable = true;
- gh-dash.enable = true;
- # Git
- git = {
- enable = true;
- difftastic = {
- enable = true;
- background = "dark";
- };
- lfs.enable = true;
- extraConfig = {
- # Add diff to the commit message editor
- commit.verbose = true;
- # Improve submodule diff
- diff.submodule = "log";
- # Set the default branch name for new branches
- init.defaultBranch = "main";
- # Better conflicts (also shows parent commit state)
- merge.conflictStyle = "zdiff3";
- # Do not create merge commits when pulling (rebase but abort on conflict)
- pull.ff = "only";
- # Use `--set-upstream` if the remote does not have the branch
- push.autoSetupRemote = true;
- rebase = {
- # If there are uncommitted changes, stash them before rebasing
- autoStash = true;
- # If there are fixup! commits, squash them while rebasing
- autoSquash = true;
- };
- # Enable ReReRe (Reuse Recovered Resolution) auto resolve previously resolved conflicts
- rerere.enabled = true;
- # Improve submodule status
- status.submoduleSummary = true;
- };
- };
- lazygit.enable = true;
- # Jujutsu (alternative DVCS (git-compatible))
- jujutsu = {
- enable = true;
- # Use the more up to date version of jj
- package = pkgs.unstable.jujutsu;
- settings = {
- ui = lib.mkMerge [
- # If `bat` is available use it as the pager
- (lib.mkIf config.programs.bat.enable { pager = "bat"; })
- # if hunk.nvim is enabled use it as a diff editor
- (lib.mkIf config.programs.nixvim.plugins.hunk.enable {
- diff-editor = [
- "nvim"
- "-c"
- "DiffEditor $left $right $output"
- ];
- })
- ];
- fix.tools = builtins.mapAttrs (tool: cmd: jjFormatters.${tool} cmd) nvimFormatters;
- # mimic git commit --verbose by adding a diff
- templates.draft_commit_description = ''
- concat(
- description,
- "\n",
- surround(
- "\nJJ: This commit contains the following changes:\n", "",
- indent("JJ: ", diff.summary()),
- ),
- surround(
- "JJ: ignore-rest\n", "",
- diff.git(),
- ),
- )
- '';
- };
- };
- };
- }
- ];
-}
diff --git a/modules/hm/gui/default.nix b/modules/hm/gui/default.nix
deleted file mode 100644
index 8c40e5a..0000000
--- a/modules/hm/gui/default.nix
+++ /dev/null
@@ -1,257 +0,0 @@
-{
- config,
- lib,
- pkgs,
- osConfig ? null,
- ...
-}:
-let
- inherit (config) jhome;
- flatpakEnabled = if osConfig != null then osConfig.services.flatpak.enable else false;
- osSway = osConfig == null && !osConfig.programs.sway.enable;
- swayPkg = if osSway then pkgs.sway else null;
- cfg = jhome.gui;
- cursor = {
- package = pkgs.nordzy-cursor-theme;
- size = 48;
- name = "Nordzy-cursors";
- };
-in
-{
- imports = [
- ./sway.nix
- ./waybar.nix
- ];
-
- config = lib.mkIf (jhome.enable && cfg.enable) {
- home.packages = [
- pkgs.webcord
- pkgs.ferdium
- pkgs.xournalpp
- pkgs.signal-desktop
- pkgs.pcmanfm
- pkgs.wl-clipboard
- # Extra fonts
- pkgs.noto-fonts-cjk-sans # Chinese, Japanese and Korean characters
- pkgs.noto-fonts-cjk-serif # Chinese, Japanese and Korean characters
- pkgs.nerd-fonts.symbols-only
- ] ++ lib.optional flatpakEnabled pkgs.flatpak;
- fonts.fontconfig = {
- enable = true;
- defaultFonts = lib.mkIf config.jhome.styling.enable {
- emoji = [ "Noto Color Emoji" ];
- monospace = [
- "JetBrains Mono"
- "Symbols Nerd Font"
- ];
- serif = [
- "Noto Serif"
- "Symbols Nerd Font"
- ];
- sansSerif = [
- "Noto Sans"
- "Symbols Nerd Font"
- ];
- };
- };
- # Browser
- programs = {
- firefox = {
- enable = true;
- profiles."${config.home.username}" = {
- search = {
- force = true; # firefox replaces the search settings, force replace them back
- engines =
- let
- queryParam = name: value: { inherit name value; };
- in
- {
- # Add search.nixos.org as search engines
- nix-packages = {
- name = "Nix Packages";
- urls = [
- {
- template = "https://search.nixos.org/packages";
- params = [
- (queryParam "type" "packages")
- (queryParam "query" "{searchTerms}")
- ];
- }
- ];
-
- icon = "${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg";
- definedAliases = [
- "@np"
- "@nixpackages"
- ];
- };
-
- nixos-options = {
- name = "NixOS Options";
- urls = [
- {
- template = "https://search.nixos.org/options";
- params = [
- (queryParam "type" "packages")
- (queryParam "query" "{searchTerms}")
- ];
- }
- ];
-
- icon = "${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg";
- definedAliases = [
- "@no"
- "@nixopts"
- ];
- };
-
- nixos-wiki = {
- name = "NixOS Wiki";
- urls = [
- {
- template = "https://wiki.nixos.org/w/index.php";
- params = [ (queryParam "search" "{searchTerms}") ];
- }
- ];
- iconMapObj."16" = "https://wiki.nixos.org/favicon.ico";
- definedAliases = [
- "@nw"
- "@nixwiki"
- ];
- };
-
- # hide bing
- bing.metaData.hidden = true;
- };
- };
- };
- };
- # Dynamic Menu
- fuzzel = {
- enable = true;
- settings.main = lib.mkIf config.jhome.styling.enable {
- inherit (cfg) terminal;
- layer = "overlay";
- };
- };
- # Video player
- mpv = {
- enable = true;
- scripts = builtins.attrValues { inherit (pkgs.mpvScripts) uosc thumbfast; };
- };
- # Text editor
- nixvim.clipboard.providers.wl-copy.enable = lib.mkDefault true;
- # Terminal
- wezterm = {
- enable = cfg.terminal == "wezterm";
- extraConfig =
- lib.optionalString config.jhome.styling.enable # lua
- ''
- local wezterm = require("wezterm")
-
- local config = wezterm.config_builder()
-
- config.front_end = "WebGpu"
- config.hide_tab_bar_if_only_one_tab = true
- config.window_padding = { left = 1, right = 1, top = 1, bottom = 1 }
-
- return config
- '';
- };
- alacritty = {
- enable = cfg.terminal == "alacritty";
- settings = {
- # hide mouse when typing, this ensures I don't have to move the mouse when it hides text
- mouse.hide_when_typing = true;
- # Start zellij when it is enabled
- terminal.shell = lib.mkIf (config.jhome.dev.enable && config.programs.zellij.enable) {
- program = "${lib.getExe config.programs.zellij.package}";
- };
- };
- };
- zellij = {
- enable = cfg.terminal == "alacritty"; # alacritty has no terminal multiplexer built-in
- # Set default shell
- settings = {
- show_startup_tips = false; # disable the startup tips dialogue
- default_shell =
- if config.programs.fish.enable then
- "fish"
- else if config.programs.zsh.enable then
- "zsh"
- else
- "bash";
- };
- };
- # PDF reader
- zathura.enable = true;
- # Auto start sway
- fish.loginShellInit =
- lib.optionalString cfg.sway.autostart # fish
- ''
- # Start Sway on login to TTY 1
- if test "$(tty)" = /dev/tty1
- exec sway
- end
- '';
- };
- services = {
- # Volume/Backlight control and notifications
- avizo = {
- enable = true;
- settings.default = {
- time = 0.8;
- border-width = 0;
- height = 176;
- y-offset = 0.1;
- block-spacing = 1;
- };
- };
- # Sound tuning
- easyeffects.enable = true;
- # Auto configure displays
- kanshi.enable = lib.mkDefault true;
- # Notifications
- mako = {
- enable = true;
- settings = {
- layer = "overlay";
- border-radius = 8;
- default-timeout = 15000;
- };
- };
- };
-
- stylix = lib.mkIf config.jhome.styling.enable {
- # Set cursor style
- inherit cursor;
- targets.firefox.profileNames = [ config.home.username ];
- iconTheme = {
- enable = true;
- light = "Papirus-Light";
- dark = "Papirus-Dark";
- package = pkgs.papirus-icon-theme;
- };
- };
- home.pointerCursor = lib.mkIf config.jhome.styling.enable (
- lib.mkDefault {
- gtk.enable = true;
- inherit (cursor) name package;
- }
- );
- # Set Gtk theme
- gtk = lib.mkIf config.jhome.styling.enable {
- enable = true;
- gtk3.extraConfig.gtk-application-prefer-dark-theme = 1;
- gtk4.extraConfig.gtk-application-prefer-dark-theme = 1;
- };
- # Set Qt theme
- qt = lib.mkIf config.jhome.styling.enable { enable = true; };
-
- xdg.systemDirs.data = [
- "/usr/share"
- "/var/lib/flatpak/exports/share"
- "${config.xdg.dataHome}/flatpak/exports/share"
- ];
- };
-}
diff --git a/modules/hm/gui/sway.nix b/modules/hm/gui/sway.nix
deleted file mode 100644
index 9c7a312..0000000
--- a/modules/hm/gui/sway.nix
+++ /dev/null
@@ -1,224 +0,0 @@
-{
- config,
- pkgs,
- lib,
- ...
-}:
-let
- cfg = config.jhome.gui.sway;
-in
-{
- config = lib.mkIf (config.jhome.enable && config.jhome.gui.enable && cfg.enable) {
- # Window Manager
- wayland.windowManager.sway = {
- inherit (cfg) enable;
- config =
- let
- inherit (config.jhome.gui) terminal;
- termCmd =
- if terminal == "wezterm" then
- "wezterm start"
- else if terminal == "alacritty" then
- "alacritty -e"
- else
- builtins.abort "no command configured for ${terminal}";
- menu = "${pkgs.fuzzel}/bin/fuzzel --terminal '${termCmd}'";
- cmdOnce = command: { inherit command; };
- cmdAlways = command: {
- inherit command;
- always = true;
- };
- in
- {
- modifier = "Mod4";
- inherit terminal menu;
- # Appearance
- bars = [ ]; # Waybar is started as a systemd service
- gaps = {
- smartGaps = true;
- smartBorders = "on";
- inner = 4;
- };
- output."*".bg = "${cfg.background} fill";
- # Window Appearance
- window = {
- border = 2;
- titlebar = false;
- # Make certain windows floating
- commands = [
- {
- command = "floating enable";
- criteria.title = "zoom";
- }
- {
- command = "floating enable";
- criteria.class = "floating";
- }
- {
- command = "floating enable";
- criteria.app_id = "floating";
- }
- ];
- };
- # Startup scripts
- startup =
- let
- # currently, there is some friction between sway and gtk:
- # https://github.com/swaywm/sway/wiki/GTK-3-settings-on-Wayland
- # the suggested way to set gtk settings is with gsettings
- # for gsettings to work, we need to tell it where the schemas are
- # using the XDG_DATA_DIR environment variable
- # run at the end of sway config
- schema = pkgs.gsettings-desktop-schemas;
- datadir = "${schema}/share/gsettings-schemas/${schema.name}";
- in
- [
- (cmdAlways "${pkgs.writers.writeDash "configure-gtk" ''
- export XDG_DATA_DIRS="${datadir}:$XDG_DATA_DIRS"
-
- gnome_schema=org.gnome.desktop.interface
- config="${config.xdg.configHome}/gtk-3.0/settings.ini"
- if [ ! -f "$config" ]; then exit 1; fi
- # Read settings from gtk3
- gtk_theme="$(${pkgs.gnugrep}/bin/grep 'gtk-theme-name' "$config" | ${pkgs.gnused}/bin/sed 's/.*\s*=\s*//')"
- icon_theme="$(${pkgs.gnugrep}/bin/grep 'gtk-icon-theme-name' "$config" | ${pkgs.gnused}/bin/sed 's/.*\s*=\s*//')"
- cursor_theme="$(${pkgs.gnugrep}/bin/grep 'gtk-cursor-theme-name' "$config" | ${pkgs.gnused}/bin/sed 's/.*\s*=\s*//')"
- font_name="$(grep 'gtk-font-name' "$config" | sed 's/.*\s*=\s*//')"
- ${pkgs.glib}/bin/gsettings set "$gnome_schema" gtk-theme "$gtk_theme"
- ${pkgs.glib}/bin/gsettings set "$gnome_schema" icon-theme "$icon_theme"
- ${pkgs.glib}/bin/gsettings set "$gnome_schema" cursor-theme "$cursor_theme"
- ${pkgs.glib}/bin/gsettings set "$gnome_schema" font-name "$font_name"
- ${pkgs.glib}/bin/gsettings set "$gnome_schema" color-scheme prefer-dark
- ''}")
- ]
- ++ (builtins.map cmdAlways cfg.exec.always)
- ++ (builtins.map cmdOnce cfg.exec.once);
- # Keyboard configuration
- input."type:keyboard" = {
- repeat_delay = "300";
- repeat_rate = "50";
- };
- # Touchpad
- input."type:touchpad" = {
- click_method = "clickfinger";
- natural_scroll = "enabled";
- scroll_method = "two_finger";
- tap = "enabled";
- tap_button_map = "lrm";
- };
- # Keybinds
- keybindings =
- let
- passmenu = "${pkgs.jpassmenu}/bin/jpassmenu";
- selectAudio = "${pkgs.audiomenu}/bin/audiomenu";
- swayconf = config.wayland.windowManager.sway.config;
- mod = swayconf.modifier;
- workspaces = map toString (lib.lists.range 1 9);
- dirs =
- map
- (dir: {
- key = swayconf.${dir};
- arrow = dir;
- direction = dir;
- })
- [
- "up"
- "down"
- "left"
- "right"
- ];
- joinKeys = builtins.concatStringsSep "+";
- # Generate a keybind from a modifier prefix and a key
- keycombo = prefix: key: joinKeys (prefix ++ [ key ]);
- modKeybind = keycombo [ mod ];
- modCtrlKeybind = keycombo [
- mod
- "Ctrl"
- ];
- modShiftKeybind = keycombo [
- mod
- "Shift"
- ];
- modCtrlShiftKeybind = keycombo [
- mod
- "Ctrl"
- "Shift"
- ];
- dir2resize.up = "resize grow height";
- dir2resize.down = "resize shrink height";
- dir2resize.right = "resize grow width";
- dir2resize.left = "resize shrink width";
- # Bind a key combo to an action
- genKeybind = prefix: action: key: { "${prefix key}" = "${action key}"; };
- genKey =
- prefix: action: genKeybind ({ key, ... }: prefix key) ({ direction, ... }: action direction);
- genArrow =
- prefix: action: genKeybind ({ arrow, ... }: prefix arrow) ({ direction, ... }: action direction);
- genArrowAndKey =
- prefix: action: key:
- (genKey prefix action key) // (genArrow prefix action key);
- # Move window
- moveWindowKeybinds = map (genArrowAndKey modShiftKeybind (dir: "move ${dir}")) dirs;
- # Focus window
- focusWindowKeybinds = map (genArrowAndKey modKeybind (dir: "focus ${dir}")) dirs;
- # Resize window
- resizeWindowKeybinds = map (genArrowAndKey modCtrlKeybind (dir: dir2resize.${dir})) dirs;
- # Move container to workspace
- moveWorkspaceKeybindings = map (genKeybind modShiftKeybind (
- number: "move container to workspace number ${number}"
- )) workspaces;
- # Focus workspace
- focusWorkspaceKeybindings = map (genKeybind modKeybind (
- number: "workspace number ${number}"
- )) workspaces;
- # Move container to Workspace and focus on it
- moveFocusWorkspaceKeybindings = map (genKeybind modCtrlShiftKeybind (
- number: "move container to workspace number ${number}; workspace number ${number}"
- )) workspaces;
- in
- builtins.foldl' (l: r: l // r)
- {
- "${mod}+Return" = "exec ${swayconf.terminal}";
- "${mod}+D" = "exec ${swayconf.menu}";
- "${mod}+P" = "exec ${passmenu}";
- "${mod}+Shift+P" = "exec ${passmenu} --type";
- "${mod}+F2" = "exec qutebrowser";
- "${mod}+Shift+Q" = "kill";
- "${mod}+F" = "fullscreen toggle";
- # Media Controls
- "${mod}+F10" = "exec ${selectAudio} select-sink";
- "${mod}+Shift+F10" = "exec ${selectAudio} select-source";
- "XF86AudioRaiseVolume" = "exec ${pkgs.avizo}/bin/volumectl up";
- "XF86AudioLowerVolume" = "exec ${pkgs.avizo}/bin/volumectl down";
- "XF86AudioMute" = "exec ${pkgs.avizo}/bin/volumectl toggle-mute";
- "XF86ScreenSaver" = "exec ${pkgs.swaylock}/bin/swaylock --image ${cfg.background}";
- "XF86MonBrightnessUp" = "exec ${pkgs.avizo}/bin/lightctl up";
- "XF86MonBrightnessDown" = "exec ${pkgs.avizo}/bin/lightctl down";
- # Floating
- "${mod}+Space" = "floating toggle";
- "${mod}+Shift+Space" = "focus mode_toggle";
- # Scratchpad
- "${mod}+Minus" = "scratchpad show";
- "${mod}+Shift+Minus" = "move scratchpad";
- # Layout
- "${mod}+e" = "layout toggle split";
- # Session control
- "${mod}+r" = "reload";
- "${mod}+Shift+m" = "exit";
- }
- (
- focusWindowKeybinds
- ++ moveWindowKeybinds
- ++ resizeWindowKeybinds
- ++ focusWorkspaceKeybindings
- ++ moveWorkspaceKeybindings
- ++ moveFocusWorkspaceKeybindings
- );
- };
- systemd = {
- enable = true;
- xdgAutostart = true;
- };
- };
- };
-}
diff --git a/modules/hm/gui/waybar.nix b/modules/hm/gui/waybar.nix
deleted file mode 100644
index eefdab4..0000000
--- a/modules/hm/gui/waybar.nix
+++ /dev/null
@@ -1,159 +0,0 @@
-{
- config,
- pkgs,
- lib,
- ...
-}:
-let
- inherit (config) jhome;
- cfg = jhome.gui;
- swayconf = config.wayland.windowManager.sway;
-in
-{
- config = lib.mkIf (config.jhome.enable && cfg.enable) {
- # Status bar
- programs.waybar = {
- enable = true;
- systemd.enable = true;
- settings = lib.mkIf config.jhome.styling.enable {
- mainBar = {
- layer = "top";
- position = "top";
- margin = "2 2 2 2";
- # Choose the order of the modules
- modules-left = [ "sway/workspaces" ];
- modules-center = [ "clock" ];
- modules-right =
- [
- "pulseaudio"
- "backlight"
- "battery"
- "sway/language"
- "memory"
- ]
- ++ lib.optional (cfg.tempInfo != null) "temperature"
- ++ [ "tray" ];
- "sway/workspaces" = lib.mkIf swayconf.enable {
- disable-scroll = true;
- persistent-workspaces = {
- "1" = [ ];
- "2" = [ ];
- "3" = [ ];
- "4" = [ ];
- "5" = [ ];
- "6" = [ ];
- "7" = [ ];
- "8" = [ ];
- "9" = [ ];
- };
- };
- "sway/language" = lib.mkIf swayconf.enable {
- format = "{} ";
- min-length = 5;
- tooltip = false;
- };
- memory = {
- format = "{used:0.1f}/{total:0.1f}GiB ";
- interval = 3;
- };
- clock = {
- timezone = "Europe/Berlin";
- tooltip-format = "{:%Y %B}\n{calendar}";
- format = "{:%a, %d %b, %H:%M}";
- };
- wireplumber = {
- reverse-scrolling = 1;
- format = "{volume}% {icon} {format_source}";
- format-bluetooth = "{volume}% {icon} {format_source}";
- format-bluetooth-muted = "{volume}% {icon} {format_source}";
- format-muted = "{volume}% {format_source}";
- format-source = "{volume}% ";
- format-source-muted = "{volume}% ";
- format-icons = {
- headphone = "";
- hands-free = "";
- headset = "";
- phone = "";
- portable = "";
- car = "";
- default = [
- ""
- ""
- ""
- ];
- };
- on-click = lib.getExe pkgs.helvum;
- min-length = 13;
- };
- temperature = lib.optionalAttrs (cfg.tempInfo != null) {
- inherit (cfg.tempInfo) hwmon-path;
- critical-threshold = 80;
- format = "{temperatureC}°C {icon}";
- format-icons = [
- ""
- ""
- ""
- ""
- ""
- ];
- tooltip = false;
- };
- backlight = {
- device = "intel_backlight";
- format = "{percent}% {icon}";
- format-icons = [
- ""
- ""
- ""
- ""
- ""
- ""
- ""
- ];
- min-length = 7;
- };
- battery = {
- states.warning = 30;
- states.critical = 15;
- format = "{capacity}% {icon}";
- format-charging = "{capacity}% ";
- format-plugged = "{capacity}% ";
- format-alt = "{time} {icon}";
- format-icons = [
- ""
- ""
- ""
- ""
- ""
- ""
- ""
- ""
- ""
- ""
- ];
- };
- tray = {
- icon-size = 16;
- spacing = 0;
- };
- };
- };
- # Style overrides to highlight workspaces with windows
- style =
- lib.pipe
- # css
- ''
- .modules-left #workspaces button {
- border-bottom: 3px solid @base01;
- }
- .modules-left #workspaces button.persistent {
- border-bottom: 3px solid transparent;
- }
- ''
- [
- (lib.optionalString config.jhome.styling.enable)
- lib.mkAfter
- ];
- };
- };
-}
diff --git a/modules/lib.nix b/modules/lib.nix
deleted file mode 100644
index 3e3a288..0000000
--- a/modules/lib.nix
+++ /dev/null
@@ -1,27 +0,0 @@
-{ lib }:
-let
- inherit (lib) types;
-in
-{
- # Like mkEnableOption but defaults to true
- mkDisableOption =
- option:
- (lib.mkEnableOption option)
- // {
- default = true;
- example = false;
- };
- # A option that accepts an image (and shows it in the docs)
- mkImageOption =
- {
- description,
- url,
- sha256 ? "",
- }:
- lib.mkOption {
- inherit description;
- type = types.path;
- default = builtins.fetchurl { inherit url sha256; };
- defaultText = lib.literalMD "";
- };
-}
diff --git a/modules/nixos/default.nix b/modules/nixos/default.nix
deleted file mode 100644
index e2e4370..0000000
--- a/modules/nixos/default.nix
+++ /dev/null
@@ -1,76 +0,0 @@
-{ pkgs, lib, ... }@args:
-let
- cfg = args.config.jconfig;
- keysFromGithub = lib.attrsets.mapAttrs' (username: sha256: {
- name = "pubkeys/${username}";
- value = {
- mode = "0755";
- source = builtins.fetchurl {
- inherit sha256;
- url = "https://github.com/${username}.keys";
- };
- };
- }) cfg.importSSHKeysFromGithub;
-in
-{
- imports = [
- ./options.nix
- ./dev.nix
- ./gui.nix
- ./starship.nix
- ./styling.nix
- ];
-
- config = lib.mkIf cfg.enable {
- # Enable unlocking the gpg-agent at boot (configured through home.nix)
- security.pam.services.login.gnupg.enable = true;
-
- environment.systemPackages = [
- # CLI tools
- pkgs.fd
- pkgs.ripgrep
- pkgs.du-dust
- pkgs.curl
- pkgs.zip
- pkgs.unzip
- ];
-
- programs.fish.enable = true;
-
- environment.etc = keysFromGithub;
- services = {
- # Enable printer autodiscovery if printing is enabled
- avahi = {
- inherit (args.config.services.printing) enable;
- nssmdns4 = true;
- openFirewall = true;
- };
- openssh.authorizedKeysFiles = builtins.map (keys: "/etc/${keys}") (
- builtins.attrNames keysFromGithub
- );
- };
- # Open ports for spotifyd
- networking.firewall = {
- allowedUDPPorts = [ 5353 ];
- allowedTCPPorts = [ 2020 ];
- };
- # Nix Settings
- nix = {
- gc = {
- automatic = true;
- dates = "weekly";
- options = "--delete-older-than 30d";
- # run between 0 and 45min after boot if run was missed
- randomizedDelaySec = "45min";
- };
- settings = {
- use-xdg-base-directories = true;
- auto-optimise-store = true;
- experimental-features = [
- "nix-command"
- "flakes"
- ];
- };
- };
- };
-}
diff --git a/modules/nixos/dev.nix b/modules/nixos/dev.nix
deleted file mode 100644
index b4aee84..0000000
--- a/modules/nixos/dev.nix
+++ /dev/null
@@ -1,18 +0,0 @@
-{ lib, config, ... }:
-let
- cfg = config.jconfig.dev;
-in
-{
- config = lib.mkIf (config.jconfig.enable && cfg.enable) {
- # Enable dev documentation
- documentation.dev = { inherit (cfg) enable; };
-
- users.extraUsers = lib.mkIf cfg.jupyter.enable { jupyter.group = "jupyter"; };
-
- services.jupyter = {
- inherit (cfg.jupyter) enable;
- group = "jupyter";
- user = "jupyter";
- };
- };
-}
diff --git a/modules/nixos/gui.nix b/modules/nixos/gui.nix
deleted file mode 100644
index d07f706..0000000
--- a/modules/nixos/gui.nix
+++ /dev/null
@@ -1,117 +0,0 @@
-{ lib, pkgs, ... }@args:
-let
- cfg = args.config.jconfig.gui;
- enable = args.config.jconfig.enable && cfg.enable;
- linuxOlderThan6_3 = lib.versionOlder args.config.boot.kernelPackages.kernel.version "6.3";
-in
-{
- config =
- lib.flip lib.pipe
- [ lib.mkMerge (lib.mkIf enable) ]
- [
- {
- environment.systemPackages = [
- pkgs.adwaita-icon-theme
- pkgs.adwaita-qt
- pkgs.nordzy-cursor-theme
- pkgs.pinentry-qt
- ];
- # Fix xdg-portals issue issue: https://github.com/NixOS/nixpkgs/issues/189851
- systemd.user.extraConfig = ''
- DefaultEnvironment="PATH=/run/wrappers/bin:/etc/profiles/per-user/%u/bin:/nix/var/nix/profiles/default/bin:/run/current-system/sw/bin"
- '';
-
- fonts.fontDir.enable = true;
- programs = {
- dconf.enable = true;
- sway = {
- enable = cfg.sway;
- # No extra packages (by default it adds foot, dmenu, and other stuff)
- extraPackages = [ ];
- wrapperFeatures = {
- base = true;
- gtk = true;
- };
- };
- };
- security = {
- polkit.enable = true;
- rtkit.enable = true; # Recommended for pipewire
- };
- services = {
- flatpak.enable = true;
- # Audio
- pipewire = {
- enable = true;
- alsa = {
- enable = true;
- support32Bit = true;
- };
- pulse.enable = true;
- wireplumber.enable = true;
- };
- # Dbus
- dbus.enable = true;
- # Virtual Filesystem (for PCManFM)
- gvfs.enable = true;
- };
- xdg.portal = {
- # XDG portals
- enable = true;
- wlr.enable = true;
- extraPortals = [ pkgs.xdg-desktop-portal-gtk ];
- config.preferred = {
- # Default to the gtk portal
- default = "gtk";
- # Use wlr for screenshots and screen recording
- "org.freedesktop.impl.portal.Screenshot" = "wlr";
- };
- # Consider using darkman like upstream
- };
- hardware = {
- graphics.enable = true;
- uinput.enable = true;
- steam-hardware.enable = cfg.steamHardwareSupport;
- };
- }
- (lib.mkIf cfg.ydotool.enable {
- environment.systemPackages = [ pkgs.ydotool ];
- systemd.user.services.ydotool = {
- enable = cfg.ydotool.autoStart;
- wantedBy = [ "default.target" ];
- description = "Generic command-line automation tool";
- documentation = [
- "man:ydotool(1)"
- "man:ydotoold(8)"
- ];
- serviceConfig = {
- Type = "simple";
- Restart = "always";
- ExecStart = "${pkgs.ydotool}/bin/ydotoold";
- ExecReload = "${pkgs.util-linux}/bin/kill -HUP $MAINPID";
- KillMode = "process";
- TimeoutSec = 180;
- };
- };
- })
- (lib.mkIf (linuxOlderThan6_3 && cfg."8bitdoFix") {
- # Udev rules to start or stop systemd service when controller is connected or disconnected
- services.udev.extraRules = # udev
- ''
- # May vary depending on your controller model, find product id using 'lsusb'
- SUBSYSTEM=="usb", ATTR{idVendor}=="2dc8", ATTR{idProduct}=="3106", ATTR{manufacturer}=="8BitDo", RUN+="${pkgs.systemd}/bin/systemctl start 8bitdo-ultimate-xinput@2dc8:3106"
- # This device (2dc8:3016) is "connected" when the above device disconnects
- SUBSYSTEM=="usb", ATTR{idVendor}=="2dc8", ATTR{idProduct}=="3016", ATTR{manufacturer}=="8BitDo", RUN+="${pkgs.systemd}/bin/systemctl stop 8bitdo-ultimate-xinput@2dc8:3106"
- '';
-
- # Systemd service which starts xboxdrv in xbox360 mode
- systemd.services."8bitdo-ultimate-xinput@" = {
- unitConfig.Description = "8BitDo Ultimate Controller XInput mode xboxdrv daemon";
- serviceConfig = {
- Type = "simple";
- ExecStart = "${pkgs.xboxdrv}/bin/xboxdrv --mimic-xpad --silent --type xbox360 --device-by-id %I --force-feedback";
- };
- };
- })
- ];
-}
diff --git a/modules/nixos/options.nix b/modules/nixos/options.nix
deleted file mode 100644
index d8b4e64..0000000
--- a/modules/nixos/options.nix
+++ /dev/null
@@ -1,95 +0,0 @@
-{ lib, ... }:
-let
- inherit (lib) types;
- inherit (import ../lib.nix { inherit lib; })
- mkDisableOption
- mkImageOption
- ;
-in
-{
- options.jconfig = lib.mkOption {
- description = "Jalil's default NixOS configuration.";
- default = { };
- type = types.submodule {
- options = {
- enable = lib.mkEnableOption "jalil's default configuration.";
- importSSHKeysFromGithub = lib.mkOption {
- description = ''
- Import public ssh keys from a github username.
-
- This will fetch the keys from https://github.com/$${username}.keys.
-
- The format is `"$${github-username}" = $${sha256-hash}`. The example
- will try to fetch the keys from .
-
- **Warning**: this will interfere with services like gitea that override
- the default ssh behaviour. In that case you want to use
- `users.users..openssh.authorizedKeys.keyFiles` on the users you
- want to allow ssh logins.
- '';
- default = { };
- example = {
- "jalil-salame" = "sha256:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
- };
- type = types.attrsOf types.str;
- };
-
- dev = lib.mkOption {
- description = "Options for setting up a dev environment";
- default = { };
- type = types.submodule {
- options = {
- enable = lib.mkEnableOption "dev configuration";
- jupyter.enable = lib.mkEnableOption "jupyter configuration";
- };
- };
- };
-
- gui = lib.mkOption {
- description = "Jalil's default configuration for a NixOS gui.";
- default = { };
- type = types.submodule {
- options = {
- enable = lib.mkEnableOption "jalil's default gui configuration.";
- # Fix for using Xinput mode on 8bitdo Ultimate C controller
- # Inspired by https://aur.archlinux.org/packages/8bitdo-ultimate-controller-udev
- # Adapted from: https://gist.github.com/interdependence/28452fbfbe692986934fbe1e54c920d4
- "8bitdoFix" = mkDisableOption "a fix for 8bitdo controllers";
- steamHardwareSupport = mkDisableOption "steam hardware support";
- ydotool = lib.mkOption {
- description = "Jalil's default ydotool configuration.";
- default = { };
- type = types.submodule {
- options.enable = mkDisableOption "ydotool";
- options.autoStart = mkDisableOption "autostarting ydotool at login";
- };
- };
- sway = mkDisableOption "sway";
- };
- };
- };
-
- styling = lib.mkOption {
- description = "Jalil's styling options";
- default = { };
- type = types.submodule {
- options = {
- enable = mkDisableOption "jalil's default styling (disables stylix)";
- wallpaper = mkImageOption {
- description = "The wallpaper to use.";
- url = "https://raw.githubusercontent.com/lunik1/nixos-logo-gruvbox-wallpaper/d4937c424fad79c1136a904599ba689fcf8d0fad/png/gruvbox-dark-rainbow.png";
- sha256 = "036gqhbf6s5ddgvfbgn6iqbzgizssyf7820m5815b2gd748jw8zc";
- };
- bootLogo = mkImageOption {
- description = "The logo used by plymouth at boot.";
- # http://xenia-linux-site.glitch.me/images/cathodegaytube-splash.png
- url = "https://efimero.github.io/xenia-images/cathodegaytube-splash.png";
- sha256 = "qKugUfdRNvMwSNah+YmMepY3Nj6mWlKFh7jlGlAQDo8=";
- };
- };
- };
- };
- };
- };
- };
-}
diff --git a/modules/nixos/starship.nix b/modules/nixos/starship.nix
deleted file mode 100644
index 3ab8d8b..0000000
--- a/modules/nixos/starship.nix
+++ /dev/null
@@ -1,183 +0,0 @@
-{ pkgs, lib, ... }@args:
-let
- cfg = args.config.jconfig;
-in
-{
- config = lib.mkIf cfg.enable {
- programs.starship = {
- enable = true;
- settings = lib.mkMerge [
- {
- format = "$time$all";
- add_newline = false;
- cmd_duration.min_time = 500;
- cmd_duration.show_milliseconds = true;
- time.disabled = false;
- status = {
- format = "[$signal_name$common_meaning$maybe_int](red)";
- symbol = "[✗](bold red)";
- disabled = false;
- };
- sudo.disabled = false;
- }
- # Add nerdfont symbols
- (lib.mkIf cfg.styling.enable {
- aws.symbol = " ";
- buf.symbol = " ";
- c.symbol = " ";
- conda.symbol = " ";
- crystal.symbol = " ";
- dart.symbol = " ";
- directory.read_only = " ";
- docker_context.symbol = " ";
- elixir.symbol = " ";
- elm.symbol = " ";
- fennel.symbol = " ";
- fossil_branch.symbol = " ";
- git_branch.symbol = " ";
- git_commit.tag_symbol = " ";
- golang.symbol = " ";
- gradle.symbol = " ";
- guix_shell.symbol = " ";
- haskell.symbol = " ";
- haxe.symbol = " ";
- hg_branch.symbol = " ";
- hostname.ssh_symbol = " ";
- java.symbol = " ";
- julia.symbol = " ";
- kotlin.symbol = " ";
- lua.symbol = " ";
- memory_usage.symbol = " ";
- meson.symbol = " ";
- nim.symbol = " ";
- nix_shell.symbol = " ";
- nodejs.symbol = " ";
- ocaml.symbol = " ";
- package.symbol = " ";
- perl.symbol = " ";
- php.symbol = " ";
- pijul_channel.symbol = " ";
- python.symbol = " ";
- rlang.symbol = " ";
- ruby.symbol = " ";
- rust.symbol = " ";
- scala.symbol = " ";
- swift.symbol = " ";
- zig.symbol = " ";
- os.symbols = {
- Alpaquita = " ";
- Alpine = " ";
- AlmaLinux = " ";
- Amazon = " ";
- Android = " ";
- Arch = " ";
- Artix = " ";
- CentOS = " ";
- Debian = " ";
- DragonFly = " ";
- Emscripten = " ";
- EndeavourOS = " ";
- Fedora = " ";
- FreeBSD = " ";
- Garuda = " ";
- Gentoo = " ";
- HardenedBSD = " ";
- Illumos = " ";
- Kali = " ";
- Linux = " ";
- Mabox = " ";
- Macos = " ";
- Manjaro = " ";
- Mariner = " ";
- MidnightBSD = " ";
- Mint = " ";
- NetBSD = " ";
- NixOS = " ";
- OpenBSD = " ";
- openSUSE = " ";
- OracleLinux = " ";
- Pop = " ";
- Raspbian = " ";
- Redhat = " ";
- RedHatEnterprise = " ";
- RockyLinux = " ";
- Redox = " ";
- Solus = " ";
- SUSE = " ";
- Ubuntu = " ";
- Unknown = " ";
- Void = " ";
- Windows = " ";
- };
- })
- # Remove the `in`s and `on`s from the prompt
- {
- aws.format = "[$symbol($profile)(\\($region\\))(\\[$duration\\])]($style) ";
- bun.format = "[$symbol($version)]($style) ";
- c.format = "[$symbol($version(-$name))]($style) ";
- cmake.format = "[$symbol($version)]($style) ";
- cmd_duration.format = "[⏱ $duration]($style) ";
- cobol.format = "[$symbol($version)]($style) ";
- conda.format = "[$symbol$environment]($style) ";
- crystal.format = "[$symbol($version)]($style) ";
- daml.format = "[$symbol($version)]($style) ";
- dart.format = "[$symbol($version)]($style) ";
- deno.format = "[$symbol($version)]($style) ";
- docker_context.format = "[$symbol$context]($style) ";
- dotnet.format = "[$symbol($version)(🎯 $tfm)]($style) ";
- elixir.format = "[$symbol($version \\(OTP $otp_version\\))]($style) ";
- elm.format = "[$symbol($version)]($style) ";
- erlang.format = "[$symbol($version)]($style) ";
- fennel.format = "[$symbol($version)]($style) ";
- fossil_branch.format = "[$symbol$branch]($style) ";
- gcloud.format = "[$symbol$account(@$domain)(\\($region\\))]($style) ";
- git_branch.format = "[$symbol$branch]($style) ";
- git_status.format = "[$all_status$ahead_behind]($style) ";
- golang.format = "[$symbol($version)]($style) ";
- gradle.format = "[$symbol($version)]($style) ";
- guix_shell.format = "[$symbol]($style) ";
- haskell.format = "[$symbol($version)]($style) ";
- haxe.format = "[$symbol($version)]($style) ";
- helm.format = "[$symbol($version)]($style) ";
- hg_branch.format = "[$symbol$branch]($style) ";
- java.format = "[$symbol($version)]($style) ";
- julia.format = "[$symbol($version)]($style) ";
- kotlin.format = "[$symbol($version)]($style) ";
- kubernetes.format = "[$symbol$context( \\($namespace\\))]($style) ";
- lua.format = "[$symbol($version)]($style) ";
- memory_usage.format = "$symbol[$ram( | $swap)]($style) ";
- meson.format = "[$symbol$project]($style) ";
- nim.format = "[$symbol($version)]($style) ";
- nix_shell.format = "[$symbol$state( \\($name\\))]($style) ";
- nodejs.format = "[$symbol($version)]($style) ";
- ocaml.format = "[$symbol($version)(\\($switch_indicator$switch_name\\))]($style) ";
- opa.format = "[$symbol($version)]($style) ";
- openstack.format = "[$symbol$cloud(\\($project\\))]($style) ";
- os.format = "[$symbol]($style) ";
- package.format = "[$symbol$version]($style) ";
- perl.format = "[$symbol($version)]($style) ";
- php.format = "[$symbol($version)]($style) ";
- pijul_channel.format = "[$symbol$channel]($style) ";
- pulumi.format = "[$symbol$stack]($style) ";
- purescript.format = "[$symbol($version)]($style) ";
- python.format = "[\${symbol}\${pyenv_prefix}(\${version})(\\($virtualenv\\))]($style) ";
- raku.format = "[$symbol($version-$vm_version)]($style) ";
- red.format = "[$symbol($version)]($style) ";
- ruby.format = "[$symbol($version)]($style) ";
- rust.format = "[$symbol($version)]($style) ";
- scala.format = "[$symbol($version)]($style) ";
- spack.format = "[$symbol$environment]($style) ";
- sudo.format = "[as $symbol]($style) ";
- swift.format = "[$symbol($version)]($style) ";
- terraform.format = "[$symbol$workspace]($style) ";
- time.format = "[$time]($style) ";
- username.format = "[$user]($style) ";
- vagrant.format = "[$symbol($version)]($style) ";
- vlang.format = "[$symbol($version)]($style) ";
- zig.format = "[$symbol($version)]($style) ";
- solidity.format = "[$symbol($version)]($style) ";
- }
- ];
- };
- };
-}
diff --git a/modules/nixos/styling.nix b/modules/nixos/styling.nix
deleted file mode 100644
index b20a2d7..0000000
--- a/modules/nixos/styling.nix
+++ /dev/null
@@ -1,43 +0,0 @@
-{ lib, pkgs, ... }@args:
-let
- cfg = args.config.jconfig.styling;
- enable = args.config.jconfig.enable && cfg.enable;
-in
-{
- config = lib.mkIf enable {
- boot.plymouth = { inherit (cfg) enable; };
-
- stylix = {
- inherit (cfg) enable;
- image = cfg.wallpaper;
- base16Scheme = "${pkgs.base16-schemes}/share/themes/gruvbox-dark-hard.yaml";
- polarity = "dark";
- fonts = {
- monospace = {
- name = "JetBrains Mono";
- package = pkgs.jetbrains-mono;
- };
- sansSerif = {
- name = "Noto Sans";
- package = pkgs.noto-fonts;
- };
- serif = {
- name = "Noto Serif";
- package = pkgs.noto-fonts;
- };
- emoji = {
- package = pkgs.noto-fonts-emoji;
- name = "Noto Color Emoji";
- };
- sizes.popups = 12;
- };
- targets = {
- plymouth = {
- logoAnimated = false;
- logo = cfg.bootLogo;
- };
- nixvim.enable = false;
- };
- };
- };
-}
diff --git a/modules/nixvim/plugins.nix b/modules/nixvim/plugins.nix
deleted file mode 100644
index 8943c56..0000000
--- a/modules/nixvim/plugins.nix
+++ /dev/null
@@ -1,151 +0,0 @@
-{ lib, helpers, ... }:
-let
- inherit (helpers) mkRaw;
-in
-{
- config.plugins = {
- cmp =
- let
- srcWithIndex = groupIndex: name: { inherit name groupIndex; };
- in
- {
- enable = true;
- cmdline = {
- "/" = {
- mapping =
- mkRaw
- # lua
- ''
- cmp.mapping.preset.cmdline()
- '';
- sources = [
- { name = "rg"; }
- { name = "buffer"; }
- ];
- };
- ":" = {
- mapping =
- mkRaw
- # lua
- "cmp.mapping.preset.cmdline()";
- sources = [
- { name = "path"; }
- { name = "cmdline"; }
- ];
- };
- };
- settings = {
- # Snippets
- snippet.expand =
- # lua
- "function(args) require('luasnip').lsp_expand(args.body) end";
- # Completion Sources
- sources = [
- # very specific (not noisy)
- (srcWithIndex 1 "calc")
- (srcWithIndex 1 "crates")
- (srcWithIndex 1 "fish")
- (srcWithIndex 1 "luasnip")
- (srcWithIndex 1 "nvim_lsp")
- # Generally ok
- (srcWithIndex 2 "conventionalcommits")
- (srcWithIndex 2 "nvim_lsp_document_symbol")
- (srcWithIndex 2 "nvim_lsp_signature_help")
- # Noisy
- (srcWithIndex 2 "path")
- (srcWithIndex 3 "spell")
- (srcWithIndex 3 "treesitter")
- # Very noisy
- (srcWithIndex 4 "buffer")
- ];
- mapping =
- mkRaw
- # lua
- ''
- cmp.mapping.preset.insert({
- [""] = function(fallback)
- if cmp.visible() then
- cmp.select_next_item()
- elseif require("luasnip").expand_or_jumpable() then
- require("luasnip").expand_or_jump()
- elseif has_words_before() then
- cmp.complete()
- else
- fallback()
- end
- end,
- [""] = function(fallback)
- if cmp.visible() then
- cmp.select_prev_item()
- elseif require("luasnip").jumpable(-1) then
- require("luasnip").jump(-1)
- else
- fallback()
- end
- end,
- [""] = cmp.mapping(function(fallback)
- if require("luasnip").choice_active() then
- require("luasnip").next_choice()
- else
- fallback()
- end
- end),
- [""] = cmp.mapping.scroll_docs(-4),
- [""] = cmp.mapping.scroll_docs(4),
- [""] = cmp.mapping.complete { },
- [""] = cmp.mapping.close(),
- [""] = cmp.mapping.confirm { select = true },
- })
- '';
- };
- };
- cmp-fish.enable = true;
- gitsigns.enable = true;
- lualine = {
- enable = true;
- settings.options.theme = lib.mkForce "gruvbox";
- };
- luasnip = {
- enable = true;
- settings.update_events = "TextChanged,TextChangedI";
- };
- noice = {
- enable = true;
- settings = {
- lsp.override = {
- "vim.lsp.util.convert_input_to_markdown_lines" = true;
- "vim.lsp.util.stylize_markdown" = true;
- "cmp.entry.get_documentation" = true;
- };
- presets = {
- # use a classic bottom cmdline for search
- bottom_search = true;
- # position the cmdline and popupmenu together
- command_palette = false;
- # long messages will be sent to a split
- long_message_to_split = true;
- # enables an input dialog for inc-rename.nvim
- inc_rename = false;
- # add a border to hover docs and signature help
- lsp_doc_border = true;
- };
- };
- };
- notify = {
- enable = true;
- settings.background_colour = "#000000";
- };
- telescope = {
- enable = true;
- extensions = {
- ui-select.enable = true;
- fzy-native.enable = true;
- };
- };
- trouble = {
- enable = true;
- settings.auto_close = true;
- };
- web-devicons.enable = true;
- };
-}
diff --git a/modules/nixvim/augroups.nix b/nvim/augroups.nix
similarity index 100%
rename from modules/nixvim/augroups.nix
rename to nvim/augroups.nix
diff --git a/modules/nixvim/default.nix b/nvim/default.nix
similarity index 78%
rename from modules/nixvim/default.nix
rename to nvim/default.nix
index 6152af6..afe1a05 100644
--- a/modules/nixvim/default.nix
+++ b/nvim/default.nix
@@ -6,9 +6,10 @@ in
imports = [ ./options.nix ];
config.programs.nixvim = lib.mkMerge [
- ./standalone.nix
+ (import ./standalone.nix)
(lib.mkIf cfg.enable {
enable = true;
+ nixpkgs.useGlobalPackages = true;
defaultEditor = lib.mkDefault true;
jhome.nvim = cfg;
})
diff --git a/modules/nixvim/dev-plugins.nix b/nvim/dev-plugins.nix
similarity index 65%
rename from modules/nixvim/dev-plugins.nix
rename to nvim/dev-plugins.nix
index d7c0a21..7659912 100644
--- a/modules/nixvim/dev-plugins.nix
+++ b/nvim/dev-plugins.nix
@@ -7,13 +7,11 @@
}:
let
inherit (helpers) enableExceptInTests;
- inherit (lib.trivial) const;
cfg = config.jhome.nvim;
enabledLSPs = [
"basedpyright"
"bashls"
"clangd"
- "gopls"
# "html" # Not writing html
"jsonls"
"marksman"
@@ -23,20 +21,22 @@ let
"typos_lsp"
# "typst_lsp" # Not using it
"zls"
- "fish_lsp"
];
-
- enableOpt.enable = true;
- noPackage.package = null;
in
{
config = lib.mkIf cfg.dev.enable (
lib.mkMerge [
# Enable LSPs
- { plugins.lsp.servers = lib.genAttrs enabledLSPs (const enableOpt); }
+ {
+ plugins.lsp.servers = lib.genAttrs enabledLSPs (_: {
+ enable = true;
+ });
+ }
# Remove bundled LSPs
(lib.mkIf (!cfg.dev.bundleLSPs) {
- plugins.lsp.servers = lib.genAttrs enabledLSPs (const noPackage);
+ plugins.lsp.servers = lib.genAttrs enabledLSPs (_: {
+ package = null;
+ });
})
# Configure LSPs
{
@@ -45,20 +45,17 @@ in
enable = true;
servers = {
# Pyright needs to have the project root set?
- basedpyright.rootMarkers = [
- "flake.nix"
- ".git"
- ".jj"
- "pyproject.toml"
- "setup.py"
- ];
- # Big but infrequently used dependencies.
- #
- # Configure the LSPs, but don't install the packages.
- # If you need to use them, add them to your project's devShell
- clangd = noPackage;
- gopls = noPackage;
- zls = noPackage;
+ basedpyright.rootDir = # lua
+ ''
+ function()
+ return vim.fs.root(0, {'flake.nix', '.git', '.jj', 'pyproject.toml', 'setup.py'})
+ end
+ '';
+ bashls.package = lib.mkDefault pkgs.bash-language-server;
+ # Adds ~2 GiB, install in a devShell instead
+ clangd.package = lib.mkDefault null;
+ # zls & other zig tools are big, install in a devShell instead
+ zls.package = lib.mkDefault null;
};
};
lspkind = {
@@ -84,26 +81,25 @@ in
(lib.mkIf (!cfg.dev.bundleGrammars) { plugins.treesitter.grammarPackages = [ ]; })
# Remove tools for building gramars when bundling them
(lib.mkIf cfg.dev.bundleGrammars {
- dependencies = {
- gcc.enable = false;
- nodejs.enable = false;
- tree-sitter.enable = false;
+ plugins.treesitter = {
+ gccPackage = null;
+ nodejsPackage = null;
+ treesitterPackage = null;
};
})
# Configure Formatters
{
- extraPackages = [ pkgs.luajitPackages.jsregexp ];
+ extraPackages = [
+ pkgs.luajitPackages.jsregexp
+ pkgs.shfmt
+ pkgs.stylua
+ pkgs.taplo
+ pkgs.yamlfmt
+ ];
plugins.conform-nvim = {
enable = true;
settings = {
- formatters = {
- fish.command = lib.getExe' pkgs.fish "fish_indent";
- nixfmt.command = lib.getExe pkgs.nixfmt-rfc-style;
- shfmt.command = lib.getExe pkgs.shfmt;
- stylua.command = lib.getExe pkgs.stylua;
- taplo.command = lib.getExe pkgs.taplo;
- yamlfmt.command = lib.getExe pkgs.yamlfmt;
- };
+ formatters.nixfmt.command = "${lib.getExe pkgs.nixfmt-rfc-style}";
formatters_by_ft = {
"_" = [ "trim_whitespace" ];
c = [ "clang_format" ];
@@ -115,24 +111,23 @@ in
toml = [ "taplo" ];
yaml = [ "yamlfmt" ];
zig = [ "zigfmt" ];
- fish = [ "fish_indent" ];
};
};
};
}
# Configure Linters
{
+ extraPackages = [
+ pkgs.dash
+ pkgs.statix
+ ];
plugins.lint = {
enable = true;
- linters = {
- dash.command = lib.getExe pkgs.dash;
- statix.command = lib.getExe pkgs.statix;
- # chktex = lib.getExe pkgs.chktex; # Not in use
- };
lintersByFt = {
# latex = [ "chktex" ]; # Not in use
nix = [ "statix" ];
sh = [ "dash" ];
+ zsh = [ "zsh" ];
};
};
}
@@ -162,9 +157,17 @@ in
}
# Rust plugins
{
- plugins.rustaceanvim.enable = true;
- # install through rustup
- dependencies.rust-analyzer.enable = false;
+ plugins = {
+ bacon = {
+ enable = true;
+ settings.quickfix.enabled = true;
+ };
+ rustaceanvim = {
+ enable = true;
+ # Install through rustup
+ rustAnalyzerPackage = null;
+ };
+ };
}
# Other plugins
{
@@ -176,7 +179,6 @@ in
mode = "virtualtext";
};
};
- hunk.enable = true;
otter.enable = true;
};
}
diff --git a/nvim/extraPlugins/default.nix b/nvim/extraPlugins/default.nix
new file mode 100644
index 0000000..87e972c
--- /dev/null
+++ b/nvim/extraPlugins/default.nix
@@ -0,0 +1,11 @@
+{ pkgs }:
+let
+ overlay = pkgs.callPackage ./generated.nix {
+ inherit (pkgs.vimUtils) buildVimPlugin buildNeovimPlugin;
+ };
+ plugins = overlay pkgs pkgs;
+in
+{
+ inherit overlay;
+ inherit (plugins) nvim-silicon;
+}
diff --git a/modules/nixvim/extraPlugins/generated.nix b/nvim/extraPlugins/generated.nix
similarity index 72%
rename from modules/nixvim/extraPlugins/generated.nix
rename to nvim/extraPlugins/generated.nix
index f0a2fcf..e4d204b 100644
--- a/modules/nixvim/extraPlugins/generated.nix
+++ b/nvim/extraPlugins/generated.nix
@@ -10,12 +10,12 @@
final: prev: {
nvim-silicon = buildVimPlugin {
pname = "nvim-silicon";
- version = "2025-01-09";
+ version = "2024-08-31";
src = fetchFromGitHub {
owner = "michaelrommel";
repo = "nvim-silicon";
- rev = "7f66bda8f60c97a5bf4b37e5b8acb0e829ae3c32";
- sha256 = "1zk6lgghvdcys20cqvh2g1kjf661q1w97niq5nx1zz4yppy2f9jy";
+ rev = "9fe6001dc8cad4d9c53bcfc8649e3dc76ffa169c";
+ sha256 = "1qczi06yndkr2pmwidlkgmk0395x189sznvscn4fnr96jx58j5yl";
};
meta.homepage = "https://github.com/michaelrommel/nvim-silicon/";
};
diff --git a/modules/nixvim/extraPlugins/plugins b/nvim/extraPlugins/plugins
similarity index 100%
rename from modules/nixvim/extraPlugins/plugins
rename to nvim/extraPlugins/plugins
diff --git a/modules/nixvim/mappings.nix b/nvim/mappings.nix
similarity index 100%
rename from modules/nixvim/mappings.nix
rename to nvim/mappings.nix
diff --git a/modules/nixvim/options.nix b/nvim/options.nix
similarity index 100%
rename from modules/nixvim/options.nix
rename to nvim/options.nix
diff --git a/nvim/plugins.nix b/nvim/plugins.nix
new file mode 100644
index 0000000..f843db6
--- /dev/null
+++ b/nvim/plugins.nix
@@ -0,0 +1,178 @@
+{ lib, helpers, ... }:
+let
+ inherit (helpers) mkRaw;
+in
+{
+ config.plugins = {
+ cmp = {
+ enable = true;
+ cmdline = {
+ "/" = {
+ mapping =
+ mkRaw
+ # lua
+ ''
+ cmp.mapping.preset.cmdline()
+ '';
+ sources = [
+ { name = "rg"; }
+ { name = "buffer"; }
+ ];
+ };
+ ":" = {
+ mapping =
+ mkRaw
+ # lua
+ ''
+ cmp.mapping.preset.cmdline()
+ '';
+ sources = [
+ { name = "path"; }
+ { name = "cmdline"; }
+ ];
+ };
+ };
+ settings = {
+ # Snippets
+ snippet.expand =
+ # lua
+ ''
+ function(args) require('luasnip').lsp_expand(args.body) end
+ '';
+ # Completion Sources
+ sources = [
+ {
+ name = "buffer";
+ groupIndex = 3;
+ }
+ {
+ name = "calc";
+ groupIndex = 2;
+ }
+ {
+ name = "conventionalcommits";
+ groupIndex = 1;
+ }
+ {
+ name = "crates";
+ groupIndex = 1;
+ }
+ {
+ name = "luasnip";
+ groupIndex = 1;
+ }
+ {
+ name = "nvim_lsp";
+ groupIndex = 1;
+ }
+ {
+ name = "nvim_lsp_document_symbol";
+ groupIndex = 1;
+ }
+ {
+ name = "nvim_lsp_signature_help";
+ groupIndex = 1;
+ }
+ {
+ name = "path";
+ groupIndex = 2;
+ }
+ {
+ name = "spell";
+ groupIndex = 2;
+ }
+ {
+ name = "treesitter";
+ groupIndex = 2;
+ }
+ ];
+ mapping =
+ mkRaw
+ # lua
+ ''
+ cmp.mapping.preset.insert({
+ [""] = function(fallback)
+ if cmp.visible() then
+ cmp.select_next_item()
+ elseif require("luasnip").expand_or_jumpable() then
+ require("luasnip").expand_or_jump()
+ elseif has_words_before() then
+ cmp.complete()
+ else
+ fallback()
+ end
+ end,
+ [""] = function(fallback)
+ if cmp.visible() then
+ cmp.select_prev_item()
+ elseif require("luasnip").jumpable(-1) then
+ require("luasnip").jump(-1)
+ else
+ fallback()
+ end
+ end,
+ [""] = cmp.mapping(function(fallback)
+ if require("luasnip").choice_active() then
+ require("luasnip").next_choice()
+ else
+ fallback()
+ end
+ end),
+ [""] = cmp.mapping.scroll_docs(-4),
+ [""] = cmp.mapping.scroll_docs(4),
+ [""] = cmp.mapping.complete { },
+ [""] = cmp.mapping.close(),
+ [""] = cmp.mapping.confirm { select = true },
+ })
+ '';
+ };
+ };
+ gitsigns.enable = true;
+ lualine = {
+ enable = true;
+ settings.options.theme = lib.mkForce "gruvbox";
+ };
+ luasnip = {
+ enable = true;
+ settings.update_events = "TextChanged,TextChangedI";
+ };
+ noice = {
+ enable = true;
+ settings = {
+ lsp.override = {
+ "vim.lsp.util.convert_input_to_markdown_lines" = true;
+ "vim.lsp.util.stylize_markdown" = true;
+ "cmp.entry.get_documentation" = true;
+ };
+ presets = {
+ # use a classic bottom cmdline for search
+ bottom_search = true;
+ # position the cmdline and popupmenu together
+ command_palette = false;
+ # long messages will be sent to a split
+ long_message_to_split = true;
+ # enables an input dialog for inc-rename.nvim
+ inc_rename = false;
+ # add a border to hover docs and signature help
+ lsp_doc_border = true;
+ };
+ };
+ };
+ notify = {
+ enable = true;
+ settings.background_colour = "#000000";
+ };
+ telescope = {
+ enable = true;
+ extensions = {
+ ui-select.enable = true;
+ fzy-native.enable = true;
+ };
+ };
+ trouble = {
+ enable = true;
+ settings.auto_close = true;
+ };
+ web-devicons.enable = true;
+ };
+}
diff --git a/modules/nixvim/standalone.nix b/nvim/standalone.nix
similarity index 90%
rename from modules/nixvim/standalone.nix
rename to nvim/standalone.nix
index f66d239..cec3117 100644
--- a/modules/nixvim/standalone.nix
+++ b/nvim/standalone.nix
@@ -7,12 +7,7 @@
let
cfg = config.jhome.nvim;
plugins = pkgs.vimPlugins;
- jExtraVimPlugins = pkgs.vimPlugins.extend (
- pkgs.callPackage ./extraPlugins/generated.nix {
- inherit (pkgs.vimUtils) buildVimPlugin;
- inherit (pkgs.neovimUtils) buildNeovimPlugin;
- }
- );
+ extraPlugins = import ./extraPlugins { inherit pkgs; };
in
{
imports = [
@@ -60,6 +55,7 @@ in
extraPlugins = [
plugins.nui-nvim
plugins.nvim-web-devicons
+ plugins.vim-jjdescription # FIXME: included since neovim nightly
];
extraPackages = [ pkgs.luajitPackages.jsregexp ];
extraConfigLuaPre =
@@ -83,7 +79,7 @@ in
}
# Big packages that are kinda unnecessary
(lib.mkIf (!cfg.reduceSize) {
- extraPlugins = [ jExtraVimPlugins.nvim-silicon ];
+ extraPlugins = [ extraPlugins.nvim-silicon ];
extraPackages = [ pkgs.silicon ];
extraConfigLua =
# lua
diff --git a/scripts/audiomenu/.envrc b/scripts/audiomenu/.envrc
deleted file mode 100644
index 729d54f..0000000
--- a/scripts/audiomenu/.envrc
+++ /dev/null
@@ -1,2 +0,0 @@
-source_up
-source .venv/bin/activate
diff --git a/scripts/audiomenu/.gitignore b/scripts/audiomenu/.gitignore
index 1d17dae..ea8c4bf 100644
--- a/scripts/audiomenu/.gitignore
+++ b/scripts/audiomenu/.gitignore
@@ -1 +1 @@
-.venv
+/target
diff --git a/scripts/audiomenu/.python-version b/scripts/audiomenu/.python-version
deleted file mode 100644
index 24ee5b1..0000000
--- a/scripts/audiomenu/.python-version
+++ /dev/null
@@ -1 +0,0 @@
-3.13
diff --git a/scripts/audiomenu/Cargo.lock b/scripts/audiomenu/Cargo.lock
new file mode 100644
index 0000000..4840d58
--- /dev/null
+++ b/scripts/audiomenu/Cargo.lock
@@ -0,0 +1,568 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "addr2line"
+version = "0.24.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
+dependencies = [
+ "gimli",
+]
+
+[[package]]
+name = "adler2"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
+
+[[package]]
+name = "anstream"
+version = "0.6.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
+dependencies = [
+ "anstyle",
+ "anstyle-parse",
+ "anstyle-query",
+ "anstyle-wincon",
+ "colorchoice",
+ "is_terminal_polyfill",
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle"
+version = "1.0.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
+
+[[package]]
+name = "anstyle-parse"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
+dependencies = [
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle-query"
+version = "1.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
+dependencies = [
+ "windows-sys",
+]
+
+[[package]]
+name = "anstyle-wincon"
+version = "3.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e"
+dependencies = [
+ "anstyle",
+ "once_cell",
+ "windows-sys",
+]
+
+[[package]]
+name = "audiomenu"
+version = "0.1.0"
+dependencies = [
+ "clap",
+ "duct",
+ "miette",
+ "serde",
+ "serde_json",
+]
+
+[[package]]
+name = "backtrace"
+version = "0.3.74"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a"
+dependencies = [
+ "addr2line",
+ "cfg-if",
+ "libc",
+ "miniz_oxide",
+ "object",
+ "rustc-demangle",
+ "windows-targets",
+]
+
+[[package]]
+name = "backtrace-ext"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "537beee3be4a18fb023b570f80e3ae28003db9167a751266b259926e25539d50"
+dependencies = [
+ "backtrace",
+]
+
+[[package]]
+name = "bitflags"
+version = "2.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "clap"
+version = "4.5.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6088f3ae8c3608d19260cd7445411865a485688711b78b5be70d78cd96136f83"
+dependencies = [
+ "clap_builder",
+ "clap_derive",
+]
+
+[[package]]
+name = "clap_builder"
+version = "4.5.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22a7ef7f676155edfb82daa97f99441f3ebf4a58d5e32f295a56259f1b6facc8"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "clap_lex",
+ "strsim",
+]
+
+[[package]]
+name = "clap_derive"
+version = "4.5.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "clap_lex"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
+
+[[package]]
+name = "colorchoice"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
+
+[[package]]
+name = "duct"
+version = "0.13.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e4ab5718d1224b63252cd0c6f74f6480f9ffeb117438a2e0f5cf6d9a4798929c"
+dependencies = [
+ "libc",
+ "once_cell",
+ "os_pipe",
+ "shared_child",
+]
+
+[[package]]
+name = "errno"
+version = "0.3.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d"
+dependencies = [
+ "libc",
+ "windows-sys",
+]
+
+[[package]]
+name = "gimli"
+version = "0.31.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
+
+[[package]]
+name = "heck"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
+
+[[package]]
+name = "is_ci"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45"
+
+[[package]]
+name = "is_terminal_polyfill"
+version = "1.70.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
+
+[[package]]
+name = "itoa"
+version = "1.0.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
+
+[[package]]
+name = "libc"
+version = "0.2.170"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828"
+
+[[package]]
+name = "linux-raw-sys"
+version = "0.9.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6db9c683daf087dc577b7506e9695b3d556a9f3849903fa28186283afd6809e9"
+
+[[package]]
+name = "memchr"
+version = "2.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
+
+[[package]]
+name = "miette"
+version = "7.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a955165f87b37fd1862df2a59547ac542c77ef6d17c666f619d1ad22dd89484"
+dependencies = [
+ "backtrace",
+ "backtrace-ext",
+ "cfg-if",
+ "miette-derive",
+ "owo-colors",
+ "supports-color",
+ "supports-hyperlinks",
+ "supports-unicode",
+ "terminal_size",
+ "textwrap",
+ "thiserror",
+ "unicode-width 0.1.14",
+]
+
+[[package]]
+name = "miette-derive"
+version = "7.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf45bf44ab49be92fd1227a3be6fc6f617f1a337c06af54981048574d8783147"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "miniz_oxide"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5"
+dependencies = [
+ "adler2",
+]
+
+[[package]]
+name = "object"
+version = "0.36.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.21.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cde51589ab56b20a6f686b2c68f7a0bd6add753d697abf720d63f8db3ab7b1ad"
+
+[[package]]
+name = "os_pipe"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5ffd2b0a5634335b135d5728d84c5e0fd726954b87111f7506a61c502280d982"
+dependencies = [
+ "libc",
+ "windows-sys",
+]
+
+[[package]]
+name = "owo-colors"
+version = "4.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1036865bb9422d3300cf723f657c2851d0e9ab12567854b1f4eba3d77decf564"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.94"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.39"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1f1914ce909e1658d9907913b4b91947430c7d9be598b15a1912935b8c04801"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rustc-demangle"
+version = "0.1.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
+
+[[package]]
+name = "rustix"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f7178faa4b75a30e269c71e61c353ce2748cf3d76f0c44c393f4e60abf49b825"
+dependencies = [
+ "bitflags",
+ "errno",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys",
+]
+
+[[package]]
+name = "ryu"
+version = "1.0.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
+
+[[package]]
+name = "serde"
+version = "1.0.219"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.219"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.140"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
+dependencies = [
+ "itoa",
+ "memchr",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "shared_child"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09fa9338aed9a1df411814a5b2252f7cd206c55ae9bf2fa763f8de84603aa60c"
+dependencies = [
+ "libc",
+ "windows-sys",
+]
+
+[[package]]
+name = "strsim"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
+
+[[package]]
+name = "supports-color"
+version = "3.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c64fc7232dd8d2e4ac5ce4ef302b1d81e0b80d055b9d77c7c4f51f6aa4c867d6"
+dependencies = [
+ "is_ci",
+]
+
+[[package]]
+name = "supports-hyperlinks"
+version = "3.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "804f44ed3c63152de6a9f90acbea1a110441de43006ea51bcce8f436196a288b"
+
+[[package]]
+name = "supports-unicode"
+version = "3.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b7401a30af6cb5818bb64852270bb722533397edcfc7344954a38f420819ece2"
+
+[[package]]
+name = "syn"
+version = "2.0.100"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "terminal_size"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "45c6481c4829e4cc63825e62c49186a34538b7b2750b73b266581ffb612fb5ed"
+dependencies = [
+ "rustix",
+ "windows-sys",
+]
+
+[[package]]
+name = "textwrap"
+version = "0.16.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c13547615a44dc9c452a8a534638acdf07120d4b6847c8178705da06306a3057"
+dependencies = [
+ "unicode-linebreak",
+ "unicode-width 0.2.0",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
+
+[[package]]
+name = "unicode-linebreak"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f"
+
+[[package]]
+name = "unicode-width"
+version = "0.1.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
+
+[[package]]
+name = "unicode-width"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd"
+
+[[package]]
+name = "utf8parse"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
+
+[[package]]
+name = "windows-sys"
+version = "0.59.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
diff --git a/scripts/audiomenu/Cargo.toml b/scripts/audiomenu/Cargo.toml
new file mode 100644
index 0000000..b469215
--- /dev/null
+++ b/scripts/audiomenu/Cargo.toml
@@ -0,0 +1,18 @@
+[package]
+name = "audiomenu"
+description = "fuzzel script to select the default audio device for pipewire+wireplumber"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+clap = { version = "4.5.23", features = ["derive", "env"] }
+duct = "0.13.7"
+miette = { version = "7.4.0", features = ["fancy"] }
+serde = { version = "1.0.215", features = ["derive"] }
+serde_json = "1.0.133"
+
+[profile.release]
+lto = true
+opt-level = 's'
+panic = "abort"
+strip = true
diff --git a/scripts/audiomenu/README.md b/scripts/audiomenu/README.md
deleted file mode 100644
index e69de29..0000000
diff --git a/scripts/audiomenu/audiomenu.py b/scripts/audiomenu/audiomenu.py
deleted file mode 100644
index 88fe671..0000000
--- a/scripts/audiomenu/audiomenu.py
+++ /dev/null
@@ -1,238 +0,0 @@
-# pyright: strict, reportAny=false
-from dataclasses import dataclass
-import json
-import subprocess
-from typing import Self
-import typing
-import click
-
-
-def expect[T](type_: type[T], value: object) -> T:
- if not isinstance(value, type_):
- raise ValueError(
- f"expected value to be of type {type_} but was of type {type(value)}"
- )
- return value
-
-
-@dataclass(slots=True)
-class PWNodeProps:
- object_id: int
- node_description: str
- node_name: str
- media_class: str
-
- @classmethod
- def from_json(cls, data: dict[str, object]) -> Self:
- return cls(
- object_id=expect(int, data["object.id"]),
- node_description=expect(str, data.get("node.description", "(unknown)")),
- node_name=expect(str, data["node.name"]),
- media_class=expect(str, data.get("media.class", "(unknown)")),
- )
-
-
-@dataclass(slots=True)
-class PWNodeInfo:
- props: PWNodeProps
-
- @classmethod
- def from_json(cls, data: dict[str, object]) -> Self:
- props = typing.cast(dict[str, object], expect(dict, data["props"]))
- return cls(PWNodeProps.from_json(props))
-
-
-@dataclass(slots=True)
-class PWNode:
- node_type: str
- info: PWNodeInfo | None
-
- @classmethod
- def from_json(cls, data: dict[str, object]) -> Self:
- info = data.get("info", None)
- if info is not None:
- info = PWNodeInfo.from_json(
- typing.cast(dict[str, object], expect(dict, info))
- )
- return cls(node_type=expect(str, data["type"]), info=info)
-
-
-@dataclass(slots=True)
-class AudioDevice:
- id: int
- name: str
- volume: float
- muted: bool
- default: bool
-
- @staticmethod
- def get_volume(id: int | str) -> tuple[float, bool]:
- wpctl_output = subprocess.run(
- ["wpctl", "get-volume", str(id)],
- encoding="UTF-8",
- check=True,
- capture_output=True,
- )
- match wpctl_output.stdout.strip().split(sep=" "):
- case ["Volume:", value]:
- return (float(value), False)
- case ["Volume:", value, "[MUTED]"]:
- return (float(value), True)
- case _:
- raise ValueError(f"Unexpected wpctl output: {wpctl_output.stdout}")
-
- @classmethod
- def from_pw_node(cls, node: PWNode, default: str) -> Self:
- if node.info is None:
- raise ValueError(f"Node is not a valid audio device {node}")
-
- id = node.info.props.object_id
- volume, muted = cls.get_volume(id)
-
- return cls(
- id=id,
- name=node.info.props.node_description,
- volume=volume,
- muted=muted,
- default=node.info.props.node_name == default,
- )
-
- def menu_item(self) -> str:
- id = f"id={self.id:<3}"
-
- if self.default:
- id = f"[{id}]"
- else:
- id = f" {id} "
-
- if self.muted:
- return f"{id} {self.volume:>4.0%} [MUTED] {self.name}"
- else:
- return f"{id} {self.volume:>4.0%} {self.name}"
-
-
-def get_nodes(data: list[dict[str, object]]) -> list[PWNode]:
- def is_audio_node(node: object) -> bool:
- if not isinstance(node, dict):
- return False
-
- node = typing.cast(dict[str, object], node)
- if node["type"] != "PipeWire:Interface:Node":
- return False
- info = node.get("info", None)
- if info is None or not isinstance(info, dict):
- return False
- info = typing.cast(dict[str, object], info)
- props = info.get("props", None)
- if props is None or not isinstance(props, dict):
- return False
- props = typing.cast(dict[str, object], props)
- if (media_class := props.get("media.class", None)) is not None:
- return isinstance(media_class, str) and media_class.startswith("Audio")
- return False
-
- return [
- PWNode.from_json(typing.cast(dict[str, object], expect(dict, node)))
- for node in data
- if is_audio_node(node)
- ]
-
-
-def pw_dump() -> list[dict[str, object]]:
- dump_output = subprocess.run(
- ["pw-dump"], encoding="UTF-8", check=True, capture_output=True
- )
- data = json.loads(dump_output.stdout)
- return typing.cast(list[dict[str, object]], expect(list, data))
-
-
-def get_defaults_metadata(data: list[dict[str, object]]) -> list[dict[str, object]]:
- return typing.cast(
- list[dict[str, object]],
- expect(
- list,
- next(
- node
- for node in data
- if node["type"] == "PipeWire:Interface:Metadata"
- and expect(dict, node["props"])["metadata.name"] == "default"
- )["metadata"],
- ),
- )
-
-
-def get_sinks() -> list[AudioDevice]:
- data = pw_dump()
- default = next(
- typing.cast(dict[str, str], expect(dict, data["value"]))["name"]
- for data in get_defaults_metadata(data)
- if data["key"] == "default.audio.sink"
- )
- return [
- AudioDevice.from_pw_node(node, default)
- for node in get_nodes(data)
- if node.info is not None and node.info.props.media_class == "Audio/Sink"
- ]
-
-
-def get_sources() -> list[AudioDevice]:
- data = pw_dump()
- default = next(
- typing.cast(dict[str, str], expect(dict, data["value"]))["name"]
- for data in get_defaults_metadata(data)
- if data["key"] == "default.audio.source"
- )
- return [
- AudioDevice.from_pw_node(node, default)
- for node in get_nodes(data)
- if node.info is not None and node.info.props.media_class == "Audio/Source"
- ]
-
-
-@click.group(name="audiomenu")
-def main() -> None:
- pass
-
-
-def select(options: list[str], prompt: str) -> int | None:
- menu_output = subprocess.run(
- ["fuzzel", "--dmenu", f"--prompt={prompt}"],
- input="\n".join(options),
- encoding="UTF-8",
- capture_output=True,
- )
- if menu_output.returncode == 2:
- return None
- menu_output.check_returncode()
- selected = menu_output.stdout.rstrip()
- return options.index(selected)
-
-
-@main.command()
-def select_sink() -> None:
- devices = get_sinks()
- selected = select([device.menu_item() for device in devices], prompt="Select Sink>")
- if selected is None:
- click.echo("No sink selected")
- return
-
- device = devices[selected]
- _ = subprocess.run(["wpctl", "set-default", str(device.id)], check=True)
-
-
-@main.command()
-def select_source() -> None:
- devices = get_sources()
- selected = select(
- [device.menu_item() for device in devices], prompt="Select Source>"
- )
- if selected is None:
- click.echo("No source selected")
- return
-
- device = devices[selected]
- _ = subprocess.run(["wpctl", "set-default", str(device.id)], check=True)
-
-
-if __name__ == "__main__":
- main()
diff --git a/scripts/audiomenu/package.nix b/scripts/audiomenu/package.nix
index 45a5a3b..88636da 100644
--- a/scripts/audiomenu/package.nix
+++ b/scripts/audiomenu/package.nix
@@ -1,9 +1,40 @@
-{ writers, python3Packages }:
-writers.writePython3Bin "audiomenu" {
- libraries = [ python3Packages.click ];
-
- flakeIgnore = [
- "E501" # line too long, but I like my code well documented
- "W503" # line break before binary operator, ruff does this, I trust it
- ];
-} ./audiomenu.py
+{ lib, rustPlatform }:
+let
+ cargoToml = builtins.fromTOML (builtins.readFile ./Cargo.toml);
+ inherit (cargoToml.package) name version description;
+ pname = name;
+ src = lib.cleanSourceWith {
+ src = ./.;
+ name = "${pname}-source";
+ # Adapted from
+ # no need to pull in crane for just this
+ filter =
+ orig_path: type:
+ let
+ path = toString orig_path;
+ base = baseNameOf path;
+ parentDir = baseNameOf (dirOf path);
+ matchesSuffix = lib.any (suffix: lib.hasSuffix suffix base) [
+ # Rust sources
+ ".rs"
+ # TOML files are often used to configure cargo based tools (e.g. .cargo/config.toml)
+ ".toml"
+ ];
+ isCargoLock = base == "Cargo.lock";
+ # .cargo/config.toml is captured above
+ isOldStyleCargoConfig = parentDir == ".cargo" && base == "config";
+ in
+ type == "directory" || matchesSuffix || isCargoLock || isOldStyleCargoConfig;
+ };
+in
+rustPlatform.buildRustPackage {
+ inherit pname version src;
+ cargoLock.lockFile = ./Cargo.lock;
+ useNextest = true;
+ meta = {
+ inherit description;
+ license = lib.licenses.mit;
+ homepage = "https://github.com/jalil-salame/configuration.nix";
+ mainProgram = name;
+ };
+}
diff --git a/scripts/audiomenu/pyproject.toml b/scripts/audiomenu/pyproject.toml
deleted file mode 100644
index 6d992a3..0000000
--- a/scripts/audiomenu/pyproject.toml
+++ /dev/null
@@ -1,9 +0,0 @@
-[project]
-name = "audiomenu"
-version = "0.1.0"
-description = "fuzzel script to select the default audio device for pipewire+wireplumber"
-readme = "README.md"
-requires-python = ">=3.12"
-dependencies = [
- "click>=8.1.7",
-]
diff --git a/scripts/audiomenu/src/main.rs b/scripts/audiomenu/src/main.rs
new file mode 100644
index 0000000..a542fd4
--- /dev/null
+++ b/scripts/audiomenu/src/main.rs
@@ -0,0 +1,231 @@
+use std::{
+ fmt::{Display, Write as _},
+ io::{Read, Write as _},
+ process::{Command, Stdio},
+};
+
+use clap::Parser;
+use duct::cmd;
+use miette::{bail, Context, IntoDiagnostic, Result};
+use serde::Deserialize;
+
+fn main() -> Result<()> {
+ miette::set_panic_hook();
+ Opts::parse().run()
+}
+
+/// fuzzel script to select the default audio device for pipewire+wireplumber
+#[derive(Debug, Parser)]
+struct Opts {
+ #[clap(subcommand)]
+ cmd: Cmd,
+}
+
+impl Opts {
+ fn run(self) -> Result<()> {
+ self.cmd.run()
+ }
+}
+
+#[derive(Debug, clap::Subcommand)]
+enum Cmd {
+ /// Select audio sink (speakers/headphones)
+ SelectSink,
+ /// Select audio source (microphone)
+ SelectSource,
+}
+
+impl Cmd {
+ fn run(self) -> Result<()> {
+ let id = match self {
+ Cmd::SelectSink => {
+ let devices = get_sinks().wrap_err("failed to get sinks")?;
+ let selected = select(
+ devices.iter().map(|dev| dev.name.as_ref()),
+ Some("Select input>"),
+ )
+ .wrap_err("failed to select a default sink")?;
+ if selected.is_empty() {
+ eprintln!("did not select a device");
+ return Ok(());
+ }
+ let Some(dev) = devices.into_iter().find(|dev| dev.name == selected) else {
+ bail!("couldn't find a device matching `{selected}`");
+ };
+ dev.id
+ }
+ Cmd::SelectSource => {
+ let devices = get_sources().wrap_err("failed to get sinks")?;
+ let selected = select(
+ devices.iter().map(|dev| dev.name.as_ref()),
+ Some("Select output>"),
+ )
+ .wrap_err("failed to select a default source")?;
+ if selected.is_empty() {
+ eprintln!("did not select a device");
+ return Ok(());
+ }
+ let Some(dev) = devices.into_iter().find(|dev| dev.name == selected) else {
+ bail!("couldn't find a device matching `{selected}`");
+ };
+ dev.id
+ }
+ };
+ cmd!("wpctl", "set-default", id.to_string())
+ .run()
+ .map(drop)
+ .into_diagnostic()
+ .wrap_err("failed to set default input")
+ }
+}
+
+#[derive(Debug, Deserialize)]
+struct PWNode {
+ #[serde(rename = "type")]
+ node_type: Box,
+ #[serde(default)]
+ info: PWNodeInfo,
+ // json ignores the rest of the fields by default
+}
+
+#[derive(Debug, Deserialize, Default)]
+struct PWNodeInfo {
+ props: PWNodeProps,
+ // json ignores the rest of the fields by default
+}
+
+#[derive(Debug, Deserialize, Default)]
+struct PWNodeProps {
+ #[serde(rename = "object.id")]
+ object_id: u32,
+ #[serde(rename = "node.description", default)]
+ node_description: Box,
+ #[serde(rename = "media.class", default)]
+ media_class: Box,
+ // json ignores the rest of the fields by default
+}
+
+struct AudioDevice {
+ id: u32,
+ name: Box,
+ _side: S,
+}
+
+/// Output (e.g. speakers)
+struct AudioSink;
+
+/// Input (e.g. microphone)
+struct AudioSource;
+
+fn get_sinks() -> Result>> {
+ get_devices()
+}
+
+fn get_sources() -> Result>> {
+ get_devices()
+}
+
+fn get_devices() -> Result>>
+where
+ AudioDevice: TryFrom,
+{
+ Ok(get_nodes()?
+ .into_iter()
+ .filter_map(|node| AudioDevice::::try_from(node).ok())
+ .collect())
+}
+
+impl TryFrom for AudioDevice {
+ type Error = miette::Report;
+
+ fn try_from(value: PWNode) -> std::result::Result {
+ if value.node_type.as_ref() != "PipeWire:Interface:Node" {
+ bail!(
+ "invalid type: `{}`, expected `PipeWire:Interface:Node`",
+ value.node_type
+ )
+ }
+ let class = value.info.props.media_class;
+ match class.as_ref() {
+ "Audio/Source" => Ok(Self {
+ id: value.info.props.object_id,
+ name: value.info.props.node_description,
+ _side: AudioSource,
+ }),
+ _ => bail!("invalid media.class: `{class}`, expected `Audio/Source`"),
+ }
+ }
+}
+
+impl TryFrom for AudioDevice {
+ type Error = miette::Report;
+
+ fn try_from(value: PWNode) -> std::result::Result {
+ if value.node_type.as_ref() != "PipeWire:Interface:Node" {
+ bail!(
+ "invalid type: `{}`, expected `PipeWire:Interface:Node`",
+ value.node_type
+ )
+ }
+ let class = value.info.props.media_class;
+ match class.as_ref() {
+ "Audio/Sink" => Ok(Self {
+ id: value.info.props.object_id,
+ name: value.info.props.node_description,
+ _side: AudioSink,
+ }),
+ _ => bail!("invalid media.class: `{class}`, expected `Audio/Sink`"),
+ }
+ }
+}
+
+fn get_nodes() -> Result> {
+ let dump = cmd!("pw-dump")
+ .read()
+ .into_diagnostic()
+ .wrap_err("failed to get devices with pw-dump")?;
+ serde_json::from_str(&dump)
+ .into_diagnostic()
+ .wrap_err("failed to parse pw-dump output")
+}
+
+fn select(options: It, prompt: Option<&str>) -> Result>
+where
+ T: Display,
+ It: IntoIterator- ,
+{
+ let append_line = |mut s: String, it| {
+ writeln!(s, "{it}").unwrap();
+ s
+ };
+ let options = options.into_iter().fold(String::new(), append_line);
+ let mut menu = Command::new("fuzzel");
+ menu.arg("--dmenu");
+ if let Some(prompt) = prompt {
+ menu.arg(format!("--prompt={prompt}"));
+ }
+ Ok(pipe_to_stdin_and_return_stdout(&mut menu, options)?
+ .trim()
+ .into())
+}
+
+fn pipe_to_stdin_and_return_stdout(cmd: &mut Command, data: impl Display) -> Result {
+ let mut child = cmd
+ .stdin(Stdio::piped())
+ .stdout(Stdio::piped())
+ .spawn()
+ .into_diagnostic()
+ .wrap_err_with(|| format!("failed to run {cmd:?}"))?;
+ let mut stdin = child.stdin.take().expect("stdin not piped");
+ write!(stdin, "{data}")
+ .into_diagnostic()
+ .wrap_err("failed to send data to process' stdin")?;
+ drop(stdin);
+ let mut stdout = child.stdout.take().expect("stdout not piped");
+ let mut buf = String::new();
+ stdout
+ .read_to_string(&mut buf)
+ .into_diagnostic()
+ .wrap_err("failed to retrieve output from process")?;
+ Ok(buf)
+}
diff --git a/scripts/default.nix b/scripts/default.nix
index 5cde95c..23ec010 100644
--- a/scripts/default.nix
+++ b/scripts/default.nix
@@ -1,17 +1,23 @@
+# Autodetects files with a package.nix and calls `callPackage` on them.
+#
+# Will add a package .#dirname to the flake if it finds a ./dirname/package.nix file.
let
- packages = pkgs: {
- jpassmenu = pkgs.callPackage ./jpassmenu/package.nix { };
- audiomenu = pkgs.callPackage ./audiomenu/package.nix { };
+ files = builtins.readDir ./.;
+ isPackage = path: type: (type == "directory") && (builtins.readDir path) ? "package.nix";
+ toPackage = name: pkgs: {
+ inherit name;
+ value = pkgs.callPackage (./. + "/${name}/package.nix") { };
};
+ # call pkgs.callPackage on all ./*/package.nix
+ makePackage =
+ pkgs: name:
+ let
+ type = files.${name};
+ path = ./. + "/${name}";
+ package = toPackage name pkgs;
+ in
+ # if it is a package then return a package otherwise return no package c:
+ if isPackage path type then [ package ] else [ ];
in
-{
- # Add scripts to overlay
- flake.overlays.scripts = _final: packages;
-
- # Add scripts to packages
- perSystem =
- { pkgs, ... }:
- {
- packages = packages pkgs;
- };
-}
+# we have lib.filterMapAttrs at home
+pkgs: builtins.listToAttrs (builtins.concatMap (makePackage pkgs) (builtins.attrNames files))
diff --git a/scripts/jpassmenu/.envrc b/scripts/jpassmenu/.envrc
deleted file mode 100644
index 729d54f..0000000
--- a/scripts/jpassmenu/.envrc
+++ /dev/null
@@ -1,2 +0,0 @@
-source_up
-source .venv/bin/activate
diff --git a/scripts/jpassmenu/.gitignore b/scripts/jpassmenu/.gitignore
new file mode 100644
index 0000000..ea8c4bf
--- /dev/null
+++ b/scripts/jpassmenu/.gitignore
@@ -0,0 +1 @@
+/target
diff --git a/scripts/jpassmenu/.python-version b/scripts/jpassmenu/.python-version
deleted file mode 100644
index 24ee5b1..0000000
--- a/scripts/jpassmenu/.python-version
+++ /dev/null
@@ -1 +0,0 @@
-3.13
diff --git a/scripts/jpassmenu/Cargo.lock b/scripts/jpassmenu/Cargo.lock
new file mode 100644
index 0000000..9e29ec2
--- /dev/null
+++ b/scripts/jpassmenu/Cargo.lock
@@ -0,0 +1,743 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "addr2line"
+version = "0.24.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
+dependencies = [
+ "gimli",
+]
+
+[[package]]
+name = "adler2"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
+
+[[package]]
+name = "aho-corasick"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "anstream"
+version = "0.6.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
+dependencies = [
+ "anstyle",
+ "anstyle-parse",
+ "anstyle-query",
+ "anstyle-wincon",
+ "colorchoice",
+ "is_terminal_polyfill",
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle"
+version = "1.0.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
+
+[[package]]
+name = "anstyle-parse"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
+dependencies = [
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle-query"
+version = "1.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
+dependencies = [
+ "windows-sys",
+]
+
+[[package]]
+name = "anstyle-wincon"
+version = "3.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e"
+dependencies = [
+ "anstyle",
+ "once_cell",
+ "windows-sys",
+]
+
+[[package]]
+name = "backtrace"
+version = "0.3.74"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a"
+dependencies = [
+ "addr2line",
+ "cfg-if",
+ "libc",
+ "miniz_oxide",
+ "object",
+ "rustc-demangle",
+ "windows-targets",
+]
+
+[[package]]
+name = "backtrace-ext"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "537beee3be4a18fb023b570f80e3ae28003db9167a751266b259926e25539d50"
+dependencies = [
+ "backtrace",
+]
+
+[[package]]
+name = "bitflags"
+version = "2.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
+
+[[package]]
+name = "bstr"
+version = "1.11.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "531a9155a481e2ee699d4f98f43c0ca4ff8ee1bfd55c31e9e98fb29d2b176fe0"
+dependencies = [
+ "memchr",
+ "serde",
+]
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "clap"
+version = "4.5.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6088f3ae8c3608d19260cd7445411865a485688711b78b5be70d78cd96136f83"
+dependencies = [
+ "clap_builder",
+ "clap_derive",
+]
+
+[[package]]
+name = "clap_builder"
+version = "4.5.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22a7ef7f676155edfb82daa97f99441f3ebf4a58d5e32f295a56259f1b6facc8"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "clap_lex",
+ "strsim",
+]
+
+[[package]]
+name = "clap_derive"
+version = "4.5.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "clap_lex"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
+
+[[package]]
+name = "colorchoice"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
+
+[[package]]
+name = "crossbeam-deque"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
+dependencies = [
+ "crossbeam-epoch",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-epoch"
+version = "0.9.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
+dependencies = [
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-utils"
+version = "0.8.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
+
+[[package]]
+name = "duct"
+version = "0.13.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e4ab5718d1224b63252cd0c6f74f6480f9ffeb117438a2e0f5cf6d9a4798929c"
+dependencies = [
+ "libc",
+ "once_cell",
+ "os_pipe",
+ "shared_child",
+]
+
+[[package]]
+name = "env_filter"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0"
+dependencies = [
+ "log",
+ "regex",
+]
+
+[[package]]
+name = "env_logger"
+version = "0.11.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3716d7a920fb4fac5d84e9d4bce8ceb321e9414b4409da61b07b75c1e3d0697"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "env_filter",
+ "jiff",
+ "log",
+]
+
+[[package]]
+name = "errno"
+version = "0.3.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d"
+dependencies = [
+ "libc",
+ "windows-sys",
+]
+
+[[package]]
+name = "gimli"
+version = "0.31.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
+
+[[package]]
+name = "globset"
+version = "0.4.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "54a1028dfc5f5df5da8a56a73e6c153c9a9708ec57232470703592a3f18e49f5"
+dependencies = [
+ "aho-corasick",
+ "bstr",
+ "log",
+ "regex-automata",
+ "regex-syntax",
+]
+
+[[package]]
+name = "heck"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
+
+[[package]]
+name = "ignore"
+version = "0.4.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d89fd380afde86567dfba715db065673989d6253f42b88179abd3eae47bda4b"
+dependencies = [
+ "crossbeam-deque",
+ "globset",
+ "log",
+ "memchr",
+ "regex-automata",
+ "same-file",
+ "walkdir",
+ "winapi-util",
+]
+
+[[package]]
+name = "is_ci"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45"
+
+[[package]]
+name = "is_terminal_polyfill"
+version = "1.70.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
+
+[[package]]
+name = "jiff"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d699bc6dfc879fb1bf9bdff0d4c56f0884fc6f0d0eb0fba397a6d00cd9a6b85e"
+dependencies = [
+ "jiff-static",
+ "log",
+ "portable-atomic",
+ "portable-atomic-util",
+ "serde",
+]
+
+[[package]]
+name = "jiff-static"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8d16e75759ee0aa64c57a56acbf43916987b20c77373cb7e808979e02b93c9f9"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "jpassmenu"
+version = "0.1.0"
+dependencies = [
+ "clap",
+ "duct",
+ "env_logger",
+ "ignore",
+ "log",
+ "miette",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.170"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828"
+
+[[package]]
+name = "linux-raw-sys"
+version = "0.9.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6db9c683daf087dc577b7506e9695b3d556a9f3849903fa28186283afd6809e9"
+
+[[package]]
+name = "log"
+version = "0.4.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e"
+
+[[package]]
+name = "memchr"
+version = "2.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
+
+[[package]]
+name = "miette"
+version = "7.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a955165f87b37fd1862df2a59547ac542c77ef6d17c666f619d1ad22dd89484"
+dependencies = [
+ "backtrace",
+ "backtrace-ext",
+ "cfg-if",
+ "miette-derive",
+ "owo-colors",
+ "supports-color",
+ "supports-hyperlinks",
+ "supports-unicode",
+ "terminal_size",
+ "textwrap",
+ "thiserror",
+ "unicode-width 0.1.14",
+]
+
+[[package]]
+name = "miette-derive"
+version = "7.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf45bf44ab49be92fd1227a3be6fc6f617f1a337c06af54981048574d8783147"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "miniz_oxide"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5"
+dependencies = [
+ "adler2",
+]
+
+[[package]]
+name = "object"
+version = "0.36.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.21.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cde51589ab56b20a6f686b2c68f7a0bd6add753d697abf720d63f8db3ab7b1ad"
+
+[[package]]
+name = "os_pipe"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5ffd2b0a5634335b135d5728d84c5e0fd726954b87111f7506a61c502280d982"
+dependencies = [
+ "libc",
+ "windows-sys",
+]
+
+[[package]]
+name = "owo-colors"
+version = "4.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1036865bb9422d3300cf723f657c2851d0e9ab12567854b1f4eba3d77decf564"
+
+[[package]]
+name = "portable-atomic"
+version = "1.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e"
+
+[[package]]
+name = "portable-atomic-util"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507"
+dependencies = [
+ "portable-atomic",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.94"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.39"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1f1914ce909e1658d9907913b4b91947430c7d9be598b15a1912935b8c04801"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "regex"
+version = "1.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-automata",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
+
+[[package]]
+name = "rustc-demangle"
+version = "0.1.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
+
+[[package]]
+name = "rustix"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f7178faa4b75a30e269c71e61c353ce2748cf3d76f0c44c393f4e60abf49b825"
+dependencies = [
+ "bitflags",
+ "errno",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys",
+]
+
+[[package]]
+name = "same-file"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
+name = "serde"
+version = "1.0.219"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.219"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "shared_child"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09fa9338aed9a1df411814a5b2252f7cd206c55ae9bf2fa763f8de84603aa60c"
+dependencies = [
+ "libc",
+ "windows-sys",
+]
+
+[[package]]
+name = "strsim"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
+
+[[package]]
+name = "supports-color"
+version = "3.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c64fc7232dd8d2e4ac5ce4ef302b1d81e0b80d055b9d77c7c4f51f6aa4c867d6"
+dependencies = [
+ "is_ci",
+]
+
+[[package]]
+name = "supports-hyperlinks"
+version = "3.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "804f44ed3c63152de6a9f90acbea1a110441de43006ea51bcce8f436196a288b"
+
+[[package]]
+name = "supports-unicode"
+version = "3.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b7401a30af6cb5818bb64852270bb722533397edcfc7344954a38f420819ece2"
+
+[[package]]
+name = "syn"
+version = "2.0.100"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "terminal_size"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "45c6481c4829e4cc63825e62c49186a34538b7b2750b73b266581ffb612fb5ed"
+dependencies = [
+ "rustix",
+ "windows-sys",
+]
+
+[[package]]
+name = "textwrap"
+version = "0.16.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c13547615a44dc9c452a8a534638acdf07120d4b6847c8178705da06306a3057"
+dependencies = [
+ "unicode-linebreak",
+ "unicode-width 0.2.0",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
+
+[[package]]
+name = "unicode-linebreak"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f"
+
+[[package]]
+name = "unicode-width"
+version = "0.1.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
+
+[[package]]
+name = "unicode-width"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd"
+
+[[package]]
+name = "utf8parse"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
+
+[[package]]
+name = "walkdir"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
+dependencies = [
+ "same-file",
+ "winapi-util",
+]
+
+[[package]]
+name = "winapi-util"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
+dependencies = [
+ "windows-sys",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.59.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
diff --git a/scripts/jpassmenu/Cargo.toml b/scripts/jpassmenu/Cargo.toml
new file mode 100644
index 0000000..7ffa4ba
--- /dev/null
+++ b/scripts/jpassmenu/Cargo.toml
@@ -0,0 +1,19 @@
+[package]
+name = "jpassmenu"
+description = "A simple program that uses dmenu compatible menu to select a password to type/copy"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+clap = { version = "4.5.23", features = ["derive", "env"] }
+duct = "0.13.7"
+env_logger = "0.11.5"
+ignore = "0.4.23"
+log = "0.4.22"
+miette = { version = "7.4.0", features = ["fancy"] }
+
+[profile.release]
+lto = true
+opt-level = "s"
+panic = "abort"
+strip = true
diff --git a/scripts/jpassmenu/README.md b/scripts/jpassmenu/README.md
deleted file mode 100644
index 2c28fb8..0000000
--- a/scripts/jpassmenu/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# jpassmenu
-
-My own implementation of the `passmenu` `dmenu` script, this one uses `fuzzel` by default and types passwords with `ydotool`.
diff --git a/scripts/jpassmenu/jpassmenu.py b/scripts/jpassmenu/jpassmenu.py
deleted file mode 100644
index f446412..0000000
--- a/scripts/jpassmenu/jpassmenu.py
+++ /dev/null
@@ -1,111 +0,0 @@
-from os import environ
-from pathlib import Path
-import subprocess
-import click
-
-
-def select(options: list[str]) -> int | None:
- menu_output = subprocess.run(
- ["fuzzel", "--dmenu"],
- input="\n".join(options),
- encoding="UTF-8",
- capture_output=True,
- )
- if menu_output.returncode == 2:
- return None
- menu_output.check_returncode()
- selected = menu_output.stdout.rstrip()
- return options.index(selected)
-
-
-@click.command(
- "jpassmenu", context_settings={"show_default": True, "max_content_width": 120}
-)
-@click.option(
- "--type",
- "typeit",
- help="Type the password using ydotool instead of copying it to the clipboard",
-)
-@click.option(
- "--store-dir",
- type=click.Path(exists=True, file_okay=False, path_type=Path),
- envvar="PASSWORD_STORE_DIR",
- default=Path("~/.password-store"),
-)
-@click.option(
- "--pass-bin",
- default="pass",
- help="Path to the pass binary\n\nNeeds to support `pass show` and `pass show --clip`",
-)
-@click.option(
- "--menu-bin", default="fuzzel", help="Path to the dmenu compatible menu binary"
-)
-@click.argument("menu_args", nargs=-1)
-def main(
- typeit: bool, store_dir: Path, pass_bin: str, menu_bin: str, menu_args: list[str]
-) -> None:
- menu_args = (
- ["--dmenu"] if not menu_args and menu_bin.endswith("fuzzel") else menu_args
- )
- store_dir = store_dir.expanduser().absolute()
- # Get all files in store_dir
- secrets = (
- dirpath / fname
- for dirpath, _dirnames, filenames in store_dir.walk()
- for fname in filenames
- )
- # Filter for files ending in .gpg and strip the extension
- secrets = (
- secret.with_suffix("")
- for secret in secrets
- if secret.is_file() and secret.suffix == ".gpg"
- )
- # Make the paths relative to store_dir and turn to strings
- secrets = sorted(str(secret.relative_to(store_dir)) for secret in secrets)
-
- if not secrets:
- click.secho(f"No valid entries found in {store_dir}", err=True, fg="red")
-
- selected = select(secrets)
- if selected is None:
- click.echo("No secret selected")
- return
- selected = secrets[selected]
-
- # If PASSWORD_STORE_DIR and --store-dir disagree, set PASSWORD_STORE_DIR to --store-dir
- env_store = (
- Path(environ.get("PASSWORD_STORE_DIR", default="~/.password-store"))
- .expanduser()
- .absolute()
- )
- if store_dir != env_store:
- environ["PASSWORD_STORE_DIR"] = str(store_dir)
-
- pass_cmd = (
- [pass_bin, "show", selected]
- if typeit
- else [pass_bin, "show", "--clip", selected]
- )
-
- pass_output = subprocess.run(
- pass_cmd,
- encoding="UTF-8",
- check=True,
- capture_output=typeit,
- )
- if not typeit:
- return
-
- pass_entry = pass_output.stdout
- secret = pass_entry.splitlines()[0].strip()
-
- _ = subprocess.run(
- ["ydotool", "type", "--file", "-"],
- input=secret,
- encoding="UTF-8",
- check=True,
- )
-
-
-if __name__ == "__main__":
- main()
diff --git a/scripts/jpassmenu/package.nix b/scripts/jpassmenu/package.nix
index 6fbfbbd..88636da 100644
--- a/scripts/jpassmenu/package.nix
+++ b/scripts/jpassmenu/package.nix
@@ -1,6 +1,40 @@
-{ writers, python3Packages }:
-writers.writePython3Bin "jpassmenu" {
- libraries = [ python3Packages.click ];
- # line too long, but I like my code well documented
- flakeIgnore = [ "E501" ];
-} ./jpassmenu.py
+{ lib, rustPlatform }:
+let
+ cargoToml = builtins.fromTOML (builtins.readFile ./Cargo.toml);
+ inherit (cargoToml.package) name version description;
+ pname = name;
+ src = lib.cleanSourceWith {
+ src = ./.;
+ name = "${pname}-source";
+ # Adapted from
+ # no need to pull in crane for just this
+ filter =
+ orig_path: type:
+ let
+ path = toString orig_path;
+ base = baseNameOf path;
+ parentDir = baseNameOf (dirOf path);
+ matchesSuffix = lib.any (suffix: lib.hasSuffix suffix base) [
+ # Rust sources
+ ".rs"
+ # TOML files are often used to configure cargo based tools (e.g. .cargo/config.toml)
+ ".toml"
+ ];
+ isCargoLock = base == "Cargo.lock";
+ # .cargo/config.toml is captured above
+ isOldStyleCargoConfig = parentDir == ".cargo" && base == "config";
+ in
+ type == "directory" || matchesSuffix || isCargoLock || isOldStyleCargoConfig;
+ };
+in
+rustPlatform.buildRustPackage {
+ inherit pname version src;
+ cargoLock.lockFile = ./Cargo.lock;
+ useNextest = true;
+ meta = {
+ inherit description;
+ license = lib.licenses.mit;
+ homepage = "https://github.com/jalil-salame/configuration.nix";
+ mainProgram = name;
+ };
+}
diff --git a/scripts/jpassmenu/pyproject.toml b/scripts/jpassmenu/pyproject.toml
deleted file mode 100644
index 5cfa6aa..0000000
--- a/scripts/jpassmenu/pyproject.toml
+++ /dev/null
@@ -1,9 +0,0 @@
-[project]
-name = "jpassmenu"
-version = "0.1.0"
-description = "A simple program that uses dmenu compatible menu to select a password to type/copy"
-readme = "README.md"
-requires-python = ">=3.12"
-dependencies = [
- "click>=8.1.7",
-]
diff --git a/scripts/jpassmenu/src/main.rs b/scripts/jpassmenu/src/main.rs
new file mode 100644
index 0000000..279dbdc
--- /dev/null
+++ b/scripts/jpassmenu/src/main.rs
@@ -0,0 +1,156 @@
+use std::{
+ ffi::OsStr,
+ fmt::Write as _,
+ path::{Path, PathBuf},
+};
+
+use clap::Parser;
+use duct::cmd;
+use miette::{bail, ensure, Context, IntoDiagnostic, Result};
+
+fn main() -> Result<()> {
+ miette::set_panic_hook();
+ env_logger::builder()
+ .filter_level(log::LevelFilter::Info)
+ .parse_default_env()
+ .try_init()
+ .into_diagnostic()?;
+ Opts::parse().run()
+}
+
+impl Opts {
+ fn run(self) -> Result<()> {
+ log::debug!("parsed opts {self:?}");
+ let Self {
+ typeit,
+ store_dir,
+ pass_bin,
+ menu_bin,
+ menu_args,
+ } = self;
+ let store_dir = resolve_home(store_dir);
+ // Search paths
+ log::info!("looking for entries in {}", store_dir.display());
+ let mut paths = ignore::Walk::new(&store_dir)
+ .filter_map(|entry| {
+ let entry = entry.ok()?;
+ if entry.file_type()?.is_file()
+ && entry.path().extension() == Some(OsStr::new("gpg"))
+ {
+ let path = entry.path();
+ Some(
+ path.strip_prefix(&store_dir)
+ .unwrap_or(path)
+ .with_extension("")
+ .into_boxed_path(),
+ )
+ } else {
+ None
+ }
+ })
+ .collect::>>();
+ paths.sort_unstable();
+ ensure!(
+ !paths.is_empty(),
+ "failed to find entries in {}",
+ store_dir.display()
+ );
+ log::debug!("found entries: {paths:#?}");
+ // Concatenate all paths
+ let paths = paths
+ .into_iter()
+ .try_fold(String::new(), |mut acc, it| {
+ writeln!(acc, "{}", it.display()).map(|_| acc)
+ })
+ .into_diagnostic()
+ .wrap_err("preparing paths")?;
+ // Show dynamic menu
+ let selected = cmd(menu_bin, menu_args)
+ .stdin_bytes(paths.as_bytes())
+ .read()
+ .into_diagnostic()
+ .wrap_err("failed to run menu and retrieve the selected entry")?;
+ let selected = selected.trim();
+ if selected.is_empty() {
+ bail!("no password entry selected");
+ }
+ // Prepare env dir
+ let env_store = std::env::var_os("PASSWORD_STORE_DIR");
+ let set_env = if let Some(env_store) = env_store {
+ if store_dir != env_store {
+ Some(store_dir)
+ } else {
+ None
+ }
+ } else if store_dir == Path::new("~/.password-store") {
+ None
+ } else {
+ Some(store_dir)
+ };
+ // Prepare pass command
+ let args = if typeit {
+ vec!["show", selected]
+ } else {
+ vec!["show", "-c", selected]
+ };
+ let pass = cmd(pass_bin, args);
+ let pass = if let Some(env) = set_env {
+ pass.env("PASSWORD_STORE_DIR", env)
+ } else {
+ pass
+ };
+ // Copy password to clipboard
+ if !typeit {
+ pass.run()
+ .into_diagnostic()
+ .wrap_err("failed to copy password to clipboard")?;
+ return Ok(());
+ }
+ // Retrieve password
+ let pass_entry = pass
+ .read()
+ .into_diagnostic()
+ .wrap_err("failed to retrieve password")?;
+ let Some(password) = pass_entry.lines().next() else {
+ bail!("failed to retrieve password or entry was empty");
+ };
+ // Type password with ydotool
+ cmd("ydotool", &["type", "--file", "-"])
+ .stdin_bytes(password.as_bytes())
+ .run()
+ .into_diagnostic()
+ .wrap_err("failed to type password with ydotool")?;
+ Ok(())
+ }
+}
+
+#[derive(Debug, Parser)]
+struct Opts {
+ /// Type the password instead of copying it to the clipboard
+ #[arg(long("type"))]
+ typeit: bool,
+ #[arg(long, env("PASSWORD_STORE_DIR"), default_value = "~/.password-store")]
+ store_dir: PathBuf,
+ /// Path to the pass binary
+ ///
+ /// Needs to support `pass show` and `pass show -c`
+ #[arg(long, default_value = "pass")]
+ pass_bin: String,
+ /// Path to the dynamic menu binary
+ #[arg(long, default_value = "fuzzel")]
+ menu_bin: String,
+ /// Args to the dynamic menu
+ #[arg(long, default_value = "--dmenu")]
+ menu_args: Vec,
+}
+
+fn resolve_home(path: PathBuf) -> PathBuf {
+ if let Ok(path) = path.strip_prefix("~") {
+ if let Some(home) = std::env::var_os("HOME") {
+ let mut home = PathBuf::from(home);
+ home.push(path);
+ return home;
+ }
+ }
+ path
+}
diff --git a/system/default.nix b/system/default.nix
new file mode 100644
index 0000000..3fdd0cf
--- /dev/null
+++ b/system/default.nix
@@ -0,0 +1,129 @@
+{ stylix }:
+{
+ config,
+ pkgs,
+ lib,
+ ...
+}:
+let
+ cfg = config.jconfig;
+ keysFromGithub = lib.attrsets.mapAttrs' (username: sha256: {
+ name = "pubkeys/${username}";
+ value = {
+ mode = "0755";
+ source = builtins.fetchurl {
+ inherit sha256;
+ url = "https://github.com/${username}.keys";
+ };
+ };
+ }) cfg.importSSHKeysFromGithub;
+in
+{
+ imports = [
+ ./options.nix
+ ./gui
+ stylix.nixosModules.stylix
+ { stylix = import ./stylix-config.nix { inherit config pkgs; }; }
+ ];
+
+ config = lib.mkIf cfg.enable (
+ lib.mkMerge [
+ {
+ boot.plymouth = {
+ inherit (cfg.styling) enable;
+ };
+
+ # Enable unlocking the gpg-agent at boot (configured through home.nix)
+ security.pam.services.login.gnupg.enable = true;
+
+ environment.systemPackages = [
+ # CLI tools
+ pkgs.fd
+ pkgs.ripgrep
+ pkgs.du-dust
+ pkgs.curl
+ pkgs.zip
+ pkgs.unzip
+ ];
+
+ # Enable dev documentation
+ documentation.dev = {
+ inherit (cfg.dev) enable;
+ };
+ programs = {
+ # Shell prompt
+ starship = {
+ enable = true;
+ settings = lib.mkMerge [
+ {
+ format = "$time$all";
+ add_newline = false;
+ cmd_duration.min_time = 500;
+ cmd_duration.show_milliseconds = true;
+ time.disabled = false;
+ status = {
+ format = "[$signal_name$common_meaning$maybe_int](red)";
+ symbol = "[✗](bold red)";
+ disabled = false;
+ };
+ sudo.disabled = false;
+ }
+ # Add nerdfont symbols
+ (lib.mkIf cfg.styling.enable (import ./starship-nerdfont-symbols.nix))
+ # Remove the `in`s and `on`s from the prompt
+ (lib.mkIf cfg.styling.enable (import ./starship-shorter-text.nix))
+ ];
+ };
+ # Default shell
+ zsh.enable = true;
+ };
+
+ environment.etc = keysFromGithub;
+ services = {
+ # Enable printer autodiscovery if printing is enabled
+ avahi = {
+ inherit (config.services.printing) enable;
+ nssmdns4 = true;
+ openFirewall = true;
+ };
+ openssh.authorizedKeysFiles = builtins.map (path: "/etc/${path}") (
+ builtins.attrNames keysFromGithub
+ );
+ };
+ users.defaultUserShell = pkgs.zsh;
+ # Open ports for spotifyd
+ networking.firewall = {
+ allowedUDPPorts = [ 5353 ];
+ allowedTCPPorts = [ 2020 ];
+ };
+ # Nix Settings
+ nix = {
+ gc = {
+ automatic = true;
+ dates = "weekly";
+ options = "--delete-older-than 30d";
+ # run between 0 and 45min after boot if run was missed
+ randomizedDelaySec = "45min";
+ };
+ settings = {
+ use-xdg-base-directories = true;
+ auto-optimise-store = true;
+ experimental-features = [
+ "nix-command"
+ "flakes"
+ ];
+ };
+ };
+ }
+ # dev configuration
+ (lib.mkIf cfg.dev.enable {
+ users.extraUsers = lib.mkIf cfg.dev.jupyter.enable { jupyter.group = "jupyter"; };
+ services.jupyter = {
+ inherit (cfg.dev.jupyter) enable;
+ group = "jupyter";
+ user = "jupyter";
+ };
+ })
+ ]
+ );
+}
diff --git a/system/gui/default.nix b/system/gui/default.nix
new file mode 100644
index 0000000..6be652f
--- /dev/null
+++ b/system/gui/default.nix
@@ -0,0 +1,113 @@
+{
+ config,
+ lib,
+ pkgs,
+ ...
+}:
+let
+ cfg = config.jconfig.gui;
+ enable = config.jconfig.enable && cfg.enable;
+ linuxOlderThan6_3 = lib.versionOlder config.boot.kernelPackages.kernel.version "6.3";
+in
+{
+ config = lib.mkMerge [
+ (lib.mkIf enable {
+ environment.systemPackages = [
+ pkgs.adwaita-icon-theme
+ pkgs.adwaita-qt
+ pkgs.nordzy-cursor-theme
+ pkgs.pinentry-qt
+ ] ++ lib.optional cfg.ydotool.enable pkgs.ydotool;
+ systemd = {
+ user.services.ydotool = lib.mkIf cfg.ydotool.enable {
+ enable = cfg.ydotool.autoStart;
+ wantedBy = [ "default.target" ];
+ description = "Generic command-line automation tool";
+ documentation = [
+ "man:ydotool(1)"
+ "man:ydotoold(8)"
+ ];
+ serviceConfig = {
+ Type = "simple";
+ Restart = "always";
+ ExecStart = "${pkgs.ydotool}/bin/ydotoold";
+ ExecReload = "${pkgs.util-linux}/bin/kill -HUP $MAINPID";
+ KillMode = "process";
+ TimeoutSec = 180;
+ };
+ };
+ # Fix xdg-portals issue issue: https://github.com/NixOS/nixpkgs/issues/189851
+ user.extraConfig = ''
+ DefaultEnvironment="PATH=/run/wrappers/bin:/etc/profiles/per-user/%u/bin:/nix/var/nix/profiles/default/bin:/run/current-system/sw/bin"
+ '';
+ };
+
+ fonts.fontDir.enable = true;
+ programs = {
+ dconf.enable = true;
+ niri = {
+ enable = cfg.windowManager;
+ package = pkgs.niri; # use nixpkgs' package instead of the flake's
+ };
+ };
+ security = {
+ polkit.enable = true;
+ rtkit.enable = true; # Recommended for pipewire
+ };
+ services = {
+ flatpak.enable = true;
+ # Audio
+ pipewire = {
+ enable = true;
+ alsa = {
+ enable = true;
+ support32Bit = true;
+ };
+ pulse.enable = true;
+ wireplumber.enable = true;
+ };
+ # Dbus
+ dbus.enable = true;
+ # Virtual Filesystem (for PCManFM)
+ gvfs.enable = true;
+ };
+ xdg.portal = {
+ # XDG portals
+ enable = true;
+ wlr.enable = true;
+ extraPortals = [ pkgs.xdg-desktop-portal-gtk ];
+ config.preferred = {
+ # Default to the gtk portal
+ default = "gtk";
+ # Use wlr for screenshots and screen recording
+ "org.freedesktop.impl.portal.Screenshot" = "wlr";
+ };
+ # Consider using darkman like upstream
+ };
+ hardware = {
+ graphics.enable = true;
+ uinput.enable = true;
+ steam-hardware.enable = cfg.steamHardwareSupport;
+ };
+ })
+ (lib.mkIf (enable && linuxOlderThan6_3 && cfg."8bitdoFix") {
+ # Udev rules to start or stop systemd service when controller is connected or disconnected
+ services.udev.extraRules = # udev
+ ''
+ # May vary depending on your controller model, find product id using 'lsusb'
+ SUBSYSTEM=="usb", ATTR{idVendor}=="2dc8", ATTR{idProduct}=="3106", ATTR{manufacturer}=="8BitDo", RUN+="${pkgs.systemd}/bin/systemctl start 8bitdo-ultimate-xinput@2dc8:3106"
+ # This device (2dc8:3016) is "connected" when the above device disconnects
+ SUBSYSTEM=="usb", ATTR{idVendor}=="2dc8", ATTR{idProduct}=="3016", ATTR{manufacturer}=="8BitDo", RUN+="${pkgs.systemd}/bin/systemctl stop 8bitdo-ultimate-xinput@2dc8:3106"
+ '';
+
+ # Systemd service which starts xboxdrv in xbox360 mode
+ systemd.services."8bitdo-ultimate-xinput@" = {
+ unitConfig.Description = "8BitDo Ultimate Controller XInput mode xboxdrv daemon";
+ serviceConfig = {
+ Type = "simple";
+ ExecStart = "${pkgs.xboxdrv}/bin/xboxdrv --mimic-xpad --silent --type xbox360 --device-by-id %I --force-feedback";
+ };
+ };
+ })
+ ];
+}
diff --git a/system/options.nix b/system/options.nix
new file mode 100644
index 0000000..51ac162
--- /dev/null
+++ b/system/options.nix
@@ -0,0 +1,119 @@
+{ lib, ... }:
+let
+ inherit (lib) types;
+ # Like mkEnableOption but defaults to true
+ mkDisableOption =
+ option:
+ (lib.mkEnableOption option)
+ // {
+ default = true;
+ example = false;
+ };
+ mkImageOption =
+ {
+ description,
+ url,
+ sha256 ? "",
+ }:
+ lib.mkOption {
+ inherit description;
+ type = types.path;
+ default = builtins.fetchurl { inherit url sha256; };
+ defaultText = lib.literalMD "";
+ };
+
+ gui.options = {
+ enable = lib.mkEnableOption "jalil's default gui configuration.";
+ # Fix for using Xinput mode on 8bitdo Ultimate C controller
+ # Inspired by https://aur.archlinux.org/packages/8bitdo-ultimate-controller-udev
+ # Adapted from: https://gist.github.com/interdependence/28452fbfbe692986934fbe1e54c920d4
+ "8bitdoFix" = mkDisableOption "a fix for 8bitdo controllers";
+ steamHardwareSupport = mkDisableOption "steam hardware support";
+ ydotool = lib.mkOption {
+ description = "Jalil's default ydotool configuration.";
+ default = { };
+ type = types.submodule {
+ options.enable = mkDisableOption "ydotool";
+ options.autoStart = mkDisableOption "autostarting ydotool at login";
+ };
+ };
+ windowManager = lib.mkOption {
+ description = "Window manager configuration";
+ default = { };
+ type = types.submodule {
+ options = {
+ enable = mkDisableOption "window manager";
+ windowManager = lib.mkOption {
+ description = "Which window manager to enable";
+ type = types.enum [ "niri" ];
+ default = "niri";
+ };
+ };
+ };
+ };
+ };
+
+ styling.options = {
+ enable = mkDisableOption "jalil's default styling (disables stylix)";
+ wallpaper = mkImageOption {
+ description = "The wallpaper to use.";
+ url = "https://raw.githubusercontent.com/lunik1/nixos-logo-gruvbox-wallpaper/d4937c424fad79c1136a904599ba689fcf8d0fad/png/gruvbox-dark-rainbow.png";
+ sha256 = "036gqhbf6s5ddgvfbgn6iqbzgizssyf7820m5815b2gd748jw8zc";
+ };
+ bootLogo = mkImageOption {
+ description = "The logo used by plymouth at boot.";
+ # http://xenia-linux-site.glitch.me/images/cathodegaytube-splash.png
+ url = "https://efimero.github.io/xenia-images/cathodegaytube-splash.png";
+ sha256 = "qKugUfdRNvMwSNah+YmMepY3Nj6mWlKFh7jlGlAQDo8=";
+ };
+ };
+
+ config.options = {
+ enable = lib.mkEnableOption "jalil's default configuration.";
+ dev = lib.mkOption {
+ description = "Options for setting up a dev environment";
+ default = { };
+ type = types.submodule {
+ options.enable = lib.mkEnableOption "dev configuration";
+ options.jupyter.enable = lib.mkEnableOption "jupyter configuration";
+ };
+ };
+ gui = lib.mkOption {
+ description = "Jalil's default configuration for a NixOS gui.";
+ default = { };
+ type = types.submodule gui;
+ };
+ styling = lib.mkOption {
+ description = "Jalil's styling options";
+ default = { };
+ type = types.submodule styling;
+ };
+ importSSHKeysFromGithub = lib.mkOption {
+ description = ''
+ Import public ssh keys from a github username.
+
+ This will fetch the keys from https://github.com/$${username}.keys.
+
+ The format is `"$${github-username}" = $${sha256-hash}`. The example
+ will try to fetch the keys from .
+
+ **Warning**: this will interfere with services like gitea that override
+ the default ssh behaviour. In that case you want to use
+ `users.users..openssh.authorizedKeys.keyFiles` on the users you
+ want to allow ssh logins.
+ '';
+ default = { };
+ example = {
+ "jalil-salame" = "sha256:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
+ };
+ type = types.attrsOf types.str;
+ };
+ };
+in
+{
+ options.jconfig = lib.mkOption {
+ description = "Jalil's default NixOS configuration.";
+ default = { };
+ type = types.submodule config;
+ };
+}
diff --git a/system/starship-nerdfont-symbols.nix b/system/starship-nerdfont-symbols.nix
new file mode 100644
index 0000000..2032150
--- /dev/null
+++ b/system/starship-nerdfont-symbols.nix
@@ -0,0 +1,89 @@
+{
+ aws.symbol = " ";
+ buf.symbol = " ";
+ c.symbol = " ";
+ conda.symbol = " ";
+ crystal.symbol = " ";
+ dart.symbol = " ";
+ directory.read_only = " ";
+ docker_context.symbol = " ";
+ elixir.symbol = " ";
+ elm.symbol = " ";
+ fennel.symbol = " ";
+ fossil_branch.symbol = " ";
+ git_branch.symbol = " ";
+ git_commit.tag_symbol = " ";
+ golang.symbol = " ";
+ gradle.symbol = " ";
+ guix_shell.symbol = " ";
+ haskell.symbol = " ";
+ haxe.symbol = " ";
+ hg_branch.symbol = " ";
+ hostname.ssh_symbol = " ";
+ java.symbol = " ";
+ julia.symbol = " ";
+ kotlin.symbol = " ";
+ lua.symbol = " ";
+ memory_usage.symbol = " ";
+ meson.symbol = " ";
+ nim.symbol = " ";
+ nix_shell.symbol = " ";
+ nodejs.symbol = " ";
+ ocaml.symbol = " ";
+ package.symbol = " ";
+ perl.symbol = " ";
+ php.symbol = " ";
+ pijul_channel.symbol = " ";
+ python.symbol = " ";
+ rlang.symbol = " ";
+ ruby.symbol = " ";
+ rust.symbol = " ";
+ scala.symbol = " ";
+ swift.symbol = " ";
+ zig.symbol = " ";
+ os.symbols = {
+ Alpaquita = " ";
+ Alpine = " ";
+ AlmaLinux = " ";
+ Amazon = " ";
+ Android = " ";
+ Arch = " ";
+ Artix = " ";
+ CentOS = " ";
+ Debian = " ";
+ DragonFly = " ";
+ Emscripten = " ";
+ EndeavourOS = " ";
+ Fedora = " ";
+ FreeBSD = " ";
+ Garuda = " ";
+ Gentoo = " ";
+ HardenedBSD = " ";
+ Illumos = " ";
+ Kali = " ";
+ Linux = " ";
+ Mabox = " ";
+ Macos = " ";
+ Manjaro = " ";
+ Mariner = " ";
+ MidnightBSD = " ";
+ Mint = " ";
+ NetBSD = " ";
+ NixOS = " ";
+ OpenBSD = " ";
+ openSUSE = " ";
+ OracleLinux = " ";
+ Pop = " ";
+ Raspbian = " ";
+ Redhat = " ";
+ RedHatEnterprise = " ";
+ RockyLinux = " ";
+ Redox = " ";
+ Solus = " ";
+ SUSE = " ";
+ Ubuntu = " ";
+ Unknown = " ";
+ Void = " ";
+ Windows = " ";
+ };
+}
diff --git a/system/starship-shorter-text.nix b/system/starship-shorter-text.nix
new file mode 100644
index 0000000..605a53a
--- /dev/null
+++ b/system/starship-shorter-text.nix
@@ -0,0 +1,66 @@
+{
+ aws.format = "[$symbol($profile)(\\($region\\))(\\[$duration\\])]($style) ";
+ bun.format = "[$symbol($version)]($style) ";
+ c.format = "[$symbol($version(-$name))]($style) ";
+ cmake.format = "[$symbol($version)]($style) ";
+ cmd_duration.format = "[⏱ $duration]($style) ";
+ cobol.format = "[$symbol($version)]($style) ";
+ conda.format = "[$symbol$environment]($style) ";
+ crystal.format = "[$symbol($version)]($style) ";
+ daml.format = "[$symbol($version)]($style) ";
+ dart.format = "[$symbol($version)]($style) ";
+ deno.format = "[$symbol($version)]($style) ";
+ docker_context.format = "[$symbol$context]($style) ";
+ dotnet.format = "[$symbol($version)(🎯 $tfm)]($style) ";
+ elixir.format = "[$symbol($version \\(OTP $otp_version\\))]($style) ";
+ elm.format = "[$symbol($version)]($style) ";
+ erlang.format = "[$symbol($version)]($style) ";
+ fennel.format = "[$symbol($version)]($style) ";
+ fossil_branch.format = "[$symbol$branch]($style) ";
+ gcloud.format = "[$symbol$account(@$domain)(\\($region\\))]($style) ";
+ git_branch.format = "[$symbol$branch]($style) ";
+ git_status.format = "[$all_status$ahead_behind]($style) ";
+ golang.format = "[$symbol($version)]($style) ";
+ gradle.format = "[$symbol($version)]($style) ";
+ guix_shell.format = "[$symbol]($style) ";
+ haskell.format = "[$symbol($version)]($style) ";
+ haxe.format = "[$symbol($version)]($style) ";
+ helm.format = "[$symbol($version)]($style) ";
+ hg_branch.format = "[$symbol$branch]($style) ";
+ java.format = "[$symbol($version)]($style) ";
+ julia.format = "[$symbol($version)]($style) ";
+ kotlin.format = "[$symbol($version)]($style) ";
+ kubernetes.format = "[$symbol$context( \\($namespace\\))]($style) ";
+ lua.format = "[$symbol($version)]($style) ";
+ memory_usage.format = "$symbol[$ram( | $swap)]($style) ";
+ meson.format = "[$symbol$project]($style) ";
+ nim.format = "[$symbol($version)]($style) ";
+ nix_shell.format = "[$symbol$state( \\($name\\))]($style) ";
+ nodejs.format = "[$symbol($version)]($style) ";
+ ocaml.format = "[$symbol($version)(\\($switch_indicator$switch_name\\))]($style) ";
+ opa.format = "[$symbol($version)]($style) ";
+ openstack.format = "[$symbol$cloud(\\($project\\))]($style) ";
+ os.format = "[$symbol]($style) ";
+ package.format = "[$symbol$version]($style) ";
+ perl.format = "[$symbol($version)]($style) ";
+ php.format = "[$symbol($version)]($style) ";
+ pijul_channel.format = "[$symbol$channel]($style) ";
+ pulumi.format = "[$symbol$stack]($style) ";
+ purescript.format = "[$symbol($version)]($style) ";
+ python.format = "[\${symbol}\${pyenv_prefix}(\${version})(\\($virtualenv\\))]($style) ";
+ raku.format = "[$symbol($version-$vm_version)]($style) ";
+ red.format = "[$symbol($version)]($style) ";
+ ruby.format = "[$symbol($version)]($style) ";
+ rust.format = "[$symbol($version)]($style) ";
+ scala.format = "[$symbol($version)]($style) ";
+ spack.format = "[$symbol$environment]($style) ";
+ sudo.format = "[as $symbol]($style) ";
+ swift.format = "[$symbol($version)]($style) ";
+ terraform.format = "[$symbol$workspace]($style) ";
+ time.format = "[$time]($style) ";
+ username.format = "[$user]($style) ";
+ vagrant.format = "[$symbol($version)]($style) ";
+ vlang.format = "[$symbol($version)]($style) ";
+ zig.format = "[$symbol($version)]($style) ";
+ solidity.format = "[$symbol($version)]($style) ";
+}
diff --git a/system/stylix-config.nix b/system/stylix-config.nix
new file mode 100644
index 0000000..a4e75d8
--- /dev/null
+++ b/system/stylix-config.nix
@@ -0,0 +1,36 @@
+{ config, pkgs }:
+let
+ cfg = config.jconfig.styling;
+in
+{
+ inherit (cfg) enable;
+ image = cfg.wallpaper;
+ base16Scheme = "${pkgs.base16-schemes}/share/themes/gruvbox-dark-hard.yaml";
+ polarity = "dark";
+ fonts = {
+ monospace = {
+ name = "JetBrains Mono";
+ package = pkgs.jetbrains-mono;
+ };
+ sansSerif = {
+ name = "Noto Sans";
+ package = pkgs.noto-fonts;
+ };
+ serif = {
+ name = "Noto Serif";
+ package = pkgs.noto-fonts;
+ };
+ emoji = {
+ package = pkgs.noto-fonts-emoji;
+ name = "Noto Color Emoji";
+ };
+ sizes.popups = 12;
+ };
+ targets = {
+ plymouth = {
+ logoAnimated = false;
+ logo = cfg.bootLogo;
+ };
+ nixvim.enable = false;
+ };
+}