Changes
92 changed files (+2580/-3792)
-
features/basics/default.nix (deleted)
-
@@ -1,143 +0,0 @@# Copyright 2023 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD { config, lib, pkgs, ... }: { imports = [ ./atuin.nix ./platform.nix ./neovim.nix ./tmux.nix ./zsh.nix ]; config = { home.packages = [ # Must-have networking CLI tool # https://curl.se/ pkgs.curl # Command to produce a depth indented directory listing pkgs.tree # A tool to fix `nix-shell` and `nix develop` forcibly use bash # https://github.com/MercuryTechnologies/nix-your-shell pkgs.nix-your-shell # Spell checker (pkgs.aspellWithDicts ( dicts: with dicts; [ en en-computers ] )) ]; home.file = { ".editorconfig".text = '' root = true [*] charset = utf-8 end_of_line = lf insert_final_newline = true indent_style = tab indent_size = 2 ''; }; # Programs available via Home Manager programs = { # For fallback purpose. bash = { enable = true; }; fish = { enable = true; interactiveShellInit = builtins.readFile ./init.fish; }; # A modern replacement for ls (fork of exa). # https://eza.rocks/ eza = { enable = true; # Enable recommended exa aliases (ls, ll…). enableZshIntegration = true; extraOptions = [ "--long" "--all" ]; }; # A terminal file manager written in Go with a heavy inspiration from ranger file manager. # https://github.com/gokcehan/lf lf = let # Linux: xdg-open # macOS: open openCommand = if pkgs.stdenv.isLinux then "xdg-open" else "open"; in { enable = true; commands = { # Open text files with nvim open = '' ''${{ case $(file --mime-type -Lb $f) in text/*) nvim $fx;; *) for f in $fx; do ${openCommand} $f > /dev/null 2> /dev/null & done;; esac }} ''; }; }; # Colourful `cat` # https://github.com/sharkdp/bat bat = { enable = true; config = { # Use ANSI colors theme = "ansi"; }; }; # `top` alternative # https://htop.dev/ htop = { enable = true; }; # ripgrep recursively searches directories for a regex pattern while respecting your gitignore # (this program is required for telescope-nvim's live_grep to work) # https://github.com/BurntSushi/ripgrep ripgrep = { enable = true; arguments = [ "--sort=path" ]; }; }; }; }
-
-
features/basics/neovim.nix (deleted)
-
@@ -1,66 +0,0 @@# Copyright 2023 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD { config, pkgs, ... }: { config = { programs = { neovim = { enable = true; defaultEditor = true; withPython3 = false; withRuby = false; extraLuaConfig = builtins.readFile ./neovim/basic.lua; plugins = with pkgs.vimPlugins; [ plenary-nvim { plugin = zen-mode-nvim; type = "lua"; config = builtins.readFile ./neovim/zen-mode.lua; } { plugin = nvim-tree-lua; type = "lua"; config = builtins.readFile ./neovim/nvim-tree.lua; } { plugin = telescope-nvim; type = "lua"; config = builtins.readFile ./neovim/telescope.lua; } { plugin = telescope-file-browser-nvim; type = "lua"; config = builtins.readFile ./neovim/telescope-file-browser.lua; } { plugin = indent-blankline-nvim; type = "lua"; config = builtins.readFile ./neovim/indent-blankline.lua; } { plugin = lualine-nvim; type = "lua"; config = builtins.readFile ./neovim/lualine.lua; } ]; }; }; }; }
-
-
features/basics/tmux.nix (deleted)
-
@@ -1,66 +0,0 @@# Copyright 2023 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD { config, pkgs, ... }: { programs = { tmux = { keyMode = "vi"; # Ctrl+t prefix = "C-t"; # Automatically spawn a session if trying to attach and none are running. newSession = true; # Use 24 hour clock. # Because I'm not insane. clock24 = true; # Whether to enable mouse support. mouse = true; # Time in milliseconds for which tmux waits after an escape is input. # NOTE: Without this, there will be a lag after hitting ESC (e.g. exiting insert mode) # https://github.com/neovim/neovim/wiki/FAQ#esc-in-tmux-or-gnu-screen-is-delayed escapeTime = 10; # True Color options: # https://gist.github.com/andersevenrud/015e61af2fd264371032763d4ed965b6 extraConfig = '' set -g default-terminal "tmux-256color" set -ga terminal-overrides ",$TERM:Tc" bind | split-window -hc "#{pane_current_path}" bind - split-window -vc "#{pane_current_path}" unbind '"' unbind % bind c new-window -c "#{pane_current_path}" bind h select-pane -L bind j select-pane -D bind k select-pane -U bind l select-pane -R unbind Up unbind Down unbind Left unbind Right set -g status-position bottom ''; }; }; }
-
-
features/basics/zsh.nix (deleted)
-
@@ -1,163 +0,0 @@# Copyright 2023 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD { config, lib, pkgs, ... }: let cfg = config.features.basics.zsh; in { options = { features.basics.zsh.theme = { text = lib.mkOption { type = lib.types.nonEmptyStr; default = "%f"; }; vi.insert = lib.mkOption { type = lib.types.nonEmptyStr; default = "%{$fg[blue]%}"; }; vi.normal = lib.mkOption { type = lib.types.nonEmptyStr; default = "%{$fg[green]%}"; }; vcs = { info = lib.mkOption { type = lib.types.nonEmptyStr; default = "%{$fg[white]%}"; }; staged = lib.mkOption { type = lib.types.nonEmptyStr; default = "%{$fg[green]%}"; }; unstaged = lib.mkOption { type = lib.types.nonEmptyStr; default = "%{$fg[red]%}"; }; }; symbol = lib.mkOption { type = lib.types.nonEmptyStr; default = "%F{8}"; }; }; }; config = { programs = { zsh = { enable = true; # The default base keymap to use. defaultKeymap = "viins"; # Enable zsh completion. Don’t forget to add enableCompletion = true; # Options related to commands history configuration. history = { # Do not enter command lines into the history list if they are duplicates of the previous event. ignoreDups = true; # Save timestamp into the history file. extended = true; # Number of history lines to keep. size = 1000; # Share command history between zsh sessions. share = false; }; sessionVariables = { # Insert space between completed string and ampersand or pipe ZLE_SPACE_SUFFIX_CHARS = "&|"; }; initContent = with cfg.theme; '' # Activate colors module in order to colourise prompt autoload -Uz colors colors # Branch character (for readability) CH_BRANCH=$'\ue0a0' function custom-prompt() { PROMPT_PREFIX="" if [[ -n $SSH_CLIENT ]] || [[ -n $SSH_TTY ]]; then PROMPT_PREFIX="''${PROMPT_PREFIX}[SSH]" fi if [[ -n $IN_NIX_SHELL ]]; then PROMPT_PREFIX="''${PROMPT_PREFIX}[Nix]" fi if [[ -n $PROMPT_PREFIX ]]; then PROMPT_PREFIX="''${PROMPT_PREFIX} " fi echo -e " %f%k%b%F{cyan}''${PROMPT_PREFIX}%f''${1}%1d ''${vcs_info_msg_0_}%k%f%b ${symbol}%# ${text}" } # VCS autoload -Uz vcs_info precmd () { vcs_info } zstyle ":vcs_info:git:*" check-for-changes true zstyle ":vcs_info:git:*" stagedstr "${vcs.staged}*" zstyle ":vcs_info:git:*" unstagedstr "${vcs.unstaged}*" zstyle ":vcs_info:*" formats "${vcs.info}''${CH_BRANCH} %b%c%u${text}" zstyle ":vcs_info:*" actionformats "[%b|%a]" zstyle ":completion:*" ignored-patterns "dpipe|exiv2" function zle-line-init zle-keymap-select { case $KEYMAP in vicmd) PROMPT=$(custom-prompt "${vi.normal}") ;; main|viins) PROMPT=$(custom-prompt "${vi.insert}") ;; esac zle reset-prompt } zle -N zle-line-init zle -N zle-keymap-select # Aliases nix commands to use Zsh rather than bash if command -v nix-your-shell > /dev/null; then nix-your-shell zsh | source /dev/stdin fi ''; }; }; }; }
-
-
features/data/default.nix (deleted)
-
@@ -1,47 +0,0 @@# Copyright 2023 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # # === # Configurations for data-related tasks: inspect, modify, etc... { config, lib, pkgs, ... }: { options = { features.data.enable = lib.mkEnableOption "Data"; }; imports = [ ./nushell.nix ]; config = lib.mkIf config.features.data.enable { home.packages = with pkgs; [ # An advanced calculator library (`qalc` command) # https://qalculate.github.io/ libqalculate ]; programs = { # JSON view/query tool # https://github.com/jqlang/jq jq = { enable = true; }; }; }; }
-
-
features/gui/ghostty.nix (deleted)
-
@@ -1,75 +0,0 @@# Copyright 2024 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD { config, lib, pkgs, ... }: { config = lib.mkIf config.features.gui.enable { programs.ghostty = { enable = true; enableZshIntegration = true; package = if pkgs.stdenv.isDarwin then pkgs.ghostty-bin else config.lib.nixGL.wrap pkgs.ghostty; installBatSyntax = !pkgs.stdenv.isDarwin; settings = { # Somehow Ghostty renders Monaspace in incorrect size at either of platform. font-size = if pkgs.stdenv.isDarwin then 13 else 10; font-family = "Monaspace Neon Var"; font-style = "Medium"; font-style-bold = "Bold"; font-style-italic = "Medium Italic"; font-style-bold-italic = "Bold Italic"; # * "calt" ... Contextual Alternates # This feature enables Monaspace's Texture healing. font-feature = [ "calt" ]; copy-on-select = false; keybind = if pkgs.stdenv.isDarwin then [ "ctrl+shift+t=new_tab" "ctrl+shift+n=new_split:down" "ctrl+shift+m=new_split:right" "super+shift+k=resize_split:up,20" "super+shift+h=resize_split:left,20" "super+shift+j=resize_split:down,20" "super+shift+l=resize_split:right,20" "ctrl+shift+k=goto_split:up" "ctrl+shift+h=goto_split:left" "ctrl+shift+j=goto_split:down" "ctrl+shift+l=goto_split:right" ] else [ "ctrl+shift+t=new_window" "ctrl+shift+n=new_window" "ctrl+shift+m=new_window" ]; }; }; }; }
-
-
features/home/default.nix (deleted)
-
@@ -1,99 +0,0 @@# Copyright 2023 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # # === # Home Manager stuffs { pkgs, lib, config, ... }: let cfg = config.features.home; in { options.features.home = { useNix = lib.mkOption { type = lib.types.bool; default = true; }; username = lib.mkOption { type = lib.types.nonEmptyStr; description = '' System user name used to login to the machine. ''; }; timezone = lib.mkOption { type = lib.types.nullOr lib.types.nonEmptyStr; default = null; description = '' Machine's timezone. Ideally this should be a mutable machine state considering it being variable property. However, in some environment or program couldn't pick up the value without explicitly specifiying in Nix config. This is to make very sure everything works. ''; }; locale = lib.mkOption { type = lib.types.nullOr lib.types.nonEmptyStr; default = null; description = '' Machine's locale (LC_ALL). e.g. `en_US.UTF-8` ''; }; }; config = let homeDir = if pkgs.stdenv.isDarwin then "/Users" else "/home"; username = cfg.username; in { home = { inherit username; homeDirectory = "${homeDir}/${username}"; # `sessionVariables` does not accept `null` as an attribute value. # Need to manually filter out `null` values. sessionVariables = lib.attrsets.filterAttrs (name: value: value != null) { TZ = cfg.timezone; LC_ALL = cfg.locale; }; }; nix = { package = lib.mkIf cfg.useNix pkgs.nix; extraOptions = '' experimental-features = nix-command flakes warn-dirty = false ''; }; }; }
-
-
features/identity/default.nix (deleted)
-
@@ -1,86 +0,0 @@# Copyright 2023 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD { lib, pkgs, config, ... }: let cfg = config.features.identity; in { options = { features.identity = { name = lib.mkOption { type = lib.types.nullOr lib.types.nonEmptyStr; default = null; description = '' Your name, prefebly publicly distinguishable. ''; }; email = lib.mkOption { type = lib.types.nullOr lib.types.nonEmptyStr; default = null; description = '' Email address. ''; }; gpgSigningKeyId = lib.mkOption { type = lib.types.nullOr lib.types.nonEmptyStr; default = null; description = '' A key ID of a signing key (primary or subkey). This is a **key ID**, which is visible to public. Do not put key signature here. ''; }; }; }; config = { programs = { gpg = { enable = cfg.gpgSigningKeyId != null; }; }; services.gpg-agent = { enable = cfg.gpgSigningKeyId != null && pkgs.stdenv.isLinux; enableFishIntegration = config.programs.fish.enable; enableZshIntegration = config.programs.zsh.enable; # 1day defaultCacheTtl = 86400; defaultCacheTtlSsh = 86400; # 30days maxCacheTtl = 2592000; maxCacheTtlSsh = 2592000; pinentry.package = pkgs.pinentry-curses; }; }; }
-
-
features/scm-server/default.nix (deleted)
-
@@ -1,148 +0,0 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD { pkgs, lib, config, ... }: let cfg = config.features.scm-server; in { options = { features.scm-server = { enable = lib.mkEnableOption "SCMServer"; }; }; config = lib.mkIf cfg.enable { home.packages = [ pkgs.soft-serve pkgs.legit-web ]; xdg.dataFile."soft-serve/config.yaml" = let sshPort = "23231"; sshDomain = "git.pocka.jp"; httpPort = "23232"; httpURL = "https://git.pocka.jp"; in { text = '' name: "git.pocka.jp" log_format: "text" ssh: listen_addr: ":${sshPort}" public_url: "ssh://${sshDomain}:${sshPort}" max_timeout: 0 idle_timeout: 120 http: listen_addr: ":${httpPort}" public_url: "${httpURL}" git: enabled: false db: driver: "sqlite" data_source: "soft-serve.db?_pragma=busy_timeout(5000)&_pragma=foreign_keys(1)" lfs: enabled: false jobs: mirror_pull: "@every 30m" ''; }; systemd.user.services.soft-serve = { Unit = { Description = "Soft Serve, SSH TUI git server."; }; Service = { Type = "simple"; Restart = "always"; RestartSec = 1; ExecStart = "${pkgs.soft-serve}/bin/soft serve"; Environment = "SOFT_SERVE_DATA_PATH=${config.xdg.dataHome}/soft-serve"; WorkingDirectory = "${config.xdg.dataHome}/soft-serve"; }; Install = { WantedBy = [ "default.target" ]; }; }; xdg.configFile."legit/config.yaml" = { # TODO: Remove `readme` once created `README.md` in forked legit. text = '' repo: scanPath: "${config.xdg.dataHome}/soft-serve/repos/x" readme: - "readme" - "README" - "README.md" - "README.adoc" - "README.txt" - "ABOUT" - "ABOUT.md" - "ABOUT.adoc" - "ABOUT.txt" mainBranch: - "master" - "main" dirs: templates: "${pkgs.legit-web}/lib/legit/templates" static: "${pkgs.legit-web}/lib/legit/static" meta: title: "git.pocka.jp" description: "My personal projects" syntaxHighlight: true server: name: "git.pocka.jp" host: "127.0.0.1" port: 5555 ''; }; systemd.user.services.legit = { Unit = { Description = "legit, web frontend for git repositories."; }; Service = { Type = "simple"; Restart = "always"; RestartSec = 1; ExecStart = "${pkgs.legit-web}/bin/legit --config=${config.xdg.configHome}/legit/config.yaml"; Environment = "PATH=$PATH:${lib.makeBinPath [ pkgs.git ]}"; }; Install = { WantedBy = [ "default.target" ]; }; }; }; }
-
-
features/scm/default.nix (deleted)
-
@@ -1,180 +0,0 @@# Copyright 2023 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD { pkgs, lib, config, ... }: let cfg = config.features.scm; in { options = { features.scm = { enable = lib.mkEnableOption "SCM"; }; }; config = lib.mkIf cfg.enable { programs.git = let difftasticConfig = if config.features.dev.enable then { # https://difftastic.wilfred.me.uk/git.html diff = { tool = "difftastic"; }; difftool = { prompt = false; }; "difftool \"difftastic\"" = { cmd = ''difft "$LOCAL" "$REMOTE"''; }; pager = { difftool = true; }; } else { }; in { enable = true; userName = config.features.identity.name; userEmail = config.features.identity.email; signing = lib.mkIf (config.features.identity.gpgSigningKeyId != null) { key = config.features.identity.gpgSigningKeyId; signByDefault = true; }; extraConfig = { core = { editor = if config.programs.neovim.enable then "nvim" else "vim"; }; init = { defaultBranch = "master"; }; # This is turned off by default for compatibility reason. # Essential for working both inside container and on host. worktree.useRelativePaths = true; } // difftasticConfig; ignores = let # # Ignore all bazel-* symlinks. There is no full list since this can change # based on the name of the directory bazel is cloned into. bazel = [ "/bazel-*" ]; # Swap file nvim = if config.programs.neovim.enable then [ ".*.swp" ] else [ ]; # https://github.com/github/gitignore/blob/main/Global/macOS.gitignore darwin = if pkgs.stdenv.isDarwin then [ ".DS_Store" ".AppleDouble" ".LSOverride" ] else [ ]; in nvim ++ darwin ++ bazel; }; # https://github.com/martinvonz/jj programs.jujutsu = { enable = true; settings = { user = { name = config.features.identity.name; email = config.features.identity.email; }; signing = lib.mkIf (config.features.identity.gpgSigningKeyId != null) { behavior = "own"; backend = "gpg"; key = config.features.identity.gpgSigningKeyId; }; ui = lib.mkIf config.features.dev.enable { diff-formatter = [ "difft" "--color=always" "$left" "$right" ]; }; revsets = { log = "all()"; }; git = { private-commits = "description(regex:'\\[WIP\\]')"; }; aliases = { # JJ by default sets incorrect author date (when "a work started" instead of "authored",) # because how it works internally (updating a git commit.) This command is to workaround # that design flaw by manually mark author date, like "git commit". author = [ "desc" "--no-edit" "--reset-author" ]; au = [ "author" ]; }; }; }; home.packages = [ pkgs.fossil ( # Fossil derivation in Nixpkgs install bash completion only, while Fossil provides zsh's one too. # Creating a new derivation is so much effective compared to using `lib.overrideAttrs` because # of build cache. pkgs.stdenv.mkDerivation { pname = "fossil-zsh-completion"; version = pkgs.fossil.version; src = pkgs.fossil.src; phases = [ "unpackPhase" "installPhase" ]; nativeBuildInputs = [ pkgs.installShellFiles ]; installPhase = '' installShellCompletion --zsh --name _fossil tools/fossil-autocomplete.zsh ''; } ) ]; }; }
-
-
features/wayland-de/default.nix (deleted)
-
@@ -1,59 +0,0 @@# Copyright 2023 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # # === # Wayland Desktop Environment { config, lib, pkgs, ... }: { options.features.wayland-de = { enable = lib.mkEnableOption "WaylandDE"; }; imports = [ ./niri.nix ./swaylock.nix ./fcitx5.nix ./my-theme.nix ./dunst.nix ./walker.nix ./waybar.nix ]; config = lib.mkIf config.features.wayland-de.enable { home.packages = [ # https://monaspace.githubnext.com/ pkgs.monaspace # https://www.brailleinstitute.org/freefont/ pkgs.atkinson-hyperlegible-next pkgs.plac ]; home.sessionVariables = { # By default, Firefox and Thunderbird uses X11. # Users need to explicitly set the env (it sucks). MOZ_ENABLE_WAYLAND = "1"; }; features.wayland-de.niri.spawn-at-startup = [ [ "${pkgs.waybar}/bin/waybar" ] ]; }; }
-
-
features/wayland-de/my-theme.nix (deleted)
-
@@ -1,52 +0,0 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD { config, lib, pkgs, ... }: { config = lib.mkIf config.features.wayland-de.enable { home.packages = [ # /programs/theme pkgs.my-theme # Sunwait calculates sunrise or sunset times with civil, nautical, # astronomical and custom twilights, for use with Windows Task Scheduler # or 'cron' on Linux. # https://github.com/risacher/sunwait pkgs.sunwait ]; systemd.user.services.my-theme = { Unit = { Description = "Apply appearance theme based on time"; }; Service = { Type = "simple"; Restart = "always"; RestartSec = 1; ExecStart = "${pkgs.my-theme}/bin/,theme auto --config ${config.xdg.configHome}/my-theme/config.json --daemon --verbose"; }; Install = { WantedBy = [ "default.target" ]; }; }; }; }
-
-
features/wayland-de/niri.nix (deleted)
-
@@ -1,513 +0,0 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD { config, lib, pkgs, ... }: let cfg = config.features.wayland-de.niri; output = lib.types.submodule { options = { name = lib.mkOption { type = lib.types.nonEmptyStr; description = "Display output name, you can obtain from `niri msg outputs`"; }; scale = lib.mkOption { type = lib.types.float; description = "DPI"; default = 1.0; }; }; }; serializeOutput = background-color: o: '' output "${o.name}" { scale ${builtins.toString o.scale} ${ if background-color == null then "//no bg" else "background-color \"${background-color}\"" } } ''; serializeSpawnArg = a: builtins.concatStringsSep " " (builtins.map (s: "\"${s}\"") a); in { options = { features.wayland-de.niri = { enable = lib.mkEnableOption "Niri"; outputs = lib.mkOption { type = lib.types.listOf output; default = [ ]; }; background-color = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; }; input = { keyboard = { repeat-delay = lib.mkOption { type = lib.types.ints.unsigned; default = 200; }; repeat-rate = lib.mkOption { type = lib.types.ints.unsigned; default = 25; }; }; }; spawn-at-startup = lib.mkOption { type = lib.types.listOf (lib.types.listOf lib.types.nonEmptyStr); description = '' `spawn-at-startup` accepts a path to the program binary as the first argument, followed by arguments to the program. Note that running niri as a systemd session supports xdg-desktop-autostart out of the box, which may be more convenient to use. Thanks to this, apps that you configured to autostart in GNOME will also "just work" in niri, without any manual `spawn-at-startup` configuration. ''; default = [ ]; }; overview = { backdrop-color = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; }; }; layout = { gaps = lib.mkOption { type = lib.types.ints.unsigned; description = "Set gaps around windows in logical pixels."; default = 16; }; center-focused-column = lib.mkOption { type = lib.types.enum [ "never" "always" "on-overflow" ]; description = '' When to center a column when changing focus, options are: - "never", default behavior, focusing an off-screen column will keep at the left or right edge of the screen. - "always", the focused column will always be centered. - "on-overflow", focusing a column will center it if it doesn't fit together with the previously focused column. ''; default = "never"; }; focus-ring = { width = lib.mkOption { type = lib.types.ints.unsigned; description = "How many logical pixels the ring extends out from the windows."; default = 3; }; active-color = lib.mkOption { type = lib.types.nonEmptyStr; description = '' Color of the ring on the active monitor. Colors can be set in a variety of ways: - CSS named colors: "red" - RGB hex: "#rgb", "#rgba", "#rrggbb", "#rrggbbaa" - CSS-like notation: "rgb(255, 127, 0)", rgba(), hsl() and a few others. You can also use gradients. They take precedence over solid colors. Gradients are rendered the same as CSS linear-gradient(angle, from, to). The angle is the same as in linear-gradient, and is optional, defaulting to 180 (top-to-bottom gradient). You can use any CSS linear-gradient tool on the web to set these up. Changing the color space is also supported, check the wiki for more info. active-gradient from="#80c8ff" to="#bbddff" angle=45 You can also color the gradient relative to the entire view of the workspace, rather than relative to just the window itself. To do that, set relative-to="workspace-view". inactive-gradient from="#505050" to="#808080" angle=45 relative-to="workspace-view" ''; default = "#7fc8ff"; }; inactive-color = lib.mkOption { type = lib.types.nonEmptyStr; description = '' Color of the ring on inactive monitors. Colors can be set in a variety of ways: - CSS named colors: "red" - RGB hex: "#rgb", "#rgba", "#rrggbb", "#rrggbbaa" - CSS-like notation: "rgb(255, 127, 0)", rgba(), hsl() and a few others. You can also use gradients. They take precedence over solid colors. Gradients are rendered the same as CSS linear-gradient(angle, from, to). The angle is the same as in linear-gradient, and is optional, defaulting to 180 (top-to-bottom gradient). You can use any CSS linear-gradient tool on the web to set these up. Changing the color space is also supported, check the wiki for more info. active-gradient from="#80c8ff" to="#bbddff" angle=45 You can also color the gradient relative to the entire view of the workspace, rather than relative to just the window itself. To do that, set relative-to="workspace-view". inactive-gradient from="#505050" to="#808080" angle=45 relative-to="workspace-view" ''; default = "#505050"; }; }; border = { width = lib.mkOption { type = lib.types.ints.unsigned; description = "How many logical pixels the ring extends out from the windows."; default = 3; }; active-color = lib.mkOption { type = lib.types.nonEmptyStr; description = '' Color of the border on the active monitor. Colors can be set in a variety of ways: - CSS named colors: "red" - RGB hex: "#rgb", "#rgba", "#rrggbb", "#rrggbbaa" - CSS-like notation: "rgb(255, 127, 0)", rgba(), hsl() and a few others. You can also use gradients. They take precedence over solid colors. Gradients are rendered the same as CSS linear-gradient(angle, from, to). The angle is the same as in linear-gradient, and is optional, defaulting to 180 (top-to-bottom gradient). You can use any CSS linear-gradient tool on the web to set these up. Changing the color space is also supported, check the wiki for more info. active-gradient from="#80c8ff" to="#bbddff" angle=45 You can also color the gradient relative to the entire view of the workspace, rather than relative to just the window itself. To do that, set relative-to="workspace-view". inactive-gradient from="#505050" to="#808080" angle=45 relative-to="workspace-view" ''; default = "#7fc8ff"; }; inactive-color = lib.mkOption { type = lib.types.nonEmptyStr; description = '' Color of the border on inactive monitors. Colors can be set in a variety of ways: - CSS named colors: "red" - RGB hex: "#rgb", "#rgba", "#rrggbb", "#rrggbbaa" - CSS-like notation: "rgb(255, 127, 0)", rgba(), hsl() and a few others. You can also use gradients. They take precedence over solid colors. Gradients are rendered the same as CSS linear-gradient(angle, from, to). The angle is the same as in linear-gradient, and is optional, defaulting to 180 (top-to-bottom gradient). You can use any CSS linear-gradient tool on the web to set these up. Changing the color space is also supported, check the wiki for more info. active-gradient from="#80c8ff" to="#bbddff" angle=45 You can also color the gradient relative to the entire view of the workspace, rather than relative to just the window itself. To do that, set relative-to="workspace-view". inactive-gradient from="#505050" to="#808080" angle=45 relative-to="workspace-view" ''; default = "#505050"; }; }; struts = { left = lib.mkOption { type = lib.types.int; description = '' Struts shrink the area occupied by windows, similarly to layer-shell panels. You can think of them as a kind of outer gaps. They are set in logical pixels. Left and right struts will cause the next window to the side to always be visible. ''; default = 0; }; right = lib.mkOption { type = lib.types.int; description = '' Struts shrink the area occupied by windows, similarly to layer-shell panels. You can think of them as a kind of outer gaps. They are set in logical pixels. Left and right struts will cause the next window to the side to always be visible. ''; default = 0; }; top = lib.mkOption { type = lib.types.int; description = '' Struts shrink the area occupied by windows, similarly to layer-shell panels. You can think of them as a kind of outer gaps. They are set in logical pixels. Top and bottom struts will simply add outer gaps in addition to the area occupied by layer-shell panels and regular gaps. ''; default = 0; }; bottom = lib.mkOption { type = lib.types.int; description = '' Struts shrink the area occupied by windows, similarly to layer-shell panels. You can think of them as a kind of outer gaps. They are set in logical pixels. Top and bottom struts will simply add outer gaps in addition to the area occupied by layer-shell panels and regular gaps. ''; default = 0; }; }; }; prefer-no-csd = lib.mkOption { type = lib.types.bool; description = '' Ask the clients to omit their client-side decorations if possible. If the client will specifically ask for CSD, the request will be honored. Additionally, clients will be informed that they are tiled, removing some client-side rounded corners. This option will also fix border/focus ring drawing behind some semitransparent windows. After enabling or disabling this, you need to restart the apps for this to take effect. ''; default = true; }; screenshot-path = lib.mkOption { type = lib.types.nonEmptyStr; description = '' You can change the path where screenshots are saved. A ~ at the front will be expanded to the home directory. The path is formatted with strftime(3) to give you the screenshot date and time. ''; default = "~/Pictures/Screenshots/Screenshot from %Y-%m-%d %H-%M-%S.png"; }; window-rule-all = { corner-radius = lib.mkOption { type = lib.types.ints.unsigned; default = 8; }; }; hotkey-overlay = { skip-at-startup = lib.mkOption { type = lib.types.bool; default = true; }; }; }; }; config = lib.mkIf config.features.wayland-de.enable { xdg.configFile."niri/config.kdl" = { # https://github.com/YaLTeR/niri/wiki/Configuration:-Overview text = '' input { keyboard { repeat-delay ${builtins.toString cfg.input.keyboard.repeat-delay} repeat-rate ${builtins.toString cfg.input.keyboard.repeat-rate} } // This section includes libinput settings. // Omitting settings disables them, or leaves them at their default values. touchpad { natural-scroll accel-speed 0.2 accel-profile "adaptive" scroll-method "two-finger" scroll-factor 0.3 click-method "clickfinger" } } ${lib.strings.concatStringsSep "\n" ( builtins.map (serializeOutput cfg.background-color) cfg.outputs )} overview { ${ if cfg.overview.backdrop-color != null then "backdrop-color \"${cfg.overview.backdrop-color}\"" else "// No backdrop-color" } workspace-shadow { off } } layout { gaps ${builtins.toString cfg.layout.gaps} center-focused-column "${cfg.layout.center-focused-column}" preset-column-widths { // Proportion sets the width as a fraction of the output width, taking gaps into account. // For example, you can perfectly fit four windows sized "proportion 0.25" on an output. // The default preset widths are 1/3, 1/2 and 2/3 of the output. proportion 0.25 proportion 0.5 proportion 0.75 } preset-window-heights { proportion 0.25 proportion 0.5 proportion 0.75 } // You can change the default width of the new windows. // If you leave the brackets empty, the windows themselves will decide their initial width. default-column-width { proportion 0.5 } focus-ring { width ${builtins.toString cfg.layout.focus-ring.width} active-color "${cfg.layout.focus-ring.active-color}" inactive-color "${cfg.layout.focus-ring.inactive-color}" } border { width ${builtins.toString cfg.layout.border.width} active-color "${cfg.layout.border.active-color}" inactive-color "${cfg.layout.border.inactive-color}" } shadow { on softness 40 spread 5 } struts { left ${builtins.toString cfg.layout.struts.left} right ${builtins.toString cfg.layout.struts.right} top ${builtins.toString cfg.layout.struts.top} bottom ${builtins.toString cfg.layout.struts.bottom} } } ${if cfg.prefer-no-csd then "" else "//"}prefer-no-csd screenshot-path "${cfg.screenshot-path}" animations { } // Open the Firefox picture-in-picture player as floating by default. window-rule { // This app-id regular expression will work for both: // - host Firefox (app-id is "firefox") // - Flatpak Firefox (app-id is "org.mozilla.firefox") match app-id=r#"firefox$"# title="^Picture-in-Picture$" open-floating true } window-rule { match app-id="^com\\.mitchellh\\.ghostty$" default-column-width { proportion 0.25 } } // Enable rounded corners for all windows. window-rule { geometry-corner-radius ${builtins.toString cfg.window-rule-all.corner-radius} clip-to-geometry true } hotkey-overlay { ${if cfg.hotkey-overlay.skip-at-startup then "" else "//"}skip-at-startup } ${builtins.concatStringsSep "\n" ( builtins.map (a: "spawn-at-startup ${serializeSpawnArg a}") cfg.spawn-at-startup )} binds { Mod+Shift+Slash { show-hotkey-overlay; } Mod+T { spawn "${config.lib.nixGL.wrap pkgs.ghostty}/bin/ghostty" "--working-directory=home"; } Mod+X { spawn "swaylock"; } Mod+Q { close-window; } Mod+Space { spawn "${pkgs.walker}/bin/walker" "--modules" "applications,commands,calc,power"; } Mod+H { focus-column-left; } Mod+J { focus-window-down-or-column-right; } Mod+K { focus-window-up-or-column-left; } Mod+L { focus-column-right; } Mod+Ctrl+H { move-column-left; } Mod+Ctrl+J { consume-or-expel-window-left; } Mod+Ctrl+K { consume-or-expel-window-right; } Mod+Ctrl+L { move-column-right; } Mod+U { focus-workspace-down; } Mod+I { focus-workspace-up; } Mod+Ctrl+U { move-column-to-workspace-down; } Mod+Ctrl+I { move-column-to-workspace-up; } Mod+BracketLeft { consume-or-expel-window-left; } Mod+BracketRight { consume-or-expel-window-right; } Mod+Comma { consume-window-into-column; } Mod+Period { expel-window-from-column; } Mod+R { switch-preset-column-width; } Mod+Shift+R { switch-preset-window-height; } Mod+Ctrl+R { reset-window-height; } Mod+F { maximize-column; } Mod+Shift+F { fullscreen-window; } Mod+C { center-column; } Mod+Minus { set-column-width "-10%"; } Mod+Equal { set-column-width "+10%"; } Mod+Shift+Minus { set-window-height "-10%"; } Mod+Shift+Equal { set-window-height "+10%"; } Mod+V { toggle-window-floating; } Mod+Shift+V { switch-focus-between-floating-and-tiling; } Mod+Shift+E { quit; } Ctrl+Alt+Delete { quit; } Mod+Shift+P { power-off-monitors; } } ''; }; }; }
-
-
features/wayland-de/walker/config.toml (deleted)
-
@@ -1,123 +0,0 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD close_when_open = true theme = "nix" as_window = false disable_click_to_close = false force_keyboard_focus = true [keys] accept_typeahead = ["tab"] trigger_labels = "ralt" next = ["down"] prev = ["up"] close = ["esc"] remove_from_history = ["shift backspace"] [list] dynamic_sub = true max_entries = 50 show_initial_entries = true single_click = true visibility_threshold = 20 placeholder = "No Results" [search] argument_delimiter = "#" placeholder = "Search..." delay = 0 [activation_mode] disabled = true [builtins.applications] weight = 5 name = "applications" placeholder = "Applications" prioritize_new = true hide_actions_with_empty_query = true refresh = true show_sub_when_single = true show_icon_when_single = true show_generic = true history = true [builtins.applications.actions] enabled = true hide_category = false hide_without_query = true [builtins.calc] require_number = true weight = 5 name = "calc" icon = "accessories-calculator" placeholder = "Calculator" [builtins.commands] weight = 5 icon = "utilities-terminal" name = "commands" placeholder = "Commands" [builtins.custom_commands] weight = 5 icon = "utilities-terminal" name = "custom_commands" placeholder = "Custom Commands" [[plugins]] keep_sort = false name = "power" placeholder = "Power" recalculate_score = true show_icon_when_single = true switcher_only = false [[plugins.entries]] exec = "shutdown now" icon = "system-shutdown" label = "Shutdown" [[plugins.entries]] exec = "reboot" icon = "system-reboot" label = "Reboot" [[plugins.entries]] exec = "niri msg action power-off-monitors && swaylock" icon = "system-lock-screen" label = "Lock Screen" # Exclude bloat binaries, which package is installed as a dependency but # the package places binary instead of / in addition to library file. [[builtins.applications.blacklist]] regexp = "Avahi\\s.*" [[builtins.applications.blacklist]] regexp = "Electron\\s+\\d+" [[builtins.applications.blacklist]] regexp = "lstopo" [[builtins.applications.blacklist]] regexp = "Vifm" [[builtins.applications.blacklist]] regexp = "Vim" [[builtins.applications.blacklist]] regexp = "Qt\\s.*[Uu]tility"
-
-
features/wayland-de/walker/theme.toml (deleted)
-
@@ -1,91 +0,0 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD [ui.anchors] bottom = true left = true right = true top = true [ui.window] h_align = "fill" v_align = "fill" [ui.window.box] h_align = "center" width = 800 [ui.window.box.bar] orientation = "horizontal" position = "end" [ui.window.box.bar.entry] h_align = "fill" h_expand = true [ui.window.box.bar.entry.icon] h_align = "center" h_expand = true pixel_size = 24 theme = "" [ui.window.box.margins] top = 400 [ui.window.box.scroll.list] marker_color = "var(--accent-foreground-color)" max_height = 500 [ui.window.box.scroll.list.item.activation_label] h_align = "fill" v_align = "fill" width = 20 x_align = 0.5 y_align = 0.5 [ui.window.box.scroll.list.item] spacing = 6 [ui.window.box.scroll.list.item.icon] pixel_size = 26 theme = "" [ui.window.box.scroll.list.margins] top = 8 [ui.window.box.search] spacing = 4 [ui.window.box.search.prompt] name = "prompt" icon = "edit-find-symbolic" pixel_size = 18 h_align = "center" v_align = "center" [ui.window.box.search.clear] name = "clear" icon = "edit-clear-symbolic" pixel_size = 18 h_align = "center" v_align = "center" [ui.window.box.search.input] h_align = "fill" h_expand = true icons = true [ui.window.box.search.spinner] hide = true
-
-
features/wayland-de/waybar.nix (deleted)
-
@@ -1,69 +0,0 @@# Copyright 2023 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD { config, lib, pkgs, ... }: { config = lib.mkIf config.features.wayland-de.enable { home.packages = [ # /programs/waybar-text pkgs.my-waybar-text ]; programs = { waybar = { enable = true; settings = { main = { layer = "top"; modules-left = [ "custom/todo" ]; modules-right = [ "clock" "pulseaudio" "tray" ]; clock = { # waybar can't read $TZ. Maybe a bug with Nix environment? timezone = config.features.home.timezone; locale = config.features.home.locale; format = "{:%Y-%m-%d %H:%M}"; }; pulseaudio = { format = "{icon} {volume}% / {format_source}"; format-muted = "muted {format_source}"; on-click = "pavucontrol"; }; "custom/todo" = { exec = "${pkgs.my-waybar-text}/bin/,waybar-text --trim-md-list ${config.xdg.dataHome}/todo.md"; restart-interval = 10; return-type = "json"; escape = true; }; }; }; }; }; }; }
-
-
-
@@ -115,6 +115,21 @@"type": "github" } }, "nix-colorizer": { "locked": { "lastModified": 1750078528, "narHash": "sha256-NuGAJx61f/r0xrpyOTUEsO+MDNpso0qE99k2/apv3as=", "owner": "nutsalhan87", "repo": "nix-colorizer", "rev": "c9ce6c710f4ed749f773104a8092a3e542dd1d7c", "type": "github" }, "original": { "owner": "nutsalhan87", "repo": "nix-colorizer", "type": "github" } }, "nixgl": { "inputs": { "flake-utils": "flake-utils_2",
-
@@ -192,6 +207,7 @@"inputs": { "home-manager": "home-manager", "mac-app-util": "mac-app-util", "nix-colorizer": "nix-colorizer", "nixgl": "nixgl", "nixpkgs": "nixpkgs_2", "plac": "plac"
-
-
-
@@ -34,6 +34,8 @@inputs.nixpkgs.follows = "nixpkgs"; }; nix-colorizer.url = "github:nutsalhan87/nix-colorizer"; plac = { url = "git+https://codeberg.org/pocka/plac-for-gtk4.git"; inputs.nixpkgs.follows = "nixpkgs";
-
@@ -47,6 +49,7 @@home-manager, mac-app-util, nixgl, nix-colorizer, plac, }: let
-
@@ -56,8 +59,6 @@system, # Machine specific module setting module ? { }, # Color theme theme ? ./themes/catppuccin, }: home-manager.lib.homeManagerConfiguration rec { pkgs = import nixpkgs {
-
@@ -65,83 +66,14 @@overlays = [ (import ./overlays/legit.nix) (import ./overlays/atkinson-hyperlegible-next.nix) # Local packages (final: prev: { my-theme = prev.callPackage ./programs/theme { }; my-waybar-text = prev.callPackage ./programs/waybar-text { }; my-workerbee = prev.callPackage ./programs/workerbee { }; plac = plac.packages."${system}".default; }) # Flake packages (final: prev: { plac = plac.packages."${system}".default; }) ]; }; modules = [ # Fix Home-Manager on MacOS cannot register GUI applications and Spotlight # won't find those applications. mac-app-util.homeManagerModules.default ./features ( { config, ... }: rec { # Turn off Home Manager news bs news.display = "silent"; home.stateVersion = "23.11"; # One of: "latte", "frappe", "macchiato", "mocha" themes.catppuccin.flavor = module.themes.catppuccin.flavor or "mocha"; home.packages = [ pkgs.home-manager (pkgs.callPackage ./programs/hm-clean { }) ]; features = nixpkgs.lib.mkDefault { identity = { name = "Shota FUJI"; email = "pockawoooh@gmail.com"; gpgSigningKeyId = "5E5148973E291363"; }; data.enable = true; scm.enable = true; syncthing.enable = true; home = { username = "pocka"; timezone = "Asia/Tokyo"; locale = "en_US.UTF-8"; }; modules = [ module ]; dev = { enable = true; lsp = { enable = true; langs = with config.features.dev.lsp; [ elm typescript deno go css html zig gleam swift ]; }; }; wayland-de = { ime.enable = true; }; }; } ) module theme ]; extraSpecialArgs = { inherit nix-colorizer mac-app-util nixgl; }; }; availableSystems = [
-
@@ -153,88 +85,27 @@homeConfigurations = { dev-linux = mkHomeConfiguration { system = "x86_64-linux"; module = { pkgs, ... }: { home.packages = with pkgs; [ pkgs.my-workerbee ]; features.wayland-de.enable = true; features.gui.enable = true; nixGL.packages = nixgl.packages; nixGL.defaultWrapper = "mesa"; nixGL.installScripts = [ "mesa" ]; features.wayland-de.niri.outputs = [ { name = "HDMI-A-1"; scale = 1.4; } ]; }; }; pixelbook = mkHomeConfiguration { system = "x86_64-linux"; module = { features.home.username = "pockawoooh"; # ChromeOS has neither tiling wm nor useful terminal emulator programs.tmux.enable = true; }; module = ./modules/hm/profiles/linux-desktop.nix; }; scm-server = mkHomeConfiguration { git-server = mkHomeConfiguration { system = "x86_64-linux"; module = { # Basically controlled over SSH programs.tmux.enable = true; # This server acts as a remote and only occasion commits are made on the server # is when fossil generates git repository on mirror (manual/automatic). features.identity.gpgSigningKeyId = null; features.dev.enable = false; features.scm-server.enable = true; # This server is only accessible via Wireguard. services.syncthing.guiAddress = "[fd33::1]:8384"; }; module = ./modules/hm/profiles/git-server.nix; }; mbp-m1 = mkHomeConfiguration { system = "aarch64-darwin"; module = { features.gui.enable = true; }; module = ./modules/hm/profiles/macos.nix; }; macmini-m1 = mkHomeConfiguration { system = "aarch64-darwin"; module = { features.gui.enable = true; }; module = ./modules/hm/profiles/macos.nix; }; workerbee = mkHomeConfiguration { system = "x86_64-linux"; module = { pkgs, ... }: { home.packages = with pkgs; [ ghostty.terminfo ]; features.home.username = "workerbee"; # Isolated container should not have access to signing key. features.identity.gpgSigningKeyId = null; features.syncthing.enable = false; # Host have to bind wayland socket at /mnt/wayland-0 to allow the # container to run graphical applications. home.sessionVariables.WAYLAND_DISPLAY = "/mnt/wayland-0"; }; module = ./modules/hm/profiles/workerbee.nix; }; };
-
@@ -257,10 +128,7 @@environment.systemPackages = with pkgs; [ neovim ]; programs.fish = { enable = true; }; programs.fish.enable = true; users.defaultUserShell = pkgs.fish; users.users = {
-
@@ -270,58 +138,7 @@}; }; home-manager.users.workerbee = { imports = [ ./features ( { config, pkgs, ... }: { home.stateVersion = "23.11"; # Host have to bind wayland socket at /mnt/wayland-0 # to allow the container to run graphical applications. home.sessionVariables.WAYLAND_DISPLAY = "/mnt/wayland-0"; home.packages = with pkgs; [ ghostty.terminfo ]; features = pkgs.lib.mkDefault { identity = { name = "Shota FUJI"; email = "pockawoooh@gmail.com"; }; scm.enable = true; home = { username = "workerbee"; timezone = "Asia/Tokyo"; locale = "en_US.UTF-8"; useNix = false; }; dev = { enable = true; lsp = { enable = true; langs = with config.features.dev.lsp; [ elm typescript deno go css html zig gleam ]; }; }; }; } ) ]; }; home-manager.users.workerbee = ./modules/hm/profiles/workerbee.nix; } ) ];
-
@@ -373,10 +190,9 @@name = system; value = pkgs.mkShell { packages = with pkgs; [ sunwait tzdata glib reuse zig zls go dprint nixfmt-rfc-style
-
-
-
@@ -0,0 +1,19 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD { ... }: { imports = [ ./plac.nix ]; }
-
-
-
@@ -0,0 +1,24 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # # > Unofficial Roon client (Roon Remote) using GTK4 and LibAdwaita # https://codeberg.org/pocka/plac-for-gtk4 { pkgs, lib, ... }: { config = { home.packages = with pkgs; lib.mkIf pkgs.stdenv.isLinux [ plac ]; }; }
-
-
-
@@ -0,0 +1,23 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD { ... }: { config = { programs.chromium = { enable = true; }; }; }
-
-
-
@@ -0,0 +1,22 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD { ... }: { imports = [ ./chromium.nix ./firefox.nix ]; }
-
-
-
@@ -1,4 +1,4 @@# Copyright 2023 Shota FUJI <pockawoooh@gmail.com> # Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted.
-
@@ -13,26 +13,22 @@# # SPDX-License-Identifier: 0BSD { pkgs, lib, ... }: { config, lib, pkgs, ... }: { services = lib.mkIf config.features.wayland-de.enable { dunst = { config = { programs.firefox = { enable = true; settings = { global = { follow = "keyboard"; languagePacks = [ "en-US" "ja" ]; }; mouse_left_click = "do_action"; mouse_middle_click = "close_current"; mouse_right_click = "context"; }; }; home.sessionVariables = lib.mkIf pkgs.stdenv.isLinux { # By default, Firefox and Thunderbird uses X11. # Users need to explicitly set the env (it sucks). MOZ_ENABLE_WAYLAND = "1"; }; }; }
-
-
-
@@ -0,0 +1,19 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD { ... }: { imports = [ ./neovim.nix ]; }
-
-
-
@@ -1,4 +1,4 @@# Copyright 2023 Shota FUJI <pockawoooh@gmail.com> # Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted.
-
@@ -20,8 +20,6 @@... }: let cfg = config.features.dev.lsp; ls = lib.types.submodule { options = { cmd = lib.mkOption {
-
@@ -105,27 +103,12 @@ letin { options = { features.dev.lsp = { enable = lib.mkEnableOption "LSP"; langs = lib.mkOption { type = lib.types.listOf ls; default = [ ]; }; elm = lib.mkOption { type = ls; default = { name = "elmls"; }; }; development.neovim.language-servers = lib.mkOption { type = lib.types.listOf ls; typescript = lib.mkOption { type = ls; default = { default = [ { name = "elmls"; } { name = "ts_ls"; rootMarkers = [ "tsconfig.json" ]; initOptions = ''
-
@@ -135,13 +118,8 @@ inautoImportFileExcludePatterns = { "**" }, } ''; }; }; deno = lib.mkOption { type = ls; default = { } { name = "denols"; rootMarkers = [ "deno.json"
-
@@ -154,21 +132,9 @@ in} } ''; }; }; go = lib.mkOption { type = ls; default = { name = "gopls"; }; }; css = lib.mkOption { type = ls; default = { } { name = "gopls"; } { name = "cssls"; singleFileSupport = true; initOptions = ''
-
@@ -179,96 +145,54 @@ invalidate = false } ''; }; }; html = lib.mkOption { type = ls; default = { } { name = "html"; singleFileSupport = true; }; }; zig = lib.mkOption { type = ls; default = { cmd = [ "zls" "--config-path" "${config.xdg.configHome}/zls.json" ]; } { name = "zls"; }; }; gleam = lib.mkOption { type = ls; default = { initOptions = '' enable_snippets = false, enable_argument_placeholders = false, ''; } { name = "gleam"; # nvim-lspconfig incorrectly have ".git" in the default root_markers. rootMarkers = [ "gleam.toml" ]; }; }; swift = lib.mkOption { type = ls; default = { name = "sourcekit"; }; }; } { name = "sourcekit"; } ]; }; }; config = { programs = lib.mkIf (config.features.dev.enable && cfg.enable) { neovim = lib.mkIf config.programs.neovim.enable { plugins = with pkgs.vimPlugins; [ { plugin = mini-completion; type = "lua"; config = builtins.readFile ./neovim/mini-completion.lua; } { plugin = nvim-lspconfig; type = "lua"; config = builtins.concatStringsSep "\n" ( [ '' -- Based on https://github.com/neovim/nvim-lspconfig#suggested-configuration local lspconfig = require("lspconfig") '' ] ++ (builtins.map lsToSetupStmt cfg.langs) ++ [ (builtins.readFile ./neovim/lspconfig.lua) ] ); } { plugin = luasnip; } ]; }; }; home.packages = [ (lib.mkIf (builtins.elem cfg.zig cfg.langs) pkgs.zls) (lib.mkIf (!pkgs.stdenv.isDarwin) pkgs.sourcekit-lsp) programs.neovim.plugins = with pkgs.vimPlugins; [ { plugin = vim-fugitive; } { plugin = mini-completion; type = "lua"; config = builtins.readFile ./neovim/mini-completion.lua; } { plugin = nvim-lspconfig; type = "lua"; config = builtins.concatStringsSep "\n" ( [ '' -- Based on https://github.com/neovim/nvim-lspconfig#suggested-configuration local lspconfig = require("lspconfig") '' ] ++ (builtins.map lsToSetupStmt config.development.neovim.language-servers) ++ [ (builtins.readFile ./neovim/lspconfig.lua) ] ); } { plugin = luasnip; } ]; # zls, the Zig Language Server does not support LSP's initializationOptions # but their own JSON config file. xdg.configFile."zls.json" = { enable = builtins.elem cfg.zig cfg.langs; text = builtins.toJSON { enable_snippets = false; enable_argument_placeholders = false; }; }; }; }
-
-
-
-
-
@@ -0,0 +1,25 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # # Data viewing / manipulation softwares. { ... }: { config = { # > jq is a lightweight and flexible command-line JSON processor. # https://jqlang.org/ programs.jq.enable = true; }; }
-
-
-
@@ -0,0 +1,28 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # # Generic softwares for daily usage and basic system administration. { ... }: { imports = [ ./data.nix ./file-system.nix ./text-editing ./shell.nix ./network.nix ./monitor.nix ]; }
-
-
-
@@ -0,0 +1,53 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # # Softwares for file system operation. { config, pkgs, ... }: { config = { home.packages = with pkgs; [ # > Command to produce a depth indented directory listing pkgs.tree ]; programs = { # A modern replacement for ls (fork of exa). # https://eza.rocks/ eza = { enable = true; # Enable recommended exa aliases (ls, ll…). enableBashIntegration = config.programs.bash.enable; enableFishIntegration = config.programs.fish.enable; enableZshIntegration = config.programs.zsh.enable; extraOptions = [ "--long" "--all" ]; }; # > ripgrep recursively searches directories for a regex pattern while respecting your gitignore # https://github.com/BurntSushi/ripgrep ripgrep = { enable = true; # Ripgrep by default does not sort the result, which results in inconsistent order between runs. arguments = [ "--sort=path" ]; }; }; }; }
-
-
-
@@ -0,0 +1,28 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # # System monitoring tools. { pkgs, ... }: { config = { # `top` alternative. # > Interactive process viewer # https://htop.dev/ programs.htop = { enable = true; }; }; }
-
-
-
@@ -0,0 +1,27 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # # Network utilities. { pkgs, ... }: { config = { home.packages = with pkgs; [ # > command line tool and library for transferring data with URLs # https://curl.se/ curl ]; }; }
-
-
-
@@ -1,4 +1,4 @@# Copyright 2024 Shota FUJI <pockawoooh@gmail.com> # Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted.
-
@@ -12,19 +12,19 @@# PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # # Shell utilities. { config, pkgs, ... }: { programs = { config = { # Replacement for a shell history which records additional commands context atuin = { programs.atuin = { enable = true; enableBashIntegration = false; enableFishIntegration = true; enableNushellIntegration = true; enableZshIntegration = true; enableBashIntegration = config.programs.bash.enable; enableFishIntegration = config.programs.fish.enable; enableZshIntegration = config.programs.zsh.enable; settings = { auto_sync = false;
-
@@ -42,5 +42,11 @@inline_height = 0; }; }; home.packages = with pkgs; [ # A tool to fix `nix-shell` and `nix develop` forcibly using bash # https://github.com/MercuryTechnologies/nix-your-shell nix-your-shell ]; }; }
-
-
-
@@ -0,0 +1,31 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # # Install GNU Aspell, an Open Source spell checker. { pkgs, ... }: { config = { home.packages = [ # > Spell checker for many languages (pkgs.aspellWithDicts ( dicts: with dicts; [ en en-computers ] )) ]; }; }
-
-
-
@@ -0,0 +1,26 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # # Basic text editing tools and configs. This module does not contain development # specific configurations, such as LSP. { ... }: { imports = [ ./aspell.nix ./editorconfig.nix ./neovim.nix ]; }
-
-
-
@@ -0,0 +1,41 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # # System-wide editorconfig settings. { ... }: { config = { editorconfig = { enable = true; settings = { "*" = { charset = "utf-8"; end_of_line = "lf"; insert_final_newline = true; indent_style = "tab"; indent_size = 2; }; # Inaccessible file formats that insists on space indentation. "*.{yaml,yml}" = { indent_style = "space"; indent_size = 2; }; }; }; }; }
-
-
-
@@ -1,4 +1,4 @@# Copyright 2023 Shota FUJI <pockawoooh@gmail.com> # Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted.
-
@@ -12,9 +12,6 @@# PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # # === # Development related configurations { config,
-
@@ -23,10 +20,6 @@... }: let cfg = config.features.dev; toml = pkgs.formats.toml { }; tsVala = pkgs.fetchgit { url = "https://codeberg.org/pocka/tree-sitter-vala"; rev = "093d98428caa4a6fe8b873fb508b022b33fd7f48";
-
@@ -38,22 +31,50 @@ let); in { options = { features.dev = { enable = lib.mkEnableOption "Development"; }; }; config = { programs = { neovim = { enable = true; imports = [ ./lsp.nix ]; defaultEditor = true; config = { programs = lib.mkIf cfg.enable { # dev tools, env vars, task runner (asdf-plugin compatible) # https://github.com/jdx/mise mise.enable = true; withPython3 = false; withRuby = false; extraLuaConfig = builtins.readFile ./neovim/basic.lua; neovim = lib.mkIf config.programs.neovim.enable { plugins = with pkgs.vimPlugins; [ plenary-nvim { plugin = zen-mode-nvim; type = "lua"; config = builtins.readFile ./neovim/zen-mode.lua; } { plugin = nvim-tree-lua; type = "lua"; config = builtins.readFile ./neovim/nvim-tree.lua; } { plugin = telescope-nvim; type = "lua"; config = builtins.readFile ./neovim/telescope.lua; } { plugin = telescope-file-browser-nvim; type = "lua"; config = builtins.readFile ./neovim/telescope-file-browser.lua; } { plugin = indent-blankline-nvim; type = "lua"; config = builtins.readFile ./neovim/indent-blankline.lua; } { plugin = lualine-nvim; type = "lua"; config = builtins.readFile ./neovim/lualine.lua; } { plugin = nvim-treesitter.grammarToPlugin ( pkgs.tree-sitter.buildGrammar {
-
@@ -81,53 +102,19 @@ intype = "lua"; config = '' require("nvim-treesitter.configs").setup { auto_install = false, highlight = { enable = true, additional_vim_regex_highlighting = false, }, } ''; config = builtins.readFile ./neovim/nvim-treesitter.lua; } { plugin = vim-flatbuffers; } { plugin = vim-fugitive; } ]; }; }; # home-manager puts global config to `.config/mise/config.toml`, which # mise writes to on `mise settings` command. xdg.configFile."mise/conf.d/immutable.toml" = lib.mkIf cfg.enable { source = toml.generate "mise-settings" { settings = { idiomatic_version_file_enable_tools = [ "bazel" "node" ]; }; }; xdg.configFile."nvim-treesitter-overrides/queries/vala/highlights.scm" = { source = tsVala + "/queries/highlights.scm"; }; # Have to explicitly disable default highlight query. # https://github.com/nvim-treesitter/nvim-treesitter/issues/3146 xdg.configFile."nvim-treesitter-overrides/queries/vala/highlights.scm" = lib.mkIf cfg.enable { source = tsVala + "/queries/highlights.scm"; }; xdg.configFile."nvim-treesitter-overrides/queries/vala/locals.scm" = lib.mkIf cfg.enable { xdg.configFile."nvim-treesitter-overrides/queries/vala/locals.scm" = { source = tsVala + "/queries/locals.scm"; }; home.packages = lib.mkIf cfg.enable [ # a structural diff tool that understands syntax # https://difftastic.wilfred.me.uk/ pkgs.difftastic # A tool for compliance with the REUSE Initiative recommendations # https://reuse.software/tutorial/ pkgs.reuse ]; }; }
-
-
-
features/basics/neovim/indent-blankline.lua > modules/hm/essentials/text-editing/neovim/indent-blankline.lua
-
-
-
-
@@ -0,0 +1,22 @@-- Copyright 2025 Shota FUJI <pockawoooh@gmail.com> -- -- Permission to use, copy, modify, and/or distribute this software for any -- purpose with or without fee is hereby granted. -- -- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -- PERFORMANCE OF THIS SOFTWARE. -- -- SPDX-License-Identifier: 0BSD require("nvim-treesitter.configs").setup({ auto_install = false, highlight = { enable = true, additional_vim_regex_highlighting = false, }, })
-
-
features/basics/neovim/telescope-file-browser.lua > modules/hm/essentials/text-editing/neovim/telescope-file-browser.lua
-
-
-
-
@@ -0,0 +1,24 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD { pkgs, ... }: { config = { home.packages = [ # https://www.brailleinstitute.org/freefont/ pkgs.atkinson-hyperlegible-next ]; }; }
-
-
-
@@ -0,0 +1,22 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD { ... }: { imports = [ ./monaspace.nix ./atkinson-hyperlegible-next.nix ]; }
-
-
-
@@ -1,4 +1,4 @@# Copyright 2023 Shota FUJI <pockawoooh@gmail.com> # Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted.
-
@@ -13,23 +13,12 @@# # SPDX-License-Identifier: 0BSD { pkgs, ... }: { config, lib, pkgs, ... }: { options = { features.gui.enable = lib.mkEnableOption "GUI"; }; config = { home.packages = [ # https://monaspace.githubnext.com/ pkgs.monaspace ]; }; imports = [ ./ghostty.nix ]; }
-
-
-
@@ -0,0 +1,21 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # # Hive manages workerbee containers using Incus. { ... }: { imports = [ ./workerbee.nix ]; }
-
-
-
@@ -0,0 +1,23 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # # Workerbee management CLI. { pkgs, ... }: { config = { home.packages = [ (pkgs.callPackage ../../../programs/workerbee { }) ]; }; }
-
-
-
@@ -0,0 +1,25 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # # Enables "home-manager" program. { pkgs, ... }: { config = { programs.home-manager.enable = true; home.packages = with pkgs; [ (callPackage ../../../programs/hm-clean { }) ]; }; }
-
-
-
@@ -0,0 +1,24 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # # This defines a Home Manager version for default state files. Change to the # version affects every modules inside "modules/hm". { pkgs, ... }: { config = { home.stateVersion = "25.11"; }; }
-
-
-
@@ -0,0 +1,26 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # # Home Manager configuration for Linux desktop environment. This profile contains # development focused softwares. { lib, pkgs, ... }: { imports = [ ./options.nix ]; config = { nix.package = lib.mkDefault pkgs.nix; }; }
-
-
-
@@ -0,0 +1,24 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD { ... }: { config = { nix.extraOptions = '' experimental-features = nix-command flakes warn-dirty = false ''; }; }
-
-
-
@@ -0,0 +1,94 @@# Copyright 2023 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # # Catppuccin color schema. { config, lib, pkgs, ... }: let cfg = config.palette.catppuccin; json = builtins.fromJSON ( builtins.readFile ( pkgs.fetchFromGitHub { owner = "catppuccin"; repo = "palette"; rev = "205dd54c6158b7648621cf9fd00e91f03888ce7e"; sha256 = "y14fd8lvnG9hNY6CRU0JgxWouexEw91aIEMkr1NaM/4="; } + "/palette.json" ) ); flavor = lib.types.enum [ "latte" "frappe" "macchiato" "mocha" ]; color = lib.types.submodule { options = { hex = lib.mkOption { type = lib.types.nonEmptyStr; }; hsl = lib.mkOption { type = lib.types.nonEmptyStr; }; raw = lib.mkOption { type = lib.types.nonEmptyStr; }; rgb = lib.mkOption { type = lib.types.nonEmptyStr; }; }; }; palette = lib.types.attrsOf color; in { options = { palette.catppuccin = { light-flavor = lib.mkOption { type = flavor; default = "latte"; description = '' Specify which Catppuccin _flavor_ (color palette) to use on light mode. ''; }; dark-flavor = lib.mkOption { type = flavor; default = "mocha"; description = '' Specify which Catppuccin _flavor_ (color palette) to use on dark mode. ''; }; light-palette = lib.mkOption { type = palette; default = { }; }; dark-palette = lib.mkOption { type = palette; default = { }; }; }; }; config = { palette.catppuccin.light-palette = json.${cfg.light-flavor}; palette.catppuccin.dark-palette = json.${cfg.dark-flavor}; }; }
-
-
-
@@ -12,18 +12,10 @@# PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # # Color palettes. { ... }: { imports = [ ./home ./scm ./scm-server ./identity ./basics ./gui ./wayland-de ./dev ./data ./syncthing ]; imports = [ ./catppuccin.nix ]; }
-
-
-
@@ -0,0 +1,48 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # # Home Manager configuration for git hosting server on non-NixOS Linux. # While it is called "git server", the server also hosts non-git features. { config, pkgs, ... }: { imports = [ ../home-manager/state-version.nix ../home-manager/cli.nix ../nix ../shell ../essentials ../vcs ../syncthing ../server/soft-serve.nix ../server/legit.nix ]; config = { home.packages = with pkgs; [ # terminfo for terminal emulators that run SSH client. ghostty.terminfo ]; home.username = "pocka"; home.homeDirectory = "/home/pocka"; xdg.enable = true; # As the server is public, its network access is strictly limited by firewall. # Wireguard is required for opening admin UI (fd33::1 is in private IP range.) services.syncthing.guiAddress = "[fd33::1]:8384"; }; }
-
-
-
@@ -0,0 +1,76 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # # Home Manager configuration for non-NixOS Linux desktop environment. # This profile contains development focused softwares. { config, pkgs, nixgl, ... }: { imports = [ ../home-manager/state-version.nix ../home-manager/cli.nix ../nix ../shell ../essentials ../signing ../terminal ../vcs ../hive ../syncthing ../fonts ../wayland-desktop ../apps/music ]; config = { home.username = "pocka"; home.homeDirectory = "/home/pocka"; xdg.enable = true; nixGL.packages = nixgl.packages; nixGL.defaultWrapper = "mesa"; nixGL.installScripts = [ "mesa" ]; wayland-desktop.niri.outputs = [ { name = "HDMI-A-1"; scale = 1.4; } ]; programs.ghostty.package = config.lib.nixGL.wrap pkgs.ghostty; # Must be installed in system's package manager. Otherwise won't work due # to missing access to PAM. programs.swaylock.package = null; # Exclude bloat binaries installed as a library dependency but the library # installs bloated utility executable. services.walker.settings.builtins.applications.blacklist = [ { regexp = "Avahi\\s.*"; } { regexp = "Electron\\s+\\d+"; } { regexp = "lstopo"; } { regexp = "Vifm"; } { regexp = "Vim"; } { regexp = "Qt\\s.*[Uu]tility"; } ]; }; }
-
-
-
@@ -1,4 +1,4 @@# Copyright 2023 Shota FUJI <pockawoooh@gmail.com> # Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted.
-
@@ -13,32 +13,51 @@# # SPDX-License-Identifier: 0BSD # # === # Platform specifc configurations # Home Manager configuration for macOS machines. { config, lib, pkgs, mac-app-util, ... }: { imports = [ # Fix Home-Manager on MacOS cannot register GUI applications and Spotlight # won't find those applications. mac-app-util.homeManagerModules.default ../home-manager/state-version.nix ../home-manager/cli.nix ../nix ../shell ../essentials ../signing ../terminal ../vcs ../syncthing ../fonts ../development ]; config = { home.username = "pocka"; home.homeDirectory = "/Users/pocka"; programs.ghostty = { package = pkgs.ghostty-bin; installBatSyntax = false; }; # https://github.com/NixOS/nix/issues/3616 # Every macOS updates overwrite /etc/zshrc and that breaks Nix initialisation. # This is a workaround for it so that I no longer need to manually edit the file. # https://github.com/NixOS/nix/issues/3616#issuecomment-1655785404 programs.zsh = lib.mkIf (pkgs.stdenv.isDarwin && config.programs.zsh.enable) { programs.zsh = lib.mkIf config.programs.zsh.enable { initContent = lib.mkBefore '' if [[ ! $(command -v nix) && -e "/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh" ]]; then source "/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh" fi ''; }; xdg = lib.mkIf pkgs.stdenv.isLinux { enable = true; }; # I'm not sure this changes behaviour in a meaningful way. targets.genericLinux = lib.mkIf pkgs.stdenv.isLinux { enable = true; }; }; }
-
-
-
@@ -12,35 +12,34 @@# PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # # Home Manager configuration for workerbee, container guest user for sandboxed # development work. { pkgs, ... }: { config, lib, pkgs, ... }: { options = { features.wayland-de.walker = { css = lib.mkOption { type = lib.types.lines; default = ""; }; }; }; imports = [ ../home-manager/state-version.nix ../nix ../shell ../essentials ../vcs ../development ]; config = lib.mkIf config.features.wayland-de.enable { home.packages = [ # Multi-Purpose Launcher with a lot of features. # https://github.com/abenz1267/walker pkgs.walker config = { home.packages = with pkgs; [ # terminfo for terminal emulators container host uses. ghostty.terminfo ]; xdg.configFile."walker/config.toml".source = ./walker/config.toml; xdg.configFile."walker/themes/nix.toml".source = ./walker/theme.toml; xdg.configFile."walker/themes/nix.css".text = '' ${builtins.readFile ./walker/theme.css} ${config.features.wayland-de.walker.css} ''; # Container host have to bind wayland socket at /mnt/wayland-0 to allow the # container to run graphical applications. home.sessionVariables.WAYLAND_DISPLAY = "/mnt/wayland-0"; home.username = "workerbee"; home.homeDirectory = "/home/workerbee"; xdg.enable = true; }; }
-
-
-
@@ -0,0 +1,109 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # # Web frontend for git repositories, powered by legit (fork.) # This module publishes public repositories managed by soft-serve. # Every repository named "x/*" will be public. # https://git.pocka.jp/legit.git { config, lib, pkgs, ... }: let cfg = config.services.legit; package = if cfg.package != null then cfg.package else pkgs.legit-web; in { imports = [ ./soft-serve.nix ]; options = { services.legit = { package = lib.mkOption { type = lib.types.nullOr lib.types.package; default = null; }; port = lib.mkOption { type = lib.types.ints.unsigned; default = 5555; }; domain = lib.mkOption { type = lib.types.str; default = "git.pocka.jp"; }; }; }; config = { home.packages = [ package ]; xdg.configFile."legit/config.yaml" = { text = '' repo: scanPath: "${config.xdg.dataHome}/soft-serve/repos/x" readme: - "README" - "README.md" - "README.adoc" - "README.txt" - "ABOUT" - "ABOUT.md" - "ABOUT.adoc" - "ABOUT.txt" mainBranch: - "trunk" - "master" - "main" dirs: templates: "${package}/lib/legit/templates" static: "${package}/lib/legit/static" meta: title: "git.pocka.jp" description: "My personal projects" syntaxHighlight: true server: name: "${cfg.domain}" host: "127.0.0.1" port: ${cfg.port} ''; }; systemd.user.services.legit = { Unit = { Description = "legit, web frontend for git repositories."; }; Service = { Type = "simple"; Restart = "always"; RestartSec = 1; ExecStart = "${package}/bin/legit --config=${config.xdg.configHome}/legit/config.yaml"; Environment = "PATH=$PATH:${lib.makeBinPath [ pkgs.git ]}"; }; Install = { WantedBy = [ "default.target" ]; }; }; }; }
-
-
-
@@ -0,0 +1,113 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # # Git server powered by soft-serve. # https://github.com/charmbracelet/soft-serve { pkgs, lib, config, ... }: let cfg = config.services.soft-serve; package = if cfg.package != null then cfg.package else pkgs.soft-serve; in { options = { services.soft-serve = { package = lib.mkOption { type = lib.types.nullOr lib.types.package; default = null; }; ssh-port = lib.mkOption { type = lib.types.ints.unsigned; default = 23231; }; ssh-domain = lib.mkOption { type = lib.types.str; default = "git.pocka.jp"; }; http-port = lib.mkOption { type = lib.types.ints.unsigned; default = 23232; }; url = lib.mkOption { type = lib.types.str; default = "https://git.pocka.jp"; }; }; }; config = { home.packages = [ package ]; xdg.dataFile."soft-serve/config.yaml" = { text = '' name: "git.pocka.jp" log_format: "text" ssh: listen_addr: ":${cfg.ssh-port}" public_url: "ssh://${cfg.ssh-domain}:${cfg.ssh-port}" max_timeout: 0 idle_timeout: 120 http: listen_addr: ":${cfg.http-port}" public_url: "${cfg.url}" git: enabled: false db: driver: "sqlite" data_source: "soft-serve.db?_pragma=busy_timeout(5000)&_pragma=foreign_keys(1)" lfs: enabled: false jobs: mirror_pull: "@every 30m" ''; }; systemd.user.services.soft-serve = { Unit = { Description = "Soft Serve, SSH TUI git server."; }; Service = { Type = "simple"; Restart = "always"; RestartSec = 1; ExecStart = "${package}/bin/soft serve"; Environment = "SOFT_SERVE_DATA_PATH=${config.xdg.dataHome}/soft-serve"; WorkingDirectory = "${config.xdg.dataHome}/soft-serve"; }; Install = { WantedBy = [ "default.target" ]; }; }; }; }
-
-
-
@@ -0,0 +1,19 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD { ... }: { imports = [ ./fish ]; }
-
-
-
@@ -0,0 +1,24 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD { pkgs, ... }: { config = { programs.fish = { enable = true; interactiveShellInit = builtins.readFile ./init.fish; }; }; }
-
-
-
-
@@ -12,29 +12,27 @@# PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # # Cryptographic signatures. { config, lib, pkgs, ... }: let cfg = config.features.wayland-de.swaylock; in { lib, ... }: { options = { features.wayland-de.swaylock = { flags = lib.mkOption { type = lib.types.listOf lib.types.str; default = [ ]; }; }; }; signing.key-id = lib.mkOption { type = lib.types.nullOr lib.types.nonEmptyStr; default = "5E5148973E291363"; config = lib.mkIf config.features.wayland-de.enable { xdg.configFile."swaylock/config" = { text = builtins.concatStringsSep "\n" cfg.flags; description = '' A key ID of a signing key (primary or subkey). This is a **key ID**, which is visible to public. Do not put key signature here. ''; }; }; imports = [ ./gpg.nix ./vcs.nix ]; }
-
-
-
@@ -0,0 +1,46 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # # GPG (GNU Privacy Guard) { config, lib, pkgs, ... }: { config = { programs.gpg.enable = true; services.gpg-agent = lib.mkIf pkgs.stdenv.isLinux { enable = true; enableBashIntegration = config.programs.fish.enable; enableFishIntegration = config.programs.fish.enable; enableZshIntegration = config.programs.fish.enable; # 1day defaultCacheTtl = 86400; defaultCacheTtlSsh = 86400; # 30days maxCacheTtl = 2592000; maxCacheTtlSsh = 2592000; pinentry.package = pkgs.pinentry-curses; }; }; }
-
-
-
@@ -1,4 +1,4 @@# Copyright 2023 Shota FUJI <pockawoooh@gmail.com> # Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted.
-
@@ -12,26 +12,21 @@# PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # # Commit signing. { config, ... }: { config, lib, pkgs, ... }: { config = lib.mkIf config.features.data.enable { programs.nushell = { enable = lib.mkDefault true; configFile.text = '' $env.config = { show_banner: false edit_mode: vi } ''; config = { programs.git.signing = { key = config.signing.key-id; signByDefault = true; }; envFile.text = ''''; programs.jujutsu.settings.signing = { behavior = "own"; backend = "gpg"; key = config.signing.key-id; }; }; }
-
-
-
@@ -12,24 +12,14 @@# PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # # File sharing between my devices. # > Syncthing is a continuous file synchronization program # https://syncthing.net/ { ... }: { pkgs, lib, config, ... }: let cfg = config.features.syncthing; in { options = { features.syncthing = { enable = lib.mkEnableOption "Syncthing"; }; }; config = lib.mkIf cfg.enable { config = { services.syncthing = { enable = true;
-
-
-
@@ -0,0 +1,21 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # # Terminal emulators. { ... }: { imports = [ ./ghostty.nix ]; }
-
-
-
@@ -0,0 +1,130 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # # Ghostty, a cross-platform terminal emulator. # https://ghostty.org/ { config, lib, pkgs, nix-colorizer, ... }: let palette = config.palette.catppuccin; in { imports = [ ../fonts/monaspace.nix ../palette/catppuccin.nix ]; config = { programs.ghostty = { enable = true; installBatSyntax = lib.mkDefault config.programs.bat.enable; enableBashIntegration = config.programs.bash.enable; enableFishIntegration = config.programs.fish.enable; enableZshIntegration = config.programs.zsh.enable; settings = { # Somehow Ghostty renders Monaspace in incorrect size at either of platform. font-size = if pkgs.stdenv.isDarwin then 13 else 10; font-family = "Monaspace Neon Var"; font-style = "Medium"; font-style-bold = "Bold"; font-style-italic = "Medium Italic"; font-style-bold-italic = "Bold Italic"; # * "calt" ... Contextual Alternates # This feature enables Monaspace's Texture healing. font-feature = [ "calt" ]; copy-on-select = false; keybind = if pkgs.stdenv.isDarwin then [ "ctrl+shift+t=new_tab" "ctrl+shift+n=new_split:down" "ctrl+shift+m=new_split:right" "super+shift+k=resize_split:up,20" "super+shift+h=resize_split:left,20" "super+shift+j=resize_split:down,20" "super+shift+l=resize_split:right,20" "ctrl+shift+k=goto_split:up" "ctrl+shift+h=goto_split:left" "ctrl+shift+j=goto_split:down" "ctrl+shift+l=goto_split:right" ] else [ "ctrl+shift+t=new_window" "ctrl+shift+n=new_window" "ctrl+shift+m=new_window" ]; theme = "light:catppuccin-${palette.light-flavor},dark:catppuccin-${palette.dark-flavor}"; }; # Both iterm2-color-schemes (Ghostty sources from) and catppuccin/ghostty # inverts 0/7 and 15/8 (bg and fg) to make colors "bright." This is unusable # as the colors' semantics no longer works. 15 can't be used for foreground, # so the program have to read background color. The reason 4-bit colors is # still used today is compatibility AND theming. Theme violates widely-used # context is completely useless. This code defines correct Catppuccin theme. themes = let stripSharp = hex: lib.strings.removePrefix "#" hex; lighten = hex: nix-colorizer.hex.lighten hex 0.1; toTheme = p: { palette = [ "0=${p.surface0.hex}" "1=${p.red.hex}" "2=${p.green.hex}" "3=${p.yellow.hex}" "4=${p.blue.hex}" "5=${p.pink.hex}" "6=${p.teal.hex}" "7=${p.subtext0.hex}" "8=${p.surface2.hex}" "9=${lighten p.red.hex}" "10=${lighten p.green.hex}" "11=${lighten p.yellow.hex}" "12=${lighten p.blue.hex}" "13=${lighten p.pink.hex}" "14=${lighten p.teal.hex}" "15=${p.text.hex}" ]; background = stripSharp p.base.hex; foreground = stripSharp p.text.hex; cursor-color = stripSharp p.rosewater.hex; selection-background = stripSharp p.surface2.hex; selection-foreground = stripSharp p.text.hex; }; in { "catppuccin-${palette.light-flavor}" = toTheme palette.light-palette; "catppuccin-${palette.dark-flavor}" = toTheme palette.dark-palette; }; }; }; }
-
-
-
@@ -0,0 +1,26 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # # All version control softwares I may use. This default module does not include # signing module. { ... }: { imports = [ ./git.nix ./jj.nix ./identity.nix ]; }
-
-
modules/hm/vcs/git.nix (new)
-
@@ -0,0 +1,59 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # # Basic git configurations. { config, pkgs, ... }: { config = { programs.git = { enable = true; # TODO: Migrate to "programs.difftastic.git.enable" difftastic.enable = true; extraConfig = { core.editor = if config.programs.neovim.enable then "nvim" else "vim"; init.defaultBranch = "trunk"; # This is turned off by default for compatibility reason. # Essential for working both inside container and on host via bind mount. worktree.useRelativePaths = true; }; ignores = let # # Ignore all bazel-* symlinks. There is no full list since this can change # based on the name of the directory bazel is cloned into. bazel = [ "/bazel-*" ]; # Swap file nvim = if config.programs.neovim.enable then [ ".*.swp" ] else [ ]; # https://github.com/github/gitignore/blob/main/Global/macOS.gitignore darwin = if pkgs.stdenv.isDarwin then [ ".DS_Store" ".AppleDouble" ".LSOverride" ] else [ ]; in nvim ++ darwin ++ bazel; }; }; }
-
-
-
@@ -0,0 +1,36 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # # Author / Committer information, for easy modification. { lib, ... }: { config = let name = "Shota FUJI"; email = "pockawoooh@gmail.com"; in { programs.git = { userName = lib.mkDefault name; userEmail = lib.mkDefault email; }; programs.jujutsu.settings.user = { name = lib.mkDefault name; email = lib.mkDefault email; }; }; }
-
-
modules/hm/vcs/jj.nix (new)
-
@@ -0,0 +1,65 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # # Basic jujutsu configurations. # https://github.com/martinvonz/jj { config, lib, pkgs, ... }: { config = { # TODO: Migrate to "programs.difftastic" home.packages = with pkgs; [ difftastic ]; programs.jujutsu = { enable = true; settings = { ui = { diff-formatter = [ "difft" "--color=always" "$left" "$right" ]; }; revsets = { log = "all()"; }; git = { private-commits = "description(regex:'\\[WIP\\]')"; }; aliases = { # JJ by default sets incorrect author date (when "a work started" instead of "authored",) # because how it works internally (updating a git commit.) This command is to workaround # that design flaw by manually mark author date, like "git commit". author = [ "desc" "--no-edit" "--reset-author" ]; au = [ "author" ]; }; }; }; }; }
-
-
-
@@ -0,0 +1,43 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # # > daemon for dark-mode and light-mode transitions on Unix-like desktops # https://darkman.whynothugo.nl { pkgs, ... }: { services.darkman = { enable = true; settings = { lat = 35.8; lng = 139.5; }; darkModeScripts = { gtk4 = '' ${pkgs.dconf}/bin/dconf write \ /org/gnome/desktop/interface/color-scheme "'prefer-dark'" ''; }; lightModeScripts = { gtk4 = '' ${pkgs.dconf}/bin/dconf write \ /org/gnome/desktop/interface/color-scheme "'prefer-light'" ''; }; }; }
-
-
-
@@ -0,0 +1,29 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # # My desktop environment on Wayland. { ... }: { imports = [ ./darkman.nix ./dunst.nix ./fcitx.nix ./niri.nix ./waybar.nix ./swaylock.nix ./walker.nix ]; }
-
-
-
@@ -0,0 +1,72 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # # > Lightweight and customizable notification daemon # https://dunst-project.org/ { config, ... }: { imports = [ ../palette/catppuccin.nix ]; config = { services = { dunst = { enable = true; settings = let dark = config.palette.catppuccin.dark-palette; in { global = { follow = "keyboard"; mouse_left_click = "do_action"; mouse_middle_click = "close_current"; mouse_right_click = "context"; width = 400; height = 300; offset = "4x4"; padding = 4; horizontal_padding = 8; frame_width = 2; gap_size = 6; font = "Monospace 10"; corner_radius = 2; }; urgency_low = { background = dark.base.hex; foreground = dark.subtext0.hex; frame_color = dark.overlay1.hex; }; urgency_normal = { background = dark.base.hex; foreground = dark.text.hex; frame_color = dark.blue.hex; }; urgency_critical = { background = dark.base.hex; foreground = dark.text.hex; frame_color = dark.yellow.hex; }; }; }; }; }; }
-
-
-
@@ -1,4 +1,4 @@# Copyright 2023 Shota FUJI <pockawoooh@gmail.com> # Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted.
-
@@ -12,24 +12,13 @@# PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # # > cross-platform input method framework. # https://github.com/fcitx/fcitx5 { pkgs, ... }: { config, lib, pkgs, ... }: let wayland-de = config.features.wayland-de; in { options = { features.wayland-de.ime = { enable = lib.mkEnableOption "Input method"; }; }; config = lib.mkIf (wayland-de.enable && wayland-de.ime.enable) { config = { i18n.inputMethod = { enable = true; type = "fcitx5";
-
@@ -37,10 +26,10 @@ infcitx5 = { waylandFrontend = true; addons = [ pkgs.fcitx5-mozc pkgs.fcitx5-gtk pkgs.libsForQt5.fcitx5-qt addons = with pkgs; [ fcitx5-mozc fcitx5-gtk libsForQt5.fcitx5-qt ]; }; };
-
-
-
@@ -0,0 +1,293 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # # > Scrollable-tiling Wayland compositor # https://github.com/YaLTeR/niri { config, lib, pkgs, ... }: let cfg = config.wayland-desktop.niri; output = lib.types.submodule { options = { name = lib.mkOption { type = lib.types.nonEmptyStr; description = "Display output name, you can obtain from `niri msg outputs`"; }; scale = lib.mkOption { type = lib.types.float; description = "DPI"; default = 1.0; }; }; }; serializeOutput = o: '' output "${o.name}" { scale ${builtins.toString o.scale} } ''; serializeSpawnArg = a: builtins.concatStringsSep " " (builtins.map (s: "\"${s}\"") a); dark = config.palette.catppuccin.dark-palette; gap = 16; in { imports = [ ../palette/catppuccin.nix ]; options = { wayland-desktop.niri = { outputs = lib.mkOption { type = lib.types.listOf output; default = [ ]; }; input = { keyboard = { repeat-delay = lib.mkOption { type = lib.types.ints.unsigned; default = 200; }; repeat-rate = lib.mkOption { type = lib.types.ints.unsigned; default = 25; }; }; }; spawn-at-startup = lib.mkOption { type = lib.types.listOf (lib.types.listOf lib.types.nonEmptyStr); description = '' `spawn-at-startup` accepts a path to the program binary as the first argument, followed by arguments to the program. Note that running niri as a systemd session supports xdg-desktop-autostart out of the box, which may be more convenient to use. Thanks to this, apps that you configured to autostart in GNOME will also "just work" in niri, without any manual `spawn-at-startup` configuration. ''; default = [ ]; }; prefer-no-csd = lib.mkOption { type = lib.types.bool; description = '' Ask the clients to omit their client-side decorations if possible. If the client will specifically ask for CSD, the request will be honored. Additionally, clients will be informed that they are tiled, removing some client-side rounded corners. This option will also fix border/focus ring drawing behind some semitransparent windows. After enabling or disabling this, you need to restart the apps for this to take effect. ''; default = true; }; screenshot-path = lib.mkOption { type = lib.types.nonEmptyStr; description = '' You can change the path where screenshots are saved. A ~ at the front will be expanded to the home directory. The path is formatted with strftime(3) to give you the screenshot date and time. ''; default = "~/Pictures/Screenshots/Screenshot from %Y-%m-%d %H-%M-%S.png"; }; hotkey-overlay = { skip-at-startup = lib.mkOption { type = lib.types.bool; default = true; }; }; }; }; config = { xdg.configFile."niri/config.kdl" = { # https://github.com/YaLTeR/niri/wiki/Configuration:-Overview text = '' input { keyboard { repeat-delay ${builtins.toString cfg.input.keyboard.repeat-delay} repeat-rate ${builtins.toString cfg.input.keyboard.repeat-rate} } // This section includes libinput settings. // Omitting settings disables them, or leaves them at their default values. touchpad { natural-scroll accel-speed 0.2 accel-profile "adaptive" scroll-method "two-finger" scroll-factor 0.3 click-method "clickfinger" } } ${lib.strings.concatStringsSep "\n" (builtins.map serializeOutput cfg.outputs)} overview { backdrop-color "${dark.base.hex}" workspace-shadow { off } } layout { gaps ${builtins.toString gap} center-focused-column "never" background-color "transparent" preset-column-widths { // Proportion sets the width as a fraction of the output width, taking gaps into account. // For example, you can perfectly fit four windows sized "proportion 0.25" on an output. // The default preset widths are 1/3, 1/2 and 2/3 of the output. proportion 0.25 proportion 0.5 proportion 0.75 } preset-window-heights { proportion 0.25 proportion 0.5 proportion 0.75 } // You can change the default width of the new windows. // If you leave the brackets empty, the windows themselves will decide their initial width. default-column-width { proportion 0.5 } focus-ring { width 1 active-color "${dark.overlay1.hex}" inactive-color "${dark.surface1.hex}" } border { width ${builtins.toString (gap / 5)} active-color "${dark.overlay2.hex}" inactive-color "${dark.surface0.hex}" } shadow { on softness 40 spread 5 } struts { left 0 right 0 top 0 bottom ${builtins.toString (gap / -2)} } } ${if cfg.prefer-no-csd then "" else "//"}prefer-no-csd screenshot-path "${cfg.screenshot-path}" animations { } // Open the Firefox picture-in-picture player as floating by default. window-rule { // This app-id regular expression will work for both: // - host Firefox (app-id is "firefox") // - Flatpak Firefox (app-id is "org.mozilla.firefox") match app-id=r#"firefox$"# title="^Picture-in-Picture$" open-floating true } window-rule { match app-id="^com\\.mitchellh\\.ghostty$" default-column-width { proportion 0.25 } } // Enable rounded corners for all windows. window-rule { geometry-corner-radius 2 clip-to-geometry true } hotkey-overlay { ${if cfg.hotkey-overlay.skip-at-startup then "" else "//"}skip-at-startup } ${builtins.concatStringsSep "\n" ( builtins.map (a: "spawn-at-startup ${serializeSpawnArg a}") cfg.spawn-at-startup )} spawn-at-startup "${pkgs.waybar}/bin/waybar" binds { Mod+Shift+Slash { show-hotkey-overlay; } Mod+T { spawn "${config.lib.nixGL.wrap pkgs.ghostty}/bin/ghostty" "--working-directory=home"; } Mod+X { spawn "swaylock"; } Mod+Q { close-window; } Mod+Space { spawn "${pkgs.walker}/bin/walker" "--modules" "applications,commands,calc,power"; } Mod+H { focus-column-left; } Mod+J { focus-window-down-or-column-right; } Mod+K { focus-window-up-or-column-left; } Mod+L { focus-column-right; } Mod+Ctrl+H { move-column-left; } Mod+Ctrl+J { consume-or-expel-window-left; } Mod+Ctrl+K { consume-or-expel-window-right; } Mod+Ctrl+L { move-column-right; } Mod+U { focus-workspace-down; } Mod+I { focus-workspace-up; } Mod+Ctrl+U { move-column-to-workspace-down; } Mod+Ctrl+I { move-column-to-workspace-up; } Mod+BracketLeft { consume-or-expel-window-left; } Mod+BracketRight { consume-or-expel-window-right; } Mod+Comma { consume-window-into-column; } Mod+Period { expel-window-from-column; } Mod+R { switch-preset-column-width; } Mod+Shift+R { switch-preset-window-height; } Mod+Ctrl+R { reset-window-height; } Mod+F { maximize-column; } Mod+Shift+F { fullscreen-window; } Mod+C { center-column; } Mod+Minus { set-column-width "-10%"; } Mod+Equal { set-column-width "+10%"; } Mod+Shift+Minus { set-window-height "-10%"; } Mod+Shift+Equal { set-window-height "+10%"; } Mod+V { toggle-window-floating; } Mod+Shift+V { switch-focus-between-floating-and-tiling; } Mod+Shift+E { quit; } Ctrl+Alt+Delete { quit; } Mod+Shift+P { power-off-monitors; } } ''; }; }; }
-
-
-
@@ -0,0 +1,56 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # # > Screen locker for Wayland # https://github.com/swaywm/swaylock { config, lib, ... }: { imports = [ ../palette/catppuccin.nix ]; config = { programs.swaylock = { enable = true; settings = let palette = config.palette.catppuccin.dark-palette; stripSharp = hex: lib.strings.removePrefix "#" hex; in { color = stripSharp palette.base.hex; indicator-thickness = 8; indicator-idle-visible = true; inside-color = stripSharp palette.base.hex; inside-clear-color = stripSharp palette.base.hex; inside-ver-color = stripSharp palette.base.hex; inside-wrong-color = stripSharp palette.base.hex; key-hl-color = stripSharp palette.mauve.hex; line-color = stripSharp palette.surface0.hex; line-clear-color = stripSharp palette.surface0.hex; line-ver-color = stripSharp palette.overlay2.hex; line-wrong-color = stripSharp palette.red.hex; ring-color = stripSharp palette.base.hex; ring-clear-color = stripSharp palette.base.hex; ring-ver-color = stripSharp palette.overlay0.hex; ring-wrong-color = stripSharp palette.maroon.hex; text-color = stripSharp palette.text.hex; text-clear-color = stripSharp palette.text.hex; text-ver-color = stripSharp palette.subtext1.hex; text-wrong-color = stripSharp palette.red.hex; }; }; }; }
-
-
-
@@ -0,0 +1,252 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # # > Wayland-native application runner # https://github.com/abenz1267/walker { config, ... }: { config = { services.walker = { enable = true; settings = { close_when_open = true; theme = "nix"; as_window = false; disable_click_to_close = false; force_keyboard_focus = true; keys = { accept_typeahead = [ "tab" ]; trigger_labels = "ralt"; next = [ "down" ]; prev = [ "up" ]; close = [ "esc" ]; remove_from_history = [ "shift backspace" ]; }; list = { dynamic_sub = true; max_entries = 50; show_initial_entries = true; single_click = true; visibility_threshold = 20; placeholder = "No Results"; }; search = { argument_delimiter = "#"; placeholder = "Search..."; delay = 0; }; activation_mode = { disabled = true; }; builtins = { applications = { weight = 5; name = "applications"; placeholder = "Applications"; prioritize_new = true; hide_actions_with_empty_query = true; refresh = true; show_sub_when_single = true; show_icon_when_single = true; show_generic = true; history = true; actions = { enabled = true; hide_category = false; hide_without_query = true; }; }; calc = { require_number = true; weight = 5; name = "calc"; icon = "accessories-calculator"; placeholder = "Calculator"; }; commands = { weight = 5; icon = "utilities-terminal"; name = "commands"; placeholder = "Commands"; }; custom_commands = { weight = 5; icon = "utilities-terminal"; name = "custom_commands"; placeholder = "Custom Commands"; }; }; plugins = [ { keep_sort = false; name = "power"; placeholder = "Power"; recalculate_score = true; show_icon_when_single = true; switcher_only = false; entries = [ { exec = "shutdown now"; icon = "system-shutdown"; label = "Shutdown"; } { exec = "reboot"; icon = "system-reboot"; label = "Reboot"; } { exec = "niri msg action power-off-monitors && swaylock"; icon = "system-lock-screen"; label = "Lock Screen"; } ]; } ]; }; theme = { name = "nix"; layout.ui = { anchors = { bottom = true; left = true; right = true; top = true; }; window = { h_align = "fill"; v_align = "fill"; box = { h_align = "center"; width = 800; bar = { orientation = "horizontal"; position = "end"; entry = { h_align = "fill"; h_expand = true; icon = { h_align = "center"; h_expand = true; pixel_size = 24; theme = ""; }; }; }; margins.top = 400; scroll.list = { marker_color = "var(--accent-foreground-color)"; max_height = 500; item = { spacing = 6; activation_label = { h_align = "fill"; v_align = "fill"; width = 20; x_align = 0.5; y_align = 0.5; }; icon = { pixel_size = 26; theme = ""; }; }; margins.top = 8; }; search = { spacing = 4; prompt = { name = "prompt"; icon = "edit-find-symbolic"; pixel_size = 18; h_align = "center"; v_align = "center"; }; clear = { name = "clear"; icon = "edit-clear-symbolic"; pixel_size = 18; h_align = "center"; v_align = "center"; }; input = { h_align = "fill"; h_expand = true; icons = true; }; spinner.hide = true; }; }; }; }; style = let light = config.palette.catppuccin.light-palette; dark = config.palette.catppuccin.dark-palette; in '' ${builtins.readFile ./walker/theme.css} #window.dark { --background-color: ${dark.base.hex}; --surface-background-color: ${dark.surface0.hex}; --border-color: ${dark.lavender.hex}; --foreground-color: ${dark.text.hex}; --dimmed-foreground-color: ${dark.subtext0.hex}; } #window.light { --background-color: ${light.base.hex}; --surface-background-color: ${light.surface0.hex}; --border-color: ${light.lavender.hex}; --foreground-color: ${light.text.hex}; --dimmed-foreground-color: ${light.subtext0.hex}; } ''; }; }; }; }
-
-
-
-
@@ -0,0 +1,133 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # # > Highly customizable Wayland bar for Sway and Wlroots based compositors # https://github.com/alexays/waybar { config, pkgs, ... }: let waybar-text = pkgs.callPackage ../../../programs/waybar-text { }; light = config.palette.catppuccin.light-palette; dark = config.palette.catppuccin.dark-palette; in { imports = [ ../palette/catppuccin.nix ]; config = { programs.waybar = { enable = true; settings = { main = { layer = "top"; position = "bottom"; modules-left = [ "custom/todo" ]; modules-right = [ "clock" "pulseaudio" "tray" ]; clock = { # waybar can't read $TZ. Maybe a bug with Nix environment? timezone = "Asia/Tokyo"; locale = "en_US.UTF-8"; format = "{:%Y-%m-%d %H:%M}"; }; pulseaudio = { format = "{icon} {volume}% / {format_source}"; format-muted = "muted {format_source}"; on-click = "pavucontrol"; }; "custom/todo" = { exec = "${waybar-text}/bin/,waybar-text --trim-md-list ${config.xdg.dataHome}/todo.md"; restart-interval = 10; return-type = "json"; escape = true; }; }; }; }; # waybar module provided by Home Manager lacks light / dark mode feature. xdg.configFile = let baseStyle = '' * { font-family: Roboto, Helvetica, Arial, sans-serif; font-size: 16px; } window#waybar { font-weight: bold; } .module { padding: 2px 4px; margin: 4px; border-radius: 3px; } #clock, #network, #pulseaudio, #tray { color: inherit; } ''; in { "waybar/style-light.css".text = '' ${baseStyle} window#waybar { background-color: ${light.base.hex}; color: ${light.text.hex}; } #tray { background-color: ${light.sapphire.hex}; } #pulseaudio:hover { background-color: ${light.surface0.hex}; } ''; "waybar/style-dark.css".text = '' ${baseStyle} window#waybar { background-color: ${dark.base.hex}; color: ${dark.text.hex}; } #tray { background-color: transparent; } #pulseaudio:hover { background-color: ${dark.surface0.hex}; } ''; }; }; }
-
-
programs/theme/build.zig (deleted)
-
@@ -1,93 +0,0 @@// Copyright 2025 Shota FUJI <pockawoooh@gmail.com> // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // SPDX-License-Identifier: Apache-2.0 const std = @import("std"); pub fn build(b: *std.Build) !void { const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); const dark_mode_start = b.option( []const u8, "dark-mode-start", "Wall clock time dark mode starts at (hh:mm).", ) orelse "18:00"; const dark_mode_end = b.option( []const u8, "dark-mode-end", "Wall clock time dark mode ends at (hh:mm).", ) orelse "08:00"; const tzdir = b.option( []const u8, "tzdir", "Path to a zoneinfo directory, used when $TZDIR is not set.", ); const config = b.addOptions(); config.addOption([]const u8, "dark_mode_start", dark_mode_start); config.addOption([]const u8, "dark_mode_end", dark_mode_end); config.addOption( ?[:0]const u8, "tzdir", if (tzdir) |slice| try b.allocator.dupeZ(u8, slice) else null, ); const main = b.createModule(.{ .root_source_file = b.path("src/main.zig"), .target = target, .optimize = optimize, }); const exe = b.addExecutable(.{ .name = ",theme", .root_module = main, }); exe.root_module.addOptions("config", config); exe.linkLibC(); b.installArtifact(exe); // zig build run { const step = b.step("run", "Compile and Run program"); const run = b.addRunArtifact(exe); if (b.args) |args| { run.addArgs(args); } step.dependOn(&run.step); } // zig build test { const step = b.step("test", "Run unit tests"); const t = b.addTest(.{ .root_module = main, }); t.linkLibC(); const run = b.addRunArtifact(t); step.dependOn(&run.step); } }
-
-
programs/theme/default.nix (deleted)
-
@@ -1,93 +0,0 @@# Copyright 2025 Shota FUJI <pockawoooh@gmail.com> # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # SPDX-License-Identifier: Apache-2.0 { lib, glib, sunwait, tzdata, pkg-config, stdenvNoCC, installShellFiles, zig, }: stdenvNoCC.mkDerivation rec { pname = "my-theme"; version = "1.0.0"; buildInputs = [ glib tzdata ]; nativeBuildInputs = [ pkg-config zig.hook installShellFiles ]; zigBuildFlags = [ "-Dtzdir=${tzdata}/share/zoneinfo" ]; src = with lib.fileset; toSource { root = ./.; fileset = unions [ ./src ./build.zig ]; }; meta = { mainProgram = ",theme"; }; dontConfigure = true; postInstall = '' installShellCompletion --zsh --cmd ${pname} <(cat << "EOF" #compdef ${meta.mainProgram} function _${pname} { local line state _arguments -C \ "1: :->variant" case "$state" in (variant) _values "variant" \ "auto" \ "system" \ "dark" \ "light" ;; esac } if [ "$funcstack[1]" = "_${pname}" ]; then _${pname} "$@" else compdef _${pname} "${meta.mainProgram}" fi EOF) installShellCompletion --fish --cmd ${meta.mainProgram} <(cat << "EOF" complete -c ${meta.mainProgram} --no-files set -l variants auto system dark light complete -c ${meta.mainProgram} --condition "not __fish_seen_subcommand_from $variants" -a "$variants" EOF) ''; }
-
-
programs/theme/src/Config.zig (deleted)
-
@@ -1,19 +0,0 @@// Copyright 2025 Shota FUJI <pockawoooh@gmail.com> // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // SPDX-License-Identifier: Apache-2.0 const sunwait = @import("./sunwait.zig"); location: sunwait.Location = .{},
-
-
programs/theme/src/gnome.zig (deleted)
-
@@ -1,86 +0,0 @@// Copyright 2025 Shota FUJI <pockawoooh@gmail.com> // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // SPDX-License-Identifier: Apache-2.0 const std = @import("std"); const Variant = @import("./variant.zig").Variant; const GnomeColorScheme = enum(c_int) { default = 0, @"prefer-dark" = 1, @"prefer-light" = 2, pub fn from_variant(variant: Variant) @This() { return switch (variant) { .system => .default, .dark => .@"prefer-dark", .light => .@"prefer-light", }; } }; pub const ApplyError = error{ FailedToSpawnProcess, GsettingsCommandUnexpectedlyTerminated, }; pub fn apply(allocator: std.mem.Allocator, variant: Variant) ApplyError!void { const gnome_color_scheme = GnomeColorScheme.from_variant(variant); const run_result = std.process.Child.run(.{ .allocator = allocator, .argv = &.{ "gsettings", "set", "org.gnome.desktop.interface", "color-scheme", @tagName(gnome_color_scheme), }, }) catch |err| { std.log.err("Failed to run gsettings command: {s}", .{@errorName(err)}); return ApplyError.FailedToSpawnProcess; }; defer allocator.free(run_result.stdout); defer allocator.free(run_result.stderr); if (run_result.stderr.len > 0) { var stdout_writer = std.fs.File.stderr().writer(&.{}); const stdout = &stdout_writer.interface; stdout.writeAll(run_result.stderr) catch |err| { std.log.err("Failed to write to stderr: {t}", .{err}); }; } switch (run_result.term) { .Exited => |code| { if (code != 0) { std.log.err("Non zero exit: {d}", .{code}); return ApplyError.GsettingsCommandUnexpectedlyTerminated; } }, .Signal => |sig| { std.log.err("Signal ({d})", .{sig}); return ApplyError.GsettingsCommandUnexpectedlyTerminated; }, else => { std.log.err("Process terminated abnormally", .{}); return ApplyError.GsettingsCommandUnexpectedlyTerminated; }, } std.log.info("Set GNOME color scheme to {s}", .{@tagName(gnome_color_scheme)}); }
-
-
programs/theme/src/main.zig (deleted)
-
@@ -1,201 +0,0 @@// Copyright 2025 Shota FUJI <pockawoooh@gmail.com> // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // SPDX-License-Identifier: Apache-2.0 //! Over-powered theme switcher. const std = @import("std"); const Config = @import("./Config.zig"); const gnome = @import("./gnome.zig"); const sunwait = @import("./sunwait.zig"); const Variant = @import("./variant.zig").Variant; pub const std_options = std.Options{ .log_level = .debug, .logFn = log, }; var log_level: std.log.Level = .info; pub fn log( comptime level: std.log.Level, comptime scope: @Type(.enum_literal), comptime format: []const u8, args: anytype, ) void { if (@intFromEnum(level) <= @intFromEnum(log_level)) { std.log.defaultLog(level, scope, format, args); } } const ExitCode = enum(u8) { ok = 0, generic_error = 1, incorrect_usage = 2, pub fn to_u8(self: @This()) u8 { return @intFromEnum(self); } }; const UnresolvedVariant = union(enum) { auto, manual: Variant, pub const FromStringError = error{ UnknownType, }; pub fn fromString(str: []const u8) FromStringError!@This() { if (std.mem.eql(u8, str, "auto")) { return .auto; } return .{ .manual = Variant.fromString(str) catch return FromStringError.UnknownType, }; } }; fn apply(allocator: std.mem.Allocator, variant: Variant) ExitCode { gnome.apply(allocator, variant) catch {}; return ExitCode.ok; } pub fn main() !u8 { var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); defer arena.deinit(); const allocator = arena.allocator(); var iter = try std.process.ArgIterator.initWithAllocator(allocator); defer iter.deinit(); // Skip program name. _ = iter.next(); var arg_config_path: ?[]const u8 = null; defer if (arg_config_path) |p| allocator.free(p); var arg_variant_unresolved: ?UnresolvedVariant = null; var is_daemon: bool = false; while (iter.next()) |arg| { if (std.mem.eql(u8, arg, "--config")) { if (arg_config_path) |_| { std.log.err("--config is already set", .{}); return ExitCode.incorrect_usage.to_u8(); } const value = iter.next() orelse { std.log.err("--config option requires a value", .{}); return ExitCode.incorrect_usage.to_u8(); }; arg_config_path = try allocator.dupe(u8, value); continue; } if (std.mem.eql(u8, arg, "--verbose")) { log_level = .debug; continue; } if (std.mem.eql(u8, arg, "--daemon")) { is_daemon = true; continue; } if (arg_variant_unresolved) |_| { std.log.err("Variant is already set (reading \"{s}\")", .{arg}); return ExitCode.incorrect_usage.to_u8(); } arg_variant_unresolved = UnresolvedVariant.fromString(arg) catch { std.log.err("Unknown variant \"{s}\".", .{arg}); return ExitCode.incorrect_usage.to_u8(); }; } const variant_unresolved = arg_variant_unresolved orelse { std.log.err("Variant is required", .{}); return ExitCode.incorrect_usage.to_u8(); }; if (is_daemon and variant_unresolved != .auto) { std.log.err("--daemon option is only available for \"auto\" variant", .{}); return ExitCode.incorrect_usage.to_u8(); } switch (variant_unresolved) { .auto => { if (arg_config_path) |config_path| { const file = std.fs.cwd().openFile(config_path, .{}) catch |err| { std.log.err("Unable to open config file at {s}: {s}", .{ config_path, @errorName(err) }); return ExitCode.generic_error.to_u8(); }; defer file.close(); var read_buffer: [1024]u8 = undefined; var file_reader = file.reader(&read_buffer); var config_reader = std.json.Reader.init(allocator, &file_reader.interface); defer config_reader.deinit(); const config = std.json.parseFromTokenSource(Config, allocator, &config_reader, .{}) catch |err| { std.log.err("Unable to parse config file at {s}: {s}", .{ config_path, @errorName(err) }); return ExitCode.generic_error.to_u8(); }; defer config.deinit(); if (is_daemon) { while (true) { const current = sunwait.poll(allocator, config.value.location) catch |err| { std.log.err("Failed to get current suntime: {s}", .{@errorName(err)}); return ExitCode.generic_error.to_u8(); }; _ = apply(allocator, current.toVariant()); sunwait.wait(allocator, config.value.location) catch |err| { std.log.err("Failed to wait for suntime event: {s}", .{@errorName(err)}); return ExitCode.generic_error.to_u8(); }; } } const current = sunwait.poll(allocator, config.value.location) catch |err| { std.log.err("Failed to get current suntime: {s}", .{@errorName(err)}); return ExitCode.generic_error.to_u8(); }; return apply(allocator, current.toVariant()).to_u8(); } const variant = Variant.fromTime() catch |err| { std.log.err("Unable to resolve variant: {s}", .{@errorName(err)}); return ExitCode.generic_error.to_u8(); }; return apply(allocator, variant).to_u8(); }, .manual => |variant| { return apply(allocator, variant).to_u8(); }, } } test { _ = @import("./variant.zig"); }
-
-
programs/theme/src/sunwait.zig (deleted)
-
@@ -1,160 +0,0 @@// Copyright 2025 Shota FUJI <pockawoooh@gmail.com> // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // SPDX-License-Identifier: Apache-2.0 //! Helper functions for running "sunwait" command. //! That program is written in plain C but contains "main" in its core file //! so we can't use that as a library. For simplicity, this module spawns //! "sunwait" command instead. const std = @import("std"); const Variant = @import("./variant.zig").Variant; pub const Error = error{ UnexpectedExitCode, CommandNotFound, CommandInterrupted, CommandUnexpectedlyTerminated, } || std.mem.Allocator.Error || std.process.Child.RunError; pub const Location = struct { latitude: f64 = 0.0, longitude: f64 = 0.0, /// Caller is responsible to release returned buffer using `allocator.free`. fn getLatitudeArg(self: Location, allocator: std.mem.Allocator) std.mem.Allocator.Error![]const u8 { const dir: u8 = if (self.latitude < 0) 'S' else 'N'; return std.fmt.allocPrint( allocator, "{d:.4}{u}", .{ self.latitude, dir }, ); } /// Caller is responsible to release returned buffer using `allocator.free`. fn getLongitudeArg(self: Location, allocator: std.mem.Allocator) std.mem.Allocator.Error![]const u8 { const dir: u8 = if (self.longitude < 0) 'W' else 'E'; return std.fmt.allocPrint( allocator, "{d:.4}{u}", .{ self.longitude, dir }, ); } }; pub const PollResult = enum { day, night, pub fn toVariant(self: PollResult) Variant { return switch (self) { .day => Variant.light, .night => Variant.dark, }; } }; pub fn poll(allocator: std.mem.Allocator, location: Location) Error!PollResult { std.log.debug("Getting suntime state...", .{}); const lat_arg = try location.getLatitudeArg(allocator); defer allocator.free(lat_arg); const lon_arg = try location.getLongitudeArg(allocator); defer allocator.free(lon_arg); const run_result = std.process.Child.run(.{ .allocator = allocator, .argv = &.{ "sunwait", "poll", lat_arg, lon_arg, }, }) catch |err| return switch (err) { error.FileNotFound => Error.CommandNotFound, else => err, }; allocator.free(run_result.stderr); allocator.free(run_result.stdout); switch (run_result.term) { .Exited => |code| switch (code) { 2 => return .day, 3 => return .night, else => { std.log.warn("sunwait exited unexpectedly: exit code={d}", .{code}); return Error.UnexpectedExitCode; }, }, .Signal => |sig| { std.log.warn("sunwait(signal): {d}", .{sig}); return Error.CommandInterrupted; }, else => { std.log.err("sunwait terminated abnormally: {s}", .{@tagName(run_result.term)}); return Error.CommandUnexpectedlyTerminated; }, } } /// Block the running thread until day/night changes. pub fn wait(allocator: std.mem.Allocator, location: Location) Error!void { std.log.debug("Waiting suntime events...", .{}); const lat_arg = try location.getLatitudeArg(allocator); defer allocator.free(lat_arg); const lon_arg = try location.getLongitudeArg(allocator); defer allocator.free(lon_arg); const run_result = std.process.Child.run(.{ .allocator = allocator, .argv = &.{ "sunwait", "wait", lat_arg, lon_arg, }, }) catch |err| return switch (err) { error.FileNotFound => Error.CommandNotFound, else => err, }; allocator.free(run_result.stderr); allocator.free(run_result.stdout); switch (run_result.term) { .Exited => |code| switch (code) { 0 => { // sunwait returns incorrect result when invoked exactly at the sunrise/sunset time. std.log.debug("Waiting 5 seconds for accurate result...", .{}); std.Thread.sleep(std.time.ns_per_s * 5); return; }, else => { std.log.warn("sunwait exited unexpectedly: exit code={d}", .{code}); return Error.UnexpectedExitCode; }, }, .Signal => |sig| { std.log.warn("sunwait(signal): {d}", .{sig}); return Error.CommandInterrupted; }, else => { std.log.err("sunwait terminated abnormally: {s}", .{@tagName(run_result.term)}); return Error.CommandUnexpectedlyTerminated; }, } }
-
-
programs/theme/src/variant.zig (deleted)
-
@@ -1,326 +0,0 @@// Copyright 2025 Shota FUJI <pockawoooh@gmail.com> // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // SPDX-License-Identifier: Apache-2.0 const config = @import("config"); const std = @import("std"); const time = @cImport({ @cInclude("time.h"); }); const stdlib = @cImport({ @cInclude("stdlib.h"); }); pub const Variant = enum { system, dark, light, pub const FromStringError = error{ UnknownVariant, }; pub fn fromString(str: []const u8) FromStringError!@This() { inline for (@typeInfo(Variant).@"enum".fields) |field| { if (std.mem.eql(u8, field.name, str)) { return @enumFromInt(field.value); } } return FromStringError.UnknownVariant; } fn ensureZoneinfoDir() void { const existing = stdlib.getenv("TZDIR"); if (existing) |tzdir| { if (std.mem.span(tzdir).len > 0) { return; } } const fallback = config.tzdir orelse return; const set_result = stdlib.setenv("TZDIR", fallback, 1); if (set_result != 0) { std.log.warn("Failed to set $TZDIR to {s}: {d}", .{ fallback, set_result, }); } } pub fn fromTime() TimeRange.InitError!@This() { ensureZoneinfoDir(); time.tzset(); var now: time.time_t = undefined; _ = time.time(&now); var now_tm: time.tm = undefined; _ = time.localtime_r(&now, &now_tm); const dark_mode_range = try TimeRange.init( &now_tm, config.dark_mode_start, config.dark_mode_end, ); return if (dark_mode_range.isIntersecting(now)) .dark else .light; } }; const ParseTimeError = error{ IncorrectFormat, }; fn parseTime(now: *const time.tm, str: []const u8) ParseTimeError!time.time_t { if (str.len != 5) { return ParseTimeError.IncorrectFormat; } var iter = std.mem.splitScalar(u8, str, ':'); const hour_str = iter.next() orelse return ParseTimeError.IncorrectFormat; const min_str = iter.next() orelse return ParseTimeError.IncorrectFormat; var t: time.tm = now.*; t.tm_hour = std.fmt.parseInt(u6, hour_str, 10) catch return ParseTimeError.IncorrectFormat; t.tm_min = std.fmt.parseInt(u6, min_str, 10) catch return ParseTimeError.IncorrectFormat; return time.mktime(&t); } test "parseTime should parse hh:mm string" { const Suite = struct { input: []const u8, expected_hour: u6, expected_min: u6, }; const suites = [_]Suite{ .{ .input = "00:00", .expected_hour = 0, .expected_min = 0, }, .{ .input = "08:31", .expected_hour = 8, .expected_min = 31, }, .{ .input = "23:59", .expected_hour = 23, .expected_min = 59, }, .{ .input = "24:00", .expected_hour = 0, .expected_min = 0, }, }; for (suites) |suite| { const date = time.tm{ .tm_isdst = -1, .tm_year = 2001, .tm_mon = 2, .tm_mday = 9, }; const parsed = try parseTime(&date, suite.input); var parsed_tm: time.tm = undefined; _ = time.localtime_r(&parsed, &parsed_tm); try std.testing.expectEqual(suite.expected_hour, parsed_tm.tm_hour); try std.testing.expectEqual(suite.expected_min, parsed_tm.tm_min); } } test "parseTime should reject invalid formats" { const suites = [_][]const u8{ "", " ", " 0:11", "07:30PM", "aa:bb", "01-10", "0832", "23.56", "seven", }; for (suites) |suite| { const date = time.tm{ .tm_isdst = -1, .tm_year = 2001, .tm_mon = 2, .tm_mday = 9, }; const result = parseTime(&date, suite); try std.testing.expectError(ParseTimeError.IncorrectFormat, result); } } pub const TimeRange = struct { start: time.time_t, end: time.time_t, pub const InitError = error{ IncorrectStartTimeFormat, IncorrectEndTimeFormat, StartAndEndTimeEquals, }; const whole_day: time.time_t = 24 * 60 * 60; pub fn init(now: *const time.tm, start_str: []const u8, end_str: []const u8) InitError!@This() { const start = parseTime(now, start_str) catch return InitError.IncorrectStartTimeFormat; var end = parseTime(now, end_str) catch return InitError.IncorrectEndTimeFormat; const diff = time.difftime(end, start); if (diff == 0) { return InitError.StartAndEndTimeEquals; } else if (diff < 0) { end += whole_day; } return .{ .start = start, .end = end, }; } pub fn isIntersecting(self: *const @This(), x: time.time_t) bool { if (self.start <= x and self.end >= x) { return true; } if ((self.start - whole_day) <= x and (self.end - whole_day) >= x) { return true; } return ((self.start + whole_day) <= x and (self.end + whole_day) >= x); } }; test TimeRange { const date = time.tm{ .tm_isdst = -1, .tm_year = 2001, .tm_mon = 2, .tm_mday = 9, }; const Suite = struct { start: []const u8, end: []const u8, inside: []const time.time_t = &.{}, outside: []const time.time_t = &.{}, pub fn formatTime(allocator: std.mem.Allocator, t: time.time_t) ![]const u8 { var tm: time.tm = undefined; _ = time.localtime_r(&t, &tm); const year: u32 = @intCast(tm.tm_year); const month: u32 = @intCast(tm.tm_mon + 1); const day: u5 = @intCast(tm.tm_mday); const hour: u6 = @intCast(tm.tm_hour); const min: u6 = @intCast(tm.tm_min); return std.fmt.allocPrint(allocator, "{d:0>4}-{d:0>2}-{d:0>2}T{d:0>2}:{d:0>2}", .{ year, month, day, hour, min, }); } }; const suites = [_]Suite{ .{ .start = "08:30", .end = "17:30", .inside = &.{ try parseTime(&date, "08:30"), try parseTime(&date, "08:31"), try parseTime(&date, "09:00"), try parseTime(&date, "17:29"), try parseTime(&date, "17:30"), }, .outside = &.{ try parseTime(&date, "00:00"), try parseTime(&date, "08:29"), try parseTime(&date, "17:31"), }, }, .{ .start = "18:00", .end = "08:00", .inside = &.{ try parseTime(&date, "00:00"), try parseTime(&date, "08:00"), try parseTime(&date, "07:59"), try parseTime(&date, "18:00"), try parseTime(&date, "22:59"), }, .outside = &.{ try parseTime(&date, "08:30"), try parseTime(&date, "12:00"), try parseTime(&date, "17:59"), }, }, }; var arena = std.heap.ArenaAllocator.init(std.testing.allocator); defer arena.deinit(); const allocator = arena.allocator(); for (suites) |suite| { const range = try TimeRange.init(&date, suite.start, suite.end); try std.testing.expect(range.end > range.start); for (suite.inside) |t| { std.testing.expect(range.isIntersecting(t)) catch |err| { std.log.err("{s} is not inside {s}~{s}", .{ try Suite.formatTime(allocator, t), try Suite.formatTime(allocator, range.start), try Suite.formatTime(allocator, range.end), }); return err; }; } for (suite.outside) |t| { std.testing.expect(!range.isIntersecting(t)) catch |err| { std.log.err("{s} is not outside {s}~{s}", .{ try Suite.formatTime(allocator, t), try Suite.formatTime(allocator, range.start), try Suite.formatTime(allocator, range.end), }); return err; }; } } }
-
-
themes/catppuccin/default.nix (deleted)
-
@@ -1,291 +0,0 @@# Copyright 2023 Shota FUJI <pockawoooh@gmail.com> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD { config, lib, pkgs, ... }: let cfg = config.themes.catppuccin; radius = 2; gap = 16; in { options = { themes.catppuccin = { flavor = lib.mkOption { type = lib.types.enum [ "latte" "frappe" "macchiato" "mocha" ]; default = "mocha"; description = '' Specify which Catppuccin _flavor_ (color palette) to use. ''; }; }; }; config = let json = builtins.fromJSON ( builtins.readFile ( pkgs.fetchFromGitHub { owner = "catppuccin"; repo = "palette"; rev = "205dd54c6158b7648621cf9fd00e91f03888ce7e"; sha256 = "y14fd8lvnG9hNY6CRU0JgxWouexEw91aIEMkr1NaM/4="; } + "/palette.json" ) ); flavor = json."${cfg.flavor}"; stripSharp = hex: lib.strings.removePrefix "#" hex; darkFlavor = if cfg.flavor == "latte" then "mocha" else cfg.flavor; dark = json."${darkFlavor}"; light = json.latte; in { features.wayland-de = lib.mkIf config.features.wayland-de.enable { niri = { background-color = "transparent"; overview = { backdrop-color = flavor.base.hex; }; layout = { focus-ring = { width = 1; active-color = flavor.overlay1.hex; inactive-color = flavor.surface1.hex; }; border = { width = gap / 5; active-color = flavor.overlay2.hex; inactive-color = flavor.surface0.hex; }; gaps = gap; struts.bottom = gap / -2; }; window-rule-all = { corner-radius = radius; }; }; walker = { css = '' #window.dark { --background-color: ${flavor.base.hex}; --surface-background-color: ${flavor.surface0.hex}; --border-color: ${flavor.lavender.hex}; --foreground-color: ${flavor.text.hex}; --dimmed-foreground-color: ${flavor.subtext0.hex}; } #window.light { --background-color: ${json.latte.base.hex}; --surface-background-color: ${json.latte.surface0.hex}; --border-color: ${json.latte.lavender.hex}; --foreground-color: ${json.latte.text.hex}; --dimmed-foreground-color: ${json.latte.subtext0.hex}; } ''; }; swaylock = { flags = [ "color=${stripSharp flavor.base.hex}" "indicator-thickness=8" "indicator-idle-visible" "inside-color=${stripSharp flavor.base.hex}" "inside-clear-color=${stripSharp flavor.base.hex}" "inside-ver-color=${stripSharp flavor.base.hex}" "inside-wrong-color=${stripSharp flavor.base.hex}" "key-hl-color=${stripSharp flavor.mauve.hex}" "line-color=${stripSharp flavor.surface0.hex}" "line-clear-color=${stripSharp flavor.surface0.hex}" "line-ver-color=${stripSharp flavor.overlay2.hex}" "line-wrong-color=${stripSharp flavor.red.hex}" "ring-color=${stripSharp flavor.base.hex}" "ring-clear-color=${stripSharp flavor.base.hex}" "ring-ver-color=${stripSharp flavor.overlay0.hex}" "ring-wrong-color=${stripSharp flavor.maroon.hex}" "text-color=${stripSharp flavor.text.hex}" "text-clear-color=${stripSharp flavor.text.hex}" "text-ver-color=${stripSharp flavor.subtext1.hex}" "text-wrong-color=${stripSharp flavor.red.hex}" ]; }; }; services.dunst = lib.mkIf config.services.dunst.enable { settings = { global = { width = 400; height = 300; offset = "4x4"; padding = 4; horizontal_padding = 8; frame_width = 2; gap_size = 6; font = "Monospace 10"; corner_radius = 2; }; urgency_low = { background = flavor.base.hex; foreground = flavor.subtext0.hex; frame_color = flavor.overlay1.hex; }; urgency_normal = { background = flavor.base.hex; foreground = flavor.text.hex; frame_color = flavor.blue.hex; }; urgency_critical = { background = flavor.base.hex; foreground = flavor.text.hex; frame_color = flavor.yellow.hex; }; }; }; programs.waybar = lib.mkIf config.programs.waybar.enable { settings = { main = { position = "bottom"; }; }; }; xdg.configFile = let baseStyle = '' * { font-family: Roboto, Helvetica, Arial, sans-serif; font-size: 16px; } window#waybar { font-weight: bold; } .module { padding: 2px 4px; margin: 4px; border-radius: 3px; } #clock, #network, #pulseaudio, #tray { color: inherit; } ''; in { "waybar/style-light.css".text = '' ${baseStyle} window#waybar { background-color: ${light.base.hex}; color: ${light.text.hex}; } #tray { background-color: ${light.sapphire.hex}; } #pulseaudio:hover { background-color: ${light.surface0.hex}; } ''; "waybar/style-dark.css".text = '' ${baseStyle} window#waybar { background-color: ${dark.base.hex}; color: ${dark.text.hex}; } #tray { background-color: transparent; } #pulseaudio:hover { background-color: ${dark.surface0.hex}; } ''; }; programs.ghostty = let darkFlavor = if cfg.flavor == "latte" then "mocha" else cfg.flavor; in { settings = { theme = "light:catppuccin-latte-corrected,dark:Catppuccin ${lib.strings.toSentenceCase darkFlavor}"; }; themes.catppuccin-latte-corrected = { palette = [ "0=${json.latte.crust.hex}" "1=${json.latte.red.hex}" "2=${json.latte.green.hex}" "3=${json.latte.yellow.hex}" "4=${json.latte.blue.hex}" "5=${json.latte.pink.hex}" "6=${json.latte.teal.hex}" "7=${json.latte.subtext0.hex}" "8=${json.latte.surface2.hex}" "9=#de293e" "10=#49af3d" "11=#eea02d" "12=#456eff" "13=#fe85d8" "14=#2d9fa8" "15=${json.latte.text.hex}" ]; background = stripSharp json.latte.base.hex; foreground = stripSharp json.latte.text.hex; cursor-color = stripSharp json.latte.rosewater.hex; selection-background = stripSharp json.latte.surface2.hex; selection-foreground = stripSharp json.latte.text.hex; }; }; }; }
-