diff --git a/infra/libkookie/home-manager-stable/.github/CODEOWNERS b/infra/libkookie/home-manager-stable/.github/CODEOWNERS new file mode 100644 index 00000000000..9a2ee5931ba --- /dev/null +++ b/infra/libkookie/home-manager-stable/.github/CODEOWNERS @@ -0,0 +1,468 @@ +* @rycee + +/flake.nix @bqv @kisik21 + +/modules/home-environment.nix @rycee + +/modules/i18n/input-method @Kranzes +/tests/modules/i18n/input-method @Kranzes + +/modules/launchd @midchildan + +/modules/misc/dconf.nix @rycee + +/modules/misc/fontconfig.nix @rycee +/tests/modules/misc/fontconfig @rycee + +/modules/misc/gtk.nix @rycee + +/modules/config/home-cursor.nix @polykernel @league + +/modules/config/i18n.nix @midchildan +/tests/modules/config/i18n @midchildan + +/modules/misc/news.nix @rycee + +/modules/misc/nix.nix @polykernel +/tests/modules/misc/nix @polykernel + +/modules/misc/nixpkgs-disabled.nix @thiagokokada + +/modules/misc/numlock.nix @evanjs +/tests/modules/misc/numlock @evanjs + +/modules/misc/pam.nix @rycee +/tests/modules/misc/pam @rycee + +/modules/misc/qt.nix @rycee + +/modules/misc/submodule-support.nix @rycee + +/modules/misc/tmpfiles.nix @dawidsowa + +/modules/misc/vte.nix @rycee + +/modules/misc/xdg-mime-apps.nix @pacien + +/modules/misc/xdg-user-dirs.nix @pacien + +/modules/misc/xdg-system-dirs.nix @tadfisher +/tests/modules/misc/xdg/system-dirs.nix @tadfisher + +/modules/misc/xdg-desktop-entries.nix @cwyc +/tests/modules/misc/xdg/desktop-entries.nix @cwyc +/tests/modules/misc/xdg/desktop-full-expected.desktop @cwyc +/tests/modules/misc/xdg/desktop-min-expected.desktop @cwyc + +/modules/programs/aria2.nix @JustinLovinger + +/modules/programs/autojump.nix @evanjs +/tests/modules/programs/autojump @evanjs + +/modules/programs/atuin.nix @hawkw +/tests/modules/programs/atuin @hawkw + +/modules/programs/autorandr.nix @uvNikita + +/modules/programs/bash.nix @rycee + +/modules/programs/bat.nix @marsam + +/modules/programs/beets.nix @rycee + +/modules/programs/bottom.nix @polykernel +/tests/modules/programs/bottom @polykernel + +/modules/programs/broot.nix @aheaume + +/modules/programs/dircolors.nix @JustinLovinger + +/modules/programs/direnv.nix @rycee + +/modules/programs/eclipse.nix @rycee + +/modules/programs/emacs.nix @rycee + +/modules/programs/eww.nix @mainrs + +/modules/programs/exa.nix @kalhauge + +/modules/programs/firefox.nix @rycee + +/modules/programs/foot.nix @plabadens +/tests/modules/programs/foot @plabadens + +/modules/services/fusuma.nix @iosmanthus +/tests/modules/services/fusuma @iosmanthus + +/modules/programs/gh.nix @Gerschtli @berbiche +/tests/modules/programs/gh @Gerschtli @berbiche + +/modules/programs/git.nix @rycee + +/modules/programs/gitui/gitui.nix @mifom +/modules/programs/gitui/default_key_config.ron @mifom + +/modules/programs/gnome-terminal.nix @kamadorueda @rycee + +/modules/programs/go.nix @rvolosatovs + +/modules/programs/helix.nix @Philipp-M +/tests/modules/programs/helix @Philipp-M + +/modules/programs/hexchat.nix @thiagokokada +/tests/modules/programs/hexchat @thiagokokada + +/modules/programs/himalaya.nix @ambroisie +/tests/modules/programs/himalaya @ambroisie + +/modules/programs/home-manager.nix @rycee + +/modules/programs/htop.nix @bjpbakker +/tests/modules/htop @bjpbakker + +/modules/programs/i3status.nix @JustinLovinger + +/modules/programs/i3status-rust.nix @workflow + +/modules/programs/java.nix @ShamrockLee + +/modules/programs/just.nix @maximsmol + +/modules/programs/keychain.nix @marsam + +/modules/programs/kodi.nix @dwagenk +/tests/modules/programs/kodi @dwagenk + +/modules/programs/lazygit.nix @kalhauge + +/modules/programs/less.nix @pamplemousse +/tests/modules/programs/less @pamplemousse + +/modules/programs/lesspipe.nix @rycee + +/modules/programs/lf.nix @owm111 +/tests/modules/programs/lf @owm111 + +/modules/programs/lieer.nix @tadfisher + +/modules/programs/lsd.nix @marsam + +/modules/programs/matplotlib.nix @rprospero + +/modules/programs/mangohud.nix @ZerataX +/tests/modules/programs/mangohud @ZerataX + +/modules/programs/mbsync.nix @KarlJoad +/tests/modules/programs/mbsync @KarlJoad + +/modules/programs/mcfly.nix @marsam + +/modules/programs/mpv.nix @tadeokondrak @thiagokokada +/tests/modules/programs/mpv @thiagokokada + +/modules/programs/mu.nix @KarlJoad + +/modules/programs/navi.nix @marsam + +/modules/programs/ncmpcpp.nix @olmokramer +/tests/modules/programs/ncmpcpp @olmokramer +/tests/modules/programs/ncmpcpp-linux @olmokramer + +/modules/programs/ncspot.nix @marsam + +/modules/programs/ne.nix @cwyc +/tests/modules/programs/ne @cwyc + +/modules/programs/newsboat.nix @sumnerevans +/tests/modules/programs/newsboat @sumnerevans + +/modules/programs/nix-index.nix @ambroisie +/tests/modules/programs/nix-index @ambroisie + +/modules/programs/nnn.nix @thiagokokada +/tests/modules/programs/nnn @thiagokokada + +/modules/programs/noti.nix @marsam + +/modules/programs/nushell.nix @Philipp-M +/tests/modules/programs/nushell @Philipp-M + +/modules/programs/obs-studio.nix @adisbladis + +/modules/programs/octant.nix @06kellyjac + +/modules/programs/opam.nix @marsam + +/modules/programs/openssh.nix @rycee + +/modules/programs/pandoc.nix @kirelagin +/tests/modules/programs/pandoc @kirelagin + +/modules/programs/password-store.nix @pacien + +/modules/programs/pazi.nix @marsam + +/modules/programs/pidgin.nix @rycee + +/modules/programs/piston-cli.nix @ethancedwards8 + +/modules/programs/powerline-go.nix @DamienCassou + +/modules/programs/pubs.nix @loicreynier +/tests/modules/programs/pubs @loicreynier + +/modules/programs/pylint.nix @florpe + +/modules/programs/rbw.nix @ambroisie +/tests/modules/programs/rbw @ambroisie + +/modules/programs/rofi.nix @thiagokokada +/tests/modules/programs/rofi @thiagokokada + +/modules/programs/rofi-pass.nix @seylerius +/tests/modules/programs/rofi-pass @seylerius + +/modules/programs/rtorrent.nix @marsam + +/modules/programs/sagemath.nix @kirelagin +/tests/modules/programs/sagemath @kirelagin + +/modules/programs/sbt.nix @kubukoz +/tests/modules/programs/sbt @kubukoz + +/modules/programs/scmpuff.nix @cpcloud +/tests/modules/programs/scmpuff @cpcloud + +/modules/programs/senpai.nix @malte-v + +/modules/programs/sioyek.nix @podocarp + +/modules/programs/sm64ex.nix @ivarwithoutbones +/tests/modules/programs/sm64ex @ivarwithoutbones + +/modules/programs/sqls.nix @marsam + +/modules/programs/ssh.nix @rycee + +/modules/programs/starship.nix @marsam + +/modules/programs/tealdeer.nix @marsam + +/modules/programs/terminator.nix @chisui + +/modules/programs/texlive.nix @rycee + +/modules/programs/timidity.nix @amesgen + +/modules/programs/tiny.nix @kmaasrud + +/modules/programs/topgrade.nix @msfjarvis +/tests/modules/programs/topgrade @msfjarvis + +/mdules/programs/watson.nix @polykernel +/tests/modules/programs/watson @polykernel + +/modules/programs/waybar.nix @berbiche +/tests/modules/programs/waybar @berbiche + +/modules/programs/xmobar.nix @t4ccer +/tests/modules/programs/xmobar @t4ccer + +/modules/programs/z-lua.nix @marsam + +/modules/programs/zathura.nix @rprospero + +/modules/programs/zellij.nix @mainrs + +/modules/programs/zoxide.nix @marsam + +/modules/programs/zsh/prezto.nix @NickHu + +/modules/services/barrier.nix @Kritnich +/tests/modules/services/barrier @Kritnich + +/modules/services/betterlockscreen.nix @SebTM + +/modules/services/caffeine.nix @uvNikita + +/modules/services/cbatticon.nix @pmiddend + +/modules/services/clipmenu.nix @DamienCassou + +/modules/services/devilspie2.nix @dawidsowa +/tests/modules/services/devilspie2 @dawidsowa + +/modules/services/dropbox.nix @eyJhb +/tests/modules/services/dropbox @eyJhb + +/modules/services/dunst.nix @rycee + +/modules/services/easyeffects.nix @fufexan + +/modules/services/emacs.nix @tadfisher + +/modules/services/etesync-dav.nix @Valodim + +/modules/services/espanso.nix @lucasew + +/modules/services/flameshot.nix @moredhel + +/modules/services/fluidsynth.nix @Valodim + +/modules/services/fnott.nix @polykernel +/tests/modules/services/fnott @polykernel + +/modules/services/git-sync.nix @IvanMalison + +/modules/services/gnome-keyring.nix @rycee + +/modules/services/gpg-agent.nix @rycee + +/modules/services/grobi.nix @mbrgm + +/modules/services/gromit-mpx.nix @pjones +/tests/modules/services/gromit-mpx @pjones + +/modules/services/home-manager-auto-upgrade.nix @pinage404 +/tests/modules/services/home-manager-auto-upgrade @pinage404 + +/modules/services/hound.nix @adisbladis + +/modules/services/imapnotify.nix @nickhu + +/modules/services/kanshi.nix @nurelin +/tests/modules/services/kanshi @nurelin + +/modules/services/kdeconnect.nix @adisbladis + +/modules/services/keepassx.nix @rycee + +/modules/services/lieer.nix @tadfisher + +/modules/services/lorri.nix @Gerschtli + +/modules/services/mako.nix @onny + +/modules/services/mbsync.nix @pjones + +/modules/services/mopidy.nix @foo-dogsquared +/tests/modules/services/mopidy @foo-dogsquared + +/modules/services/mpdris2.nix @pjones + +/modules/services/mpd-discord-rpc.nix @Kranzes + +/modules/services/mpris-proxy.nix @ThibautMarty + +/modules/services/muchsync.nix @pacien + +/modules/services/network-manager-applet.nix @rycee + +/modules/services/notify-osd.nix @imalison + +/modules/services/opensnitch-ui.nix @onny + +/modules/services/pantalaimon.nix @jojosch +/tests/modules/services/pantalaimon @jojosch + +/modules/services/parcellite.nix @gleber + +/modules/services/pass-secret-service.nix @cab404 + +/modules/services/password-store-sync.nix @pacien + +/modules/services/pasystray.nix @pltanton + +/modules/services/pbgopy.nix @ivarwithoutbones +/tests/modules/services/pbgopy @ivarwithoutbones + +/modules/services/plan9port.nix @ehmry + +/modules/services/playerctld.nix @fendse +/tests/modules/playerctld @fendse + +/modules/services/poweralertd.nix @ThibautMarty + +/modules/services/pulseeffects.nix @jonringer + +/modules/services/random-background.nix @rycee + +/modules/services/redshift-gammastep @rycee @petabyteboy @thiagokokada +/tests/modules/redshift-gammastep @thiagokokada + +/modules/services/screen-locker.nix @jrobsonchase @rszamszur +/tests/modules/services/screen-locker @jrobsonchase @rszamszur + +/modules/services/status-notifier-watcher.nix @pltanton + +/modules/services/syncthing.nix @rycee + +/modules/services/taffybar.nix @rycee + +/modules/services/tahoe-lafs.nix @rycee + +/modules/services/taskwarrior-sync.nix @minijackson @pacien + +/modules/services/trayer.nix @AndreasMager +/tests/modules/services/trayer @AndreasMager + +/modules/services/twmn.nix @Austreelis +/tests/modules/services/twmn @Austreelis + +/modules/services/udiskie.nix @rycee + +/modules/services/unison.nix @pacien + +/modules/services/window-managers/bspwm @ncfavier +/tests/modules/services/window-managers/bspwm @ncfavier + +/modules/services/window-managers/herbstluftwm @olmokramer +/tests/modules/services/window-managers/herbstluftwm @olmokramer + +/modules/services/window-managers/i3-sway/i3.nix @sumnerevans @sebtm +/tests/modules/services/window-managers/i3 @sumnerevans @sebtm + +/modules/services/window-managers/i3-sway/lib @sumnerevans @sebtm + +/modules/services/window-managers/i3-sway/sway.nix @alexarice @sumnerevans @sebtm +/tests/modules/services/window-managers/sway @sumnerevans @sebtm + +/modules/services/window-managers/i3-sway/swaynag.nix @polykernel + +/modules/services/wlsunset.nix @matrss +/tests/modules/services/wlsunset @matrss + +/modules/services/xcape.nix @nickhu + +/modules/services/xembed-sni-proxy.nix @rycee + +/modules/services/xidlehook.nix @dschrempf + +/modules/services/xscreensaver.nix @rycee + +/modules/services/xsuspender.nix @offlinehacker + +/modules/systemd.nix @rycee + +/modules/xresources.nix @rycee + +/modules/xsession.nix @rycee + +/modules/services/volnoti.nix @IvanMalison + +/modules/services/systembus-notify.nix @asymmetric + +/modules/targets/darwin @midchildan +/tests/modules/targets-darwin @midchildan + +/modules/programs/tint2.nix @CarlosLoboxyz + +Makefile @thiagokokada + +/modules/services/swayidle.nix @c0deaddict +/tests/modules/services/swayidle @c0deaddict + +/modules/programs/ion.nix @jo1gi + +/modules/services/plex-mpv-shim.nix @starcraft66 diff --git a/infra/libkookie/home-manager-stable/.github/ISSUE_TEMPLATE/feature-request.md b/infra/libkookie/home-manager-stable/.github/ISSUE_TEMPLATE/feature-request.md new file mode 100644 index 00000000000..c984617828e --- /dev/null +++ b/infra/libkookie/home-manager-stable/.github/ISSUE_TEMPLATE/feature-request.md @@ -0,0 +1,15 @@ +--- +name: Feature request +about: Ask for a new feature to be added (module, program, etc.) +title: '' +labels: feature request +assignees: rycee, berbiche, sumnerevans + +--- + + + +### Description + diff --git a/infra/libkookie/home-manager-stable/.github/ISSUE_TEMPLATE/issue.yaml b/infra/libkookie/home-manager-stable/.github/ISSUE_TEMPLATE/issue.yaml new file mode 100644 index 00000000000..e7a0dc3c032 --- /dev/null +++ b/infra/libkookie/home-manager-stable/.github/ISSUE_TEMPLATE/issue.yaml @@ -0,0 +1,46 @@ +name: Bug Report +description: File a bug/issue +title: 'bug: ' +labels: [bug, triage] + +# We cannot use nix-community/home-manager +# See https://github.com/dear-github/dear-github/issues/170 +assignees: [rycee, berbiche, sumnerevans] + +body: +- type: checkboxes + attributes: + label: Is there an existing issue for this? + description: | + Please search to see if an issue already exists for the bug you encountered. + options: + - label: I have searched the existing issues + required: true +- type: textarea + attributes: + label: Issue description + description: | + Please describe the issue. + + For support and help please use the IRC channel #home-manager at irc.oftc.net or + Matrix room instead. + validations: + required: false +- type: textarea + attributes: + label: Maintainer CC + description: | + Please @ people who are in the `meta.maintainers` list of the offending module. + If in doubt, check `git blame` for whoever last touched something. + validations: + required: false +- type: textarea + id: system + attributes: + label: System information + description: | + Please run `nix-shell -p nix-info --run "nix-info -m"` and paste the result. + render: markdown + validations: + required: true + diff --git a/infra/libkookie/home-manager-stable/.github/PULL_REQUEST_TEMPLATE.md b/infra/libkookie/home-manager-stable/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000000..fd0a266be96 --- /dev/null +++ b/infra/libkookie/home-manager-stable/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,44 @@ +### Description + + + +### Checklist + + + +- [ ] Change is backwards compatible. + +- [ ] Code formatted with `./format`. + +- [ ] Code tested through `nix-shell --pure tests -A run.all`. + +- [ ] Test cases updated/added. See [example](https://github.com/nix-community/home-manager/commit/f3fbb50b68df20da47f9b0def5607857fcc0d021#diff-b61a6d542f9036550ba9c401c80f00ef). + +- [ ] Commit messages are formatted like + + ``` + {component}: {description} + + {long description} + ``` + + See [CONTRIBUTING](https://github.com/nix-community/home-manager/blob/master/docs/contributing.adoc#sec-commit-style) for more information and [recent commit messages](https://github.com/nix-community/home-manager/commits/master) for examples. + +- If this PR adds a new module + + - [ ] Added myself as module maintainer. See [example](https://github.com/nix-community/home-manager/blob/068ff76a10e95820f886ac46957edcff4e44621d/modules/programs/lesspipe.nix#L6). + + - [ ] Added myself and the module files to `.github/CODEOWNERS`. diff --git a/infra/libkookie/home-manager-stable/.github/dependabot.yml b/infra/libkookie/home-manager-stable/.github/dependabot.yml new file mode 100644 index 00000000000..c1d917c2cd0 --- /dev/null +++ b/infra/libkookie/home-manager-stable/.github/dependabot.yml @@ -0,0 +1,17 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + target-branch: "master" + schedule: + interval: "weekly" + commit-message: + prefix: "ci:" + + - package-ecosystem: "github-actions" + directory: "/" + target-branch: "release-21.11" + schedule: + interval: "weekly" + commit-message: + prefix: "ci:" diff --git a/infra/libkookie/home-manager-stable/.github/stale.yml b/infra/libkookie/home-manager-stable/.github/stale.yml new file mode 100644 index 00000000000..adc74083f65 --- /dev/null +++ b/infra/libkookie/home-manager-stable/.github/stale.yml @@ -0,0 +1,71 @@ +# Configuration for probot-stale - https://github.com/probot/stale +daysUntilStale: 90 +daysUntilClose: false +staleLabel: "status: stale" +issues: + markComment: | +

+ Thank you for your contribution! + I marked this issue as stale due to inactivity. + Please be considerate of people watching this issue and receiving notifications before commenting 'I have this issue too'. + We welcome additional information that will help resolve this issue. + Please read the relevant sections below before commenting. +

+ +
+ If you are the original author of the issue +

+ + * If this is resolved, please consider closing it so that the maintainers know not to focus on this. + * If this might still be an issue, but you are not interested in promoting its resolution, please consider closing it while encouraging others to take over and reopen an issue if they care enough. + * If you know how to solve the issue, please consider submitting a Pull Request that addresses this issue. + +

+
+ +
+ If you are not the original author of the issue +

+ + * If you are also experiencing this issue, please add details of your situation to help with the debugging process. + * If you know how to solve the issue, please consider submitting a Pull Request that addresses this issue. + +

+
+ +
+ Memorandum on closing issues +

+ Don't be afraid to manually close an issue, even if it holds valuable information. + Closed issues stay in the system for people to search, read, cross-reference, or even reopen – nothing is lost! + Closing obsolete issues is an important way to help maintainers focus their time and effort. +

+
+pulls: + markComment: | +

+ Thank you for your contribution! + I marked this pull request as stale due to inactivity. + Please read the relevant sections below before commenting. +

+ +
+ If you are the original author of the PR +

+ + * GitHub sometimes doesn't notify people who commented / reviewed a PR previously when you (force) push commits. *If you have addressed the reviews* you can [officially ask for a review](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/requesting-a-pull-request-review) from those who commented to you or anyone else. + * If it is unfinished but you plan to finish it, please mark it as a draft. + * If you don't expect to work on it any time soon, please consider closing it with a short comment encouraging someone else to pick up your work. + * To get things rolling again, rebase the PR against the target branch and address valid comments. + +

+
+ +
+ If you are not the original author of the PR +

+ + * If you want to pick up the work on this PR, please create a new PR and indicate that it supercedes and closes this PR. + +

+
diff --git a/infra/libkookie/home-manager-stable/.github/workflows/github_pages.yml b/infra/libkookie/home-manager-stable/.github/workflows/github_pages.yml new file mode 100644 index 00000000000..1e0a0f9a9f8 --- /dev/null +++ b/infra/libkookie/home-manager-stable/.github/workflows/github_pages.yml @@ -0,0 +1,28 @@ +name: GitHub Pages +on: + push: + branches: + - master +jobs: + publish: + strategy: + matrix: + os: [ubuntu-latest] + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v3 + - uses: cachix/install-nix-action@v17 + with: + nix_path: nixpkgs=channel:nixos-unstable + - uses: cachix/cachix-action@v10 + with: + name: nix-community + signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}' + - run: | + nix-build -A docs.html + cp -r result/share/doc/home-manager public + - name: Deploy + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./public diff --git a/infra/libkookie/home-manager-stable/.github/workflows/test.yml b/infra/libkookie/home-manager-stable/.github/workflows/test.yml new file mode 100644 index 00000000000..22e76b5958c --- /dev/null +++ b/infra/libkookie/home-manager-stable/.github/workflows/test.yml @@ -0,0 +1,30 @@ +name: Test +on: + pull_request: + schedule: + - cron: "30 2 * * *" +jobs: + tests: + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest] + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v3 + - uses: cachix/install-nix-action@v17 + with: + nix_path: nixpkgs=channel:nixos-unstable + - uses: cachix/cachix-action@v10 + with: + name: nix-community + signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}' + - run: | + if grep -R --exclude stdlib-extended.nix literalExample modules ; then + echo "Error: literalExample should be replaced by literalExpression" > /dev/stderr + exit 1 + fi + - run: nix-build -A docs.jsonModuleMaintainers + - run: ./format -c + - run: nix-shell . -A install + - run: nix-shell --arg enableBig false --pure tests -A run.all diff --git a/infra/libkookie/home-manager-stable/.gitignore b/infra/libkookie/home-manager-stable/.gitignore new file mode 100644 index 00000000000..3526db71892 --- /dev/null +++ b/infra/libkookie/home-manager-stable/.gitignore @@ -0,0 +1,2 @@ +/flake.lock +/result* diff --git a/infra/libkookie/home-manager-stable/.gitlab-ci.yml b/infra/libkookie/home-manager-stable/.gitlab-ci.yml new file mode 100644 index 00000000000..37b08ef6d29 --- /dev/null +++ b/infra/libkookie/home-manager-stable/.gitlab-ci.yml @@ -0,0 +1,41 @@ +image: nixos/nix:latest + +variables: + NIX_PATH: "nixpkgs=channel:nixos-unstable" + +stages: + - test + - deploy + +Run tests: + stage: test + script: + - nix-shell --pure tests -A run.files-text + rules: + - if: $CI_COMMIT_BRANCH == "master" + when: always + +pages: + stage: deploy + script: + - nix-build -A docs.html + - mkdir public + - cp -r ./result/share/doc/home-manager/* public/ + artifacts: + paths: + - public + rules: + - if: $CI_COMMIT_BRANCH == "master" + when: always + +Deploy NUR: + stage: deploy + variables: + HM_BRANCH: $CI_COMMIT_REF_NAME + HM_COMMIT_SHA: $CI_COMMIT_SHA + trigger: + project: rycee/nur-expressions + branch: master + rules: + - if: $CI_COMMIT_BRANCH == "master" || $CI_COMMIT_BRANCH =~ /^release-/ + when: always diff --git a/infra/libkookie/home-manager-stable/.release b/infra/libkookie/home-manager-stable/.release new file mode 100644 index 00000000000..a01c758c189 --- /dev/null +++ b/infra/libkookie/home-manager-stable/.release @@ -0,0 +1 @@ +22.05 diff --git a/infra/libkookie/home-manager-stable/LICENSE b/infra/libkookie/home-manager-stable/LICENSE new file mode 100644 index 00000000000..97c93528183 --- /dev/null +++ b/infra/libkookie/home-manager-stable/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017-2022 Home Manager contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/infra/libkookie/home-manager-stable/Makefile b/infra/libkookie/home-manager-stable/Makefile new file mode 100644 index 00000000000..5172e8386ff --- /dev/null +++ b/infra/libkookie/home-manager-stable/Makefile @@ -0,0 +1,20 @@ +.PHONY: all all-tests test test-install format +NIXPKGS_REV := nixpkgs-unstable +NIX_PATH := nixpkgs=https://github.com/NixOS/nixpkgs/archive/${NIXPKGS_REV}.tar.gz + +all: all-tests test-install + +all-tests: + $(MAKE) test TEST=all + +test: +ifndef TEST + $(error Use 'make test TEST=' to run desired test) +endif + nix-shell --pure tests -I ${NIX_PATH} -A run.${TEST} + +test-install: + HOME=$(shell mktemp -d) NIX_PATH=${NIX_PATH} nix-shell . -A install + +format: + ./format diff --git a/infra/libkookie/home-manager-stable/README.md b/infra/libkookie/home-manager-stable/README.md new file mode 100644 index 00000000000..095effcd3a2 --- /dev/null +++ b/infra/libkookie/home-manager-stable/README.md @@ -0,0 +1,134 @@ +Home Manager using Nix +====================== + +This project provides a basic system for managing a user environment +using the [Nix][] package manager together with the Nix libraries +found in [Nixpkgs][]. It allows declarative configuration of user +specific (non global) packages and dotfiles. + +Usage +----- + +Before attempting to use Home Manager please read the warning below. + +For a systematic overview of Home Manager and its available options, +please see + +- the [Home Manager manual][manual] and +- the [Home Manager configuration options][configuration options]. + +If you would like to contribute to Home Manager +then please have a look at the [contributing][] chapter of the manual. + +Words of warning +---------------- + +Unfortunately, it is quite possible to get difficult to understand +errors when working with Home Manager, such as infinite loops with no +clear source reference. You should therefore be comfortable using the +Nix language and the various tools in the Nix ecosystem. Reading +through the [Nix Pills][] document is a good way to familiarize +yourself with them. + +If you are not very familiar with Nix but still want to use Home +Manager then you are strongly encouraged to start with a small and +very simple configuration and gradually make it more elaborate as you +learn. + +In some cases Home Manager cannot detect whether it will overwrite a +previous manual configuration. For example, the Gnome Terminal module +will write to your dconf store and cannot tell whether a configuration +that it is about to be overwritten was from a previous Home Manager +generation or from manual configuration. + +Home Manager targets [NixOS][] unstable and NixOS version 22.05 (the +current stable version), it may or may not work on other Linux +distributions and NixOS versions. + +Also, the `home-manager` tool does not explicitly support rollbacks at +the moment so if your home directory gets messed up you'll have to fix +it yourself. See the [rollbacks][] section for instructions on how to +manually perform a rollback. + +Now when your expectations have been built up and you are eager to try +all this out you can go ahead and read the rest of this text. + +Contact +------- + +You can chat with us on IRC in the channel [#home-manager][] on [OFTC][]. +There is also a [Matrix room](https://matrix.to/#/#hm:rycee.net), +which is bridged to the IRC channel. + +Installation +------------ + +Home Manager can be used in three primary ways: + +1. Using the standalone `home-manager` tool. For platforms other than + NixOS and Darwin, this is the only available choice. It is also + recommended for people on NixOS or Darwin that want to manage their + home directory independently of the system as a whole. See + [Standalone installation][manual standalone install] in the manual + for instructions on how to perform this installation. + +2. As a module within a NixOS system configuration. This allows the + user profiles to be built together with the system when running + `nixos-rebuild`. See [NixOS module installation][manual nixos + install] in the manual for a description of this setup. + +3. As a module within a [nix-darwin][] system configuration. This + allows the user profiles to be built together with the system when + running `darwin-rebuild`. See [nix-darwin module + installation][manual nix-darwin install] in the manual for a + description of this setup. + +Home Manager provides both the channel-based setup and the flake-based one. +See [Nix Flakes][manual nix flakes] for a description of the flake-based setup. + +Translations +------------ + +Home Manager has basic support for internationalization through +[gettext](https://www.gnu.org/software/gettext/). The translations are +hosted by [Weblate](https://weblate.org/). If you would like to +contribute to the translation effort then start by going to the +[Home Manager Weblate project](https://hosted.weblate.org/engage/home-manager/). + + +Translation status + + +Releases +-------- + +Home Manager is developed against `nixpkgs-unstable` branch, which +often causes it to contain tweaks for changes/packages not yet +released in stable NixOS. To avoid breaking users' configurations, +Home Manager is released in branches corresponding to NixOS releases +(e.g. `release-22.05`). These branches get fixes, but usually not new +modules. If you need a module to be backported, then feel free to open +an issue. + +License +------- + +This project is licensed under the terms of the [MIT license](LICENSE). + +[Nix]: https://nixos.org/explore.html +[NixOS]: https://nixos.org/ +[Nixpkgs]: https://github.com/NixOS/nixpkgs +[manual]: https://nix-community.github.io/home-manager/index.html +[contributing]: https://nix-community.github.io/home-manager/#ch-contributing +[manual usage]: https://nix-community.github.io/home-manager/#ch-usage +[configuration options]: https://nix-community.github.io/home-manager/options.html +[#home-manager]: https://webchat.oftc.net/?channels=home-manager +[OFTC]: https://oftc.net/ +[Nix Pills]: https://nixos.org/guides/nix-pills/ +[Nix Flakes]: https://nixos.wiki/wiki/Flakes +[nix-darwin]: https://github.com/LnL7/nix-darwin +[manual standalone install]: https://nix-community.github.io/home-manager/index.html#sec-install-standalone +[manual nixos install]: https://nix-community.github.io/home-manager/index.html#sec-install-nixos-module +[manual nix-darwin install]: https://nix-community.github.io/home-manager/index.html#sec-install-nix-darwin-module +[manual nix flakes]: https://nix-community.github.io/home-manager/index.html#ch-nix-flakes +[rollbacks]: https://nix-community.github.io/home-manager/index.html#sec-usage-rollbacks diff --git a/infra/libkookie/home-manager-stable/default.nix b/infra/libkookie/home-manager-stable/default.nix new file mode 100644 index 00000000000..b665b7a66fc --- /dev/null +++ b/infra/libkookie/home-manager-stable/default.nix @@ -0,0 +1,19 @@ +{ pkgs ? import { } }: + +rec { + docs = with import ./docs { inherit pkgs; }; { + html = manual.html; + manPages = manPages; + json = options.json; + jsonModuleMaintainers = jsonModuleMaintainers; # Unstable, mainly for CI. + }; + + home-manager = pkgs.callPackage ./home-manager { path = toString ./.; }; + + install = + pkgs.callPackage ./home-manager/install.nix { inherit home-manager; }; + + nixos = import ./nixos; + + path = ./.; +} diff --git a/infra/libkookie/home-manager-stable/docs/contributing.adoc b/infra/libkookie/home-manager-stable/docs/contributing.adoc new file mode 100644 index 00000000000..cffa621392c --- /dev/null +++ b/infra/libkookie/home-manager-stable/docs/contributing.adoc @@ -0,0 +1,258 @@ +[[ch-contributing]] +== Contributing + +:open-issues: https://github.com/nix-community/home-manager/issues +:new-issue: https://github.com/nix-community/home-manager/issues/new +:fork-a-repo: https://help.github.com/articles/fork-a-repo/ +:create-a-pull-request: https://help.github.com/articles/creating-a-pull-request/ +:seven-rules: https://chris.beams.io/posts/git-commit/#seven-rules +:news-nix: https://github.com/nix-community/home-manager/blob/master/modules/misc/news.nix +:nixfmt: https://github.com/serokell/nixfmt/ +:example-commit-message: https://github.com/nix-community/home-manager/commit/69f8e47e9e74c8d3d060ca22e18246b7f7d988ef + +Contributions to Home Manager are very welcome. To make the process as smooth as possible for both you and the Home Manager maintainers we provide some guidelines that we ask you to follow. See <> for information on how to set up a suitable development environment and <> for the actual guidelines. + +This text is mainly directed at those who would like to make code contributions to Home Manager. If you just want to report a bug then first look among the already {open-issues}[open issues], if you find one matching yours then feel free to comment on it to add any additional information you may have. If no matching issue exists then go to the {new-issue}[new issue] page and write a description of your problem. Include as much information as you can, ideally also include relevant excerpts from your Home Manager configuration. + +[[sec-contrib-getting-started]] +=== Getting started + +If you have not previously forked Home Manager then you need to do that first. Have a look at GitHub's {fork-a-repo}[Fork a repo] for instructions on how to do this. + +Once you have a fork of Home Manager you should create a branch starting at the most recent `master` branch. Give your branch a reasonably descriptive name. Commit your changes to this branch and when you are happy with the result and it fulfills <> then push the branch to GitHub and {create-a-pull-request}[create a pull request]. + +Assuming your clone is at `$HOME/devel/home-manager` then you can make the `home-manager` command use it by either + +1. overriding the default path by using the `-I` command line option: ++ +[source,console] +$ home-manager -I home-manager=$HOME/devel/home-manager ++ +or + +2. changing the default path by ensuring your configuration includes ++ +[source,nix] +---- +programs.home-manager.enable = true; +programs.home-manager.path = "$HOME/devel/home-manager"; +---- ++ +and running `home-manager switch` to activate the change. Afterwards, `home-manager build` and `home-manager switch` will use your cloned repository. + +The first option is good if you only temporarily want to use your clone. + +[[sec-guidelines]] +=== Guidelines +:irc-home-manager: https://webchat.oftc.net/?channels=home-manager +:valuable-options: https://github.com/Infinisil/rfcs/blob/config-option/rfcs/0042-config-option.md#valuable-options +:rfc-42: https://github.com/Infinisil/rfcs/blob/config-option/rfcs/0042-config-option.md +:assertions: https://nixos.org/manual/nixos/stable/index.html#sec-assertions + +If your contribution satisfy the following rules then there is a good chance it will be merged without too much trouble. The rules are enforced by the Home Manager maintainers and to a lesser extent the Home Manager CI system. + +If you are uncertain how these rules affect the change you would like to make then feel free to start a discussion in the {irc-home-manager}[#home-manager] IRC channel, ideally before you start developing. + +[[sec-guidelines-back-compat]] +==== Maintain backward compatibility + +Your contribution should not cause another user's existing configuration to break unless there is a very good reason and the change should be announced to the user through an {assertions}[assertion] or similar. + +Remember that Home Manager is used in many different environments and you should consider how your change may effect others. For example, + +- Does your change work for people that do not use NixOS? Consider other GNU/Linux distributions and macOS. +- Does your change work for people whose configuration is built on one system and deployed on another system? + +[[sec-guidelines-forward-compat]] +==== Keep forward compatibility in mind + +The master branch of Home Manager tracks the unstable channel of Nixpkgs, which may update package versions at any time. It is therefore important to consider how a package update may affect your code and try to reduce the risk of breakage. + +The most effective way to reduce this risk is to follow the advice in <>. + +[[sec-guidelines-valuable-options]] +==== Add only valuable options + +When creating a new module it is tempting to include every option supported by the software. This is _strongly_ discouraged. Providing many options increases maintenance burden and risk of breakage considerably. This is why only the most {valuable-options}[important software options] should be modeled explicitly. Less important options should be expressible through an `extraConfig` escape hatch. + +A good rule of thumb for the first implementation of a module is to only add explicit options for those settings that absolutely must be set for the software to function correctly. It follows that a module for software that provides sensible default values for all settings would require no explicit options at all. + +If the software uses a structured configuration format like a JSON, YAML, INI, TOML, or even a plain list of key/value pairs then consider using a `settings` option as described in {rfc-42}[Nix RFC 42]. + +[[sec-guidelines-add-tests]] +==== Add relevant tests + +If at all possible, make sure to add new tests and expand existing tests so that your change will keep working in the future. See <> for more information about the Home Manager test suite. + +All contributed code _must_ pass the test suite. + +[[sec-guidelines-module-maintainer]] + +==== Add relevant documentation +:docbook: https://tdg.docbook.org/ +:asciidoc: https://asciidoc.org/ +:docbook-rocks: https://berbiche.github.io/docbook.rocks/ + +Many code changes require changing the documentation as well. Module options should be documented with DocBook. See {docbook-rocks}[DocBook rocks!] for a quick introduction and {docbook}[DocBook 5: The Definitive Guide] for in-depth information of DocBook. Home Manager is itself documented using a combination of DocBook and {asciidoc}[AsciiDoc]. All text is hosted in Home Manager's Git repository. + +The HTML version of the manual containing both the module option descriptions and the documentation of Home Manager can be generated and opened by typing the following in a shell within a clone of the Home Manager Git repository: + +[source,console] +$ nix-build -A docs.html +$ xdg-open ./result/share/doc/home-manager/index.html + +When you have made changes to a module, it is a good idea to check that the man page version of the module options looks good: + +[source,console] +$ nix-build -A docs.manPages +$ man ./result/share/man/man5/home-configuration.nix.5 + +==== Add yourself as a module maintainer + +Every new module _must_ include a named maintainer using the `meta.maintainers` attribute. If you are a user of a module that currently lacks a maintainer then please consider adopting it. + +If you are present in the NixOS maintainer list then you can use that entry. If you are not then you can add yourself to `modules/lib/maintainers.nix` in the Home Manager project. + +Also add yourself to `.github/CODEOWNERS` as owner of the associated module files, including the test files. You will then be automatically added as a reviewer on any new pull request that touches your files. + +Maintainers are encouraged to join the IRC channel and participate when they have opportunity. + +[[sec-guidelines-code-style]] +==== Format your code + +Make sure your code is formatted as described in <>. To maintain consistency throughout the project you are encouraged to browse through existing code and adopt its style also in new code. + +[[sec-guidelines-commit-message-style]] +==== Format your commit messages + +Similar to <> we encourage a consistent commit message format as described in <>. + +[[sec-guidelines-news-style]] +==== Format your news entries + +If your contribution includes a change that should be communicated to users of Home Manager then you can add a news entry. The entry must be formatted as described in <>. + +When new modules are added a news entry should be included but you do not need to create this entry manually. The merging maintainer will create the entry for you. This is to reduce the risk of merge conflicts. + +[[sec-guidelines-conditional-modules]] +==== Use conditional modules and news + +Home Manager includes a number of modules that are only usable on some of the supported platforms. The most common example of platform specific modules are those that define systemd user services, which only works on Linux systems. + +If you add a module that is platform specific then make sure to include a condition in the `loadModule` function call. This will make the module accessible only on systems where the condition evaluates to `true`. + +Similarly, if you are adding a news entry then it should be shown only to users that may find it relevant, see <> for a description of conditional news. + +[[sec-guidelines-licensing]] +==== Mind the license + +The Home Manager project is covered by the MIT license and we can only accept contributions that fall under this license, or are licensed in a compatible way. When you contribute self written code and documentation it is assumed that you are doing so under the MIT license. + +A potential gotcha with respect to licensing are option descriptions. Often it is convenient to copy from the upstream software documentation. When this is done it is important to verify that the license of the upstream documentation allows redistribution under the terms of the MIT license. + +[[sec-commit-style]] +=== Commits + +The commits in your pull request should be reasonably self-contained, that is, each commit should make sense in isolation. In particular, you will be asked to amend any commit that introduces syntax errors or similar problems even if they are fixed in a later commit. + +The commit messages should follow the {seven-rules}[seven rules]. We also ask you to include the affected code component or module in the first line. That is, a commit message should follow the template + +---- +{component}: {description} + +{long description} +---- + +where `{component}` refers to the code component (or module) your change affects, `{description}` is a very brief description of your change, and `{long description}` is an optional clarifying description. As a rare exception, if there is no clear component, or your change affects many components, then the `{component}` part is optional. See <> for a commit message that fulfills these requirements. + +[[ex-commit-message]] +.Compliant commit message +=============================================================================== +The commit {example-commit-message}[69f8e47e9e74c8d3d060ca22e18246b7f7d988ef] contains the commit message + +---- +starship: allow running in Emacs if vterm is used + +The vterm buffer is backed by libvterm and can handle Starship prompts +without issues. +---- + +which ticks all the boxes necessary to be accepted in Home Manager. +=============================================================================== + +Finally, when adding a new module, say `programs/foo.nix`, we use the fixed commit format `foo: add module`. You can, of course, still include a long description if you wish. + +[[sec-code-style]] +=== Code Style + +The code in Home Manager is formatted by the {nixfmt}[nixfmt] tool and the formatting is checked in the pull request tests. Run the `format` tool inside the project repository before submitting your pull request. + +Keep lines at a reasonable width, ideally 80 characters or less. This also applies to string literals. + +We prefer `lowerCamelCase` for variable and attribute names with the accepted exception of variables directly referencing packages in Nixpkgs which use a hyphenated style. For example, the Home Manager option `services.gpg-agent.enableSshSupport` references the `gpg-agent` package in Nixpkgs. + +[[sec-news]] +=== News + +Home Manager includes a system for presenting news to the user. When making a change you, therefore, have the option to also include an associated news entry. In general, a news entry should only be added for truly noteworthy news. For example, a bug fix or new option does generally not need a news entry. + +If you do have a change worthy of a news entry then please add one in {news-nix}[`news.nix`] but you should follow some basic guidelines: + +- The entry timestamp should be in ISO-8601 format having "+00:00" as time zone. For example, "2017-09-13T17:10:14+00:00". A suitable timestamp can be produced by the command ++ +[source,console] +$ date --iso-8601=second --universal + +- The entry condition should be as specific as possible. For example, if you are changing or deprecating a specific option then you could restrict the news to those users who actually use this option. + +- Wrap the news message so that it will fit in the typical terminal, that is, at most 80 characters wide. Ideally a bit less. + +- Unlike commit messages, news will be read without any connection to the Home Manager source code. It is therefore important to make the message understandable in isolation and to those who do not have knowledge of the Home Manager internals. To this end it should be written in more descriptive, prose like way. + +- If you refer to an option then write its full attribute path. That is, instead of writing ++ +---- +The option 'foo' has been deprecated, please use 'bar' instead. +---- ++ +it should read ++ +---- +The option 'services.myservice.foo' has been deprecated, please +use 'services.myservice.bar' instead. +---- + +- A new module, say `foo.nix`, should always include a news entry that has a message along the lines of ++ +---- +A new module is available: 'services.foo'. +---- ++ +If the module is platform specific, e.g., a service module using systemd, then a condition like ++ +[source,nix] +condition = hostPlatform.isLinux; ++ +should be added. If you contribute a module then you don't need to add this entry, the merger will create an entry for you. + +[[sec-tests]] +=== Tests + +Home Manager includes a basic test suite and it is highly recommended to include at least one test when adding a module. Tests are typically in the form of "golden tests" where, for example, a generated configuration file is compared to a known correct file. + +It is relatively easy to create tests by modeling the existing tests, found in the `tests` project directory. + +The full Home Manager test suite can be run by executing + +[source,console] +$ nix-shell --pure tests -A run.all + +in the project root. List all test cases through + +[source,console] +$ nix-shell --pure tests -A list + +and run an individual test, for example `alacritty-empty-settings`, through + +[source,console] +$ nix-shell --pure tests -A run.alacritty-empty-settings diff --git a/infra/libkookie/home-manager-stable/docs/default.nix b/infra/libkookie/home-manager-stable/docs/default.nix new file mode 100644 index 00000000000..2e65396eaed --- /dev/null +++ b/infra/libkookie/home-manager-stable/docs/default.nix @@ -0,0 +1,131 @@ +{ pkgs + +# Note, this should be "the standard library" + HM extensions. +, lib ? import ../modules/lib/stdlib-extended.nix pkgs.lib }: + +let + + nmdSrc = pkgs.fetchFromGitLab { + name = "nmd"; + owner = "rycee"; + repo = "nmd"; + rev = "9e7a20e6ee3f6751f699f79c0b299390f81f7bcd"; + sha256 = "1s49gjn1wapcjn0q4gabi8jwp8k5f18354a9c1vji0hfqsaknxzj"; + }; + + nmd = import nmdSrc { inherit lib pkgs; }; + + # Make sure the used package is scrubbed to avoid actually + # instantiating derivations. + scrubbedPkgsModule = { + imports = [{ + _module.args = { + pkgs = lib.mkForce (nmd.scrubDerivations "pkgs" pkgs); + pkgs_i686 = lib.mkForce { }; + }; + }]; + }; + + buildModulesDocs = args: + nmd.buildModulesDocs ({ + moduleRootPaths = [ ./.. ]; + mkModuleUrl = path: + "https://github.com/nix-community/home-manager/blob/master/${path}#blob-path"; + channelName = "home-manager"; + } // args); + + hmModulesDocs = buildModulesDocs { + modules = import ../modules/modules.nix { + inherit lib pkgs; + check = false; + } ++ [ scrubbedPkgsModule ]; + docBook.id = "home-manager-options"; + }; + + nixosModuleDocs = buildModulesDocs { + modules = let + nixosModule = module: pkgs.path + "/nixos/modules" + module; + mockedNixos = with lib; { + options = { + environment.pathsToLink = mkSinkUndeclaredOptions { }; + systemd.services = mkSinkUndeclaredOptions { }; + users.users = mkSinkUndeclaredOptions { }; + }; + }; + in [ + ../nixos/default.nix + mockedNixos + (nixosModule "/misc/assertions.nix") + scrubbedPkgsModule + ]; + docBook = { + id = "nixos-options"; + optionIdPrefix = "nixos-opt"; + }; + }; + + nixDarwinModuleDocs = buildModulesDocs { + modules = let + nixosModule = module: pkgs.path + "/nixos/modules" + module; + mockedNixDarwin = with lib; { + options = { + environment.pathsToLink = mkSinkUndeclaredOptions { }; + system.activationScripts.postActivation.text = + mkSinkUndeclaredOptions { }; + users.users = mkSinkUndeclaredOptions { }; + }; + }; + in [ + ../nix-darwin/default.nix + mockedNixDarwin + (nixosModule "/misc/assertions.nix") + scrubbedPkgsModule + ]; + docBook = { + id = "nix-darwin-options"; + optionIdPrefix = "nix-darwin-opt"; + }; + }; + + docs = nmd.buildDocBookDocs { + pathName = "home-manager"; + projectName = "Home Manager"; + modulesDocs = [ hmModulesDocs nixDarwinModuleDocs nixosModuleDocs ]; + documentsDirectory = ./.; + documentType = "book"; + chunkToc = '' + + + + + + + + + + ''; + }; + +in { + inherit nmdSrc; + + options = { + json = hmModulesDocs.json.override { + path = "share/doc/home-manager/options.json"; + }; + }; + + manPages = docs.manPages; + + manual = { inherit (docs) html htmlOpenTool; }; + + # Unstable, mainly for CI. + jsonModuleMaintainers = pkgs.writeText "hm-module-maintainers.json" (let + result = lib.evalModules { + modules = import ../modules/modules.nix { + inherit lib pkgs; + check = false; + } ++ [ scrubbedPkgsModule ]; + }; + in builtins.toJSON result.config.meta.maintainers); +} diff --git a/infra/libkookie/home-manager-stable/docs/faq.adoc b/infra/libkookie/home-manager-stable/docs/faq.adoc new file mode 100644 index 00000000000..935317e7a13 --- /dev/null +++ b/infra/libkookie/home-manager-stable/docs/faq.adoc @@ -0,0 +1,189 @@ +[[ch-faq]] +== Frequently Asked Questions (FAQ) + +=== Why is there a collision error when switching generation? + +Home Manager currently installs packages into the user environment, precisely as if the packages were installed through `nix-env --install`. This means that you will get a collision error if your Home Manager configuration attempts to install a package that you already have installed manually, that is, packages that shows up when you run `nix-env --query`. + +For example, imagine you have the `hello` package installed in your environment + +[source,console] +---- +$ nix-env --query +hello-2.10 +---- + +and your Home Manager configuration contains + +[source,nix] +---- +home.packages = [ pkgs.hello ]; +---- + +Then attempting to switch to this configuration will result in an error similar to + +[source,console] +---- +$ home-manager switch +these derivations will be built: + /nix/store/xg69wsnd1rp8xgs9qfsjal017nf0ldhm-home-manager-path.drv +[…] +Activating installPackages +replacing old ‘home-manager-path’ +installing ‘home-manager-path’ +building path(s) ‘/nix/store/b5c0asjz9f06l52l9812w6k39ifr49jj-user-environment’ +Wide character in die at /nix/store/64jc9gd2rkbgdb4yjx3nrgc91bpjj5ky-buildenv.pl line 79. +collision between ‘/nix/store/fmwa4axzghz11cnln5absh31nbhs9lq1-home-manager-path/bin/hello’ and ‘/nix/store/c2wyl8b9p4afivpcz8jplc9kis8rj36d-hello-2.10/bin/hello’; use ‘nix-env --set-flag priority NUMBER PKGNAME’ to change the priority of one of the conflicting packages +builder for ‘/nix/store/b37x3s7pzxbasfqhaca5dqbf3pjjw0ip-user-environment.drv’ failed with exit code 2 +error: build of ‘/nix/store/b37x3s7pzxbasfqhaca5dqbf3pjjw0ip-user-environment.drv’ failed +---- + +The solution is typically to uninstall the package from the environment using `nix-env --uninstall` and reattempt the Home Manager generation switch. + +You could also opt to unistall _all_ of the packages from your profile with `nix-env --uninstall '*'`. + +=== Why are the session variables not set? +:foreign-env: https://github.com/oh-my-fish/plugin-foreign-env + +Home Manager is only able to set session variables automatically if it manages your Bash, Z shell, or fish shell configuration. To enable such management you use <>, <>, or <>. + +If you don't want to let Home Manager manage your shell then you will have to manually source the `~/.nix-profile/etc/profile.d/hm-session-vars.sh` file in an appropriate way. In Bash and Z shell this can be done by adding + +[source,bash] +---- +. "$HOME/.nix-profile/etc/profile.d/hm-session-vars.sh" +---- + +to your `.profile` and `.zshrc` files, respectively. The `hm-session-vars.sh` file should work in most Bourne-like shells. For fish shell, it is possible to source it using {foreign-env}[the foreign-env plugin] + +[source,bash] +---- +fenv source "$HOME/.nix-profile/etc/profile.d/hm-session-vars.sh" > /dev/null +---- + +=== How to set up a configuration for multiple users/machines? +:post-your-homenix: https://www.reddit.com/r/NixOS/comments/9bb9h9/post_your_homemanager_homenix_file/ + +A typical way to prepare a repository of configurations for multiple logins and machines is to prepare one "top-level" file for each unique combination. + +For example, if you have two machines, called "kronos" and "rhea" on which you want to configure your user "jane" then you could create the files + +- `kronos-jane.nix`, +- `rhea-jane.nix`, and +- `common.nix` + +in your repository. On the kronos and rhea machines you can then make `~jane/.config/nixpkgs/home.nix` be a symbolic link to the corresponding file in your configuration repository. + +The `kronos-jane.nix` and `rhea-jane.nix` files follow the format + +[source,nix] +---- +{ ... }: + +{ + imports = [ ./common.nix ]; + + # Various options that are specific for this machine/user. +} +---- + +while the `common.nix` file contains configuration shared across the two logins. Of course, instead of just a single `common.nix` file you can have multiple ones, even one per program or service. + +You can get some inspiration from the {post-your-homenix}[Post your home-manager home.nix file!] Reddit thread. + +=== Why do I get an error message about `ca.desrt.dconf` or `dconf.service`? + +You are most likely trying to configure something that uses dconf +but the DBus session is not aware of the dconf service. +The full error you might get is + +---- +error: GDBus.Error:org.freedesktop.DBus.Error.ServiceUnknown: The name ca.desrt.dconf was not provided by any .service files +---- + +or + +---- +error: GDBus.Error:org.freedesktop.systemd1.NoSuchUnit: Unit dconf.service not found. +---- + +The solution on NixOS is to add + +[source,nix] +programs.dconf.enable = true; + +to your system configuration. + +=== How do I install packages from Nixpkgs unstable? + +If you are using a stable version of Nixpkgs but would like to install some particular packages from Nixpkgs unstable – or some other channel – then you can import the unstable Nixpkgs and refer to its packages within your configuration. Something like + +[source,nix] +---- +{ pkgs, config, ... }: + +let + + pkgsUnstable = import {}; + +in + +{ + home.packages = [ + pkgsUnstable.foo + ]; + + # … +} +---- + +should work provided you have a Nix channel called `nixpkgs-unstable`. + +You can add the `nixpkgs-unstable` channel by running + +[source,console] +---- +# nix-channel --add https://nixos.org/channels/nixpkgs-unstable nixpkgs-unstable +# nix-channel --update +---- + +Note, the package will not be affected by any package overrides, overlays, etc. + +=== How do I override the package used by a module? +:nixpkgs-overlays: https://nixos.org/nixpkgs/manual/#chap-overlays + +By default Home Manager will install the package provided by your chosen `nixpkgs` channel but occasionally you might end up needing to change this package. This can typically be done in two ways. + +1. If the module provides a `package` option, such as `programs.beets.package`, then this is the recommended way to perform the override. For example, ++ +[source,nix] +programs.beets.package = pkgs.beets.override { enableCheck = true; }; + +2. If no `package` option is available then you can typically override the relevant package using an {nixpkgs-overlays}[overlay]. ++ +For example, if you want to use the `programs.skim` module but use the `skim` package from Nixpkgs unstable, then a configuration like ++ +[source,nix] +---- +{ pkgs, config, ... }: + +let + + pkgsUnstable = import {}; + +in + +{ + programs.skim.enable = true; + + nixpkgs.overlays = [ + (self: super: { + skim = pkgsUnstable.skim; + }) + ]; + + # … +} +---- ++ +should work OK. diff --git a/infra/libkookie/home-manager-stable/docs/installation.adoc b/infra/libkookie/home-manager-stable/docs/installation.adoc new file mode 100644 index 00000000000..f35fcf64558 --- /dev/null +++ b/infra/libkookie/home-manager-stable/docs/installation.adoc @@ -0,0 +1,335 @@ +[[ch-installation]] +== Installing Home Manager + +:nix-darwin: https://github.com/LnL7/nix-darwin/ + +Home Manager can be used in three primary ways: + +1. Using the standalone `home-manager` tool. For platforms other than +NixOS and Darwin, this is the only available choice. It is also +recommended for people on NixOS or Darwin that want to manage their +home directory independently of the system as a whole. See +<> for instructions on how to perform this +installation. + +2. As a module within a NixOS system configuration. This allows the +user profiles to be built together with the system when running +`nixos-rebuild`. See <> for a description of +this setup. + +3. As a module within a {nix-darwin}[nix-darwin] system configuration. +This allows the user profiles to be built together with the system +when running `darwin-rebuild`. See <> +for a description of this setup. + +[[sec-install-standalone]] +=== Standalone installation + +:nix-allowed-users: https://nixos.org/nix/manual/#conf-allowed-users +:nixos-allowed-users: https://nixos.org/nixos/manual/options.html#opt-nix.allowedUsers +:bash: https://www.gnu.org/software/bash/ +:zsh: http://zsh.sourceforge.net/ +:fish: https://fishshell.com +:plugin-foreign-env: https://github.com/oh-my-fish/plugin-foreign-env +:babelfish: https://github.com/bouk/babelfish + +1. Make sure you have a working Nix installation. Specifically, make +sure that your user is able to build and install Nix packages. For +example, you should be able to successfully run a command like +`nix-instantiate '' -A hello` without having to switch to the +root user. For a multi-user install of Nix this means that your user +must be covered by the {nix-allowed-users}[`allowed-users`] Nix +option. On NixOS you can control this option using the +{nixos-allowed-users}[`nix.allowedUsers`] system option. ++ +Note that Nix 2.4 is not yet fully supported. Most significantly, Home +Manager is incompatible with the new `nix profile`. + +2. Add the appropriate Home Manager channel. If you are following +Nixpkgs master or an unstable channel you can run ++ +[source,console] +---- +$ nix-channel --add https://github.com/nix-community/home-manager/archive/master.tar.gz home-manager +$ nix-channel --update +---- ++ +and if you follow a Nixpkgs version 22.05 channel you can run ++ +[source,console] +---- +$ nix-channel --add https://github.com/nix-community/home-manager/archive/release-22.05.tar.gz home-manager +$ nix-channel --update +---- ++ +On non-NixOS, you may have to add ++ +[source,bash] +export NIX_PATH=$HOME/.nix-defexpr/channels:/nix/var/nix/profiles/per-user/root/channels${NIX_PATH:+:$NIX_PATH} ++ +to your shell (see https://github.com/NixOS/nix/issues/2033[nix#2033] +and +https://discourse.nixos.org/t/where-is-nix-path-supposed-to-be-set/16434/8[this +reply on the Nix Discourse]). + +3. Run the Home Manager installation command and create the first Home +Manager generation: ++ +[source,console] +$ nix-shell '' -A install ++ +Once finished, Home Manager should be active and available in your +user environment. + +4. If you do not plan on having Home Manager manage your shell +configuration then you must source the ++ +[source,bash] +$HOME/.nix-profile/etc/profile.d/hm-session-vars.sh ++ +file in your shell configuration. Alternatively source ++ +[source,bash] +/etc/profiles/per-user/$USER/etc/profile.d/hm-session-vars.sh ++ +when managing home configuration together with system configuration. ++ +This file can be sourced directly by POSIX.2-like shells such as +{bash}[Bash] or {zsh}[Z shell]. {fish}[Fish] users can use utilities +such as {plugin-foreign-env}[foreign-env] or {babelfish}[babelfish]. ++ +For example, if you use Bash then add ++ +[source,bash] +---- +. "$HOME/.nix-profile/etc/profile.d/hm-session-vars.sh" +---- ++ +to your `~/.profile` file. + +If instead of using channels you want to run Home Manager from a Git +checkout of the repository then you can use the +<> option to specify the absolute path +to the repository. + +Once installed you can see <> for a more detailed +description of Home Manager and how to use it. + +[[sec-install-nixos-module]] +=== NixOS module + +Home Manager provides a NixOS module that allows you to prepare user +environments directly from the system configuration file, which often +is more convenient than using the `home-manager` tool. It also opens +up additional possibilities, for example, to automatically configure +user environments in NixOS declarative containers or on systems +deployed through NixOps. + +To make the NixOS module available for use you must `import` it into +your system configuration. This is most conveniently done by adding a +Home Manager channel. For example, if you are following Nixpkgs master +or an unstable channel, you can run + +[source,console] +---- +# nix-channel --add https://github.com/nix-community/home-manager/archive/master.tar.gz home-manager +# nix-channel --update +---- + +and if you follow a Nixpkgs version 22.05 channel, you can run + +[source,console] +---- +# nix-channel --add https://github.com/nix-community/home-manager/archive/release-22.05.tar.gz home-manager +# nix-channel --update +---- + +It is then possible to add + +[source,nix] +imports = [ ]; + +to your system `configuration.nix` file, which will introduce a new +NixOS option called `home-manager.users` whose type is an attribute +set that maps user names to Home Manager configurations. + +For example, a NixOS configuration may include the lines + +[source,nix] +---- +users.users.eve.isNormalUser = true; +home-manager.users.eve = { pkgs, ... }: { + home.packages = [ pkgs.atool pkgs.httpie ]; + programs.bash.enable = true; +}; +---- + +and after a `nixos-rebuild switch` the user eve's environment should +include a basic Bash configuration and the packages atool and httpie. + +[NOTE] +==== +If `nixos-rebuild switch` does not result in the environment you expect, +you can take a look at the output of the Home Manager activation script output using + +[source,console] +$ systemctl status "home-manager-$USER.service" +==== + +If you do not plan on having Home Manager manage your shell +configuration then you must add either + +[source,bash] +---- +. "$HOME/.nix-profile/etc/profile.d/hm-session-vars.sh" +---- + +or + +[source,bash] +---- +. "/etc/profiles/per-user/$USER/etc/profile.d/hm-session-vars.sh" +---- + +to your shell configuration, depending on whether +<> is enabled. This file can +be sourced directly by POSIX.2-like shells such as {bash}[Bash] or +{zsh}[Z shell]. {fish}[Fish] users can use utilities such as +{plugin-foreign-env}[foreign-env] or {babelfish}[babelfish]. + +[NOTE] +==== +By default packages will be installed to `$HOME/.nix-profile` but they +can be installed to `/etc/profiles` if + +[source,nix] +home-manager.useUserPackages = true; + +is added to the system configuration. This is necessary if, for +example, you wish to use `nixos-rebuild build-vm`. This option may +become the default value in the future. +==== + +[NOTE] +==== +By default, Home Manager uses a private `pkgs` instance that is +configured via the `home-manager.users..nixpkgs` options. To +instead use the global `pkgs` that is configured via the system level +`nixpkgs` options, set + +[source,nix] +home-manager.useGlobalPkgs = true; + +This saves an extra Nixpkgs evaluation, adds consistency, and removes +the dependency on `NIX_PATH`, which is otherwise used for importing +Nixpkgs. +==== + +Once installed you can see <> for a more detailed +description of Home Manager and how to use it. + +[[sec-install-nix-darwin-module]] +=== nix-darwin module + +Home Manager provides a module that allows you to prepare user +environments directly from the {nix-darwin}[nix-darwin] configuration +file, which often is more convenient than using the `home-manager` +tool. + +To make the NixOS module available for use you must `import` it into +your system configuration. This is most conveniently done by adding a +Home Manager channel. For example, if you are following Nixpkgs master +or an unstable channel, you can run + +[source,console] +---- +# nix-channel --add https://github.com/nix-community/home-manager/archive/master.tar.gz home-manager +# nix-channel --update +---- + +and if you follow a Nixpkgs version 22.05 channel, you can run + +[source,console] +---- +# nix-channel --add https://github.com/nix-community/home-manager/archive/release-22.05.tar.gz home-manager +# nix-channel --update +---- + +It is then possible to add + +[source,nix] +imports = [ ]; + +to your nix-darwin `configuration.nix` file, which will introduce a +new NixOS option called `home-manager` whose type is an attribute set +that maps user names to Home Manager configurations. + +For example, a nix-darwin configuration may include the lines + +[source,nix] +---- +users.users.eve = { + name = "eve"; + home = "/Users/eve"; +} +home-manager.users.eve = { pkgs, ... }: { + home.packages = [ pkgs.atool pkgs.httpie ]; + programs.bash.enable = true; +}; +---- + +and after a `darwin-rebuild switch` the user eve's environment +should include a basic Bash configuration and the packages atool and +httpie. + +If you do not plan on having Home Manager manage your shell +configuration then you must add either + +[source,bash] +---- +. "$HOME/.nix-profile/etc/profile.d/hm-session-vars.sh" +---- + +or + +[source,bash] +---- +. "/etc/profiles/per-user/$USER/etc/profile.d/hm-session-vars.sh" +---- + +to your shell configuration, depending on whether +<> is enabled. This file +can be sourced directly by POSIX.2-like shells such as {bash}[Bash] or +{zsh}[Z shell]. {fish}[Fish] users can use utilities such as +{plugin-foreign-env}[foreign-env] or {babelfish}[babelfish]. + +[NOTE] +==== +By default user packages will not be ignored in favor of +`environment.systemPackages`, but they will be intalled to +`/etc/profiles/per-user/$USERNAME` if + +[source,nix] +home-manager.useUserPackages = true; + +is added to the nix-darwin configuration. This option may become the +default value in the future. +==== + +[NOTE] +==== +By default, Home Manager uses a private `pkgs` instance that is +configured via the `home-manager.users..nixpkgs` options. To +instead use the global `pkgs` that is configured via the system level +`nixpkgs` options, set + +[source,nix] +home-manager.useGlobalPkgs = true; + +This saves an extra Nixpkgs evaluation, adds consistency, and removes +the dependency on `NIX_PATH`, which is otherwise used for importing +Nixpkgs. +==== + +Once installed you can see <> for a more detailed +description of Home Manager and how to use it. diff --git a/infra/libkookie/home-manager-stable/docs/man-configuration.xml b/infra/libkookie/home-manager-stable/docs/man-configuration.xml new file mode 100644 index 00000000000..42962a75f3c --- /dev/null +++ b/infra/libkookie/home-manager-stable/docs/man-configuration.xml @@ -0,0 +1,40 @@ + + + home-configuration.nix + 5 + Home Manager + + + + home-configuration.nix + Home Manager configuration specification + + + Description + + The file ~/.config/nixpkgs/home.nix contains the + declarative specification of your Home Manager configuration. The command + home-manager takes this file and realises the user + environment configuration specified therein. + + + + Options + + You can use the following options in + home-configuration.nix: + + + + + See also + + + home-manager + 1 + + + + diff --git a/infra/libkookie/home-manager-stable/docs/man-home-manager.xml b/infra/libkookie/home-manager-stable/docs/man-home-manager.xml new file mode 100644 index 00000000000..cbc977abc9b --- /dev/null +++ b/infra/libkookie/home-manager-stable/docs/man-home-manager.xml @@ -0,0 +1,634 @@ + + + home-manager + 1 + Home Manager + + + home-manager + reconfigure a user environment + + + + home-manager + + build + + + + instantiate + + + + edit + + + + expire-generations timestamp + + + + generations + + + + help + + + + news + + + + option option.name + + + + packages + + + + remove-generations ID … + + + + switch + + + + uninstall + + + + + -A attrPath + + + + -I path + + + + --flake flake-uri + + + + -b ext + + + + + + -f + + + + --file + + path + + + + + + -h + + + + --help + + + + + + --version + + + + + + -n + + + + --dry-run + + + + + + --option name value + + + + --cores number + + + + + + -j + + + + --max-jobs + + + number + + + + --debug + + + + --impure + + + + --keep-failed + + + + --keep-going + + + + --show-trace + + + + --(no-)substitute + + + + --no-out-link + + + + + + -v + + + + --verbose + + + + + + + Description + + This command updates the user environment so that it corresponds to the + configuration specified in ~/.config/nixpkgs/home.nix or ~/.config/nixpkgs/flake.nix. + + + All operations using this tool expects a sub-command that indicates the + operation to perform. It must be one of + + + + + + + + Build configuration into a result directory. + + + + + + + + + + Instantiate the configuration and print the resulting derivation. + + + + + + + + + + Open the home configuration using the editor indicated by + EDITOR. + + + + + + + + + + Remove generations older than timestamp where + timestamp is interpreted as in the + argument of the + date + 1 tool. For example -30 + days or 2018-01-01. + + + + + + + + + + List all home environment generations. + + + + + + + + + + Print tool help. + + + + + + + + + + Show news entries in a pager. + + + + + + + + + + Inspect the given option name in the home configuration, like + nixos-option + 8 . + + + + + + + + + + List all packages installed in home-manager-path. + + + + + + + + + + Remove indicated generations. Use the + sub-command to find suitable generation numbers. + + + + + + + + + + Build and activate the configuration. + + + + + + + + + + Remove Home Manager from the user environment. This will + + + + remove all managed files from the home directory, + + + + + remove packages installed through Home Manager from the user profile, + and + + + + + optionally remove all Home Manager generations and make them + available for immediate garbage collection. + + + + + + + + + + + Options + + The tool accepts the options + + + + + + + + + Optional attribute that selects a configuration expression in the + configuration file. That is, if home.nix contains + +{ + joe-at-work = {pkgs, ...}: { home.packages = [ pkgs.fortune ]; }; + joe-at-home = {pkgs, ...}: { home.packages = [ pkgs.cowsay ]; }; +} + + then the command home-manager switch -A joe-at-work + will activate the profile containing the fortune program. + + + + + + + + + + Add a path to the Nix expression search path. For example, to build a + Home Manager profile using a specific Nixpkgs run home-manager + -I nixpkgs=/absolute/path/to/nixpkgs build. By default + <nixpkgs> is used. + + + + + + + + + + Build Home Manager configuration from the flake, which must contain the + output homeConfigurations.name. If no name is specified it will first try + username@hostname and then username. + + + + + + + + + + Enable automatic resolution of collisions between unmanaged and managed + files. The name of the original file will be suffixed by the given + extension. For example, + +$ home-manager -b bck switch + + will cause a colliding file ~/.config/foo.conf to be + moved to ~/.config/foo.conf.bck. + + + + + + + + + + + + + Indicates the path to the Home Manager configuration file. If not given, + $XDG_CONFIG_HOME/nixpkgs/home.nix is used. + + + + + + + + + + + + + Prints usage information for the home-manager tool. + + + + + + + + + + Prints the version number of the home-manager tool. + + + + + + + + + + + + + Perform a dry-run of the given operation, only prints what actions would + be taken. + + + + + + + + + + Passed on to + nix-build + 1 . + + + + + + + + + + Passed on to + nix-build + 1 . + + + + + + + + + + + + + Passed on to + nix-build + 1 . + + + + + + + + + + Passed on to + nix-build + 1 . + + + + + + + + + + Passed on to + nix-build + 1 . + + + + + + + + + + Passed on to + nix-build + 1 . + + + + + + + + + + Passed on to + nix-build + 1 . + + + + + + + + + + Passed on to + nix-build + 1 . + + + + + + + + + + Passed on to + nix-build + 1 . + + + + + + + + + + Passed on to + nix-build + 1 + when running home-manager build. + + + + + + + + + + + + + Activates verbose output. + + + + + + + Files + + + + $XDG_DATA_HOME/home-manager/news-read-ids + + + + Identifiers of news items that have been shown. Can be deleted to reset + the read news indicator. + + + + + + + Bugs + + Please report any bugs on the + project + issue tracker. + + + + See also + + + home-configuration.nix + 5 + + + diff --git a/infra/libkookie/home-manager-stable/docs/man-pages.xml b/infra/libkookie/home-manager-stable/docs/man-pages.xml new file mode 100644 index 00000000000..a68b0e60d77 --- /dev/null +++ b/infra/libkookie/home-manager-stable/docs/man-pages.xml @@ -0,0 +1,12 @@ + + Home Manager Reference Pages + + Home Manager contributors + 2017–2022Home Manager contributors + + + + + diff --git a/infra/libkookie/home-manager-stable/docs/manual.xml b/infra/libkookie/home-manager-stable/docs/manual.xml new file mode 100644 index 00000000000..375a9694ce0 --- /dev/null +++ b/infra/libkookie/home-manager-stable/docs/manual.xml @@ -0,0 +1,56 @@ + + + Home Manager Manual + + + Preface + + This manual will eventually describe how to install, use, and extend Home + Manager. + + + If you encounter problems then please reach out on the IRC channel + #home-manager + hosted by OFTC. + There is also a Matrix room, + which is bridged to the IRC channel. + If your problem is caused by a bug in Home Manager then it should + be reported on the + Home Manager issue tracker. + + + + Commands prefixed with # have to be run as root, either + requiring to login as root user or temporarily switching to it using + sudo for example. + + + + + + + + + + + Configuration Options + + + + NixOS Module Options + + + + nix-darwin Module Options + + + + Tools + + + + diff --git a/infra/libkookie/home-manager-stable/docs/nix-flakes.adoc b/infra/libkookie/home-manager-stable/docs/nix-flakes.adoc new file mode 100644 index 00000000000..a979552e350 --- /dev/null +++ b/infra/libkookie/home-manager-stable/docs/nix-flakes.adoc @@ -0,0 +1,223 @@ +[[ch-nix-flakes]] +== Nix Flakes + +:nixos-wiki-flakes: https://nixos.wiki/wiki/Flakes + +Home Manager includes a `flake.nix` file for compatibility with {nixos-wiki-flakes}[Nix Flakes]. +The support is still experimental and may change in backwards incompatible ways. + +[[sec-flakes-prerequisties]] +=== Prerequisties + +* Install Nix 2.4 or have it in `nix-shell`. + +* Enable experimental features `nix-command` and `flakes`. ++ +Either set in `nix.conf` ++ +[source,bash] +experimental-features = nix-command flakes ++ +or pass them to `nix` and `home-manager` by ++ +[source,console] +---- +$ nix --extra-experimental-features "nix-command flakes" +$ home-manager --extra-experimental-features "nix-command flakes" +---- + +* Prepare your Home Manager configuration (`home.nix`). ++ +Unlike the channel-based setup, +`home.nix` will be evaluated when the flake is built, +so it must be present before bootstrap of Home Manager from the flake. +See <> for introduction about +writing a Home Manager configuration. ++ +[NOTE] +==== +The `stateVersion` will be specified in the flake instead of in the configuration file. + +Remove the line containing `home.stateVersion` in the example. +==== + +[[sec-flakes-standalone]] +=== Standalone setup + +1. Set up a flake with a `flake.nix` as follows: ++ +[source,nix] +---- +{ + description = "Home Manager configuration of Jane Doe"; + + inputs = { + # Specify the source of Home Manager and Nixpkgs + home-manager.url = "github:nix-community/home-manager"; + nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; + home-manager.inputs.nixpkgs.follows = "nixpkgs"; + }; + + outputs = { home-manager, ... }: + let + system = "x86_64-linux"; + username = "jdoe"; + in { + homeConfigurations.${username} = home-manager.lib.homeManagerConfiguration { + # Specify the path to your home configuration here + configuration = import ./home.nix; + + inherit system username; + homeDirectory = "/home/${username}"; + # Update the state version as needed. + # See the changelog here: + # https://nix-community.github.io/home-manager/release-notes.html#sec-release-21.05 + stateVersion = "22.05"; + + # Optionally use extraSpecialArgs + # to pass through arguments to home.nix + }; + }; +} +---- ++ +[NOTE] +==== +* The above example tracks the master branch of Home Manager +and nixos-unstable branch of Nixpkgs. +If you would like to use the `release-22.05` branch, +change the `home-manager` input url to `github:nix-community/home-manager/release-22.05` +and `nixpkgs` url to `github:NixOS/nixpkgs/nixos-22.05`. +Make sure to also update to the `stateVersion` option accordingly. + +* The Home Manager library is exported by the flake under +`lib.hm`. +==== + +2. Install Home Manager and apply the configuration by ++ +[source,console] +---- +$ nix build --no-link #homeConfigurations.jdoe.activationPackage +$ "$(nix path-info #homeConfigurations.jdoe.activationPackage)"/activate +---- ++ +Substitute `` with the flake URI of the configuration flake. +If `flake.nix` resides in `~/.config/nixpkgs`, +`` may be `~/.config/nixpkgs` +as a Git tree or `path:~/.config/nixpkgs` if not. + +3. Since the release `21.05`, +building a flake-based configuration is as simple as ++ +[source,console] +$ home-manager switch --flake '#jdoe' ++ +once home-manager is installed. ++ +Here, `jdoe` is a configuration specified in the flake file, +and `#jdoe` will be expanded to +`#homeConfigurations.jdoe.activationPackage` +and be built by Nix. + +[NOTE] +==== +The flake inputs are not upgraded automatically when switching. +The analogy to the command `home-manager --update ...` is `nix flake update`. + +If updating more than one input is undesirable, +the command `nix flake lock --update-input ` can be used. + +You can also pass flake-related options +such as `--recreate-lock-file` or `--update-input [input]` +to `home-manager` when building/switching, +and these options will be forwarded to `nix build`. +See the {nixos-wiki-flakes}[NixOS Wiki page] for detail. +==== + +[[sec-flakes-nixos-module]] +=== NixOS module + +To use Home Manager as a NixOS module, +a bare-minimum `flake.nix` would be as follows: + +[source,nix] +---- +{ + description = "NixOS configuration"; + + inputs = { + nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; + home-manager.url = "github:nix-community/home-manager"; + home-manager.inputs.nixpkgs.follows = "nixpkgs"; + }; + + outputs = inputs@{ nixpkgs, home-manager, ... }: { + nixosConfigurations = { + hostname = nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + modules = [ + ./configuration.nix + home-manager.nixosModules.home-manager + { + home-manager.useGlobalPkgs = true; + home-manager.useUserPackages = true; + home-manager.users.jdoe = import ./home.nix; + + # Optionally, use home-manager.extraSpecialArgs to pass + # arguments to home.nix + } + ]; + }; + }; + }; +} +---- + +The Home Manager configuration is then part of the NixOS configuration +and is automatically rebuilt with the system when using the appropriate command +for the system, such as `nixos-rebuild switch --flake `. + +[[sec-flakes-nix-darwin-module]] +=== nix-darwin module + +The flake-based setup of the Home Manager nix-darwin module +is similar to that of NixOS. The `flake.nix` would be: + +[source,nix] +---- +{ + description = "NixOS configuration"; + + inputs = { + nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; + nix-darwin.url = "github:lnl7/nix-darwin"; + darwin.inputs.nixpkgs.follows = "nixpkgs"; + home-manager.url = "github:nix-community/home-manager"; + home-manager.inputs.nixpkgs.follows = "nixpkgs"; + }; + + outputs = inputs@{ nixpkgs, home-manager, nix-darwin, ... }: { + darwinConfigurations = { + hostname = nix-darwin.lib.darwinSystem { + system = "x86_64-darwin"; + modules = [ + ./configuration.nix + home-manager.darwinModules.home-manager + { + home-manager.useGlobalPkgs = true; + home-manager.useUserPackages = true; + home-manager.users.jdoe = import ./home.nix; + + # Optionally, use home-manager.extraSpecialArgs to pass + # arguments to home.nix + } + ]; + }; + }; + }; +} +---- + +and it is also rebuilt with the nix-darwin generations. +The rebuild command here may be `darwin-rebuild switch --flake `. diff --git a/infra/libkookie/home-manager-stable/docs/release-notes/release-notes.adoc b/infra/libkookie/home-manager-stable/docs/release-notes/release-notes.adoc new file mode 100644 index 00000000000..56bfa20b620 --- /dev/null +++ b/infra/libkookie/home-manager-stable/docs/release-notes/release-notes.adoc @@ -0,0 +1,25 @@ +[[ch-release-notes]] +[appendix] +== Release Notes + +This section lists the release notes for stable versions of Home Manager and the current unstable version. + +:leveloffset: 1 + +include::rl-2205.adoc[] + +include::rl-2111.adoc[] + +include::rl-2105.adoc[] + +include::rl-2009.adoc[] + +include::rl-2003.adoc[] + +include::rl-1909.adoc[] + +include::rl-1903.adoc[] + +include::rl-1809.adoc[] + +:leveloffset: 0 diff --git a/infra/libkookie/home-manager-stable/docs/release-notes/rl-1809.adoc b/infra/libkookie/home-manager-stable/docs/release-notes/rl-1809.adoc new file mode 100644 index 00000000000..b363704e241 --- /dev/null +++ b/infra/libkookie/home-manager-stable/docs/release-notes/rl-1809.adoc @@ -0,0 +1,4 @@ +[[sec-release-18.09]] +== Release 18.09 + +The 18.09 release branch became the stable branch in September, 2018. diff --git a/infra/libkookie/home-manager-stable/docs/release-notes/rl-1903.adoc b/infra/libkookie/home-manager-stable/docs/release-notes/rl-1903.adoc new file mode 100644 index 00000000000..1cba4235d60 --- /dev/null +++ b/infra/libkookie/home-manager-stable/docs/release-notes/rl-1903.adoc @@ -0,0 +1,59 @@ +[[sec-release-19.03]] +== Release 19.03 + +The 19.03 release branch became the stable branch in April, 2019. + +[[sec-release-19.03-highlights]] +=== Highlights +:opt-home-file-source: opt-home.file._name_.source + +This release has the following notable changes: + +* The <<{opt-home-file-source}>> option now allows source files to be +hidden, that is, having a name starting with the `.` character. It +also allows the source file name to contain characters not typically +allowed for Nix store paths. For example, your configuration can now +contain things such as ++ +[source,nix] +---- +home.file."my file".source = ./. + "/file with spaces!"; +---- + +* The type used for the systemd unit options under +<>, <>, etc. has +been changed to offer more robust merging of configurations. If you +don't override values within systemd units then you are not affected +by this change. Unfortunately, if you do override unit values you may +encounter errors. ++ +In particular, if you get an error saying that a ``unique option'' is +``defined multiple times'' then you need to use the +https://nixos.org/nixos/manual/#sec-option-definitions-setting-priorities[`mkForce`] +function. For example, ++ +[source,nix] +---- +systemd.user.services.foo.Service.ExecStart = "/foo/bar"; +---- ++ +becomes ++ +[source,nix] +---- +systemd.user.services.foo.Service.ExecStart = lib.mkForce "/foo/bar"; +---- ++ +We had to make this change because the old merging was causing too +many confusing situations for people. + +[[sec-release-19.03-state-version-changes]] +=== State Version Changes + +The state version in this release includes the changes below. These +changes are only active if the <> option is set +to ``19.03'' or later. + +* There is now an option <> that defaults +to `false`. Before the module would be active if the +<> option was non-empty. diff --git a/infra/libkookie/home-manager-stable/docs/release-notes/rl-1909.adoc b/infra/libkookie/home-manager-stable/docs/release-notes/rl-1909.adoc new file mode 100644 index 00000000000..89bbbdc2b4f --- /dev/null +++ b/infra/libkookie/home-manager-stable/docs/release-notes/rl-1909.adoc @@ -0,0 +1,31 @@ +[[sec-release-19.09]] +== Release 19.09 + +The 19.09 release branch became the stable branch in October, 2019. + +[[sec-release-19.09-highlights]] +=== Highlights + +This release has the following notable changes: + +* The `programs.firefox.enableGoogleTalk` and + `programs.firefox.enableIcedTea` options are now deprecated + and will only work if Firefox ESR 52.x is used. + +* The `home-manager` tool now provides an `uninstall` sub-command that + can be used to uninstall Home Manager, if used in the standalone + mode. That is, not as a NixOS module. + +[[sec-release-19.09-state-version-changes]] +=== State Version Changes + +The state version in this release includes the changes below. These +changes are only active if the `home.stateVersion` option is set to +"19.09" or later. + +* The <> option now expects a wrapped + Firefox package and defaults to `pkgs.firefox`. + +* The options <> and + <> now default to `null`, which indicates + that the system value should be used. diff --git a/infra/libkookie/home-manager-stable/docs/release-notes/rl-2003.adoc b/infra/libkookie/home-manager-stable/docs/release-notes/rl-2003.adoc new file mode 100644 index 00000000000..5832e2e5ab5 --- /dev/null +++ b/infra/libkookie/home-manager-stable/docs/release-notes/rl-2003.adoc @@ -0,0 +1,126 @@ +[[sec-release-20.03]] +== Release 20.03 + +The 20.03 release branch became the stable branch in April, 2020. + +[[sec-release-20.03-highlights]] +=== Highlights + +This release has the following notable changes: + +* Assigning a list to the <>, <>, +and <> options is now deprecated and will produce a +warning message if used. Specifically, if your configuration currently +contains something like ++ +[source,nix] +---- +home.file = [ + { + target = ".config/foo.txt"; + text = "bar"; + } +] +---- ++ +then it should be updated to instead use the equivalent attribute set form ++ +[source,nix] +---- +home.file = { + ".config/foo.txt".text = "bar"; +} +---- ++ +Support for the list form will be removed in Home Manager version +20.09. + +* The `lib` function attribute given to modules is now enriched with +an attribute `hm` containing extra library functions specific for Home +Manager. More specifically, `lib.hm` is now the same as `config.lib` +and should be the preferred choice since it is more robust. ++ +Therefore, if your configuration makes use of, for example, +`config.lib.dag` to create activation script blocks, it is recommended +to change to `lib.hm.dag`. ++ +Note, in the unlikely case that you are ++ +** using Home Manager's NixOS or nix-darwin module, +** have made your own Home Manager module containing an top-level + option named `config` or `options`, and +** assign to this option in your system configuration inside a plain + attribute set, i.e., without a function argument, + ++ +then you must update your configuration to perform the option +assignment inside a `config` attribute. For example, instead of ++ +[source,nix] +---- +home-manager.users.jane = { config = "foo"; }; +---- ++ +use ++ +[source,nix] +---- +home-manager.users.jane = { config.config = "foo"; }; +---- + +* The `services.compton` module has been deprecated and instead the +new module `services.picom` should be used. This is because Nixpkgs no +longer packages compton, and instead packages the (mostly) compatible +fork called picom. + +* The list form of the <> option has +been deprecated and configurations requiring match blocks in a defined +order should switch to using DAG entries instead. For example, a +configuration ++ +[source,nix] +---- +programs.ssh.matchBlocks = [ + { + host = "alpha.foo.com"; + user = "jd"; + } + { + host = "*.foo.com"; + user = "john.doe"; + } +]; +---- ++ +can be expressed along the lines of ++ +[source,nix] +---- +programs.ssh.matchBlocks = { + "*.example.com" = { + user = "john.doe"; + } + "alpha.example.com" = lib.hm.dag.entryBefore ["*.example.com"] { + user = "jd"; + } +}; +---- ++ +Support for the list form will be removed in Home Manager version +20.09. + +[[sec-release-20.03-state-version-changes]] +=== State Version Changes + +The state version in this release includes the changes below. These +changes are only active if the `home.stateVersion` option is set to +"20.03" or later. + +* The <> option is no longer prepended + by `$HOME`, which allows specifying absolute paths, for example, + using the xdg module. Also, the default value is fixed to + `$HOME/.zsh_history` and `dotDir` path is not prepended to it + anymore. +* The newsboat module will now default in displaying `queries` before `urls` in + its main window. This makes sense in the case when one has a lot of URLs and + few queries. diff --git a/infra/libkookie/home-manager-stable/docs/release-notes/rl-2009.adoc b/infra/libkookie/home-manager-stable/docs/release-notes/rl-2009.adoc new file mode 100644 index 00000000000..a3de0260c7d --- /dev/null +++ b/infra/libkookie/home-manager-stable/docs/release-notes/rl-2009.adoc @@ -0,0 +1,96 @@ +[[sec-release-20.09]] +== Release 20.09 + +The 20.09 release branch became the stable branch in late September, 2020. + +[[sec-release-20.09-highlights]] +=== Highlights + +This release has the following notable changes: + +* Nothing has happened. + +[[sec-release-20.09-state-version-changes]] +=== State Version Changes + +The state version in this release includes the changes below. These +changes are only active if the `home.stateVersion` option is set to +"20.09" or later. + +* The options <> and <> no +longer have default values and must therefore be provided in your +configuration. Previously their values would default to the content of +the environment variables `HOME` and `USER`, respectively. ++ +-- +Further, the options <>, <>, +and <> will no longer be affected by the +`XDG_CACHE_HOME`, `XDG_CONFIG_HOME`, and `XDG_DATA_HOME` environment +variables. They now unconditionally default to + +- `"${config.home.homeDirectory}/.cache"`, +- `"${config.home.homeDirectory}/.config"`, and +- `"${config.home.homeDirectory}/.local/share"`. + +If you choose to switch to state version 20.09 then you must set these +options if you use non-default XDG base directory paths. + +The initial configuration generated by + +[source,console] +$ nix-shell '' -A install + +will automatically include these options, when necessary. +-- + +* Git's `smtpEncryption` option is now set to `tls` only if both <> and <> are `true`. If only <> is `true`, `ssl` is used instead. + +* The `nixpkgs` module no longer references ``. Before it would do so when building the `pkgs` module argument. Starting with state version 20.09, the `pkgs` argument is instead built from the same Nixpkgs that was used to initialize the Home Manager modules. This is useful, for example, when using Home Manager within a Nix Flake. If you want to keep using `` with state version ≥ 20.09 then add ++ +[source,nix] +_module.args.pkgsPath = ; ++ +to your Home Manager configuration. + +* The options `wayland.windowManager.sway.config.bars` and `opt-xsession.windowManager.i3.config.bars` have been changed so that most of the suboptions are now nullable and default to `null`. The default for these two options has been changed to manually set the old defaults for each suboption. The overall effect is that if the `bars` options is not set, then the default remains the same. On the other hand, something like: ++ +-- +[source,nix] +---- +bars = [ { + command = "waybar"; +} ]; +---- +will now create the config: +.... +bar { + swaybar_command waybar +} +.... +instead of +.... +bar { + + font pango:monospace 8 + mode dock + hidden_state hide + position bottom + status_command /nix/store/h7s6i9q1z5fxrlyyw5ls8vqxhf5bcs5a-i3status-2.13/bin/i3status + swaybar_command waybar + workspace_buttons yes + strip_workspace_numbers no + tray_output primary + colors { + background #000000 + statusline #ffffff + separator #666666 + focused_workspace #4c7899 #285577 #ffffff + active_workspace #333333 #5f676a #ffffff + inactive_workspace #333333 #222222 #888888 + urgent_workspace #2f343a #900000 #ffffff + binding_mode #2f343a #900000 #ffffff + } + +} +.... +-- diff --git a/infra/libkookie/home-manager-stable/docs/release-notes/rl-2105.adoc b/infra/libkookie/home-manager-stable/docs/release-notes/rl-2105.adoc new file mode 100644 index 00000000000..7fcfb268d37 --- /dev/null +++ b/infra/libkookie/home-manager-stable/docs/release-notes/rl-2105.adoc @@ -0,0 +1,200 @@ +[[sec-release-21.05]] +== Release 21.05 + +The 21.05 release branch became the stable branch in May, 2021. + +[[sec-release-21.05-highlights]] +=== Highlights + +This release has the following notable changes: + +* The <> option is now a list rather than an +attribute set. To migrate, move the keys of the attrset into the list +items' `invocation` keys. For example, ++ +[source,nix] +---- +programs.broot.verbs = { + "p" = { execution = ":parent"; }; +}; +---- ++ +becomes ++ +[source,nix] +---- +programs.broot.verbs = [ + { + invocation = "p"; + execution = ":parent"; + } +]; +---- + +* The <> option has been changed to allow custom +derivations. The following configuration is now possible: ++ +[source,nix] +---- +programs.mpv.package = (pkgs.wrapMpv (pkgs.mpv-unwrapped.override { + vapoursynthSupport = true; +}) { + extraMakeWrapperArgs = [ + "--prefix" "LD_LIBRARY_PATH" ":" "${pkgs.vapoursynth-mvtools}/lib/vapoursynth" + ]; +}); +---- ++ +As a result of this change, <> is no longer the +resulting derivation. Use the newly introduced `programs.mpv.finalPackage` +instead. + +* The <> option is now an attribute set rather +than a string. To migrate, move each line into the attribute set, +removing the `rofi.` prefix from the keys. For example, ++ +[source,nix] +---- +programs.rofi.extraConfig = '' + rofi.show-icons: true + rofi.modi: drun,emoji,ssh +''; +---- ++ +becomes ++ +[source,nix] +---- +programs.rofi.extraConfig = { + show-icons = true; + modi = "drun,emoji,ssh"; +}; +---- ++ +* The <> option now supports defining a theme +using an attribute set, the following configuration is now possible: ++ +[source,nix] +---- +programs.rofi.theme = let + # Necessary to avoid quoting non-string values + inherit (config.lib.formats.rasi) mkLiteral; +in { + "@import" = "~/.config/rofi/theme.rasi"; + + "*" = { + background-color = mkLiteral "#000000"; + foreground-color = mkLiteral "rgba ( 250, 251, 252, 100 % )"; + border-color = mkLiteral "#FFFFFF"; + width = 512; + }; + + "#textbox-prompt-colon" = { + expand = false; + str = ":"; + margin = mkLiteral "0px 0.3em 0em 0em"; + text-color = mkLiteral "@foreground-color"; + }; +}; +---- + + +* The `services.redshift.extraOptions` and `services.gammastep.extraOptions` +options were removed in favor of <> and +`services.gammastep.settings`, that are now an attribute set rather +than a string. They also support new features not available before, for +example: ++ +[source,nix] +---- +services.redshift = { + dawnTime = "6:00-7:45"; + duskTime = "18:35-20:15"; + settings = { + redshift = { + gamma = 0.8; + adjustment-method = "randr"; + }; + + randr = { + screen = 0; + }; + }; +}; +---- ++ +It is recommended to check either +https://github.com/jonls/redshift/blob/master/redshift.conf.sample[redshift.conf.sample] or +https://gitlab.com/chinstrap/gammastep/-/blob/master/gammastep.conf.sample[gammastep.conf.sample] +for the available additional options in each program. + +* Specifying `programs.neomutt.binds.map` or `programs.neomutt.macros.map` as a + single string is now deprecated in favor of specfiying it as a list of + strings. + +* The `programs.neovim.configure` is deprecated in favor of other `programs.neovim` options; +please use the other options at your disposal: ++ +[source,nix] +---- +configure.packages.*.opt -> programs.neovim.plugins = [ { plugin = ...; optional = true; }] +configure.packages.*.start -> programs.neovim.plugins = [ { plugin = ...; }] +configure.customRC -> programs.neovim.extraConfig +---- + +* Home Manager now respects the `NO_COLOR` environment variable as per +https://no-color.org/[]. + +* Qt module now supports <> to specify a theme name and +<> to specify a theme package. If you have set +<> to `gnome`, a <> compatible +with both Qt and Gtk is now required to be set. For instance: ++ +[source,nix] +---- +qt = { + platformTheme = "gnome"; + style = { + name = "adwaita-dark"; + package = pkgs.adwaita-qt; + }; +}; +---- + +* The library type `fontType` now has a `size` attribute in addition to `name`. For example: ++ +[source,nix] +---- +font = { + name = "DejaVu Sans"; + size = 8; +}; +---- + +* The <> option is introduced to replace individual +options in `programs.htop`. To migrate, set the htop options directly in +<>. For example: ++ +[source,nix] +---- +programs.htop = { + enabled = true; + settings = { + color_scheme = 5; + delay = 15; + highlight_base_name = 1; + highlight_megabytes = 1; + highlight_threads = 1; + }; +}; +---- + +[[sec-release-21.05-state-version-changes]] +=== State Version Changes + +The state version in this release includes the changes below. These +changes are only active if the `home.stateVersion` option is set to +"21.05" or later. + +* The `newsboat` module now stores generated configuration in + `$XDG_CONFIG_HOME/newsboat`. diff --git a/infra/libkookie/home-manager-stable/docs/release-notes/rl-2111.adoc b/infra/libkookie/home-manager-stable/docs/release-notes/rl-2111.adoc new file mode 100644 index 00000000000..0ac83a322e0 --- /dev/null +++ b/infra/libkookie/home-manager-stable/docs/release-notes/rl-2111.adoc @@ -0,0 +1,73 @@ +[[sec-release-21.11]] +== Release 21.11 + +The 21.11 release branch became the stable branch in November, 2021. + +[[sec-release-21.11-highlights]] +=== Highlights + +This release has the following notable changes: + +* All Home Manager modules are now loaded on all platforms. With this +change you will get a more descriptive error message if you attempt to +enable a module that is incompatible with the host platform. ++ +Previously, modules that were platform specific would only be loaded +on that particular platform. For example, a module defining a +https://systemd.io/[systemd] service would only be loaded when the +host platform was Linux. This reduced evaluation times, simplified the +generated documentation, and made it impossible to accidentally use +modules that do not support the host platform. ++ +While the above benefits are quite nice, avoiding module loads also +brings a few problems. For example, the +https://nix-community.github.io/home-manager/[public documentation] +will only show the options available for Linux hosts and the +documentation cannot make references to options within modules that +are unavailable on some hosts. Finally, users who wish to use the same +configuration file for different platforms cannot do so, even if the +platform incompatible options are unused. ++ +Ultimately, the benefits of loading all modules won and the behavior +has now changed. For associated discussion see +https://github.com/nix-community/home-manager/issues/1906[issue #1906]. + +* Rofi version 1.7.0 removed many options that were used by the module and replaced them with custom themes, which are more flexible and powerful. ++ +You can replicate your old configuration by moving those options to <>. Keep in mind that the syntax is different so you may need to do some changes. + +* Taskwarrior version 2.6.0 respects XDG Specification for the config file now. +Option <> and friends now generate the config file at +`$XDG_CONFIG_HOME/task/taskrc` instead of `~/.taskrc`. + +[[sec-release-21.11-state-version-changes]] +=== State Version Changes + +The state version in this release includes the changes below. These +changes are only active if the `home.stateVersion` option is set to +"21.11" or later. + +* The <> option now defaults to `null`, meaning that Home Manager won't do any keyboard layout management. For example, `setxkbmap` won't be run in X sessions. + +* The <> option no longer place its value inside a `General` attribute. +For example, ++ +[source,nix] +programs.pet.settings.editor = "nvim"; ++ +becomes ++ +[source,nix] +programs.pet.settings.General.editor = "nvim"; + +* The <> option now allows defining modules directly under <>. +For example, ++ +[source,nix] +programs.waybar.settings.modules."custom/my-module" = { }; ++ +becomes ++ +[source,nix] +programs.waybar.settings."custom/my-module" = { }; + diff --git a/infra/libkookie/home-manager-stable/docs/release-notes/rl-2205.adoc b/infra/libkookie/home-manager-stable/docs/release-notes/rl-2205.adoc new file mode 100644 index 00000000000..f600640e4f4 --- /dev/null +++ b/infra/libkookie/home-manager-stable/docs/release-notes/rl-2205.adoc @@ -0,0 +1,44 @@ +[[sec-release-22.05]] +== Release 22.05 + +The 22.05 release branch became the stable branch in May, 2022. + +[[sec-release-22.05-highlights]] +=== Highlights + +:hm-weblate: https://hosted.weblate.org/projects/home-manager/ + +This release has the following notable changes: + +* The `programs.waybar.settings.modules` option was removed. +Waybar modules should now be declared directly under `programs.waybar.settings`. + +* Home Manager now partially support translation of texts into different languages. +Note, the support is quite limited at the moment. +Specifically, it only applies to parts of the system written in the Bash language, +such as the `home-manager` command line tool and the activation script. ++ +If you would like to contribute to the translation effort +then you can do so through the {hm-weblate}[Home Manager Weblate project]. + +* A new module, `launchd.agents` was added. +Use this to enable services based on macOS LaunchAgents. + +[[sec-release-22.05-state-version-changes]] +=== State Version Changes + +The state version in this release includes the changes below. +These changes are only active if the `home.stateVersion` option is set to "22.05" or later. + +* The <> option now allows defining modules directly under <>. +Defining modules under `programs.waybar.settings.modules` will now be an error. +For example, ++ +[source,nix] +programs.waybar.settings.modules."custom/my-module" = { }; ++ +becomes ++ +[source,nix] +programs.waybar.settings."custom/my-module" = { }; + diff --git a/infra/libkookie/home-manager-stable/docs/usage.adoc b/infra/libkookie/home-manager-stable/docs/usage.adoc new file mode 100644 index 00000000000..26b9eee78ec --- /dev/null +++ b/infra/libkookie/home-manager-stable/docs/usage.adoc @@ -0,0 +1,245 @@ +[[ch-usage]] +== Using Home Manager + +Your use of Home Manager is centered around the configuration file, which is typically found at `~/.config/nixpkgs/home.nix`. + +This configuration file can be _built_ and _activated_. + +Building a configuration produces a directory in the Nix store that contains all files and programs that should be available in your home directory and Nix user profile, respectively. The build step also checks that the configuration is valid and it will fail with an error if you, for example, assign a value to an option that does not exist or assign a value of the wrong type. Some modules also have custom assertions that perform more detailed, module specific, checks. + +Concretely, if your configuration contains + +[source,nix] +programs.emacs.enable = "yes"; + +then building it, for example using `home-manager build`, will result in an error message saying something like + +[source,console] +---- +$ home-manager build +error: A definition for option `programs.emacs.enable' is not of type `boolean'. Definition values: +- In `/home/jdoe/.config/nixpkgs/home.nix': "yes" +(use '--show-trace' to show detailed location information) +---- + +The message indicates that you must provide a Boolean value for this option, that is, either `true` or `false`. The documentation of each option will state the expected type, for <> you will see ``Type: boolean''. You there also find information about the default value and a description of the option. You can find the complete option documentation in <> or directly in the terminal by running + +[source,console] +man home-configuration.nix + +Once a configuration is successfully built, it can be activated. The activation performs the steps necessary to make the files, programs, and services available in your user environment. The `home-manager switch` command performs a combined build and activation. + +[[sec-usage-configuration]] +=== Configuration Example + +A fresh install of Home Manager will generate a minimal `~/.config/nixpkgs/home.nix` file containing something like + +[source,nix] +---- +{ config, pkgs, ... }: + +{ + # Home Manager needs a bit of information about you and the + # paths it should manage. + home.username = "jdoe"; + home.homeDirectory = "/home/jdoe"; + + # This value determines the Home Manager release that your + # configuration is compatible with. This helps avoid breakage + # when a new Home Manager release introduces backwards + # incompatible changes. + # + # You can update Home Manager without changing this value. See + # the Home Manager release notes for a list of state version + # changes in each release. + home.stateVersion = "22.05"; + + # Let Home Manager install and manage itself. + programs.home-manager.enable = true; +} +---- + +You can use this as a base for your further configurations. + +[NOTE] +If you are not very familiar with the Nix language and NixOS modules then it is encouraged to start with small and simple changes. As you learn you can gradually grow the configuration with confidence. + +As an example, let us expand the initial configuration file to also install the htop and fortune packages, install Emacs with a few extra packages available, and enable the user gpg-agent service. + +To satisfy the above setup we should elaborate the `home.nix` file as follows: + +[source,nix] +---- +{ config, pkgs, ... }: + +{ + # Home Manager needs a bit of information about you and the + # paths it should manage. + home.username = "jdoe"; + home.homeDirectory = "/home/jdoe"; + + # Packages that should be installed to the user profile. + home.packages = [ <1> + pkgs.htop + pkgs.fortune + ]; + + # This value determines the Home Manager release that your + # configuration is compatible with. This helps avoid breakage + # when a new Home Manager release introduces backwards + # incompatible changes. + # + # You can update Home Manager without changing this value. See + # the Home Manager release notes for a list of state version + # changes in each release. + home.stateVersion = "22.05"; + + # Let Home Manager install and manage itself. + programs.home-manager.enable = true; + + programs.emacs = { <2> + enable = true; + extraPackages = epkgs: [ + epkgs.nix-mode + epkgs.magit + ]; + }; + + services.gpg-agent = { <3> + enable = true; + defaultCacheTtl = 1800; + enableSshSupport = true; + }; +} +---- +<1> Nixpkgs packages can be installed to the user profile using <>. +<2> The option names of a program module typically start with `programs.`. +<3> Similarly, for a service module, the names start with `services.`. Note in some cases a package has both programs _and_ service options – Emacs is such an example. + +To activate this configuration you can run + +[source,console] +home-manager switch + +or if you are not feeling so lucky, + +[source,console] +home-manager build + +which will create a `result` link to a directory containing an +activation script and the generated home directory files. + +[[sec-usage-rollbacks]] +=== Rollbacks + +While the `home-manager` tool does not explicitly support rollbacks at the moment it is relatively easy to perform one manually. The steps to do so are + +1. Run `home-manager generations` to determine which generation you wish to rollback to: ++ +[source,console] +---- +$ home-manager generations +2018-01-04 11:56 : id 765 -> /nix/store/kahm1rxk77mnvd2l8pfvd4jkkffk5ijk-home-manager-generation +2018-01-03 10:29 : id 764 -> /nix/store/2wsmsliqr5yynqkdyjzb1y57pr5q2lsj-home-manager-generation +2018-01-01 12:21 : id 763 -> /nix/store/mv960kl9chn2lal5q8lnqdp1ygxngcd1-home-manager-generation +2017-12-29 21:03 : id 762 -> /nix/store/6c0k1r03fxckql4vgqcn9ccb616ynb94-home-manager-generation +2017-12-25 18:51 : id 761 -> /nix/store/czc5y6vi1rvnkfv83cs3rn84jarcgsgh-home-manager-generation +… +---- + +2. Copy the Nix store path of the generation you chose, e.g., ++ +---- +/nix/store/mv960kl9chn2lal5q8lnqdp1ygxngcd1-home-manager-generation +---- ++ +for generation 763. + +3. Run the `activate` script inside the copied store path: ++ +[source,console] +---- +$ /nix/store/mv960kl9chn2lal5q8lnqdp1ygxngcd1-home-manager-generation/activate +Starting home manager activation +… +---- + +[[sec-usage-dotfiles]] +=== Keeping your ~ safe from harm + +To configure programs and services Home Manager must write various things to your home directory. To prevent overwriting any existing files when switching to a new generation, Home Manager will attempt to detect collisions between existing files and generated files. If any such collision is detected the activation will terminate before changing anything on your computer. + +For example, suppose you have a wonderful, painstakingly created `~/.config/git/config` and add + +[source,nix] +---- +{ + # … + + programs.git = { + enable = true; + userName = "Jane Doe"; + userEmail = "jane.doe@example.org"; + }; + + # … +} +---- + +to your configuration. Attempting to switch to the generation will then result in + +[source,console] +---- +$ home-manager switch +… +Activating checkLinkTargets +Existing file '/home/jdoe/.config/git/config' is in the way +Please move the above files and try again +---- + +[[sec-usage-graphical]] +=== Graphical services + +Home Manager includes a number of services intended to run in a graphical session, for example `xscreensaver` and `dunst`. Unfortunately, such services will not be started automatically unless you let Home Manager start your X session. That is, you have something like + +[source,nix] +---- +{ + # … + + services.xserver.enable = true; + + # … +} +---- + +in your system configuration and + +[source,nix] +---- +{ + # … + + xsession.enable = true; + xsession.windowManager.command = "…"; + + # … +} +---- + +in your Home Manager configuration. + +[[sec-updating]] +=== Updating + +If you have installed Home Manager using the Nix channel method +then updating Home Manager is done by first updating the channel. +You can then switch to the updated Home Manager environment. + +[source,console] +---- +$ nix-channel --update +… +unpacking channels... +$ home-manager switch +---- diff --git a/infra/libkookie/home-manager-stable/docs/writing-modules.adoc b/infra/libkookie/home-manager-stable/docs/writing-modules.adoc new file mode 100644 index 00000000000..0f3336ff2c0 --- /dev/null +++ b/infra/libkookie/home-manager-stable/docs/writing-modules.adoc @@ -0,0 +1,187 @@ +[[ch-writing-modules]] +== Writing Home Manager Modules +:writing-nixos-modules: https://nixos.org/nixos/manual/index.html#sec-writing-modules + +The module system in Home Manager is based entirely on the NixOS module system so we will here only highlight aspects that are specific for Home Manager. For information about the module system as such please refer to the {writing-nixos-modules}[Writing NixOS Modules] chapter of the NixOS manual. + +[[sec-option-types]] +=== Option Types +:wikipedia-dag: https://en.wikipedia.org/w/index.php?title=Directed_acyclic_graph&oldid=939656095 +:gvariant-description: https://developer.gnome.org/glib/stable/glib-GVariant.html#glib-GVariant.description + +Overall the basic option types are the same in Home Manager as NixOS. A few Home Manager options, however, make use of custom types that are worth describing in more detail. These are the option types `dagOf` and `gvariant` that are used, for example, by <> and <>. + +`hm.types.dagOf`:: +Options of this type have attribute sets as values where each member is a node in a {wikipedia-dag}[directed acyclic graph] (DAG). This allows the attribute set entries to express dependency relations among themselves. This can, for example, be used to control the order of match blocks in a OpenSSH client configuration or the order of activation script blocks in <>. ++ +A number of functions are provided to create DAG nodes. The functions are shown below with examples using an option `foo.bar` of type `hm.types.dagOf types.int`. ++ +`hm.dag.entryAnywhere (value: T)`::: +Indicates that `value` can be placed anywhere within the DAG. This is also the default for plain attribute set entries, that is ++ +[source,nix] +---- +foo.bar = { + a = hm.dag.entryAnywhere 0; +} +---- ++ +and ++ +[source,nix] +---- +foo.bar = { + a = 0; +} +---- ++ +are equivalent. ++ +`hm.dag.entryAfter (afters: list string) (value: T)`::: +Indicates that `value` must be placed _after_ each of the attribute names in the given list. For example ++ +[source,nix] +---- +foo.bar = { + a = 0; + b = hm.dag.entryAfter [ "a" ] 1; +} +---- ++ +would place `b` after `a` in the graph. ++ +`hm.dag.entryBefore (befores: list string) (value: T)`::: +Indicates that `value` must be placed _before_ each of the attribute names in the given list. For example ++ +[source,nix] +---- +foo.bar = { + b = hm.dag.entryBefore [ "a" ] 1; + a = 0; +} +---- ++ +would place `b` before `a` in the graph. ++ +`hm.dag.entryBetween (befores: list string) (afters: list string) (value: T)`::: +Indicates that `value` must be placed _before_ the attribute names in the first list and _after_ the attribute names in the second list. For example ++ +[source,nix] +---- +foo.bar = { + a = 0; + c = hm.dag.entryBetween [ "b" ] [ "a" ] 2; + b = 1; +} +---- ++ +would place `c` before `b` and after `a` in the graph. + +`hm.types.gvariant`:: +This type is useful for options representing {gvariant-description}[GVariant] values. The type accepts all primitive GVariant types as well as arrays and tuples. Dictionaries are not currently supported. ++ +To create a GVariant value you can use a number of provided functions. Examples assume an option `foo.bar` of type `hm.types.gvariant`. ++ +`hm.gvariant.mkBoolean (v: bool)`::: +Takes a Nix value `v` to a GVariant `boolean` value. Note, Nix booleans are automatically coerced using this function. That is, ++ +[source,nix] +---- +foo.bar = hm.gvariant.mkBoolean true; +---- ++ +is equivalent to ++ +[source,nix] +---- +foo.bar = true; +---- +`hm.gvariant.mkString (v: string)`::: +Takes a Nix value `v` to a GVariant `string` value. Note, Nix strings are automatically coerced using this function. That is, ++ +[source,nix] +---- +foo.bar = hm.gvariant.mkString "a string"; +---- ++ +is equivalent to ++ +[source,nix] +---- +foo.bar = "a string"; +---- +`hm.gvariant.mkObjectpath (v: string)`::: +Takes a Nix value `v` to a GVariant `objectpath` value. +`hm.gvariant.mkUchar (v: string)`::: +Takes a Nix value `v` to a GVariant `uchar` value. +`hm.gvariant.mkInt16 (v: int)`::: +Takes a Nix value `v` to a GVariant `int16` value. +`hm.gvariant.mkUint16 (v: int)`::: +Takes a Nix value `v` to a GVariant `uint16` value. +`hm.gvariant.mkInt32 (v: int)`::: +Takes a Nix value `v` to a GVariant `int32` value. Note, Nix integers are automatically coerced using this function. That is, ++ +[source,nix] +---- +foo.bar = hm.gvariant.mkInt32 7; +---- ++ +is equivalent to ++ +[source,nix] +---- +foo.bar = 7; +---- +`hm.gvariant.mkUint32 (v: int)`::: +Takes a Nix value `v` to a GVariant `uint32` value. +`hm.gvariant.mkInt64 (v: int)`::: +Takes a Nix value `v` to a GVariant `int64` value. +`hm.gvariant.mkUint64 (v: int)`::: +Takes a Nix value `v` to a GVariant `uint64` value. +`hm.gvariant.mkDouble (v: double)`::: +Takes a Nix value `v` to a GVariant `double` value. Note, Nix floats are automatically coerced using this function. That is, ++ +[source,nix] +---- +foo.bar = hm.gvariant.mkDouble 3.14; +---- ++ +is equivalent to ++ +[source,nix] +---- +foo.bar = 3.14; +---- ++ +`hm.gvariant.mkArray type elements`::: +Builds a GVariant array containing the given list of elements, where each element is a GVariant value of the given type. The `type` value can be constructed using ++ +-- +- `hm.gvariant.type.string` +- `hm.gvariant.type.boolean` +- `hm.gvariant.type.uchar` +- `hm.gvariant.type.int16` +- `hm.gvariant.type.uint16` +- `hm.gvariant.type.int32` +- `hm.gvariant.type.uint32` +- `hm.gvariant.type.int64` +- `hm.gvariant.type.uint64` +- `hm.gvariant.type.double` +- `hm.gvariant.type.arrayOf type` +- `hm.gvariant.type.maybeOf type` +- `hm.gvariant.type.tupleOf types` +-- ++ +where `type` and `types` are themselves a type and list of types, respectively. ++ +`hm.gvariant.mkEmptyArray type`::: +An alias of `hm.gvariant.mkArray type []`. ++ +`hm.gvariant.mkNothing type`::: +Builds a GVariant maybe value whose (non-existent) element is of the given type. The `type` value is constructed as described for the `mkArray` function above. ++ +`hm.gvariant.mkJust element`::: +Builds a GVariant maybe value containing the given GVariant element. ++ +`hm.gvariant.mkTuple elements`::: +Builds a GVariant tuple containing the given list of elements, where each element is a GVariant value. diff --git a/infra/libkookie/home-manager-stable/flake.nix b/infra/libkookie/home-manager-stable/flake.nix new file mode 100644 index 00000000000..a5e073173a2 --- /dev/null +++ b/infra/libkookie/home-manager-stable/flake.nix @@ -0,0 +1,60 @@ +{ + description = "Home Manager for Nix"; + + outputs = { self, nixpkgs }: + let + # List of systems supported by home-manager binary + supportedSystems = with nixpkgs.lib.platforms; linux ++ darwin; + + # Function to generate a set based on supported systems + forAllSystems = nixpkgs.lib.genAttrs supportedSystems; + + nixpkgsFor = forAllSystems (system: import nixpkgs { inherit system; }); + in rec { + nixosModules.home-manager = import ./nixos; + nixosModule = self.nixosModules.home-manager; + + darwinModules.home-manager = import ./nix-darwin; + darwinModule = self.darwinModules.home-manager; + + packages = forAllSystems (system: + let docs = import ./docs { pkgs = nixpkgsFor.${system}; }; + in { + home-manager = nixpkgsFor.${system}.callPackage ./home-manager { }; + docs-html = docs.manual.html; + docs-manpages = docs.manPages; + docs-json = docs.options.json; + default = self.packages.${system}.home-manager; + }); + + # defaultPackage is deprecated as of Nix 2.7.0 + defaultPackage = forAllSystems (system: self.packages.${system}.default); + + apps = forAllSystems (system: { + home-manager = { + type = "app"; + program = "${defaultPackage.${system}}/bin/home-manager"; + }; + }); + + defaultApp = forAllSystems (system: apps.${system}.home-manager); + + lib = { + hm = import ./modules/lib { lib = nixpkgs.lib; }; + homeManagerConfiguration = { configuration, system, homeDirectory + , username, extraModules ? [ ], extraSpecialArgs ? { } + , pkgs ? builtins.getAttr system nixpkgs.outputs.legacyPackages + , lib ? pkgs.lib, check ? true, stateVersion ? "20.09" }@args: + assert nixpkgs.lib.versionAtLeast stateVersion "20.09"; + + import ./modules { + inherit pkgs lib check extraSpecialArgs; + configuration = { ... }: { + imports = [ configuration ] ++ extraModules; + home = { inherit homeDirectory stateVersion username; }; + nixpkgs = { inherit (pkgs) config overlays; }; + }; + }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/format b/infra/libkookie/home-manager-stable/format new file mode 100755 index 00000000000..8bf78064523 --- /dev/null +++ b/infra/libkookie/home-manager-stable/format @@ -0,0 +1,32 @@ +#! /usr/bin/env nix-shell +#! nix-shell -I nixpkgs=https://github.com/NixOS/nixpkgs/archive/5edf5b60c3d8f82b5fc5e73e822b6f7460584945.tar.gz -i bash -p findutils nixfmt + +CHECK_ARG= + +case $1 in + -h) + echo "$0 [-c]" + ;; + -c) + CHECK_ARG=-c + ;; +esac + +# The excludes are for files touched by open pull requests and we want +# to avoid merge conflicts. +find . -name '*.nix' \ + ! -path ./home-manager/home-manager.nix \ + ! -path ./modules/default.nix \ + ! -path ./modules/files.nix \ + ! -path ./modules/home-environment.nix \ + ! -path ./modules/launchd/launchd.nix \ + ! -path ./modules/lib/default.nix \ + ! -path ./modules/lib/file-type.nix \ + ! -path ./modules/manual.nix \ + ! -path ./modules/misc/news.nix \ + ! -path ./modules/programs/bash.nix \ + ! -path ./modules/programs/ssh.nix \ + ! -path ./modules/programs/zsh.nix \ + ! -path ./nix-darwin/default.nix \ + ! -path ./tests/default.nix \ + -exec nixfmt $CHECK_ARG {} + diff --git a/infra/libkookie/home-manager-stable/home-manager/completion.bash b/infra/libkookie/home-manager-stable/home-manager/completion.bash new file mode 100644 index 00000000000..ec20bbc1b8a --- /dev/null +++ b/infra/libkookie/home-manager-stable/home-manager/completion.bash @@ -0,0 +1,366 @@ +#!/bin/env bash + +################################################## + +# « home-manager » command-line completion +# +# © 2019 "Sam Boosalis" +# +# MIT License +# + +################################################## +# Contributing: + +# Compatibility — Bash 3. +# +# OSX won't update Bash 3 (last updated circa 2009) to Bash 4, +# and we'd like this completion script to work on both Linux and Mac. +# +# For example, OSX Yosemite (released circa 2014) ships with Bash 3: +# +# $ echo $BASH_VERSION +# 3.2 +# +# While Ubuntu LTS 14.04 (a.k.a. Trusty, also released circa 2016) +# ships with the latest version, Bash 4 (updated circa 2016): +# +# $ echo $BASH_VERSION +# 4.3 +# + +# Testing +# +# (1) Invoke « shellcheck » +# +# * source: « https://github.com/koalaman/shellcheck » +# * run: « shellcheck ./share/bash-completion/completions/home-manager » +# +# (2) Interpret via Bash 3 +# +# * run: « bash --noprofile --norc ./share/bash-completion/completions/home-manager » +# + +################################################## +# Examples: + +# $ home-manager +# +# -A +# -I +# -f +# --file +# -h +# --help +# -n +# --dry-run +# -v +# --verbose +# build +# edit +# expire-generations +# generations +# help +# news +# option +# packages +# remove-generations +# switch +# uninstall + +# $ home-manager e +# +# edit +# expire-generations + +# $ home-manager remove-generations 20 +# +# 200 +# 201 +# 202 +# 203 + +################################################## +# Notes: + +# « home-manager » Subcommands: +# +# help +# edit +# option +# build +# switch +# generations +# remove-generations +# expire-generations +# packages +# news +# uninstall + +# « home-manager » Options: +# +# -b EXT +# -f FILE +# --file FILE +# -A ATTRIBUTE +# -I PATH +# -v +# --verbose +# -n +# --dry-run +# -h +# --help + +# $ home-manager +# +# Usage: /home/sboo/.nix-profile/bin/home-manager [OPTION] COMMAND +# +# Options +# +# -f FILE The home configuration file. +# Default is '~/.config/nixpkgs/home.nix'. +# -A ATTRIBUTE Optional attribute that selects a configuration +# expression in the configuration file. +# -I PATH Add a path to the Nix expression search path. +# -b EXT Move existing files to new path rather than fail. +# -v Verbose output +# -n Do a dry run, only prints what actions would be taken +# -h Print this help +# +# Commands +# +# help Print this help +# +# edit Open the home configuration in $EDITOR +# +# option OPTION.NAME +# Inspect configuration option named OPTION.NAME. +# +# build Build configuration into result directory +# +# switch Build and activate configuration +# +# generations List all home environment generations +# +# remove-generations ID... +# Remove indicated generations. Use 'generations' command to +# find suitable generation numbers. +# +# expire-generations TIMESTAMP +# Remove generations older than TIMESTAMP where TIMESTAMP is +# interpreted as in the -d argument of the date tool. For +# example "-30 days" or "2018-01-01". +# +# packages List all packages installed in home-manager-path +# +# news Show news entries in a pager +# +# uninstall Remove Home Manager +# +################################################## +# Dependencies: + +command -v home-manager >/dev/null +command -v grep >/dev/null +command -v sed >/dev/null + +################################################## +# Code: + +_home-manager_list-generation-identifiers () + +{ + + home-manager generations | sed -n -e 's/^................ : id \([[:alnum:]]\+\) -> .*/\1/p' + +} + +# NOTES +# +# (1) the « sed -n -e 's/.../.../p' » invocation: +# +# * the « -e '...' » option takes a Sed Script. +# * the « -n » option only prints when « .../p » would print. +# * the « s/xxx/yyy/ » Sed Script substitutes « yyy » whenever « xxx » is matched. +# +# (2) the « '^................ : id \([[:alnum:]]\+\) -> .*' » regular expression: +# +# * matches « 199 », for example, in the line « 2019-03-13 15:26 : id 199 -> /nix/store/mv619y9pzgsx3kndq0q7fjfvbqqdy5k8-home-manager-generation » +# +# + +#------------------------------------------------# + +# shellcheck disable=SC2120 +_home-manager_list-nix-attributes () + +{ + local HomeFile + local HomeAttrsString + # local HomeAttrsArray + # local HomeAttr + + if [ -z "$1" ] + then + HomeFile=$(readlink -f "$(_home-manager_get-default-home-file)") + else + HomeFile="$1" + fi + + HomeAttrsString=$(nix-instantiate --eval -E "let home = import ${HomeFile}; in (builtins.trace (builtins.toString (builtins.attrNames home)) null)" |& grep '^trace: ') + HomeAttrsString="${HomeAttrsString#trace: }" + + echo "${HomeAttrsString}" + + # IFS=" " read -ar HomeAttrsArray <<< "${HomeAttrsString}" + # + # local HomeAttr + # for HomeAttr in "${HomeAttrsArray[@]}" + # do + # echo "${HomeAttr}" + # done + +} + +# e.g.: +# +# $ nix-instantiate --eval -E 'let home = import /home/sboo/configuration/configs/nixpkgs/home-attrs.nix; in (builtins.trace (builtins.toString (builtins.attrNames home)) null)' 1>/dev/null +# trace: darwin linux +# +# $ _home-manager_list-nix-attributes +# linux darwin +# + +#------------------------------------------------# + +_home-manager_get-default-home-file () + +{ + local HomeFileDefault + + HomeFileDefault="$(_home-manager_xdg-get-config-home)/nixpkgs/home.nix" + + echo "${HomeFileDefault}" +} + +# e.g.: +# +# $ _home-manager_get-default-home-file +# ~/.config/nixpkgs/home.nix +# + +################################################## +# XDG-BaseDirs: + +_home-manager_xdg-get-config-home () { + + echo "${XDG_CONFIG_HOME:-$HOME/.config}" + +} + +#------------------------------------------------# + +_home-manager_xdg-get-data-home () { + + echo "${XDG_DATA_HOME:-$HOME/.local/share}" + +} + + +#------------------------------------------------# +_home-manager_xdg-get-cache-home () { + + echo "${XDG_CACHE_HOME:-$HOME/.cache}" + +} + +################################################## + +# shellcheck disable=SC2207 +_home-manager_completions () +{ + + #--------------------------# + + local Subcommands + Subcommands=( "help" "edit" "option" "build" "instantiate" "switch" "generations" "remove-generations" "expire-generations" "packages" "news" "uninstall" ) + + # ^ « home-manager »'s subcommands. + + #--------------------------# + + local Options + Options=( "-f" "--file" "-b" "-A" "-I" "-h" "--help" "-n" "--dry-run" "-v" \ + "--verbose" "--cores" "--debug" "--impure" "--keep-failed" \ + "--keep-going" "-j" "--max-jobs" "--no-substitute" "--no-out-link" \ + "--show-trace" "--substitute" "--builders" "--version" \ + "--update-input" "--override-input" "--experimental-features" \ + "--extra-experimental-features" ) + + # ^ « home-manager »'s options. + + #--------------------------# + + local CurrentWord + CurrentWord="${COMP_WORDS[$COMP_CWORD]}" + + # ^ the word currently being completed + + local PreviousWord + if [ "$COMP_CWORD" -ge 1 ] + then + PreviousWord="${COMP_WORDS[COMP_CWORD-1]}" + else + PreviousWord="" + fi + + # ^ the word to the left of the current word. + # + # e.g. in « home-manager -v -f ./ »: + # + # PreviousWord="-f" + # CurrentWord="./" + + #--------------------------# + + COMPREPLY=() + + case "$PreviousWord" in + + "-f"|"--file") + + COMPREPLY+=( $( compgen -A file -- "$CurrentWord") ) + ;; + + "-I") + + COMPREPLY+=( $( compgen -A directory -- "$CurrentWord") ) + ;; + + "-A") + + # shellcheck disable=SC2119 + COMPREPLY+=( $( compgen -W "$(_home-manager_list-nix-attributes)" -- "$CurrentWord") ) + ;; + + "remove-generations") + + COMPREPLY+=( $( compgen -W "$(_home-manager_list-generation-identifiers)" -- "$CurrentWord" ) ) + ;; + + *) + + COMPREPLY+=( $( compgen -W "${Subcommands[*]}" -- "$CurrentWord" ) ) + COMPREPLY+=( $( compgen -W "${Options[*]}" -- "$CurrentWord" ) ) + ;; + + esac + + #--------------------------# +} + +################################################## + +complete -F _home-manager_completions -o default home-manager + +#complete -W "help edit option build switch generations remove-generations expire-generations packages news" home-manager diff --git a/infra/libkookie/home-manager-stable/home-manager/completion.fish b/infra/libkookie/home-manager-stable/home-manager/completion.fish new file mode 100644 index 00000000000..aca4943fe94 --- /dev/null +++ b/infra/libkookie/home-manager-stable/home-manager/completion.fish @@ -0,0 +1,70 @@ +#!/bin/env fish +################################################## + +# « home-manager » command-line fish completion +# +# © 2021 "Ariel AxionL" +# +# MIT License +# + +################################################## + +### Functions +function __home_manager_generations --description "Get all generations" + for i in (home-manager generations) + set -l split (string split " " $i) + set -l gen_id $split[5] + set -l gen_datetime $split[1..2] + set -l gen_hash (string match -r '\w{32}' $i) + echo $gen_id\t$gen_datetime $gen_hash + end +end + + +### SubCommands +complete -c home-manager -n "__fish_use_subcommand" -f -a "help" -d "Print home-manager help" +complete -c home-manager -n "__fish_use_subcommand" -f -a "edit" -d "Open the home configuration in $EDITOR" +complete -c home-manager -n "__fish_use_subcommand" -f -a "option" -d "Inspect configuration option" +complete -c home-manager -n "__fish_use_subcommand" -f -a "build" -d "Build configuration into result directory" +complete -c home-manager -n "__fish_use_subcommand" -f -a "instantiate" -d "Instantiate the configuration and print the resulting derivation" +complete -c home-manager -n "__fish_use_subcommand" -f -a "switch" -d "Build and activate configuration" +complete -c home-manager -n "__fish_use_subcommand" -f -a "generations" -d "List all home environment generations" +complete -c home-manager -n "__fish_use_subcommand" -f -a "packages" -d "List all packages installed in home-manager-path" +complete -c home-manager -n "__fish_use_subcommand" -f -a "news" -d "Show news entries in a pager" +complete -c home-manager -n "__fish_use_subcommand" -f -a "uninstall" -d "Remove Home Manager" + +complete -c home-manager -n "__fish_use_subcommand" -x -a "remove-generations" -d "Remove indicated generations" +complete -c home-manager -n "__fish_seen_subcommand_from remove-generations" -f -ka '(__home_manager_generations)' + +complete -c home-manager -n "__fish_use_subcommand" -x -a "expire-generations" -d "Remove generations older than TIMESTAMP" + +### Options +complete -c home-manager -F -s f -l "file" -d "The home configuration file" +complete -c home-manager -x -s A -d "Select an expression in the configuration file" +complete -c home-manager -F -s I -d "Add a path to the Nix expression search path" +complete -c home-manager -F -l "flake" -d "Use Home Manager configuration at specified flake-uri" +complete -c home-manager -F -s b -d "Move existing files to new path rather than fail" +complete -c home-manager -f -s v -l "verbose" -d "Verbose output" +complete -c home-manager -f -s n -l "dry-run" -d "Do a dry run, only prints what actions would be taken" +complete -c home-manager -f -s h -l "help" -d "Print this help" +complete -c home-manager -f -s h -l "version" -d "Print the Home Manager version" + +complete -c home-manager -x -l "arg" -d "Override inputs passed to home-manager.nix" +complete -c home-manager -x -l "argstr" -d "Like --arg but the value is a string" +complete -c home-manager -x -l "cores" -d "Threads per job (e.g. -j argument to make)" +complete -c home-manager -x -l "debug" +complete -c home-manager -x -l "impure" +complete -c home-manager -f -l "keep-failed" -d "Keep temporary directory used by failed builds" +complete -c home-manager -f -l "keep-going" -d "Keep going in case of failed builds" +complete -c home-manager -x -s j -l "max-jobs" -d "Max number of build jobs in parallel" +complete -c home-manager -x -l "option" -d "Set Nix configuration option" +complete -c home-manager -x -l "builders" -d "Remote builders" +complete -c home-manager -f -l "show-trace" -d "Print stack trace of evaluation errors" +complete -c home-manager -f -l "substitute" +complete -c home-manager -f -l "no-substitute" +complete -c home-manager -f -l "no-out-link" +complete -c home-manager -f -l "update-input" +complete -c home-manager -f -l "override-input" +complete -c home-manager -f -l "experimental-features" +complete -c home-manager -f -l "extra-experimental-features" diff --git a/infra/libkookie/home-manager-stable/home-manager/completion.zsh b/infra/libkookie/home-manager-stable/home-manager/completion.zsh new file mode 100644 index 00000000000..6e20d17d07f --- /dev/null +++ b/infra/libkookie/home-manager-stable/home-manager/completion.zsh @@ -0,0 +1,73 @@ +#compdef home-manager + +local state ret=1 + +_arguments \ + '-A[attribute]:ATTRIBUTE:()' \ + '-I[search path]:PATH:_files -/' \ + '-b[backup files]:EXT:()' \ + '--cores[cores]:NUM:()' \ + '--debug[debug]' \ + '--impure[impure]' \ + '--keep-failed[keep failed]' \ + '--keep-going[keep going]' \ + '--version[version]' \ + '(-h --help)'{--help,-h}'[help]' \ + '(-v --verbose)'{--verbose,-v}'[verbose]' \ + '(-n --dry-run)'{--dry-run,-n}'[dry run]' \ + '(-f --file)'{--file,-f}'[configuration file]:FILE:_files' \ + '(-j --max-jobs)'{--max-jobs,-j}'[max jobs]:NUM:()' \ + '--option[option]:NAME VALUE:()' \ + '--builders[builders]:SPEC:()' \ + '--show-trace[show trace]' \ + '--override-input[override flake input]:NAME VALUE:()' \ + '--update-input[update flake input]:NAME:()' \ + '--experimental-features[set experimental Nix features]:VALUE:()' \ + '--extra-experimental-features:[append to experimental Nix features]:VALUE:()' \ + '1: :->cmds' \ + '*:: :->args' && ret=0 + +case "$state" in + cmds) + _values 'command' \ + 'help[help]' \ + 'edit[edit]' \ + 'option[inspect option]' \ + 'build[build]' \ + 'switch[switch]' \ + 'generations[list generations]' \ + 'remove-generations[remove generations]' \ + 'expire-generations[expire generations]' \ + 'packages[managed packages]' \ + 'news[read the news]' \ + 'uninstall[uninstall]' && ret=0 + ;; + args) + case $line[1] in + remove-generations) + _values 'generations' \ + $(home-manager generations | cut -d ' ' -f 5) && ret=0 + ;; + build|switch) + _arguments \ + '--cores[cores]:NUM:()' \ + '--debug[debug]' \ + '--impure[impure]' \ + '--keep-failed[keep failed]' \ + '--keep-going[keep going]' \ + '--max-jobs[max jobs]:NUM:()' \ + '--no-out-link[no out link]' \ + '--no-substitute[no substitute]' \ + '--option[option]:NAME VALUE:()' \ + '--show-trace[show trace]' \ + '--substitute[substitute]' \ + '--builders[builders]:SPEC:()' \ + '--override-input[override flake input]:NAME VALUE:()' \ + '--update-input[update flake input]:NAME:()' \ + '--experimental-features[set experimental Nix features]:VALUE:()' \ + '--extra-experimental-features:[append to experimental Nix features]:VALUE:()' + ;; + esac +esac + +return ret diff --git a/infra/libkookie/home-manager-stable/home-manager/default.nix b/infra/libkookie/home-manager-stable/home-manager/default.nix new file mode 100644 index 00000000000..4bb55904ae0 --- /dev/null +++ b/infra/libkookie/home-manager-stable/home-manager/default.nix @@ -0,0 +1,55 @@ +{ runCommand, lib, bash, callPackage, coreutils, findutils, gettext, gnused +, less +# used for pkgs.path for nixos-option +, pkgs + +# Extra path to Home Manager. If set then this path will be tried +# before `$HOME/.config/nixpkgs/home-manager` and +# `$HOME/.nixpkgs/home-manager`. +, path ? null }: + +let + + pathStr = if path == null then "" else path; + + nixos-option = pkgs.nixos-option or (callPackage + (pkgs.path + "/nixos/modules/installer/tools/nixos-option") { }); + +in runCommand "home-manager" { + preferLocalBuild = true; + nativeBuildInputs = [ gettext ]; + meta = with lib; { + description = "A user environment configurator"; + maintainers = [ maintainers.rycee ]; + platforms = platforms.unix; + license = licenses.mit; + }; +} '' + install -v -D -m755 ${./home-manager} $out/bin/home-manager + + substituteInPlace $out/bin/home-manager \ + --subst-var-by bash "${bash}" \ + --subst-var-by DEP_PATH "${ + lib.makeBinPath [ coreutils findutils gettext gnused less nixos-option ] + }" \ + --subst-var-by HOME_MANAGER_LIB '${../lib/bash/home-manager.sh}' \ + --subst-var-by HOME_MANAGER_PATH '${pathStr}' \ + --subst-var-by OUT "$out" + + install -D -m755 ${./completion.bash} \ + $out/share/bash-completion/completions/home-manager + install -D -m755 ${./completion.zsh} \ + $out/share/zsh/site-functions/_home-manager + install -D -m755 ${./completion.fish} \ + $out/share/fish/vendor_completions.d/home-manager.fish + + install -D -m755 ${../lib/bash/home-manager.sh} \ + "$out/share/bash/home-manager.sh" + + for path in ${./po}/*.po; do + lang="''${path##*/}" + lang="''${lang%%.*}" + mkdir -p "$out/share/locale/$lang/LC_MESSAGES" + msgfmt -o "$out/share/locale/$lang/LC_MESSAGES/home-manager.mo" "$path" + done +'' diff --git a/infra/libkookie/home-manager-stable/home-manager/home-manager b/infra/libkookie/home-manager-stable/home-manager/home-manager new file mode 100644 index 00000000000..6483c59f10c --- /dev/null +++ b/infra/libkookie/home-manager-stable/home-manager/home-manager @@ -0,0 +1,736 @@ +#!@bash@/bin/bash + +# Prepare to use tools from Nixpkgs. +PATH=@DEP_PATH@${PATH:+:}$PATH + +set -euo pipefail + +export TEXTDOMAIN=home-manager +export TEXTDOMAINDIR=@OUT@/share/locale + +# shellcheck disable=1091 +source @HOME_MANAGER_LIB@ + +function removeByName() { + nix profile list \ + | { grep "$1" || test $? = 1; } \ + | cut -d ' ' -f 4 \ + | xargs -t $DRY_RUN_CMD nix profile remove $VERBOSE_ARG +} + +function setNixProfileCommands() { + if [[ -e ~/.nix-profile/manifest.json ]] ; then + LIST_OUTPATH_CMD="nix profile list" + REMOVE_CMD="removeByName" + else + LIST_OUTPATH_CMD="nix-env -q --out-path" + REMOVE_CMD="nix-env -q" + fi +} + +function setVerboseAndDryRun() { + if [[ -v VERBOSE ]]; then + export VERBOSE_ARG="--verbose" + else + export VERBOSE_ARG="" + fi + + if [[ -v DRY_RUN ]] ; then + export DRY_RUN_CMD=echo + else + export DRY_RUN_CMD="" + fi +} + +function setWorkDir() { + if [[ ! -v WORK_DIR ]]; then + WORK_DIR="$(mktemp --tmpdir -d home-manager-build.XXXXXXXXXX)" + # shellcheck disable=2064 + trap "rm -r '$WORK_DIR'" EXIT + fi +} + +# Attempts to set the HOME_MANAGER_CONFIG global variable. +# +# If no configuration file can be found then this function will print +# an error message and exit with an error code. +function setConfigFile() { + if [[ -v HOME_MANAGER_CONFIG ]] ; then + if [[ ! -e "$HOME_MANAGER_CONFIG" ]] ; then + _i "No configuration file found at %s" \ + "$HOME_MANAGER_CONFIG" >&2 + exit 1 + fi + + HOME_MANAGER_CONFIG="$(realpath "$HOME_MANAGER_CONFIG")" + return + fi + + local defaultConfFile="${XDG_CONFIG_HOME:-$HOME/.config}/nixpkgs/home.nix" + local confFile + for confFile in "$defaultConfFile" \ + "$HOME/.nixpkgs/home.nix" ; do + if [[ -e "$confFile" ]] ; then + HOME_MANAGER_CONFIG="$(realpath "$confFile")" + return + fi + done + + _i "No configuration file found. Please create one at %s" \ + "$defaultConfFile" >&2 + exit 1 +} + +function setHomeManagerNixPath() { + local path + for path in "@HOME_MANAGER_PATH@" \ + "${XDG_CONFIG_HOME:-$HOME/.config}/nixpkgs/home-manager" \ + "$HOME/.nixpkgs/home-manager" ; do + if [[ -e "$path" || "$path" =~ ^https?:// ]] ; then + export NIX_PATH="home-manager=$path${NIX_PATH:+:}$NIX_PATH" + return + fi + done +} + +function setFlakeAttribute() { + local configFlake="${XDG_CONFIG_HOME:-$HOME/.config}/nixpkgs/flake.nix" + if [[ -z $FLAKE_ARG && ! -v HOME_MANAGER_CONFIG && -e "$configFlake" ]]; then + FLAKE_ARG="$(dirname "$(readlink -f "$configFlake")")" + fi + + if [[ -n "$FLAKE_ARG" ]]; then + local flake="${FLAKE_ARG%#*}" + case $FLAKE_ARG in + *#*) + local name="${FLAKE_ARG#*#}" + ;; + *) + local name="$USER@$(hostname)" + if [ "$(nix eval "$flake#homeConfigurations" --apply "x: x ? \"$name\"")" = "false" ]; then + name="$USER" + fi + ;; + esac + export FLAKE_CONFIG_URI="$flake#homeConfigurations.\"$name\"" + fi +} + +function doInspectOption() { + setFlakeAttribute + if [[ -v FLAKE_CONFIG_URI ]]; then + _iError "Can't inspect options of a flake configuration" + exit 1 + fi + setConfigFile + setHomeManagerNixPath + + local extraArgs=("$@") + + for p in "${EXTRA_NIX_PATH[@]}"; do + extraArgs=("${extraArgs[@]}" "-I" "$p") + done + + if [[ -v VERBOSE ]]; then + extraArgs=("${extraArgs[@]}" "--show-trace") + fi + + local HOME_MANAGER_CONFIG_NIX HOME_MANAGER_CONFIG_ATTRIBUTE_NIX + HOME_MANAGER_CONFIG_NIX=${HOME_MANAGER_CONFIG//'\'/'\\'} + HOME_MANAGER_CONFIG_NIX=${HOME_MANAGER_CONFIG_NIX//'"'/'\"'} + HOME_MANAGER_CONFIG_NIX=${HOME_MANAGER_CONFIG_NIX//$'\n'/$'\\n'} + HOME_MANAGER_CONFIG_ATTRIBUTE_NIX=${HOME_MANAGER_CONFIG_ATTRIBUTE//'\'/'\\'} + HOME_MANAGER_CONFIG_ATTRIBUTE_NIX=${HOME_MANAGER_CONFIG_ATTRIBUTE_NIX//'"'/'\"'} + HOME_MANAGER_CONFIG_ATTRIBUTE_NIX=${HOME_MANAGER_CONFIG_ATTRIBUTE_NIX//$'\n'/$'\\n'} + local modulesExpr + modulesExpr="let confPath = \"${HOME_MANAGER_CONFIG_NIX}\"; " + modulesExpr+="confAttr = \"${HOME_MANAGER_CONFIG_ATTRIBUTE_NIX}\"; in " + modulesExpr+="(import {" + modulesExpr+=" configuration = if confAttr == \"\" then confPath else (import confPath).\${confAttr};" + modulesExpr+=" pkgs = import {}; check = true; })" + + nixos-option \ + --options_expr "$modulesExpr.options" \ + --config_expr "$modulesExpr.config" \ + "${extraArgs[@]}" \ + "${PASSTHROUGH_OPTS[@]}" +} + +function doInstantiate() { + setFlakeAttribute + if [[ -v FLAKE_CONFIG_URI ]]; then + _i "Can't instantiate a flake configuration" >&2 + exit 1 + fi + setConfigFile + setHomeManagerNixPath + + local extraArgs=() + + for p in "${EXTRA_NIX_PATH[@]}"; do + extraArgs=("${extraArgs[@]}" "-I" "$p") + done + + if [[ -v VERBOSE ]]; then + extraArgs=("${extraArgs[@]}" "--show-trace") + fi + + nix-instantiate \ + "" \ + "${extraArgs[@]}" \ + "${PASSTHROUGH_OPTS[@]}" \ + --argstr confPath "$HOME_MANAGER_CONFIG" \ + --argstr confAttr "$HOME_MANAGER_CONFIG_ATTRIBUTE" +} + +function doBuildAttr() { + setConfigFile + setHomeManagerNixPath + + local extraArgs=("$@") + + for p in "${EXTRA_NIX_PATH[@]}"; do + extraArgs=("${extraArgs[@]}" "-I" "$p") + done + + if [[ -v VERBOSE ]]; then + extraArgs=("${extraArgs[@]}" "--show-trace") + fi + + nix-build \ + "" \ + "${extraArgs[@]}" \ + "${PASSTHROUGH_OPTS[@]}" \ + --argstr confPath "$HOME_MANAGER_CONFIG" \ + --argstr confAttr "$HOME_MANAGER_CONFIG_ATTRIBUTE" +} + +function doBuildFlake() { + local extraArgs=("$@") + + if [[ -v VERBOSE ]]; then + extraArgs=("${extraArgs[@]}" "--verbose") + fi + + nix build \ + "${extraArgs[@]}" \ + "${PASSTHROUGH_OPTS[@]}" +} + +# Presents news to the user. Takes as argument the path to a "news +# info" file as generated by `buildNews`. +function presentNews() { + local infoFile="$1" + + # shellcheck source=/dev/null + . "$infoFile" + + # shellcheck disable=2154 + if [[ $newsNumUnread -eq 0 ]]; then + return + elif [[ "$newsDisplay" == "silent" ]]; then + return + elif [[ "$newsDisplay" == "notify" ]]; then + local cmd msg + cmd="$(basename "$0")" + msg="$(_ip \ + $'There is %d unread and relevant news item.\nRead it by running the command "%s news".' \ + $'There are %d unread and relevant news items.\nRead them by running the command "%s news".' \ + "$newsNumUnread" "$newsNumUnread" "$cmd")" + + # Not actually an error but here stdout is reserved for + # nix-build output. + echo $'\n'"$msg"$'\n' >&2 + + if [[ -v DISPLAY ]] && type -P notify-send > /dev/null; then + notify-send "Home Manager" "$msg" + fi + elif [[ "$newsDisplay" == "show" ]]; then + doShowNews --unread + else + _i 'Unknown "news.display" setting "%s".' "$newsDisplay" >&2 + fi +} + +function doEdit() { + if [[ ! -v EDITOR || -z $EDITOR ]]; then + # shellcheck disable=2016 + _i 'Please set the $EDITOR environment variable' >&2 + return 1 + fi + + setConfigFile + + # Don't quote $EDITOR in order to support values including options, e.g., + # "code --wait". + # + # shellcheck disable=2086 + exec $EDITOR "$HOME_MANAGER_CONFIG" +} + +function doBuild() { + if [[ ! -w . ]]; then + _i 'Cannot run build in read-only directory' >&2 + return 1 + fi + + setWorkDir + + setFlakeAttribute + if [[ -v FLAKE_CONFIG_URI ]]; then + doBuildFlake \ + "$FLAKE_CONFIG_URI.activationPackage" \ + ${DRY_RUN+--dry-run} \ + ${NO_OUT_LINK+--no-link} \ + || return + else + doBuildAttr \ + ${NO_OUT_LINK+--no-out-link} \ + --attr activationPackage \ + || return + + local newsInfo + newsInfo=$(buildNews) + + presentNews "$newsInfo" + fi +} + +function doSwitch() { + setWorkDir + + local generation + + # Build the generation and run the activate script. Note, we + # specify an output link so that it is treated as a GC root. This + # prevents an unfortunately timed GC from removing the generation + # before activation completes. + generation="$WORK_DIR/generation" + + setFlakeAttribute + if [[ -v FLAKE_CONFIG_URI ]]; then + doBuildFlake \ + "$FLAKE_CONFIG_URI.activationPackage" \ + --out-link "$generation" \ + && "$generation/activate" || return + else + doBuildAttr \ + --out-link "$generation" \ + --attr activationPackage \ + && "$generation/activate" || return + + local newsInfo + newsInfo=$(buildNews) + + presentNews "$newsInfo" + fi +} + +function doListGens() { + # Whether to colorize the generations output. + local color="never" + if [[ ! -v NO_COLOR && -t 1 ]]; then + color="always" + fi + + pushd "$NIX_STATE_DIR/profiles/per-user/$USER" > /dev/null + # shellcheck disable=2012 + ls --color=$color -gG --time-style=long-iso --sort time home-manager-*-link \ + | cut -d' ' -f 4- \ + | sed -E 's/home-manager-([[:digit:]]*)-link/: id \1/' + popd > /dev/null +} + +# Removes linked generations. Takes as arguments identifiers of +# generations to remove. +function doRmGenerations() { + setVerboseAndDryRun + + pushd "$NIX_STATE_DIR/profiles/per-user/$USER" > /dev/null + + for generationId in "$@"; do + local linkName="home-manager-$generationId-link" + + if [[ ! -e $linkName ]]; then + _i 'No generation with ID %s' "$generationId" >&2 + elif [[ $linkName == $(readlink home-manager) ]]; then + _i 'Cannot remove the current generation %s' "$generationId" >&2 + else + _i 'Removing generation %s' "$generationId" + $DRY_RUN_CMD rm $VERBOSE_ARG $linkName + fi + done + + popd > /dev/null +} + +function doRmAllGenerations() { + $DRY_RUN_CMD rm $VERBOSE_ARG \ + "$NIX_STATE_DIR/profiles/per-user/$USER/home-manager"* +} + +function doExpireGenerations() { + local profileDir="$NIX_STATE_DIR/profiles/per-user/$USER" + + local generations + generations="$( \ + find "$profileDir" -name 'home-manager-*-link' -not -newermt "$1" \ + | sed 's/^.*-\([0-9]*\)-link$/\1/' \ + )" + + if [[ -n $generations ]]; then + # shellcheck disable=2086 + doRmGenerations $generations + elif [[ -v VERBOSE ]]; then + _i "No generations to expire" + fi +} + +function doListPackages() { + setNixProfileCommands + local outPath + outPath="$($LIST_OUTPATH_CMD | grep -o '/.*home-manager-path$')" + if [[ -n "$outPath" ]] ; then + nix-store -q --references "$outPath" | sed 's/[^-]*-//' + else + _i 'No home-manager packages seem to be installed.' >&2 + fi +} + +function newsReadIdsFile() { + local dataDir="${XDG_DATA_HOME:-$HOME/.local/share}/home-manager" + local path="$dataDir/news-read-ids" + + # If the path doesn't exist then we should create it, otherwise + # Nix will error out when we attempt to use builtins.readFile. + if [[ ! -f "$path" ]]; then + mkdir -p "$dataDir" + touch "$path" + fi + + echo "$path" +} + +# Builds news meta information to be sourced into this script. +# +# Note, we suppress build output to remove unnecessary verbosity. We +# put the output in the work directory to avoid the risk of an +# unfortunately timed GC removing it. +function buildNews() { + local output + output="$WORK_DIR/news-info.sh" + + doBuildAttr \ + --out-link "$output" \ + --no-build-output \ + --quiet \ + --arg check false \ + --argstr newsReadIdsFile "$(newsReadIdsFile)" \ + --attr newsInfo \ + > /dev/null + + echo "$output" +} + +function doShowNews() { + setWorkDir + + local infoFile + infoFile=$(buildNews) || return 1 + + # shellcheck source=/dev/null + . "$infoFile" + + # shellcheck disable=2154 + case $1 in + --all) + ${PAGER:-less} "$newsFileAll" + ;; + --unread) + ${PAGER:-less} "$newsFileUnread" + ;; + *) + _i 'Unknown argument %s' "$1" + return 1 + esac + + # shellcheck disable=2154 + if [[ -s "$newsUnreadIdsFile" ]]; then + local newsReadIdsFile + newsReadIdsFile="$(newsReadIdsFile)" + cat "$newsUnreadIdsFile" >> "$newsReadIdsFile" + fi +} + +function doUninstall() { + setVerboseAndDryRun + setNixProfileCommands + + _i 'This will remove Home Manager from your system.' + + if [[ -v DRY_RUN ]]; then + _i 'This is a dry run, nothing will actually be uninstalled.' + fi + + local confirmation + read -r -n 1 -p "$(_i 'Really uninstall Home Manager?') [y/n] " confirmation + echo + + case $confirmation in + y|Y) + _i "Switching to empty Home Manager configuration..." + HOME_MANAGER_CONFIG="$(mktemp --tmpdir home-manager.XXXXXXXXXX)" + echo "{ lib, ... }: { home.file = lib.mkForce {}; }" > "$HOME_MANAGER_CONFIG" + doSwitch + $DRY_RUN_CMD $REMOVE_CMD home-manager-path || true + rm "$HOME_MANAGER_CONFIG" + $DRY_RUN_CMD rm $VERBOSE_ARG -r \ + "${XDG_DATA_HOME:-$HOME/.local/share}/home-manager" + $DRY_RUN_CMD rm $VERBOSE_ARG \ + "$NIX_STATE_DIR/gcroots/per-user/$USER/current-home" + ;; + *) + _i "Yay!" + exit 0 + ;; + esac + + local deleteProfiles + read -r -n 1 \ + -p "$(_i 'Remove all Home Manager generations?') [y/n] " \ + deleteProfiles + echo + + case $deleteProfiles in + y|Y) + doRmAllGenerations + _i 'All generations are now eligible for garbage collection.' + ;; + *) + _i 'Leaving generations but they may still be garbage collected.' + ;; + esac + + _i "Home Manager is uninstalled but your home.nix is left untouched." +} + +function doHelp() { + echo "Usage: $0 [OPTION] COMMAND" + echo + echo "Options" + echo + echo " -f FILE The home configuration file." + echo " Default is '~/.config/nixpkgs/home.nix'." + echo " -A ATTRIBUTE Optional attribute that selects a configuration" + echo " expression in the configuration file." + echo " -I PATH Add a path to the Nix expression search path." + echo " --flake flake-uri Use Home Manager configuration at flake-uri" + echo " -b EXT Move existing files to new path rather than fail." + echo " -v Verbose output" + echo " -n Do a dry run, only prints what actions would be taken" + echo " -h Print this help" + echo " --version Print the Home Manager version" + echo + echo "Options passed on to nix-build(1)" + echo + echo " --arg(str) NAME VALUE Override inputs passed to home-manager.nix" + echo " --cores NUM" + echo " --debug" + echo " --impure" + echo " --keep-failed" + echo " --keep-going" + echo " -j, --max-jobs NUM" + echo " --option NAME VALUE" + echo " --show-trace" + echo " --(no-)substitute" + echo " --no-out-link Do not create a symlink to the output path" + echo " --no-write-lock-file" + echo " --builders VALUE" + echo + echo "Commands" + echo + echo " help Print this help" + echo + echo " edit Open the home configuration in \$EDITOR" + echo + echo " option OPTION.NAME" + echo " Inspect configuration option named OPTION.NAME." + echo + echo " build Build configuration into result directory" + echo + echo " instantiate Instantiate the configuration and print the resulting derivation" + echo + echo " switch Build and activate configuration" + echo + echo " generations List all home environment generations" + echo + echo " remove-generations ID..." + echo " Remove indicated generations. Use 'generations' command to" + echo " find suitable generation numbers." + echo + echo " expire-generations TIMESTAMP" + echo " Remove generations older than TIMESTAMP where TIMESTAMP is" + echo " interpreted as in the -d argument of the date tool. For" + echo " example \"-30 days\" or \"2018-01-01\"." + echo + echo " packages List all packages installed in home-manager-path" + echo + echo " news Show news entries in a pager" + echo + echo " uninstall Remove Home Manager" +} + +readonly NIX_STATE_DIR="${NIX_STATE_DIR:-/nix/var/nix}" + +EXTRA_NIX_PATH=() +HOME_MANAGER_CONFIG_ATTRIBUTE="" +PASSTHROUGH_OPTS=() +COMMAND="" +COMMAND_ARGS=() +FLAKE_ARG="" + +while [[ $# -gt 0 ]]; do + opt="$1" + shift + case $opt in + build|instantiate|option|edit|expire-generations|generations|help|news|packages|remove-generations|switch|uninstall) + COMMAND="$opt" + ;; + -A) + HOME_MANAGER_CONFIG_ATTRIBUTE="$1" + shift + ;; + -I) + EXTRA_NIX_PATH+=("$1") + shift + ;; + -b) + export HOME_MANAGER_BACKUP_EXT="$1" + shift + ;; + -f|--file) + HOME_MANAGER_CONFIG="$1" + shift + ;; + --flake) + FLAKE_ARG="$1" + shift + ;; + --recreate-lock-file|--no-update-lock-file|--no-write-lock-file|--no-registries|--commit-lock-file) + PASSTHROUGH_OPTS+=("$opt") + ;; + --update-input) + PASSTHROUGH_OPTS+=("$opt" "$1") + shift + ;; + --override-input) + PASSTHROUGH_OPTS+=("$opt" "$1" "$2") + shift 2 + ;; + --experimental-features) + PASSTHROUGH_OPTS+=("$opt" "$1") + shift + ;; + --extra-experimental-features) + PASSTHROUGH_OPTS+=("$opt" "$1") + shift + ;; + --no-out-link) + NO_OUT_LINK=1 + ;; + -h|--help) + doHelp + exit 0 + ;; + -n|--dry-run) + export DRY_RUN=1 + ;; + --option|--arg|--argstr) + PASSTHROUGH_OPTS+=("$opt" "$1" "$2") + shift 2 + ;; + -j|--max-jobs|--cores|--builders) + PASSTHROUGH_OPTS+=("$opt" "$1") + shift + ;; + --debug|--keep-failed|--keep-going|--show-trace\ + |--substitute|--no-substitute|--impure) + PASSTHROUGH_OPTS+=("$opt") + ;; + -v|--verbose) + export VERBOSE=1 + ;; + --version) + echo 22.05 + exit 0 + ;; + *) + case $COMMAND in + expire-generations|remove-generations|option) + COMMAND_ARGS+=("$opt") + ;; + *) + _iError "%s: unknown option '%s'" "$0" "$opt" >&2 + _i "Run '%s --help' for usage help" "$0" >&2 + exit 1 + ;; + esac + ;; + esac +done + +if [[ -z $COMMAND ]]; then + doHelp >&2 + exit 1 +fi + +case $COMMAND in + edit) + doEdit + ;; + build) + doBuild + ;; + instantiate) + doInstantiate + ;; + switch) + doSwitch + ;; + generations) + doListGens + ;; + remove-generations) + doRmGenerations "${COMMAND_ARGS[@]}" + ;; + expire-generations) + if [[ ${#COMMAND_ARGS[@]} != 1 ]]; then + _i 'expire-generations expects one argument, got %d.' "${#COMMAND_ARGS[@]}" >&2 + exit 1 + else + doExpireGenerations "${COMMAND_ARGS[@]}" + fi + ;; + option) + doInspectOption "${COMMAND_ARGS[@]}" + ;; + packages) + doListPackages + ;; + news) + doShowNews --all + ;; + uninstall) + doUninstall + ;; + help) + doHelp + ;; + *) + _iError 'Unknown command: %s' "$COMMAND" >&2 + doHelp >&2 + exit 1 + ;; +esac + +# vim: ft=bash diff --git a/infra/libkookie/home-manager-stable/home-manager/home-manager.nix b/infra/libkookie/home-manager-stable/home-manager/home-manager.nix new file mode 100644 index 00000000000..a113d1d820d --- /dev/null +++ b/infra/libkookie/home-manager-stable/home-manager/home-manager.nix @@ -0,0 +1,89 @@ +{ pkgs ? import {} +, confPath +, confAttr ? null +, check ? true +, newsReadIdsFile ? null +}: + +let + inherit (pkgs.lib) + concatMapStringsSep fileContents filter length optionalString removeSuffix + replaceStrings splitString; + + env = import ../modules { + configuration = + if confAttr == "" || confAttr == null + then confPath + else (import confPath).${confAttr}; + pkgs = pkgs; + check = check; + }; + + newsReadIds = + if newsReadIdsFile == null + then {} + else + let + ids = splitString "\n" (fileContents newsReadIdsFile); + in + builtins.listToAttrs (map (id: { name = id; value = null; }) ids); + + newsIsRead = entry: builtins.hasAttr entry.id newsReadIds; + + newsFiltered = + let + pred = entry: entry.condition && ! newsIsRead entry; + in + filter pred env.newsEntries; + + newsNumUnread = length newsFiltered; + + newsFileUnread = pkgs.writeText "news-unread.txt" ( + concatMapStringsSep "\n\n" (entry: + let + time = replaceStrings ["T"] [" "] (removeSuffix "+00:00" entry.time); + in + '' + * ${time} + + ${replaceStrings ["\n"] ["\n "] entry.message} + '' + ) newsFiltered + ); + + newsFileAll = pkgs.writeText "news-all.txt" ( + concatMapStringsSep "\n\n" (entry: + let + flag = if newsIsRead entry then "read" else "unread"; + time = replaceStrings ["T"] [" "] (removeSuffix "+00:00" entry.time); + in + '' + * ${time} [${flag}] + + ${replaceStrings ["\n"] ["\n "] entry.message} + '' + ) env.newsEntries + ); + + # File where each line corresponds to an unread news entry + # identifier. If non-empty then the file ends in "\n". + newsUnreadIdsFile = pkgs.writeText "news-unread-ids" ( + let + text = concatMapStringsSep "\n" (entry: entry.id) newsFiltered; + in + text + optionalString (text != "") "\n" + ); + + newsInfo = pkgs.writeText "news-info.sh" '' + local newsNumUnread=${toString newsNumUnread} + local newsDisplay="${env.newsDisplay}" + local newsFileAll="${newsFileAll}" + local newsFileUnread="${newsFileUnread}" + local newsUnreadIdsFile="${newsUnreadIdsFile}" + ''; + +in + { + inherit (env) activationPackage; + inherit newsInfo; + } diff --git a/infra/libkookie/home-manager-stable/home-manager/install.nix b/infra/libkookie/home-manager-stable/home-manager/install.nix new file mode 100644 index 00000000000..f69508a8504 --- /dev/null +++ b/infra/libkookie/home-manager-stable/home-manager/install.nix @@ -0,0 +1,85 @@ +{ home-manager, gettext, runCommand, ncurses }: + +let + + hmBashLibInit = '' + export TEXTDOMAIN=home-manager + export TEXTDOMAINDIR=${home-manager}/share/locale + source ${home-manager}/share/bash/home-manager.sh + ''; + +in runCommand "home-manager-install" { + propagatedBuildInputs = [ home-manager gettext ncurses ]; + preferLocalBuild = true; + shellHookOnly = true; + shellHook = '' + ${hmBashLibInit} + + confFile="''${XDG_CONFIG_HOME:-$HOME/.config}/nixpkgs/home.nix" + + if [[ ! -e $confFile ]]; then + echo + _i "Creating initial Home Manager configuration..." + + nl=$'\n' + xdgVars="" + if [[ -v XDG_CACHE_HOME && $XDG_CACHE_HOME != "$HOME/.cache" ]]; then + xdgVars="$xdgVars xdg.cacheHome = \"$XDG_CACHE_HOME\";$nl" + fi + if [[ -v XDG_CONFIG_HOME && $XDG_CONFIG_HOME != "$HOME/.config" ]]; then + xdgVars="$xdgVars xdg.configHome = \"$XDG_CONFIG_HOME\";$nl" + fi + if [[ -v XDG_DATA_HOME && $XDG_DATA_HOME != "$HOME/.local/share" ]]; then + xdgVars="$xdgVars xdg.dataHome = \"$XDG_DATA_HOME\";$nl" + fi + if [[ -v XDG_STATE_HOME && $XDG_STATE_HOME != "$HOME/.local/state" ]]; then + xdgVars="$xdgVars xdg.stateHome = \"$XDG_STATE_HOME\";$nl" + fi + + mkdir -p "$(dirname "$confFile")" + cat > $confFile <, YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: Home Manager\n" +"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" +"POT-Creation-Date: 2022-03-26 15:08+0100\n" +"PO-Revision-Date: 2022-03-23 18:56+0000\n" +"Last-Translator: Manu [tennox] \n" +"Language-Team: German \n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.12-dev\n" + +#: home-manager/home-manager:60 +msgid "No configuration file found at %s" +msgstr "Keine Konfigurationsdatei unter %s gefunden" + +#: home-manager/home-manager:79 +msgid "No configuration file found. Please create one at %s" +msgstr "Keine Konfigurationsdatei gefunden. Bitte erstellen Sie eine unter %s" + +#: home-manager/home-manager:122 +msgid "Can't inspect options of a flake configuration" +msgstr "" +"Die Optionen einer Flake-Konfigurationen können nicht inspizieren werden" + +#: home-manager/home-manager:162 +msgid "Can't instantiate a flake configuration" +msgstr "Kann eine Flake-Konfiguration nicht instanziieren" + +#: home-manager/home-manager:237 +msgid "" +"There is %d unread and relevant news item.\n" +"Read it by running the command \"%s news\"." +msgid_plural "" +"There are %d unread and relevant news items.\n" +"Read them by running the command \"%s news\"." +msgstr[0] "" +"Es gibt eine ungelesene und relevante Nachricht.\n" +"Lesen Sie sie, indem Sie den Befehl \"%s news\" ausführen." +msgstr[1] "" +"Es gibt %d ungelesene und relevante Nachrichten.\n" +"Lesen Sie sie, indem Sie den Befehl \"%s news\" ausführen." + +#: home-manager/home-manager:251 +msgid "Unknown \"news.display\" setting \"%s\"." +msgstr "Unbekannte \"news.display\" Einstellung \"%s\"." + +#: home-manager/home-manager:258 +#, sh-format +msgid "Please set the $EDITOR environment variable" +msgstr "Bitte legen Sie die $EDITOR Variable fest" + +#: home-manager/home-manager:273 +msgid "Cannot run build in read-only directory" +msgstr "Build kann nicht im schreibgeschützten Ordner ausgeführt werden" + +#: home-manager/home-manager:355 +msgid "No generation with ID %s" +msgstr "Keine Generation mit ID %s" + +#: home-manager/home-manager:357 +msgid "Cannot remove the current generation %s" +msgstr "Die jetzige Generation %s kann nicht entfernt werden" + +#: home-manager/home-manager:359 +msgid "Removing generation %s" +msgstr "Entferne Generation %s" + +#: home-manager/home-manager:385 +msgid "No generations to expire" +msgstr "Keine ablaufenden Generationen" + +#: home-manager/home-manager:396 +msgid "No home-manager packages seem to be installed." +msgstr "Es scheint, als ob keine Home Manager Pakete installiert sind." + +#: home-manager/home-manager:453 +msgid "Unknown argument %s" +msgstr "Unbekannte Argumente %s" + +#: home-manager/home-manager:469 +msgid "This will remove Home Manager from your system." +msgstr "Dies wird Home Manager von Ihrem System entfernen." + +#: home-manager/home-manager:472 +msgid "This is a dry run, nothing will actually be uninstalled." +msgstr "Dies ist ein Probelauf, es wird nichts vom System deinstalliert." + +#: home-manager/home-manager:476 +msgid "Really uninstall Home Manager?" +msgstr "Möchten Sie wirklich Home Manager deinstallieren?" + +#: home-manager/home-manager:481 +msgid "Switching to empty Home Manager configuration..." +msgstr "Wechsle zu einer leeren Home Manager Konfiguration..." + +#: home-manager/home-manager:493 +msgid "Yay!" +msgstr "Juhu!" + +#: home-manager/home-manager:500 +msgid "Remove all Home Manager generations?" +msgstr "Entferne alle Home Manager Generationen?" + +#: home-manager/home-manager:507 +msgid "All generations are now eligible for garbage collection." +msgstr "Alle Generationen kommen nun für die Garbage Collection in Frage." + +#: home-manager/home-manager:510 +msgid "Leaving generations but they may still be garbage collected." +msgstr "" +"Ignoriere Generationen, aber diese könnten immer noch mittels des Garbage " +"Collectors aufgeräumt werden." + +#: home-manager/home-manager:514 +msgid "Home Manager is uninstalled but your home.nix is left untouched." +msgstr "" +"Home Manager ist installiert, aber Ihre home.nix Datei bleibt unberührt." + +#: home-manager/home-manager:673 +msgid "%s: unknown option '%s'" +msgstr "%s: unbekannte Option '%s'" + +#: home-manager/home-manager:674 +msgid "Run '%s --help' for usage help" +msgstr "Führe '%s --help' aus, um Hilfe zur Verwendung zu erhalten" + +#: home-manager/home-manager:708 +msgid "expire-generations expects one argument, got %d." +msgstr "expire-generations erwartet ein Argument, hat aber %d erhalten." + +#: home-manager/home-manager:730 +msgid "Unknown command: %s" +msgstr "Unbekannter Befehl: %s" + +#: home-manager/install.nix:22 +msgid "Creating initial Home Manager configuration..." +msgstr "Erstelle initiale Home Manager Konfiguration..." + +#: home-manager/install.nix:66 +msgid "Creating initial Home Manager generation..." +msgstr "Erstelle initiale Home Manager Generation..." + +#. translators: The "%s" specifier will be replaced by a file path. +#: home-manager/install.nix:71 +msgid "" +"All done! The home-manager tool should now be installed and you can edit\n" +"\n" +" %s\n" +"\n" +"to configure Home Manager. Run 'man home-configuration.nix' to\n" +"see all available options." +msgstr "" +"Alles fertig! Das Home Manager Tool sollte nun installiert sein. Sie können\n" +"\n" +" %s\n" +"\n" +"bearbeiten um Home Manager zu konfigurieren. Führen Sie\n" +"'man home-configuration.nix' aus, um alle verfügbaren Optionen zu\n" +"sehen." + +#. translators: The "%s" specifier will be replaced by a URL. +#: home-manager/install.nix:76 +msgid "" +"Uh oh, the installation failed! Please create an issue at\n" +"\n" +" %s\n" +"\n" +"if the error seems to be the fault of Home Manager." +msgstr "" +"Ups, die Installation schlug fehl. Bitte erstellen Sie ein Issue unter\n" +"\n" +" %s\n" +"\n" +"falls der Fehler auf Home Manager zurückzuführen ist." + +#: home-manager/install.nix:83 +msgid "This derivation is not buildable, please run it using nix-shell." +msgstr "" +"Diese Derivation ist nicht kompilierbar. Bitte führen Sie nix-shell aus." diff --git a/infra/libkookie/home-manager-stable/home-manager/po/es.po b/infra/libkookie/home-manager-stable/home-manager/po/es.po new file mode 100644 index 00000000000..95f2fea382d --- /dev/null +++ b/infra/libkookie/home-manager-stable/home-manager/po/es.po @@ -0,0 +1,185 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Home Manager contributors +# This file is distributed under the same license as the Home Manager package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: Home Manager\n" +"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" +"POT-Creation-Date: 2022-03-26 15:08+0100\n" +"PO-Revision-Date: 2022-01-11 21:45+0000\n" +"Last-Translator: Robert Helgesson \n" +"Language-Team: Spanish \n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.10.1\n" + +#: home-manager/home-manager:60 +msgid "No configuration file found at %s" +msgstr "Archivo de configuración no encontrado en %s" + +#: home-manager/home-manager:79 +msgid "No configuration file found. Please create one at %s" +msgstr "Archivo de configuración no encontrado. Por favor cree uno en %s" + +#: home-manager/home-manager:122 +msgid "Can't inspect options of a flake configuration" +msgstr "No se pudo inspeccionar las opciones de la configuración flake" + +#: home-manager/home-manager:162 +msgid "Can't instantiate a flake configuration" +msgstr "No se pudo instanciar una configuración flake" + +#: home-manager/home-manager:237 +msgid "" +"There is %d unread and relevant news item.\n" +"Read it by running the command \"%s news\"." +msgid_plural "" +"There are %d unread and relevant news items.\n" +"Read them by running the command \"%s news\"." +msgstr[0] "" +"Hay %d noticia relevante no leída.\n" +"Léala ejecutando el comando \"%s news\"." +msgstr[1] "" +"Hay %d noticias relevantes no leídas.\n" +"Léalas ejecutando el comando \"%s news\"." + +#: home-manager/home-manager:251 +msgid "Unknown \"news.display\" setting \"%s\"." +msgstr "Configuración \"news.display\" no reconocida \"%s\"." + +#: home-manager/home-manager:258 +#, sh-format +msgid "Please set the $EDITOR environment variable" +msgstr "Defina la variable de ambiente $EDITOR" + +#: home-manager/home-manager:273 +msgid "Cannot run build in read-only directory" +msgstr "No se puede ejecutar en un directorio de sólo lectura" + +#: home-manager/home-manager:355 +msgid "No generation with ID %s" +msgstr "No existe la generación con ID %s" + +#: home-manager/home-manager:357 +msgid "Cannot remove the current generation %s" +msgstr "No se pudo borrar la generación actual %s" + +#: home-manager/home-manager:359 +msgid "Removing generation %s" +msgstr "Borrando generación %s" + +#: home-manager/home-manager:385 +msgid "No generations to expire" +msgstr "No se encontraron generaciones para expirar" + +#: home-manager/home-manager:396 +msgid "No home-manager packages seem to be installed." +msgstr "No se encontró ningún paquete home-manager instalado." + +#: home-manager/home-manager:453 +msgid "Unknown argument %s" +msgstr "Argumento desconocido %s" + +#: home-manager/home-manager:469 +msgid "This will remove Home Manager from your system." +msgstr "Home Manager será borrado del sistema." + +#: home-manager/home-manager:472 +msgid "This is a dry run, nothing will actually be uninstalled." +msgstr "Este es un simulacro, nada será realmente desinstalado." + +#: home-manager/home-manager:476 +msgid "Really uninstall Home Manager?" +msgstr "Desinstalar Home Manager?" + +#: home-manager/home-manager:481 +msgid "Switching to empty Home Manager configuration..." +msgstr "Cambiando a configuración vacía de Home Manager..." + +#: home-manager/home-manager:493 +msgid "Yay!" +msgstr "Bien!" + +#: home-manager/home-manager:500 +msgid "Remove all Home Manager generations?" +msgstr "Borrar todas las generaciones de Home Manager?" + +#: home-manager/home-manager:507 +msgid "All generations are now eligible for garbage collection." +msgstr "Ahora todas las generaciones son aptas para recolección de basura." + +#: home-manager/home-manager:510 +msgid "Leaving generations but they may still be garbage collected." +msgstr "" +"Dejando generaciones aunque podrían aún ser borradas por el recolector de " +"basura." + +#: home-manager/home-manager:514 +msgid "Home Manager is uninstalled but your home.nix is left untouched." +msgstr "Home Manager desinstalado pero no se ha modificado home.nix." + +#: home-manager/home-manager:673 +msgid "%s: unknown option '%s'" +msgstr "%s: opción desconocida '%s'" + +#: home-manager/home-manager:674 +msgid "Run '%s --help' for usage help" +msgstr "Ejecute '%s --help' para ver ayuda" + +#: home-manager/home-manager:708 +msgid "expire-generations expects one argument, got %d." +msgstr "expire-generations espera un argumento pero se dieron %d." + +#: home-manager/home-manager:730 +msgid "Unknown command: %s" +msgstr "Comando desconocido %s" + +#: home-manager/install.nix:22 +msgid "Creating initial Home Manager configuration..." +msgstr "Creando configuración inicial de Home Manager..." + +#: home-manager/install.nix:66 +msgid "Creating initial Home Manager generation..." +msgstr "Creando generación inicial de Home Manager..." + +#. translators: The "%s" specifier will be replaced by a file path. +#: home-manager/install.nix:71 +msgid "" +"All done! The home-manager tool should now be installed and you can edit\n" +"\n" +" %s\n" +"\n" +"to configure Home Manager. Run 'man home-configuration.nix' to\n" +"see all available options." +msgstr "" +"Listo! home-manager ha sido instalado y ahora puede editar\n" +"\n" +" %s\n" +"\n" +"para configurar Home Manager. Ejecute 'man home-configuration.nix' para\n" +"ver todas las opciones disponibles." + +#. translators: The "%s" specifier will be replaced by a URL. +#: home-manager/install.nix:76 +msgid "" +"Uh oh, the installation failed! Please create an issue at\n" +"\n" +" %s\n" +"\n" +"if the error seems to be the fault of Home Manager." +msgstr "" +"La instalación ha fallado. Por favor notifíquelo en\n" +"\n" +" %s\n" +"\n" +"si el error parecer ser culpa de Home Manager." + +#: home-manager/install.nix:83 +msgid "This derivation is not buildable, please run it using nix-shell." +msgstr "Esta derivación no se puede construir, ejecute con nix-shell." diff --git a/infra/libkookie/home-manager-stable/home-manager/po/fa.po b/infra/libkookie/home-manager-stable/home-manager/po/fa.po new file mode 100644 index 00000000000..d7791d649af --- /dev/null +++ b/infra/libkookie/home-manager-stable/home-manager/po/fa.po @@ -0,0 +1,169 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Home Manager contributors +# This file is distributed under the same license as the Home Manager package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: Home Manager\n" +"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" +"POT-Creation-Date: 2022-03-26 15:08+0100\n" +"PO-Revision-Date: 2022-04-09 18:11+0000\n" +"Last-Translator: Artin Mobasher \n" +"Language-Team: Persian \n" +"Language: fa\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 4.12-dev\n" + +#: home-manager/home-manager:60 +msgid "No configuration file found at %s" +msgstr "هیچ فایل تنظیماتی در %s پیدا نشد" + +#: home-manager/home-manager:79 +msgid "No configuration file found. Please create one at %s" +msgstr "هیچ فایل تنظیماتی پیدا نشد. لطفا یک فایل در %s بسازید" + +#: home-manager/home-manager:122 +msgid "Can't inspect options of a flake configuration" +msgstr "" + +#: home-manager/home-manager:162 +msgid "Can't instantiate a flake configuration" +msgstr "" + +#: home-manager/home-manager:237 +msgid "" +"There is %d unread and relevant news item.\n" +"Read it by running the command \"%s news\"." +msgid_plural "" +"There are %d unread and relevant news items.\n" +"Read them by running the command \"%s news\"." +msgstr[0] "" +msgstr[1] "" + +#: home-manager/home-manager:251 +msgid "Unknown \"news.display\" setting \"%s\"." +msgstr "" + +#: home-manager/home-manager:258 +#, sh-format +msgid "Please set the $EDITOR environment variable" +msgstr "" + +#: home-manager/home-manager:273 +msgid "Cannot run build in read-only directory" +msgstr "" + +#: home-manager/home-manager:355 +msgid "No generation with ID %s" +msgstr "" + +#: home-manager/home-manager:357 +msgid "Cannot remove the current generation %s" +msgstr "" + +#: home-manager/home-manager:359 +msgid "Removing generation %s" +msgstr "" + +#: home-manager/home-manager:385 +msgid "No generations to expire" +msgstr "" + +#: home-manager/home-manager:396 +msgid "No home-manager packages seem to be installed." +msgstr "" + +#: home-manager/home-manager:453 +msgid "Unknown argument %s" +msgstr "" + +#: home-manager/home-manager:469 +msgid "This will remove Home Manager from your system." +msgstr "" + +#: home-manager/home-manager:472 +msgid "This is a dry run, nothing will actually be uninstalled." +msgstr "" + +#: home-manager/home-manager:476 +msgid "Really uninstall Home Manager?" +msgstr "" + +#: home-manager/home-manager:481 +msgid "Switching to empty Home Manager configuration..." +msgstr "" + +#: home-manager/home-manager:493 +#, fuzzy +msgid "Yay!" +msgstr "آره!" + +#: home-manager/home-manager:500 +msgid "Remove all Home Manager generations?" +msgstr "" + +#: home-manager/home-manager:507 +msgid "All generations are now eligible for garbage collection." +msgstr "" + +#: home-manager/home-manager:510 +msgid "Leaving generations but they may still be garbage collected." +msgstr "" + +#: home-manager/home-manager:514 +msgid "Home Manager is uninstalled but your home.nix is left untouched." +msgstr "" + +#: home-manager/home-manager:673 +msgid "%s: unknown option '%s'" +msgstr "" + +#: home-manager/home-manager:674 +msgid "Run '%s --help' for usage help" +msgstr "" + +#: home-manager/home-manager:708 +msgid "expire-generations expects one argument, got %d." +msgstr "" + +#: home-manager/home-manager:730 +msgid "Unknown command: %s" +msgstr "دستور ناشناخته: %s" + +#: home-manager/install.nix:22 +msgid "Creating initial Home Manager configuration..." +msgstr "ایجاد تنظیمات اولیه Home-Manager..." + +#: home-manager/install.nix:66 +msgid "Creating initial Home Manager generation..." +msgstr "" + +#. translators: The "%s" specifier will be replaced by a file path. +#: home-manager/install.nix:71 +msgid "" +"All done! The home-manager tool should now be installed and you can edit\n" +"\n" +" %s\n" +"\n" +"to configure Home Manager. Run 'man home-configuration.nix' to\n" +"see all available options." +msgstr "" + +#. translators: The "%s" specifier will be replaced by a URL. +#: home-manager/install.nix:76 +msgid "" +"Uh oh, the installation failed! Please create an issue at\n" +"\n" +" %s\n" +"\n" +"if the error seems to be the fault of Home Manager." +msgstr "" + +#: home-manager/install.nix:83 +msgid "This derivation is not buildable, please run it using nix-shell." +msgstr "" diff --git a/infra/libkookie/home-manager-stable/home-manager/po/fr.po b/infra/libkookie/home-manager-stable/home-manager/po/fr.po new file mode 100644 index 00000000000..5a129e9d24f --- /dev/null +++ b/infra/libkookie/home-manager-stable/home-manager/po/fr.po @@ -0,0 +1,191 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Home Manager contributors +# This file is distributed under the same license as the Home Manager package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: Home Manager\n" +"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" +"POT-Creation-Date: 2022-03-26 15:08+0100\n" +"PO-Revision-Date: 2021-12-19 16:51+0000\n" +"Last-Translator: TheBlackBeans \n" +"Language-Team: French \n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 4.10\n" + +#: home-manager/home-manager:60 +msgid "No configuration file found at %s" +msgstr "Aucun fichier de configuration trouvé à l'emplacement %s" + +#: home-manager/home-manager:79 +msgid "No configuration file found. Please create one at %s" +msgstr "" +"Aucun fichier de configuration trouvé. Veuillez en créer un à l'emplacement " +"%s" + +#: home-manager/home-manager:122 +msgid "Can't inspect options of a flake configuration" +msgstr "Impossible d'inspecter les options d'une configuration en flocons" + +#: home-manager/home-manager:162 +msgid "Can't instantiate a flake configuration" +msgstr "Impossible d'instancier une configuration flake" + +#: home-manager/home-manager:237 +msgid "" +"There is %d unread and relevant news item.\n" +"Read it by running the command \"%s news\"." +msgid_plural "" +"There are %d unread and relevant news items.\n" +"Read them by running the command \"%s news\"." +msgstr[0] "" +"Il y a %d nouvel élément non lu et pertinent.\n" +"Vous pouvez le lire en exécutant la commande \"%s news\"." +msgstr[1] "" +"Il y a %d nouveaux éléments non lus et pertinents.\n" +"Vous pouvez les lire en exécutant la commande \"%s news\"." + +#: home-manager/home-manager:251 +msgid "Unknown \"news.display\" setting \"%s\"." +msgstr "Configuration \"news.display\" iconnue \"%s\"." + +#: home-manager/home-manager:258 +#, sh-format +msgid "Please set the $EDITOR environment variable" +msgstr "Veuillez définir la variable d'environnement $EDITOR" + +#: home-manager/home-manager:273 +msgid "Cannot run build in read-only directory" +msgstr "Impossible de lancer une compilation dans un dossier en écriture seule" + +#: home-manager/home-manager:355 +msgid "No generation with ID %s" +msgstr "Aucune génération avec l'identifiant %s" + +#: home-manager/home-manager:357 +msgid "Cannot remove the current generation %s" +msgstr "Impossible de supprimer la génération courante %s" + +#: home-manager/home-manager:359 +msgid "Removing generation %s" +msgstr "Suppression de la génération %s" + +#: home-manager/home-manager:385 +msgid "No generations to expire" +msgstr "Aucune génération expirée" + +#: home-manager/home-manager:396 +msgid "No home-manager packages seem to be installed." +msgstr "Aucun paquet home-manager ne semble être installé." + +#: home-manager/home-manager:453 +msgid "Unknown argument %s" +msgstr "Aucun argument %s" + +#: home-manager/home-manager:469 +msgid "This will remove Home Manager from your system." +msgstr "Cela va supprimer Home Manager de votre système." + +#: home-manager/home-manager:472 +msgid "This is a dry run, nothing will actually be uninstalled." +msgstr "C'est un essai, rien ne sera réellement désinstallé." + +#: home-manager/home-manager:476 +msgid "Really uninstall Home Manager?" +msgstr "Voulez-vous vraiment désinstaller Home Manager ?" + +#: home-manager/home-manager:481 +msgid "Switching to empty Home Manager configuration..." +msgstr "Changement vers une configuration vierge de Home Manager..." + +#: home-manager/home-manager:493 +msgid "Yay!" +msgstr "Yay !" + +#: home-manager/home-manager:500 +msgid "Remove all Home Manager generations?" +msgstr "Supprimer toutes les générations de Home Manager ?" + +#: home-manager/home-manager:507 +msgid "All generations are now eligible for garbage collection." +msgstr "" +"Toutes les générations sont maintenant éligibles pour la collecte des " +"ordures." + +#: home-manager/home-manager:510 +msgid "Leaving generations but they may still be garbage collected." +msgstr "" +"Les générations sortantes mais elles peuvent encore être collectées par les " +"ordures." + +#: home-manager/home-manager:514 +msgid "Home Manager is uninstalled but your home.nix is left untouched." +msgstr "Home Manager est désinstallé mais votre home.nix reste intact." + +#: home-manager/home-manager:673 +msgid "%s: unknown option '%s'" +msgstr "%s : option inconnue « %s »" + +#: home-manager/home-manager:674 +msgid "Run '%s --help' for usage help" +msgstr "Exécuter « %s --help » pour de l'aide sur l'utilisation" + +#: home-manager/home-manager:708 +msgid "expire-generations expects one argument, got %d." +msgstr "expire-generations attend un argument, a obtenu %d." + +#: home-manager/home-manager:730 +msgid "Unknown command: %s" +msgstr "Commande inconnue : %s" + +#: home-manager/install.nix:22 +msgid "Creating initial Home Manager configuration..." +msgstr "Création de la configuration initiale de Home Manager..." + +#: home-manager/install.nix:66 +msgid "Creating initial Home Manager generation..." +msgstr "Création de la génération initiale de Home Manager..." + +#. translators: The "%s" specifier will be replaced by a file path. +#: home-manager/install.nix:71 +msgid "" +"All done! The home-manager tool should now be installed and you can edit\n" +"\n" +" %s\n" +"\n" +"to configure Home Manager. Run 'man home-configuration.nix' to\n" +"see all available options." +msgstr "" +"Tout est fait! Home Manager devrait désormais être installé et vous pouvez " +"éditer\n" +"\n" +" %s\n" +"\n" +"pour configurer Home Manager. Pour avoir une liste des options disponibles,\n" +"essayez 'man home-configuration.nix'." + +#. translators: The "%s" specifier will be replaced by a URL. +#: home-manager/install.nix:76 +msgid "" +"Uh oh, the installation failed! Please create an issue at\n" +"\n" +" %s\n" +"\n" +"if the error seems to be the fault of Home Manager." +msgstr "" +"Uh oh, l'installation n'a pas réussi! Veuillez signaler cette erreur à " +"l'adresse suivante\n" +"\n" +" %s\n" +"\n" +"si l'erreur semble être liée à Home Manager." + +#: home-manager/install.nix:83 +msgid "This derivation is not buildable, please run it using nix-shell." +msgstr "Cette dérivation ne peut être construite, essayez avec nix-shell." diff --git a/infra/libkookie/home-manager-stable/home-manager/po/home-manager.pot b/infra/libkookie/home-manager-stable/home-manager/po/home-manager.pot new file mode 100644 index 00000000000..003a344b0e9 --- /dev/null +++ b/infra/libkookie/home-manager-stable/home-manager/po/home-manager.pot @@ -0,0 +1,167 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Home Manager contributors +# This file is distributed under the same license as the Home Manager package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: Home Manager\n" +"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" +"POT-Creation-Date: 2022-03-26 15:08+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" + +#: home-manager/home-manager:60 +msgid "No configuration file found at %s" +msgstr "" + +#: home-manager/home-manager:79 +msgid "No configuration file found. Please create one at %s" +msgstr "" + +#: home-manager/home-manager:122 +msgid "Can't inspect options of a flake configuration" +msgstr "" + +#: home-manager/home-manager:162 +msgid "Can't instantiate a flake configuration" +msgstr "" + +#: home-manager/home-manager:237 +msgid "" +"There is %d unread and relevant news item.\n" +"Read it by running the command \"%s news\"." +msgid_plural "" +"There are %d unread and relevant news items.\n" +"Read them by running the command \"%s news\"." +msgstr[0] "" +msgstr[1] "" + +#: home-manager/home-manager:251 +msgid "Unknown \"news.display\" setting \"%s\"." +msgstr "" + +#: home-manager/home-manager:258 +#, sh-format +msgid "Please set the $EDITOR environment variable" +msgstr "" + +#: home-manager/home-manager:273 +msgid "Cannot run build in read-only directory" +msgstr "" + +#: home-manager/home-manager:355 +msgid "No generation with ID %s" +msgstr "" + +#: home-manager/home-manager:357 +msgid "Cannot remove the current generation %s" +msgstr "" + +#: home-manager/home-manager:359 +msgid "Removing generation %s" +msgstr "" + +#: home-manager/home-manager:385 +msgid "No generations to expire" +msgstr "" + +#: home-manager/home-manager:396 +msgid "No home-manager packages seem to be installed." +msgstr "" + +#: home-manager/home-manager:453 +msgid "Unknown argument %s" +msgstr "" + +#: home-manager/home-manager:469 +msgid "This will remove Home Manager from your system." +msgstr "" + +#: home-manager/home-manager:472 +msgid "This is a dry run, nothing will actually be uninstalled." +msgstr "" + +#: home-manager/home-manager:476 +msgid "Really uninstall Home Manager?" +msgstr "" + +#: home-manager/home-manager:481 +msgid "Switching to empty Home Manager configuration..." +msgstr "" + +#: home-manager/home-manager:493 +msgid "Yay!" +msgstr "" + +#: home-manager/home-manager:500 +msgid "Remove all Home Manager generations?" +msgstr "" + +#: home-manager/home-manager:507 +msgid "All generations are now eligible for garbage collection." +msgstr "" + +#: home-manager/home-manager:510 +msgid "Leaving generations but they may still be garbage collected." +msgstr "" + +#: home-manager/home-manager:514 +msgid "Home Manager is uninstalled but your home.nix is left untouched." +msgstr "" + +#: home-manager/home-manager:673 +msgid "%s: unknown option '%s'" +msgstr "" + +#: home-manager/home-manager:674 +msgid "Run '%s --help' for usage help" +msgstr "" + +#: home-manager/home-manager:708 +msgid "expire-generations expects one argument, got %d." +msgstr "" + +#: home-manager/home-manager:730 +msgid "Unknown command: %s" +msgstr "" + +#: home-manager/install.nix:22 +msgid "Creating initial Home Manager configuration..." +msgstr "" + +#: home-manager/install.nix:66 +msgid "Creating initial Home Manager generation..." +msgstr "" + +#. translators: The "%s" specifier will be replaced by a file path. +#: home-manager/install.nix:71 +msgid "" +"All done! The home-manager tool should now be installed and you can edit\n" +"\n" +" %s\n" +"\n" +"to configure Home Manager. Run 'man home-configuration.nix' to\n" +"see all available options." +msgstr "" + +#. translators: The "%s" specifier will be replaced by a URL. +#: home-manager/install.nix:76 +msgid "" +"Uh oh, the installation failed! Please create an issue at\n" +"\n" +" %s\n" +"\n" +"if the error seems to be the fault of Home Manager." +msgstr "" + +#: home-manager/install.nix:83 +msgid "This derivation is not buildable, please run it using nix-shell." +msgstr "" diff --git a/infra/libkookie/home-manager-stable/home-manager/po/it.po b/infra/libkookie/home-manager-stable/home-manager/po/it.po new file mode 100644 index 00000000000..610762624c1 --- /dev/null +++ b/infra/libkookie/home-manager-stable/home-manager/po/it.po @@ -0,0 +1,185 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Home Manager contributors +# This file is distributed under the same license as the Home Manager package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: Home Manager\n" +"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" +"POT-Creation-Date: 2022-03-26 15:08+0100\n" +"PO-Revision-Date: 2022-04-20 18:18+0000\n" +"Last-Translator: Frankie McEyes \n" +"Language-Team: Italian \n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.12-dev\n" + +#: home-manager/home-manager:60 +msgid "No configuration file found at %s" +msgstr "Nessun file di configurazione trovato in %s" + +#: home-manager/home-manager:79 +msgid "No configuration file found. Please create one at %s" +msgstr "Nessun file di configurazione trovato. Per favore crearne uno in %s" + +#: home-manager/home-manager:122 +msgid "Can't inspect options of a flake configuration" +msgstr "Impossibile ispezionare le opzioni di configurazione flake" + +#: home-manager/home-manager:162 +msgid "Can't instantiate a flake configuration" +msgstr "Impossibile istanziare una configurazione flake" + +#: home-manager/home-manager:237 +msgid "" +"There is %d unread and relevant news item.\n" +"Read it by running the command \"%s news\"." +msgid_plural "" +"There are %d unread and relevant news items.\n" +"Read them by running the command \"%s news\"." +msgstr[0] "" +"C'è %d novità di elementi non letta.\n" +"Leggila con il comando \"%s news\"." +msgstr[1] "" +"Ci sono %d novità di elementi non letti\n" +"Leggile con il comando \"%s news\"." + +#: home-manager/home-manager:251 +msgid "Unknown \"news.display\" setting \"%s\"." +msgstr "Opzione \"news.display\" sconosciuta \"%s\"." + +#: home-manager/home-manager:258 +#, sh-format +msgid "Please set the $EDITOR environment variable" +msgstr "Per favore impostare la variabile d'ambient $EDITOR" + +#: home-manager/home-manager:273 +msgid "Cannot run build in read-only directory" +msgstr "Impossibile eseguire la build in una cartella in sola lettura" + +#: home-manager/home-manager:355 +msgid "No generation with ID %s" +msgstr "Nessuna generazione con ID %s" + +#: home-manager/home-manager:357 +msgid "Cannot remove the current generation %s" +msgstr "Impossibile rimuovere la generazione corrente %s" + +#: home-manager/home-manager:359 +msgid "Removing generation %s" +msgstr "Rimuovo la generazione %s" + +#: home-manager/home-manager:385 +msgid "No generations to expire" +msgstr "Nessuna generazione in scadenza" + +#: home-manager/home-manager:396 +msgid "No home-manager packages seem to be installed." +msgstr "Nessun pacchetto home-manager sembra essere installato." + +#: home-manager/home-manager:453 +msgid "Unknown argument %s" +msgstr "Argomento sconosciuto: %s" + +#: home-manager/home-manager:469 +msgid "This will remove Home Manager from your system." +msgstr "Questo rimuoverà Home Manger dal tuo sistema." + +#: home-manager/home-manager:472 +msgid "This is a dry run, nothing will actually be uninstalled." +msgstr "Questo è un avvio a secco, nulla verrà realmente disinstallato." + +#: home-manager/home-manager:476 +msgid "Really uninstall Home Manager?" +msgstr "Vuoi davvero disinstallare Home Manager?" + +#: home-manager/home-manager:481 +msgid "Switching to empty Home Manager configuration..." +msgstr "Cambio ad una configurazione Home Manager vuota..." + +#: home-manager/home-manager:493 +msgid "Yay!" +msgstr "Urrà!" + +#: home-manager/home-manager:500 +msgid "Remove all Home Manager generations?" +msgstr "Rimuovere tutte le generazioni Home Manager?" + +#: home-manager/home-manager:507 +msgid "All generations are now eligible for garbage collection." +msgstr "Tutte le generazioni sono ora pronte per essere cestinate." + +#: home-manager/home-manager:510 +msgid "Leaving generations but they may still be garbage collected." +msgstr "Abbandono le generazioni, ma possono essere ancora cestinate." + +#: home-manager/home-manager:514 +msgid "Home Manager is uninstalled but your home.nix is left untouched." +msgstr "Home Manager è disinstallato ma la tua home.Nix non è stata toccata." + +#: home-manager/home-manager:673 +msgid "%s: unknown option '%s'" +msgstr "%s: opzione sconosciuta '%s'" + +#: home-manager/home-manager:674 +msgid "Run '%s --help' for usage help" +msgstr "Esegui '%s --help' per ottenere aiuto" + +#: home-manager/home-manager:708 +msgid "expire-generations expects one argument, got %d." +msgstr "expire-generations si aspetta un solo argomento, invece di %d." + +#: home-manager/home-manager:730 +msgid "Unknown command: %s" +msgstr "Comando sconosciuto: %s" + +#: home-manager/install.nix:22 +msgid "Creating initial Home Manager configuration..." +msgstr "Creando la configurazione iniziale di Home Manager..." + +#: home-manager/install.nix:66 +msgid "Creating initial Home Manager generation..." +msgstr "Creando la generazione iniziale di Home Manager..." + +#. translators: The "%s" specifier will be replaced by a file path. +#: home-manager/install.nix:71 +msgid "" +"All done! The home-manager tool should now be installed and you can edit\n" +"\n" +" %s\n" +"\n" +"to configure Home Manager. Run 'man home-configuration.nix' to\n" +"see all available options." +msgstr "" +"Tutto fatto! Home-manager dovrebbe essere installato e puoi modificare\n" +"\n" +"%s\n" +"\n" +"per configurare Home Manager. Esegui 'man home-configurazion.nix' per\n" +"consultare tutte le opzioni disponibili." + +#. translators: The "%s" specifier will be replaced by a URL. +#: home-manager/install.nix:76 +msgid "" +"Uh oh, the installation failed! Please create an issue at\n" +"\n" +" %s\n" +"\n" +"if the error seems to be the fault of Home Manager." +msgstr "" +"Oh no, l'installazione non è andata a buon fine! Per favore aprire un ticket " +"issue a\n" +"\n" +"%s\n" +"\n" +"se l'errore sembra essere causato da Home Manager." + +#: home-manager/install.nix:83 +msgid "This derivation is not buildable, please run it using nix-shell." +msgstr "" +"Questa derivazione non è compilabile, prova ad eseguila usando nix-shell." diff --git a/infra/libkookie/home-manager-stable/home-manager/po/ja.po b/infra/libkookie/home-manager-stable/home-manager/po/ja.po new file mode 100644 index 00000000000..42c50a278a9 --- /dev/null +++ b/infra/libkookie/home-manager-stable/home-manager/po/ja.po @@ -0,0 +1,186 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Home Manager contributors +# This file is distributed under the same license as the Home Manager package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: Home Manager\n" +"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" +"POT-Creation-Date: 2022-03-26 15:08+0100\n" +"PO-Revision-Date: 2022-02-10 04:55+0000\n" +"Last-Translator: Heman Gandhi \n" +"Language-Team: Japanese \n" +"Language: ja\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 4.11-dev\n" + +#: home-manager/home-manager:60 +msgid "No configuration file found at %s" +msgstr "%s に設定ファイルを見つかりません" + +#: home-manager/home-manager:79 +msgid "No configuration file found. Please create one at %s" +msgstr "設定ファイルがありません。ファイルを %s に作ってください" + +#: home-manager/home-manager:122 +msgid "Can't inspect options of a flake configuration" +msgstr "flake設定のオプションを検査できません" + +#: home-manager/home-manager:162 +msgid "Can't instantiate a flake configuration" +msgstr "flake設定をインスタンス化できません" + +#: home-manager/home-manager:237 +msgid "" +"There is %d unread and relevant news item.\n" +"Read it by running the command \"%s news\"." +msgid_plural "" +"There are %d unread and relevant news items.\n" +"Read them by running the command \"%s news\"." +msgstr[0] "" +"未読の関連ニュースが%d件あります\n" +"\"%s news\"コマンドを使って読んでください。" + +#: home-manager/home-manager:251 +msgid "Unknown \"news.display\" setting \"%s\"." +msgstr "知らない\"news.display\"設定\"%s\"." + +#: home-manager/home-manager:258 +#, sh-format +msgid "Please set the $EDITOR environment variable" +msgstr "$EDITOR環境変数を設定してください" + +#: home-manager/home-manager:273 +msgid "Cannot run build in read-only directory" +msgstr "読み込み専用ディレクトリ内ではbuild(作成)できません" + +#: home-manager/home-manager:355 +msgid "No generation with ID %s" +msgstr "ID %s を持つ世代はありません" + +#: home-manager/home-manager:357 +msgid "Cannot remove the current generation %s" +msgstr "現在使用中の世代 %s は削除できません" + +#: home-manager/home-manager:359 +msgid "Removing generation %s" +msgstr "世代 %s を削除中です" + +#: home-manager/home-manager:385 +msgid "No generations to expire" +msgstr "期限切れで削除する世代はありません" + +#: home-manager/home-manager:396 +msgid "No home-manager packages seem to be installed." +msgstr "home-managerパッケージはインストールされていないようです。" + +#: home-manager/home-manager:453 +msgid "Unknown argument %s" +msgstr "不明な引数 %s" + +#: home-manager/home-manager:469 +msgid "This will remove Home Manager from your system." +msgstr "これはシステムからHome Managerを削除します。" + +#: home-manager/home-manager:472 +msgid "This is a dry run, nothing will actually be uninstalled." +msgstr "これはdry run (予行練習)で、実際にはアンインストールは行われません。" + +#: home-manager/home-manager:476 +msgid "Really uninstall Home Manager?" +msgstr "本当にHome Managerをアンインストールしますか?" + +#: home-manager/home-manager:481 +msgid "Switching to empty Home Manager configuration..." +msgstr "空のHome Managerの設定に切り替え中です..." + +#: home-manager/home-manager:493 +msgid "Yay!" +msgstr "イェイ!" + +#: home-manager/home-manager:500 +msgid "Remove all Home Manager generations?" +msgstr "Home-managerの全ての世代を削除しますか?" + +#: home-manager/home-manager:507 +msgid "All generations are now eligible for garbage collection." +msgstr "全ての世代がガベージコレクションの対象になりました。" + +#: home-manager/home-manager:510 +msgid "Leaving generations but they may still be garbage collected." +msgstr "" +"世代を残していますが、それらはガベージコレクションで回収されるかもしれませ" +"ん。" + +#: home-manager/home-manager:514 +msgid "Home Manager is uninstalled but your home.nix is left untouched." +msgstr "" +"Home Managerはアンインストールされましたが、home.nixはそのまま残してありま" +"す。" + +#: home-manager/home-manager:673 +msgid "%s: unknown option '%s'" +msgstr "%s: 不明なオプション '%s'" + +#: home-manager/home-manager:674 +msgid "Run '%s --help' for usage help" +msgstr "利用方法のヘルプは'%s --help' を実行してください" + +#: home-manager/home-manager:708 +msgid "expire-generations expects one argument, got %d." +msgstr "expire-generations は一つの引数を期待しますが、%d が与えられました。" + +#: home-manager/home-manager:730 +msgid "Unknown command: %s" +msgstr "不明なコマンド: %s" + +#: home-manager/install.nix:22 +msgid "Creating initial Home Manager configuration..." +msgstr "Home Managerの初期設定を生成しています..." + +#: home-manager/install.nix:66 +msgid "Creating initial Home Manager generation..." +msgstr "Home Managertの最初の世代を生成しています..." + +#. translators: The "%s" specifier will be replaced by a file path. +#: home-manager/install.nix:71 +msgid "" +"All done! The home-manager tool should now be installed and you can edit\n" +"\n" +" %s\n" +"\n" +"to configure Home Manager. Run 'man home-configuration.nix' to\n" +"see all available options." +msgstr "" +"全て実行しました! 現在Home-managerツールはインストールされているはずで、\n" +"\n" +" %s\n" +"\n" +"でHome Managerの設定を編集することができます。利用可能なオプションを見るに" +"は\n" +"'man home-configuration.nix' を実行してください。" + +#. translators: The "%s" specifier will be replaced by a URL. +#: home-manager/install.nix:76 +msgid "" +"Uh oh, the installation failed! Please create an issue at\n" +"\n" +" %s\n" +"\n" +"if the error seems to be the fault of Home Manager." +msgstr "" +"うあ、インストールに失敗しました!もしこのエラーがHome Managerの欠陥のせいで" +"生じたようなら、\n" +"\n" +" %s\n" +"\n" +"というissueを立ててください。" + +#: home-manager/install.nix:83 +msgid "This derivation is not buildable, please run it using nix-shell." +msgstr "この派生はビルドできませんので、nix-shellを使って実行してください。" diff --git a/infra/libkookie/home-manager-stable/home-manager/po/ko.po b/infra/libkookie/home-manager-stable/home-manager/po/ko.po new file mode 100644 index 00000000000..2dfe7e49aaa --- /dev/null +++ b/infra/libkookie/home-manager-stable/home-manager/po/ko.po @@ -0,0 +1,186 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Home Manager contributors +# This file is distributed under the same license as the Home Manager package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: Home Manager\n" +"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" +"POT-Creation-Date: 2022-03-26 15:08+0100\n" +"PO-Revision-Date: 2022-01-30 21:50+0000\n" +"Last-Translator: 박수원 \n" +"Language-Team: Korean \n" +"Language: ko\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 4.11-dev\n" + +#: home-manager/home-manager:60 +msgid "No configuration file found at %s" +msgstr "%s에서 설정 파일을 찾을 수 없음" + +#: home-manager/home-manager:79 +msgid "No configuration file found. Please create one at %s" +msgstr "설정 파일을 찾을 수 없음. %s에 설정 파일을 생성하십시오" + +#: home-manager/home-manager:122 +msgid "Can't inspect options of a flake configuration" +msgstr "flake 설정의 옵션들을 검사할 수 없음" + +#: home-manager/home-manager:162 +msgid "Can't instantiate a flake configuration" +msgstr "flake 설정을 인스턴스화 할 수 없음" + +#: home-manager/home-manager:237 +msgid "" +"There is %d unread and relevant news item.\n" +"Read it by running the command \"%s news\"." +msgid_plural "" +"There are %d unread and relevant news items.\n" +"Read them by running the command \"%s news\"." +msgstr[0] "" +"읽지 않은 관련된 뉴스 항목들이 %d 개 있습니다.\n" +"\"%s news\" 명령어를 실행해 읽어보십시오." + +#: home-manager/home-manager:251 +msgid "Unknown \"news.display\" setting \"%s\"." +msgstr "알 수 없는 \"news.display\"의 설정 \"%s\"." + +#: home-manager/home-manager:258 +#, sh-format +msgid "Please set the $EDITOR environment variable" +msgstr "환경변수 $EDITOR를 설정하십시오" + +#: home-manager/home-manager:273 +msgid "Cannot run build in read-only directory" +msgstr "읽기전용 폴더에서 빌드를 실행할 수 없습니다" + +#: home-manager/home-manager:355 +msgid "No generation with ID %s" +msgstr "ID %s를 갖는 세대가 존재하지 않음" + +#: home-manager/home-manager:357 +msgid "Cannot remove the current generation %s" +msgstr "현재 세대인 %s를 삭제할 수 없음" + +#: home-manager/home-manager:359 +msgid "Removing generation %s" +msgstr "%s 세대를 삭제하는 중" + +#: home-manager/home-manager:385 +msgid "No generations to expire" +msgstr "유효 기간이 지난 세대가 없음" + +#: home-manager/home-manager:396 +msgid "No home-manager packages seem to be installed." +msgstr "홈 매니저 패키지들이 설치되지 않은 것으로 보입니다." + +#: home-manager/home-manager:453 +msgid "Unknown argument %s" +msgstr "알 수 없는 매개변수 %s" + +#: home-manager/home-manager:469 +msgid "This will remove Home Manager from your system." +msgstr "시스템에서 홈 매니저를 삭제할 것입니다." + +#: home-manager/home-manager:472 +msgid "This is a dry run, nothing will actually be uninstalled." +msgstr "모의 실행 중으로, 아무것도 실제로 설치되지 않습니다." + +#: home-manager/home-manager:476 +msgid "Really uninstall Home Manager?" +msgstr "정말로 홈 매니저를 삭제할까요?" + +#: home-manager/home-manager:481 +msgid "Switching to empty Home Manager configuration..." +msgstr "빈 홈 매니저 설정으로 바꾸는 중..." + +#: home-manager/home-manager:493 +msgid "Yay!" +msgstr "야호!" + +#: home-manager/home-manager:500 +msgid "Remove all Home Manager generations?" +msgstr "모든 홈 매니저 세대를 지울까요?" + +#: home-manager/home-manager:507 +msgid "All generations are now eligible for garbage collection." +msgstr "이제 모든 세대가 쓰레기 수집(가비지 컬렉션)의 대상이 됩니다." + +#: home-manager/home-manager:510 +msgid "Leaving generations but they may still be garbage collected." +msgstr "" +"세대들을 그대로 놔두지만 그들은 여전히 쓰레기 수집(가비지 컬렉션) 될 수 있습" +"니다." + +#: home-manager/home-manager:514 +msgid "Home Manager is uninstalled but your home.nix is left untouched." +msgstr "홈 매니저는 삭제되지만 home.nix 파일은 남겨집니다." + +#: home-manager/home-manager:673 +msgid "%s: unknown option '%s'" +msgstr "%s: 알 수 없는 옵션 '%s'" + +#: home-manager/home-manager:674 +msgid "Run '%s --help' for usage help" +msgstr "도움말을 보려면 '%s --help'를 실행하십시오" + +#: home-manager/home-manager:708 +msgid "expire-generations expects one argument, got %d." +msgstr "" +"expire-generations 명령어는 매개변수가 한 개 필요한데, %d 개가 입력되었습니" +"다." + +#: home-manager/home-manager:730 +msgid "Unknown command: %s" +msgstr "알 수 없는 명령어: %s" + +#: home-manager/install.nix:22 +msgid "Creating initial Home Manager configuration..." +msgstr "최초의 홈 매니저 설정을 생성하는 중..." + +#: home-manager/install.nix:66 +msgid "Creating initial Home Manager generation..." +msgstr "최초의 홈 매니저 세대를 생성하는 중..." + +#. translators: The "%s" specifier will be replaced by a file path. +#: home-manager/install.nix:71 +msgid "" +"All done! The home-manager tool should now be installed and you can edit\n" +"\n" +" %s\n" +"\n" +"to configure Home Manager. Run 'man home-configuration.nix' to\n" +"see all available options." +msgstr "" +"완료! 홈 매니저 도구들이 설치 되었고 이제 \n" +"\n" +" %s\n" +"\n" +"파일을 수정해서 홈 매니저를 설정할 수 있습니다. 'man home-configuration." +"nix'를\n" +"실행해서 가능한 모든 옵션을 살펴보십시오." + +#. translators: The "%s" specifier will be replaced by a URL. +#: home-manager/install.nix:76 +msgid "" +"Uh oh, the installation failed! Please create an issue at\n" +"\n" +" %s\n" +"\n" +"if the error seems to be the fault of Home Manager." +msgstr "" +"이런, 설치가 실패했습니다! 만약 에러가 홈 매니저의 문제라고 생각된다면\n" +"\n" +" %s\n" +"\n" +"위 사이트에서 이슈를 생성하십시오." + +#: home-manager/install.nix:83 +msgid "This derivation is not buildable, please run it using nix-shell." +msgstr "" +"이 derivation은 빌드 할 수 없습니다. nix-shell을 이용해서 실행해 주십시오." diff --git a/infra/libkookie/home-manager-stable/home-manager/po/nb_NO.po b/infra/libkookie/home-manager-stable/home-manager/po/nb_NO.po new file mode 100644 index 00000000000..55127791d39 --- /dev/null +++ b/infra/libkookie/home-manager-stable/home-manager/po/nb_NO.po @@ -0,0 +1,172 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Home Manager contributors +# This file is distributed under the same license as the Home Manager package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: Home Manager\n" +"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" +"POT-Creation-Date: 2022-03-26 15:08+0100\n" +"PO-Revision-Date: 2021-12-13 20:50+0000\n" +"Last-Translator: Allan Nordhøy \n" +"Language-Team: Norwegian Bokmål \n" +"Language: nb_NO\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.10-dev\n" + +#: home-manager/home-manager:60 +msgid "No configuration file found at %s" +msgstr "Fant ingen oppsettsfil i %s" + +#: home-manager/home-manager:79 +msgid "No configuration file found. Please create one at %s" +msgstr "Fant ikke noenoppsettsfil. Opprett en i %s" + +#: home-manager/home-manager:122 +msgid "Can't inspect options of a flake configuration" +msgstr "Kan ikke inspisere alternativer for et flake-oppsett" + +#: home-manager/home-manager:162 +msgid "Can't instantiate a flake configuration" +msgstr "Kan ikke igangsette flak-oppsett" + +#: home-manager/home-manager:237 +msgid "" +"There is %d unread and relevant news item.\n" +"Read it by running the command \"%s news\"." +msgid_plural "" +"There are %d unread and relevant news items.\n" +"Read them by running the command \"%s news\"." +msgstr[0] "" +"Det er %d ulest og relevant nyhetselement.\n" +"Les det ved å kjøre kommandoen «%s news»." +msgstr[1] "" +"Det er %d uleste og relevant nyhetselementer.\n" +"Les det ved å kjøre kommandoen «%s news»." + +#: home-manager/home-manager:251 +msgid "Unknown \"news.display\" setting \"%s\"." +msgstr "Ukjent «news.display»-innstilling «%s»." + +#: home-manager/home-manager:258 +#, sh-format +msgid "Please set the $EDITOR environment variable" +msgstr "Sett «$EDITOR»-miljøvariabelen" + +#: home-manager/home-manager:273 +msgid "Cannot run build in read-only directory" +msgstr "Kan ikke kjøre bygg i skrivebeskyttet mappe" + +#: home-manager/home-manager:355 +msgid "No generation with ID %s" +msgstr "Ingen generering med ID-en %s" + +#: home-manager/home-manager:357 +msgid "Cannot remove the current generation %s" +msgstr "Kan ikke fjerne nåværende generering %s" + +#: home-manager/home-manager:359 +msgid "Removing generation %s" +msgstr "Fjerner generering %s" + +#: home-manager/home-manager:385 +msgid "No generations to expire" +msgstr "Ingen genereringer til utløp" + +#: home-manager/home-manager:396 +msgid "No home-manager packages seem to be installed." +msgstr "Ingen «home-manager»-pakker ser ut til å være installert." + +#: home-manager/home-manager:453 +msgid "Unknown argument %s" +msgstr "Ukjent argument %s" + +#: home-manager/home-manager:469 +msgid "This will remove Home Manager from your system." +msgstr "Dette vil fjerne Home Manager fra systemet ditt." + +#: home-manager/home-manager:472 +msgid "This is a dry run, nothing will actually be uninstalled." +msgstr "Dette er en testkjøring. Ingenting vil bli avinstallert." + +#: home-manager/home-manager:476 +msgid "Really uninstall Home Manager?" +msgstr "Vil du avinstallere Home Manager?" + +#: home-manager/home-manager:481 +msgid "Switching to empty Home Manager configuration..." +msgstr "Bytter til tomt Home Manager-oppsett …" + +#: home-manager/home-manager:493 +msgid "Yay!" +msgstr "Hurra." + +#: home-manager/home-manager:500 +msgid "Remove all Home Manager generations?" +msgstr "Fjern alle Home Manager-genereringer?" + +#: home-manager/home-manager:507 +msgid "All generations are now eligible for garbage collection." +msgstr "Alle genereringer kan nå hentes av søppelinnsamling." + +#: home-manager/home-manager:510 +msgid "Leaving generations but they may still be garbage collected." +msgstr "Levner genereringer, men de kan fremdeles hentes av søppelinnsamling." + +#: home-manager/home-manager:514 +msgid "Home Manager is uninstalled but your home.nix is left untouched." +msgstr "Home Manager er avinstallert, men din home.nix er levnet uforandret." + +#: home-manager/home-manager:673 +msgid "%s: unknown option '%s'" +msgstr "%s: ukjent alternativ «%s»" + +#: home-manager/home-manager:674 +msgid "Run '%s --help' for usage help" +msgstr "Kjør «%s --help» for brukshjelp" + +#: home-manager/home-manager:708 +msgid "expire-generations expects one argument, got %d." +msgstr "«expire-generations» forventet ett argument, mottok %d." + +#: home-manager/home-manager:730 +msgid "Unknown command: %s" +msgstr "Ukjent kommando: %s" + +#: home-manager/install.nix:22 +msgid "Creating initial Home Manager configuration..." +msgstr "" + +#: home-manager/install.nix:66 +msgid "Creating initial Home Manager generation..." +msgstr "" + +#. translators: The "%s" specifier will be replaced by a file path. +#: home-manager/install.nix:71 +msgid "" +"All done! The home-manager tool should now be installed and you can edit\n" +"\n" +" %s\n" +"\n" +"to configure Home Manager. Run 'man home-configuration.nix' to\n" +"see all available options." +msgstr "" + +#. translators: The "%s" specifier will be replaced by a URL. +#: home-manager/install.nix:76 +msgid "" +"Uh oh, the installation failed! Please create an issue at\n" +"\n" +" %s\n" +"\n" +"if the error seems to be the fault of Home Manager." +msgstr "" + +#: home-manager/install.nix:83 +msgid "This derivation is not buildable, please run it using nix-shell." +msgstr "" diff --git a/infra/libkookie/home-manager-stable/home-manager/po/pl.po b/infra/libkookie/home-manager-stable/home-manager/po/pl.po new file mode 100644 index 00000000000..4835b505e97 --- /dev/null +++ b/infra/libkookie/home-manager-stable/home-manager/po/pl.po @@ -0,0 +1,191 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Home Manager contributors +# This file is distributed under the same license as the Home Manager package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: Home Manager\n" +"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" +"POT-Creation-Date: 2022-03-26 15:08+0100\n" +"PO-Revision-Date: 2021-12-29 08:48+0000\n" +"Last-Translator: Tomasz Czyż \n" +"Language-Team: Polish \n" +"Language: pl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " +"|| n%100>=20) ? 1 : 2;\n" +"X-Generator: Weblate 4.10.1\n" + +#: home-manager/home-manager:60 +msgid "No configuration file found at %s" +msgstr "Nie znaleziono pliku konfiguracyjnego %s" + +#: home-manager/home-manager:79 +msgid "No configuration file found. Please create one at %s" +msgstr "Nie znaleziono pliku konfiguracyjnego. Proszę utworzyć plik %s" + +#: home-manager/home-manager:122 +msgid "Can't inspect options of a flake configuration" +msgstr "Nie mogę sprawdzić konfiguracji flake'a" + +#: home-manager/home-manager:162 +msgid "Can't instantiate a flake configuration" +msgstr "Nie mogę zinstancjować konfiguracji flake'a" + +#: home-manager/home-manager:237 +msgid "" +"There is %d unread and relevant news item.\n" +"Read it by running the command \"%s news\"." +msgid_plural "" +"There are %d unread and relevant news items.\n" +"Read them by running the command \"%s news\"." +msgstr[0] "" +"Jest %d nieodczytana wiadomość.\n" +"Możesz ją odczytać uruchamiając „%s news”." +msgstr[1] "" +"Jest %d nieodczytanych wiadomości.\n" +"Możesz je odczytać uruchamiając „%s news”." +msgstr[2] "" +"Jest %d nieodczytanych wiadomości.\n" +"Możesz je odczytać uruchamiając „%s news”." + +#: home-manager/home-manager:251 +msgid "Unknown \"news.display\" setting \"%s\"." +msgstr "Nieznane ustawienie „%s” „news.display”." + +#: home-manager/home-manager:258 +#, sh-format +msgid "Please set the $EDITOR environment variable" +msgstr "Proszę ustawić zmienną środowiskową $EDITOR" + +#: home-manager/home-manager:273 +msgid "Cannot run build in read-only directory" +msgstr "Nie mogę uruchomić budowania w katalogu tylko-do-odczytu" + +#: home-manager/home-manager:355 +msgid "No generation with ID %s" +msgstr "Brak generacji z ID %s" + +#: home-manager/home-manager:357 +msgid "Cannot remove the current generation %s" +msgstr "Nie mogę usunąć bieżącej generacji %s" + +#: home-manager/home-manager:359 +msgid "Removing generation %s" +msgstr "Usuwanie generacji %s" + +#: home-manager/home-manager:385 +msgid "No generations to expire" +msgstr "Brak wygasających generacji" + +#: home-manager/home-manager:396 +msgid "No home-manager packages seem to be installed." +msgstr "Pakiety home-manager nie wydają się być zainstalowane." + +#: home-manager/home-manager:453 +msgid "Unknown argument %s" +msgstr "Nieznany argument %s" + +#: home-manager/home-manager:469 +msgid "This will remove Home Manager from your system." +msgstr "To usunie Home Managera z twojego systemu." + +#: home-manager/home-manager:472 +msgid "This is a dry run, nothing will actually be uninstalled." +msgstr "To jest próba, faktycznie nic nie będzie usunięte." + +#: home-manager/home-manager:476 +msgid "Really uninstall Home Manager?" +msgstr "Jesteś pewien usunięcia Home Managera?" + +#: home-manager/home-manager:481 +msgid "Switching to empty Home Manager configuration..." +msgstr "Przełączanie do pustej konfiguracji Home Managera..." + +#: home-manager/home-manager:493 +msgid "Yay!" +msgstr "Jej!" + +#: home-manager/home-manager:500 +msgid "Remove all Home Manager generations?" +msgstr "Usunąć wszystkie generacje Home Managera?" + +#: home-manager/home-manager:507 +msgid "All generations are now eligible for garbage collection." +msgstr "" +"Wszystkie generacje są uwzględnione przy oczyszczaniu (garbage collection)." + +#: home-manager/home-manager:510 +msgid "Leaving generations but they may still be garbage collected." +msgstr "" +"Zostawiam generacje ale wciąż mogą zostać usunięte (garbage collection)." + +#: home-manager/home-manager:514 +msgid "Home Manager is uninstalled but your home.nix is left untouched." +msgstr "" +"Home Manager jest usunięty ale twój home.nix jest pozostawiony nietknięty." + +#: home-manager/home-manager:673 +msgid "%s: unknown option '%s'" +msgstr "%s: nieznana opcja „%s”" + +#: home-manager/home-manager:674 +msgid "Run '%s --help' for usage help" +msgstr "Uruchom „%s --help” by otrzymać pomoc" + +#: home-manager/home-manager:708 +msgid "expire-generations expects one argument, got %d." +msgstr "expire-generations oczekuje jednego argumentu, otrzymane %d." + +#: home-manager/home-manager:730 +msgid "Unknown command: %s" +msgstr "Nieznana komenda: %s" + +#: home-manager/install.nix:22 +msgid "Creating initial Home Manager configuration..." +msgstr "Tworzenie pierwotnej konfiguracji Home Managera..." + +#: home-manager/install.nix:66 +msgid "Creating initial Home Manager generation..." +msgstr "Tworzenie pierwotnej generacji Home Managera..." + +#. translators: The "%s" specifier will be replaced by a file path. +#: home-manager/install.nix:71 +msgid "" +"All done! The home-manager tool should now be installed and you can edit\n" +"\n" +" %s\n" +"\n" +"to configure Home Manager. Run 'man home-configuration.nix' to\n" +"see all available options." +msgstr "" +"Skończone! Narzędzie home-manager powinno być zainstalowane i może edytować\n" +"\n" +" %s\n" +"\n" +"by skonfigurować Home Managera. Uruchom „man home-configuration.nix” aby\n" +"sprawdzić wszystkie możliwe opcje konfiguracyjne." + +#. translators: The "%s" specifier will be replaced by a URL. +#: home-manager/install.nix:76 +msgid "" +"Uh oh, the installation failed! Please create an issue at\n" +"\n" +" %s\n" +"\n" +"if the error seems to be the fault of Home Manager." +msgstr "" +"Ojoj, instalacja nie powiodła się! Proszę opisz problem na\n" +"\n" +" %s\n" +"\n" +"jeśli myślisz, że problem spowodowany jest przez błąd Home Managera." + +#: home-manager/install.nix:83 +msgid "This derivation is not buildable, please run it using nix-shell." +msgstr "" +"Ta paczka (derivation) nie da się budować, proszę uruchom używając nix-shell." diff --git a/infra/libkookie/home-manager-stable/home-manager/po/pt_BR.po b/infra/libkookie/home-manager-stable/home-manager/po/pt_BR.po new file mode 100644 index 00000000000..de2fb705676 --- /dev/null +++ b/infra/libkookie/home-manager-stable/home-manager/po/pt_BR.po @@ -0,0 +1,188 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Home Manager contributors +# This file is distributed under the same license as the Home Manager package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: Home Manager\n" +"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" +"POT-Creation-Date: 2022-03-26 15:08+0100\n" +"PO-Revision-Date: 2022-04-04 11:11+0000\n" +"Last-Translator: Alex Miranda \n" +"Language-Team: Portuguese (Brazil) \n" +"Language: pt_BR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 4.12-dev\n" + +#: home-manager/home-manager:60 +msgid "No configuration file found at %s" +msgstr "Nenhum arquivo de configuração encontrado no %s" + +#: home-manager/home-manager:79 +msgid "No configuration file found. Please create one at %s" +msgstr "Arquivo de configuração não encontrado. Por favor crie um em %s" + +#: home-manager/home-manager:122 +msgid "Can't inspect options of a flake configuration" +msgstr "Não é possivel inspecionar a opção de configuração do flake" + +#: home-manager/home-manager:162 +msgid "Can't instantiate a flake configuration" +msgstr "Não foi possível instanciar a configuração de flake" + +#: home-manager/home-manager:237 +msgid "" +"There is %d unread and relevant news item.\n" +"Read it by running the command \"%s news\"." +msgid_plural "" +"There are %d unread and relevant news items.\n" +"Read them by running the command \"%s news\"." +msgstr[0] "" +"Há %d novo item relevante não lido\n" +"Leia executando o comando \"%s news\"." +msgstr[1] "" +"Há %d novos itens relevants não lidos\n" +"Leia executando o comando \"%s news\"." + +#: home-manager/home-manager:251 +msgid "Unknown \"news.display\" setting \"%s\"." +msgstr "Valor \"%s\" para configuração \"news.display\" não reconhecido." + +#: home-manager/home-manager:258 +#, sh-format +msgid "Please set the $EDITOR environment variable" +msgstr "Por favor defina a variável de ambiente $EDITOR" + +#: home-manager/home-manager:273 +msgid "Cannot run build in read-only directory" +msgstr "Não é possível fazer o build em um diretório somente leitura" + +#: home-manager/home-manager:355 +msgid "No generation with ID %s" +msgstr "Nenhuma geração com ID %s" + +#: home-manager/home-manager:357 +msgid "Cannot remove the current generation %s" +msgstr "Não foi possível remover a geração atual %s" + +#: home-manager/home-manager:359 +msgid "Removing generation %s" +msgstr "Removendo geração %s" + +#: home-manager/home-manager:385 +msgid "No generations to expire" +msgstr "Nenhuma geração a expirar" + +#: home-manager/home-manager:396 +msgid "No home-manager packages seem to be installed." +msgstr "Nenhum pacote parece instalado com home-manager." + +#: home-manager/home-manager:453 +msgid "Unknown argument %s" +msgstr "Argumento desconhecido %s" + +#: home-manager/home-manager:469 +msgid "This will remove Home Manager from your system." +msgstr "Isso irá remover o Home Manager do seu sistema." + +#: home-manager/home-manager:472 +msgid "This is a dry run, nothing will actually be uninstalled." +msgstr "Essa é uma execução de teste, nada de fato será desinstalado." + +#: home-manager/home-manager:476 +msgid "Really uninstall Home Manager?" +msgstr "Confirma a desinstalação do Home Manager?" + +#: home-manager/home-manager:481 +msgid "Switching to empty Home Manager configuration..." +msgstr "Trocando para configuração vazia do Home Manager..." + +#: home-manager/home-manager:493 +msgid "Yay!" +msgstr "Boa!" + +#: home-manager/home-manager:500 +msgid "Remove all Home Manager generations?" +msgstr "Remover todas as gerações do Home Manager?" + +#: home-manager/home-manager:507 +msgid "All generations are now eligible for garbage collection." +msgstr "Todas gerações agora são elegíveis para coleta do garbage collector." + +#: home-manager/home-manager:510 +msgid "Leaving generations but they may still be garbage collected." +msgstr "" +"Deixando gerações, entretanto elas ainda poderão ser limpas pelo garbage " +"collector." + +#: home-manager/home-manager:514 +msgid "Home Manager is uninstalled but your home.nix is left untouched." +msgstr "Home Manager foi desinstalado, mas o seu home.nix foi deixado intacto." + +#: home-manager/home-manager:673 +msgid "%s: unknown option '%s'" +msgstr "%s: opção não reconhecida '%s'" + +#: home-manager/home-manager:674 +msgid "Run '%s --help' for usage help" +msgstr "Execute '%s --help' para instruções de uso" + +#: home-manager/home-manager:708 +msgid "expire-generations expects one argument, got %d." +msgstr "expire-generations espera um argumento, recebeu %d." + +#: home-manager/home-manager:730 +msgid "Unknown command: %s" +msgstr "Comando não reconhecido: %s" + +#: home-manager/install.nix:22 +msgid "Creating initial Home Manager configuration..." +msgstr "Criando a configuração inicial do Home Manager..." + +#: home-manager/install.nix:66 +msgid "Creating initial Home Manager generation..." +msgstr "Criando a geração inicial do Home Manager..." + +#. translators: The "%s" specifier will be replaced by a file path. +#: home-manager/install.nix:71 +msgid "" +"All done! The home-manager tool should now be installed and you can edit\n" +"\n" +" %s\n" +"\n" +"to configure Home Manager. Run 'man home-configuration.nix' to\n" +"see all available options." +msgstr "" +"Pronto! O home-manager deve ser instalado agora e você poderá editar o " +"arquivo\n" +"\n" +" %s\n" +"\n" +"para configurar o Home Manager. Execute 'man home-configuration.nix' para\n" +"ver todas as opções disponíveis." + +#. translators: The "%s" specifier will be replaced by a URL. +#: home-manager/install.nix:76 +msgid "" +"Uh oh, the installation failed! Please create an issue at\n" +"\n" +" %s\n" +"\n" +"if the error seems to be the fault of Home Manager." +msgstr "" +"Ixi, a instalação falhou! Por favor crie um issue no\n" +"\n" +" %s\n" +"\n" +"se o erro lhe parecer ser um problema do Home Manager." + +#: home-manager/install.nix:83 +msgid "This derivation is not buildable, please run it using nix-shell." +msgstr "" +"O build dessa derivation não pode ser feito, por favor rode usando o nix-" +"shell." diff --git a/infra/libkookie/home-manager-stable/home-manager/po/ru.po b/infra/libkookie/home-manager-stable/home-manager/po/ru.po new file mode 100644 index 00000000000..05378c0fe52 --- /dev/null +++ b/infra/libkookie/home-manager-stable/home-manager/po/ru.po @@ -0,0 +1,188 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Home Manager contributors +# This file is distributed under the same license as the Home Manager package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: Home Manager\n" +"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" +"POT-Creation-Date: 2022-03-26 15:08+0100\n" +"PO-Revision-Date: 2021-12-21 19:55+0000\n" +"Last-Translator: Mikhail Chekan \n" +"Language-Team: Russian \n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Generator: Weblate 4.10\n" + +#: home-manager/home-manager:60 +msgid "No configuration file found at %s" +msgstr "Не найден файл конфигурации в %s" + +#: home-manager/home-manager:79 +msgid "No configuration file found. Please create one at %s" +msgstr "Не найден файл конфигурации. Пожалуйста, создайте его в %s" + +#: home-manager/home-manager:122 +msgid "Can't inspect options of a flake configuration" +msgstr "Не могу получить опции для flake-конфигурации" + +#: home-manager/home-manager:162 +msgid "Can't instantiate a flake configuration" +msgstr "Не могу создать экземляр для flake-конфигурации" + +#: home-manager/home-manager:237 +msgid "" +"There is %d unread and relevant news item.\n" +"Read it by running the command \"%s news\"." +msgid_plural "" +"There are %d unread and relevant news items.\n" +"Read them by running the command \"%s news\"." +msgstr[0] "" +"У вас есть %d непрочитанная и релевантная новость.\n" +"Прочтите её, выполнив команду \"%s news\"." +msgstr[1] "" +"У вас есть %d непрочитанные и релевантные новости.\n" +"Прочтите их, выполнив команду \"%s news\"." +msgstr[2] "" +"У вас есть %d непрочитанных и релевантных новостей.\n" +"Прочтите их, выполнив команду \"%s news\"." + +#: home-manager/home-manager:251 +msgid "Unknown \"news.display\" setting \"%s\"." +msgstr "Неизвестное значение \"news.display\": \"%s\"." + +#: home-manager/home-manager:258 +#, sh-format +msgid "Please set the $EDITOR environment variable" +msgstr "Пожалуйста, определите переменную среды $EDITOR" + +#: home-manager/home-manager:273 +msgid "Cannot run build in read-only directory" +msgstr "Не могу начать сборку в директории, защищённой от записи" + +#: home-manager/home-manager:355 +msgid "No generation with ID %s" +msgstr "Поколение под номером %s не существует" + +#: home-manager/home-manager:357 +msgid "Cannot remove the current generation %s" +msgstr "Не могу удалить текущее поколение %s" + +#: home-manager/home-manager:359 +msgid "Removing generation %s" +msgstr "Удаляю поколение %s" + +#: home-manager/home-manager:385 +msgid "No generations to expire" +msgstr "Нет поколений, которые можно просрочить" + +#: home-manager/home-manager:396 +msgid "No home-manager packages seem to be installed." +msgstr "Не обнаружено пакетов, установленных через home-manager." + +#: home-manager/home-manager:453 +msgid "Unknown argument %s" +msgstr "Неизвестный аргумент %s" + +#: home-manager/home-manager:469 +msgid "This will remove Home Manager from your system." +msgstr "Это удалит Home Manager из вашей системы." + +#: home-manager/home-manager:472 +msgid "This is a dry run, nothing will actually be uninstalled." +msgstr "Это пробный запуск, на самом деле ничего не удаляется." + +#: home-manager/home-manager:476 +msgid "Really uninstall Home Manager?" +msgstr "Действительно хотите удалить Home Manager?" + +#: home-manager/home-manager:481 +msgid "Switching to empty Home Manager configuration..." +msgstr "Переключаюсь на пустую конфигурацию Home Manager..." + +#: home-manager/home-manager:493 +msgid "Yay!" +msgstr "Ура!" + +#: home-manager/home-manager:500 +msgid "Remove all Home Manager generations?" +msgstr "Удалить все поколения Home Manager?" + +#: home-manager/home-manager:507 +msgid "All generations are now eligible for garbage collection." +msgstr "Теперь все поколения готовы к удалению сборщиком мусора." + +#: home-manager/home-manager:510 +msgid "Leaving generations but they may still be garbage collected." +msgstr "Поколения остаются, но их ещё можно удалить сборщиком мусора." + +#: home-manager/home-manager:514 +msgid "Home Manager is uninstalled but your home.nix is left untouched." +msgstr "Home Manager удалён, но ваш home.nix остался нетронутым." + +#: home-manager/home-manager:673 +msgid "%s: unknown option '%s'" +msgstr "%s: неизвестная опция '%s'" + +#: home-manager/home-manager:674 +msgid "Run '%s --help' for usage help" +msgstr "Выполните '%s --help', чтобы получить справку" + +#: home-manager/home-manager:708 +msgid "expire-generations expects one argument, got %d." +msgstr "expire-generations требует один аргумент, но передано %d." + +#: home-manager/home-manager:730 +msgid "Unknown command: %s" +msgstr "Неизвестная команда: %s" + +#: home-manager/install.nix:22 +msgid "Creating initial Home Manager configuration..." +msgstr "Создаю начальную конфигурацию Home Manager..." + +#: home-manager/install.nix:66 +msgid "Creating initial Home Manager generation..." +msgstr "Создаю начальное поколение Home Manager..." + +#. translators: The "%s" specifier will be replaced by a file path. +#: home-manager/install.nix:71 +msgid "" +"All done! The home-manager tool should now be installed and you can edit\n" +"\n" +" %s\n" +"\n" +"to configure Home Manager. Run 'man home-configuration.nix' to\n" +"see all available options." +msgstr "" +"Готово! Теперь вам должна быть доступна утилита home-manager,\n" +"и вы можете отредактировать настройки в файле\n" +"\n" +" %s\n" +"\n" +"Выполните 'man home-configuration.nix', чтобы увидеть доступные опции." + +#. translators: The "%s" specifier will be replaced by a URL. +#: home-manager/install.nix:76 +msgid "" +"Uh oh, the installation failed! Please create an issue at\n" +"\n" +" %s\n" +"\n" +"if the error seems to be the fault of Home Manager." +msgstr "" +"Ой, установка не удалась! Пожалуйста, создайте тему в багтрекере\n" +"\n" +" %s\n" +"\n" +"если считаете, что в ошибке виноват Home Manager." + +#: home-manager/install.nix:83 +msgid "This derivation is not buildable, please run it using nix-shell." +msgstr "" +"Это определение нельзя собрать. Пожалуйста, запустите его через nix-shell." diff --git a/infra/libkookie/home-manager-stable/home-manager/po/sv.po b/infra/libkookie/home-manager-stable/home-manager/po/sv.po new file mode 100644 index 00000000000..6ca1fc7f946 --- /dev/null +++ b/infra/libkookie/home-manager-stable/home-manager/po/sv.po @@ -0,0 +1,183 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: Home Manager\n" +"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" +"POT-Creation-Date: 2022-03-26 15:08+0100\n" +"PO-Revision-Date: 2021-12-17 20:50+0000\n" +"Last-Translator: Robert Helgesson \n" +"Language-Team: Swedish \n" +"Language: sv\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.10\n" + +#: home-manager/home-manager:60 +msgid "No configuration file found at %s" +msgstr "Det finns ingen konfigurationsfil i %s" + +#: home-manager/home-manager:79 +msgid "No configuration file found. Please create one at %s" +msgstr "Hittade ingen konfigurationsfil. Skapa en i %s" + +#: home-manager/home-manager:122 +msgid "Can't inspect options of a flake configuration" +msgstr "Kan inte granska alternativ i en flake-konfiguration" + +#: home-manager/home-manager:162 +msgid "Can't instantiate a flake configuration" +msgstr "Kan inte instansera en flake-konfiguration" + +#: home-manager/home-manager:237 +msgid "" +"There is %d unread and relevant news item.\n" +"Read it by running the command \"%s news\"." +msgid_plural "" +"There are %d unread and relevant news items.\n" +"Read them by running the command \"%s news\"." +msgstr[0] "" +"Det finns %d oläst och relevant nyhet.\n" +"Läs den genom att köra kommandot \"%s news\"." +msgstr[1] "" +"Det finns %d olästa och relevanta nyheter.\n" +"Läs dem genom att köra kommandot \"%s news\"." + +#: home-manager/home-manager:251 +msgid "Unknown \"news.display\" setting \"%s\"." +msgstr "Okänt \"news.display\"-värde \"%s\"." + +#: home-manager/home-manager:258 +#, sh-format +msgid "Please set the $EDITOR environment variable" +msgstr "Vänligen tilldela miljövariablen $EDITOR" + +#: home-manager/home-manager:273 +msgid "Cannot run build in read-only directory" +msgstr "Kan inte bygga i katalog med bara läsrättigheter" + +#: home-manager/home-manager:355 +msgid "No generation with ID %s" +msgstr "Ingen generation med ID %s" + +#: home-manager/home-manager:357 +msgid "Cannot remove the current generation %s" +msgstr "Kan inte ta bort nuvarande generation %s" + +#: home-manager/home-manager:359 +msgid "Removing generation %s" +msgstr "Tar bort generation %s" + +#: home-manager/home-manager:385 +msgid "No generations to expire" +msgstr "Ingen generation att förfalla" + +#: home-manager/home-manager:396 +msgid "No home-manager packages seem to be installed." +msgstr "Paketet home-manager verkar inte vara installerat." + +#: home-manager/home-manager:453 +msgid "Unknown argument %s" +msgstr "Okänt argument %s" + +#: home-manager/home-manager:469 +msgid "This will remove Home Manager from your system." +msgstr "Detta kommer att ta bort Home Manager från ditt system." + +#: home-manager/home-manager:472 +msgid "This is a dry run, nothing will actually be uninstalled." +msgstr "Detta är en testkörning, inget kommer att bli avinstallerat." + +#: home-manager/home-manager:476 +msgid "Really uninstall Home Manager?" +msgstr "Verkligen avinstallera Home Manager?" + +#: home-manager/home-manager:481 +msgid "Switching to empty Home Manager configuration..." +msgstr "Byter till tom Home Manager-konfiguration..." + +#: home-manager/home-manager:493 +msgid "Yay!" +msgstr "Hurra!" + +#: home-manager/home-manager:500 +msgid "Remove all Home Manager generations?" +msgstr "Ta bort alla Home Manager-generationer?" + +#: home-manager/home-manager:507 +msgid "All generations are now eligible for garbage collection." +msgstr "Alla generationer kan nu skräpsamlas." + +#: home-manager/home-manager:510 +msgid "Leaving generations but they may still be garbage collected." +msgstr "Låter generationer vara kvar men de kan fortfarande skräpsamlas." + +#: home-manager/home-manager:514 +msgid "Home Manager is uninstalled but your home.nix is left untouched." +msgstr "Home Manager är avinstallerad men din home.nix är orörd." + +#: home-manager/home-manager:673 +msgid "%s: unknown option '%s'" +msgstr "%s: okänt val '%s'" + +#: home-manager/home-manager:674 +msgid "Run '%s --help' for usage help" +msgstr "Kör '%s --help' för användarhjälp" + +#: home-manager/home-manager:708 +msgid "expire-generations expects one argument, got %d." +msgstr "expect-generations förväntar sig ett argument, fick %d." + +#: home-manager/home-manager:730 +msgid "Unknown command: %s" +msgstr "Okänt kommando: %s" + +#: home-manager/install.nix:22 +msgid "Creating initial Home Manager configuration..." +msgstr "Skapar initial Home Manager-konfiguration..." + +#: home-manager/install.nix:66 +msgid "Creating initial Home Manager generation..." +msgstr "Skapar initial Home Manager-generation..." + +#. translators: The "%s" specifier will be replaced by a file path. +#: home-manager/install.nix:71 +msgid "" +"All done! The home-manager tool should now be installed and you can edit\n" +"\n" +" %s\n" +"\n" +"to configure Home Manager. Run 'man home-configuration.nix' to\n" +"see all available options." +msgstr "" +"Färdig! Verktyget home-manager borde nu vara installerat och du kan editera\n" +"\n" +" %s\n" +"\n" +"för att konfigurera Home Manager. Kör 'man home-configuration.nix' för\n" +"att se alla tillgängliga alternativ." + +#. translators: The "%s" specifier will be replaced by a URL. +#: home-manager/install.nix:76 +msgid "" +"Uh oh, the installation failed! Please create an issue at\n" +"\n" +" %s\n" +"\n" +"if the error seems to be the fault of Home Manager." +msgstr "" +"Ajdå, installationen misslyckades! Skapa gärna en rapport på\n" +"\n" +" %s\n" +"\n" +"om problemet verkar bero på något Home Manager gör fel." + +#: home-manager/install.nix:83 +msgid "This derivation is not buildable, please run it using nix-shell." +msgstr "Denna derivation är inte byggbar, kör den med nix-shell istället." diff --git a/infra/libkookie/home-manager-stable/home-manager/po/tr.po b/infra/libkookie/home-manager-stable/home-manager/po/tr.po new file mode 100644 index 00000000000..fade64173d7 --- /dev/null +++ b/infra/libkookie/home-manager-stable/home-manager/po/tr.po @@ -0,0 +1,186 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Home Manager contributors +# This file is distributed under the same license as the Home Manager package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: Home Manager\n" +"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" +"POT-Creation-Date: 2022-03-26 15:08+0100\n" +"PO-Revision-Date: 2022-03-26 23:57+0000\n" +"Last-Translator: Oğuz Ersen \n" +"Language-Team: Turkish \n" +"Language: tr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.12-dev\n" + +#: home-manager/home-manager:60 +msgid "No configuration file found at %s" +msgstr "%s konumunda yapılandırma dosyası bulunamadı" + +#: home-manager/home-manager:79 +msgid "No configuration file found. Please create one at %s" +msgstr "" +"Yapılandırma dosyası bulunamadı. Lütfen %s konumunda bir tane oluşturun" + +#: home-manager/home-manager:122 +msgid "Can't inspect options of a flake configuration" +msgstr "Flake yapılandırmasının ayarları incelenemiyor" + +#: home-manager/home-manager:162 +msgid "Can't instantiate a flake configuration" +msgstr "Flake yapılandırması örneklendirilemiyor" + +#: home-manager/home-manager:237 +msgid "" +"There is %d unread and relevant news item.\n" +"Read it by running the command \"%s news\"." +msgid_plural "" +"There are %d unread and relevant news items.\n" +"Read them by running the command \"%s news\"." +msgstr[0] "" +"%d tane okunmamış ilgili haber bulunmakta.\n" +"Okumak için \"%s news\"." +msgstr[1] "" +"%d tane okunmamış ilgili haberler bulunmakta.\n" +"Okumak için \"%s news\"." + +#: home-manager/home-manager:251 +msgid "Unknown \"news.display\" setting \"%s\"." +msgstr "Bilinmeyen \"news.display\" seçeneği \"%s\"." + +#: home-manager/home-manager:258 +#, sh-format +msgid "Please set the $EDITOR environment variable" +msgstr "Lütfen $EDITOR ortam değişkenini tanımlayın" + +#: home-manager/home-manager:273 +msgid "Cannot run build in read-only directory" +msgstr "İnşa, sadece okunabilir bir klasörde çalıştırılamaz" + +#: home-manager/home-manager:355 +msgid "No generation with ID %s" +msgstr "%s ID'sine sahip inşa bulunamadı" + +#: home-manager/home-manager:357 +msgid "Cannot remove the current generation %s" +msgstr "Kullanımda olan %s inşası silinemez" + +#: home-manager/home-manager:359 +msgid "Removing generation %s" +msgstr "İnşa siliniyor %s" + +#: home-manager/home-manager:385 +msgid "No generations to expire" +msgstr "Süresi dolacak inşa yok" + +#: home-manager/home-manager:396 +msgid "No home-manager packages seem to be installed." +msgstr "Galiba home-manager paketi kurulu değil." + +#: home-manager/home-manager:453 +msgid "Unknown argument %s" +msgstr "Bilinmeyen argüman %s" + +#: home-manager/home-manager:469 +msgid "This will remove Home Manager from your system." +msgstr "Bu, sisteminizden Home Manager'ı kaldıracak." + +#: home-manager/home-manager:472 +msgid "This is a dry run, nothing will actually be uninstalled." +msgstr "Bu sadece bir inşa denemesi, hiçbir şey silinmeyecek." + +#: home-manager/home-manager:476 +msgid "Really uninstall Home Manager?" +msgstr "Home Manager'ı silmek istediğinize emin misiniz?" + +#: home-manager/home-manager:481 +msgid "Switching to empty Home Manager configuration..." +msgstr "Boş Home Manager yapılandırmasına geçiliyor..." + +#: home-manager/home-manager:493 +msgid "Yay!" +msgstr "Güzel!" + +#: home-manager/home-manager:500 +msgid "Remove all Home Manager generations?" +msgstr "Tüm Home Manager inşaları kaldırılsın mı?" + +#: home-manager/home-manager:507 +msgid "All generations are now eligible for garbage collection." +msgstr "Artık tüm inşalar çöp olarak toplanabilir." + +#: home-manager/home-manager:510 +msgid "Leaving generations but they may still be garbage collected." +msgstr "İnşalar yine de çöp olarak toplanabilir." + +#: home-manager/home-manager:514 +msgid "Home Manager is uninstalled but your home.nix is left untouched." +msgstr "Home Manager kaldırıldı ama home.nix dosyasına dokunulmadı." + +#: home-manager/home-manager:673 +msgid "%s: unknown option '%s'" +msgstr "%s: Bilinmeyen komut '%s'" + +#: home-manager/home-manager:674 +msgid "Run '%s --help' for usage help" +msgstr "Yardım için '%s --help'" + +#: home-manager/home-manager:708 +msgid "expire-generations expects one argument, got %d." +msgstr "expire-generations bir argüman istiyor, %d tane girildi." + +#: home-manager/home-manager:730 +msgid "Unknown command: %s" +msgstr "Bilinmeyen komut: %s" + +#: home-manager/install.nix:22 +msgid "Creating initial Home Manager configuration..." +msgstr "İlk Home Manager yapılandırması oluşturuluyor..." + +#: home-manager/install.nix:66 +msgid "Creating initial Home Manager generation..." +msgstr "İlk Home Manager inşası oluşturuluyor..." + +#. translators: The "%s" specifier will be replaced by a file path. +#: home-manager/install.nix:71 +msgid "" +"All done! The home-manager tool should now be installed and you can edit\n" +"\n" +" %s\n" +"\n" +"to configure Home Manager. Run 'man home-configuration.nix' to\n" +"see all available options." +msgstr "" +"Herşey tamam! home-manager aracı kuruldu. Home Manager'ı yapılandırmak için\n" +"\n" +" %s\n" +"\n" +"dosyasını düzenleyin. Kullanılabilir seçenekleri görmek için:\n" +"'man home-configuration.nix'." + +#. translators: The "%s" specifier will be replaced by a URL. +#: home-manager/install.nix:76 +msgid "" +"Uh oh, the installation failed! Please create an issue at\n" +"\n" +" %s\n" +"\n" +"if the error seems to be the fault of Home Manager." +msgstr "" +"Eyvah, kurulum başarısız! Eğer hatanın Home Manager'dan kaynaklandığını " +"düşünüyorsanız\n" +"\n" +" %s\n" +"\n" +"adresinden bildirin." + +#: home-manager/install.nix:83 +msgid "This derivation is not buildable, please run it using nix-shell." +msgstr "" +"Bu türetim inşa edilebilir değil, lütfen onu nix-shell kullanarak çalıştırın." diff --git a/infra/libkookie/home-manager-stable/home-manager/po/zh_Hans.po b/infra/libkookie/home-manager-stable/home-manager/po/zh_Hans.po new file mode 100644 index 00000000000..b3de7b2b73a --- /dev/null +++ b/infra/libkookie/home-manager-stable/home-manager/po/zh_Hans.po @@ -0,0 +1,180 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Home Manager contributors +# This file is distributed under the same license as the Home Manager package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: Home Manager\n" +"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" +"POT-Creation-Date: 2022-03-26 15:08+0100\n" +"PO-Revision-Date: 2021-12-28 12:41+0000\n" +"Last-Translator: WhiredPlanck \n" +"Language-Team: Chinese (Simplified) \n" +"Language: zh_Hans\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 4.10.1\n" + +#: home-manager/home-manager:60 +msgid "No configuration file found at %s" +msgstr "未在 %s 找到配置文件" + +#: home-manager/home-manager:79 +msgid "No configuration file found. Please create one at %s" +msgstr "未找到配置文件。请在 %s 处创建一份" + +#: home-manager/home-manager:122 +msgid "Can't inspect options of a flake configuration" +msgstr "无法检查 flake 配置中的选项" + +#: home-manager/home-manager:162 +msgid "Can't instantiate a flake configuration" +msgstr "无法创建 flake 配置实例" + +#: home-manager/home-manager:237 +msgid "" +"There is %d unread and relevant news item.\n" +"Read it by running the command \"%s news\"." +msgid_plural "" +"There are %d unread and relevant news items.\n" +"Read them by running the command \"%s news\"." +msgstr[0] "" +"有 %d 条未读的相关新闻或消息。\n" +"可运行 “%s news” 命令进行阅读。" + +#: home-manager/home-manager:251 +msgid "Unknown \"news.display\" setting \"%s\"." +msgstr "未知的 “news.display” 设置项 “%s”。" + +#: home-manager/home-manager:258 +#, sh-format +msgid "Please set the $EDITOR environment variable" +msgstr "请设定 $EDITOR 环境变量" + +#: home-manager/home-manager:273 +msgid "Cannot run build in read-only directory" +msgstr "无法在只读目录中运行构建" + +#: home-manager/home-manager:355 +msgid "No generation with ID %s" +msgstr "没有 ID 为 %s 的世代" + +#: home-manager/home-manager:357 +msgid "Cannot remove the current generation %s" +msgstr "无法移除当前世代 %s" + +#: home-manager/home-manager:359 +msgid "Removing generation %s" +msgstr "正在移除世代 %s" + +#: home-manager/home-manager:385 +msgid "No generations to expire" +msgstr "没有即将过期的世代" + +#: home-manager/home-manager:396 +msgid "No home-manager packages seem to be installed." +msgstr "似乎没有安装 home-manager 软件包。" + +#: home-manager/home-manager:453 +msgid "Unknown argument %s" +msgstr "未知参数 %s" + +#: home-manager/home-manager:469 +msgid "This will remove Home Manager from your system." +msgstr "这将会从系统中移除 Home Manager。" + +#: home-manager/home-manager:472 +msgid "This is a dry run, nothing will actually be uninstalled." +msgstr "这是试运行结果,没有实际卸载任何软件包。" + +#: home-manager/home-manager:476 +msgid "Really uninstall Home Manager?" +msgstr "确定要卸载 Home Manager 吗?" + +#: home-manager/home-manager:481 +msgid "Switching to empty Home Manager configuration..." +msgstr "正在切换至空的 Home Manager 配置 ..." + +#: home-manager/home-manager:493 +msgid "Yay!" +msgstr "好耶!" + +#: home-manager/home-manager:500 +msgid "Remove all Home Manager generations?" +msgstr "要移除所有 Home Manager 配置世代吗?" + +#: home-manager/home-manager:507 +msgid "All generations are now eligible for garbage collection." +msgstr "所有世代现在均符合垃圾回收的条件。" + +#: home-manager/home-manager:510 +msgid "Leaving generations but they may still be garbage collected." +msgstr "保留世代,但它们仍然可能被垃圾回收。" + +#: home-manager/home-manager:514 +msgid "Home Manager is uninstalled but your home.nix is left untouched." +msgstr "Home Manager 已卸载,但未改动您的 home.nix 配置文件。" + +#: home-manager/home-manager:673 +msgid "%s: unknown option '%s'" +msgstr "%s:未知选项 ‘%s’" + +#: home-manager/home-manager:674 +msgid "Run '%s --help' for usage help" +msgstr "运行 ‘%s --help’ 获取用法帮助" + +#: home-manager/home-manager:708 +msgid "expire-generations expects one argument, got %d." +msgstr "expire-generations 须要一个参数,但获取到了 %d 个。" + +#: home-manager/home-manager:730 +msgid "Unknown command: %s" +msgstr "未知命令:%s" + +#: home-manager/install.nix:22 +msgid "Creating initial Home Manager configuration..." +msgstr "正在创建初始 Home Manager 配置 ..." + +#: home-manager/install.nix:66 +msgid "Creating initial Home Manager generation..." +msgstr "正在创建初始 Home Manager 世代 ..." + +#. translators: The "%s" specifier will be replaced by a file path. +#: home-manager/install.nix:71 +msgid "" +"All done! The home-manager tool should now be installed and you can edit\n" +"\n" +" %s\n" +"\n" +"to configure Home Manager. Run 'man home-configuration.nix' to\n" +"see all available options." +msgstr "" +"全部工作完成了!home-manager 工具现应已安装,您可以编辑\n" +"\n" +" %s\n" +"\n" +"来配置 Home Manager。运行 ‘man home-configuration.nix’\n" +"来查看所有可用选项。" + +#. translators: The "%s" specifier will be replaced by a URL. +#: home-manager/install.nix:76 +msgid "" +"Uh oh, the installation failed! Please create an issue at\n" +"\n" +" %s\n" +"\n" +"if the error seems to be the fault of Home Manager." +msgstr "" +"啊哦,安装失败了!如果感觉是 Home Manager 造成的错误,请在下方\n" +"\n" +" %s\n" +"\n" +"处创建 Issue 告知我们。" + +#: home-manager/install.nix:83 +msgid "This derivation is not buildable, please run it using nix-shell." +msgstr "此配置文件/变体不可构建,请在 nix-shell 中运行它。" diff --git a/infra/libkookie/home-manager-stable/home-manager/po/zh_Hant.po b/infra/libkookie/home-manager-stable/home-manager/po/zh_Hant.po new file mode 100644 index 00000000000..917f053e9cd --- /dev/null +++ b/infra/libkookie/home-manager-stable/home-manager/po/zh_Hant.po @@ -0,0 +1,180 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Home Manager contributors +# This file is distributed under the same license as the Home Manager package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: Home Manager\n" +"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" +"POT-Creation-Date: 2022-03-26 15:08+0100\n" +"PO-Revision-Date: 2021-12-29 08:48+0000\n" +"Last-Translator: WhiredPlanck \n" +"Language-Team: Chinese (Traditional) \n" +"Language: zh_Hant\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 4.10.1\n" + +#: home-manager/home-manager:60 +msgid "No configuration file found at %s" +msgstr "未在 %s 處找到配置檔案" + +#: home-manager/home-manager:79 +msgid "No configuration file found. Please create one at %s" +msgstr "未找到配置檔案。請在 %s 處建立一份" + +#: home-manager/home-manager:122 +msgid "Can't inspect options of a flake configuration" +msgstr "無法檢查 flake 配置中的選項" + +#: home-manager/home-manager:162 +msgid "Can't instantiate a flake configuration" +msgstr "無法建立 flake 配置例項" + +#: home-manager/home-manager:237 +msgid "" +"There is %d unread and relevant news item.\n" +"Read it by running the command \"%s news\"." +msgid_plural "" +"There are %d unread and relevant news items.\n" +"Read them by running the command \"%s news\"." +msgstr[0] "" +"有 %d 條未讀的相關新聞或訊息。\n" +"可執行 “%s news” 命令進行閱讀。" + +#: home-manager/home-manager:251 +msgid "Unknown \"news.display\" setting \"%s\"." +msgstr "未知的 “news.display” 設定項 “%s”。" + +#: home-manager/home-manager:258 +#, sh-format +msgid "Please set the $EDITOR environment variable" +msgstr "請設定 $EDITOR 環境變數" + +#: home-manager/home-manager:273 +msgid "Cannot run build in read-only directory" +msgstr "無法在只讀目錄中執行構建" + +#: home-manager/home-manager:355 +msgid "No generation with ID %s" +msgstr "沒有 ID 為 %s 的世代" + +#: home-manager/home-manager:357 +msgid "Cannot remove the current generation %s" +msgstr "無法移除當前世代 %s" + +#: home-manager/home-manager:359 +msgid "Removing generation %s" +msgstr "正在移除世代 %s" + +#: home-manager/home-manager:385 +msgid "No generations to expire" +msgstr "沒有即將過期的世代" + +#: home-manager/home-manager:396 +msgid "No home-manager packages seem to be installed." +msgstr "似乎沒有安裝 home-manager 軟體包。" + +#: home-manager/home-manager:453 +msgid "Unknown argument %s" +msgstr "未知引數 %s" + +#: home-manager/home-manager:469 +msgid "This will remove Home Manager from your system." +msgstr "這將會從系統中移除 Home Manager。" + +#: home-manager/home-manager:472 +msgid "This is a dry run, nothing will actually be uninstalled." +msgstr "這是試執行結果,沒有實際解除安裝任何軟體包。" + +#: home-manager/home-manager:476 +msgid "Really uninstall Home Manager?" +msgstr "確定要解除安裝 Home Manager 嗎?" + +#: home-manager/home-manager:481 +msgid "Switching to empty Home Manager configuration..." +msgstr "正在切換至空的 Home Manager 配置 ..." + +#: home-manager/home-manager:493 +msgid "Yay!" +msgstr "好耶!" + +#: home-manager/home-manager:500 +msgid "Remove all Home Manager generations?" +msgstr "要移除所有 Home Manager 配置世代嗎?" + +#: home-manager/home-manager:507 +msgid "All generations are now eligible for garbage collection." +msgstr "所有世代現在均符合垃圾回收的條件。" + +#: home-manager/home-manager:510 +msgid "Leaving generations but they may still be garbage collected." +msgstr "保留世代,但它們仍然可能被垃圾回收。" + +#: home-manager/home-manager:514 +msgid "Home Manager is uninstalled but your home.nix is left untouched." +msgstr "Home Manager 已解除安裝,但未改動您的 home.nix 配置檔案。" + +#: home-manager/home-manager:673 +msgid "%s: unknown option '%s'" +msgstr "%s:未知選項 ‘%s’" + +#: home-manager/home-manager:674 +msgid "Run '%s --help' for usage help" +msgstr "執行 ‘%s --help’ 獲取用法幫助" + +#: home-manager/home-manager:708 +msgid "expire-generations expects one argument, got %d." +msgstr "expire-generations 須要一個引數,但獲取到了 %d 個。" + +#: home-manager/home-manager:730 +msgid "Unknown command: %s" +msgstr "未知命令:%s" + +#: home-manager/install.nix:22 +msgid "Creating initial Home Manager configuration..." +msgstr "正在建立初始 Home Manager 配置 ..." + +#: home-manager/install.nix:66 +msgid "Creating initial Home Manager generation..." +msgstr "正在建立初始 Home Manager 世代 ..." + +#. translators: The "%s" specifier will be replaced by a file path. +#: home-manager/install.nix:71 +msgid "" +"All done! The home-manager tool should now be installed and you can edit\n" +"\n" +" %s\n" +"\n" +"to configure Home Manager. Run 'man home-configuration.nix' to\n" +"see all available options." +msgstr "" +"全部工作完成了!home-manager 工具現應已安裝,您可以編輯\n" +"\n" +" %s\n" +"\n" +"來配置 Home Manager。執行 ‘man home-configuration.nix’\n" +"來檢視所有可用選項。" + +#. translators: The "%s" specifier will be replaced by a URL. +#: home-manager/install.nix:76 +msgid "" +"Uh oh, the installation failed! Please create an issue at\n" +"\n" +" %s\n" +"\n" +"if the error seems to be the fault of Home Manager." +msgstr "" +"啊哦,安裝失敗了!如果感覺是 Home Manager 造成的錯誤,請在下方\n" +"\n" +" %s\n" +"\n" +"處建立 Issue 告知我們。" + +#: home-manager/install.nix:83 +msgid "This derivation is not buildable, please run it using nix-shell." +msgstr "此配置檔案/變體不可構建,請在 nix-shell 中執行它。" diff --git a/infra/libkookie/home-manager-stable/lib/bash/color-echo b/infra/libkookie/home-manager-stable/lib/bash/color-echo new file mode 100644 index 00000000000..c16381807f6 --- /dev/null +++ b/infra/libkookie/home-manager-stable/lib/bash/color-echo @@ -0,0 +1,41 @@ +#!/usr/bin/env bash + +# The check for terminal output and color support is heavily inspired +# by https://unix.stackexchange.com/a/10065. +# +# Allow opt out by respecting the `NO_COLOR` environment variable. + +function setupColors() { + normalColor="" + errorColor="" + warnColor="" + noteColor="" + + # Enable colors for terminals, and allow opting out. + if [[ ! -v NO_COLOR && -t 1 ]]; then + # See if it supports colors. + local ncolors + ncolors=$(tput colors) + + if [[ -n "$ncolors" && "$ncolors" -ge 8 ]]; then + normalColor="$(tput sgr0)" + errorColor="$(tput bold)$(tput setaf 1)" + warnColor="$(tput setaf 3)" + noteColor="$(tput bold)$(tput setaf 6)" + fi + fi +} + +setupColors + +function errorEcho() { + echo "${errorColor}$*${normalColor}" +} + +function warnEcho() { + echo "${warnColor}$*${normalColor}" +} + +function noteEcho() { + echo "${noteColor}$*${normalColor}" +} diff --git a/infra/libkookie/home-manager-stable/lib/bash/home-manager.sh b/infra/libkookie/home-manager-stable/lib/bash/home-manager.sh new file mode 100644 index 00000000000..c7ff5c34469 --- /dev/null +++ b/infra/libkookie/home-manager-stable/lib/bash/home-manager.sh @@ -0,0 +1,85 @@ +#!/usr/bin/env bash + +# +# This file contains a number of utilities for use by the home-manager tool and +# the generated Home Manager activation scripts. No guarantee is made about +# backwards or forward compatibility. +# + +# Sets up colors suitable for the `errorEcho`, `warnEcho`, and `noteEcho` +# functions. +# +# The check for terminal output and color support is heavily inspired by +# https://unix.stackexchange.com/a/10065. +# +# The setup respects the `NO_COLOR` environment variable. +function setupColors() { + normalColor="" + errorColor="" + warnColor="" + noteColor="" + + # Enable colors for terminals, and allow opting out. + if [[ ! -v NO_COLOR && -t 1 ]]; then + # See if it supports colors. + local ncolors + ncolors=$(tput colors) + + if [[ -n "$ncolors" && "$ncolors" -ge 8 ]]; then + normalColor="$(tput sgr0)" + errorColor="$(tput bold)$(tput setaf 1)" + warnColor="$(tput setaf 3)" + noteColor="$(tput bold)$(tput setaf 6)" + fi + fi +} + +setupColors + +function errorEcho() { + echo "${errorColor}$*${normalColor}" +} + +function warnEcho() { + echo "${warnColor}$*${normalColor}" +} + +function noteEcho() { + echo "${noteColor}$*${normalColor}" +} + +function _i() { + local msgid="$1" + shift + + # shellcheck disable=2059 + printf "$(gettext "$msgid")\n" "$@" +} + +function _ip() { + local msgid="$1" + local msgidPlural="$2" + local count="$3" + shift 3 + + # shellcheck disable=2059 + printf "$(ngettext "$msgid" "$msgidPlural" "$count")\n" "$@" +} + +function _iError() { + echo -n "${errorColor}" + _i "$@" + echo -n "${normalColor}" +} + +function _iWarn() { + echo -n "${warnColor}" + _i "$@" + echo -n "${normalColor}" +} + +function _iNote() { + echo -n "${noteColor}" + _i "$@" + echo -n "${normalColor}" +} diff --git a/infra/libkookie/home-manager-stable/modules/accounts/email.nix b/infra/libkookie/home-manager-stable/modules/accounts/email.nix new file mode 100644 index 00000000000..72eb538b2ba --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/accounts/email.nix @@ -0,0 +1,418 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.accounts.email; + + gpgModule = types.submodule { + options = { + key = mkOption { + type = types.str; + description = '' + The key to use as listed in gpg --list-keys. + ''; + }; + + signByDefault = mkOption { + type = types.bool; + default = false; + description = "Sign messages by default."; + }; + + encryptByDefault = mkOption { + type = types.bool; + default = false; + description = "Encrypt outgoing messages by default."; + }; + }; + }; + + signatureModule = types.submodule { + options = { + text = mkOption { + type = types.str; + default = ""; + example = '' + -- + Luke Skywalker + May the force be with you. + ''; + description = '' + Signature content. + ''; + }; + + command = mkOption { + type = with types; nullOr path; + default = null; + example = literalExpression '' + pkgs.writeScript "signature" "echo This is my signature" + ''; + description = "A command that generates a signature."; + }; + + showSignature = mkOption { + type = types.enum [ "append" "attach" "none" ]; + default = "none"; + description = "Method to communicate the signature."; + }; + }; + }; + + tlsModule = types.submodule { + options = { + enable = mkOption { + type = types.bool; + default = true; + description = '' + Whether to enable TLS/SSL. + ''; + }; + + useStartTls = mkOption { + type = types.bool; + default = false; + description = '' + Whether to use STARTTLS. + ''; + }; + + certificatesFile = mkOption { + type = types.nullOr types.path; + default = config.accounts.email.certificatesFile; + defaultText = "config.accounts.email.certificatesFile"; + description = '' + Path to file containing certificate authorities that should + be used to validate the connection authenticity. If + null then the system default is used. + Note, if set then the system default may still be accepted. + ''; + }; + }; + }; + + imapModule = types.submodule { + options = { + host = mkOption { + type = types.str; + example = "imap.example.org"; + description = '' + Hostname of IMAP server. + ''; + }; + + port = mkOption { + type = types.nullOr types.port; + default = null; + example = 993; + description = '' + The port on which the IMAP server listens. If + null then the default port is used. + ''; + }; + + tls = mkOption { + type = tlsModule; + default = { }; + description = '' + Configuration for secure connections. + ''; + }; + }; + }; + + smtpModule = types.submodule { + options = { + host = mkOption { + type = types.str; + example = "smtp.example.org"; + description = '' + Hostname of SMTP server. + ''; + }; + + port = mkOption { + type = types.nullOr types.port; + default = null; + example = 465; + description = '' + The port on which the SMTP server listens. If + null then the default port is used. + ''; + }; + + tls = mkOption { + type = tlsModule; + default = { }; + description = '' + Configuration for secure connections. + ''; + }; + }; + }; + + maildirModule = types.submodule ({ config, ... }: { + options = { + path = mkOption { + type = types.str; + description = '' + Path to maildir directory where mail for this account is + stored. This is relative to the base maildir path. + ''; + }; + + absPath = mkOption { + type = types.path; + readOnly = true; + internal = true; + default = "${cfg.maildirBasePath}/${config.path}"; + description = '' + A convenience option whose value is the absolute path of + this maildir. + ''; + }; + }; + }); + + mailAccountOpts = { name, config, ... }: { + options = { + name = mkOption { + type = types.str; + readOnly = true; + description = '' + Unique identifier of the account. This is set to the + attribute name of the account configuration. + ''; + }; + + primary = mkOption { + type = types.bool; + default = false; + description = '' + Whether this is the primary account. Only one account may be + set as primary. + ''; + }; + + flavor = mkOption { + type = types.enum [ "plain" "gmail.com" "runbox.com" "fastmail.com" ]; + default = "plain"; + description = '' + Some email providers have peculiar behavior that require + special treatment. This option is therefore intended to + indicate the nature of the provider. + + When this indicates a specific provider then, for example, + the IMAP and SMTP server configuration may be set + automatically. + ''; + }; + + address = mkOption { + type = types.strMatching ".*@.*"; + example = "jane.doe@example.org"; + description = "The email address of this account."; + }; + + aliases = mkOption { + type = types.listOf (types.strMatching ".*@.*"); + default = [ ]; + example = [ "webmaster@example.org" "admin@example.org" ]; + description = "Alternative email addresses of this account."; + }; + + realName = mkOption { + type = types.str; + example = "Jane Doe"; + description = "Name displayed when sending mails."; + }; + + userName = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + The server username of this account. This will be used as + the SMTP and IMAP user name. + ''; + }; + + passwordCommand = mkOption { + type = types.nullOr (types.either types.str (types.listOf types.str)); + default = null; + apply = p: if isString p then splitString " " p else p; + example = "secret-tool lookup email me@example.org"; + description = '' + A command, which when run writes the account password on + standard output. + ''; + }; + + folders = mkOption { + type = types.submodule { + options = { + inbox = mkOption { + type = types.str; + default = "Inbox"; + description = '' + Relative path of the inbox mail. + ''; + }; + + sent = mkOption { + type = types.nullOr types.str; + default = "Sent"; + description = '' + Relative path of the sent mail folder. + ''; + }; + + drafts = mkOption { + type = types.str; + default = "Drafts"; + description = '' + Relative path of the drafts mail folder. + ''; + }; + + trash = mkOption { + type = types.str; + default = "Trash"; + description = '' + Relative path of the deleted mail folder. + ''; + }; + }; + }; + default = { }; + description = '' + Standard email folders. + ''; + }; + + imap = mkOption { + type = types.nullOr imapModule; + default = null; + description = '' + The IMAP configuration to use for this account. + ''; + }; + + signature = mkOption { + type = signatureModule; + default = { }; + description = '' + Signature configuration. + ''; + }; + + gpg = mkOption { + type = types.nullOr gpgModule; + default = null; + description = '' + GPG configuration. + ''; + }; + + smtp = mkOption { + type = types.nullOr smtpModule; + default = null; + description = '' + The SMTP configuration to use for this account. + ''; + }; + + maildir = mkOption { + type = types.nullOr maildirModule; + defaultText = { path = "\${name}"; }; + description = '' + Maildir configuration for this account. + ''; + }; + }; + + config = mkMerge [ + { + name = name; + maildir = mkOptionDefault { path = "${name}"; }; + } + (mkIf (config.flavor == "fastmail.com") { + userName = mkDefault config.address; + smtp = { + host = "smtp.fastmail.com"; + port = if config.smtp.tls.useStartTls then 587 else 465; + }; + imap = { + host = "imap.fastmail.com"; + port = 993; + }; + }) + (mkIf (config.flavor == "gmail.com") { + userName = mkDefault config.address; + + imap = { + host = "imap.gmail.com"; + port = 993; + }; + + smtp = { + host = "smtp.gmail.com"; + port = if config.smtp.tls.useStartTls then 587 else 465; + }; + }) + + (mkIf (config.flavor == "runbox.com") { + imap = { host = "mail.runbox.com"; }; + + smtp = { host = "mail.runbox.com"; }; + }) + ]; + }; + +in { + options.accounts.email = { + certificatesFile = mkOption { + type = types.nullOr types.path; + default = "/etc/ssl/certs/ca-certificates.crt"; + description = '' + Path to default file containing certificate authorities that + should be used to validate the connection authenticity. This + path may be overridden on a per-account basis. + ''; + }; + + maildirBasePath = mkOption { + type = types.str; + default = "${config.home.homeDirectory}/Maildir"; + defaultText = "$HOME/Maildir"; + apply = p: + if hasPrefix "/" p then p else "${config.home.homeDirectory}/${p}"; + description = '' + The base directory for account maildir directories. May be a + relative path, in which case it is relative the home + directory. + ''; + }; + + accounts = mkOption { + type = types.attrsOf (types.submodule mailAccountOpts); + default = { }; + description = "List of email accounts."; + }; + }; + + config = mkIf (cfg.accounts != { }) { + assertions = [ + (let + primaries = + catAttrs "name" (filter (a: a.primary) (attrValues cfg.accounts)); + in { + assertion = length primaries == 1; + message = "Must have exactly one primary mail account but found " + + toString (length primaries) + optionalString (length primaries > 1) + (", namely " + concatStringsSep ", " primaries); + }) + ]; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/config/home-cursor.nix b/infra/libkookie/home-manager-stable/modules/config/home-cursor.nix new file mode 100644 index 00000000000..e2d26a5ba23 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/config/home-cursor.nix @@ -0,0 +1,156 @@ +{ config, options, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.home.pointerCursor; + + pointerCursorModule = types.submodule { + options = { + package = mkOption { + type = types.package; + example = literalExpression "pkgs.vanilla-dmz"; + description = "Package providing the cursor theme."; + }; + + name = mkOption { + type = types.str; + example = "Vanilla-DMZ"; + description = "The cursor name within the package."; + }; + + size = mkOption { + type = types.int; + default = 32; + example = 64; + description = "The cursor size."; + }; + + x11 = { + enable = mkEnableOption '' + x11 config generation for + ''; + + defaultCursor = mkOption { + type = types.str; + default = "left_ptr"; + example = "X_cursor"; + description = "The default cursor file to use within the package."; + }; + }; + + gtk = { + enable = mkEnableOption '' + gtk config generation for + ''; + }; + }; + }; + + cursorPath = "${cfg.package}/share/icons/${escapeShellArg cfg.name}/cursors/${ + escapeShellArg cfg.x11.defaultCursor + }"; + +in { + meta.maintainers = [ maintainers.polykernel maintainers.league ]; + + imports = [ + (mkAliasOptionModule [ "xsession" "pointerCursor" "package" ] [ + "home" + "pointerCursor" + "package" + ]) + (mkAliasOptionModule [ "xsession" "pointerCursor" "name" ] [ + "home" + "pointerCursor" + "name" + ]) + (mkAliasOptionModule [ "xsession" "pointerCursor" "size" ] [ + "home" + "pointerCursor" + "size" + ]) + (mkAliasOptionModule [ "xsession" "pointerCursor" "defaultCursor" ] [ + "home" + "pointerCursor" + "x11" + "defaultCursor" + ]) + + ({ ... }: { + warnings = optional (any (x: + getAttrFromPath + ([ "xsession" "pointerCursor" ] ++ [ x ] ++ [ "isDefined" ]) + options) [ "package" "name" "size" "defaultCursor" ]) '' + The option `xsession.pointerCursor` has been merged into `home.pointerCursor` and will be removed + in the future. Please change to set `home.pointerCursor` directly and enable `home.pointerCursor.x11.enable` + to generate x11 specific cursor configurations. You can refer to the documentation for more details. + ''; + }) + ]; + + options = { + home.pointerCursor = mkOption { + type = types.nullOr pointerCursorModule; + default = null; + description = '' + Cursor configuration. Set to null to disable. + + Top-level options declared under this submodule are backend indepedent + options. Options declared under namespaces such as x11 + are backend specific options. By default, only backend independent cursor + configurations are generated. If you need configurations for specific + backends, you can toggle them via the enable option. For example, + home.pointerCursor.x11.enable + will enable x11 cursor configurations. + ''; + }; + }; + + config = mkIf (cfg != null) (mkMerge [ + { + assertions = [ + (hm.assertions.assertPlatform "home.pointerCursor" pkgs platforms.linux) + ]; + + home.packages = [ cfg.package ]; + + # Set name in icons theme, for compatibility with AwesomeWM etc. See: + # https://github.com/nix-community/home-manager/issues/2081 + # https://wiki.archlinux.org/title/Cursor_themes#XDG_specification + home.file.".icons/default/index.theme".text = '' + [icon theme] + Name=Default + Comment=Default Cursor Theme + Inherits=${cfg.name} + ''; + + # Set directory to look for cursors in, needed for some applications + # that are unable to find cursors otherwise. See: + # https://github.com/nix-community/home-manager/issues/2812 + # https://wiki.archlinux.org/title/Cursor_themes#Environment_variable + home.sessionVariables = { + XCURSOR_PATH = "$XCURSOR_PATH\${XCURSOR_PATH:+:}" + + "${config.home.profileDirectory}/share/icons"; + }; + } + + (mkIf cfg.x11.enable { + xsession.initExtra = '' + ${pkgs.xorg.xsetroot}/bin/xsetroot -xcf ${cursorPath} ${ + toString cfg.size + } + ''; + + xresources.properties = { + "Xcursor.theme" = cfg.name; + "Xcursor.size" = cfg.size; + }; + }) + + (mkIf cfg.gtk.enable { + gtk.cursorTheme = mkDefault { inherit (cfg) package name size; }; + }) + ]); +} diff --git a/infra/libkookie/home-manager-stable/modules/config/i18n.nix b/infra/libkookie/home-manager-stable/modules/config/i18n.nix new file mode 100644 index 00000000000..e9b01b4efd3 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/config/i18n.nix @@ -0,0 +1,46 @@ +# The glibc package in Nixpkgs is patched to make it possible to specify +# an alternative path for the locale archive through a special environment +# variable. This would allow different versions of glibc to coexist on the +# same system because each version of glibc could look up different paths +# for its locale archive should the archive format ever change in +# incompatible ways. +# +# See also: +# - localedef(1) +# - https://nixos.org/manual/nixpkgs/stable/#locales +# - https://github.com/NixOS/nixpkgs/issues/38991 +# +# Note, the name of the said environment variable gets updated with each +# breaking release of the glibcLocales package. Periodically check the link +# below for changes: +# https://github.com/NixOS/nixpkgs/blob/nixpkgs-unstable/pkgs/development/libraries/glibc/nix-locale-archive.patch + +{ lib, pkgs, ... }: + +with lib; + +let + + inherit (pkgs.glibcLocales) version; + + archivePath = "${pkgs.glibcLocales}/lib/locale/locale-archive"; + + # lookup the version of glibcLocales and set the appropriate environment vars + localeVars = if versionAtLeast version "2.27" then { + LOCALE_ARCHIVE_2_27 = archivePath; + } else if versionAtLeast version "2.11" then { + LOCALE_ARCHIVE_2_11 = archivePath; + } else + { }; + +in { + meta.maintainers = with maintainers; [ midchildan ]; + + config = mkIf pkgs.stdenv.hostPlatform.isLinux { + # For shell sessions. + home.sessionVariables = localeVars; + + # For desktop apps. + systemd.user.sessionVariables = localeVars; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/default.nix b/infra/libkookie/home-manager-stable/modules/default.nix new file mode 100644 index 00000000000..02be152fdde --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/default.nix @@ -0,0 +1,66 @@ +{ configuration +, pkgs +, lib ? pkgs.lib + + # Whether to check that each option has a matching declaration. +, check ? true + # Extra arguments passed to specialArgs. +, extraSpecialArgs ? { } +}: + +with lib; + +let + + collectFailed = cfg: + map (x: x.message) (filter (x: !x.assertion) cfg.assertions); + + showWarnings = res: + let + f = w: x: builtins.trace "warning: ${w}" x; + in + fold f res res.config.warnings; + + extendedLib = import ./lib/stdlib-extended.nix lib; + + hmModules = + import ./modules.nix { + inherit check pkgs; + lib = extendedLib; + }; + + rawModule = extendedLib.evalModules { + modules = [ configuration ] ++ hmModules; + specialArgs = { + modulesPath = builtins.toString ./.; + } // extraSpecialArgs; + }; + + module = showWarnings ( + let + failed = collectFailed rawModule.config; + failedStr = concatStringsSep "\n" (map (x: "- ${x}") failed); + in + if failed == [] + then rawModule + else throw "\nFailed assertions:\n${failedStr}" + ); + +in + +{ + inherit (module) options config; + + activationPackage = module.config.home.activationPackage; + + # For backwards compatibility. Please use activationPackage instead. + activation-script = module.config.home.activationPackage; + + newsDisplay = rawModule.config.news.display; + newsEntries = + sort (a: b: a.time > b.time) ( + filter (a: a.condition) rawModule.config.news.entries + ); + + inherit (module._module.args) pkgs; +} diff --git a/infra/libkookie/home-manager-stable/modules/files.nix b/infra/libkookie/home-manager-stable/modules/files.nix new file mode 100644 index 00000000000..a7fd67f57a0 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/files.nix @@ -0,0 +1,405 @@ +{ pkgs, config, lib, ... }: + +with lib; + +let + + cfg = config.home.file; + + homeDirectory = config.home.homeDirectory; + + fileType = (import lib/file-type.nix { + inherit homeDirectory lib pkgs; + }).fileType; + + sourceStorePath = file: + let + sourcePath = toString file.source; + sourceName = config.lib.strings.storeFileName (baseNameOf sourcePath); + in + if builtins.hasContext sourcePath + then file.source + else builtins.path { path = file.source; name = sourceName; }; + +in + +{ + options = { + home.file = mkOption { + description = "Attribute set of files to link into the user home."; + default = {}; + type = fileType "HOME" homeDirectory; + }; + + home-files = mkOption { + type = types.package; + internal = true; + description = "Package to contain all home files"; + }; + }; + + config = { + assertions = [( + let + dups = + attrNames + (filterAttrs (n: v: v > 1) + (foldAttrs (acc: v: acc + v) 0 + (mapAttrsToList (n: v: { ${v.target} = 1; }) cfg))); + dupsStr = concatStringsSep ", " dups; + in { + assertion = dups == []; + message = '' + Conflicting managed target files: ${dupsStr} + + This may happen, for example, if you have a configuration similar to + + home.file = { + conflict1 = { source = ./foo.nix; target = "baz"; }; + conflict2 = { source = ./bar.nix; target = "baz"; }; + }''; + }) + ]; + + lib.file.mkOutOfStoreSymlink = path: + let + pathStr = toString path; + name = hm.strings.storeFileName (baseNameOf pathStr); + in + pkgs.runCommandLocal name {} ''ln -s ${escapeShellArg pathStr} $out''; + + # This verifies that the links we are about to create will not + # overwrite an existing file. + home.activation.checkLinkTargets = hm.dag.entryBefore ["writeBoundary"] ( + let + # Paths that should be forcibly overwritten by Home Manager. + # Caveat emptor! + forcedPaths = + concatMapStringsSep " " (p: ''"$HOME"/${escapeShellArg p}'') + (mapAttrsToList (n: v: v.target) + (filterAttrs (n: v: v.force) cfg)); + + check = pkgs.writeText "check" '' + ${config.lib.bash.initHomeManagerLib} + + # A symbolic link whose target path matches this pattern will be + # considered part of a Home Manager generation. + homeFilePattern="$(readlink -e ${escapeShellArg builtins.storeDir})/*-home-manager-files/*" + + forcedPaths=(${forcedPaths}) + + newGenFiles="$1" + shift + for sourcePath in "$@" ; do + relativePath="''${sourcePath#$newGenFiles/}" + targetPath="$HOME/$relativePath" + + forced="" + for forcedPath in "''${forcedPaths[@]}"; do + if [[ $targetPath == $forcedPath* ]]; then + forced="yeah" + break + fi + done + + if [[ -n $forced ]]; then + $VERBOSE_ECHO "Skipping collision check for $targetPath" + elif [[ -e "$targetPath" \ + && ! "$(readlink "$targetPath")" == $homeFilePattern ]] ; then + # The target file already exists and it isn't a symlink owned by Home Manager. + if cmp -s "$sourcePath" "$targetPath"; then + # First compare the files' content. If they're equal, we're fine. + warnEcho "Existing file '$targetPath' is in the way of '$sourcePath', will be skipped since they are the same" + elif [[ ! -L "$targetPath" && -n "$HOME_MANAGER_BACKUP_EXT" ]] ; then + # Next, try to move the file to a backup location if configured and possible + backup="$targetPath.$HOME_MANAGER_BACKUP_EXT" + if [[ -e "$backup" ]]; then + errorEcho "Existing file '$backup' would be clobbered by backing up '$targetPath'" + collision=1 + else + warnEcho "Existing file '$targetPath' is in the way of '$sourcePath', will be moved to '$backup'" + fi + else + # Fail if nothing else works + errorEcho "Existing file '$targetPath' is in the way of '$sourcePath'" + collision=1 + fi + fi + done + + if [[ -v collision ]] ; then + errorEcho "Please move the above files and try again or use 'home-manager switch -b backup' to back up existing files automatically." + exit 1 + fi + ''; + in + '' + function checkNewGenCollision() { + local newGenFiles + newGenFiles="$(readlink -e "$newGenPath/home-files")" + find "$newGenFiles" \( -type f -or -type l \) \ + -exec bash ${check} "$newGenFiles" {} + + } + + checkNewGenCollision || exit 1 + '' + ); + + # This activation script will + # + # 1. Remove files from the old generation that are not in the new + # generation. + # + # 2. Switch over the Home Manager gcroot and current profile + # links. + # + # 3. Symlink files from the new generation into $HOME. + # + # This order is needed to ensure that we always know which links + # belong to which generation. Specifically, if we're moving from + # generation A to generation B having sets of home file links FA + # and FB, respectively then cleaning before linking produces state + # transitions similar to + # + # FA → FA ∩ FB → (FA ∩ FB) ∪ FB = FB + # + # and a failure during the intermediate state FA ∩ FB will not + # result in lost links because this set of links are in both the + # source and target generation. + home.activation.linkGeneration = hm.dag.entryAfter ["writeBoundary"] ( + let + link = pkgs.writeShellScript "link" '' + newGenFiles="$1" + shift + for sourcePath in "$@" ; do + relativePath="''${sourcePath#$newGenFiles/}" + targetPath="$HOME/$relativePath" + if [[ -e "$targetPath" && ! -L "$targetPath" && -n "$HOME_MANAGER_BACKUP_EXT" ]] ; then + # The target exists, back it up + backup="$targetPath.$HOME_MANAGER_BACKUP_EXT" + $DRY_RUN_CMD mv $VERBOSE_ARG "$targetPath" "$backup" || errorEcho "Moving '$targetPath' failed!" + fi + + if [[ -e "$targetPath" && ! -L "$targetPath" ]] && cmp -s "$sourcePath" "$targetPath" ; then + # The target exists but is identical – don't do anything. + $VERBOSE_ECHO "Skipping '$targetPath' as it is identical to '$sourcePath'" + else + # Place that symlink, --force + $DRY_RUN_CMD mkdir -p $VERBOSE_ARG "$(dirname "$targetPath")" + $DRY_RUN_CMD ln -nsf $VERBOSE_ARG "$sourcePath" "$targetPath" + fi + done + ''; + + cleanup = pkgs.writeShellScript "cleanup" '' + ${config.lib.bash.initHomeManagerLib} + + # A symbolic link whose target path matches this pattern will be + # considered part of a Home Manager generation. + homeFilePattern="$(readlink -e ${escapeShellArg builtins.storeDir})/*-home-manager-files/*" + + newGenFiles="$1" + shift 1 + for relativePath in "$@" ; do + targetPath="$HOME/$relativePath" + if [[ -e "$newGenFiles/$relativePath" ]] ; then + $VERBOSE_ECHO "Checking $targetPath: exists" + elif [[ ! "$(readlink "$targetPath")" == $homeFilePattern ]] ; then + warnEcho "Path '$targetPath' does not link into a Home Manager generation. Skipping delete." + else + $VERBOSE_ECHO "Checking $targetPath: gone (deleting)" + $DRY_RUN_CMD rm $VERBOSE_ARG "$targetPath" + + # Recursively delete empty parent directories. + targetDir="$(dirname "$relativePath")" + if [[ "$targetDir" != "." ]] ; then + pushd "$HOME" > /dev/null + + # Call rmdir with a relative path excluding $HOME. + # Otherwise, it might try to delete $HOME and exit + # with a permission error. + $DRY_RUN_CMD rmdir $VERBOSE_ARG \ + -p --ignore-fail-on-non-empty \ + "$targetDir" + + popd > /dev/null + fi + fi + done + ''; + in + '' + function linkNewGen() { + _i "Creating home file links in %s" "$HOME" + + local newGenFiles + newGenFiles="$(readlink -e "$newGenPath/home-files")" + find "$newGenFiles" \( -type f -or -type l \) \ + -exec bash ${link} "$newGenFiles" {} + + } + + function cleanOldGen() { + if [[ ! -v oldGenPath || ! -e "$oldGenPath/home-files" ]] ; then + return + fi + + _i "Cleaning up orphan links from %s" "$HOME" + + local newGenFiles oldGenFiles + newGenFiles="$(readlink -e "$newGenPath/home-files")" + oldGenFiles="$(readlink -e "$oldGenPath/home-files")" + + # Apply the cleanup script on each leaf in the old + # generation. The find command below will print the + # relative path of the entry. + find "$oldGenFiles" '(' -type f -or -type l ')' -printf '%P\0' \ + | xargs -0 bash ${cleanup} "$newGenFiles" + } + + cleanOldGen + + if [[ ! -v oldGenPath || "$oldGenPath" != "$newGenPath" ]] ; then + _i "Creating profile generation %s" $newGenNum + if [[ -e "$genProfilePath"/manifest.json ]] ; then + # Remove all packages from "$genProfilePath" + # `nix profile remove '.*' --profile "$genProfilePath"` was not working, so here is a workaround: + nix profile list --profile "$genProfilePath" \ + | cut -d ' ' -f 4 \ + | xargs -t $DRY_RUN_CMD nix profile remove $VERBOSE_ARG --profile "$genProfilePath" + $DRY_RUN_CMD nix profile install $VERBOSE_ARG --profile "$genProfilePath" "$newGenPath" + else + $DRY_RUN_CMD nix-env $VERBOSE_ARG --profile "$genProfilePath" --set "$newGenPath" + fi + + $DRY_RUN_CMD ln -Tsf $VERBOSE_ARG "$newGenPath" "$newGenGcPath" + else + _i "No change so reusing latest profile generation %s" "$oldGenNum" + fi + + linkNewGen + '' + ); + + home.activation.checkFilesChanged = hm.dag.entryBefore ["linkGeneration"] ( + let + homeDirArg = escapeShellArg homeDirectory; + in '' + function _cmp() { + if [[ -d $1 && -d $2 ]]; then + diff -rq "$1" "$2" &> /dev/null + else + cmp --quiet "$1" "$2" + fi + } + declare -A changedFiles + '' + concatMapStrings (v: + let + sourceArg = escapeShellArg (sourceStorePath v); + targetArg = escapeShellArg v.target; + in '' + _cmp ${sourceArg} ${homeDirArg}/${targetArg} \ + && changedFiles[${targetArg}]=0 \ + || changedFiles[${targetArg}]=1 + '') (filter (v: v.onChange != "") (attrValues cfg)) + + '' + unset -f _cmp + '' + ); + + home.activation.onFilesChange = hm.dag.entryAfter ["linkGeneration"] ( + concatMapStrings (v: '' + if (( ''${changedFiles[${escapeShellArg v.target}]} == 1 )); then + if [[ -v DRY_RUN || -v VERBOSE ]]; then + echo "Running onChange hook for" ${escapeShellArg v.target} + fi + if [[ ! -v DRY_RUN ]]; then + ${v.onChange} + fi + fi + '') (filter (v: v.onChange != "") (attrValues cfg)) + ); + + # Symlink directories and files that have the right execute bit. + # Copy files that need their execute bit changed. + home-files = pkgs.runCommandLocal + "home-manager-files" + { + nativeBuildInputs = [ pkgs.xorg.lndir ]; + } + ('' + mkdir -p $out + + # Needed in case /nix is a symbolic link. + realOut="$(realpath -m "$out")" + + function insertFile() { + local source="$1" + local relTarget="$2" + local executable="$3" + local recursive="$4" + + # If the target already exists then we have a collision. Note, this + # should not happen due to the assertion found in the 'files' module. + # We therefore simply log the conflict and otherwise ignore it, mainly + # to make the `files-target-config` test work as expected. + if [[ -e "$realOut/$relTarget" ]]; then + echo "File conflict for file '$relTarget'" >&2 + return + fi + + # Figure out the real absolute path to the target. + local target + target="$(realpath -m "$realOut/$relTarget")" + + # Target path must be within $HOME. + if [[ ! $target == $realOut* ]] ; then + echo "Error installing file '$relTarget' outside \$HOME" >&2 + exit 1 + fi + + mkdir -p "$(dirname "$target")" + if [[ -d $source ]]; then + if [[ $recursive ]]; then + mkdir -p "$target" + lndir -silent "$source" "$target" + else + ln -s "$source" "$target" + fi + else + [[ -x $source ]] && isExecutable=1 || isExecutable="" + + # Link the file into the home file directory if possible, + # i.e., if the executable bit of the source is the same we + # expect for the target. Otherwise, we copy the file and + # set the executable bit to the expected value. + if [[ $executable == inherit || $isExecutable == $executable ]]; then + ln -s "$source" "$target" + else + cp "$source" "$target" + + if [[ $executable == inherit ]]; then + # Don't change file mode if it should match the source. + : + elif [[ $executable ]]; then + chmod +x "$target" + else + chmod -x "$target" + fi + fi + fi + } + '' + concatStrings ( + mapAttrsToList (n: v: '' + insertFile ${ + escapeShellArgs [ + (sourceStorePath v) + v.target + (if v.executable == null + then "inherit" + else toString v.executable) + (toString v.recursive) + ]} + '') cfg + )); + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/home-environment.nix b/infra/libkookie/home-manager-stable/modules/home-environment.nix new file mode 100644 index 00000000000..b83cf1d1e31 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/home-environment.nix @@ -0,0 +1,715 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + inherit (config.home) stateVersion; + + cfg = config.home; + + languageSubModule = types.submodule { + options = { + base = mkOption { + default = null; + type = types.nullOr types.str; + description = '' + The language to use unless overridden by a more specific option. + ''; + }; + + ctype = mkOption { + default = null; + type = types.nullOr types.str; + description = '' + Character classification category. + ''; + }; + + numeric = mkOption { + default = null; + type = types.nullOr types.str; + description = '' + The language to use for numerical values. + ''; + }; + + time = mkOption { + default = null; + type = types.nullOr types.str; + description = '' + The language to use for formatting times. + ''; + }; + + collate = mkOption { + default = null; + type = types.nullOr types.str; + description = '' + The language to use for collation (alphabetical ordering). + ''; + }; + + monetary = mkOption { + default = null; + type = types.nullOr types.str; + description = '' + The language to use for formatting currencies and money amounts. + ''; + }; + + messages = mkOption { + default = null; + type = types.nullOr types.str; + description = '' + The language to use for messages, application UI languages, etc. + ''; + }; + + paper = mkOption { + default = null; + type = types.nullOr types.str; + description = '' + The language to use for paper sizes. + ''; + }; + + name = mkOption { + default = null; + type = types.nullOr types.str; + description = '' + The language to use for personal names. + ''; + }; + + address = mkOption { + default = null; + type = types.nullOr types.str; + description = '' + The language to use for addresses. + ''; + }; + + telephone = mkOption { + default = null; + type = types.nullOr types.str; + description = '' + The language to use for telephone numbers. + ''; + }; + + measurement = mkOption { + default = null; + type = types.nullOr types.str; + description = '' + The language to use for measurement values. + ''; + }; + + }; + }; + + keyboardSubModule = types.submodule { + options = { + layout = mkOption { + type = with types; nullOr str; + default = + if versionAtLeast config.home.stateVersion "19.09" + then null + else "us"; + defaultText = literalExpression "null"; + description = '' + Keyboard layout. If null, then the system + configuration will be used. + + This defaults to null for state + version ≥ 19.09 and "us" otherwise. + ''; + }; + + model = mkOption { + type = with types; nullOr str; + default = null; + example = "presario"; + description = '' + Keyboard model. + ''; + }; + + options = mkOption { + type = types.listOf types.str; + default = []; + example = ["grp:caps_toggle" "grp_led:scroll"]; + description = '' + X keyboard options; layout switching goes here. + ''; + }; + + variant = mkOption { + type = with types; nullOr str; + default = + if versionAtLeast config.home.stateVersion "19.09" + then null + else ""; + defaultText = literalExpression "null"; + example = "colemak"; + description = '' + X keyboard variant. If null, then the + system configuration will be used. + + This defaults to null for state + version ≥ 19.09 and "" otherwise. + ''; + }; + }; + }; + +in + +{ + meta.maintainers = [ maintainers.rycee ]; + + imports = [ + (mkRemovedOptionModule [ "home" "sessionVariableSetter" ] '' + Session variables are now always set through the shell. This is + done automatically if the shell configuration is managed by Home + Manager. If not, then you must source the + + ~/.nix-profile/etc/profile.d/hm-session-vars.sh + + file yourself. + '') + ]; + + options = { + home.username = mkOption { + type = types.str; + defaultText = literalExpression '' + "$USER" for state version < 20.09, + undefined for state version ≥ 20.09 + ''; + example = "jane.doe"; + description = "The user's username."; + }; + + home.homeDirectory = mkOption { + type = types.path; + defaultText = literalExpression '' + "$HOME" for state version < 20.09, + undefined for state version ≥ 20.09 + ''; + apply = toString; + example = "/home/jane.doe"; + description = "The user's home directory. Must be an absolute path."; + }; + + home.profileDirectory = mkOption { + type = types.path; + defaultText = literalExpression '' + "''${home.homeDirectory}/.nix-profile" or + "/etc/profiles/per-user/''${home.username}" + ''; + readOnly = true; + description = '' + The profile directory where Home Manager generations are installed. + ''; + }; + + home.language = mkOption { + type = languageSubModule; + default = {}; + description = "Language configuration."; + }; + + home.keyboard = mkOption { + type = types.nullOr keyboardSubModule; + default = if versionAtLeast stateVersion "21.11" then null else { }; + defaultText = literalExpression '' + "{ }" for state version < 21.11, + "null" for state version ≥ 21.11 + ''; + description = '' + Keyboard configuration. Set to null to + disable Home Manager keyboard management. + ''; + }; + + home.shellAliases = mkOption { + type = with types; attrsOf str; + default = { }; + example = literalExpression '' + { + g = "git"; + "..." = "cd ../.."; + } + ''; + description = '' + An attribute set that maps aliases (the top level attribute names + in this option) to command strings or directly to build outputs. + + This option should only be used to manage simple aliases that are + compatible across all shells. If you need to use a shell specific + feature then make sure to use a shell specific option, for example + for Bash. + ''; + }; + + home.sessionVariables = mkOption { + default = {}; + type = types.attrs; + example = { EDITOR = "emacs"; GS_OPTIONS = "-sPAPERSIZE=a4"; }; + description = '' + Environment variables to always set at login. + + The values may refer to other environment variables using + POSIX.2 style variable references. For example, a variable + parameter may be referenced as + $parameter or ''${parameter}. A + default value foo may be given as per + ''${parameter:-foo} and, similarly, an alternate + value bar can be given as per + ''${parameter:+bar}. + + Note, these variables may be set in any order so no session + variable may have a runtime dependency on another session + variable. In particular code like + + home.sessionVariables = { + FOO = "Hello"; + BAR = "$FOO World!"; + }; + + may not work as expected. If you need to reference another + session variable, then do so inside Nix instead. The above + example then becomes + + home.sessionVariables = { + FOO = "Hello"; + BAR = "''${config.home.sessionVariables.FOO} World!"; + }; + + ''; + }; + + home.sessionPath = mkOption { + type = with types; listOf str; + default = [ ]; + example = [ + "$HOME/.local/bin" + "\${xdg.configHome}/emacs/bin" + ".git/safe/../../bin" + ]; + description = '' + Extra directories to add to PATH. + + + + These directories are added to the PATH variable in a + double-quoted context, so expressions like $HOME are + expanded by the shell. However, since expressions like ~ or + * are escaped, they will end up in the PATH + verbatim. + ''; + }; + + home.sessionVariablesExtra = mkOption { + type = types.lines; + default = ""; + internal = true; + description = '' + Extra configuration to add to the + hm-session-vars.sh file. + ''; + }; + + home.packages = mkOption { + type = types.listOf types.package; + default = []; + description = "The set of packages to appear in the user environment."; + }; + + home.extraOutputsToInstall = mkOption { + type = types.listOf types.str; + default = []; + example = [ "doc" "info" "devdoc" ]; + description = '' + List of additional package outputs of the packages + home.packages that should be installed into + the user environment. + ''; + }; + + home.path = mkOption { + internal = true; + description = "The derivation installing the user packages."; + }; + + home.emptyActivationPath = mkOption { + internal = true; + default = false; + type = types.bool; + description = '' + Whether the activation script should start with an empty + PATH variable. When false + then the user's PATH will be used. + ''; + }; + + home.activation = mkOption { + type = hm.types.dagOf types.str; + default = {}; + example = literalExpression '' + { + myActivationAction = lib.hm.dag.entryAfter ["writeBoundary"] ''' + $DRY_RUN_CMD ln -s $VERBOSE_ARG \ + ''${builtins.toPath ./link-me-directly} $HOME + '''; + } + ''; + description = '' + The activation scripts blocks to run when activating a Home + Manager generation. Any entry here should be idempotent, + meaning running twice or more times produces the same result + as running it once. + + + + If the script block produces any observable side effect, such + as writing or deleting files, then it + must be placed after the special + writeBoundary script block. Prior to the + write boundary one can place script blocks that verifies, but + does not modify, the state of the system and exits if an + unexpected state is found. For example, the + checkLinkTargets script block checks for + collisions between non-managed files and files defined in + home.file. + + + + A script block should respect the DRY_RUN + variable, if it is set then the actions taken by the script + should be logged to standard out and not actually performed. + The variable DRY_RUN_CMD is set to + echo if dry run is enabled. + + + + A script block should also respect the + VERBOSE variable, and if set print + information on standard out that may be useful for debugging + any issue that may arise. The variable + VERBOSE_ARG is set to + if verbose output is enabled. + ''; + }; + + home.activationPackage = mkOption { + internal = true; + type = types.package; + description = "The package containing the complete activation script."; + }; + + home.extraActivationPath = mkOption { + internal = true; + type = types.listOf types.package; + default = [ ]; + description = '' + Extra packages to add to PATH within the activation + script. + ''; + }; + + home.extraBuilderCommands = mkOption { + type = types.lines; + default = ""; + internal = true; + description = '' + Extra commands to run in the Home Manager generation builder. + ''; + }; + + home.extraProfileCommands = mkOption { + type = types.lines; + default = ""; + internal = true; + description = '' + Extra commands to run in the Home Manager profile builder. + ''; + }; + + home.enableNixpkgsReleaseCheck = mkOption { + type = types.bool; + default = false; # Temporarily disabled until release stabilizes. + description = '' + Determines whether to check for release version mismatch between Home + Manager and Nixpkgs. Using mismatched versions is likely to cause errors + and unexpected behavior. It is therefore highly recommended to use a + release of Home Manager than corresponds with your chosen release of + Nixpkgs. + + When this option is enabled and a mismatch is detected then a warning + will be printed when the user configuration is being built. + ''; + }; + }; + + config = { + assertions = [ + { + assertion = config.home.username != ""; + message = "Username could not be determined"; + } + { + assertion = config.home.homeDirectory != ""; + message = "Home directory could not be determined"; + } + ]; + + warnings = + let + hmRelease = fileContents ../.release; + nixpkgsRelease = pkgs.lib.trivial.release; + releaseMismatch = + config.home.enableNixpkgsReleaseCheck + && hmRelease != nixpkgsRelease; + in + optional releaseMismatch '' + You are using + + Home Manager version ${hmRelease} and + Nixpkgs version ${nixpkgsRelease}. + + Using mismatched versions is likely to cause errors and unexpected + behavior. It is therefore highly recommended to use a release of Home + Manager than corresponds with your chosen release of Nixpkgs. + + If you insist then you can disable this warning by adding + + home.enableNixpkgsReleaseCheck = false; + + to your configuration. + ''; + + home.username = + mkIf (versionOlder config.home.stateVersion "20.09") + (mkDefault (builtins.getEnv "USER")); + home.homeDirectory = + mkIf (versionOlder config.home.stateVersion "20.09") + (mkDefault (builtins.getEnv "HOME")); + + home.profileDirectory = + if config.submoduleSupport.enable + && config.submoduleSupport.externalPackageInstall + then "/etc/profiles/per-user/${cfg.username}" + else cfg.homeDirectory + "/.nix-profile"; + + programs.bash.shellAliases = cfg.shellAliases; + programs.zsh.shellAliases = cfg.shellAliases; + programs.fish.shellAliases = cfg.shellAliases; + + home.sessionVariables = + let + maybeSet = n: v: optionalAttrs (v != null) { ${n} = v; }; + in + (maybeSet "LANG" cfg.language.base) + // + (maybeSet "LC_CTYPE" cfg.language.ctype) + // + (maybeSet "LC_NUMERIC" cfg.language.numeric) + // + (maybeSet "LC_TIME" cfg.language.time) + // + (maybeSet "LC_COLLATE" cfg.language.collate) + // + (maybeSet "LC_MONETARY" cfg.language.monetary) + // + (maybeSet "LC_MESSAGES" cfg.language.messages) + // + (maybeSet "LC_PAPER" cfg.language.paper) + // + (maybeSet "LC_NAME" cfg.language.name) + // + (maybeSet "LC_ADDRESS" cfg.language.address) + // + (maybeSet "LC_TELEPHONE" cfg.language.telephone) + // + (maybeSet "LC_MEASUREMENT" cfg.language.measurement); + + home.packages = [ + # Provide a file holding all session variables. + ( + pkgs.writeTextFile { + name = "hm-session-vars.sh"; + destination = "/etc/profile.d/hm-session-vars.sh"; + text = '' + # Only source this once. + if [ -n "$__HM_SESS_VARS_SOURCED" ]; then return; fi + export __HM_SESS_VARS_SOURCED=1 + + ${config.lib.shell.exportAll cfg.sessionVariables} + '' + lib.optionalString (cfg.sessionPath != [ ]) '' + export PATH="$PATH''${PATH:+:}${concatStringsSep ":" cfg.sessionPath}" + '' + cfg.sessionVariablesExtra; + } + ) + ]; + + # A dummy entry acting as a boundary between the activation + # script's "check" and the "write" phases. + home.activation.writeBoundary = hm.dag.entryAnywhere ""; + + # Install packages to the user environment. + # + # Note, sometimes our target may not allow modification of the Nix + # store and then we cannot rely on `nix-env -i`. This is the case, + # for example, if we are running as a NixOS module and building a + # virtual machine. Then we must instead rely on an external + # mechanism for installing packages, which in NixOS is provided by + # the `users.users..packages` option. The activation + # command is still needed since some modules need to run their + # activation commands after the packages are guaranteed to be + # installed. + # + # In case the user has moved from a user-install of Home Manager + # to a submodule managed one we attempt to uninstall the + # `home-manager-path` package if it is installed. + home.activation.installPackages = hm.dag.entryAfter ["writeBoundary"] ( + if config.submoduleSupport.externalPackageInstall + then + '' + if [[ -e "$nixProfilePath"/manifest.json ]] ; then + nix profile list \ + | { grep 'home-manager-path$' || test $? = 1; } \ + | awk -F ' ' '{ print $4 }' \ + | cut -d ' ' -f 4 \ + | xargs -t $DRY_RUN_CMD nix profile remove $VERBOSE_ARG + else + if nix-env -q | grep '^home-manager-path$'; then + $DRY_RUN_CMD nix-env -e home-manager-path + fi + fi + '' + else + '' + if [[ -e "$nixProfilePath"/manifest.json ]] ; then + INSTALL_CMD="nix profile install" + LIST_CMD="nix profile list" + REMOVE_CMD_SYNTAX='nix profile remove {number | store path}' + else + INSTALL_CMD="nix-env -i" + LIST_CMD="nix-env -q" + REMOVE_CMD_SYNTAX='nix-env -e {package name}' + fi + + if ! $DRY_RUN_CMD $INSTALL_CMD ${cfg.path} ; then + echo + _iError $'Oops, Nix failed to install your new Home Manager profile!\n\nPerhaps there is a conflict with a package that was installed using\n"%s"? Try running\n\n %s\n\nand if there is a conflicting package you can remove it with\n\n %s\n\nThen try activating your Home Manager configuration again.' "$INSTALL_CMD" "$LIST_CMD" "$REMOVE_CMD_SYNTAX" + exit 1 + fi + unset INSTALL_CMD LIST_CMD REMOVE_CMD_SYNTAX + '' + ); + + # Text containing Bash commands that will initialize the Home Manager Bash + # library. Most importantly, this will prepare for using translated strings + # in the `hm-modules` text domain. + lib.bash.initHomeManagerLib = + let + domainDir = pkgs.runCommand "hm-modules-messages" { + nativeBuildInputs = [ pkgs.buildPackages.gettext ]; + } '' + for path in ${./po}/*.po; do + lang="''${path##*/}" + lang="''${lang%%.*}" + mkdir -p "$out/$lang/LC_MESSAGES" + msgfmt -o "$out/$lang/LC_MESSAGES/hm-modules.mo" "$path" + done + ''; + in + '' + export TEXTDOMAIN=hm-modules + export TEXTDOMAINDIR=${domainDir} + source ${../lib/bash/home-manager.sh} + ''; + + home.activationPackage = + let + mkCmd = res: '' + _iNote "Activating %s" "${res.name}" + ${res.data} + ''; + sortedCommands = hm.dag.topoSort cfg.activation; + activationCmds = + if sortedCommands ? result then + concatStringsSep "\n" (map mkCmd sortedCommands.result) + else + abort ("Dependency cycle in activation script: " + + builtins.toJSON sortedCommands); + + # Programs that always should be available on the activation + # script's PATH. + activationBinPaths = lib.makeBinPath ( + with pkgs; [ + bash + coreutils + diffutils # For `cmp` and `diff`. + findutils + gettext + gnugrep + gnused + ncurses # For `tput`. + ] ++ config.home.extraActivationPath + ) + + optionalString (!cfg.emptyActivationPath) "\${PATH:+:}$PATH"; + + activationScript = pkgs.writeShellScript "activation-script" '' + set -eu + set -o pipefail + + cd $HOME + + export PATH="${activationBinPaths}" + ${config.lib.bash.initHomeManagerLib} + + ${builtins.readFile ./lib-bash/activation-init.sh} + + ${activationCmds} + ''; + in + pkgs.runCommand + "home-manager-generation" + { + preferLocalBuild = true; + } + '' + mkdir -p $out + + cp ${activationScript} $out/activate + + mkdir $out/bin + ln -s $out/activate $out/bin/home-manager-generation + + substituteInPlace $out/activate \ + --subst-var-by GENERATION_DIR $out + + ln -s ${config.home-files} $out/home-files + ln -s ${cfg.path} $out/home-path + + ${cfg.extraBuilderCommands} + ''; + + home.path = pkgs.buildEnv { + name = "home-manager-path"; + + paths = cfg.packages; + inherit (cfg) extraOutputsToInstall; + + postBuild = cfg.extraProfileCommands; + + meta = { + description = "Environment of packages installed through home-manager"; + }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/i18n/input-method/default.nix b/infra/libkookie/home-manager-stable/modules/i18n/input-method/default.nix new file mode 100644 index 00000000000..27b3ae86dd6 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/i18n/input-method/default.nix @@ -0,0 +1,106 @@ +{ config, pkgs, lib, ... }: + +with lib; +let + + cfg = config.i18n.inputMethod; + + gtk2Cache = pkgs.runCommandLocal "gtk2-immodule.cache" { + buildInputs = [ pkgs.gtk2 cfg.package ]; + } '' + mkdir -p $out/etc/gtk-2.0/ + GTK_PATH=${cfg.package}/lib/gtk-2.0/ \ + gtk-query-immodules-2.0 > $out/etc/gtk-2.0/immodules.cache + ''; + + gtk3Cache = pkgs.runCommandLocal "gtk3-immodule.cache" { + buildInputs = [ pkgs.gtk3 cfg.package ]; + } '' + mkdir -p $out/etc/gtk-3.0/ + GTK_PATH=${cfg.package}/lib/gtk-3.0/ \ + gtk-query-immodules-3.0 > $out/etc/gtk-3.0/immodules.cache + ''; + +in { + imports = + [ ./fcitx.nix ./fcitx5.nix ./hime.nix ./kime.nix ./nabi.nix ./uim.nix ]; + + options.i18n = { + inputMethod = { + enabled = mkOption { + type = types.nullOr + (types.enum [ "fcitx" "fcitx5" "nabi" "uim" "hime" "kime" ]); + default = null; + example = "fcitx"; + description = '' + Select the enabled input method. Input methods is a software to input + symbols that are not available on standard input devices. + + Input methods are specially used to input Chinese, Japanese and Korean + characters. + + Currently the following input methods are available in Home Manager: + + + + fcitx + + A customizable lightweight input method + extra input engines can be added using + i18n.inputMethod.fcitx.engines. + + + + fcitx5 + + The next generation of fcitx, + addons (including engines, dictionaries, skins) can be added using + i18n.inputMethod.fcitx5.addons. + + + + nabi + + A Korean input method based on XIM. Nabi doesn't support Qt 5. + + + + uim + + The universal input method, is a library with a XIM bridge. + uim mainly support Chinese, Japanese and Korean. + + + + hime + An extremely easy-to-use input method framework. + + + kime + A Korean IME. + + + ''; + }; + + package = mkOption { + internal = true; + type = types.nullOr types.path; + default = null; + description = '' + The input method method package. + ''; + }; + }; + }; + + config = mkIf (cfg.enabled != null) { + assertions = [ + (hm.assertions.assertPlatform "i18n.inputMethod" pkgs platforms.linux) + ]; + + home.packages = [ cfg.package gtk2Cache gtk3Cache ]; + }; + + meta.maintainers = with lib; [ hm.maintainers.kranzes ]; +} diff --git a/infra/libkookie/home-manager-stable/modules/i18n/input-method/fcitx.nix b/infra/libkookie/home-manager-stable/modules/i18n/input-method/fcitx.nix new file mode 100644 index 00000000000..f7d1b41a94c --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/i18n/input-method/fcitx.nix @@ -0,0 +1,50 @@ +{ config, pkgs, lib, ... }: + +with lib; + +let + cfg = config.i18n.inputMethod.fcitx; + fcitxPackage = pkgs.fcitx.override { plugins = cfg.engines; }; + fcitxEngine = types.package // { + name = "fcitx-engine"; + check = x: + types.package.check x && attrByPath [ "meta" "isFcitxEngine" ] false x; + }; +in { + options = { + + i18n.inputMethod.fcitx = { + engines = mkOption { + type = with types; listOf fcitxEngine; + default = [ ]; + example = literalExpression "with pkgs.fcitx-engines; [ mozc hangul ]"; + description = let + enginesDrv = filterAttrs (const isDerivation) pkgs.fcitx-engines; + engines = concatStringsSep ", " + (map (name: "${name}") (attrNames enginesDrv)); + in "Enabled Fcitx engines. Available engines are: ${engines}."; + }; + }; + + }; + + config = mkIf (config.i18n.inputMethod.enabled == "fcitx") { + i18n.inputMethod.package = fcitxPackage; + + home.sessionVariables = { + GTK_IM_MODULE = "fcitx"; + QT_IM_MODULE = "fcitx"; + XMODIFIERS = "@im=fcitx"; + }; + + systemd.user.services.fcitx-daemon = { + Unit = { + Description = "Fcitx input method editor"; + PartOf = [ "graphical-session.desktop" ]; + }; + Service.ExecStart = "${fcitxPackage}/bin/fcitx"; + Install.WantedBy = [ "graphical-session.target" ]; + }; + }; + +} diff --git a/infra/libkookie/home-manager-stable/modules/i18n/input-method/fcitx5.nix b/infra/libkookie/home-manager-stable/modules/i18n/input-method/fcitx5.nix new file mode 100644 index 00000000000..9211d0b7efc --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/i18n/input-method/fcitx5.nix @@ -0,0 +1,42 @@ +{ config, pkgs, lib, ... }: + +with lib; + +let + im = config.i18n.inputMethod; + cfg = im.fcitx5; + fcitx5Package = pkgs.fcitx5-with-addons.override { inherit (cfg) addons; }; +in { + options = { + i18n.inputMethod.fcitx5 = { + addons = mkOption { + type = with types; listOf package; + default = [ ]; + example = literalExpression "with pkgs; [ fcitx5-rime ]"; + description = '' + Enabled Fcitx5 addons. + ''; + }; + }; + }; + + config = mkIf (im.enabled == "fcitx5") { + i18n.inputMethod.package = fcitx5Package; + + home.sessionVariables = { + GTK_IM_MODULE = "fcitx"; + QT_IM_MODULE = "fcitx"; + XMODIFIERS = "@im=fcitx"; + }; + + systemd.user.services.fcitx5-daemon = { + Unit = { + Description = "Fcitx5 input method editor"; + PartOf = [ "graphical-session.target" ]; + }; + Service.ExecStart = "${fcitx5Package}/bin/fcitx5"; + Install.WantedBy = [ "graphical-session.target" ]; + }; + }; + +} diff --git a/infra/libkookie/home-manager-stable/modules/i18n/input-method/hime.nix b/infra/libkookie/home-manager-stable/modules/i18n/input-method/hime.nix new file mode 100644 index 00000000000..7b5700a9db1 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/i18n/input-method/hime.nix @@ -0,0 +1,23 @@ +{ config, pkgs, lib, ... }: + +with lib; { + config = mkIf (config.i18n.inputMethod.enabled == "hime") { + i18n.inputMethod.package = pkgs.hime; + + home.sessionVariables = { + GTK_IM_MODULE = "hime"; + QT_IM_MODULE = "hime"; + XMODIFIERS = "@im=hime"; + }; + + systemd.user.services.hime-daemon = { + Unit = { + Description = "Hime input method editor"; + PartOf = [ "graphical-session.desktop" ]; + }; + Service.ExecStart = "${pkgs.hime}/bin/hime"; + Install.WantedBy = [ "graphical-session.target" ]; + }; + }; + +} diff --git a/infra/libkookie/home-manager-stable/modules/i18n/input-method/kime.nix b/infra/libkookie/home-manager-stable/modules/i18n/input-method/kime.nix new file mode 100644 index 00000000000..70f32190012 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/i18n/input-method/kime.nix @@ -0,0 +1,59 @@ +{ config, pkgs, lib, generators, ... }: +with lib; +let + cfg = config.i18n.inputMethod.kime; + yamlFormat = pkgs.formats.yaml { }; +in { + options = { + i18n.inputMethod.kime = { + config = mkOption { + type = yamlFormat.type; + default = { }; + example = literalExpression '' + { + daemon = { + modules = ["Xim" "Indicator"]; + }; + + indicator = { + icon_color = "White"; + }; + + engine = { + hangul = { + layout = "dubeolsik"; + }; + }; + } + ''; + description = '' + kime configuration. Refer to + + for details on supported values. + ''; + }; + }; + }; + + config = mkIf (config.i18n.inputMethod.enabled == "kime") { + i18n.inputMethod.package = pkgs.kime; + + home.sessionVariables = { + GTK_IM_MODULE = "kime"; + QT_IM_MODULE = "kime"; + XMODIFIERS = "@im=kime"; + }; + + xdg.configFile."kime/config.yaml".text = + replaceStrings [ "\\\\" ] [ "\\" ] (builtins.toJSON cfg.config); + + systemd.user.services.kime-daemon = { + Unit = { + Description = "Kime input method editor"; + PartOf = [ "graphical-session.target" ]; + }; + Service.ExecStart = "${pkgs.kime}/bin/kime"; + Install.WantedBy = [ "graphical-session.target" ]; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/i18n/input-method/nabi.nix b/infra/libkookie/home-manager-stable/modules/i18n/input-method/nabi.nix new file mode 100644 index 00000000000..01f9f7911ec --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/i18n/input-method/nabi.nix @@ -0,0 +1,23 @@ +{ config, pkgs, lib, ... }: + +with lib; { + config = mkIf (config.i18n.inputMethod.enabled == "nabi") { + i18n.inputMethod.package = pkgs.nabi; + + home.sessionVariables = { + GTK_IM_MODULE = "nabi"; + QT_IM_MODULE = "nabi"; + XMODIFIERS = "@im=nabi"; + }; + + systemd.user.services.nabi-daemon = { + Unit = { + Description = "Nabi input method editor"; + PartOf = [ "graphical-session.desktop" ]; + }; + Service.ExecStart = "${pkgs.nabi}/bin/nabi"; + Install.WantedBy = [ "graphical-session.target" ]; + }; + }; + +} diff --git a/infra/libkookie/home-manager-stable/modules/i18n/input-method/uim.nix b/infra/libkookie/home-manager-stable/modules/i18n/input-method/uim.nix new file mode 100644 index 00000000000..e7890352c92 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/i18n/input-method/uim.nix @@ -0,0 +1,45 @@ +{ config, pkgs, lib, ... }: + +with lib; + +let cfg = config.i18n.inputMethod.uim; +in { + options = { + + i18n.inputMethod.uim = { + toolbar = mkOption { + type = types.enum [ "gtk" "gtk3" "gtk-systray" "gtk3-systray" "qt4" ]; + default = "gtk"; + example = "gtk-systray"; + description = '' + Selected UIM toolbar. + ''; + }; + }; + + }; + + config = mkIf (config.i18n.inputMethod.enabled == "uim") { + i18n.inputMethod.package = pkgs.uim; + + home.sessionVariables = { + GTK_IM_MODULE = "uim"; + QT_IM_MODULE = "uim"; + XMODIFIERS = "@im=uim"; + }; + + systemd.user.services.uim-daemon = { + Unit = { + Description = "Uim input method editor"; + PartOf = [ "graphical-session.desktop" ]; + }; + Service.ExecStart = toString + (pkgs.writeShellScript "start-uim-xim-and-uim-toolbar" '' + ${pkgs.uim}/bin/uim-xim & + ${pkgs.uim}/bin/uim-toolbar-${cfg.toolbar} + ''); + Install.WantedBy = [ "graphical-session.target" ]; + }; + }; + +} diff --git a/infra/libkookie/home-manager-stable/modules/launchd/default.nix b/infra/libkookie/home-manager-stable/modules/launchd/default.nix new file mode 100644 index 00000000000..17b36cdb954 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/launchd/default.nix @@ -0,0 +1,213 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + inherit (pkgs.stdenv.hostPlatform) isDarwin; + inherit (lib.generators) toPlist; + + cfg = config.launchd; + labelPrefix = "org.nix-community.home."; + dstDir = "${config.home.homeDirectory}/Library/LaunchAgents"; + + launchdConfig = { config, name, ... }: { + options = { + enable = mkEnableOption name; + config = mkOption { + type = types.submodule (import ./launchd.nix); + default = { }; + example = literalExpression '' + { + ProgramArguments = [ "/usr/bin/say" "Good afternoon" ]; + StartCalendarInterval = { + Hour = 12; + Minute = 0; + }; + } + ''; + description = '' + Define a launchd job. See + launchd.plist5 + for details. + ''; + }; + }; + + config = { config.Label = mkDefault "${labelPrefix}${name}"; }; + }; + + toAgent = config: pkgs.writeText "${config.Label}.plist" (toPlist { } config); + + agentPlists = + mapAttrs' (n: v: nameValuePair "${v.config.Label}.plist" (toAgent v.config)) + (filterAttrs (n: v: v.enable) cfg.agents); + + agentsDrv = pkgs.runCommand "home-manager-agents" { } '' + mkdir -p "$out" + + declare -A plists + plists=(${ + concatStringsSep " " + (mapAttrsToList (name: value: "['${name}']='${value}'") agentPlists) + }) + + for dest in "''${!plists[@]}"; do + src="''${plists[$dest]}" + ln -s "$src" "$out/$dest" + done + ''; +in { + meta.maintainers = with maintainers; [ midchildan ]; + + options.launchd = { + enable = mkOption { + type = types.bool; + default = isDarwin; + defaultText = literalExpression "pkgs.stdenv.hostPlatform.isDarwin"; + description = '' + Whether to enable Home Manager to define per-user daemons by making use + of launchd's LaunchAgents. + ''; + }; + + agents = mkOption { + type = with types; attrsOf (submodule launchdConfig); + default = { }; + description = "Define LaunchAgents."; + }; + }; + + config = mkMerge [ + { + assertions = [{ + assertion = (cfg.enable && agentPlists != { }) -> isDarwin; + message = let names = lib.concatStringsSep ", " (attrNames agentPlists); + in "Must use Darwin for modules that require Launchd: " + names; + }]; + } + + (mkIf isDarwin { + home.extraBuilderCommands = '' + ln -s "${agentsDrv}" $out/LaunchAgents + ''; + + home.activation.checkLaunchAgents = + hm.dag.entryBefore [ "writeBoundary" ] '' + checkLaunchAgents() { + local oldDir newDir dstDir err + oldDir="" + err=0 + if [[ -n "''${oldGenPath:-}" ]]; then + oldDir="$(readlink -m "$oldGenPath/LaunchAgents")" || err=$? + if (( err )); then + oldDir="" + fi + fi + newDir=${escapeShellArg agentsDrv} + dstDir=${escapeShellArg dstDir} + + local oldSrcPath newSrcPath dstPath agentFile agentName + + find -L "$newDir" -maxdepth 1 -name '*.plist' -type f -print0 \ + | while IFS= read -rd "" newSrcPath; do + agentFile="''${newSrcPath##*/}" + agentName="''${agentFile%.plist}" + dstPath="$dstDir/$agentFile" + oldSrcPath="$oldDir/$agentFile" + + if [[ ! -e "$dstPath" ]]; then + continue + fi + + if ! cmp --quiet "$oldSrcPath" "$dstPath"; then + errorEcho "Existing file '$dstPath' is in the way of '$newSrcPath'" + exit 1 + fi + done + } + + checkLaunchAgents + ''; + + # NOTE: Launch Agent configurations can't be symlinked from the Nix store + # because it needs to be owned by the user running it. + home.activation.setupLaunchAgents = + hm.dag.entryAfter [ "writeBoundary" ] '' + setupLaunchAgents() { + local oldDir newDir dstDir domain err + oldDir="" + err=0 + if [[ -n "''${oldGenPath:-}" ]]; then + oldDir="$(readlink -m "$oldGenPath/LaunchAgents")" || err=$? + if (( err )); then + oldDir="" + fi + fi + newDir="$(readlink -m "$newGenPath/LaunchAgents")" + dstDir=${escapeShellArg dstDir} + domain="gui/$UID" + err=0 + + local srcPath dstPath agentFile agentName i bootout_retries + bootout_retries=10 + + find -L "$newDir" -maxdepth 1 -name '*.plist' -type f -print0 \ + | while IFS= read -rd "" srcPath; do + agentFile="''${srcPath##*/}" + agentName="''${agentFile%.plist}" + dstPath="$dstDir/$agentFile" + + if cmp --quiet "$srcPath" "$dstPath"; then + continue + fi + if [[ -f "$dstPath" ]]; then + for (( i = 0; i < bootout_retries; i++ )); do + $DRY_RUN_CMD launchctl bootout "$domain/$agentName" || err=$? + if [[ -v DRY_RUN ]]; then + break + fi + if (( err != 9216 )) && + ! launchctl print "$domain/$agentName" &> /dev/null; then + break + fi + sleep 1 + done + if (( i == bootout_retries )); then + warnEcho "Failed to stop '$domain/$agentName'" + return 1 + fi + fi + $DRY_RUN_CMD install -Dm444 -T "$srcPath" "$dstPath" + $DRY_RUN_CMD launchctl bootstrap "$domain" "$dstPath" + done + + if [[ ! -e "$oldDir" ]]; then + return + fi + + find -L "$oldDir" -maxdepth 1 -name '*.plist' -type f -print0 \ + | while IFS= read -rd "" srcPath; do + agentFile="''${srcPath##*/}" + agentName="''${agentFile%.plist}" + dstPath="$dstDir/$agentFile" + if [[ -e "$newDir/$agentFile" ]]; then + continue + fi + + $DRY_RUN_CMD launchctl bootout "$domain/$agentName" || : + if [[ ! -e "$dstPath" ]]; then + continue + fi + if ! cmp --quiet "$srcPath" "$dstPath"; then + warnEcho "Skipping deletion of '$dstPath', since its contents have diverged" + continue + fi + $DRY_RUN_CMD rm -f $VERBOSE_ARG "$dstPath" + done + } + + setupLaunchAgents + ''; + }) + ]; +} diff --git a/infra/libkookie/home-manager-stable/modules/launchd/launchd.nix b/infra/libkookie/home-manager-stable/modules/launchd/launchd.nix new file mode 100644 index 00000000000..e25c005b29a --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/launchd/launchd.nix @@ -0,0 +1,869 @@ +# launchd option type from nix-darwin +# +# Original Source: +# https://github.com/LnL7/nix-darwin/blob/a34dea2/modules/launchd/launchd.nix + +# Copyright 2017 Daiderd Jordan +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE +# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +{ config, lib, ... }: + +with lib; + +{ + options = { + Label = mkOption { + type = types.str; + description = "This required key uniquely identifies the job to launchd."; + }; + + Disabled = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + This optional key is used as a hint to launchctl(1) that it should not submit this job to launchd when + loading a job or jobs. The value of this key does NOT reflect the current state of the job on the run-ning running + ning system. If you wish to know whether a job is loaded in launchd, reading this key from a configura-tion configuration + tion file yourself is not a sufficient test. You should query launchd for the presence of the job using + the launchctl(1) list subcommand or use the ServiceManagement framework's + SMJobCopyDictionary() method. + + Note that as of Mac OS X v10.6, this key's value in a configuration file conveys a default value, which + is changed with the [-w] option of the launchctl(1) load and unload subcommands. These subcommands no + longer modify the configuration file, so the value displayed in the configuration file is not necessar-ily necessarily + ily the value that launchctl(1) will apply. See launchctl(1) for more information. + + Please also be mindful that you should only use this key if the provided on-demand and KeepAlive crite-ria criteria + ria are insufficient to describe the conditions under which your job needs to run. The cost to have a + job loaded in launchd is negligible, so there is no harm in loading a job which only runs once or very + rarely. + ''; + }; + + UserName = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + This optional key specifies the user to run the job as. This key is only applicable when launchd is + running as root. + ''; + }; + + GroupName = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + This optional key specifies the group to run the job as. This key is only applicable when launchd is + running as root. If UserName is set and GroupName is not, the the group will be set to the default + group of the user. + ''; + }; + + inetdCompatibility = mkOption { + default = null; + example = { Wait = true; }; + description = '' + The presence of this key specifies that the daemon expects to be run as if it were launched from inetd. + ''; + type = types.nullOr (types.submodule { + options = { + Wait = mkOption { + type = types.nullOr (types.either types.bool types.str); + default = null; + description = '' + This flag corresponds to the "wait" or "nowait" option of inetd. If true, then the listening + socket is passed via the standard in/out/error file descriptors. If false, then accept(2) is + called on behalf of the job, and the result is passed via the standard in/out/error descriptors. + ''; + }; + }; + }); + }; + + LimitLoadToHosts = mkOption { + type = types.nullOr (types.listOf types.str); + default = null; + description = '' + This configuration file only applies to the hosts listed with this key. Note: One should set kern.host-name kern.hostname + name in sysctl.conf(5) for this feature to work reliably. + ''; + }; + + LimitLoadFromHosts = mkOption { + type = types.nullOr (types.listOf types.str); + default = null; + description = '' + This configuration file only applies to hosts NOT listed with this key. Note: One should set kern.host-name kern.hostname + name in sysctl.conf(5) for this feature to work reliably. + ''; + }; + + LimitLoadToSessionType = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + This configuration file only applies to sessions of the type specified. This key is used in concert + with the -S flag to launchctl. + ''; + }; + + Program = mkOption { + type = types.nullOr types.path; + default = null; + description = '' + This key maps to the first argument of execvp(3). If this key is missing, then the first element of + the array of strings provided to the ProgramArguments will be used instead. This key is required in + the absence of the ProgramArguments key. + ''; + }; + + ProgramArguments = mkOption { + type = types.nullOr (types.listOf types.str); + default = null; + description = '' + This key maps to the second argument of execvp(3). This key is required in the absence of the Program + key. Please note: many people are confused by this key. Please read execvp(3) very carefully! + ''; + }; + + EnableGlobbing = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + This flag causes launchd to use the glob(3) mechanism to update the program arguments before invoca-tion. invocation. + tion. + ''; + }; + + EnableTransactions = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + This flag instructs launchd that the job promises to use vproc_transaction_begin(3) and + vproc_transaction_end(3) to track outstanding transactions that need to be reconciled before the + process can safely terminate. If no outstanding transactions are in progress, then launchd is free to + send the SIGKILL signal. + ''; + }; + + OnDemand = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + This key was used in Mac OS X 10.4 to control whether a job was kept alive or not. The default was + true. This key has been deprecated and replaced in Mac OS X 10.5 and later with the more powerful + KeepAlive option. + ''; + }; + + KeepAlive = mkOption { + type = types.nullOr (types.either types.bool (types.submodule { + options = { + + SuccessfulExit = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + If true, the job will be restarted as long as the program exits and with an exit status of zero. + If false, the job will be restarted in the inverse condition. This key implies that "RunAtLoad" + is set to true, since the job needs to run at least once before we can get an exit status. + ''; + }; + + NetworkState = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + If true, the job will be kept alive as long as the network is up, where up is defined as at least + one non-loopback interface being up and having IPv4 or IPv6 addresses assigned to them. If + false, the job will be kept alive in the inverse condition. + ''; + }; + + PathState = mkOption { + type = types.nullOr (types.attrsOf types.bool); + default = null; + description = '' + Each key in this dictionary is a file-system path. If the value of the key is true, then the job + will be kept alive as long as the path exists. If false, the job will be kept alive in the + inverse condition. The intent of this feature is that two or more jobs may create semaphores in + the file-system namespace. + ''; + }; + + OtherJobEnabled = mkOption { + type = types.nullOr (types.attrsOf types.bool); + default = null; + description = '' + Each key in this dictionary is the label of another job. If the value of the key is true, then + this job is kept alive as long as that other job is enabled. Otherwise, if the value is false, + then this job is kept alive as long as the other job is disabled. This feature should not be + considered a substitute for the use of IPC. + ''; + }; + + # NOTE: this was missing in the original source at the time of writing + Crashed = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + If true, the the job will be restarted as long as it exited due to a signal which is typically + associated with a crash (SIGILL, SIGSEGV, etc.). If false, the job will be restarted in the inverse + condition. + ''; + }; + + }; + })); + default = null; + description = '' + This optional key is used to control whether your job is to be kept continuously running or to let + demand and conditions control the invocation. The default is false and therefore only demand will start + the job. The value may be set to true to unconditionally keep the job alive. Alternatively, a dictio-nary dictionary + nary of conditions may be specified to selectively control whether launchd keeps a job alive or not. If + multiple keys are provided, launchd ORs them, thus providing maximum flexibility to the job to refine + the logic and stall if necessary. If launchd finds no reason to restart the job, it falls back on + demand based invocation. Jobs that exit quickly and frequently when configured to be kept alive will + be throttled to converve system resources. + ''; + }; + + RunAtLoad = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + This optional key is used to control whether your job is launched once at the time the job is loaded. + The default is false. + ''; + }; + + RootDirectory = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + This optional key is used to specify a directory to chroot(2) to before running the job. + ''; + }; + + WorkingDirectory = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + This optional key is used to specify a directory to chdir(2) to before running the job. + ''; + }; + + EnvironmentVariables = mkOption { + type = types.nullOr (types.attrsOf types.str); + default = null; + description = '' + This optional key is used to specify additional environment variables to be set before running the + job. + ''; + }; + + Umask = mkOption { + type = types.nullOr types.int; + default = null; + description = '' + This optional key specifies what value should be passed to umask(2) before running the job. Known bug: + Property lists don't support octal, so please convert the value to decimal. + ''; + }; + + TimeOut = mkOption { + type = types.nullOr types.int; + default = null; + description = '' + The recommended idle time out (in seconds) to pass to the job. If no value is specified, a default time + out will be supplied by launchd for use by the job at check in time. + ''; + }; + + ExitTimeOut = mkOption { + type = types.nullOr types.int; + default = null; + description = '' + The amount of time launchd waits before sending a SIGKILL signal. The default value is 20 seconds. The + value zero is interpreted as infinity. + ''; + }; + + ThrottleInterval = mkOption { + type = types.nullOr types.int; + default = null; + description = '' + This key lets one override the default throttling policy imposed on jobs by launchd. The value is in + seconds, and by default, jobs will not be spawned more than once every 10 seconds. The principle + behind this is that jobs should linger around just in case they are needed again in the near future. + This not only reduces the latency of responses, but it encourages developers to amortize the cost of + program invocation. + ''; + }; + + InitGroups = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + This optional key specifies whether initgroups(3) should be called before running the job. The default + is true in 10.5 and false in 10.4. This key will be ignored if the UserName key is not set. + ''; + }; + + WatchPaths = mkOption { + type = types.nullOr (types.listOf types.path); + default = null; + description = '' + This optional key causes the job to be started if any one of the listed paths are modified. + ''; + }; + + QueueDirectories = mkOption { + type = types.nullOr (types.listOf types.str); + default = null; + description = '' + Much like the WatchPaths option, this key will watch the paths for modifications. The difference being + that the job will only be started if the path is a directory and the directory is not empty. + ''; + }; + + StartOnMount = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + This optional key causes the job to be started every time a filesystem is mounted. + ''; + }; + + StartInterval = mkOption { + type = types.nullOr types.int; + default = null; + description = '' + This optional key causes the job to be started every N seconds. If the system is asleep, the job will + be started the next time the computer wakes up. If multiple intervals transpire before the computer is + woken, those events will be coalesced into one event upon wake from sleep. + ''; + }; + + StartCalendarInterval = mkOption { + default = null; + example = { Hour = 2; Minute = 30; }; + description = '' + This optional key causes the job to be started every calendar interval as specified. Missing arguments + are considered to be wildcard. The semantics are much like crontab(5). Unlike cron which skips job + invocations when the computer is asleep, launchd will start the job the next time the computer wakes + up. If multiple intervals transpire before the computer is woken, those events will be coalesced into + one event upon wake from sleep. + ''; + type = types.nullOr (types.listOf (types.submodule { + options = { + Minute = mkOption { + type = types.nullOr types.int; + default = null; + description = '' + The minute on which this job will be run. + ''; + }; + + Hour = mkOption { + type = types.nullOr types.int; + default = null; + description = '' + The hour on which this job will be run. + ''; + }; + + Day = mkOption { + type = types.nullOr types.int; + default = null; + description = '' + The day on which this job will be run. + ''; + }; + + Weekday = mkOption { + type = types.nullOr types.int; + default = null; + description = '' + The weekday on which this job will be run (0 and 7 are Sunday). + ''; + }; + + Month = mkOption { + type = types.nullOr types.int; + default = null; + description = '' + The month on which this job will be run. + ''; + }; + }; + })); + }; + + StandardInPath = mkOption { + type = types.nullOr types.path; + default = null; + description = '' + This optional key specifies what file should be used for data being supplied to stdin when using + stdio(3). + ''; + }; + + StandardOutPath = mkOption { + type = types.nullOr types.path; + default = null; + description = '' + This optional key specifies what file should be used for data being sent to stdout when using stdio(3). + ''; + }; + + StandardErrorPath = mkOption { + type = types.nullOr types.path; + default = null; + description = '' + This optional key specifies what file should be used for data being sent to stderr when using stdio(3). + ''; + }; + + Debug = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + This optional key specifies that launchd should adjust its log mask temporarily to LOG_DEBUG while + dealing with this job. + ''; + }; + + WaitForDebugger = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + This optional key specifies that launchd should instruct the kernel to have the job wait for a debugger + to attach before any code in the job is executed. + ''; + }; + + SoftResourceLimits = mkOption { + default = null; + description = '' + Resource limits to be imposed on the job. These adjust variables set with setrlimit(2). The following + keys apply: + ''; + type = types.nullOr (types.submodule { + options = { + Core = mkOption { + type = types.nullOr types.int; + default = null; + description = '' + The largest size (in bytes) core file that may be created. + ''; + }; + + CPU = mkOption { + type = types.nullOr types.int; + default = null; + description = '' + The maximum amount of cpu time (in seconds) to be used by each process. + ''; + }; + + Data = mkOption { + type = types.nullOr types.int; + default = null; + description = '' + The maximum size (in bytes) of the data segment for a process; this defines how far a program may + extend its break with the sbrk(2) system call. + ''; + }; + + FileSize = mkOption { + type = types.nullOr types.int; + default = null; + description = '' + The largest size (in bytes) file that may be created. + ''; + }; + + MemoryLock = mkOption { + type = types.nullOr types.int; + default = null; + description = '' + The maximum size (in bytes) which a process may lock into memory using the mlock(2) function. + ''; + }; + + NumberOfFiles = mkOption { + type = types.nullOr types.int; + default = null; + description = '' + The maximum number of open files for this process. Setting this value in a system wide daemon + will set the sysctl(3) kern.maxfiles (SoftResourceLimits) or kern.maxfilesperproc (HardResource-Limits) (HardResourceLimits) + Limits) value in addition to the setrlimit(2) values. + ''; + }; + + NumberOfProcesses = mkOption { + type = types.nullOr types.int; + default = null; + description = '' + The maximum number of simultaneous processes for this user id. Setting this value in a system + wide daemon will set the sysctl(3) kern.maxproc (SoftResourceLimits) or kern.maxprocperuid + (HardResourceLimits) value in addition to the setrlimit(2) values. + ''; + }; + + ResidentSetSize = mkOption { + type = types.nullOr types.int; + default = null; + description = '' + The maximum size (in bytes) to which a process's resident set size may grow. This imposes a + limit on the amount of physical memory to be given to a process; if memory is tight, the system + will prefer to take memory from processes that are exceeding their declared resident set size. + ''; + }; + + Stack = mkOption { + type = types.nullOr types.int; + default = null; + description = '' + The maximum size (in bytes) of the stack segment for a process; this defines how far a program's + stack segment may be extended. Stack extension is performed automatically by the system. + ''; + }; + }; + }); + }; + + HardResourceLimits = mkOption { + default = null; + example = { NumberOfFiles = 4096; }; + description = '' + Resource limits to be imposed on the job. These adjust variables set with setrlimit(2). The following + keys apply: + ''; + type = types.nullOr (types.submodule { + options = { + Core = mkOption { + type = types.nullOr types.int; + default = null; + description = '' + The largest size (in bytes) core file that may be created. + ''; + }; + + CPU = mkOption { + type = types.nullOr types.int; + default = null; + description = '' + The maximum amount of cpu time (in seconds) to be used by each process. + ''; + }; + + Data = mkOption { + type = types.nullOr types.int; + default = null; + description = '' + The maximum size (in bytes) of the data segment for a process; this defines how far a program may + extend its break with the sbrk(2) system call. + ''; + }; + + FileSize = mkOption { + type = types.nullOr types.int; + default = null; + description = '' + The largest size (in bytes) file that may be created. + ''; + }; + + MemoryLock = mkOption { + type = types.nullOr types.int; + default = null; + description = '' + The maximum size (in bytes) which a process may lock into memory using the mlock(2) function. + ''; + }; + + NumberOfFiles = mkOption { + type = types.nullOr types.int; + default = null; + description = '' + The maximum number of open files for this process. Setting this value in a system wide daemon + will set the sysctl(3) kern.maxfiles (SoftResourceLimits) or kern.maxfilesperproc (HardResource-Limits) (HardResourceLimits) + Limits) value in addition to the setrlimit(2) values. + ''; + }; + + NumberOfProcesses = mkOption { + type = types.nullOr types.int; + default = null; + description = '' + The maximum number of simultaneous processes for this user id. Setting this value in a system + wide daemon will set the sysctl(3) kern.maxproc (SoftResourceLimits) or kern.maxprocperuid + (HardResourceLimits) value in addition to the setrlimit(2) values. + ''; + }; + + ResidentSetSize = mkOption { + type = types.nullOr types.int; + default = null; + description = '' + The maximum size (in bytes) to which a process's resident set size may grow. This imposes a + limit on the amount of physical memory to be given to a process; if memory is tight, the system + will prefer to take memory from processes that are exceeding their declared resident set size. + ''; + }; + + Stack = mkOption { + type = types.nullOr types.int; + default = null; + description = '' + The maximum size (in bytes) of the stack segment for a process; this defines how far a program's + stack segment may be extended. Stack extension is performed automatically by the system. + ''; + }; + }; + }); + }; + + Nice = mkOption { + type = types.nullOr types.int; + default = null; + description = '' + This optional key specifies what nice(3) value should be applied to the daemon. + ''; + }; + + ProcessType = mkOption { + type = types.nullOr (types.enum [ "Background" "Standard" "Adaptive" "Interactive" ]); + default = null; + example = "Background"; + description = '' + This optional key describes, at a high level, the intended purpose of the job. The system will apply + resource limits based on what kind of job it is. If left unspecified, the system will apply light + resource limits to the job, throttling its CPU usage and I/O bandwidth. The following are valid values: + + Background + Background jobs are generally processes that do work that was not directly requested by the user. + The resource limits applied to Background jobs are intended to prevent them from disrupting the + user experience. + + Standard + Standard jobs are equivalent to no ProcessType being set. + + Adaptive + Adaptive jobs move between the Background and Interactive classifications based on activity over + XPC connections. See xpc_transaction_begin(3) for details. + + Interactive + Interactive jobs run with the same resource limitations as apps, that is to say, none. Interac-tive Interactive + tive jobs are critical to maintaining a responsive user experience, and this key should only be + used if an app's ability to be responsive depends on it, and cannot be made Adaptive. + ''; + }; + + AbandonProcessGroup = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + When a job dies, launchd kills any remaining processes with the same process group ID as the job. Set-ting Setting + ting this key to true disables that behavior. + ''; + }; + + LowPriorityIO = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + This optional key specifies whether the kernel should consider this daemon to be low priority when + doing file system I/O. + ''; + }; + + LaunchOnlyOnce = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + This optional key specifies whether the job can only be run once and only once. In other words, if the + job cannot be safely respawned without a full machine reboot, then set this key to be true. + ''; + }; + + MachServices = mkOption { + default = null; + example = { ResetAtClose = true; }; + description = '' + This optional key is used to specify Mach services to be registered with the Mach bootstrap sub-system. + Each key in this dictionary should be the name of service to be advertised. The value of the key must + be a boolean and set to true. Alternatively, a dictionary can be used instead of a simple true value. + + Finally, for the job itself, the values will be replaced with Mach ports at the time of check-in with + launchd. + ''; + type = types.nullOr (types.submodule { + options = { + ResetAtClose = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + If this boolean is false, the port is recycled, thus leaving clients to remain oblivious to the + demand nature of job. If the value is set to true, clients receive port death notifications when + the job lets go of the receive right. The port will be recreated atomically with respect to boot-strap_look_up() bootstrap_look_up() + strap_look_up() calls, so that clients can trust that after receiving a port death notification, + the new port will have already been recreated. Setting the value to true should be done with + care. Not all clients may be able to handle this behavior. The default value is false. + ''; + }; + + HideUntilCheckIn = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + Reserve the name in the namespace, but cause bootstrap_look_up() to fail until the job has + checked in with launchd. + ''; + }; + }; + }); + }; + + Sockets = mkOption { + default = null; + description = '' + This optional key is used to specify launch on demand sockets that can be used to let launchd know when + to run the job. The job must check-in to get a copy of the file descriptors using APIs outlined in + launch(3). The keys of the top level Sockets dictionary can be anything. They are meant for the appli-cation application + cation developer to use to differentiate which descriptors correspond to which application level proto-cols protocols + cols (e.g. http vs. ftp vs. DNS...). At check-in time, the value of each Sockets dictionary key will + be an array of descriptors. Daemon/Agent writers should consider all descriptors of a given key to be + to be effectively equivalent, even though each file descriptor likely represents a different networking + protocol which conforms to the criteria specified in the job configuration file. + + The parameters below are used as inputs to call getaddrinfo(3). + ''; + type = types.nullOr (types.attrsOf (types.submodule { + options = { + SockType = mkOption { + type = types.nullOr (types.enum [ "stream" "dgram" "seqpacket" ]); + default = null; + description = '' + This optional key tells launchctl what type of socket to create. The default is "stream" and + other valid values for this key are "dgram" and "seqpacket" respectively. + ''; + }; + + SockPassive = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + This optional key specifies whether listen(2) or connect(2) should be called on the created file + descriptor. The default is true ("to listen"). + ''; + }; + + SockNodeName = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + This optional key specifies the node to connect(2) or bind(2) to. + ''; + }; + + SockServiceName = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + This optional key specifies the service on the node to connect(2) or bind(2) to. + ''; + }; + + SockFamily = mkOption { + type = types.nullOr (types.enum [ "IPv4" "IPv6" ]); + default = null; + description = '' + This optional key can be used to specifically request that "IPv4" or "IPv6" socket(s) be created. + ''; + }; + + SockProtocol = mkOption { + type = types.nullOr (types.enum [ "TCP" ]); + default = null; + description = '' + This optional key specifies the protocol to be passed to socket(2). The only value understood by + this key at the moment is "TCP". + ''; + }; + + SockPathName = mkOption { + type = types.nullOr types.path; + default = null; + description = '' + This optional key implies SockFamily is set to "Unix". It specifies the path to connect(2) or + bind(2) to. + ''; + }; + + SecureSocketWithKey = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + This optional key is a variant of SockPathName. Instead of binding to a known path, a securely + generated socket is created and the path is assigned to the environment variable that is inher-ited inherited + ited by all jobs spawned by launchd. + ''; + }; + + SockPathMode = mkOption { + type = types.nullOr types.int; + default = null; + description = '' + This optional key specifies the mode of the socket. Known bug: Property lists don't support + octal, so please convert the value to decimal. + ''; + }; + + Bonjour = mkOption { + type = types.nullOr (types.either types.bool (types.listOf types.str)); + default = null; + description = '' + This optional key can be used to request that the service be registered with the + mDNSResponder(8). If the value is boolean, the service name is inferred from the SockService-Name. SockServiceName. + Name. + ''; + }; + + MulticastGroup = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + This optional key can be used to request that the datagram socket join a multicast group. If the + value is a hostname, then getaddrinfo(3) will be used to join the correct multicast address for a + given socket family. If an explicit IPv4 or IPv6 address is given, it is required that the Sock-Family SockFamily + Family family also be set, otherwise the results are undefined. + ''; + }; + }; + })); + }; + }; + + config = { + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/lib-bash/activation-init.sh b/infra/libkookie/home-manager-stable/modules/lib-bash/activation-init.sh new file mode 100755 index 00000000000..aadc88dd355 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/lib-bash/activation-init.sh @@ -0,0 +1,83 @@ +#!/usr/bin/env bash + +function setupVars() { + local nixStateDir="${NIX_STATE_DIR:-/nix/var/nix}" + local profilesPath="$nixStateDir/profiles/per-user/$USER" + local gcPath="$nixStateDir/gcroots/per-user/$USER" + + declare -gr nixProfilePath="$profilesPath/profile" + declare -gr genProfilePath="$profilesPath/home-manager" + declare -gr newGenPath="@GENERATION_DIR@"; + declare -gr newGenGcPath="$gcPath/current-home" + + local greatestGenNum + greatestGenNum=$( \ + nix-env --list-generations --profile "$genProfilePath" \ + | tail -1 \ + | sed -E 's/ *([[:digit:]]+) .*/\1/') + + if [[ -n $greatestGenNum ]] ; then + declare -gr oldGenNum=$greatestGenNum + declare -gr newGenNum=$((oldGenNum + 1)) + else + declare -gr newGenNum=1 + fi + + if [[ -e $profilesPath/home-manager ]] ; then + oldGenPath="$(readlink -e "$profilesPath/home-manager")" + declare -gr oldGenPath + fi + + $VERBOSE_RUN _i "Sanity checking oldGenNum and oldGenPath" + if [[ -v oldGenNum && ! -v oldGenPath + || ! -v oldGenNum && -v oldGenPath ]]; then + _i $'The previous generation number and path are in conflict! These\nmust be either both empty or both set but are now set to\n\n \'%s\' and \'%s\'\n\nIf you don\'t mind losing previous profile generations then\nthe easiest solution is probably to run\n\n rm %s/home-manager*\n rm %s/current-home\n\nand trying home-manager switch again. Good luck!' \ + "${oldGenNum:-}" "${oldGenPath:-}" \ + "$profilesPath" "$gcPath" + exit 1 + fi +} + +if [[ -v VERBOSE ]]; then + export VERBOSE_ECHO=echo + export VERBOSE_ARG="--verbose" + export VERBOSE_RUN="" +else + export VERBOSE_ECHO=true + export VERBOSE_ARG="" + export VERBOSE_RUN=true +fi + +_i "Starting Home Manager activation" + +# Verify that we can connect to the Nix store and/or daemon. This will +# also create the necessary directories in profiles and gcroots. +$VERBOSE_RUN _i "Sanity checking Nix" +nix-build --expr '{}' --no-out-link + +setupVars + +if [[ -v DRY_RUN ]] ; then + _i "This is a dry run" + export DRY_RUN_CMD=echo +else + $VERBOSE_RUN _i "This is a live run" + export DRY_RUN_CMD="" +fi + +if [[ -v VERBOSE ]]; then + _i 'Using Nix version: %s' "$(nix-env --version)" +fi + +$VERBOSE_RUN _i "Activation variables:" +if [[ -v oldGenNum ]] ; then + $VERBOSE_ECHO " oldGenNum=$oldGenNum" + $VERBOSE_ECHO " oldGenPath=$oldGenPath" +else + $VERBOSE_ECHO " oldGenNum undefined (first run?)" + $VERBOSE_ECHO " oldGenPath undefined (first run?)" +fi +$VERBOSE_ECHO " newGenPath=$newGenPath" +$VERBOSE_ECHO " newGenNum=$newGenNum" +$VERBOSE_ECHO " newGenGcPath=$newGenGcPath" +$VERBOSE_ECHO " genProfilePath=$genProfilePath" diff --git a/infra/libkookie/home-manager-stable/modules/lib-bash/color-echo.sh b/infra/libkookie/home-manager-stable/modules/lib-bash/color-echo.sh new file mode 100644 index 00000000000..ac36cedc6e8 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/lib-bash/color-echo.sh @@ -0,0 +1,39 @@ +# The check for terminal output and color support is heavily inspired +# by https://unix.stackexchange.com/a/10065. +# +# Allow opt out by respecting the `NO_COLOR` environment variable. + +function setupColors() { + normalColor="" + errorColor="" + warnColor="" + noteColor="" + + # Enable colors for terminals, and allow opting out. + if [[ ! -v NO_COLOR && -t 1 ]]; then + # See if it supports colors. + local ncolors + ncolors=$(tput colors) + + if [[ -n "$ncolors" && "$ncolors" -ge 8 ]]; then + normalColor="$(tput sgr0)" + errorColor="$(tput bold)$(tput setaf 1)" + warnColor="$(tput setaf 3)" + noteColor="$(tput bold)$(tput setaf 6)" + fi + fi +} + +setupColors + +function errorEcho() { + echo "${errorColor}$*${normalColor}" +} + +function warnEcho() { + echo "${warnColor}$*${normalColor}" +} + +function noteEcho() { + echo "${noteColor}$*${normalColor}" +} diff --git a/infra/libkookie/home-manager-stable/modules/lib/assertions.nix b/infra/libkookie/home-manager-stable/modules/lib/assertions.nix new file mode 100644 index 00000000000..1089c27b858 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/lib/assertions.nix @@ -0,0 +1,14 @@ +{ lib }: + +{ + assertPlatform = module: pkgs: platforms: { + assertion = lib.elem pkgs.stdenv.hostPlatform.system platforms; + message = let + platformsStr = lib.concatStringsSep "\n" + (map (p: " - ${p}") (lib.sort (a: b: a < b) platforms)); + in '' + The module ${module} does not support your platform. It only supports + + ${platformsStr}''; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/lib/booleans.nix b/infra/libkookie/home-manager-stable/modules/lib/booleans.nix new file mode 100644 index 00000000000..f6c2af586e7 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/lib/booleans.nix @@ -0,0 +1,5 @@ +{ lib }: { + # Converts a boolean to a yes/no string. This is used in lots of + # configuration formats. + yesNo = value: if value then "yes" else "no"; +} diff --git a/infra/libkookie/home-manager-stable/modules/lib/dag.nix b/infra/libkookie/home-manager-stable/modules/lib/dag.nix new file mode 100644 index 00000000000..0c0e33ee767 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/lib/dag.nix @@ -0,0 +1,116 @@ +# A generalization of Nixpkgs's `strings-with-deps.nix`. +# +# The main differences from the Nixpkgs version are +# +# - not specific to strings, i.e., any payload is OK, +# +# - the addition of the function `dagEntryBefore` indicating a +# "wanted by" relationship. + +{ lib }: + +let inherit (lib) all any filterAttrs mapAttrs mapAttrsToList toposort; +in rec { + + emptyDag = { }; + + isDag = dag: + let isEntry = e: (e ? data) && (e ? after) && (e ? before); + in builtins.isAttrs dag && all (x: x) (mapAttrsToList (n: isEntry) dag); + + # Takes an attribute set containing entries built by + # dagEntryAnywhere, dagEntryAfter, and dagEntryBefore to a + # topologically sorted list of entries. + # + # Internally this function uses the `toposort` function in + # `` and its value is accordingly. + # + # Specifically, the result on success is + # + # { result = [{name = ?; data = ?;} …] } + # + # For example + # + # nix-repl> dagTopoSort { + # a = dagEntryAnywhere "1"; + # b = dagEntryAfter ["a" "c"] "2"; + # c = dagEntryBefore ["d"] "3"; + # d = dagEntryBefore ["e"] "4"; + # e = dagEntryAnywhere "5"; + # } == { + # result = [ + # { data = "1"; name = "a"; } + # { data = "3"; name = "c"; } + # { data = "2"; name = "b"; } + # { data = "4"; name = "d"; } + # { data = "5"; name = "e"; } + # ]; + # } + # true + # + # And the result on error is + # + # { + # cycle = [ {after = ?; name = ?; data = ?} … ]; + # loops = [ {after = ?; name = ?; data = ?} … ]; + # } + # + # For example + # + # nix-repl> dagTopoSort { + # a = dagEntryAnywhere "1"; + # b = dagEntryAfter ["a" "c"] "2"; + # c = dagEntryAfter ["d"] "3"; + # d = dagEntryAfter ["b"] "4"; + # e = dagEntryAnywhere "5"; + # } == { + # cycle = [ + # { after = ["a" "c"]; data = "2"; name = "b"; } + # { after = ["d"]; data = "3"; name = "c"; } + # { after = ["b"]; data = "4"; name = "d"; } + # ]; + # loops = [ + # { after = ["a" "c"]; data = "2"; name = "b"; } + # ]; + # } == {} + # true + dagTopoSort = dag: + let + dagBefore = dag: name: + mapAttrsToList (n: v: n) + (filterAttrs (n: v: any (a: a == name) v.before) dag); + normalizedDag = mapAttrs (n: v: { + name = n; + data = v.data; + after = v.after ++ dagBefore dag n; + }) dag; + before = a: b: any (c: a.name == c) b.after; + sorted = toposort before (mapAttrsToList (n: v: v) normalizedDag); + in if sorted ? result then { + result = map (v: { inherit (v) name data; }) sorted.result; + } else + sorted; + + # Applies a function to each element of the given DAG. + dagMap = f: dag: mapAttrs (n: v: v // { data = f n v.data; }) dag; + + # Create a DAG entry with no particular dependency information. + dagEntryAnywhere = data: { + inherit data; + before = [ ]; + after = [ ]; + }; + + dagEntryBetween = before: after: data: { inherit data before after; }; + + dagEntryAfter = after: data: { + inherit data after; + before = [ ]; + }; + + dagEntryBefore = before: data: { + inherit data before; + after = [ ]; + }; + +} diff --git a/infra/libkookie/home-manager-stable/modules/lib/default.nix b/infra/libkookie/home-manager-stable/modules/lib/default.nix new file mode 100644 index 00000000000..580316e099f --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/lib/default.nix @@ -0,0 +1,29 @@ +{ lib }: + +rec { + dag = + let + d = import ./dag.nix { inherit lib; }; + in + { + empty = d.emptyDag; + isDag = d.isDag; + topoSort = d.dagTopoSort; + map = d.dagMap; + entryAnywhere = d.dagEntryAnywhere; + entryBetween = d.dagEntryBetween; + entryAfter = d.dagEntryAfter; + entryBefore = d.dagEntryBefore; + }; + + assertions = import ./assertions.nix { inherit lib; }; + + booleans = import ./booleans.nix { inherit lib; }; + gvariant = import ./gvariant.nix { inherit lib; }; + maintainers = import ./maintainers.nix; + strings = import ./strings.nix { inherit lib; }; + types = import ./types.nix { inherit dag gvariant lib; }; + + shell = import ./shell.nix { inherit lib; }; + zsh = import ./zsh.nix { inherit lib; }; +} diff --git a/infra/libkookie/home-manager-stable/modules/lib/file-type.nix b/infra/libkookie/home-manager-stable/modules/lib/file-type.nix new file mode 100644 index 00000000000..0b30cb1b693 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/lib/file-type.nix @@ -0,0 +1,116 @@ +{ homeDirectory, lib, pkgs }: + +let + inherit (lib) hasPrefix hm literalExpression mkDefault mkIf mkOption removePrefix types; +in +{ + # Constructs a type suitable for a `home.file` like option. The + # target path may be either absolute or relative, in which case it + # is relative the `basePath` argument (which itself must be an + # absolute path). + # + # Arguments: + # - basePathDesc docbook compatible description of the base path + # - basePath the file base path + fileType = basePathDesc: basePath: types.attrsOf (types.submodule ( + { name, config, ... }: { + options = { + target = mkOption { + type = types.str; + apply = p: + let + absPath = if hasPrefix "/" p then p else "${basePath}/${p}"; + in + removePrefix (homeDirectory + "/") absPath; + defaultText = literalExpression ""; + description = '' + Path to target file relative to ${basePathDesc}. + ''; + }; + + text = mkOption { + default = null; + type = types.nullOr types.lines; + description = '' + Text of the file. If this option is null then + home.file.<name?>.source + must be set. + ''; + }; + + source = mkOption { + type = types.path; + description = '' + Path of the source file or directory. If + home.file.<name?>.text + is non-null then this option will automatically point to a file + containing that text. + ''; + }; + + executable = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + Set the execute bit. If null, defaults to the mode + of the source file or to false + for files created through the text option. + ''; + }; + + recursive = mkOption { + type = types.bool; + default = false; + description = '' + If the file source is a directory, then this option + determines whether the directory should be recursively + linked to the target location. This option has no effect + if the source is a file. + + If false (the default) then the target + will be a symbolic link to the source directory. If + true then the target will be a + directory structure matching the source's but whose leafs + are symbolic links to the files of the source directory. + ''; + }; + + onChange = mkOption { + type = types.lines; + default = ""; + description = '' + Shell commands to run when file has changed between + generations. The script will be run + after the new files have been linked + into place. + + Note, this code is always run when recursive is + enabled. + ''; + }; + + force = mkOption { + type = types.bool; + default = false; + visible = false; + description = '' + Whether the target path should be unconditionally replaced + by the managed file source. Warning, this will silently + delete the target regardless of whether it is a file or + link. + ''; + }; + }; + + config = { + target = mkDefault name; + source = mkIf (config.text != null) ( + mkDefault (pkgs.writeTextFile { + inherit (config) executable text; + name = hm.strings.storeFileName name; + }) + ); + }; + } + )); +} diff --git a/infra/libkookie/home-manager-stable/modules/lib/gvariant.nix b/infra/libkookie/home-manager-stable/modules/lib/gvariant.nix new file mode 100644 index 00000000000..7c4ca5b08c6 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/lib/gvariant.nix @@ -0,0 +1,159 @@ +# A partial and basic implementation of GVariant formatted strings. +# +# Note, this API is not considered fully stable and it might therefore +# change in backwards incompatible ways without prior notice. + +{ lib }: + +let + inherit (lib) + concatMapStringsSep concatStrings escape hasPrefix head replaceStrings; + + mkPrimitive = t: v: { + _type = "gvariant"; + type = t; + value = v; + __toString = self: "@${self.type} ${toString self.value}"; + }; + + type = { + arrayOf = t: "a${t}"; + maybeOf = t: "m${t}"; + tupleOf = ts: "(${concatStrings ts})"; + string = "s"; + boolean = "b"; + uchar = "y"; + int16 = "n"; + uint16 = "q"; + int32 = "i"; + uint32 = "u"; + int64 = "x"; + uint64 = "t"; + double = "d"; + }; + + # Returns the GVariant type of a given Nix value. If no type can be + # found for the value then the empty string is returned. + typeOf = v: + with type; + if builtins.isBool v then + boolean + else if builtins.isInt v then + int32 + else if builtins.isFloat v then + double + else if builtins.isString v then + string + else if builtins.isList v then + let elemType = elemTypeOf v; + in if elemType == "" then "" else arrayOf elemType + else if builtins.isAttrs v && v ? type then + v.type + else + ""; + + elemTypeOf = vs: + if builtins.isList vs then + if vs == [ ] then "" else typeOf (head vs) + else + ""; + + mkMaybe = elemType: elem: + mkPrimitive (type.maybeOf elemType) elem // { + __toString = self: + if self.value == null then + "@${self.type} nothing" + else + "just ${toString self.value}"; + }; + +in rec { + + inherit type typeOf; + + isGVariant = v: v._type or "" == "gvariant"; + + isArray = hasPrefix "a"; + isMaybe = hasPrefix "m"; + isTuple = hasPrefix "("; + + # Returns the GVariant value that most closely matches the given Nix + # value. If no GVariant value can be found then `null` is returned. + # + # No support for dictionaries, maybe types, or variants. + mkValue = v: + if builtins.isBool v then + mkBoolean v + else if builtins.isInt v then + mkInt32 v + else if builtins.isFloat v then + mkDouble v + else if builtins.isString v then + mkString v + else if builtins.isList v then + if v == [ ] then mkArray type.string [ ] else mkArray (elemTypeOf v) v + else if builtins.isAttrs v && (v._type or "") == "gvariant" then + v + else + null; + + mkArray = elemType: elems: + mkPrimitive (type.arrayOf elemType) (map mkValue elems) // { + __toString = self: + "@${self.type} [${concatMapStringsSep "," toString self.value}]"; + }; + + mkEmptyArray = elemType: mkArray elemType [ ]; + + mkNothing = elemType: mkMaybe elemType null; + + mkJust = elem: let gvarElem = mkValue elem; in mkMaybe gvarElem.type gvarElem; + + mkTuple = elems: + let + gvarElems = map mkValue elems; + tupleType = type.tupleOf (map (e: e.type) gvarElems); + in mkPrimitive tupleType gvarElems // { + __toString = self: + "@${self.type} (${concatMapStringsSep "," toString self.value})"; + }; + + mkBoolean = v: + mkPrimitive type.boolean v // { + __toString = self: if self.value then "true" else "false"; + }; + + mkString = v: + let sanitize = s: replaceStrings [ "\n" ] [ "\\n" ] (escape [ "'" "\\" ] s); + in mkPrimitive type.string v // { + __toString = self: "'${sanitize self.value}'"; + }; + + mkObjectpath = v: + mkPrimitive type.string v // { + __toString = self: "objectpath '${escape [ "'" ] self.value}'"; + }; + + mkUchar = mkPrimitive type.uchar; + + mkInt16 = mkPrimitive type.int16; + + mkUint16 = mkPrimitive type.uint16; + + mkInt32 = v: + mkPrimitive type.int32 v // { + __toString = self: toString self.value; + }; + + mkUint32 = mkPrimitive type.uint32; + + mkInt64 = mkPrimitive type.int64; + + mkUint64 = mkPrimitive type.uint64; + + mkDouble = v: + mkPrimitive type.double v // { + __toString = self: toString self.value; + }; + +} diff --git a/infra/libkookie/home-manager-stable/modules/lib/maintainers.nix b/infra/libkookie/home-manager-stable/modules/lib/maintainers.nix new file mode 100644 index 00000000000..a485d6cddde --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/lib/maintainers.nix @@ -0,0 +1,274 @@ +# Home Manager maintainers. +# +# This attribute set contains Home Manager module maintainers that do +# not have an entry in the Nixpkgs maintainer list [1]. Entries here +# are expected to be follow the same format as described in [1]. +# +# [1] https://github.com/NixOS/nixpkgs/blob/fca0d6e093c82b31103dc0dacc48da2a9b06e24b/maintainers/maintainer-list.nix#LC1 + +{ + amesgen = { + name = "amesgen"; + email = "amesgen@amesgen.de"; + github = "amesgen"; + githubId = 15369874; + }; + austreelis = { + email = "github@accounts.austreelis.net"; + github = "Austreelis"; + githubId = 56743515; + name = "Morgane Austreelis"; + }; + CarlosLoboxyz = { + name = "Carlos Lobo"; + email = "86011416+CarlosLoboxyz@users.noreply.github.com"; + github = "CarlosLoboxyz"; + githubId = 86011416; + }; + dwagenk = { + email = "dwagenk@mailbox.org"; + github = "dwagenk"; + githubId = 32838899; + name = "Daniel Wagenknecht"; + }; + justinlovinger = { + name = "Justin Lovinger"; + email = "git@justinlovinger.com"; + github = "JustinLovinger"; + githubId = 7183441; + }; + owm111 = { + email = "7798336+owm111@users.noreply.github.com"; + name = "Owen McGrath"; + github = "owm111"; + githubId = 7798336; + }; + cwyc = { + email = "cwyc@users.noreply.github.com"; + name = "cwyc"; + github = "cwyc"; + githubId = 16950437; + }; + chisui = { + name = "Philipp Dargel"; + email = "chisui@users.noreply.github.com"; + github = "chisui"; + githubId = 4526429; + }; + foo-dogsquared = { + name = "Gabriel Arazas"; + email = "foo.dogsquared@gmail.com"; + github = "foo-dogsquared"; + githubId = 34962634; + }; + olmokramer = { + name = "Olmo Kramer"; + email = "olmokramer@users.noreply.github.com"; + github = "olmokramer"; + githubId = 3612514; + }; + iosmanthus = { + name = "iosmanthus"; + email = "myosmanthustree@gmail.com"; + github = "iosmanthus"; + githubId = 16307070; + }; + kalhauge = { + name = "Christian Gram Kalhauge"; + email = "kalhauge@users.noreply.github.com"; + github = "kalhauge"; + githubId = 1182166; + }; + kamadorueda = { + name = "Kevin Amado"; + email = "kamadorueda@gmail.com"; + github = "kamadorueda"; + githubId = 47480384; + keys = [{ + longkeyid = "rsa4096/0x04D0CEAF916A9A40"; + fingerprint = "2BE3 BAFD 793E A349 ED1F F00F 04D0 CEAF 916A 9A40"; + }]; + }; + kubukoz = { + name = "Jakub Kozłowski"; + email = "kubukoz@users.noreply.github.com"; + github = "kubukoz"; + githubId = 894884; + }; + loicreynier = { + name = "Loïc Reynier"; + email = "loic@loireynier.fr"; + github = "loicreynier"; + githubId = 88983487; + }; + matrss = { + name = "Matthias Riße"; + email = "matrss@users.noreply.github.com"; + github = "matrss"; + githubId = 9308656; + }; + mifom = { + name = "mifom"; + email = "mifom@users.noreply.github.com"; + github = "mifom"; + githubId = 23462908; + }; + seylerius = { + email = "sable@seyleri.us"; + name = "Sable Seyler"; + github = "seylerius"; + githubId = 1145981; + keys = [{ + logkeyid = "rsa4096/0x68BF2EAE6D91CAFF"; + fingerprint = "F0E0 0311 126A CD72 4392 25E6 68BF 2EAE 6D91 CAFF"; + }]; + }; + fendse = { + email = "46252070+Fendse@users.noreply.github.com"; + github = "Fendse"; + githubId = 46252070; + name = "Sara Johnsson"; + }; + florpe = { + email = "jens.krewald@gmail.com"; + github = "florpe"; + githubId = 53856373; + name = "Jens Krewald"; + }; + maximsmol = { + email = "maximsmol@gmail.com"; + github = "maximsmol"; + githubId = 1472826; + name = "Max Smolin"; + }; + msfjarvis = { + email = "me@msfjarvis.dev"; + github = "msfjarvis"; + githubId = "13348378"; + name = "Harsh Shandilya"; + keys = [{ + longkeyid = "rsa4096/0xB7843F823355E9B9"; + fingerprint = "8F87 050B 0F9C B841 1515 7399 B784 3F82 3355 E9B9"; + }]; + }; + ambroisie = { + email = "bruno.home-manager@belanyi.fr"; + github = "ambroisie"; + githubId = 12465195; + name = "Bruno BELANYI"; + }; + malvo = { + email = "malte@malvo.org"; + github = "malte-v"; + githubId = 34393802; + name = "Malte Voos"; + }; + kranzes = { + email = "personal@ilanjoselevich.com"; + github = "Kranzes"; + githubId = 56614642; + name = "Ilan Joselevich"; + }; + mager = { + email = "andreas@mager.eu"; + github = "AndreasMager"; + githubId = 5646732; + name = "Andreas Mager"; + }; + bjpbakker = { + email = "bart@thesoftwarecraft.com"; + github = "bjpbakker"; + githubId = 605641; + name = "Bart Bakker"; + }; + jrobsonchase = { + email = "josh@robsonchase.com"; + github = "jrobsonchase"; + githubId = 1553581; + name = "Josh Robson Chase"; + }; + hawkw = { + name = "Eliza Weisman"; + email = "eliza@elizas.website"; + github = "hawkw"; + githubId = 2796466; + }; + pamplemousse = { + name = "Xavier Maso"; + email = "xav.maso@gmail.com"; + github = "pamplemousse"; + githubId = 2647236; + }; + onny = { + name = "onny"; + email = "onny@project-insanity.org"; + github = "onny"; + githubId = 757752; + }; + aheaume = { + name = "aheaume"; + email = "aheaume@users.noreply.github.com"; + github = "aheaume"; + githubId = 13830042; + }; + t4ccer = { + name = "t4ccer"; + email = "t4ccer@users.noreply.github.com"; + github = "t4ccer"; + githubId = 64430288; + }; + nurelin = { + name = "nurelin"; + email = "nurelin@users.noreply.github.com"; + github = "nurelin"; + githubId = 5276274; + }; + pltanton = { + name = "pltanton"; + email = "plotnikovanton@gmail.com"; + github = "pltanton"; + githubId = 4561823; + }; + Philipp-M = { + email = "philipp@mildenberger.me"; + github = "Philipp-M"; + githubId = 9267430; + name = "Philipp Mildenberger"; + }; + pinage404 = { + name = "pinage404"; + email = "pinage404@gmail.com"; + github = "pinage404"; + githubId = 6325757; + }; + podocarp = { + name = "Jia Xiaodong"; + email = "xdjiaxd@gmail.com"; + github = "podocarp"; + githubId = 10473184; + }; + mainrs = { + name = "mainrs"; + email = "5113257+mainrs@users.noreply.github.com"; + github = "mainrs"; + githubId = 5113257; + }; + kmaasrud = { + name = "Knut Magnus Aasrud"; + email = "km@aasrud.com"; + github = "kmaasrud"; + githubId = 54394333; + }; + sebtm = { + name = "Sebastian Sellmeier"; + email = "sebtm@users.noreply.github.com"; + github = "sebtm"; + githubId = 17243347; + }; + rszamszur = { + name = "Radosław Szamszur"; + email = "radoslawszamszur@gmail.com"; + github = "rszamszur"; + githubId = 10353018; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/lib/shell.nix b/infra/libkookie/home-manager-stable/modules/lib/shell.nix new file mode 100644 index 00000000000..5e5743f51ea --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/lib/shell.nix @@ -0,0 +1,11 @@ +{ lib }: + +rec { + # Produces a Bourne shell like variable export statement. + export = n: v: ''export ${n}="${toString v}"''; + + # Given an attribute set containing shell variable names and their + # assignment, this function produces a string containing an export + # statement for each set entry. + exportAll = vars: lib.concatStringsSep "\n" (lib.mapAttrsToList export vars); +} diff --git a/infra/libkookie/home-manager-stable/modules/lib/stdlib-extended.nix b/infra/libkookie/home-manager-stable/modules/lib/stdlib-extended.nix new file mode 100644 index 00000000000..3c4e032aa97 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/lib/stdlib-extended.nix @@ -0,0 +1,13 @@ +# Just a convenience function that returns the given Nixpkgs standard +# library extended with the HM library. + +nixpkgsLib: + +let mkHmLib = import ./.; +in nixpkgsLib.extend (self: super: { + hm = mkHmLib { lib = self; }; + + # For forward compatibility. + literalExpression = super.literalExpression or super.literalExample; + literalDocBook = super.literalDocBook or super.literalExample; +}) diff --git a/infra/libkookie/home-manager-stable/modules/lib/strings.nix b/infra/libkookie/home-manager-stable/modules/lib/strings.nix new file mode 100644 index 00000000000..f59d8150809 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/lib/strings.nix @@ -0,0 +1,23 @@ +{ lib }: + +let + inherit (lib) + genList length lowerChars replaceStrings stringToCharacters upperChars; +in { + # Figures out a valid Nix store name for the given path. + storeFileName = path: + let + # All characters that are considered safe. Note "-" is not + # included to avoid "-" followed by digit being interpreted as a + # version. + safeChars = [ "+" "." "_" "?" "=" ] ++ lowerChars ++ upperChars + ++ stringToCharacters "0123456789"; + + empties = l: genList (x: "") (length l); + + unsafeInName = + stringToCharacters (replaceStrings safeChars (empties safeChars) path); + + safeName = replaceStrings unsafeInName (empties unsafeInName) path; + in "hm_" + safeName; +} diff --git a/infra/libkookie/home-manager-stable/modules/lib/types-dag.nix b/infra/libkookie/home-manager-stable/modules/lib/types-dag.nix new file mode 100644 index 00000000000..366cc2bee70 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/lib/types-dag.nix @@ -0,0 +1,106 @@ +{ dag, lib }: + +let + inherit (lib) + concatStringsSep defaultFunctor fixedWidthNumber imap1 isAttrs isList length + listToAttrs mapAttrs mkIf mkOption mkOptionType nameValuePair stringLength + types warn; + + isDagEntry = e: isAttrs e && (e ? data) && (e ? after) && (e ? before); + + dagEntryOf = elemType: + let + submoduleType = types.submodule ({ name, ... }: { + options = { + data = mkOption { type = elemType; }; + after = mkOption { type = with types; uniq (listOf str); }; + before = mkOption { type = with types; uniq (listOf str); }; + }; + config = mkIf (elemType.name == "submodule") { + data._module.args.dagName = name; + }; + }); + maybeConvert = v: if isDagEntry v then v else dag.entryAnywhere v; + in mkOptionType { + name = "dagEntryOf"; + description = "DAG entry of ${elemType.description}"; + # leave the checking to the submodule type + merge = loc: defs: + submoduleType.merge loc + (map (def: def // { value = maybeConvert def.value; }) defs); + }; + +in rec { + # A directed acyclic graph of some inner type. + # + # Note, if the element type is a submodule then the `name` argument + # will always be set to the string "data" since it picks up the + # internal structure of the DAG values. To give access to the + # "actual" attribute name a new submodule argument is provided with + # the name `dagName`. + dagOf = elemType: + let attrEquivalent = types.attrsOf (dagEntryOf elemType); + in mkOptionType rec { + name = "dagOf"; + description = "DAG of ${elemType.description}s"; + inherit (attrEquivalent) check merge emptyValue; + getSubOptions = prefix: elemType.getSubOptions (prefix ++ [ "" ]); + getSubModules = elemType.getSubModules; + substSubModules = m: dagOf (elemType.substSubModules m); + functor = (defaultFunctor name) // { wrapped = elemType; }; + nestedTypes.elemType = elemType; + }; + + # A directed acyclic graph of some inner type OR a list of that + # inner type. This is a temporary hack for use by the + # `programs.ssh.matchBlocks` and is only guaranteed to be vaguely + # correct! + # + # In particular, adding a dependency on one of the "unnamed-N-M" + # entries generated by a list value is almost guaranteed to destroy + # the list's order. + # + # This function will be removed in version 20.09. + listOrDagOf = elemType: + let + paddedIndexStr = list: i: + let padWidth = stringLength (toString (length list)); + in fixedWidthNumber padWidth i; + + convertAll = loc: defs: + let + convertListValue = namePrefix: def: + let + vs = def.value; + pad = paddedIndexStr vs; + makeEntry = i: v: nameValuePair "${namePrefix}.${pad i}" v; + warning = '' + In file ${def.file} + a list is being assigned to the option '${ + concatStringsSep "." loc + }'. + This will soon be an error due to the list form being deprecated. + Please use the attribute set form instead with DAG functions to + express the desired order of entries. + ''; + in warn warning (listToAttrs (imap1 makeEntry vs)); + + convertValue = i: def: + if isList def.value then + convertListValue "unnamed-${paddedIndexStr defs i}" def + else + def.value; + in imap1 (i: def: def // { value = convertValue i def; }) defs; + + dagType = dagOf elemType; + in mkOptionType rec { + name = "listOrDagOf"; + description = "list or DAG of ${elemType.description}s"; + check = x: isList x || dagType.check x; + merge = loc: defs: dagType.merge loc (convertAll loc defs); + getSubOptions = dagType.getSubOptions; + getSubModules = dagType.getSubModules; + substSubModules = m: listOrDagOf (elemType.substSubModules m); + functor = (defaultFunctor name) // { wrapped = elemType; }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/lib/types.nix b/infra/libkookie/home-manager-stable/modules/lib/types.nix new file mode 100644 index 00000000000..71ec587f1ab --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/lib/types.nix @@ -0,0 +1,107 @@ +{ lib, dag ? import ./dag.nix { inherit lib; } +, gvariant ? import ./gvariant.nix { inherit lib; } }: + +let + inherit (lib) + all concatMap foldl' getFiles getValues head isFunction literalExpression + mergeAttrs mergeDefaultOption mergeOneOption mergeOptions mkOption + mkOptionType showFiles showOption types; + + typesDag = import ./types-dag.nix { inherit dag lib; }; + + # Needed since the type is called gvariant and its merge attribute + # must refer back to the type. + gvar = gvariant; + +in rec { + + inherit (typesDag) dagOf listOrDagOf; + + selectorFunction = mkOptionType { + name = "selectorFunction"; + description = "Function that takes an attribute set and returns a list" + + " containing a selection of the values of the input set"; + check = isFunction; + merge = _loc: defs: as: concatMap (select: select as) (getValues defs); + }; + + overlayFunction = mkOptionType { + name = "overlayFunction"; + description = "An overlay function, takes self and super and returns" + + " an attribute set overriding the desired attributes."; + check = isFunction; + merge = _loc: defs: self: super: + foldl' (res: def: mergeAttrs res (def.value self super)) { } defs; + }; + + fontType = types.submodule { + options = { + package = mkOption { + type = types.nullOr types.package; + default = null; + example = literalExpression "pkgs.dejavu_fonts"; + description = '' + Package providing the font. This package will be installed + to your profile. If null then the font + is assumed to already be available in your profile. + ''; + }; + + name = mkOption { + type = types.str; + example = "DejaVu Sans"; + description = '' + The family name of the font within the package. + ''; + }; + + size = mkOption { + type = types.nullOr types.int; + default = null; + example = "8"; + description = '' + The size of the font. + ''; + }; + }; + }; + + gvariant = mkOptionType rec { + name = "gvariant"; + description = "GVariant value"; + check = v: gvar.mkValue v != null; + merge = loc: defs: + let + vdefs = map (d: + d // { + value = + if gvar.isGVariant d.value then d.value else gvar.mkValue d.value; + }) defs; + vals = map (d: d.value) vdefs; + defTypes = map (x: x.type) vals; + sameOrNull = x: y: if x == y then y else null; + # A bit naive to just check the first entry… + sharedDefType = foldl' sameOrNull (head defTypes) defTypes; + allChecked = all (x: check x) vals; + in if sharedDefType == null then + throw ("Cannot merge definitions of `${showOption loc}' with" + + " mismatched GVariant types given in" + + " ${showFiles (getFiles defs)}.") + else if gvar.isArray sharedDefType && allChecked then + gvar.mkValue ((types.listOf gvariant).merge loc + (map (d: d // { value = d.value.value; }) vdefs)) // { + type = sharedDefType; + } + else if gvar.isTuple sharedDefType && allChecked then + mergeOneOption loc defs + else if gvar.isMaybe sharedDefType && allChecked then + mergeOneOption loc defs + else if gvar.type.string == sharedDefType && allChecked then + types.str.merge loc defs + else if gvar.type.double == sharedDefType && allChecked then + types.float.merge loc defs + else + mergeDefaultOption loc defs; + }; + +} diff --git a/infra/libkookie/home-manager-stable/modules/lib/zsh.nix b/infra/libkookie/home-manager-stable/modules/lib/zsh.nix new file mode 100644 index 00000000000..c6901350f50 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/lib/zsh.nix @@ -0,0 +1,30 @@ +{ lib }: + +rec { + # Produces a Zsh shell like value + toZshValue = v: + if builtins.isBool v then + if v then "true" else "false" + else if builtins.isString v then + ''"${v}"'' + else if builtins.isList v then + "(${lib.concatStringsSep " " (map toZshValue v)})" + else + ''"${toString v}"''; + + # Produces a Zsh shell like definition statement + define = n: v: "${n}=${toZshValue v}"; + + # Given an attribute set containing shell variable names and their + # assignments, this function produces a string containing a definition + # statement for each set entry. + defineAll = vars: lib.concatStringsSep "\n" (lib.mapAttrsToList define vars); + + # Produces a Zsh shell like export statement + export = n: v: "export ${define n v}"; + + # Given an attribute set containing shell variable names and their + # assignments, this function produces a string containing an export + # statement for each set entry. + exportAll = vars: lib.concatStringsSep "\n" (lib.mapAttrsToList export vars); +} diff --git a/infra/libkookie/home-manager-stable/modules/manual.nix b/infra/libkookie/home-manager-stable/modules/manual.nix new file mode 100644 index 00000000000..a5c020510f5 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/manual.nix @@ -0,0 +1,68 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.manual; + + docs = import ../docs { inherit lib pkgs; }; + +in + +{ + options = { + manual.html.enable = mkOption { + type = types.bool; + default = false; + description = '' + Whether to install the HTML manual. This also installs the + home-manager-help tool, which opens a local + copy of the Home Manager manual in the system web browser. + ''; + }; + + manual.manpages.enable = mkOption { + type = types.bool; + default = true; + example = false; + description = '' + Whether to install the configuration manual page. The manual can + be reached by man home-configuration.nix. + + When looking at the manual page pretend that all references to + NixOS stuff are actually references to Home Manager stuff. + Thanks! + ''; + }; + + manual.json.enable = mkOption { + type = types.bool; + default = false; + example = true; + description = '' + Whether to install a JSON formatted list of all Home Manager + options. This can be located at + <profile directory>/share/doc/home-manager/options.json, + and may be used for navigating definitions, auto-completing, + and other miscellaneous tasks. + ''; + }; + }; + + config = { + home.packages = mkMerge [ + (mkIf cfg.html.enable [ docs.manual.html docs.manual.htmlOpenTool ]) + (mkIf cfg.manpages.enable [ docs.manPages ]) + (mkIf cfg.json.enable [ docs.options.json ]) + ]; + + # Whether a dependency on nmd should be introduced. + home.extraBuilderCommands = + mkIf (cfg.html.enable || cfg.manpages.enable || cfg.json.enable) '' + mkdir $out/lib + ln -s ${docs.nmdSrc} $out/lib/nmd + ''; + }; + +} diff --git a/infra/libkookie/home-manager-stable/modules/misc/dconf.nix b/infra/libkookie/home-manager-stable/modules/misc/dconf.nix new file mode 100644 index 00000000000..d731679c380 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/misc/dconf.nix @@ -0,0 +1,75 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.dconf; + + toDconfIni = generators.toINI { mkKeyValue = mkIniKeyValue; }; + + mkIniKeyValue = key: value: "${key}=${toString (hm.gvariant.mkValue value)}"; + +in { + meta.maintainers = [ maintainers.rycee ]; + + options = { + dconf = { + enable = mkOption { + type = types.bool; + default = true; + visible = false; + description = '' + Whether to enable dconf settings. + + Note, if you use NixOS then you must add + programs.dconf.enable = true + to your system configuration. Otherwise you will see a systemd error + message when your configuration is activated. + ''; + }; + + settings = mkOption { + type = with types; attrsOf (attrsOf hm.types.gvariant); + default = { }; + example = literalExpression '' + { + "org/gnome/calculator" = { + button-mode = "programming"; + show-thousands = true; + base = 10; + word-size = 64; + window-position = lib.hm.gvariant.mkTuple [100 100]; + }; + } + ''; + description = '' + Settings to write to the dconf configuration system. + ''; + }; + }; + }; + + config = mkIf (cfg.enable && cfg.settings != { }) { + # Make sure the dconf directory exists. + xdg.configFile."dconf/.keep".source = builtins.toFile "keep" ""; + + home.activation.dconfSettings = hm.dag.entryAfter [ "installPackages" ] + (let iniFile = pkgs.writeText "hm-dconf.ini" (toDconfIni cfg.settings); + in '' + if [[ -v DBUS_SESSION_BUS_ADDRESS ]]; then + DCONF_DBUS_RUN_SESSION="" + else + DCONF_DBUS_RUN_SESSION="${pkgs.dbus}/bin/dbus-run-session" + fi + + if [[ -v DRY_RUN ]]; then + echo $DCONF_DBUS_RUN_SESSION ${pkgs.dconf}/bin/dconf load / "<" ${iniFile} + else + $DCONF_DBUS_RUN_SESSION ${pkgs.dconf}/bin/dconf load / < ${iniFile} + fi + + unset DCONF_DBUS_RUN_SESSION + ''); + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/misc/debug.nix b/infra/libkookie/home-manager-stable/modules/misc/debug.nix new file mode 100644 index 00000000000..d27d496b423 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/misc/debug.nix @@ -0,0 +1,26 @@ +{ config, pkgs, lib, ... }: + +with lib; + +{ + options.home = { + enableDebugInfo = mkEnableOption "" // { + description = '' + Some Nix-packages provide debug symbols for + gdb in the debug-output. + This option ensures that those are automatically fetched from + the binary cache if available and gdb is + configured to find those symbols. + ''; + }; + }; + + config = mkIf config.home.enableDebugInfo { + home.extraOutputsToInstall = [ "debug" ]; + + home.sessionVariables = { + NIX_DEBUG_INFO_DIRS = + "$NIX_DEBUG_INFO_DIRS\${NIX_DEBUG_INFO_DIRS:+:}${config.home.profileDirectory}/lib/debug"; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/misc/fontconfig.nix b/infra/libkookie/home-manager-stable/modules/misc/fontconfig.nix new file mode 100644 index 00000000000..756f45699d0 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/misc/fontconfig.nix @@ -0,0 +1,95 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.fonts.fontconfig; + + profileDirectory = config.home.profileDirectory; + +in { + meta.maintainers = [ maintainers.rycee ]; + + imports = [ + (mkRenamedOptionModule [ "fonts" "fontconfig" "enableProfileFonts" ] [ + "fonts" + "fontconfig" + "enable" + ]) + ]; + + options = { + fonts.fontconfig = { + enable = mkOption { + type = types.bool; + default = false; + description = '' + Whether to enable fontconfig configuration. This will, for + example, allow fontconfig to discover fonts and + configurations installed through + home.packages and + nix-env. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ + # Make sure that buildEnv creates a real directory path so that we avoid + # trying to write to a read-only location. + (pkgs.runCommandLocal "dummy-fc-dir1" { } "mkdir -p $out/lib/fontconfig") + (pkgs.runCommandLocal "dummy-fc-dir2" { } "mkdir -p $out/lib/fontconfig") + ]; + + home.extraProfileCommands = '' + if [[ -d $out/lib/X11/fonts || -d $out/share/fonts ]]; then + export FONTCONFIG_FILE="$(pwd)/fonts.conf" + + cat > $FONTCONFIG_FILE << EOF + + + + $out/lib/X11/fonts + $out/share/fonts + $out/lib/fontconfig/cache + + EOF + + ${getBin pkgs.fontconfig}/bin/fc-cache -f + rm -f $out/lib/fontconfig/cache/CACHEDIR.TAG + rmdir --ignore-fail-on-non-empty -p $out/lib/fontconfig/cache + + rm "$FONTCONFIG_FILE" + unset FONTCONFIG_FILE + fi + + # Remove the fontconfig directory if no files were available. + if [[ -d $out/lib/fontconfig ]] ; then + rmdir --ignore-fail-on-non-empty -p $out/lib/fontconfig + fi + ''; + + xdg.configFile = { + "fontconfig/conf.d/10-hm-fonts.conf".text = '' + + + + + + + ${config.home.path}/etc/fonts/conf.d + ${config.home.path}/etc/fonts/fonts.conf + + ${config.home.path}/lib/X11/fonts + ${config.home.path}/share/fonts + ${profileDirectory}/lib/X11/fonts + ${profileDirectory}/share/fonts + + ${config.home.path}/lib/fontconfig/cache + + ''; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/misc/gtk.nix b/infra/libkookie/home-manager-stable/modules/misc/gtk.nix new file mode 100644 index 00000000000..dfebf201f19 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/misc/gtk.nix @@ -0,0 +1,273 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.gtk; + cfg2 = config.gtk.gtk2; + cfg3 = config.gtk.gtk3; + cfg4 = config.gtk.gtk4; + + toGtk3Ini = generators.toINI { + mkKeyValue = key: value: + let value' = if isBool value then boolToString value else toString value; + in "${escape [ "=" ] key}=${value'}"; + }; + + formatGtk2Option = n: v: + let + v' = if isBool v then + boolToString value + else if isString v then + ''"${v}"'' + else + toString v; + in "${escape [ "=" ] n} = ${v'}"; + + themeType = types.submodule { + options = { + package = mkOption { + type = types.nullOr types.package; + default = null; + example = literalExpression "pkgs.gnome.gnome-themes-extra"; + description = '' + Package providing the theme. This package will be installed + to your profile. If null then the theme + is assumed to already be available in your profile. + ''; + }; + + name = mkOption { + type = types.str; + example = "Adwaita"; + description = "The name of the theme within the package."; + }; + }; + }; + + iconThemeType = types.submodule { + options = { + package = mkOption { + type = types.nullOr types.package; + default = null; + example = literalExpression "pkgs.gnome.adwaita-icon-theme"; + description = '' + Package providing the icon theme. This package will be installed + to your profile. If null then the theme + is assumed to already be available in your profile. + ''; + }; + + name = mkOption { + type = types.str; + example = "Adwaita"; + description = "The name of the icon theme within the package."; + }; + }; + }; + + cursorThemeType = types.submodule { + options = { + package = mkOption { + type = types.nullOr types.package; + default = null; + example = literalExpression "pkgs.vanilla-dmz"; + description = '' + Package providing the cursor theme. This package will be installed + to your profile. If null then the theme + is assumed to already be available in your profile. + ''; + }; + + name = mkOption { + type = types.str; + example = "Vanilla-DMZ"; + description = "The name of the cursor theme within the package."; + }; + + size = mkOption { + type = types.nullOr types.int; + default = null; + example = 16; + description = '' + The size of the cursor. + ''; + }; + }; + }; + +in { + meta.maintainers = [ maintainers.rycee ]; + + imports = [ + (mkRemovedOptionModule [ "gtk" "gtk3" "waylandSupport" ] '' + This options is not longer needed and can be removed. + '') + ]; + + options = { + gtk = { + enable = mkEnableOption "GTK 2/3 configuration"; + + font = mkOption { + type = types.nullOr hm.types.fontType; + default = null; + description = '' + The font to use in GTK+ 2/3 applications. + ''; + }; + + cursorTheme = mkOption { + type = types.nullOr cursorThemeType; + default = null; + description = "The cursor theme to use."; + }; + + iconTheme = mkOption { + type = types.nullOr iconThemeType; + default = null; + description = "The icon theme to use."; + }; + + theme = mkOption { + type = types.nullOr themeType; + default = null; + description = "The GTK+2/3 theme to use."; + }; + + gtk2 = { + extraConfig = mkOption { + type = types.lines; + default = ""; + example = "gtk-can-change-accels = 1"; + description = '' + Extra configuration lines to add verbatim to + ~/.gtkrc-2.0. + ''; + }; + + configLocation = mkOption { + type = types.path; + default = "${config.home.homeDirectory}/.gtkrc-2.0"; + defaultText = + literalExpression ''"''${config.home.homeDirectory}/.gtkrc-2.0"''; + example = + literalExpression ''"''${config.xdg.configHome}/gtk-2.0/gtkrc"''; + description = '' + The location to put the GTK configuration file. + ''; + }; + }; + + gtk3 = { + bookmarks = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "file:///home/jane/Documents" ]; + description = "Bookmarks in the sidebar of the GTK file browser"; + }; + + extraConfig = mkOption { + type = with types; attrsOf (oneOf [ bool int str ]); + default = { }; + example = { + gtk-cursor-blink = false; + gtk-recent-files-limit = 20; + }; + description = '' + Extra configuration options to add to + $XDG_CONFIG_HOME/gtk-3.0/settings.ini. + ''; + }; + + extraCss = mkOption { + type = types.lines; + default = ""; + description = '' + Extra configuration lines to add verbatim to + $XDG_CONFIG_HOME/gtk-3.0/gtk.css. + ''; + }; + }; + + gtk4 = { + extraConfig = mkOption { + type = with types; attrsOf (either bool (either int str)); + default = { }; + example = { + gtk-cursor-blink = false; + gtk-recent-files-limit = 20; + }; + description = '' + Extra configuration options to add to + $XDG_CONFIG_HOME/gtk-4.0/settings.ini. + ''; + }; + }; + }; + }; + + config = mkIf cfg.enable (let + gtkIni = optionalAttrs (cfg.font != null) { + gtk-font-name = let + fontSize = + optionalString (cfg.font.size != null) " ${toString cfg.font.size}"; + in "${cfg.font.name}" + fontSize; + } // optionalAttrs (cfg.theme != null) { gtk-theme-name = cfg.theme.name; } + // optionalAttrs (cfg.iconTheme != null) { + gtk-icon-theme-name = cfg.iconTheme.name; + } // optionalAttrs (cfg.cursorTheme != null) { + gtk-cursor-theme-name = cfg.cursorTheme.name; + } // optionalAttrs + (cfg.cursorTheme != null && cfg.cursorTheme.size != null) { + gtk-cursor-theme-size = cfg.cursorTheme.size; + }; + + dconfIni = optionalAttrs (cfg.font != null) { + font-name = let + fontSize = + optionalString (cfg.font.size != null) " ${toString cfg.font.size}"; + in "${cfg.font.name}" + fontSize; + } // optionalAttrs (cfg.theme != null) { gtk-theme = cfg.theme.name; } + // optionalAttrs (cfg.iconTheme != null) { + icon-theme = cfg.iconTheme.name; + } // optionalAttrs (cfg.cursorTheme != null) { + cursor-theme = cfg.cursorTheme.name; + } // optionalAttrs + (cfg.cursorTheme != null && cfg.cursorTheme.size != null) { + cursor-size = cfg.cursorTheme.size; + }; + + optionalPackage = opt: + optional (opt != null && opt.package != null) opt.package; + in { + home.packages = concatMap optionalPackage [ + cfg.font + cfg.theme + cfg.iconTheme + cfg.cursorTheme + ]; + + home.file.${cfg2.configLocation}.text = + concatMapStrings (l: l + "\n") (mapAttrsToList formatGtk2Option gtkIni) + + cfg2.extraConfig + "\n"; + + home.sessionVariables.GTK2_RC_FILES = cfg2.configLocation; + + xdg.configFile."gtk-3.0/settings.ini".text = + toGtk3Ini { Settings = gtkIni // cfg3.extraConfig; }; + + xdg.configFile."gtk-3.0/gtk.css" = + mkIf (cfg3.extraCss != "") { text = cfg3.extraCss; }; + + xdg.configFile."gtk-3.0/bookmarks" = mkIf (cfg3.bookmarks != [ ]) { + text = concatMapStrings (l: l + "\n") cfg3.bookmarks; + }; + + xdg.configFile."gtk-4.0/settings.ini".text = + toGtk3Ini { Settings = gtkIni // cfg4.extraConfig; }; + + dconf.settings."org/gnome/desktop/interface" = dconfIni; + }); +} diff --git a/infra/libkookie/home-manager-stable/modules/misc/lib.nix b/infra/libkookie/home-manager-stable/modules/misc/lib.nix new file mode 100644 index 00000000000..13c00dc59a6 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/misc/lib.nix @@ -0,0 +1,14 @@ +{ lib, ... }: + +{ + options = { + lib = lib.mkOption { + type = lib.types.attrsOf lib.types.attrs; + default = { }; + description = '' + This option allows modules to define helper functions, + constants, etc. + ''; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/misc/news.nix b/infra/libkookie/home-manager-stable/modules/misc/news.nix new file mode 100644 index 00000000000..ea06be5f037 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/misc/news.nix @@ -0,0 +1,559 @@ +{ config, lib, options, pkgs, ... }: + +with lib; + +let + + cfg = config.news; + + hostPlatform = pkgs.stdenv.hostPlatform; + + entryModule = types.submodule ({ config, ... }: { + options = { + id = mkOption { + internal = true; + type = types.str; + description = '' + A unique entry identifier. By default it is a base16 + formatted hash of the entry message. + ''; + }; + + time = mkOption { + internal = true; + type = types.str; + example = "2017-07-10T21:55:04+00:00"; + description = '' + News entry time stamp in ISO-8601 format. Must be in UTC + (ending in '+00:00'). + ''; + }; + + condition = mkOption { + internal = true; + default = true; + description = "Whether the news entry should be active."; + }; + + message = mkOption { + internal = true; + type = types.str; + description = "The news entry content."; + }; + }; + + config = { + id = mkDefault (builtins.hashString "sha256" config.message); + }; + }); + +in + +{ + meta.maintainers = [ maintainers.rycee ]; + + options = { + news = { + display = mkOption { + type = types.enum [ "silent" "notify" "show" ]; + default = "notify"; + description = '' + How unread and relevant news should be presented when + running home-manager build and + home-manager switch. + + + + The options are + + + + silent + + + Do not print anything during build or switch. The + home-manager news command still + works for viewing the entries. + + + + + notify + + + The number of unread and relevant news entries will be + printed to standard output. The home-manager + news command can later be used to view the + entries. + + + + + show + + + A pager showing unread news entries is opened. + + + + + ''; + }; + + entries = mkOption { + internal = true; + type = types.listOf entryModule; + default = []; + description = "News entries."; + }; + }; + }; + + config = { + # Add news entries in chronological order (i.e., latest time + # should be at the bottom of the list). The time should be + # formatted as given in the output of + # + # date --iso-8601=second --universal + # + # On darwin (or BSD like systems) use + # + # date -u +'%Y-%m-%dT%H:%M:%S+00:00' + news.entries = [ + { + time = "2021-06-02T04:24:10+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'services.xidlehook'. + ''; + } + + { + time = "2021-06-07T20:44:00+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'services.pantalaimon'. + ''; + } + + { + time = "2021-06-12T05:00:22+00:00"; + message = '' + A new module is available: 'programs.mangohud'. + ''; + } + + { + time = "2021-06-16T01:26:16+00:00"; + condition = hostPlatform.isLinux; + message = '' + The xmonad module now compiles the configuration before + linking the binary to the place xmonad expects to find + the compiled configuration (the binary). + + This breaks recompilation of xmonad (i.e. the 'q' binding or + 'xmonad --recompile'). + + If this behavior is undesirable, do not use the + 'xsession.windowManager.xmonad.config' option. Instead, set the + contents of the configuration file with + 'home.file.".xmonad/config.hs".text = "content of the file"' + or 'home.file.".xmonad/config.hs".source = ./path-to-config'. + ''; + } + + { + time = "2021-06-24T22:36:11+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'i18n.inputMethod'. + ''; + } + + { + time = "2021-06-22T14:43:53+00:00"; + message = '' + A new module is available: 'programs.himalaya'. + ''; + } + + { + time = "2021-07-11T17:45:56+00:00"; + message = '' + A new module is available: 'programs.sm64ex'. + ''; + } + + { + time = "2021-07-15T13:38:32+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'services.xsettingsd'. + ''; + } + + { + time = "2021-07-14T20:06:18+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'services.volnoti'. + ''; + } + + { + time = "2021-07-23T22:22:31+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'services.trayer'. + ''; + } + + { + time = "2021-07-19T01:30:46+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'services.notify-osd'. + ''; + } + + { + time = "2021-08-10T21:28:40+00:00"; + message = '' + A new module is available: 'programs.java'. + ''; + } + + { + time = "2021-08-11T13:55:51+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'services.easyeffects'. + ''; + } + + { + time = "2021-08-16T21:59:02+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'services.git-sync'. + ''; + } + + { + time = "2021-08-26T06:40:59+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'services.fnott'. + ''; + } + + { + time = "2021-08-31T18:44:26+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'services.betterlockscreen'. + ''; + } + + { + time = "2021-09-14T21:31:03+00:00"; + message = '' + A new module is available: 'programs.bottom'. + ''; + } + + { + time = "2021-09-23T17:04:48+00:00"; + condition = hostPlatform.isLinux && config.services.screen-locker.enable; + message = '' + 'xautolock' is now optional in 'services.screen-locker', and the + 'services.screen-locker' options have been reorganized for clarity. + See the 'xautolock' and 'xss-lock' options modules in + 'services.screen-locker'. + ''; + } + + { + time = "2021-10-05T20:55:07+00:00"; + message = '' + A new module is available: 'programs.atuin'. + ''; + } + + { + time = "2021-10-05T22:15:00+00:00"; + message = '' + A new module is available: 'programs.nnn'. + ''; + } + + { + time = "2021-10-08T22:16:50+00:00"; + condition = hostPlatform.isLinux && config.programs.rofi.enable; + message = '' + Rofi version '1.7.0' removed many options that were used by the module + and replaced them with custom themes, which are more flexible and + powerful. + + You can replicate your old configuration by moving those options to + 'programs.rofi.theme'. Keep in mind that the syntax is different so + you may need to do some changes. + ''; + } + + { + time = "2021-10-23T17:12:22+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'programs.hexchat'. + ''; + } + + { + time = "2021-11-21T17:21:04+00:00"; + condition = config.wayland.windowManager.sway.enable; + message = '' + A new module is available: 'wayland.windowManager.sway.swaynag'. + ''; + } + + { + time = "2021-11-23T20:26:37+00:00"; + condition = config.programs.taskwarrior.enable; + message = '' + Taskwarrior version 2.6.0 respects XDG Specification for the config + file now. Option 'programs.taskwarrior.config' and friends now + generate the config file at '$XDG_CONFIG_HOME/task/taskrc' instead of + '~/.taskrc'. + ''; + } + + { + time = "2021-11-30T22:28:12+00:00"; + message = '' + A new module is available: 'programs.less'. + ''; + } + + { + time = "2021-11-29T15:15:59+00:00"; + condition = hostPlatform.isDarwin; + message = '' + The option 'targets.darwin.defaults."com.apple.menuextra.battery".ShowPercent' + has been deprecated since it no longer works on the latest version of + macOS. + ''; + } + + { + time = "2021-12-02T02:59:59+00:00"; + condition = config.programs.waybar.enable; + message = '' + The Waybar module now allows defining modules directly under the 'settings' + option instead of nesting the modules under 'settings.modules'. + The Waybar module will also stop reporting errors about unused or misnamed + modules. + ''; + } + + { + time = "2021-12-08T10:23:42+00:00"; + condition = config.programs.less.enable; + message = '' + The 'lesskey' configuration file is now stored under + '$XDG_CONFIG_HOME/lesskey' since it is fully supported upstream + starting from v596. + ''; + } + + { + time = "2021-12-10T23:19:57+00:00"; + message = '' + A new module is available: 'programs.sqls'. + ''; + } + + { + time = "2021-12-11T11:55:12+00:00"; + message = '' + A new module is available: 'programs.navi'. + ''; + } + + { + time = "2021-12-11T16:07:00+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'services.gromit-mpx'. + ''; + } + + { + time = "2021-12-12T17:09:38+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'services.opensnitch-ui'. + ''; + } + + { + time = "2021-12-21T22:17:30+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'services.systembus-notify'. + ''; + } + + { + time = "2021-12-31T09:39:20+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'xsession.windowManager.herbstluftwm'. + ''; + } + + { + time = "2022-01-03T10:34:45+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'services.swayidle'. + ''; + } + + { + time = "2022-01-11T12:26:43+00:00"; + message = '' + A new module is available: 'programs.sagemath'. + ''; + } + + { + time = "2022-01-22T14:36:25+00:00"; + message = '' + A new module is available: 'programs.helix'. + ''; + } + + { + time = "2022-01-22T15:12:20+00:00"; + message = '' + A new module is available: 'programs.watson'. + ''; + } + + { + time = "2022-01-22T15:33:42+00:00"; + message = '' + A new module is available: 'programs.timidity'. + ''; + } + + { + time = "2022-01-22T16:54:31+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'programs.tint2'. + ''; + } + + { + time = "2022-01-22T17:39:20+00:00"; + message = '' + A new module is available: 'programs.pandoc'. + ''; + } + + { + time = "2022-01-26T22:08:29+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'programs.kodi'. + ''; + } + + { + time = "2022-02-03T23:23:49+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'services.twmn'. + ''; + } + + { + time = "2022-02-16T23:50:35+00:00"; + message = '' + A new module is available: 'programs.zellij'. + ''; + } + + { + time = "2022-02-17T17:12:46+00:00"; + message = '' + A new module is available: 'programs.eww'. + ''; + } + + { + time = "2022-02-17T23:11:13+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'services.espanso'. + ''; + } + + { + time = "2022-02-24T22:35:22+00:00"; + message = '' + A new module is available: 'programs.gitui'. + ''; + } + + { + time = "2022-02-26T09:28:57+00:00"; + condition = hostPlatform.isDarwin; + message = '' + A new module is available: 'launchd.agents' + + Use this to enable services based on macOS LaunchAgents. + ''; + } + + { + time = "2022-03-06T08:50:32+00:00"; + message = '' + A new module is available: 'programs.just'. + ''; + } + + { + time = "2022-03-06T09:40:17+00:00"; + message = '' + A new module is available: 'programs.pubs'. + ''; + } + + { + time = "2022-03-13T20:59:38+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'services.fusuma'. + ''; + } + + { + time = "2022-05-02T20:55:46+00:00"; + message = '' + A new module is available: 'programs.tealdeer'. + ''; + } + + { + time = "2022-05-18T22:09:45+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'services.mopidy'. + ''; + } + ]; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/misc/nix.nix b/infra/libkookie/home-manager-stable/modules/misc/nix.nix new file mode 100644 index 00000000000..7214ac4b388 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/misc/nix.nix @@ -0,0 +1,240 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.nix; + + nixPackage = cfg.package; + + isNixAtLeast = versionAtLeast (getVersion nixPackage); + + nixConf = assert isNixAtLeast "2.2"; + let + + mkValueString = v: + if v == null then + "" + else if isInt v then + toString v + else if isBool v then + boolToString v + else if isFloat v then + floatToString v + else if isList v then + toString v + else if isDerivation v then + toString v + else if builtins.isPath v then + toString v + else if isString v then + v + else if isCoercibleToString v then + toString v + else + abort "The nix conf value: ${toPretty { } v} can not be encoded"; + + mkKeyValue = k: v: "${escape [ "=" ] k} = ${mkValueString v}"; + + mkKeyValuePairs = attrs: + concatStringsSep "\n" (mapAttrsToList mkKeyValue attrs); + + in pkgs.writeTextFile { + name = "nix.conf"; + text = '' + # WARNING: this file is generated from the nix.settings option in + # your Home Manager configuration at $XDG_CONFIG_HOME/nix/nix.conf. + # Do not edit it! + ${mkKeyValuePairs cfg.settings} + ${cfg.extraOptions} + ''; + checkPhase = + if pkgs.stdenv.hostPlatform != pkgs.stdenv.buildPlatform then '' + echo "Ignoring validation for cross-compilation" + '' else '' + echo "Validating generated nix.conf" + ln -s $out ./nix.conf + set -e + set +o pipefail + NIX_CONF_DIR=$PWD \ + ${cfg.package}/bin/nix show-config ${ + optionalString (isNixAtLeast "2.3pre") + "--no-net --option experimental-features nix-command" + } \ + |& sed -e 's/^warning:/error:/' \ + | (! grep '${ + if cfg.checkConfig then "^error:" else "^error: unknown setting" + }') + set -o pipefail + ''; + }; + + semanticConfType = with types; + let + confAtom = nullOr (oneOf [ bool int float str path package ]) // { + description = + "Nix config atom (null, bool, int, float, str, path or package)"; + }; + in attrsOf (either confAtom (listOf confAtom)); + + jsonFormat = pkgs.formats.json { }; + +in { + options.nix = { + enable = mkEnableOption '' + the Nix configuration module + '' // { + default = true; + visible = false; + }; + + package = mkOption { + type = types.nullOr types.package; + default = null; + example = literalExpression "pkgs.nix"; + description = '' + The Nix package that the configuration should be generated for. + ''; + }; + + registry = mkOption { + type = types.attrsOf (types.submodule (let + inputAttrs = types.attrsOf + (types.oneOf [ types.str types.int types.bool types.package ]); + in { config, name, ... }: { + options = { + from = mkOption { + type = inputAttrs; + example = { + type = "indirect"; + id = "nixpkgs"; + }; + description = "The flake reference to be rewritten."; + }; + to = mkOption { + type = inputAttrs; + example = { + type = "github"; + owner = "my-org"; + repo = "my-nixpkgs"; + }; + description = + "The flake reference to which is to be rewritten."; + }; + flake = mkOption { + type = types.nullOr types.attrs; + default = null; + example = literalExpression "nixpkgs"; + description = '' + The flake input to which is to be rewritten. + ''; + }; + exact = mkOption { + type = types.bool; + default = true; + description = '' + Whether the reference needs to match exactly. If set, + a reference like nixpkgs does not + match with a reference like nixpkgs/nixos-20.03. + ''; + }; + }; + config = { + from = mkDefault { + type = "indirect"; + id = name; + }; + to = mkIf (config.flake != null) ({ + type = "path"; + path = config.flake.outPath; + } // lib.filterAttrs (n: v: + n == "lastModified" || n == "rev" || n == "revCount" || n + == "narHash") config.flake); + }; + })); + default = { }; + description = '' + User level flake registry. + ''; + }; + + registryVersion = mkOption { + type = types.int; + default = 2; + internal = true; + description = "The flake registry format version."; + }; + + checkConfig = mkOption { + type = types.bool; + default = true; + description = '' + If enabled (the default), checks for data type mismatches and that Nix + can parse the generated nix.conf. + ''; + }; + + extraOptions = mkOption { + type = types.lines; + default = ""; + example = '' + keep-outputs = true + keep-derivations = true + ''; + description = + "Additional text appended to nix.conf."; + }; + + settings = mkOption { + type = types.submodule { freeformType = semanticConfType; }; + default = { }; + example = literalExpression '' + { + use-sandbox = true; + show-trace = true; + system-features = [ "big-parallel" "kvm" "recursive-nix" ]; + } + ''; + description = '' + Configuration for Nix, see + or + + nix.conf + 5 + for avalaible options. + The value declared here will be translated directly to the key-value pairs Nix expects. + + + Configuration specified in which will be appended + verbatim to the resulting config file. + ''; + }; + }; + + config = mkIf cfg.enable { + assertions = [{ + assertion = cfg.settings == { } || cfg.package != null; + message = '' + A corresponding Nix package must be specified via `nix.package` for generating + nix.conf. + ''; + }]; + + xdg.configFile = { + "nix/registry.json" = mkIf (cfg.registry != { }) { + source = jsonFormat.generate "registry.json" { + version = cfg.registryVersion; + flakes = + mapAttrsToList (n: v: { inherit (v) from to exact; }) cfg.registry; + }; + }; + + "nix/nix.conf" = mkIf (cfg.settings != { } || cfg.extraOptions != "") { + source = nixConf; + }; + }; + }; + + meta.maintainers = [ maintainers.polykernel ]; +} diff --git a/infra/libkookie/home-manager-stable/modules/misc/nixpkgs-disabled.nix b/infra/libkookie/home-manager-stable/modules/misc/nixpkgs-disabled.nix new file mode 100644 index 00000000000..ab0f35df7db --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/misc/nixpkgs-disabled.nix @@ -0,0 +1,73 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.nixpkgs; + + # Copied from nixpkgs.nix. + isConfig = x: builtins.isAttrs x || builtins.isFunction x; + + # Copied from nixpkgs.nix. + optCall = f: x: if builtins.isFunction f then f x else f; + + # Copied from nixpkgs.nix. + mergeConfig = lhs_: rhs_: + let + lhs = optCall lhs_ { inherit pkgs; }; + rhs = optCall rhs_ { inherit pkgs; }; + in lhs // rhs // optionalAttrs (lhs ? packageOverrides) { + packageOverrides = pkgs: + optCall lhs.packageOverrides pkgs + // optCall (attrByPath [ "packageOverrides" ] ({ }) rhs) pkgs; + } // optionalAttrs (lhs ? perlPackageOverrides) { + perlPackageOverrides = pkgs: + optCall lhs.perlPackageOverrides pkgs + // optCall (attrByPath [ "perlPackageOverrides" ] ({ }) rhs) pkgs; + }; + + # Copied from nixpkgs.nix. + configType = mkOptionType { + name = "nixpkgs-config"; + description = "nixpkgs config"; + check = x: + let traceXIfNot = c: if c x then true else lib.traceSeqN 1 x false; + in traceXIfNot isConfig; + merge = args: fold (def: mergeConfig def.value) { }; + }; + + # Copied from nixpkgs.nix. + overlayType = mkOptionType { + name = "nixpkgs-overlay"; + description = "nixpkgs overlay"; + check = builtins.isFunction; + merge = lib.mergeOneOption; + }; + +in { + meta.maintainers = with maintainers; [ thiagokokada ]; + + options.nixpkgs = { + config = mkOption { + default = null; + type = types.nullOr configType; + visible = false; + }; + + overlays = mkOption { + default = null; + type = types.nullOr (types.listOf overlayType); + visible = false; + }; + }; + + config = { + assertions = [{ + assertion = cfg.config == null || cfg.overlays == null; + message = '' + `nixpkgs` options are disabled when `home-manager.useGlobalPkgs` is enabled. + ''; + }]; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/misc/nixpkgs.nix b/infra/libkookie/home-manager-stable/modules/misc/nixpkgs.nix new file mode 100644 index 00000000000..e4b931fb2a6 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/misc/nixpkgs.nix @@ -0,0 +1,139 @@ +# Adapted from Nixpkgs. + +{ config, lib, pkgs, pkgsPath, ... }: + +with lib; + +let + + isConfig = x: builtins.isAttrs x || builtins.isFunction x; + + optCall = f: x: if builtins.isFunction f then f x else f; + + mergeConfig = lhs_: rhs_: + let + lhs = optCall lhs_ { inherit pkgs; }; + rhs = optCall rhs_ { inherit pkgs; }; + in lhs // rhs // optionalAttrs (lhs ? packageOverrides) { + packageOverrides = pkgs: + optCall lhs.packageOverrides pkgs + // optCall (attrByPath [ "packageOverrides" ] ({ }) rhs) pkgs; + } // optionalAttrs (lhs ? perlPackageOverrides) { + perlPackageOverrides = pkgs: + optCall lhs.perlPackageOverrides pkgs + // optCall (attrByPath [ "perlPackageOverrides" ] ({ }) rhs) pkgs; + }; + + configType = mkOptionType { + name = "nixpkgs-config"; + description = "nixpkgs config"; + check = x: + let traceXIfNot = c: if c x then true else lib.traceSeqN 1 x false; + in traceXIfNot isConfig; + merge = args: fold (def: mergeConfig def.value) { }; + }; + + overlayType = mkOptionType { + name = "nixpkgs-overlay"; + description = "nixpkgs overlay"; + check = builtins.isFunction; + merge = lib.mergeOneOption; + }; + + _pkgs = import pkgsPath (filterAttrs (n: v: v != null) config.nixpkgs); + +in { + options.nixpkgs = { + config = mkOption { + default = null; + example = { allowBroken = true; }; + type = types.nullOr configType; + description = '' + The configuration of the Nix Packages collection. (For + details, see the Nixpkgs documentation.) It allows you to set + package configuration options. + + + + If null, then configuration is taken from + the fallback location, for example, + ~/.config/nixpkgs/config.nix. + + + + Note, this option will not apply outside your Home Manager + configuration like when installing manually through + nix-env. If you want to apply it both + inside and outside Home Manager you can put it in a separate + file and include something like + + + nixpkgs.config = import ./nixpkgs-config.nix; + xdg.configFile."nixpkgs/config.nix".source = ./nixpkgs-config.nix; + + + in your Home Manager configuration. + ''; + }; + + overlays = mkOption { + default = null; + example = literalExpression '' + [ (self: super: { + openssh = super.openssh.override { + hpnSupport = true; + withKerberos = true; + kerberos = self.libkrb5; + }; + }; + ) ] + ''; + type = types.nullOr (types.listOf overlayType); + description = '' + List of overlays to use with the Nix Packages collection. (For + details, see the Nixpkgs documentation.) It allows you to + override packages globally. This is a function that takes as + an argument the original Nixpkgs. The + first argument should be used for finding dependencies, and + the second should be used for overriding recipes. + + + + If null, then the overlays are taken from + the fallback location, for example, + ~/.config/nixpkgs/overlays. + + + + Like nixpkgs.config this option only + applies within the Home Manager configuration. See + nixpkgs.config for a suggested setup that + works both internally and externally. + ''; + }; + + system = mkOption { + type = types.str; + example = "i686-linux"; + internal = true; + description = '' + Specifies the Nix platform type for which the user environment + should be built. If unset, it defaults to the platform type of + your host system. Specifying this option is useful when doing + distributed multi-platform deployment, or when building + virtual machines. + ''; + }; + }; + + config = { + _module.args = { + pkgs = mkOverride modules.defaultPriority _pkgs; + pkgs_i686 = + if _pkgs.stdenv.isLinux && _pkgs.stdenv.hostPlatform.isx86 then + _pkgs.pkgsi686Linux + else + { }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/misc/numlock.nix b/infra/libkookie/home-manager-stable/modules/misc/numlock.nix new file mode 100644 index 00000000000..88032417ffb --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/misc/numlock.nix @@ -0,0 +1,35 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.xsession.numlock; + +in { + meta.maintainers = [ maintainers.evanjs ]; + + options = { xsession.numlock.enable = mkEnableOption "Num Lock"; }; + + config = mkIf cfg.enable { + assertions = [ + (hm.assertions.assertPlatform "xsession.numlock" pkgs platforms.linux) + ]; + + systemd.user.services.numlockx = { + Unit = { + Description = "NumLockX"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + }; + + Service = { + Type = "oneshot"; + RemainAfterExit = true; + ExecStart = "${pkgs.numlockx}/bin/numlockx"; + }; + + Install = { WantedBy = [ "graphical-session.target" ]; }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/misc/pam.nix b/infra/libkookie/home-manager-stable/modules/misc/pam.nix new file mode 100644 index 00000000000..cf3321ffba3 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/misc/pam.nix @@ -0,0 +1,71 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.pam; + +in { + meta.maintainers = with maintainers; [ rycee veehaitch ]; + + options = { + pam.sessionVariables = mkOption { + default = { }; + type = types.attrs; + example = { EDITOR = "vim"; }; + description = '' + Environment variables that will be set for the PAM session. + The variable values must be as described in + + pam_env.conf + 5 + . + + Note, this option will become deprecated in the future and its use is + therefore discouraged. + ''; + }; + + pam.yubico.authorizedYubiKeys = { + ids = mkOption { + type = with types; + let + yubiKeyId = addCheck str (s: stringLength s == 12) // { + name = "yubiKeyId"; + description = "string of length 12"; + }; + in listOf yubiKeyId; + default = [ ]; + description = '' + List of authorized YubiKey token IDs. Refer to + + for details on how to obtain the token ID of a YubiKey. + ''; + }; + + path = mkOption { + type = types.str; + default = ".yubico/authorized_yubikeys"; + description = '' + File path to write the authorized YubiKeys, + relative to HOME. + ''; + }; + }; + }; + + config = mkMerge [ + (mkIf (cfg.sessionVariables != { }) { + home.file.".pam_environment".text = concatStringsSep "\n" + (mapAttrsToList (n: v: ''${n} OVERRIDE="${toString v}"'') + cfg.sessionVariables) + "\n"; + }) + + (mkIf (cfg.yubico.authorizedYubiKeys.ids != [ ]) { + home.file.${cfg.yubico.authorizedYubiKeys.path}.text = + concatStringsSep ":" + ([ config.home.username ] ++ cfg.yubico.authorizedYubiKeys.ids); + }) + ]; +} diff --git a/infra/libkookie/home-manager-stable/modules/misc/qt.nix b/infra/libkookie/home-manager-stable/modules/misc/qt.nix new file mode 100644 index 00000000000..313e79ee4cd --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/misc/qt.nix @@ -0,0 +1,121 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.qt; + +in { + meta.maintainers = [ maintainers.rycee ]; + + imports = [ + (mkChangedOptionModule [ "qt" "useGtkTheme" ] [ "qt" "platformTheme" ] + (config: + if getAttrFromPath [ "qt" "useGtkTheme" ] config then "gtk" else null)) + ]; + + options = { + qt = { + enable = mkEnableOption "Qt 4 and 5 configuration"; + + platformTheme = mkOption { + type = types.nullOr (types.enum [ "gtk" "gnome" ]); + default = null; + example = "gnome"; + relatedPackages = + [ "qgnomeplatform" [ "libsForQt5" "qtstyleplugins" ] ]; + description = '' + Selects the platform theme to use for Qt applications. + The options are + + + gtk + Use GTK theme with + qtstyleplugins + + + + gnome + Use GNOME theme with + qgnomeplatform + + + + ''; + }; + + style = { + name = mkOption { + type = types.nullOr types.str; + default = null; + example = "adwaita-dark"; + relatedPackages = [ "adwaita-qt" [ "libsForQt5" "qtstyleplugins" ] ]; + description = '' + Selects the style to use for Qt5 applications. + The options are + + + adwaita + adwaita-dark + Use Adwaita Qt style with + adwaita + + + + cleanlooks + gtk2 + motif + plastique + Use styles from + qtstyleplugins + + + + ''; + }; + + package = mkOption { + type = types.nullOr types.package; + default = null; + example = literalExpression "pkgs.adwaita-qt"; + description = "Theme package to be used in Qt5 applications."; + }; + }; + }; + }; + + config = mkIf (cfg.enable && cfg.platformTheme != null) { + assertions = [{ + assertion = (cfg.platformTheme == "gnome") + -> ((cfg.style.name != null) && (cfg.style.package != null)); + message = '' + `qt.platformTheme` "gnome" must have `qt.style` set to a theme that + supports both Qt and Gtk, for example "adwaita" or "adwaita-dark". + ''; + }]; + + # Necessary because home.sessionVariables is of types.attrs + home.sessionVariables = (filterAttrs (n: v: v != null) { + QT_QPA_PLATFORMTHEME = + if cfg.platformTheme == "gnome" then "gnome" else "gtk2"; + QT_STYLE_OVERRIDE = cfg.style.name; + }); + + home.packages = if cfg.platformTheme == "gnome" then + [ pkgs.qgnomeplatform ] + ++ lib.optionals (cfg.style.package != null) [ cfg.style.package ] + else + [ pkgs.libsForQt5.qtstyleplugins ]; + + xsession.importedVariables = [ "QT_QPA_PLATFORMTHEME" ] + ++ lib.optionals (cfg.style != null) [ "QT_STYLE_OVERRIDE" ]; + + # Enable GTK+ style for Qt4 in either case. + # It doesn’t support the platform theme packages. + home.activation.useGtkThemeInQt4 = hm.dag.entryAfter [ "writeBoundary" ] '' + $DRY_RUN_CMD ${pkgs.crudini}/bin/crudini $VERBOSE_ARG \ + --set "${config.xdg.configHome}/Trolltech.conf" Qt style GTK+ + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/misc/specialization.nix b/infra/libkookie/home-manager-stable/modules/misc/specialization.nix new file mode 100644 index 00000000000..67e593e2c4d --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/misc/specialization.nix @@ -0,0 +1,71 @@ +{ config, extendModules, lib, ... }: + +with lib; + +{ + options.specialization = mkOption { + type = types.attrsOf (types.submodule { + options = { + configuration = mkOption { + type = let + stopRecursion = { specialization = mkOverride 0 { }; }; + extended = extendModules { modules = [ stopRecursion ]; }; + in extended.type; + default = { }; + visible = "shallow"; + description = '' + Arbitrary Home Manager configuration settings. + ''; + }; + }; + }); + default = { }; + description = '' + A set of named specialized configurations. These can be used to extend + your base configuration with additional settings. For example, you can + have specializations named light and dark + that applies light and dark color theme configurations. + + + + Note, this is an experimental option for now and you therefore have to + activate the specialization by looking up and running the activation + script yourself. Note, running the activation script will create a new + Home Manager generation. + + + + For example, to activate the dark specialization. You can + first look up your current Home Manager generation by running + + + $ home-manager generations | head -1 + 2022-05-02 22:49 : id 1758 -> /nix/store/jy…ac-home-manager-generation + + + then run + + + $ /nix/store/jy…ac-home-manager-generation/specialization/dark/activate + Starting Home Manager activation + … + + + + + WARNING! Since this option is experimental, the activation process may + change in backwards incompatible ways. + ''; + }; + + config = mkIf (config.specialization != { }) { + home.extraBuilderCommands = let + link = n: v: + let pkg = v.configuration.home.activationPackage; + in "ln -s ${pkg} $out/specialization/${n}"; + in '' + mkdir $out/specialization + ${concatStringsSep "\n" (mapAttrsToList link config.specialization)} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/misc/submodule-support.nix b/infra/libkookie/home-manager-stable/modules/misc/submodule-support.nix new file mode 100644 index 00000000000..ff80291cadf --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/misc/submodule-support.nix @@ -0,0 +1,32 @@ +{ lib, ... }: + +with lib; + +{ + meta.maintainers = [ maintainers.rycee ]; + + options.submoduleSupport = { + enable = mkOption { + type = types.bool; + default = false; + internal = true; + description = '' + Whether the Home Manager module system is used as a submodule + in, for example, NixOS or nix-darwin. + ''; + }; + + externalPackageInstall = mkOption { + type = types.bool; + default = false; + internal = true; + description = '' + Whether the packages of are + installed separately from the Home Manager activation script. + In NixOS, for example, this may be accomplished by installing + the packages through + . + ''; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/misc/tmpfiles.nix b/infra/libkookie/home-manager-stable/modules/misc/tmpfiles.nix new file mode 100644 index 00000000000..248843029fa --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/misc/tmpfiles.nix @@ -0,0 +1,54 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.systemd.user.tmpfiles; + +in { + meta.maintainers = [ maintainers.dawidsowa ]; + + options.systemd.user.tmpfiles.rules = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "L /home/user/Documents - - - - /mnt/data/Documents" ]; + description = '' + Rules for creating and cleaning up temporary files + automatically. See + + tmpfiles.d + 5 + + for the exact format. + ''; + }; + + config = mkIf (cfg.rules != [ ]) { + assertions = [ + (hm.assertions.assertPlatform "systemd.user.tmpfiles" pkgs + platforms.linux) + ]; + + xdg = { + dataFile."user-tmpfiles.d/home-manager.conf" = { + text = '' + # This file is created automatically and should not be modified. + # Please change the option ‘systemd.user.tmpfiles.rules’ instead. + ${concatStringsSep "\n" cfg.rules} + ''; + onChange = "${pkgs.systemd}/bin/systemd-tmpfiles --user --create"; + }; + configFile = { + "systemd/user/basic.target.wants/systemd-tmpfiles-setup.service".source = + "${pkgs.systemd}/example/systemd/user/systemd-tmpfiles-setup.service"; + "systemd/user/systemd-tmpfiles-setup.service".source = + "${pkgs.systemd}/example/systemd/user/systemd-tmpfiles-setup.service"; + "systemd/user/timers.target.wants/systemd-tmpfiles-clean.timer".source = + "${pkgs.systemd}/example/systemd/user/systemd-tmpfiles-clean.timer"; + "systemd/user/systemd-tmpfiles-clean.service".source = + "${pkgs.systemd}/example/systemd/user/systemd-tmpfiles-clean.service"; + }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/misc/version.nix b/infra/libkookie/home-manager-stable/modules/misc/version.nix new file mode 100644 index 00000000000..9673c0ffa5a --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/misc/version.nix @@ -0,0 +1,34 @@ +{ config, lib, ... }: + +with lib; + +{ + options = { + home.stateVersion = mkOption { + type = types.enum [ + "18.09" + "19.03" + "19.09" + "20.03" + "20.09" + "21.03" + "21.05" + "21.11" + "22.05" + ]; + default = "18.09"; + description = '' + It is occasionally necessary for Home Manager to change + configuration defaults in a way that is incompatible with + stateful data. This could, for example, include switching the + default data format or location of a file. + + The state version indicates which default + settings are in effect and will therefore help avoid breaking + program configurations. Switching to a higher state version + typically requires performing some manual steps, such as data + conversion or moving files. + ''; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/misc/vte.nix b/infra/libkookie/home-manager-stable/modules/misc/vte.nix new file mode 100644 index 00000000000..fbe38c0163e --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/misc/vte.nix @@ -0,0 +1,51 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + meta.maintainers = [ maintainers.rycee ]; + + options.programs = let + description = '' + Whether to enable integration with terminals using the VTE + library. This will let the terminal track the current working + directory. + ''; + in { + bash.enableVteIntegration = mkEnableOption "" // { inherit description; }; + + zsh.enableVteIntegration = mkEnableOption "" // { inherit description; }; + }; + + config = mkMerge [ + (mkIf config.programs.bash.enableVteIntegration { + # Unfortunately we have to do a little dance here to fix two + # problems with the upstream vte.sh file: + # + # - It does `PROMPT_COMMAND="__vte_prompt_command"` which + # clobbers any previously assigned prompt command. + # + # - Its `__vte_prompt_command` function runs commands that will + # overwrite the exit status of the command the user ran. + programs.bash.initExtra = '' + __HM_PROMPT_COMMAND="''${PROMPT_COMMAND:+''${PROMPT_COMMAND%;};}__hm_vte_prompt_command" + . ${pkgs.vte}/etc/profile.d/vte.sh + if [[ $(type -t __vte_prompt_command) = function ]]; then + __hm_vte_prompt_command() { + local old_exit_status=$? + __vte_prompt_command + return $old_exit_status + } + PROMPT_COMMAND="$__HM_PROMPT_COMMAND" + fi + unset __HM_PROMPT_COMMAND + ''; + }) + + (mkIf config.programs.zsh.enableVteIntegration { + programs.zsh.initExtra = '' + . ${pkgs.vte}/etc/profile.d/vte.sh + ''; + }) + ]; +} diff --git a/infra/libkookie/home-manager-stable/modules/misc/xdg-desktop-entries.nix b/infra/libkookie/home-manager-stable/modules/misc/xdg-desktop-entries.nix new file mode 100644 index 00000000000..f563f49d871 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/misc/xdg-desktop-entries.nix @@ -0,0 +1,215 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + desktopEntry = { + imports = [ + (mkRemovedOptionModule [ "extraConfig" ] + "The `extraConfig` option of `xdg.desktopEntries` has been removed following a change in Nixpkgs.") + (mkRemovedOptionModule [ "fileValidation" ] + "Validation of the desktop file is always enabled.") + ]; + options = { + # Since this module uses the nixpkgs/pkgs/build-support/make-desktopitem function, + # our options and defaults follow its parameters, with the following exceptions: + + # `desktopName` on makeDesktopItem is controlled by `name`. + # This is what we'd commonly consider the name of the application. + # `name` on makeDesktopItem is controlled by this module's key in the attrset. + # This is the file's filename excluding ".desktop". + + # `extraConfig` on makeDesktopItem is controlled by `settings`, + # to match what's commonly used by other home manager modules. + + # Descriptions are taken from the desktop entry spec: + # https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#recognized-keys + + type = mkOption { + description = "The type of the desktop entry."; + default = "Application"; + type = types.enum [ "Application" "Link" "Directory" ]; + }; + + exec = mkOption { + description = "Program to execute, possibly with arguments."; + type = types.nullOr types.str; + }; + + icon = mkOption { + description = "Icon to display in file manager, menus, etc."; + type = types.nullOr types.str; + default = null; + }; + + comment = mkOption { + description = "Tooltip for the entry."; + type = types.nullOr types.str; + default = null; + }; + + terminal = mkOption { + description = "Whether the program runs in a terminal window."; + type = types.bool; + default = false; + }; + + name = mkOption { + description = "Specific name of the application."; + type = types.str; + }; + + genericName = mkOption { + description = "Generic name of the application."; + type = types.nullOr types.str; + default = null; + }; + + mimeType = mkOption { + description = "The MIME type(s) supported by this application."; + type = types.nullOr (types.listOf types.str); + default = null; + }; + + categories = mkOption { + description = + "Categories in which the entry should be shown in a menu."; + type = types.nullOr (types.listOf types.str); + default = null; + }; + + startupNotify = mkOption { + description = '' + If true, it is KNOWN that the application will send a "remove" + message when started with the DESKTOP_STARTUP_ID + environment variable set. If false, it is KNOWN that the application + does not work with startup notification at all.''; + type = types.nullOr types.bool; + default = null; + }; + + noDisplay = mkOption { + description = '' + Means "this application exists, but don't display it in the menus". + This can be useful to e.g. associate this application with MIME types. + ''; + type = types.nullOr types.bool; + default = null; + }; + + prefersNonDefaultGPU = mkOption { + description = '' + If true, the application prefers to be run on a more powerful discrete GPU if available. + ''; + type = types.nullOr types.bool; + default = null; + }; + + settings = mkOption { + type = types.attrsOf types.string; + description = '' + Extra key-value pairs to add to the [Desktop Entry] section. + This may override other values. + ''; + default = { }; + example = literalExpression '' + { + Keywords = "calc;math"; + DBusActivatable = "false"; + } + ''; + }; + + actions = mkOption { + type = types.attrsOf (types.submodule ({ name, ... }: { + options.name = mkOption { + type = types.str; + default = name; + defaultText = literalExpression ""; + description = "Name of the action."; + }; + options.exec = mkOption { + type = types.nullOr types.str; + description = "Program to execute, possibly with arguments."; + }; + options.icon = mkOption { + type = types.nullOr types.str; + default = null; + description = "Icon to display in file manager, menus, etc."; + }; + })); + default = { }; + defaultText = literalExpression "{ }"; + example = literalExpression '' + { + "New Window" = { + exec = "''${pkgs.firefox}/bin/firefox --new-window %u"; + }; + } + ''; + description = + "The set of actions made available to application launchers."; + }; + + # Required for the assertions + # TODO: Remove me once `mkRemovedOptionModule` works correctly with submodules + assertions = mkOption { + type = types.listOf types.unspecified; + default = [ ]; + visible = false; + internal = true; + }; + }; + }; + + #formatting helpers + semicolonList = list: + (concatStringsSep ";" list) + ";"; # requires trailing semicolon + + #passes config options to makeDesktopItem in expected format + makeFile = name: config: + pkgs.makeDesktopItem { + inherit name; + inherit (config) + type exec icon comment terminal genericName startupNotify noDisplay + prefersNonDefaultGPU actions; + desktopName = config.name; + mimeTypes = optionals (config.mimeType != null) config.mimeType; + categories = optionals (config.categories != null) config.categories; + extraConfig = config.settings; + }; +in { + meta.maintainers = [ hm.maintainers.cwyc ]; + + options.xdg.desktopEntries = mkOption { + description = '' + Desktop Entries allow applications to be shown in your desktop environment's app launcher. + You can define entries for programs without entries or override existing entries. + See for more information on options. + ''; + default = { }; + type = types.attrsOf (types.submodule desktopEntry); + example = literalExpression '' + { + firefox = { + name = "Firefox"; + genericName = "Web Browser"; + exec = "firefox %U"; + terminal = false; + categories = [ "Application" "Network" "WebBrowser" ]; + mimeType = [ "text/html" "text/xml" ]; + }; + } + ''; + }; + + config = mkIf (config.xdg.desktopEntries != { }) { + assertions = [ + (hm.assertions.assertPlatform "xdg.desktopEntries" pkgs platforms.linux) + ] ++ flatten (catAttrs "assertions" (attrValues config.xdg.desktopEntries)); + + home.packages = (map hiPrio # we need hiPrio to override existing entries + (attrsets.mapAttrsToList makeFile config.xdg.desktopEntries)); + }; + +} diff --git a/infra/libkookie/home-manager-stable/modules/misc/xdg-mime-apps.nix b/infra/libkookie/home-manager-stable/modules/misc/xdg-mime-apps.nix new file mode 100644 index 00000000000..cda9bd19b80 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/misc/xdg-mime-apps.nix @@ -0,0 +1,121 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.xdg.mimeApps; + + strListOrSingleton = with types; + coercedTo (either (listOf str) str) toList (listOf str); + +in { + meta.maintainers = with maintainers; [ pacien ]; + + options.xdg.mimeApps = { + enable = mkOption { + type = types.bool; + default = false; + description = '' + Whether to manage $XDG_CONFIG_HOME/mimeapps.list. + + + The generated file is read-only. + ''; + }; + + # descriptions from + # https://specifications.freedesktop.org/mime-apps-spec/mime-apps-spec-1.0.1.html + + associations.added = mkOption { + type = types.attrsOf strListOrSingleton; + default = { }; + example = literalExpression '' + { + "mimetype1" = [ "foo1.desktop" "foo2.desktop" "foo3.desktop" ]; + "mimetype2" = "foo4.desktop"; + } + ''; + description = '' + Defines additional associations of applications with + mimetypes, as if the .desktop file was listing this mimetype + in the first place. + ''; + }; + + associations.removed = mkOption { + type = types.attrsOf strListOrSingleton; + default = { }; + example = { "mimetype1" = "foo5.desktop"; }; + description = '' + Removes associations of applications with mimetypes, as if the + .desktop file was not listing this + mimetype in the first place. + ''; + }; + + defaultApplications = mkOption { + type = types.attrsOf strListOrSingleton; + default = { }; + example = literalExpression '' + { + "mimetype1" = [ "default1.desktop" "default2.desktop" ]; + } + ''; + description = '' + The default application to be used for a given mimetype. This + is, for instance, the one that will be started when + double-clicking on a file in a file manager. If the + application is no longer installed, the next application in + the list is attempted, and so on. + ''; + }; + }; + + config = mkMerge [ + { + # Given a package that installs .desktop files in the usual location, + # return a mapping from mime types to lists of desktop file names. This is + # suitable for use with `xdg.mimeApps.defaultApplications`. + lib.xdg.mimeAssociations = let + processLines = str: + zipAttrs + (filter (e: e != null) (map processLine (splitString "\n" str))); + + processLine = str: + let + entry = splitString ";" str; + k = elemAt entry 0; + v = elemAt entry 1; + in if length entry == 2 then { ${k} = v; } else null; + + associations = ps: + pkgs.runCommand "mime-assoc" { inherit ps; } '' + for p in $ps ; do + for path in "$p"/share/applications/*.desktop ; do + name="''${path##*/}" + sed -n "/^MimeType=/ { s/.*=//; s/;/;$name\n/g; p; }" "$path" + done + done > "$out" + ''; + in p: processLines (builtins.readFile (associations p)); + } + + (mkIf cfg.enable { + assertions = + [ (hm.assertions.assertPlatform "xdg.mimeApps" pkgs platforms.linux) ]; + + # Deprecated but still used by some applications. + xdg.dataFile."applications/mimeapps.list".source = + config.xdg.configFile."mimeapps.list".source; + + xdg.configFile."mimeapps.list".text = + let joinValues = mapAttrs (n: concatStringsSep ";"); + in generators.toINI { } { + "Added Associations" = joinValues cfg.associations.added; + "Removed Associations" = joinValues cfg.associations.removed; + "Default Applications" = joinValues cfg.defaultApplications; + }; + }) + ]; +} diff --git a/infra/libkookie/home-manager-stable/modules/misc/xdg-mime.nix b/infra/libkookie/home-manager-stable/modules/misc/xdg-mime.nix new file mode 100644 index 00000000000..c9c7658d111 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/misc/xdg-mime.nix @@ -0,0 +1,60 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.xdg.mime; + +in { + options = { + xdg.mime.enable = mkOption { + type = types.bool; + default = pkgs.stdenv.hostPlatform.isLinux; + defaultText = + literalExpression "true if host platform is Linux, false otherwise"; + description = '' + Whether to install programs and files to support the + XDG Shared MIME-info specification and XDG MIME Applications + specification at + + and + , + respectively. + ''; + }; + }; + + config = mkIf config.xdg.mime.enable { + assertions = + [ (hm.assertions.assertPlatform "xdg.mime" pkgs platforms.linux) ]; + + home.packages = [ + # Explicitly install package to provide basic mime types. + pkgs.shared-mime-info + + # Make sure the target directories will be real directories. + (pkgs.runCommandLocal "dummy-xdg-mime-dirs1" { } '' + mkdir -p $out/share/{applications,mime/packages} + '') + (pkgs.runCommandLocal "dummy-xdg-mime-dirs2" { } '' + mkdir -p $out/share/{applications,mime/packages} + '') + ]; + + home.extraProfileCommands = '' + if [[ -w $out/share/mime && -w $out/share/mime/packages && -d $out/share/mime/packages ]]; then + XDG_DATA_DIRS=$out/share \ + PKGSYSTEM_ENABLE_FSYNC=0 \ + ${pkgs.buildPackages.shared-mime-info}/bin/update-mime-database \ + -V $out/share/mime > /dev/null + fi + + if [[ -w $out/share/applications ]]; then + ${pkgs.buildPackages.desktop-file-utils}/bin/update-desktop-database \ + $out/share/applications + fi + ''; + }; + +} diff --git a/infra/libkookie/home-manager-stable/modules/misc/xdg-system-dirs.nix b/infra/libkookie/home-manager-stable/modules/misc/xdg-system-dirs.nix new file mode 100644 index 00000000000..989131c5fac --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/misc/xdg-system-dirs.nix @@ -0,0 +1,61 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.xdg.systemDirs; + + configDirs = concatStringsSep ":" cfg.config; + + dataDirs = concatStringsSep ":" cfg.data; + +in { + meta.maintainers = with maintainers; [ tadfisher ]; + + options.xdg.systemDirs = { + config = mkOption { + type = types.listOf types.str; + default = [ ]; + example = literalExpression ''[ "/etc/xdg" ]''; + description = '' + Directory names to add to XDG_CONFIG_DIRS + in the user session. + ''; + }; + + data = mkOption { + type = types.listOf types.str; + default = [ ]; + example = literalExpression ''[ "/usr/share" "/usr/local/share" ]''; + description = '' + Directory names to add to XDG_DATA_DIRS + in the user session. + ''; + }; + }; + + config = mkMerge [ + (mkIf (cfg.config != [ ] || cfg.data != [ ]) { + assertions = [ + (hm.assertions.assertPlatform "xdg.systemDirs" pkgs platforms.linux) + ]; + }) + + (mkIf (cfg.config != [ ]) { + home.sessionVariables.XDG_CONFIG_DIRS = + "${configDirs}\${XDG_CONFIG_DIRS:+:$XDG_CONFIG_DIRS}"; + + systemd.user.sessionVariables.XDG_CONFIG_DIRS = + "${configDirs}\${XDG_CONFIG_DIRS:+:$XDG_CONFIG_DIRS}"; + }) + + (mkIf (cfg.data != [ ]) { + home.sessionVariables.XDG_DATA_DIRS = + "${dataDirs}\${XDG_DATA_DIRS:+:$XDG_DATA_DIRS}"; + + systemd.user.sessionVariables.XDG_DATA_DIRS = + "${dataDirs}\${XDG_DATA_DIRS:+:$XDG_DATA_DIRS}"; + }) + ]; +} diff --git a/infra/libkookie/home-manager-stable/modules/misc/xdg-user-dirs.nix b/infra/libkookie/home-manager-stable/modules/misc/xdg-user-dirs.nix new file mode 100644 index 00000000000..bac6b3c25c6 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/misc/xdg-user-dirs.nix @@ -0,0 +1,131 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.xdg.userDirs; + +in { + meta.maintainers = with maintainers; [ pacien ]; + + imports = [ + (mkRenamedOptionModule [ "xdg" "userDirs" "publishShare" ] [ + "xdg" + "userDirs" + "publicShare" + ]) + ]; + + options.xdg.userDirs = { + enable = mkOption { + type = types.bool; + default = false; + description = '' + Whether to manage $XDG_CONFIG_HOME/user-dirs.dirs. + + + The generated file is read-only. + ''; + }; + + # Well-known directory list from + # https://gitlab.freedesktop.org/xdg/xdg-user-dirs/blob/master/man/user-dirs.dirs.xml + + desktop = mkOption { + type = with types; coercedTo path toString str; + default = "$HOME/Desktop"; + description = "The Desktop directory."; + }; + + documents = mkOption { + type = with types; coercedTo path toString str; + default = "$HOME/Documents"; + description = "The Documents directory."; + }; + + download = mkOption { + type = with types; coercedTo path toString str; + default = "$HOME/Downloads"; + description = "The Downloads directory."; + }; + + music = mkOption { + type = with types; coercedTo path toString str; + default = "$HOME/Music"; + description = "The Music directory."; + }; + + pictures = mkOption { + type = with types; coercedTo path toString str; + default = "$HOME/Pictures"; + description = "The Pictures directory."; + }; + + publicShare = mkOption { + type = with types; coercedTo path toString str; + default = "$HOME/Public"; + description = "The Public share directory."; + }; + + templates = mkOption { + type = with types; coercedTo path toString str; + default = "$HOME/Templates"; + description = "The Templates directory."; + }; + + videos = mkOption { + type = with types; coercedTo path toString str; + default = "$HOME/Videos"; + description = "The Videos directory."; + }; + + extraConfig = mkOption { + type = with types; attrsOf (coercedTo path toString str); + default = { }; + defaultText = literalExpression "{ }"; + example = literalExpression '' + { + XDG_MISC_DIR = "$HOME/Misc"; + } + ''; + description = "Other user directories."; + }; + + createDirectories = + mkEnableOption "automatic creation of the XDG user directories"; + }; + + config = let + directories = { + XDG_DESKTOP_DIR = cfg.desktop; + XDG_DOCUMENTS_DIR = cfg.documents; + XDG_DOWNLOAD_DIR = cfg.download; + XDG_MUSIC_DIR = cfg.music; + XDG_PICTURES_DIR = cfg.pictures; + XDG_PUBLICSHARE_DIR = cfg.publicShare; + XDG_TEMPLATES_DIR = cfg.templates; + XDG_VIDEOS_DIR = cfg.videos; + } // cfg.extraConfig; + in mkIf cfg.enable { + assertions = + [ (hm.assertions.assertPlatform "xdg.userDirs" pkgs platforms.linux) ]; + + xdg.configFile."user-dirs.dirs".text = let + # For some reason, these need to be wrapped with quotes to be valid. + wrapped = mapAttrs (_: value: ''"${value}"'') directories; + in generators.toKeyValue { } wrapped; + + xdg.configFile."user-dirs.conf".text = "enabled=False"; + + home.sessionVariables = directories; + + home.activation = mkIf cfg.createDirectories { + createXdgUserDirectories = let + directoriesList = attrValues directories; + mkdir = (dir: ''$DRY_RUN_CMD mkdir -p $VERBOSE_ARG "${dir}"''); + in lib.hm.dag.entryAfter [ "writeBoundary" ] + (strings.concatMapStringsSep "\n" mkdir directoriesList); + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/misc/xdg.nix b/infra/libkookie/home-manager-stable/modules/misc/xdg.nix new file mode 100644 index 00000000000..247e7319218 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/misc/xdg.nix @@ -0,0 +1,128 @@ +{ options, config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.xdg; + + fileType = (import ../lib/file-type.nix { + inherit (config.home) homeDirectory; + inherit lib pkgs; + }).fileType; + + defaultCacheHome = "${config.home.homeDirectory}/.cache"; + defaultConfigHome = "${config.home.homeDirectory}/.config"; + defaultDataHome = "${config.home.homeDirectory}/.local/share"; + defaultStateHome = "${config.home.homeDirectory}/.local/state"; + + getEnvFallback = name: fallback: + let value = builtins.getEnv name; + in if value != "" then value else fallback; + +in { + options.xdg = { + enable = mkEnableOption "management of XDG base directories"; + + cacheHome = mkOption { + type = types.path; + defaultText = "~/.cache"; + apply = toString; + description = '' + Absolute path to directory holding application caches. + ''; + }; + + configFile = mkOption { + type = fileType "xdg.configHome" cfg.configHome; + default = { }; + description = '' + Attribute set of files to link into the user's XDG + configuration home. + ''; + }; + + configHome = mkOption { + type = types.path; + defaultText = "~/.config"; + apply = toString; + description = '' + Absolute path to directory holding application configurations. + ''; + }; + + dataFile = mkOption { + type = fileType "xdg.dataHome" cfg.dataHome; + default = { }; + description = '' + Attribute set of files to link into the user's XDG + data home. + ''; + }; + + dataHome = mkOption { + type = types.path; + defaultText = "~/.local/share"; + apply = toString; + description = '' + Absolute path to directory holding application data. + ''; + }; + + stateHome = mkOption { + type = types.path; + defaultText = "~/.local/state"; + apply = toString; + description = '' + Absolute path to directory holding application states. + ''; + }; + }; + + config = mkMerge [ + (let + variables = { + XDG_CACHE_HOME = cfg.cacheHome; + XDG_CONFIG_HOME = cfg.configHome; + XDG_DATA_HOME = cfg.dataHome; + XDG_STATE_HOME = cfg.stateHome; + }; + in mkIf cfg.enable { + xdg.cacheHome = mkDefault defaultCacheHome; + xdg.configHome = mkDefault defaultConfigHome; + xdg.dataHome = mkDefault defaultDataHome; + xdg.stateHome = mkDefault defaultStateHome; + + home.sessionVariables = variables; + systemd.user.sessionVariables = + mkIf pkgs.stdenv.hostPlatform.isLinux variables; + }) + + # Legacy non-deterministic setup. + (mkIf (!cfg.enable && versionOlder config.home.stateVersion "20.09") { + xdg.cacheHome = + mkDefault (getEnvFallback "XDG_CACHE_HOME" defaultCacheHome); + xdg.configHome = + mkDefault (getEnvFallback "XDG_CONFIG_HOME" defaultConfigHome); + xdg.dataHome = mkDefault (getEnvFallback "XDG_DATA_HOME" defaultDataHome); + }) + + # "Modern" deterministic setup. + (mkIf (!cfg.enable && versionAtLeast config.home.stateVersion "20.09") { + xdg.cacheHome = mkDefault defaultCacheHome; + xdg.configHome = mkDefault defaultConfigHome; + xdg.dataHome = mkDefault defaultDataHome; + xdg.stateHome = mkDefault defaultStateHome; + }) + + { + home.file = mkMerge [ + (mapAttrs' (name: file: nameValuePair "${cfg.configHome}/${name}" file) + cfg.configFile) + (mapAttrs' (name: file: nameValuePair "${cfg.dataHome}/${name}" file) + cfg.dataFile) + { "${cfg.cacheHome}/.keep".text = ""; } + ]; + } + ]; +} diff --git a/infra/libkookie/home-manager-stable/modules/modules.nix b/infra/libkookie/home-manager-stable/modules/modules.nix new file mode 100644 index 00000000000..22eedc5a976 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/modules.nix @@ -0,0 +1,301 @@ +{ pkgs + +# Note, this should be "the standard library" + HM extensions. +, lib + +# Whether to enable module type checking. +, check ? true + + # If disabled, the pkgs attribute passed to this function is used instead. +, useNixpkgsModule ? true }: + +with lib; + +let + + modules = [ + ./accounts/email.nix + ./config/home-cursor.nix + ./config/i18n.nix + ./files.nix + ./home-environment.nix + ./i18n/input-method/default.nix + ./launchd/default.nix + ./manual.nix + ./misc/dconf.nix + ./misc/debug.nix + ./misc/fontconfig.nix + ./misc/gtk.nix + ./misc/lib.nix + ./misc/news.nix + ./misc/numlock.nix + ./misc/pam.nix + ./misc/qt.nix + ./misc/specialization.nix + ./misc/submodule-support.nix + ./misc/tmpfiles.nix + ./misc/version.nix + ./misc/vte.nix + ./misc/xdg-desktop-entries.nix + ./misc/xdg-mime-apps.nix + ./misc/xdg-mime.nix + ./misc/xdg-system-dirs.nix + ./misc/xdg-user-dirs.nix + ./misc/xdg.nix + ./programs/abook.nix + ./programs/afew.nix + ./programs/alacritty.nix + ./programs/alot.nix + ./programs/aria2.nix + ./programs/astroid.nix + ./programs/atuin.nix + ./programs/autojump.nix + ./programs/autorandr.nix + ./programs/bash.nix + ./programs/bat.nix + ./programs/beets.nix + ./programs/bottom.nix + ./programs/broot.nix + ./programs/browserpass.nix + ./programs/chromium.nix + ./programs/command-not-found/command-not-found.nix + ./programs/dircolors.nix + ./programs/direnv.nix + ./programs/eclipse.nix + ./programs/emacs.nix + ./programs/eww.nix + ./programs/exa.nix + ./programs/feh.nix + ./programs/firefox.nix + ./programs/fish.nix + ./programs/foot.nix + ./programs/fzf.nix + ./programs/getmail.nix + ./programs/gh.nix + ./programs/git.nix + ./programs/gitui.nix + ./programs/gnome-terminal.nix + ./programs/go.nix + ./programs/gpg.nix + ./programs/helix.nix + ./programs/hexchat.nix + ./programs/himalaya.nix + ./programs/home-manager.nix + ./programs/htop.nix + ./programs/i3status-rust.nix + ./programs/i3status.nix + ./programs/info.nix + ./programs/ion.nix + ./programs/irssi.nix + ./programs/java.nix + ./programs/jq.nix + ./programs/just.nix + ./programs/kakoune.nix + ./programs/keychain.nix + ./programs/kitty.nix + ./programs/kodi.nix + ./programs/lazygit.nix + ./programs/less.nix + ./programs/lesspipe.nix + ./programs/lf.nix + ./programs/lieer.nix + ./programs/lsd.nix + ./programs/man.nix + ./programs/mangohud.nix + ./programs/matplotlib.nix + ./programs/mbsync.nix + ./programs/mcfly.nix + ./programs/mercurial.nix + ./programs/mpv.nix + ./programs/msmtp.nix + ./programs/mu.nix + ./programs/navi.nix + ./programs/ncmpcpp.nix + ./programs/ncspot.nix + ./programs/ne.nix + ./programs/neomutt.nix + ./programs/neovim.nix + ./programs/newsboat.nix + ./programs/nix-index.nix + ./programs/nnn.nix + ./programs/noti.nix + ./programs/notmuch.nix + ./programs/nushell.nix + ./programs/obs-studio.nix + ./programs/octant.nix + ./programs/offlineimap.nix + ./programs/opam.nix + ./programs/pandoc.nix + ./programs/password-store.nix + ./programs/pazi.nix + ./programs/pet.nix + ./programs/pidgin.nix + ./programs/piston-cli.nix + ./programs/powerline-go.nix + ./programs/pubs.nix + ./programs/pylint.nix + ./programs/qutebrowser.nix + ./programs/rbw.nix + ./programs/readline.nix + ./programs/rofi-pass.nix + ./programs/rofi.nix + ./programs/rtorrent.nix + ./programs/sagemath.nix + ./programs/sbt.nix + ./programs/scmpuff.nix + ./programs/senpai.nix + ./programs/sioyek.nix + ./programs/skim.nix + ./programs/sm64ex.nix + ./programs/sqls.nix + ./programs/ssh.nix + ./programs/starship.nix + ./programs/taskwarrior.nix + ./programs/tealdeer.nix + ./programs/terminator.nix + ./programs/termite.nix + ./programs/texlive.nix + ./programs/timidity.nix + ./programs/tint2.nix + ./programs/tiny.nix + ./programs/tmux.nix + ./programs/topgrade.nix + ./programs/urxvt.nix + ./programs/vim.nix + ./programs/vscode.nix + ./programs/vscode/haskell.nix + ./programs/watson.nix + ./programs/waybar.nix + ./programs/xmobar.nix + ./programs/z-lua.nix + ./programs/zathura.nix + ./programs/zellij.nix + ./programs/zoxide.nix + ./programs/zplug.nix + ./programs/zsh.nix + ./programs/zsh/prezto.nix + ./services/barrier.nix + ./services/betterlockscreen.nix + ./services/blueman-applet.nix + ./services/caffeine.nix + ./services/cbatticon.nix + ./services/clipmenu.nix + ./services/compton.nix + ./services/devilspie2.nix + ./services/dropbox.nix + ./services/dunst.nix + ./services/dwm-status.nix + ./services/easyeffects.nix + ./services/emacs.nix + ./services/etesync-dav.nix + ./services/espanso.nix + ./services/flameshot.nix + ./services/fluidsynth.nix + ./services/fnott.nix + ./services/fusuma.nix + ./services/getmail.nix + ./services/git-sync.nix + ./services/gnome-keyring.nix + ./services/gpg-agent.nix + ./services/grobi.nix + ./services/gromit-mpx.nix + ./services/home-manager-auto-upgrade.nix + ./services/hound.nix + ./services/imapnotify.nix + ./services/kanshi.nix + ./services/kbfs.nix + ./services/kdeconnect.nix + ./services/keepassx.nix + ./services/keybase.nix + ./services/keynav.nix + ./services/lieer.nix + ./services/lorri.nix + ./services/mako.nix + ./services/mbsync.nix + ./services/mopidy.nix + ./services/mpd.nix + ./services/mpdris2.nix + ./services/mpd-discord-rpc.nix + ./services/mpris-proxy.nix + ./services/muchsync.nix + ./services/network-manager-applet.nix + ./services/nextcloud-client.nix + ./services/notify-osd.nix + ./services/opensnitch-ui.nix + ./services/owncloud-client.nix + ./services/pantalaimon.nix + ./services/parcellite.nix + ./services/pass-secret-service.nix + ./services/password-store-sync.nix + ./services/pasystray.nix + ./services/pbgopy.nix + ./services/picom.nix + ./services/plan9port.nix + ./services/playerctld.nix + ./services/plex-mpv-shim.nix + ./services/polybar.nix + ./services/poweralertd.nix + ./services/pulseeffects.nix + ./services/random-background.nix + ./services/redshift-gammastep/gammastep.nix + ./services/redshift-gammastep/redshift.nix + ./services/rsibreak.nix + ./services/screen-locker.nix + ./services/spotifyd.nix + ./services/stalonetray.nix + ./services/status-notifier-watcher.nix + ./services/swayidle.nix + ./services/sxhkd.nix + ./services/syncthing.nix + ./services/systembus-notify.nix + ./services/taffybar.nix + ./services/tahoe-lafs.nix + ./services/taskwarrior-sync.nix + ./services/trayer.nix + ./services/twmn.nix + ./services/udiskie.nix + ./services/unclutter.nix + ./services/unison.nix + ./services/volnoti.nix + ./services/window-managers/awesome.nix + ./services/window-managers/bspwm/default.nix + ./services/window-managers/herbstluftwm.nix + ./services/window-managers/i3-sway/i3.nix + ./services/window-managers/i3-sway/sway.nix + ./services/window-managers/i3-sway/swaynag.nix + ./services/window-managers/xmonad.nix + ./services/wlsunset.nix + ./services/xcape.nix + ./services/xembed-sni-proxy.nix + ./services/xidlehook.nix + ./services/xscreensaver.nix + ./services/xsettingsd.nix + ./services/xsuspender.nix + ./systemd.nix + ./targets/darwin + ./targets/generic-linux.nix + ./xresources.nix + ./xsession.nix + ./misc/nix.nix + (pkgs.path + "/nixos/modules/misc/assertions.nix") + (pkgs.path + "/nixos/modules/misc/meta.nix") + ] ++ optional useNixpkgsModule ./misc/nixpkgs.nix + ++ optional (!useNixpkgsModule) ./misc/nixpkgs-disabled.nix; + + pkgsModule = { config, ... }: { + config = { + _module.args.baseModules = modules; + _module.args.pkgsPath = lib.mkDefault + (if versionAtLeast config.home.stateVersion "20.09" then + pkgs.path + else + ); + _module.args.pkgs = lib.mkDefault pkgs; + _module.check = check; + lib = lib.hm; + } // optionalAttrs useNixpkgsModule { + nixpkgs.system = mkDefault pkgs.stdenv.hostPlatform.system; + }; + }; + +in modules ++ [ pkgsModule ] diff --git a/infra/libkookie/home-manager-stable/modules/po/de.po b/infra/libkookie/home-manager-stable/modules/po/de.po new file mode 100644 index 00000000000..c4f4c509c35 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/po/de.po @@ -0,0 +1,153 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Home Manager contributors +# This file is distributed under the same license as the Home Manager Modules package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: Home Manager Modules\n" +"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" +"POT-Creation-Date: 2022-03-26 15:08+0100\n" +"PO-Revision-Date: 2022-03-26 23:57+0000\n" +"Last-Translator: Robert Helgesson \n" +"Language-Team: German \n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.12-dev\n" + +#: modules/files.nix:233 +msgid "Creating home file links in %s" +msgstr "Erstelle home Dateiverknpfungen in %s" + +#: modules/files.nix:246 +msgid "Cleaning up orphan links from %s" +msgstr "Bereinige verwaiste Links unter %s" + +#: modules/files.nix:262 +msgid "Creating profile generation %s" +msgstr "Erstelle Profilgeneration %s" + +#: modules/files.nix:276 +msgid "No change so reusing latest profile generation %s" +msgstr "Keine Änderungen. Benutze daher letzte Profilgeneration %s" + +#: modules/home-environment.nix:607 +msgid "" +"Oops, Nix failed to install your new Home Manager profile!\n" +"\n" +"Perhaps there is a conflict with a package that was installed using\n" +"\"%s\"? Try running\n" +"\n" +" %s\n" +"\n" +"and if there is a conflicting package you can remove it with\n" +"\n" +" %s\n" +"\n" +"Then try activating your Home Manager configuration again." +msgstr "" +"Ups, Nix konnte Ihr neues Home Manager Profil nicht installieren!\n" +"\n" +"Vielleicht gibt es einen Konflikt mit einem Paket, welches über\n" +"\"%s\" installiert wurde? Versuchen Sie\n" +"\n" +" %s\n" +"\n" +"auszuführen und wenn es ein problematisches Paket gibt, entfernen Sie es\n" +"mit\n" +"\n" +" %s\n" +"\n" +"Versuchen Sie dann, Ihre Home Manager Konfiguration erneut zu aktivieren." + +#: modules/home-environment.nix:639 +msgid "Activating %s" +msgstr "Aktiviere %s" + +#: modules/lib-bash/activation-init.sh:31 +msgid "Sanity checking oldGenNum and oldGenPath" +msgstr "Überprüfe zur Sicherheit oldGenNum und oldGenPath" + +#: modules/lib-bash/activation-init.sh:34 +msgid "" +"The previous generation number and path are in conflict! These\n" +"must be either both empty or both set but are now set to\n" +"\n" +" '%s' and '%s'\n" +"\n" +"If you don't mind losing previous profile generations then\n" +"the easiest solution is probably to run\n" +"\n" +" rm %s/home-manager*\n" +" rm %s/current-home\n" +"\n" +"and trying home-manager switch again. Good luck!" +msgstr "" +"Die vorherige Generationsnummer und -pfad stehen im Konflikt. Es\n" +"müssen entweder beide leer sein oder beide haben den Wert\n" +"\n" +" '%s' und '%s'\n" +"\n" +"Wenn es Ihnen nichts ausmacht frühere Generationen zu verlieren,\n" +"dann ist die einfachste Lösung folgendes auszuführen:\n" +"\n" +" rm %s/home-manager*\n" +" rm %s/current-home\n" +"\n" +"Führen Sie danach 'home-manager switch' aus. Viel Glück!" + +#: modules/lib-bash/activation-init.sh:51 +msgid "Starting Home Manager activation" +msgstr "Starte Home Manager Aktivierung" + +#: modules/lib-bash/activation-init.sh:55 +msgid "Sanity checking Nix" +msgstr "Überprüfe zur Sicherheit Nix" + +#: modules/lib-bash/activation-init.sh:61 +msgid "This is a dry run" +msgstr "Dies ist ein Probelauf" + +#: modules/lib-bash/activation-init.sh:64 +msgid "This is a live run" +msgstr "Dies ist eine Live-Ausführung" + +#: modules/lib-bash/activation-init.sh:69 +msgid "Using Nix version: %s" +msgstr "Nutze Nix Version: %s" + +#: modules/lib-bash/activation-init.sh:72 +msgid "Activation variables:" +msgstr "Aktivierungsvariablen:" + +#~ msgid "" +#~ "Oops, nix-env failed to install your new Home Manager profile!\n" +#~ "\n" +#~ "Perhaps there is a conflict with a package that was installed using\n" +#~ "\"nix-env -i\"? Try running\n" +#~ "\n" +#~ " nix-env -q\n" +#~ "\n" +#~ "and if there is a conflicting package you can remove it with\n" +#~ "\n" +#~ " nix-env -e {package name}\n" +#~ "\n" +#~ "Then try activating your Home Manager configuration again." +#~ msgstr "" +#~ "Ups, nix-env konnte Ihr neues Home Manager Profil nicht installieren!\n" +#~ "\n" +#~ "Vielleicht gibt es einen Konflikt mit einem Paket, welches über \"nix-env " +#~ "-i\" installiert wurde? Versuchen Sie\n" +#~ "\n" +#~ " nix-env -q\n" +#~ "\n" +#~ "auszuführen und wenn es ein problematisches Paket gibt, entfernen Sie es " +#~ "mit\n" +#~ "\n" +#~ " nix-env -e {package name}\n" +#~ "\n" +#~ "Versuchen Sie dann, Ihre Home Manager Konfiguration erneut zu aktivieren." diff --git a/infra/libkookie/home-manager-stable/modules/po/es.po b/infra/libkookie/home-manager-stable/modules/po/es.po new file mode 100644 index 00000000000..b5c0ee58a31 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/po/es.po @@ -0,0 +1,151 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Home Manager contributors +# This file is distributed under the same license as the Home Manager Modules package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: Home Manager Modules\n" +"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" +"POT-Creation-Date: 2022-03-26 15:08+0100\n" +"PO-Revision-Date: 2022-03-26 23:57+0000\n" +"Last-Translator: Robert Helgesson \n" +"Language-Team: Spanish \n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.12-dev\n" + +#: modules/files.nix:233 +msgid "Creating home file links in %s" +msgstr "Creando vínculos del directorio de inicio en %s" + +#: modules/files.nix:246 +msgid "Cleaning up orphan links from %s" +msgstr "Limpiando vínculos huérfanos de %s" + +#: modules/files.nix:262 +msgid "Creating profile generation %s" +msgstr "Creando generación de perfil %s" + +#: modules/files.nix:276 +msgid "No change so reusing latest profile generation %s" +msgstr "No hay cambios, reutilizando la generación más reciente del perfil: %s" + +#: modules/home-environment.nix:607 +msgid "" +"Oops, Nix failed to install your new Home Manager profile!\n" +"\n" +"Perhaps there is a conflict with a package that was installed using\n" +"\"%s\"? Try running\n" +"\n" +" %s\n" +"\n" +"and if there is a conflicting package you can remove it with\n" +"\n" +" %s\n" +"\n" +"Then try activating your Home Manager configuration again." +msgstr "" +"Nix no pudo instalar el nuevo perfil de Home Manager!\n" +"\n" +"Tal vez haya un conflicto con algún paquete instalado con \"%s\"?\n" +"Intente ejecutar\n" +"\n" +" %s\n" +"\n" +"y si hay algún paquete en conflicto bórrelo con:\n" +"\n" +" %s\n" +"\n" +"Y después reintente activar su configuración de Home Manager." + +#: modules/home-environment.nix:639 +msgid "Activating %s" +msgstr "Activando %s" + +#: modules/lib-bash/activation-init.sh:31 +msgid "Sanity checking oldGenNum and oldGenPath" +msgstr "Chequeando oldGenNum y oldGenPath" + +#: modules/lib-bash/activation-init.sh:34 +msgid "" +"The previous generation number and path are in conflict! These\n" +"must be either both empty or both set but are now set to\n" +"\n" +" '%s' and '%s'\n" +"\n" +"If you don't mind losing previous profile generations then\n" +"the easiest solution is probably to run\n" +"\n" +" rm %s/home-manager*\n" +" rm %s/current-home\n" +"\n" +"and trying home-manager switch again. Good luck!" +msgstr "" +"Conflicto entre ruta y número de la generación previa. Ambos deben o estar " +"vacíos o definidos como\n" +"\n" +" '%s' y '%s'\n" +"\n" +"Si no le importa perder las generaciones de perfil anteriores, la solución " +"más sencilla es ejecutar:\n" +"\n" +" rm %s/home-manager*\n" +" rm %s/current-home\n" +"\n" +"y luego reintente ejectuar \"home-manager switch\". Suerte!" + +#: modules/lib-bash/activation-init.sh:51 +msgid "Starting Home Manager activation" +msgstr "Comenzando activación de Home Manager" + +#: modules/lib-bash/activation-init.sh:55 +msgid "Sanity checking Nix" +msgstr "Chequeando Nix" + +#: modules/lib-bash/activation-init.sh:61 +msgid "This is a dry run" +msgstr "Ejecución de simulacro" + +#: modules/lib-bash/activation-init.sh:64 +msgid "This is a live run" +msgstr "Ejecución en vivo" + +#: modules/lib-bash/activation-init.sh:69 +msgid "Using Nix version: %s" +msgstr "Usando Nix versión %s" + +#: modules/lib-bash/activation-init.sh:72 +msgid "Activation variables:" +msgstr "Variables de activación:" + +#~ msgid "" +#~ "Oops, nix-env failed to install your new Home Manager profile!\n" +#~ "\n" +#~ "Perhaps there is a conflict with a package that was installed using\n" +#~ "\"nix-env -i\"? Try running\n" +#~ "\n" +#~ " nix-env -q\n" +#~ "\n" +#~ "and if there is a conflicting package you can remove it with\n" +#~ "\n" +#~ " nix-env -e {package name}\n" +#~ "\n" +#~ "Then try activating your Home Manager configuration again." +#~ msgstr "" +#~ "nix-env no pudo instalar el nuevo perfil de Home Manager!\n" +#~ "\n" +#~ "Tal vez haya un conflicto con algún paquete instalado con \"nix-env -i\"? " +#~ "Intente ejecutar\n" +#~ "\n" +#~ " nix-env -q\n" +#~ "\n" +#~ "y si hay algún paquete en conflicto bórrelo con:\n" +#~ "\n" +#~ " nix-env -e {paquete}\n" +#~ "\n" +#~ "Y después reintente activar su configuración de Home Manager." diff --git a/infra/libkookie/home-manager-stable/modules/po/fa.po b/infra/libkookie/home-manager-stable/modules/po/fa.po new file mode 100644 index 00000000000..fe1713272ac --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/po/fa.po @@ -0,0 +1,97 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Home Manager contributors +# This file is distributed under the same license as the Home Manager Modules package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: Home Manager Modules\n" +"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" +"POT-Creation-Date: 2022-03-26 15:08+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: fa\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: modules/files.nix:233 +msgid "Creating home file links in %s" +msgstr "" + +#: modules/files.nix:246 +msgid "Cleaning up orphan links from %s" +msgstr "" + +#: modules/files.nix:262 +msgid "Creating profile generation %s" +msgstr "" + +#: modules/files.nix:276 +msgid "No change so reusing latest profile generation %s" +msgstr "" + +#: modules/home-environment.nix:607 +msgid "" +"Oops, Nix failed to install your new Home Manager profile!\n" +"\n" +"Perhaps there is a conflict with a package that was installed using\n" +"\"%s\"? Try running\n" +"\n" +" %s\n" +"\n" +"and if there is a conflicting package you can remove it with\n" +"\n" +" %s\n" +"\n" +"Then try activating your Home Manager configuration again." +msgstr "" + +#: modules/home-environment.nix:639 +msgid "Activating %s" +msgstr "" + +#: modules/lib-bash/activation-init.sh:31 +msgid "Sanity checking oldGenNum and oldGenPath" +msgstr "" + +#: modules/lib-bash/activation-init.sh:34 +msgid "" +"The previous generation number and path are in conflict! These\n" +"must be either both empty or both set but are now set to\n" +"\n" +" '%s' and '%s'\n" +"\n" +"If you don't mind losing previous profile generations then\n" +"the easiest solution is probably to run\n" +"\n" +" rm %s/home-manager*\n" +" rm %s/current-home\n" +"\n" +"and trying home-manager switch again. Good luck!" +msgstr "" + +#: modules/lib-bash/activation-init.sh:51 +msgid "Starting Home Manager activation" +msgstr "" + +#: modules/lib-bash/activation-init.sh:55 +msgid "Sanity checking Nix" +msgstr "" + +#: modules/lib-bash/activation-init.sh:61 +msgid "This is a dry run" +msgstr "" + +#: modules/lib-bash/activation-init.sh:64 +msgid "This is a live run" +msgstr "" + +#: modules/lib-bash/activation-init.sh:69 +msgid "Using Nix version: %s" +msgstr "" + +#: modules/lib-bash/activation-init.sh:72 +msgid "Activation variables:" +msgstr "" diff --git a/infra/libkookie/home-manager-stable/modules/po/fr.po b/infra/libkookie/home-manager-stable/modules/po/fr.po new file mode 100644 index 00000000000..c538ddc5dd8 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/po/fr.po @@ -0,0 +1,154 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Home Manager contributors +# This file is distributed under the same license as the Home Manager Modules package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: Home Manager Modules\n" +"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" +"POT-Creation-Date: 2022-03-26 15:08+0100\n" +"PO-Revision-Date: 2022-05-18 23:12+0000\n" +"Last-Translator: Naïm Camille Favier \n" +"Language-Team: French \n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 4.13-dev\n" + +#: modules/files.nix:233 +msgid "Creating home file links in %s" +msgstr "Création des liens de fichiers personnels dans %s" + +#: modules/files.nix:246 +msgid "Cleaning up orphan links from %s" +msgstr "Nettoyage des liens orphelins de %s" + +#: modules/files.nix:262 +msgid "Creating profile generation %s" +msgstr "Création de la génération de profil %s" + +#: modules/files.nix:276 +msgid "No change so reusing latest profile generation %s" +msgstr "Pas de changement, réutilisation du dernier profil génération %s" + +#: modules/home-environment.nix:607 +msgid "" +"Oops, Nix failed to install your new Home Manager profile!\n" +"\n" +"Perhaps there is a conflict with a package that was installed using\n" +"\"%s\"? Try running\n" +"\n" +" %s\n" +"\n" +"and if there is a conflicting package you can remove it with\n" +"\n" +" %s\n" +"\n" +"Then try activating your Home Manager configuration again." +msgstr "" +"Oups, Nix n'a pas réussi à installer votre nouveau profil de Home Manager !\n" +"\n" +"Il y a peut-être un conflit avec un autre paquet qui a été installé avec\n" +"« %s » ? Essayez d'exécuter\n" +"\n" +" %s\n" +"\n" +"et s'il y a un paquet en conflit, vous pourrez le supprimer avec\n" +"\n" +" %s\n" +"\n" +"Après, essayez encore d'activer votre configuration de Home Manager." + +#: modules/home-environment.nix:639 +msgid "Activating %s" +msgstr "Activation de %s" + +#: modules/lib-bash/activation-init.sh:31 +msgid "Sanity checking oldGenNum and oldGenPath" +msgstr "Vérification de oldGenNum et oldGenPath" + +#: modules/lib-bash/activation-init.sh:34 +msgid "" +"The previous generation number and path are in conflict! These\n" +"must be either both empty or both set but are now set to\n" +"\n" +" '%s' and '%s'\n" +"\n" +"If you don't mind losing previous profile generations then\n" +"the easiest solution is probably to run\n" +"\n" +" rm %s/home-manager*\n" +" rm %s/current-home\n" +"\n" +"and trying home-manager switch again. Good luck!" +msgstr "" +"Le numéro et le chemin de la génération précédente sont en conflit ! Ils " +"doivent\n" +"être vides ou les deux mis à\n" +"\n" +" '%s' et '%s'\n" +"\n" +"Si ça ne vous dérange pas de perdre les générations précédentes, la solution " +"la plus\n" +"simple est probablement d'exécuter\n" +"\n" +" rm %s/home-manager*\n" +" rm %s/current-home\n" +"\n" +"et de réessayer home-manager switch. Bonne chance !" + +#: modules/lib-bash/activation-init.sh:51 +msgid "Starting Home Manager activation" +msgstr "Démarrage de l'activation de Home Manager" + +#: modules/lib-bash/activation-init.sh:55 +msgid "Sanity checking Nix" +msgstr "Vérification de Nix" + +#: modules/lib-bash/activation-init.sh:61 +msgid "This is a dry run" +msgstr "Ceci est une fausse activation (essai à blanc)" + +#: modules/lib-bash/activation-init.sh:64 +msgid "This is a live run" +msgstr "Ceci est une vraie activation" + +#: modules/lib-bash/activation-init.sh:69 +msgid "Using Nix version: %s" +msgstr "Version de Nix : %s" + +#: modules/lib-bash/activation-init.sh:72 +msgid "Activation variables:" +msgstr "Variables d'activation :" + +#~ msgid "" +#~ "Oops, nix-env failed to install your new Home Manager profile!\n" +#~ "\n" +#~ "Perhaps there is a conflict with a package that was installed using\n" +#~ "\"nix-env -i\"? Try running\n" +#~ "\n" +#~ " nix-env -q\n" +#~ "\n" +#~ "and if there is a conflicting package you can remove it with\n" +#~ "\n" +#~ " nix-env -e {package name}\n" +#~ "\n" +#~ "Then try activating your Home Manager configuration again." +#~ msgstr "" +#~ "Oups, nix-env n'a pas réussi à installer votre nouveau profil de Home " +#~ "Manager\n" +#~ "\n" +#~ "Il y a peut-être un conflit avec un autre paquet qui a été installé avec\n" +#~ "« nix-env -i » ? Essayez d'éxecuter\n" +#~ "\n" +#~ " nix-env -q\n" +#~ "\n" +#~ "et s'il y a un paquet en conflict, vous pourrez le supprimer avec\n" +#~ "\n" +#~ " nix-env -e {package name}\n" +#~ "\n" +#~ "Après, essayez encore d'activer votre configuration de Home Manager." diff --git a/infra/libkookie/home-manager-stable/modules/po/hm-modules.pot b/infra/libkookie/home-manager-stable/modules/po/hm-modules.pot new file mode 100644 index 00000000000..7bff64af49a --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/po/hm-modules.pot @@ -0,0 +1,98 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Home Manager contributors +# This file is distributed under the same license as the Home Manager Modules package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: Home Manager Modules\n" +"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" +"POT-Creation-Date: 2022-03-26 15:08+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: modules/files.nix:233 +msgid "Creating home file links in %s" +msgstr "" + +#: modules/files.nix:246 +msgid "Cleaning up orphan links from %s" +msgstr "" + +#: modules/files.nix:262 +msgid "Creating profile generation %s" +msgstr "" + +#: modules/files.nix:276 +msgid "No change so reusing latest profile generation %s" +msgstr "" + +#: modules/home-environment.nix:607 +msgid "" +"Oops, Nix failed to install your new Home Manager profile!\n" +"\n" +"Perhaps there is a conflict with a package that was installed using\n" +"\"%s\"? Try running\n" +"\n" +" %s\n" +"\n" +"and if there is a conflicting package you can remove it with\n" +"\n" +" %s\n" +"\n" +"Then try activating your Home Manager configuration again." +msgstr "" + +#: modules/home-environment.nix:639 +msgid "Activating %s" +msgstr "" + +#: modules/lib-bash/activation-init.sh:31 +msgid "Sanity checking oldGenNum and oldGenPath" +msgstr "" + +#: modules/lib-bash/activation-init.sh:34 +msgid "" +"The previous generation number and path are in conflict! These\n" +"must be either both empty or both set but are now set to\n" +"\n" +" '%s' and '%s'\n" +"\n" +"If you don't mind losing previous profile generations then\n" +"the easiest solution is probably to run\n" +"\n" +" rm %s/home-manager*\n" +" rm %s/current-home\n" +"\n" +"and trying home-manager switch again. Good luck!" +msgstr "" + +#: modules/lib-bash/activation-init.sh:51 +msgid "Starting Home Manager activation" +msgstr "" + +#: modules/lib-bash/activation-init.sh:55 +msgid "Sanity checking Nix" +msgstr "" + +#: modules/lib-bash/activation-init.sh:61 +msgid "This is a dry run" +msgstr "" + +#: modules/lib-bash/activation-init.sh:64 +msgid "This is a live run" +msgstr "" + +#: modules/lib-bash/activation-init.sh:69 +msgid "Using Nix version: %s" +msgstr "" + +#: modules/lib-bash/activation-init.sh:72 +msgid "Activation variables:" +msgstr "" diff --git a/infra/libkookie/home-manager-stable/modules/po/it.po b/infra/libkookie/home-manager-stable/modules/po/it.po new file mode 100644 index 00000000000..cec8b104291 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/po/it.po @@ -0,0 +1,112 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Home Manager contributors +# This file is distributed under the same license as the Home Manager Modules package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: Home Manager Modules\n" +"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" +"POT-Creation-Date: 2022-03-26 15:08+0100\n" +"PO-Revision-Date: 2022-04-20 18:18+0000\n" +"Last-Translator: Frankie McEyes \n" +"Language-Team: Italian \n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.12-dev\n" + +#: modules/files.nix:233 +msgid "Creating home file links in %s" +msgstr "Creo i collegamenti della home in %s" + +#: modules/files.nix:246 +msgid "Cleaning up orphan links from %s" +msgstr "Pulisco i collegamenti rimasti orfani da %s" + +#: modules/files.nix:262 +msgid "Creating profile generation %s" +msgstr "Creando profilo di generazione %s" + +#: modules/files.nix:276 +msgid "No change so reusing latest profile generation %s" +msgstr "Nessuna modifica, verrà riutilizzata l'ultimo generazione di profilo %s" + +#: modules/home-environment.nix:607 +msgid "" +"Oops, Nix failed to install your new Home Manager profile!\n" +"\n" +"Perhaps there is a conflict with a package that was installed using\n" +"\"%s\"? Try running\n" +"\n" +" %s\n" +"\n" +"and if there is a conflicting package you can remove it with\n" +"\n" +" %s\n" +"\n" +"Then try activating your Home Manager configuration again." +msgstr "" + +#: modules/home-environment.nix:639 +msgid "Activating %s" +msgstr "Attivando %s" + +#: modules/lib-bash/activation-init.sh:31 +msgid "Sanity checking oldGenNum and oldGenPath" +msgstr "" + +#: modules/lib-bash/activation-init.sh:34 +msgid "" +"The previous generation number and path are in conflict! These\n" +"must be either both empty or both set but are now set to\n" +"\n" +" '%s' and '%s'\n" +"\n" +"If you don't mind losing previous profile generations then\n" +"the easiest solution is probably to run\n" +"\n" +" rm %s/home-manager*\n" +" rm %s/current-home\n" +"\n" +"and trying home-manager switch again. Good luck!" +msgstr "" +"I precedenti numero di generazione e il percorso sono in conflitto!\n" +"Devono essere entrambi vuoti o entrambi popolati ma ora sono impostati su\n" +"\n" +"'%s' e '%s'\n" +"\n" +"Se non ti dispiace perdere le generazioni di profili precedenti,\n" +"allora la soluzione più semplice è probabilmente eseguire i comandi\n" +"\n" +"rm %s/home-manager*\n" +"rm %s/current-home\n" +"\n" +"e provare a cambiare home-manager di nuovo. Buona fortuna!" + +#: modules/lib-bash/activation-init.sh:51 +msgid "Starting Home Manager activation" +msgstr "Iniziando attivazione Home Manager" + +#: modules/lib-bash/activation-init.sh:55 +msgid "Sanity checking Nix" +msgstr "Controllando Nix" + +#: modules/lib-bash/activation-init.sh:61 +msgid "This is a dry run" +msgstr "Questo è un avvio secco" + +#: modules/lib-bash/activation-init.sh:64 +msgid "This is a live run" +msgstr "Questa è una esecuzione live" + +#: modules/lib-bash/activation-init.sh:69 +msgid "Using Nix version: %s" +msgstr "Versione di Nix in uso: %s" + +#: modules/lib-bash/activation-init.sh:72 +msgid "Activation variables:" +msgstr "Variabili di attivazione:" diff --git a/infra/libkookie/home-manager-stable/modules/po/ja.po b/infra/libkookie/home-manager-stable/modules/po/ja.po new file mode 100644 index 00000000000..f5cec7ba210 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/po/ja.po @@ -0,0 +1,153 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Home Manager contributors +# This file is distributed under the same license as the Home Manager Modules package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: Home Manager Modules\n" +"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" +"POT-Creation-Date: 2022-03-26 15:08+0100\n" +"PO-Revision-Date: 2022-03-26 23:57+0000\n" +"Last-Translator: Robert Helgesson \n" +"Language-Team: Japanese \n" +"Language: ja\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 4.12-dev\n" + +#: modules/files.nix:233 +msgid "Creating home file links in %s" +msgstr "ホームファイルのリンクを %s に作ります" + +#: modules/files.nix:246 +msgid "Cleaning up orphan links from %s" +msgstr "%s から無効なリンクを消去しています" + +#: modules/files.nix:262 +msgid "Creating profile generation %s" +msgstr "世代 %s のプロファイルを生成しています" + +#: modules/files.nix:276 +msgid "No change so reusing latest profile generation %s" +msgstr "変更されていないので最新の世代 %s のプロファイルを再利用します" + +#: modules/home-environment.nix:607 +msgid "" +"Oops, Nix failed to install your new Home Manager profile!\n" +"\n" +"Perhaps there is a conflict with a package that was installed using\n" +"\"%s\"? Try running\n" +"\n" +" %s\n" +"\n" +"and if there is a conflicting package you can remove it with\n" +"\n" +" %s\n" +"\n" +"Then try activating your Home Manager configuration again." +msgstr "" +"NixはHome Managerの新しいプロファイルをインストールできませんでした!\n" +"\n" +"おそらく\"%s\"を使ってインストールしたパッケージが矛盾しているのでは?\n" +"以下のコマンド\n" +"\n" +" %s\n" +"\n" +"を試してみて、もし衝突しているパッケージがあれば、\n" +"\n" +" %s\n" +"\n" +"で削除し、再度Home Managerの設定の有効化を試してみてください。" + +#: modules/home-environment.nix:639 +msgid "Activating %s" +msgstr "%s を有効化しています" + +#: modules/lib-bash/activation-init.sh:31 +msgid "Sanity checking oldGenNum and oldGenPath" +msgstr "oldGenNum と oldGenPath の健全性検査をしています" + +#: modules/lib-bash/activation-init.sh:34 +msgid "" +"The previous generation number and path are in conflict! These\n" +"must be either both empty or both set but are now set to\n" +"\n" +" '%s' and '%s'\n" +"\n" +"If you don't mind losing previous profile generations then\n" +"the easiest solution is probably to run\n" +"\n" +" rm %s/home-manager*\n" +" rm %s/current-home\n" +"\n" +"and trying home-manager switch again. Good luck!" +msgstr "" +"先行する世代番号とパスが矛盾しています!\n" +"それらはどちらも空かどちらもセットされていなければいけません。しかし\n" +"\n" +" '%s' と '%s'\n" +"\n" +"となっています。もしプロファイルの以前の世代を失っても構わないなら\n" +"おそらくもっとも簡単な解決法は\n" +"\n" +" rm %s/home-manager*\n" +" rm %s/current-home\n" +"\n" +"を実行して、home-manager switch を再び実行してみることでしょう。幸運を!" + +#: modules/lib-bash/activation-init.sh:51 +msgid "Starting Home Manager activation" +msgstr "Home Managerの有効化を開始しました" + +#: modules/lib-bash/activation-init.sh:55 +msgid "Sanity checking Nix" +msgstr "Nixの健全性検査中です" + +#: modules/lib-bash/activation-init.sh:61 +msgid "This is a dry run" +msgstr "これは予行練習(dry run)です" + +#: modules/lib-bash/activation-init.sh:64 +msgid "This is a live run" +msgstr "これは実際に実行します" + +#: modules/lib-bash/activation-init.sh:69 +msgid "Using Nix version: %s" +msgstr "Nix バージョン %s を使用しています" + +#: modules/lib-bash/activation-init.sh:72 +msgid "Activation variables:" +msgstr "有効化変数:" + +#~ msgid "" +#~ "Oops, nix-env failed to install your new Home Manager profile!\n" +#~ "\n" +#~ "Perhaps there is a conflict with a package that was installed using\n" +#~ "\"nix-env -i\"? Try running\n" +#~ "\n" +#~ " nix-env -q\n" +#~ "\n" +#~ "and if there is a conflicting package you can remove it with\n" +#~ "\n" +#~ " nix-env -e {package name}\n" +#~ "\n" +#~ "Then try activating your Home Manager configuration again." +#~ msgstr "" +#~ "nix-envはHome managerの新しいプロファイルをインストールできませんでし" +#~ "た!\n" +#~ "\n" +#~ "おそらく\"nix-env -i\"を使ってインストールしたパッケージが矛盾しているので" +#~ "は?\n" +#~ "以下のコマンド\n" +#~ "\n" +#~ "nix-env -q\n" +#~ "\n" +#~ "を試してみて、もし衝突しているパッケージがあれば、\n" +#~ "\n" +#~ "nix-env -e {パッケージ名前}\n" +#~ "\n" +#~ "で削除し、再度Home Managerの設定の有効化を試してみてください。" diff --git a/infra/libkookie/home-manager-stable/modules/po/ko.po b/infra/libkookie/home-manager-stable/modules/po/ko.po new file mode 100644 index 00000000000..7c97f64a3f0 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/po/ko.po @@ -0,0 +1,154 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Home Manager contributors +# This file is distributed under the same license as the Home Manager Modules package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: Home Manager Modules\n" +"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" +"POT-Creation-Date: 2022-03-26 15:08+0100\n" +"PO-Revision-Date: 2022-03-26 23:57+0000\n" +"Last-Translator: Robert Helgesson \n" +"Language-Team: Korean \n" +"Language: ko\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 4.12-dev\n" + +#: modules/files.nix:233 +msgid "Creating home file links in %s" +msgstr "home 파일 링크를 %s에 생성하는 중" + +#: modules/files.nix:246 +msgid "Cleaning up orphan links from %s" +msgstr "%s에서 연결이 끊어진 링크 파일들을 지우는 중" + +#: modules/files.nix:262 +msgid "Creating profile generation %s" +msgstr "profile 세대 %s를 생성하는 중" + +#: modules/files.nix:276 +msgid "No change so reusing latest profile generation %s" +msgstr "" +"바뀐 것이 없어서 가장 최근의 profile 세대 %s를 다시 사용하는 것으로 설정하는 " +"중" + +#: modules/home-environment.nix:607 +msgid "" +"Oops, Nix failed to install your new Home Manager profile!\n" +"\n" +"Perhaps there is a conflict with a package that was installed using\n" +"\"%s\"? Try running\n" +"\n" +" %s\n" +"\n" +"and if there is a conflicting package you can remove it with\n" +"\n" +" %s\n" +"\n" +"Then try activating your Home Manager configuration again." +msgstr "" +"아이고, Nix가 새로운 홈 매니저 profile을 설치하는데 실패했네요!\n" +"\n" +"혹시나 \"%s\"를 이용해서 설치된 패키지와 충돌이 일어난 것 일까요?\n" +"다음의 명령어를 시도해보세요.\n" +"\n" +" %s\n" +"\n" +"만약 충돌하는 패키지가 있다면 다음의 명령어로 제거할 수 있습니다.\n" +"\n" +" %s\n" +"\n" +"그런 후, 다시 홈 매니저 설정을 활성화 해보세요." + +#: modules/home-environment.nix:639 +msgid "Activating %s" +msgstr "%s를 활성화 하는 중" + +#: modules/lib-bash/activation-init.sh:31 +msgid "Sanity checking oldGenNum and oldGenPath" +msgstr "oldGenNum과 oldGenPath가 정상인지 확인 중" + +#: modules/lib-bash/activation-init.sh:34 +msgid "" +"The previous generation number and path are in conflict! These\n" +"must be either both empty or both set but are now set to\n" +"\n" +" '%s' and '%s'\n" +"\n" +"If you don't mind losing previous profile generations then\n" +"the easiest solution is probably to run\n" +"\n" +" rm %s/home-manager*\n" +" rm %s/current-home\n" +"\n" +"and trying home-manager switch again. Good luck!" +msgstr "" +"이전 세대 번호와 경로가 서로 충돌하고 있습니다! 이들은 둘 다 비어있든지\n" +"아니면 둘 다 설정돼있어야 하는데 지금 이들은 다음으로 설정되어있습니다.\n" +"\n" +" '%s' 와 '%s'\n" +"\n" +"만약 이전 profile 세대들을 잃는 것이 상관없다면\n" +"가장 쉬운 해결 방법은 아마 다음의 명령어를 실행하는 것일 겁니다.\n" +"\n" +" rm %s/home-manager*\n" +" rm %s/current-home\n" +"\n" +"그런 후 'home-manager switch'를 다시 시도해 보십시오. 행운을 빕니다!" + +#: modules/lib-bash/activation-init.sh:51 +msgid "Starting Home Manager activation" +msgstr "홈 매니저 활성화를 시작하는 중" + +#: modules/lib-bash/activation-init.sh:55 +msgid "Sanity checking Nix" +msgstr "Nix가 정상인지 확인 중" + +#: modules/lib-bash/activation-init.sh:61 +msgid "This is a dry run" +msgstr "모의 실행 중 입니다" + +#: modules/lib-bash/activation-init.sh:64 +msgid "This is a live run" +msgstr "모의 실행이 아닌 실제 실행 중 입니다" + +#: modules/lib-bash/activation-init.sh:69 +msgid "Using Nix version: %s" +msgstr "사용 중인 Nix 버전: %s" + +#: modules/lib-bash/activation-init.sh:72 +msgid "Activation variables:" +msgstr "활성화 변수들:" + +#~ msgid "" +#~ "Oops, nix-env failed to install your new Home Manager profile!\n" +#~ "\n" +#~ "Perhaps there is a conflict with a package that was installed using\n" +#~ "\"nix-env -i\"? Try running\n" +#~ "\n" +#~ " nix-env -q\n" +#~ "\n" +#~ "and if there is a conflicting package you can remove it with\n" +#~ "\n" +#~ " nix-env -e {package name}\n" +#~ "\n" +#~ "Then try activating your Home Manager configuration again." +#~ msgstr "" +#~ "아이고, nix-env가 새로운 홈 매니저 profile을 설치하는데 실패했네요!\n" +#~ "\n" +#~ "혹시나 \"nix-env -i\"를 이용해서 설치된 패키지와 충돌이 일어난 것 일까" +#~ "요?\n" +#~ "다음의 명령어를 시도해보세요.\n" +#~ "\n" +#~ " nix-env -q\n" +#~ "\n" +#~ "만약 충돌하는 패키지가 있다면 다음의 명령어로 제거할 수 있습니다.\n" +#~ "\n" +#~ " nix-env -e {패키지 이름}\n" +#~ "\n" +#~ "그런 후, 다시 홈 매니저 설정을 활성화 해보세요." diff --git a/infra/libkookie/home-manager-stable/modules/po/nb_NO.po b/infra/libkookie/home-manager-stable/modules/po/nb_NO.po new file mode 100644 index 00000000000..11bc04d9431 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/po/nb_NO.po @@ -0,0 +1,153 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Home Manager contributors +# This file is distributed under the same license as the Home Manager Modules package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: Home Manager Modules\n" +"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" +"POT-Creation-Date: 2022-03-26 15:08+0100\n" +"PO-Revision-Date: 2022-03-26 23:57+0000\n" +"Last-Translator: Robert Helgesson \n" +"Language-Team: Norwegian Bokmål \n" +"Language: nb_NO\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.12-dev\n" + +#: modules/files.nix:233 +msgid "Creating home file links in %s" +msgstr "Lager hjemmefillenker i %s …" + +#: modules/files.nix:246 +msgid "Cleaning up orphan links from %s" +msgstr "Tømmer overflødige lenker fra %s …" + +#: modules/files.nix:262 +#, fuzzy +msgid "Creating profile generation %s" +msgstr "Oppretter profil for generering %s …" + +#: modules/files.nix:276 +msgid "No change so reusing latest profile generation %s" +msgstr "Ingen endring. Gjenbruker siste profilgenerering %s …" + +#: modules/home-environment.nix:607 +msgid "" +"Oops, Nix failed to install your new Home Manager profile!\n" +"\n" +"Perhaps there is a conflict with a package that was installed using\n" +"\"%s\"? Try running\n" +"\n" +" %s\n" +"\n" +"and if there is a conflicting package you can remove it with\n" +"\n" +" %s\n" +"\n" +"Then try activating your Home Manager configuration again." +msgstr "" +"Nix kunne ikke installere din nye Home Manager-profil!\n" +"\n" +"Kanskje det er en konflikt med en pakke som ble installert ved bruk av\n" +"«%s«? Prøv å kjøre\n" +"\n" +" %s\n" +"\n" +"og hvis det er en pakke i konflikt kan du fjerne den med\n" +"\n" +" %s\n" +"\n" +"for så å aktivere ditt Home Manager-oppsett igjen." + +#: modules/home-environment.nix:639 +msgid "Activating %s" +msgstr "Aktiverer %s …" + +#: modules/lib-bash/activation-init.sh:31 +msgid "Sanity checking oldGenNum and oldGenPath" +msgstr "Kontrollerer verdiene av oldGenNum og oldGenPath" + +#: modules/lib-bash/activation-init.sh:34 +#, fuzzy +msgid "" +"The previous generation number and path are in conflict! These\n" +"must be either both empty or both set but are now set to\n" +"\n" +" '%s' and '%s'\n" +"\n" +"If you don't mind losing previous profile generations then\n" +"the easiest solution is probably to run\n" +"\n" +" rm %s/home-manager*\n" +" rm %s/current-home\n" +"\n" +"and trying home-manager switch again. Good luck!" +msgstr "" +"Forrige generasjonstall og sti er i konflikt. Disse\n" +"må enten begge være tomme, eller så må begge settes, men er nå\n" +"\n" +" «%s« og «%s«\n" +"\n" +"Hvis du ikke bryr deg om å miste tidligere profilgenereringer\n" +"er det enkleste å kjøre\n" +"\n" +" rm %s/home-manager*\n" +" rm %s/current-home\n" +"\n" +"for så å prøve «home-manager»-bryteren igjen. Lykke til!" + +#: modules/lib-bash/activation-init.sh:51 +msgid "Starting Home Manager activation" +msgstr "Starter aktivering av hjemmebehandler …" + +#: modules/lib-bash/activation-init.sh:55 +msgid "Sanity checking Nix" +msgstr "Kontrollerer at Nix fungerer" + +#: modules/lib-bash/activation-init.sh:61 +msgid "This is a dry run" +msgstr "Dette er en simulert kjøring" + +#: modules/lib-bash/activation-init.sh:64 +msgid "This is a live run" +msgstr "Dette er en virkelig kjøring" + +#: modules/lib-bash/activation-init.sh:69 +msgid "Using Nix version: %s" +msgstr "Bruker Nix-versjon: %s" + +#: modules/lib-bash/activation-init.sh:72 +msgid "Activation variables:" +msgstr "Aktiveringsvariabler:" + +#~ msgid "" +#~ "Oops, nix-env failed to install your new Home Manager profile!\n" +#~ "\n" +#~ "Perhaps there is a conflict with a package that was installed using\n" +#~ "\"nix-env -i\"? Try running\n" +#~ "\n" +#~ " nix-env -q\n" +#~ "\n" +#~ "and if there is a conflicting package you can remove it with\n" +#~ "\n" +#~ " nix-env -e {package name}\n" +#~ "\n" +#~ "Then try activating your Home Manager configuration again." +#~ msgstr "" +#~ "nix-env kunne ikke installere din nye Home Manager-profil!\n" +#~ "\n" +#~ "Kanskje det er en konflikt med en pakke som ble installert ved bruk av\n" +#~ "«nix-env -i«? Prøv å kjøre\n" +#~ "\n" +#~ " nix-env -q\n" +#~ "\n" +#~ "og hvis det er en pakke i konflikt kan du fjerne den med\n" +#~ "\n" +#~ " nix-env -e {package name}\n" +#~ "\n" +#~ "for så å aktivere ditt Home Manager-oppsett igjen." diff --git a/infra/libkookie/home-manager-stable/modules/po/pl.po b/infra/libkookie/home-manager-stable/modules/po/pl.po new file mode 100644 index 00000000000..e9262433797 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/po/pl.po @@ -0,0 +1,103 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Home Manager contributors +# This file is distributed under the same license as the Home Manager Modules package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: Home Manager Modules\n" +"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" +"POT-Creation-Date: 2022-03-26 15:08+0100\n" +"PO-Revision-Date: 2022-03-01 13:58+0000\n" +"Last-Translator: Anon Ymous \n" +"Language-Team: Polish \n" +"Language: pl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " +"|| n%100>=20) ? 1 : 2;\n" +"X-Generator: Weblate 4.11.1-dev\n" + +#: modules/files.nix:233 +msgid "Creating home file links in %s" +msgstr "Tworzenie dowiązań plików w %s" + +#: modules/files.nix:246 +msgid "Cleaning up orphan links from %s" +msgstr "Czyszczenie osieroconych linków z %s" + +#: modules/files.nix:262 +msgid "Creating profile generation %s" +msgstr "Tworzenie profilu generacji %s" + +#: modules/files.nix:276 +msgid "No change so reusing latest profile generation %s" +msgstr "Brak zmian więc używam ostatniej generacji profilu %s" + +#: modules/home-environment.nix:607 +msgid "" +"Oops, Nix failed to install your new Home Manager profile!\n" +"\n" +"Perhaps there is a conflict with a package that was installed using\n" +"\"%s\"? Try running\n" +"\n" +" %s\n" +"\n" +"and if there is a conflicting package you can remove it with\n" +"\n" +" %s\n" +"\n" +"Then try activating your Home Manager configuration again." +msgstr "" + +#: modules/home-environment.nix:639 +msgid "Activating %s" +msgstr "Aktywowanie %s" + +#: modules/lib-bash/activation-init.sh:31 +msgid "Sanity checking oldGenNum and oldGenPath" +msgstr "Sprawdzanie poprawności oldGenNum i oldGenPath" + +#: modules/lib-bash/activation-init.sh:34 +msgid "" +"The previous generation number and path are in conflict! These\n" +"must be either both empty or both set but are now set to\n" +"\n" +" '%s' and '%s'\n" +"\n" +"If you don't mind losing previous profile generations then\n" +"the easiest solution is probably to run\n" +"\n" +" rm %s/home-manager*\n" +" rm %s/current-home\n" +"\n" +"and trying home-manager switch again. Good luck!" +msgstr "" + +#: modules/lib-bash/activation-init.sh:51 +msgid "Starting Home Manager activation" +msgstr "Rozpoczynam aktywację Home Managera" + +#: modules/lib-bash/activation-init.sh:55 +msgid "Sanity checking Nix" +msgstr "Sprawdzanie poprawności Nix" + +#: modules/lib-bash/activation-init.sh:61 +#, fuzzy +msgid "This is a dry run" +msgstr "To jest próbne wykonanie" + +#: modules/lib-bash/activation-init.sh:64 +msgid "This is a live run" +msgstr "" + +#: modules/lib-bash/activation-init.sh:69 +msgid "Using Nix version: %s" +msgstr "Używając wersji Nix: %s" + +#: modules/lib-bash/activation-init.sh:72 +#, fuzzy +msgid "Activation variables:" +msgstr "Zmienne aktywacyjne:" diff --git a/infra/libkookie/home-manager-stable/modules/po/pt_BR.po b/infra/libkookie/home-manager-stable/modules/po/pt_BR.po new file mode 100644 index 00000000000..3ca9977ce78 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/po/pt_BR.po @@ -0,0 +1,124 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Home Manager contributors +# This file is distributed under the same license as the Home Manager Modules package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: Home Manager Modules\n" +"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" +"POT-Creation-Date: 2022-03-26 15:08+0100\n" +"PO-Revision-Date: 2022-04-04 11:11+0000\n" +"Last-Translator: Alex Miranda \n" +"Language-Team: Portuguese (Brazil) \n" +"Language: pt_BR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 4.12-dev\n" + +#: modules/files.nix:233 +msgid "Creating home file links in %s" +msgstr "Criando links simbólicos em %s" + +#: modules/files.nix:246 +msgid "Cleaning up orphan links from %s" +msgstr "Limpando links órfãos do directório %s" + +#: modules/files.nix:262 +msgid "Creating profile generation %s" +msgstr "Criando geração %s para o perfil" + +#: modules/files.nix:276 +msgid "No change so reusing latest profile generation %s" +msgstr "Nenhuma mudança, portanto reusando a última geração %s para o perfil" + +#: modules/home-environment.nix:607 +msgid "" +"Oops, Nix failed to install your new Home Manager profile!\n" +"\n" +"Perhaps there is a conflict with a package that was installed using\n" +"\"%s\"? Try running\n" +"\n" +" %s\n" +"\n" +"and if there is a conflicting package you can remove it with\n" +"\n" +" %s\n" +"\n" +"Then try activating your Home Manager configuration again." +msgstr "" +"Opa! O nix não conseguiu instalar seu novo perfil do Home Manager.\n" +"\n" +"Talvez haja um conflito com um pacote que foi instalado usando\n" +"\"%s\"? Tente executar\n" +"\n" +" %s\n" +"\n" +"e se houver algum pacote com conflito, remova-o com\n" +"\n" +" %s\n" +"\n" +"E então tente novamente ativar a sua configuração do Home Manager." + +#: modules/home-environment.nix:639 +msgid "Activating %s" +msgstr "Ativando %s" + +#: modules/lib-bash/activation-init.sh:31 +msgid "Sanity checking oldGenNum and oldGenPath" +msgstr "Revalidando oldGenNum e oldGenPath" + +#: modules/lib-bash/activation-init.sh:34 +msgid "" +"The previous generation number and path are in conflict! These\n" +"must be either both empty or both set but are now set to\n" +"\n" +" '%s' and '%s'\n" +"\n" +"If you don't mind losing previous profile generations then\n" +"the easiest solution is probably to run\n" +"\n" +" rm %s/home-manager*\n" +" rm %s/current-home\n" +"\n" +"and trying home-manager switch again. Good luck!" +msgstr "" +"O número da geração anterior e o caminho não batem! Ambos\n" +"precisam estar ou vazios ou definidos, mas estão definidos como\n" +"\n" +" '%s' e '%s'\n" +"\n" +"Se você não se importa de perder gerações de perfis anteriores, então\n" +"a solução mais rápida é provavelmente rodar\n" +"\n" +" rm %s/home-manager*\n" +" rm %s/current-home\n" +"\n" +"e tentar rodar \"home-manager switch\" de novo. Boa sorte!" + +#: modules/lib-bash/activation-init.sh:51 +msgid "Starting Home Manager activation" +msgstr "Iniciando ativação do Home Manager" + +#: modules/lib-bash/activation-init.sh:55 +msgid "Sanity checking Nix" +msgstr "Revalidando Nix" + +#: modules/lib-bash/activation-init.sh:61 +msgid "This is a dry run" +msgstr "Essa é uma execução de teste" + +#: modules/lib-bash/activation-init.sh:64 +msgid "This is a live run" +msgstr "Essa é uma execução de fato" + +#: modules/lib-bash/activation-init.sh:69 +msgid "Using Nix version: %s" +msgstr "Usando versão do Nix: %s" + +#: modules/lib-bash/activation-init.sh:72 +msgid "Activation variables:" +msgstr "Variáveis durante ativação:" diff --git a/infra/libkookie/home-manager-stable/modules/po/ru.po b/infra/libkookie/home-manager-stable/modules/po/ru.po new file mode 100644 index 00000000000..feba1b94ab8 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/po/ru.po @@ -0,0 +1,152 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Home Manager contributors +# This file is distributed under the same license as the Home Manager Modules package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: Home Manager Modules\n" +"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" +"POT-Creation-Date: 2022-03-26 15:08+0100\n" +"PO-Revision-Date: 2022-03-26 23:57+0000\n" +"Last-Translator: Robert Helgesson \n" +"Language-Team: Russian \n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Generator: Weblate 4.12-dev\n" + +#: modules/files.nix:233 +msgid "Creating home file links in %s" +msgstr "Создаю ссылки в домашней директории %s" + +#: modules/files.nix:246 +msgid "Cleaning up orphan links from %s" +msgstr "Удаляю устаревшие ссылки из %s" + +#: modules/files.nix:262 +msgid "Creating profile generation %s" +msgstr "Создаю профиль в поколении %s" + +#: modules/files.nix:276 +msgid "No change so reusing latest profile generation %s" +msgstr "Изменений нет, переиспользую профиль в последнем поколении %s" + +#: modules/home-environment.nix:607 +msgid "" +"Oops, Nix failed to install your new Home Manager profile!\n" +"\n" +"Perhaps there is a conflict with a package that was installed using\n" +"\"%s\"? Try running\n" +"\n" +" %s\n" +"\n" +"and if there is a conflicting package you can remove it with\n" +"\n" +" %s\n" +"\n" +"Then try activating your Home Manager configuration again." +msgstr "" +"Ой, Nix не смог установить новый профиль Home Manager!\n" +"\n" +"Возможно, возник конфликт с пакетом, ранее установленным\n" +"с помощью \"%s\". Попробуйте выполнить\n" +"\n" +" %s\n" +"\n" +"и если найдётся конфликтующий пакет, удалите его командой\n" +"\n" +" %s\n" +"\n" +"После попробуйте активировать конфигурацию снова." + +#: modules/home-environment.nix:639 +msgid "Activating %s" +msgstr "Активирую %s" + +#: modules/lib-bash/activation-init.sh:31 +msgid "Sanity checking oldGenNum and oldGenPath" +msgstr "Сравниваю oldGenNum и oldGenPath на всякий" + +#: modules/lib-bash/activation-init.sh:34 +msgid "" +"The previous generation number and path are in conflict! These\n" +"must be either both empty or both set but are now set to\n" +"\n" +" '%s' and '%s'\n" +"\n" +"If you don't mind losing previous profile generations then\n" +"the easiest solution is probably to run\n" +"\n" +" rm %s/home-manager*\n" +" rm %s/current-home\n" +"\n" +"and trying home-manager switch again. Good luck!" +msgstr "" +"Номер и путь прошлого поколения конфликтуют! Они должны быть\n" +"одинаково пустыми или заполненными, но сейчас имеют значения\n" +"\n" +" '%s' и '%s'\n" +"\n" +"Если вы не против потерять предыдущие профили, тогда,\n" +"вероятно, простейшим решением будет запустить\n" +"\n" +" rm %s/home-manager*\n" +" rm %s/current-home\n" +"\n" +"и выполнить home-manager switch ещё раз. Удачи!" + +#: modules/lib-bash/activation-init.sh:51 +msgid "Starting Home Manager activation" +msgstr "Начинаю активацию Home Manager" + +#: modules/lib-bash/activation-init.sh:55 +msgid "Sanity checking Nix" +msgstr "Проверяю Nix на всякий случай" + +#: modules/lib-bash/activation-init.sh:61 +msgid "This is a dry run" +msgstr "Это пробный запуск" + +#: modules/lib-bash/activation-init.sh:64 +msgid "This is a live run" +msgstr "Это реальный запуск" + +#: modules/lib-bash/activation-init.sh:69 +msgid "Using Nix version: %s" +msgstr "Использую Nix версии: %s" + +#: modules/lib-bash/activation-init.sh:72 +msgid "Activation variables:" +msgstr "Переменные для активации:" + +#~ msgid "" +#~ "Oops, nix-env failed to install your new Home Manager profile!\n" +#~ "\n" +#~ "Perhaps there is a conflict with a package that was installed using\n" +#~ "\"nix-env -i\"? Try running\n" +#~ "\n" +#~ " nix-env -q\n" +#~ "\n" +#~ "and if there is a conflicting package you can remove it with\n" +#~ "\n" +#~ " nix-env -e {package name}\n" +#~ "\n" +#~ "Then try activating your Home Manager configuration again." +#~ msgstr "" +#~ "Ой, nix-env не смог установить новый профиль Home Manager!\n" +#~ "\n" +#~ "Возможно, возник конфликт с пакетом, ранее установленным\n" +#~ "с помощью \"nix-env -i\". Попробуйте выполнить\n" +#~ "\n" +#~ " nix-env -q\n" +#~ "\n" +#~ "и если найдётся конфликтующий пакет, удалите его командой\n" +#~ "\n" +#~ " nix-env -e {имя пакета}\n" +#~ "\n" +#~ "После попробуйте активировать конфигурацию снова." diff --git a/infra/libkookie/home-manager-stable/modules/po/sv.po b/infra/libkookie/home-manager-stable/modules/po/sv.po new file mode 100644 index 00000000000..09e8a9e99ad --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/po/sv.po @@ -0,0 +1,151 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Home Manager contributors +# This file is distributed under the same license as the Home Manager Modules package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: Home Manager Modules\n" +"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" +"POT-Creation-Date: 2022-03-26 15:08+0100\n" +"PO-Revision-Date: 2022-03-26 23:56+0000\n" +"Last-Translator: Robert Helgesson \n" +"Language-Team: Swedish \n" +"Language: sv\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.12-dev\n" + +#: modules/files.nix:233 +msgid "Creating home file links in %s" +msgstr "Skapar hemfil-länkar i %s" + +#: modules/files.nix:246 +msgid "Cleaning up orphan links from %s" +msgstr "Rensar bort överflödiga länkar från %s" + +#: modules/files.nix:262 +msgid "Creating profile generation %s" +msgstr "Skapar profil för generation %s" + +#: modules/files.nix:276 +msgid "No change so reusing latest profile generation %s" +msgstr "Ingen förändring, återanvänder därför profil-generation %s" + +#: modules/home-environment.nix:607 +msgid "" +"Oops, Nix failed to install your new Home Manager profile!\n" +"\n" +"Perhaps there is a conflict with a package that was installed using\n" +"\"%s\"? Try running\n" +"\n" +" %s\n" +"\n" +"and if there is a conflicting package you can remove it with\n" +"\n" +" %s\n" +"\n" +"Then try activating your Home Manager configuration again." +msgstr "" +"Ajdå, Nix lyckades inte installera din nya Home Manager-profil!\n" +"\n" +"Kanske det finns en konflikt med ett paket som installerades genom\n" +"\"%s\"? Prova att köra\n" +"\n" +" %s\n" +"\n" +"och om det finns ett paket som är i vägen så kan du ta bort det med\n" +"\n" +" %s\n" +"\n" +"Prova sedan att aktivera din Home Manager-konfiguration igen." + +#: modules/home-environment.nix:639 +msgid "Activating %s" +msgstr "Aktiverar %s" + +#: modules/lib-bash/activation-init.sh:31 +msgid "Sanity checking oldGenNum and oldGenPath" +msgstr "Kontrollerar värdena på oldGenNum och oldGenPath" + +#: modules/lib-bash/activation-init.sh:34 +msgid "" +"The previous generation number and path are in conflict! These\n" +"must be either both empty or both set but are now set to\n" +"\n" +" '%s' and '%s'\n" +"\n" +"If you don't mind losing previous profile generations then\n" +"the easiest solution is probably to run\n" +"\n" +" rm %s/home-manager*\n" +" rm %s/current-home\n" +"\n" +"and trying home-manager switch again. Good luck!" +msgstr "" +"Föregående generationsnummer och sökväg motsäger varandra! Dessa måste\n" +"antingen båda vara tomma eller båda vara satta men de har nu värdena\n" +"\n" +" '%s' and '%s'\n" +"\n" +"Om du inte har något emot att förlora tidigare profilgenerationer så\n" +"är den enklaste lösningen antagligen att köra\n" +"\n" +" rm %s/home-manager*\n" +" rm %s/current-home\n" +"\n" +"och prova 'home-manager switch' igen. Lycka till!" + +#: modules/lib-bash/activation-init.sh:51 +msgid "Starting Home Manager activation" +msgstr "Startar Home Manager-aktivering" + +#: modules/lib-bash/activation-init.sh:55 +msgid "Sanity checking Nix" +msgstr "Kontrollerar att Nix funkar" + +#: modules/lib-bash/activation-init.sh:61 +msgid "This is a dry run" +msgstr "Detta är en simulerad körning" + +#: modules/lib-bash/activation-init.sh:64 +msgid "This is a live run" +msgstr "Detta är en verklig körning" + +#: modules/lib-bash/activation-init.sh:69 +msgid "Using Nix version: %s" +msgstr "Använder Nix-version: %s" + +#: modules/lib-bash/activation-init.sh:72 +msgid "Activation variables:" +msgstr "Aktiveringsvariabler:" + +#~ msgid "" +#~ "Oops, nix-env failed to install your new Home Manager profile!\n" +#~ "\n" +#~ "Perhaps there is a conflict with a package that was installed using\n" +#~ "\"nix-env -i\"? Try running\n" +#~ "\n" +#~ " nix-env -q\n" +#~ "\n" +#~ "and if there is a conflicting package you can remove it with\n" +#~ "\n" +#~ " nix-env -e {package name}\n" +#~ "\n" +#~ "Then try activating your Home Manager configuration again." +#~ msgstr "" +#~ "Ajdå, nix-env lyckades inte installera din nya Home Manager-profil!\n" +#~ "\n" +#~ "Kanske det finns en konflikt med ett paket som installerades genom\n" +#~ "\"nix-env -i\"? Prova att köra\n" +#~ "\n" +#~ " nix-env -q\n" +#~ "\n" +#~ "och om det finns ett paket som är i vägen så kan du ta bort det med\n" +#~ "\n" +#~ " nix-env -e {paketnamn}\n" +#~ "\n" +#~ "Prova sedan att aktivera din Home Manager-konfiguration igen." diff --git a/infra/libkookie/home-manager-stable/modules/po/tr.po b/infra/libkookie/home-manager-stable/modules/po/tr.po new file mode 100644 index 00000000000..5b7dad73962 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/po/tr.po @@ -0,0 +1,125 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Home Manager contributors +# This file is distributed under the same license as the Home Manager Modules package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: Home Manager Modules\n" +"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" +"POT-Creation-Date: 2022-03-26 15:08+0100\n" +"PO-Revision-Date: 2022-03-26 23:57+0000\n" +"Last-Translator: Oğuz Ersen \n" +"Language-Team: Turkish \n" +"Language: tr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.12-dev\n" + +#: modules/files.nix:233 +msgid "Creating home file links in %s" +msgstr "%s konumunda ev dosya bağlantıları oluşturuluyor" + +#: modules/files.nix:246 +msgid "Cleaning up orphan links from %s" +msgstr "Geçersiz bağlantılar temizleniyor %s" + +#: modules/files.nix:262 +msgid "Creating profile generation %s" +msgstr "%s profil inşası oluşturuluyor" + +#: modules/files.nix:276 +msgid "No change so reusing latest profile generation %s" +msgstr "Değişiklik yok, bu nedenle en son profil inşası %s yeniden kullanılıyor" + +#: modules/home-environment.nix:607 +msgid "" +"Oops, Nix failed to install your new Home Manager profile!\n" +"\n" +"Perhaps there is a conflict with a package that was installed using\n" +"\"%s\"? Try running\n" +"\n" +" %s\n" +"\n" +"and if there is a conflicting package you can remove it with\n" +"\n" +" %s\n" +"\n" +"Then try activating your Home Manager configuration again." +msgstr "" +"Eyvah, Nix yeni Home Manager profilinizi kuramadı!\n" +"\n" +"Belki de \"%s\" kullanan kurulan paketlerin biriyle bir çakışma vardır?\n" +"\n" +" %s\n" +"\n" +"komutunu çalıştırın ve eğer çakışan bir paket varsa onu\n" +"\n" +" %s\n" +"\n" +"ile kaldırabilirsiniz. Sonra Home Manager yapılandırmanızı yeniden\n" +"etkinleştirmeyi deneyin." + +#: modules/home-environment.nix:639 +msgid "Activating %s" +msgstr "%s etkinleştiriliyor" + +#: modules/lib-bash/activation-init.sh:31 +msgid "Sanity checking oldGenNum and oldGenPath" +msgstr "oldGenNum ve oldGenPath denetleniyor" + +#: modules/lib-bash/activation-init.sh:34 +msgid "" +"The previous generation number and path are in conflict! These\n" +"must be either both empty or both set but are now set to\n" +"\n" +" '%s' and '%s'\n" +"\n" +"If you don't mind losing previous profile generations then\n" +"the easiest solution is probably to run\n" +"\n" +" rm %s/home-manager*\n" +" rm %s/current-home\n" +"\n" +"and trying home-manager switch again. Good luck!" +msgstr "" +"Önceki inşa numarası ve yolu çakışıyor! Bunların ikisi de boş olmalı\n" +"veya ayarlanmalı ama şu anda\n" +"\n" +" '%s' ve '%s'\n" +"\n" +"olarak ayarlandı. Önceki profil inşalarını kaybetmeyi önemsemiyorsanız\n" +"en kolay çözüm muhtemelen\n" +"\n" +" rm %s/home-manager*\n" +" rm %s/current-home\n" +"\n" +"komutlarını çalıştırmak ve tekrar home-manager switch denemektir. İyi " +"şanslar!" + +#: modules/lib-bash/activation-init.sh:51 +msgid "Starting Home Manager activation" +msgstr "Home Manager etkinleştirmesi başlatılıyor" + +#: modules/lib-bash/activation-init.sh:55 +msgid "Sanity checking Nix" +msgstr "Nix denetleniyor" + +#: modules/lib-bash/activation-init.sh:61 +msgid "This is a dry run" +msgstr "Bu bir deneme çalıştırmasıdır" + +#: modules/lib-bash/activation-init.sh:64 +msgid "This is a live run" +msgstr "Bu bir gerçek çalıştırmadır" + +#: modules/lib-bash/activation-init.sh:69 +msgid "Using Nix version: %s" +msgstr "Kullanılan Nix sürümü: %s" + +#: modules/lib-bash/activation-init.sh:72 +msgid "Activation variables:" +msgstr "Etkinleştirme değişkenleri:" diff --git a/infra/libkookie/home-manager-stable/modules/po/zh_Hans.po b/infra/libkookie/home-manager-stable/modules/po/zh_Hans.po new file mode 100644 index 00000000000..ca62aa87498 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/po/zh_Hans.po @@ -0,0 +1,112 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Home Manager contributors +# This file is distributed under the same license as the Home Manager Modules package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: Home Manager Modules\n" +"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" +"POT-Creation-Date: 2022-03-26 15:08+0100\n" +"PO-Revision-Date: 2022-05-16 13:18+0000\n" +"Last-Translator: Yubo-Cao \n" +"Language-Team: Chinese (Simplified) \n" +"Language: zh_Hans\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 4.13-dev\n" + +#: modules/files.nix:233 +msgid "Creating home file links in %s" +msgstr "正在 %s 中创建家目录文件链接" + +#: modules/files.nix:246 +msgid "Cleaning up orphan links from %s" +msgstr "正在从 %s 清理孤立链接" + +#: modules/files.nix:262 +msgid "Creating profile generation %s" +msgstr "正在创建配置文件世代 %s" + +#: modules/files.nix:276 +msgid "No change so reusing latest profile generation %s" +msgstr "未发生变化,正在重新使用最近一次的配置文件世代 %s" + +#: modules/home-environment.nix:607 +msgid "" +"Oops, Nix failed to install your new Home Manager profile!\n" +"\n" +"Perhaps there is a conflict with a package that was installed using\n" +"\"%s\"? Try running\n" +"\n" +" %s\n" +"\n" +"and if there is a conflicting package you can remove it with\n" +"\n" +" %s\n" +"\n" +"Then try activating your Home Manager configuration again." +msgstr "" +"糟糕,Nix 未能安装您的新 Home Manager 配置文件!\n" +"\n" +"也许这里和使用 \"%s\" 安装的包有冲突?\n" +"尝试运行\n" +"\n" +" %s\n" +"\n" +"如果有冲突的包,你可以用\n" +"\n" +" %s\n" +"\n" +"来移除。然后尝试再次激活您的 Home Manager 配置。" + +#: modules/home-environment.nix:639 +msgid "Activating %s" +msgstr "正在激活 %s" + +#: modules/lib-bash/activation-init.sh:31 +msgid "Sanity checking oldGenNum and oldGenPath" +msgstr "正在进行 oldGenNum 和 oldGenPath 的完整性检查" + +#: modules/lib-bash/activation-init.sh:34 +msgid "" +"The previous generation number and path are in conflict! These\n" +"must be either both empty or both set but are now set to\n" +"\n" +" '%s' and '%s'\n" +"\n" +"If you don't mind losing previous profile generations then\n" +"the easiest solution is probably to run\n" +"\n" +" rm %s/home-manager*\n" +" rm %s/current-home\n" +"\n" +"and trying home-manager switch again. Good luck!" +msgstr "" + +#: modules/lib-bash/activation-init.sh:51 +msgid "Starting Home Manager activation" +msgstr "正在启动 Home Manager 初始化程序" + +#: modules/lib-bash/activation-init.sh:55 +msgid "Sanity checking Nix" +msgstr "正在进行 Nix 完整性检查" + +#: modules/lib-bash/activation-init.sh:61 +msgid "This is a dry run" +msgstr "这是试运行" + +#: modules/lib-bash/activation-init.sh:64 +msgid "This is a live run" +msgstr "这是在实际运行" + +#: modules/lib-bash/activation-init.sh:69 +msgid "Using Nix version: %s" +msgstr "正在使用的 Nix 版本: %s" + +#: modules/lib-bash/activation-init.sh:72 +msgid "Activation variables:" +msgstr "激活的变量:" diff --git a/infra/libkookie/home-manager-stable/modules/po/zh_Hant.po b/infra/libkookie/home-manager-stable/modules/po/zh_Hant.po new file mode 100644 index 00000000000..06f379e0987 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/po/zh_Hant.po @@ -0,0 +1,100 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Home Manager contributors +# This file is distributed under the same license as the Home Manager Modules package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: Home Manager Modules\n" +"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n" +"POT-Creation-Date: 2022-03-26 15:08+0100\n" +"PO-Revision-Date: 2021-12-29 08:48+0000\n" +"Last-Translator: WhiredPlanck \n" +"Language-Team: Chinese (Traditional) \n" +"Language: zh_Hant\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 4.10.1\n" + +#: modules/files.nix:233 +msgid "Creating home file links in %s" +msgstr "正在 %s 中建立家目錄檔案連結" + +#: modules/files.nix:246 +msgid "Cleaning up orphan links from %s" +msgstr "正在從 %s 清理孤立連結" + +#: modules/files.nix:262 +msgid "Creating profile generation %s" +msgstr "正在建立配置檔案世代 %s" + +#: modules/files.nix:276 +msgid "No change so reusing latest profile generation %s" +msgstr "未發生變化,正在重新使用最近一次的配置檔案世代 %s" + +#: modules/home-environment.nix:607 +msgid "" +"Oops, Nix failed to install your new Home Manager profile!\n" +"\n" +"Perhaps there is a conflict with a package that was installed using\n" +"\"%s\"? Try running\n" +"\n" +" %s\n" +"\n" +"and if there is a conflicting package you can remove it with\n" +"\n" +" %s\n" +"\n" +"Then try activating your Home Manager configuration again." +msgstr "" + +#: modules/home-environment.nix:639 +msgid "Activating %s" +msgstr "正在啟用 %s" + +#: modules/lib-bash/activation-init.sh:31 +msgid "Sanity checking oldGenNum and oldGenPath" +msgstr "" + +#: modules/lib-bash/activation-init.sh:34 +msgid "" +"The previous generation number and path are in conflict! These\n" +"must be either both empty or both set but are now set to\n" +"\n" +" '%s' and '%s'\n" +"\n" +"If you don't mind losing previous profile generations then\n" +"the easiest solution is probably to run\n" +"\n" +" rm %s/home-manager*\n" +" rm %s/current-home\n" +"\n" +"and trying home-manager switch again. Good luck!" +msgstr "" + +#: modules/lib-bash/activation-init.sh:51 +msgid "Starting Home Manager activation" +msgstr "正在啟動 Home Manager 初始化程式" + +#: modules/lib-bash/activation-init.sh:55 +msgid "Sanity checking Nix" +msgstr "" + +#: modules/lib-bash/activation-init.sh:61 +msgid "This is a dry run" +msgstr "" + +#: modules/lib-bash/activation-init.sh:64 +msgid "This is a live run" +msgstr "" + +#: modules/lib-bash/activation-init.sh:69 +msgid "Using Nix version: %s" +msgstr "" + +#: modules/lib-bash/activation-init.sh:72 +msgid "Activation variables:" +msgstr "" diff --git a/infra/libkookie/home-manager-stable/modules/programs/abook.nix b/infra/libkookie/home-manager-stable/modules/programs/abook.nix new file mode 100644 index 00000000000..bdbf7e87d23 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/abook.nix @@ -0,0 +1,44 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.abook; + +in { + options.programs.abook = { + enable = mkEnableOption "Abook"; + + extraConfig = mkOption { + type = types.lines; + default = ""; + example = '' + field pager = Pager + view CONTACT = name, email + set autosave=true + ''; + description = '' + Extra lines added to $HOME/.config/abook/abookrc. + Available configuration options are described in the abook repository: + . + ''; + }; + }; + + config = mkIf cfg.enable { + assertions = + [ (hm.assertions.assertPlatform "programs.abook" pkgs platforms.linux) ]; + + home.packages = [ pkgs.abook ]; + + xdg.configFile."abook/abookrc" = mkIf (cfg.extraConfig != "") { + text = '' + # Generated by Home Manager. + # See http://abook.sourceforge.net/ + + ${cfg.extraConfig} + ''; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/afew.nix b/infra/libkookie/home-manager-stable/modules/programs/afew.nix new file mode 100644 index 00000000000..6c480f03be3 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/afew.nix @@ -0,0 +1,50 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.afew; + +in { + options.programs.afew = { + enable = mkEnableOption "the afew initial tagging script for Notmuch"; + + extraConfig = mkOption { + type = types.lines; + default = '' + [SpamFilter] + [KillThreadsFilter] + [ListMailsFilter] + [ArchiveSentMailsFilter] + [InboxFilter] + ''; + example = '' + [SpamFilter] + + [Filter.0] + query = from:pointyheaded@boss.com + tags = -new;+boss + message = Message from above + + [InboxFilter] + ''; + description = '' + Extra lines added to afew configuration file. Available + configuration options are described in the afew manual: + . + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ pkgs.afew ]; + + xdg.configFile."afew/config".text = '' + # Generated by Home Manager. + # See https://afew.readthedocs.io/ + + ${cfg.extraConfig} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/alacritty.nix b/infra/libkookie/home-manager-stable/modules/programs/alacritty.nix new file mode 100644 index 00000000000..eaf304144d4 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/alacritty.nix @@ -0,0 +1,63 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.programs.alacritty; + yamlFormat = pkgs.formats.yaml { }; +in { + options = { + programs.alacritty = { + enable = mkEnableOption "Alacritty"; + + package = mkOption { + type = types.package; + default = pkgs.alacritty; + defaultText = literalExpression "pkgs.alacritty"; + description = "The Alacritty package to install."; + }; + + settings = mkOption { + type = yamlFormat.type; + default = { }; + example = literalExpression '' + { + window.dimensions = { + lines = 3; + columns = 200; + }; + key_bindings = [ + { + key = "K"; + mods = "Control"; + chars = "\\x0c"; + } + ]; + } + ''; + description = '' + Configuration written to + $XDG_CONFIG_HOME/alacritty/alacritty.yml. See + + for the default configuration. + ''; + }; + }; + }; + + config = mkMerge [ + (mkIf cfg.enable { + home.packages = [ cfg.package ]; + + xdg.configFile."alacritty/alacritty.yml" = mkIf (cfg.settings != { }) { + # TODO: Replace by the generate function but need to figure out how to + # handle the escaping first. + # + # source = yamlFormat.generate "alacritty.yml" cfg.settings; + + text = + replaceStrings [ "\\\\" ] [ "\\" ] (builtins.toJSON cfg.settings); + }; + }) + ]; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/alot-accounts.nix b/infra/libkookie/home-manager-stable/modules/programs/alot-accounts.nix new file mode 100644 index 00000000000..9dee3c83adc --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/alot-accounts.nix @@ -0,0 +1,58 @@ +pkgs: +{ config, lib, ... }: + +with lib; + +{ + options.alot = { + sendMailCommand = mkOption { + type = types.nullOr types.str; + description = '' + Command to send a mail. If msmtp is enabled for the account, + then this is set to + msmtpq --read-envelope-from --read-recipients. + ''; + }; + + contactCompletion = mkOption { + type = types.attrsOf types.str; + default = { + type = "shellcommand"; + command = + "'${pkgs.notmuch}/bin/notmuch address --format=json --output=recipients date:6M..'"; + regexp = "'\\[?{" + '' + "name": "(?P.*)", "address": "(?P.+)", "name-addr": ".*"'' + + "}[,\\]]?'"; + shellcommand_external_filtering = "False"; + }; + example = literalExpression '' + { + type = "shellcommand"; + command = "abook --mutt-query"; + regexp = "'^(?P[^@]+@[^\t]+)\t+(?P[^\t]+)'"; + ignorecase = "True"; + } + ''; + description = '' + Contact completion configuration as expected per alot. + See alot's wiki for + explanation about possible values. + ''; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Extra settings to add to this Alot account configuration. + ''; + }; + }; + + config = mkIf config.notmuch.enable { + alot.sendMailCommand = mkOptionDefault (if config.msmtp.enable then + "msmtpq --read-envelope-from --read-recipients" + else + null); + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/alot.nix b/infra/libkookie/home-manager-stable/modules/programs/alot.nix new file mode 100644 index 00000000000..0cc20ec6e0f --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/alot.nix @@ -0,0 +1,240 @@ +# alot config loader is sensitive to leading space ! +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.alot; + + enabledAccounts = + filter (a: a.notmuch.enable) (attrValues config.accounts.email.accounts); + + # sorted: primary first + alotAccounts = sort (a: b: !(a.primary -> b.primary)) enabledAccounts; + + boolStr = v: if v then "True" else "False"; + + mkKeyValue = key: value: + let value' = if isBool value then boolStr value else toString value; + in "${key} = ${value'}"; + + mk2ndLevelSectionName = name: "[" + name + "]"; + + tagSubmodule = types.submodule { + options = { + translated = mkOption { + type = types.nullOr types.str; + description = '' + Fixed string representation for this tag. The tag can be + hidden from view, if the key translated is set to + "", the empty string. + ''; + }; + + translation = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + A pair of strings that define a regular substitution to + compute the string representation on the fly using + re.sub. + ''; + }; + + normal = mkOption { + type = types.nullOr types.str; + default = null; + example = "'','', 'white','light red', 'white','#d66'"; + description = '' + How to display the tag when unfocused. + See . + ''; + }; + + focus = mkOption { + type = types.nullOr types.str; + default = null; + description = "How to display the tag when focused."; + }; + }; + }; + + accountStr = account: + with account; + concatStringsSep "\n" ([ "[[${name}]]" ] + ++ mapAttrsToList (n: v: n + "=" + v) ({ + address = address; + realname = realName; + sendmail_command = + optionalString (alot.sendMailCommand != null) alot.sendMailCommand; + sent_box = "maildir" + "://" + maildir.absPath + "/" + folders.sent; + draft_box = "maildir" + "://" + maildir.absPath + "/" + folders.drafts; + } // optionalAttrs (aliases != [ ]) { + aliases = concatStringsSep "," aliases; + } // optionalAttrs (gpg != null) { + gpg_key = gpg.key; + encrypt_by_default = if gpg.encryptByDefault then "all" else "none"; + sign_by_default = boolStr gpg.signByDefault; + } // optionalAttrs (signature.showSignature != "none") { + signature = pkgs.writeText "signature.txt" signature.text; + signature_as_attachment = boolStr (signature.showSignature == "attach"); + }) ++ [ alot.extraConfig ] ++ [ "[[[abook]]]" ] + ++ mapAttrsToList (n: v: n + "=" + v) alot.contactCompletion); + + configFile = let + bindingsToStr = attrSet: + concatStringsSep "\n" (mapAttrsToList (n: v: "${n} = ${v}") attrSet); + in '' + # Generated by Home Manager. + # See http://alot.readthedocs.io/en/latest/configuration/config_options.html + + ${generators.toKeyValue { inherit mkKeyValue; } cfg.settings} + ${cfg.extraConfig} + [tags] + '' + (let + submoduleToAttrs = m: + filterAttrs (name: v: name != "_module" && v != null) m; + in generators.toINI { mkSectionName = mk2ndLevelSectionName; } + (mapAttrs (name: x: submoduleToAttrs x) cfg.tags)) + '' + [bindings] + ${bindingsToStr cfg.bindings.global} + + [[bufferlist]] + ${bindingsToStr cfg.bindings.bufferlist} + [[search]] + ${bindingsToStr cfg.bindings.search} + [[envelope]] + ${bindingsToStr cfg.bindings.envelope} + [[taglist]] + ${bindingsToStr cfg.bindings.taglist} + [[thread]] + ${bindingsToStr cfg.bindings.thread} + + [accounts] + + ${concatStringsSep "\n\n" (map accountStr alotAccounts)} + ''; + +in { + options = { + programs.alot = { + enable = mkOption { + type = types.bool; + default = false; + example = true; + description = '' + Whether to enable the Alot mail user agent. Alot uses the + Notmuch email system and will therefore be automatically + enabled for each email account that is managed by Notmuch. + ''; + }; + + hooks = mkOption { + type = types.lines; + default = ""; + description = '' + Content of the hooks file. + ''; + }; + + bindings = mkOption { + type = types.submodule { + options = { + global = mkOption { + type = types.attrsOf types.str; + default = { }; + description = "Global keybindings."; + }; + + bufferlist = mkOption { + type = types.attrsOf types.str; + default = { }; + description = "Bufferlist mode keybindings."; + }; + + search = mkOption { + type = types.attrsOf types.str; + default = { }; + description = "Search mode keybindings."; + }; + + envelope = mkOption { + type = types.attrsOf types.str; + default = { }; + description = "Envelope mode keybindings."; + }; + + taglist = mkOption { + type = types.attrsOf types.str; + default = { }; + description = "Taglist mode keybindings."; + }; + + thread = mkOption { + type = types.attrsOf types.str; + default = { }; + description = "Thread mode keybindings."; + }; + }; + }; + default = { }; + description = '' + Keybindings. + ''; + }; + + tags = mkOption { + type = types.attrsOf tagSubmodule; + default = { }; + description = "How to display the tags."; + }; + + settings = mkOption { + type = with types; + let primitive = either (either (either str int) bool) float; + in attrsOf primitive; + default = { + initial_command = "search tag:inbox AND NOT tag:killed"; + auto_remove_unread = true; + handle_mouse = true; + prefer_plaintext = true; + }; + example = literalExpression '' + { + auto_remove_unread = true; + ask_subject = false; + thread_indent_replies = 2; + } + ''; + description = '' + Configuration options added to alot configuration file. + ''; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Extra lines added to alot configuration file. + ''; + }; + }; + + accounts.email.accounts = mkOption { + type = with types; attrsOf (submodule (import ./alot-accounts.nix pkgs)); + }; + }; + + config = mkIf cfg.enable { + home.packages = [ pkgs.alot ]; + + xdg.configFile."alot/config".text = configFile; + + xdg.configFile."alot/hooks.py" = mkIf (cfg.hooks != "") { + text = '' + # Generated by Home Manager. + '' + cfg.hooks; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/aria2.nix b/infra/libkookie/home-manager-stable/modules/programs/aria2.nix new file mode 100644 index 00000000000..25727cead51 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/aria2.nix @@ -0,0 +1,61 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.programs.aria2; + + formatLine = n: v: + let + formatValue = v: + if builtins.isBool v then + (if v then "true" else "false") + else + toString v; + in "${n}=${formatValue v}"; +in { + meta.maintainers = [ hm.maintainers.justinlovinger ]; + + options.programs.aria2 = { + enable = mkEnableOption "aria2"; + + settings = mkOption { + type = with types; attrsOf (oneOf [ bool float int str ]); + default = { }; + description = '' + Options to add to aria2.conf file. + See + + aria2c + 1 + + for options. + ''; + example = literalExpression '' + { + listen-port = 60000; + dht-listen-port = 60000; + seed-ratio = 1.0; + max-upload-limit = "50K"; + ftp-pasv = true; + } + ''; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Extra lines added to aria2.conf file. + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ pkgs.aria2 ]; + + xdg.configFile."aria2/aria2.conf".text = concatStringsSep "\n" ([ ] + ++ mapAttrsToList formatLine cfg.settings + ++ optional (cfg.extraConfig != "") cfg.extraConfig); + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/astroid-accounts.nix b/infra/libkookie/home-manager-stable/modules/programs/astroid-accounts.nix new file mode 100644 index 00000000000..fb803867efb --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/astroid-accounts.nix @@ -0,0 +1,32 @@ +{ config, lib, ... }: + +with lib; + +{ + options.astroid = { + enable = mkEnableOption "Astroid"; + + sendMailCommand = mkOption { + type = types.str; + description = '' + Command to send a mail. If msmtp is enabled for the account, + then this is set to + msmtpq --read-envelope-from --read-recipients. + ''; + }; + + extraConfig = mkOption { + type = types.attrsOf types.anything; + default = { }; + example = { select_query = ""; }; + description = '' + Extra settings to add to this astroid account configuration. + ''; + }; + }; + + config = mkIf config.notmuch.enable { + astroid.sendMailCommand = mkIf config.msmtp.enable + (mkOptionDefault "msmtpq --read-envelope-from --read-recipients"); + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/astroid-config-template.json b/infra/libkookie/home-manager-stable/modules/programs/astroid-config-template.json new file mode 100644 index 00000000000..87e3f764f9c --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/astroid-config-template.json @@ -0,0 +1,113 @@ +{ + "astroid": { + "config": { + "version": "11" + }, + "debug": { + "dryrun_sending": "false" + }, + "hints": { + "level": "0" + }, + "log": { + "syslog": "false", + "stdout": "true", + "level": "info" + } + }, + "startup": { + "queries": { + "inbox": "tag:inbox" + } + }, + "terminal": { + "height": "10", + "font_description": "default" + }, + "thread_index": { + "page_jump_rows": "6", + "sort_order": "newest", + "cell": { + "font_description": "default", + "line_spacing": "2", + "date_length": "10", + "message_count_length": "4", + "authors_length": "20", + "subject_color": "#807d74", + "subject_color_selected": "#000000", + "background_color_selected": "", + "background_color_marked": "#fff584", + "background_color_marked_selected": "#bcb559", + "tags_length": "80", + "tags_upper_color": "#e5e5e5", + "tags_lower_color": "#333333", + "tags_alpha": "0.5", + "hidden_tags": "attachment,flagged,unread" + } + }, + "general": { + "time": { + "clock_format": "local", + "same_year": "%b %-e", + "diff_year": "%x" + } + }, + "editor": { + "charset": "utf-8", + "save_draft_on_force_quit": "true", + "attachment_words": "attach", + "attachment_directory": "~", + "markdown_processor": "marked" + }, + "mail": { + "reply": { + "quote_line": "Excerpts from %1's message of %2:", + "mailinglist_reply_to_sender": "true" + }, + "forward": { + "quote_line": "Forwarding %1's message of %2:", + "disposition": "inline" + }, + "sent_tags": "sent", + "message_id_fqdn": "", + "message_id_user": "", + "user_agent": "default", + "send_delay": "2", + "close_on_success": "false", + "format_flowed": "false" + }, + "poll": { + "interval": "60", + "always_full_refresh": "false" + }, + "attachment": { + "external_open_cmd": "xdg-open" + }, + "thread_view": { + "open_html_part_external": "false", + "preferred_type": "plain", + "preferred_html_only": "false", + "allow_remote_when_encrypted": "false", + "open_external_link": "xdg-open", + "default_save_directory": "~", + "indent_messages": "false", + "gravatar": { + "enable": "true" + }, + "mark_unread_delay": "0.5", + "expand_flagged": "true" + }, + "crypto": { + "gpg": { + "path": "gpg2", + "always_trust": "true", + "enabled": "true" + } + }, + "saved_searches": { + "show_on_startup": "false", + "save_history": "true", + "history_lines_to_show": "15", + "history_lines": "1000" + } +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/astroid.nix b/infra/libkookie/home-manager-stable/modules/programs/astroid.nix new file mode 100644 index 00000000000..4e79ea4d3cf --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/astroid.nix @@ -0,0 +1,128 @@ +{ config, lib, pkgs, ... }: + +with lib; +with builtins; + +let + + cfg = config.programs.astroid; + + jsonFormat = pkgs.formats.json { }; + + astroidAccounts = + filterAttrs (n: v: v.astroid.enable) config.accounts.email.accounts; + + boolOpt = b: if b then "true" else "false"; + + accountAttr = account: + with account; + { + email = address; + name = realName; + sendmail = astroid.sendMailCommand; + additional_sent_tags = ""; + default = boolOpt primary; + save_drafts_to = "${maildir.absPath}/${folders.drafts}/cur/"; + save_sent = "true"; + save_sent_to = "${maildir.absPath}/${folders.sent}/cur/"; + select_query = ""; + } // optionalAttrs (signature.showSignature != "none") { + signature_attach = boolOpt (signature.showSignature == "attach"); + signature_default_on = boolOpt (signature.showSignature != "none"); + signature_file = pkgs.writeText "signature.txt" signature.text; + signature_file_markdown = "false"; + signature_separate = "true"; # prepends '--\n' to the signature + } // optionalAttrs (gpg != null) { + always_gpg_sign = boolOpt gpg.signByDefault; + gpgkey = gpg.key; + } // astroid.extraConfig; + + # See https://github.com/astroidmail/astroid/wiki/Configuration-Reference + finalConfig = let + template = fromJSON (readFile ./astroid-config-template.json); + astroidConfig = foldl' recursiveUpdate template [ + { + astroid.notmuch_config = + "${config.xdg.configHome}/notmuch/default/config"; + accounts = mapAttrs (n: accountAttr) astroidAccounts; + crypto.gpg.path = "${pkgs.gnupg}/bin/gpg"; + } + cfg.extraConfig + cfg.externalEditor + ]; + in astroidConfig; + +in { + options = { + programs.astroid = { + enable = mkEnableOption "Astroid"; + + pollScript = mkOption { + type = types.str; + default = ""; + example = "mbsync gmail"; + description = '' + Script to run to fetch/update mails. + ''; + }; + + externalEditor = mkOption { + type = types.nullOr types.str; + default = null; + # Converts it into JSON that can be merged into the configuration. + apply = cmd: + optionalAttrs (cmd != null) { + editor = { + "external_editor" = "true"; + "cmd" = cmd; + }; + }; + example = + "nvim-qt -- -c 'set ft=mail' '+set fileencoding=utf-8' '+set ff=unix' '+set enc=utf-8' '+set fo+=w' %1"; + description = '' + You can use %1, %2, and + %3 to refer respectively to: + + file name + server name + socket ID + + See . + ''; + }; + + extraConfig = mkOption { + type = jsonFormat.type; + default = { }; + example = literalExpression '' + { + poll.interval = 0; + } + ''; + description = '' + JSON config that will override the default Astroid configuration. + ''; + }; + }; + + accounts.email.accounts = mkOption { + type = with types; attrsOf (submodule (import ./astroid-accounts.nix)); + }; + }; + + config = mkIf cfg.enable { + home.packages = [ pkgs.astroid ]; + + xdg.configFile."astroid/config".source = + jsonFormat.generate "astroid-config" finalConfig; + + xdg.configFile."astroid/poll.sh" = { + executable = true; + text = '' + # Generated by Home Manager + + ${cfg.pollScript} + ''; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/atuin.nix b/infra/libkookie/home-manager-stable/modules/programs/atuin.nix new file mode 100644 index 00000000000..9a38f542184 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/atuin.nix @@ -0,0 +1,108 @@ +{ config, pkgs, lib, ... }: + +with lib; + +let + + cfg = config.programs.atuin; + + tomlFormat = pkgs.formats.toml { }; + +in { + meta.maintainers = [ maintainers.hawkw ]; + + options.programs.atuin = { + enable = mkEnableOption "atuin"; + + package = mkOption { + type = types.package; + default = pkgs.atuin; + defaultText = literalExpression "pkgs.atuin"; + description = "The package to use for atuin."; + }; + + enableBashIntegration = mkOption { + type = types.bool; + default = true; + description = '' + Whether to enable Atuin's Bash integration. This will bind + ctrl-r to open the Atuin history. + ''; + }; + + enableZshIntegration = mkEnableOption "Zsh integration" // { + default = true; + description = '' + Whether to enable Atuin's Zsh integration. + + If enabled, this will bind ctrl-r and the up-arrow + key to open the Atuin history. + ''; + }; + + enableFishIntegration = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable Atuin's Fish integration. + + If enabled, this will bind the up-arrow key to open the Atuin history. + ''; + }; + + settings = mkOption { + type = with types; + let + prim = oneOf [ bool int str ]; + primOrPrimAttrs = either prim (attrsOf prim); + entry = either prim (listOf primOrPrimAttrs); + entryOrAttrsOf = t: either entry (attrsOf t); + entries = entryOrAttrsOf (entryOrAttrsOf entry); + in attrsOf entries // { description = "Atuin configuration"; }; + default = { }; + example = literalExpression '' + { + auto_sync = true; + sync_frequency = "5m"; + sync_address = "https://api.atuin.sh"; + search_mode = "prefix"; + } + ''; + description = '' + Configuration written to + $XDG_CONFIG_HOME/atuin/config.toml. + + See for the full list + of options. + ''; + }; + }; + + config = mkIf cfg.enable { + + # Always add the configured `atuin` package. + home.packages = [ cfg.package ]; + + # If there are user-provided settings, generate the config file. + xdg.configFile."atuin/config.toml" = mkIf (cfg.settings != { }) { + source = tomlFormat.generate "atuin-config" cfg.settings; + }; + + programs.bash.initExtra = mkIf cfg.enableBashIntegration '' + if [[ :$SHELLOPTS: =~ :(vi|emacs): ]]; then + source "${pkgs.bash-preexec}/share/bash/bash-preexec.sh" + eval "$(${cfg.package}/bin/atuin init bash)" + fi + ''; + + programs.zsh.initExtra = mkIf cfg.enableZshIntegration '' + if [[ $options[zle] = on ]]; then + eval "$(${cfg.package}/bin/atuin init zsh)" + fi + ''; + + programs.fish.interactiveShellInit = mkIf cfg.enableFishIntegration '' + ${cfg.package}/bin/atuin init fish | source + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/autojump.nix b/infra/libkookie/home-manager-stable/modules/programs/autojump.nix new file mode 100644 index 00000000000..e8bf6b4375c --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/autojump.nix @@ -0,0 +1,56 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.autojump; + package = pkgs.autojump; + +in { + meta.maintainers = [ maintainers.evanjs ]; + + options.programs.autojump = { + enable = mkEnableOption "autojump"; + + enableBashIntegration = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable Bash integration. + ''; + }; + + enableZshIntegration = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable Zsh integration. + ''; + }; + + enableFishIntegration = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable Fish integration. + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ package ]; + + programs.bash.initExtra = mkIf cfg.enableBashIntegration (mkBefore '' + . ${package}/share/autojump/autojump.bash + ''); + + programs.zsh.initExtra = mkIf cfg.enableZshIntegration '' + . ${package}/share/autojump/autojump.zsh + ''; + + programs.fish.interactiveShellInit = mkIf cfg.enableFishIntegration '' + . ${package}/share/autojump/autojump.fish + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/autorandr.nix b/infra/libkookie/home-manager-stable/modules/programs/autorandr.nix new file mode 100644 index 00000000000..3eeedfc2b1f --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/autorandr.nix @@ -0,0 +1,372 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.autorandr; + + matrixOf = n: m: elemType: + mkOptionType rec { + name = "matrixOf"; + description = + "${toString n}×${toString m} matrix of ${elemType.description}s"; + check = xss: + let listOfSize = l: xs: isList xs && length xs == l; + in listOfSize n xss + && all (xs: listOfSize m xs && all elemType.check xs) xss; + merge = mergeOneOption; + getSubOptions = prefix: elemType.getSubOptions (prefix ++ [ "*" "*" ]); + getSubModules = elemType.getSubModules; + substSubModules = mod: matrixOf n m (elemType.substSubModules mod); + functor = (defaultFunctor name) // { wrapped = elemType; }; + }; + + profileModule = types.submodule { + options = { + fingerprint = mkOption { + type = types.attrsOf types.str; + description = '' + Output name to EDID mapping. + Use autorandr --fingerprint to get current setup values. + ''; + default = { }; + }; + + config = mkOption { + type = types.attrsOf configModule; + description = "Per output profile configuration."; + default = { }; + }; + + hooks = mkOption { + type = profileHooksModule; + description = "Profile hook scripts."; + default = { }; + }; + }; + }; + + configModule = types.submodule { + options = { + enable = mkOption { + type = types.bool; + description = "Whether to enable the output."; + default = true; + }; + + crtc = mkOption { + type = types.nullOr types.ints.unsigned; + description = "Output video display controller."; + default = null; + example = 0; + }; + + primary = mkOption { + type = types.bool; + description = "Whether output should be marked as primary"; + default = false; + }; + + position = mkOption { + type = types.str; + description = "Output position"; + default = ""; + example = "5760x0"; + }; + + mode = mkOption { + type = types.str; + description = "Output resolution."; + default = ""; + example = "3840x2160"; + }; + + rate = mkOption { + type = types.str; + description = "Output framerate."; + default = ""; + example = "60.00"; + }; + + gamma = mkOption { + type = types.str; + description = "Output gamma configuration."; + default = ""; + example = "1.0:0.909:0.833"; + }; + + rotate = mkOption { + type = types.nullOr (types.enum [ "normal" "left" "right" "inverted" ]); + description = "Output rotate configuration."; + default = null; + example = "left"; + }; + + transform = mkOption { + type = types.nullOr (matrixOf 3 3 types.float); + default = null; + example = literalExpression '' + [ + [ 0.6 0.0 0.0 ] + [ 0.0 0.6 0.0 ] + [ 0.0 0.0 1.0 ] + ] + ''; + description = '' + Refer to + + xrandr + 1 + + for the documentation of the transform matrix. + ''; + }; + + dpi = mkOption { + type = types.nullOr types.ints.positive; + description = "Output DPI configuration."; + default = null; + example = 96; + }; + + scale = mkOption { + type = types.nullOr (types.submodule { + options = { + method = mkOption { + type = types.enum [ "factor" "pixel" ]; + description = "Output scaling method."; + default = "factor"; + example = "pixel"; + }; + + x = mkOption { + type = types.either types.float types.ints.positive; + description = "Horizontal scaling factor/pixels."; + }; + + y = mkOption { + type = types.either types.float types.ints.positive; + description = "Vertical scaling factor/pixels."; + }; + }; + }); + description = '' + Output scale configuration. + + Either configure by pixels or a scaling factor. When using pixel method the + + xrandr + 1 + + option + --scale-from + will be used; when using factor method the option + --scale + will be used. + + This option is a shortcut version of the transform option and they are mutually + exclusive. + ''; + default = null; + example = literalExpression '' + { + x = 1.25; + y = 1.25; + } + ''; + }; + + filter = mkOption { + type = types.nullOr (types.enum [ "bilinear" "nearest" ]); + description = "Interpolation method to be used for scaling the output."; + default = null; + example = "nearest"; + }; + }; + }; + + hookType = types.lines; + + globalHooksModule = types.submodule { + options = { + postswitch = mkOption { + type = types.attrsOf hookType; + description = "Postswitch hook executed after mode switch."; + default = { }; + }; + + preswitch = mkOption { + type = types.attrsOf hookType; + description = "Preswitch hook executed before mode switch."; + default = { }; + }; + + predetect = mkOption { + type = types.attrsOf hookType; + description = '' + Predetect hook executed before autorandr attempts to run xrandr. + ''; + default = { }; + }; + }; + }; + + profileHooksModule = types.submodule { + options = { + postswitch = mkOption { + type = hookType; + description = "Postswitch hook executed after mode switch."; + default = ""; + }; + + preswitch = mkOption { + type = hookType; + description = "Preswitch hook executed before mode switch."; + default = ""; + }; + + predetect = mkOption { + type = hookType; + description = '' + Predetect hook executed before autorandr attempts to run xrandr. + ''; + default = ""; + }; + }; + }; + + hookToFile = folder: name: hook: + nameValuePair "autorandr/${folder}/${name}" { + source = "${pkgs.writeShellScriptBin "hook" hook}/bin/hook"; + }; + profileToFiles = name: profile: + with profile; + mkMerge ([ + { + "autorandr/${name}/setup".text = concatStringsSep "\n" + (mapAttrsToList fingerprintToString fingerprint); + "autorandr/${name}/config".text = + concatStringsSep "\n" (mapAttrsToList configToString profile.config); + } + (mkIf (hooks.postswitch != "") + (listToAttrs [ (hookToFile name "postswitch" hooks.postswitch) ])) + (mkIf (hooks.preswitch != "") + (listToAttrs [ (hookToFile name "preswitch" hooks.preswitch) ])) + (mkIf (hooks.predetect != "") + (listToAttrs [ (hookToFile name "predetect" hooks.predetect) ])) + ]); + fingerprintToString = name: edid: "${name} ${edid}"; + configToString = name: config: + if config.enable then + concatStringsSep "\n" ([ "output ${name}" ] + ++ optional (config.position != "") "pos ${config.position}" + ++ optional (config.crtc != null) "crtc ${toString config.crtc}" + ++ optional config.primary "primary" + ++ optional (config.dpi != null) "dpi ${toString config.dpi}" + ++ optional (config.gamma != "") "gamma ${config.gamma}" + ++ optional (config.mode != "") "mode ${config.mode}" + ++ optional (config.rate != "") "rate ${config.rate}" + ++ optional (config.rotate != null) "rotate ${config.rotate}" + ++ optional (config.filter != null) "filter ${config.filter}" + ++ optional (config.transform != null) ("transform " + + concatMapStringsSep "," toString (flatten config.transform)) + ++ optional (config.scale != null) + ((if config.scale.method == "factor" then "scale" else "scale-from") + + " ${toString config.scale.x}x${toString config.scale.y}")) + else '' + output ${name} + off + ''; + +in { + options = { + programs.autorandr = { + enable = mkEnableOption "Autorandr"; + + hooks = mkOption { + type = globalHooksModule; + description = "Global hook scripts"; + default = { }; + example = literalExpression '' + { + postswitch = { + "notify-i3" = "''${pkgs.i3}/bin/i3-msg restart"; + "change-background" = readFile ./change-background.sh; + "change-dpi" = ''' + case "$AUTORANDR_CURRENT_PROFILE" in + default) + DPI=120 + ;; + home) + DPI=192 + ;; + work) + DPI=144 + ;; + *) + echo "Unknown profle: $AUTORANDR_CURRENT_PROFILE" + exit 1 + esac + + echo "Xft.dpi: $DPI" | ''${pkgs.xorg.xrdb}/bin/xrdb -merge + ''' + }; + } + ''; + }; + + profiles = mkOption { + type = types.attrsOf profileModule; + description = "Autorandr profiles specification."; + default = { }; + example = literalExpression '' + { + "work" = { + fingerprint = { + eDP1 = ""; + DP1 = ""; + }; + config = { + eDP1.enable = false; + DP1 = { + enable = true; + crtc = 0; + primary = true; + position = "0x0"; + mode = "3840x2160"; + gamma = "1.0:0.909:0.833"; + rate = "60.00"; + rotate = "left"; + }; + }; + hooks.postswitch = readFile ./work-postswitch.sh; + }; + } + ''; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = flatten (mapAttrsToList (profile: + { config, ... }: + mapAttrsToList (output: opts: { + assertion = opts.scale == null || opts.transform == null; + message = '' + Cannot use the profile output options 'scale' and 'transform' simultaneously. + Check configuration for: programs.autorandr.profiles.${profile}.config.${output} + ''; + }) config) cfg.profiles); + + home.packages = [ pkgs.autorandr ]; + xdg.configFile = mkMerge ([ + (mapAttrs' (hookToFile "postswitch.d") cfg.hooks.postswitch) + (mapAttrs' (hookToFile "preswitch.d") cfg.hooks.preswitch) + (mapAttrs' (hookToFile "predetect.d") cfg.hooks.predetect) + (mkMerge (mapAttrsToList profileToFiles cfg.profiles)) + ]); + }; + + meta.maintainers = [ maintainers.uvnikita ]; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/bash.nix b/infra/libkookie/home-manager-stable/modules/programs/bash.nix new file mode 100644 index 00000000000..53477bf9a94 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/bash.nix @@ -0,0 +1,224 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.bash; + + writeBashScript = name: text: pkgs.writeTextFile { + inherit name text; + checkPhase = '' + ${pkgs.stdenv.shellDryRun} "$target" + ''; + }; + +in + +{ + meta.maintainers = [ maintainers.rycee ]; + + imports = [ + (mkRenamedOptionModule [ "programs" "bash" "enableAutojump" ] [ + "programs" + "autojump" + "enable" + ]) + ]; + + options = { + programs.bash = { + enable = mkEnableOption "GNU Bourne-Again SHell"; + + historySize = mkOption { + type = types.int; + default = 10000; + description = "Number of history lines to keep in memory."; + }; + + historyFile = mkOption { + type = types.nullOr types.str; + default = null; + description = "Location of the bash history file."; + }; + + historyFileSize = mkOption { + type = types.int; + default = 100000; + description = "Number of history lines to keep on file."; + }; + + historyControl = mkOption { + type = types.listOf (types.enum [ + "erasedups" + "ignoredups" + "ignorespace" + ]); + default = []; + description = "Controlling how commands are saved on the history list."; + }; + + historyIgnore = mkOption { + type = types.listOf types.str; + default = []; + example = [ "ls" "cd" "exit" ]; + description = "List of commands that should not be saved to the history list."; + }; + + shellOptions = mkOption { + type = types.listOf types.str; + default = [ + # Append to history file rather than replacing it. + "histappend" + + # check the window size after each command and, if + # necessary, update the values of LINES and COLUMNS. + "checkwinsize" + + # Extended globbing. + "extglob" + "globstar" + + # Warn if closing shell with running jobs. + "checkjobs" + ]; + example = [ + "extglob" + "-cdspell" + ]; + description = '' + Shell options to set. Prefix an option with + - to unset. + ''; + }; + + sessionVariables = mkOption { + default = {}; + type = types.attrs; + example = { MAILCHECK = 30; }; + description = '' + Environment variables that will be set for the Bash session. + ''; + }; + + shellAliases = mkOption { + default = {}; + type = types.attrsOf types.str; + example = literalExpression '' + { + ll = "ls -l"; + ".." = "cd .."; + } + ''; + description = '' + An attribute set that maps aliases (the top level attribute names in + this option) to command strings or directly to build outputs. + ''; + }; + + profileExtra = mkOption { + default = ""; + type = types.lines; + description = '' + Extra commands that should be run when initializing a login + shell. + ''; + }; + + initExtra = mkOption { + default = ""; + type = types.lines; + description = '' + Extra commands that should be run when initializing an + interactive shell. + ''; + }; + + bashrcExtra = mkOption { + default = ""; + type = types.lines; + description = '' + Extra commands that should be placed in ~/.bashrc. + Note that these commands will be run even in non-interactive shells. + ''; + }; + + logoutExtra = mkOption { + default = ""; + type = types.lines; + description = '' + Extra commands that should be run when logging out of an + interactive shell. + ''; + }; + }; + }; + + config = ( + let + aliasesStr = concatStringsSep "\n" ( + mapAttrsToList (k: v: "alias ${k}=${escapeShellArg v}") cfg.shellAliases + ); + + shoptsStr = let + switch = v: if hasPrefix "-" v then "-u" else "-s"; + in concatStringsSep "\n" ( + map (v: "shopt ${switch v} ${removePrefix "-" v}") cfg.shellOptions + ); + + sessionVarsStr = config.lib.shell.exportAll cfg.sessionVariables; + + historyControlStr = + concatStringsSep "\n" (mapAttrsToList (n: v: "${n}=${v}") ( + { + HISTFILESIZE = toString cfg.historyFileSize; + HISTSIZE = toString cfg.historySize; + } + // optionalAttrs (cfg.historyFile != null) { + HISTFILE = "\"${cfg.historyFile}\""; + } + // optionalAttrs (cfg.historyControl != []) { + HISTCONTROL = concatStringsSep ":" cfg.historyControl; + } + // optionalAttrs (cfg.historyIgnore != []) { + HISTIGNORE = concatStringsSep ":" cfg.historyIgnore; + } + )); + in mkIf cfg.enable { + home.file.".bash_profile".source = writeBashScript "bash_profile" '' + # include .profile if it exists + [[ -f ~/.profile ]] && . ~/.profile + + # include .bashrc if it exists + [[ -f ~/.bashrc ]] && . ~/.bashrc + ''; + + home.file.".profile".source = writeBashScript "profile" '' + . "${config.home.profileDirectory}/etc/profile.d/hm-session-vars.sh" + + ${sessionVarsStr} + + ${cfg.profileExtra} + ''; + + home.file.".bashrc".source = writeBashScript "bashrc" '' + ${cfg.bashrcExtra} + + # Commands that should be applied only for interactive shells. + [[ $- == *i* ]] || return + + ${historyControlStr} + + ${shoptsStr} + + ${aliasesStr} + + ${cfg.initExtra} + ''; + + home.file.".bash_logout" = mkIf (cfg.logoutExtra != "") { + source = writeBashScript "bash_logout" cfg.logoutExtra; + }; + } + ); +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/bat.nix b/infra/libkookie/home-manager-stable/modules/programs/bat.nix new file mode 100644 index 00000000000..30b0bbb7152 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/bat.nix @@ -0,0 +1,62 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.bat; + + toConfigFile = generators.toKeyValue { + mkKeyValue = k: v: "--${k}=${lib.escapeShellArg v}"; + listsAsDuplicateKeys = true; + }; + +in { + meta.maintainers = [ maintainers.marsam ]; + + options.programs.bat = { + enable = mkEnableOption "bat, a cat clone with wings"; + + config = mkOption { + type = with types; attrsOf (either str (listOf str)); + default = { }; + example = { + theme = "TwoDark"; + pager = "less -FR"; + map-syntax = [ "*.jenkinsfile:Groovy" "*.props:Java Properties" ]; + }; + description = '' + Bat configuration. + ''; + }; + + themes = mkOption { + type = types.attrsOf types.lines; + default = { }; + example = literalExpression '' + { + dracula = builtins.readFile (pkgs.fetchFromGitHub { + owner = "dracula"; + repo = "sublime"; # Bat uses sublime syntax for its themes + rev = "26c57ec282abcaa76e57e055f38432bd827ac34e"; + sha256 = "019hfl4zbn4vm4154hh3bwk6hm7bdxbr1hdww83nabxwjn99ndhv"; + } + "/Dracula.tmTheme"); + } + ''; + description = '' + Additional themes to provide. + ''; + }; + + }; + + config = mkIf cfg.enable { + home.packages = [ pkgs.bat ]; + + xdg.configFile = mkMerge ([{ + "bat/config" = + mkIf (cfg.config != { }) { text = toConfigFile cfg.config; }; + }] ++ flip mapAttrsToList cfg.themes + (name: body: { "bat/themes/${name}.tmTheme" = { text = body; }; })); + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/beets.nix b/infra/libkookie/home-manager-stable/modules/programs/beets.nix new file mode 100644 index 00000000000..fa959669c2f --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/beets.nix @@ -0,0 +1,60 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.beets; + + yamlFormat = pkgs.formats.yaml { }; + +in { + meta.maintainers = [ maintainers.rycee ]; + + options = { + programs.beets = { + enable = mkOption { + type = types.bool; + default = if versionAtLeast config.home.stateVersion "19.03" then + false + else + cfg.settings != { }; + defaultText = "false"; + description = '' + Whether to enable the beets music library manager. This + defaults to false for state + version ≥ 19.03. For earlier versions beets is enabled if + is non-empty. + ''; + }; + + package = mkOption { + type = types.package; + default = pkgs.beets; + defaultText = literalExpression "pkgs.beets"; + example = + literalExpression "(pkgs.beets.override { enableCheck = true; })"; + description = '' + The beets package to use. + Can be used to specify extensions. + ''; + }; + + settings = mkOption { + type = yamlFormat.type; + default = { }; + description = '' + Configuration written to + $XDG_CONFIG_HOME/beets/config.yaml + ''; + }; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + + xdg.configFile."beets/config.yaml".source = + yamlFormat.generate "beets-config" cfg.settings; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/bottom.nix b/infra/libkookie/home-manager-stable/modules/programs/bottom.nix new file mode 100644 index 00000000000..459a3132c8b --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/bottom.nix @@ -0,0 +1,66 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.bottom; + + tomlFormat = pkgs.formats.toml { }; + + configDir = if pkgs.stdenv.isDarwin then + "Library/Application Support" + else + config.xdg.configHome; + +in { + options = { + programs.bottom = { + enable = mkEnableOption '' + bottom, a cross-platform graphical process/system monitor with a + customizable interface''; + + package = mkOption { + type = types.package; + default = pkgs.bottom; + defaultText = literalExpression "pkgs.bottom"; + description = "Package providing bottom."; + }; + + settings = mkOption { + type = tomlFormat.type; + default = { }; + description = '' + Configuration written to + $XDG_CONFIG_HOME/bottom/bottom.toml on Linux or + $HOME/Library/Application Support/bottom/bottom.toml on Darwin. + + See + for the default configuration. + ''; + example = literalExpression '' + { + flags = { + avg_cpu = true; + temperature_type = "c"; + }; + + colors = { + low_battery_color = "red"; + }; + } + ''; + }; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + + home.file."${configDir}/bottom/bottom.toml" = mkIf (cfg.settings != { }) { + source = tomlFormat.generate "bottom.toml" cfg.settings; + }; + }; + + meta.maintainers = [ maintainers.polykernel ]; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/broot.nix b/infra/libkookie/home-manager-stable/modules/programs/broot.nix new file mode 100644 index 00000000000..f37470d7c72 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/broot.nix @@ -0,0 +1,276 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.broot; + + tomlFormat = pkgs.formats.toml { }; + + brootConf = { + verbs = cfg.verbs; + skin = cfg.skin; + modal = cfg.modal; + }; + +in { + meta.maintainers = [ hm.maintainers.aheaume ]; + + options.programs.broot = { + enable = mkEnableOption "Broot, a better way to navigate directories"; + + enableBashIntegration = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable Bash integration. + ''; + }; + + enableZshIntegration = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable Zsh integration. + ''; + }; + + enableFishIntegration = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable Fish integration. + ''; + }; + + modal = mkEnableOption "modal (vim) mode"; + + verbs = mkOption { + type = with types; listOf (attrsOf (either bool str)); + default = [ + { + invocation = "p"; + execution = ":parent"; + } + { + invocation = "edit"; + shortcut = "e"; + execution = "$EDITOR {file}"; + } + { + invocation = "create {subpath}"; + execution = "$EDITOR {directory}/{subpath}"; + } + { + invocation = "view"; + execution = "less {file}"; + } + ]; + example = literalExpression '' + [ + { invocation = "p"; execution = ":parent"; } + { invocation = "edit"; shortcut = "e"; execution = "$EDITOR {file}" ; } + { invocation = "create {subpath}"; execution = "$EDITOR {directory}/{subpath}"; } + { invocation = "view"; execution = "less {file}"; } + { + invocation = "blop {name}\\.{type}"; + execution = "/bin/mkdir {parent}/{type} && /usr/bin/nvim {parent}/{type}/{name}.{type}"; + from_shell = true; + } + ] + ''; + description = '' + Define new verbs. For more information, see + . + + The possible attributes are: + + + + + + invocation (optional) + how the verb is called by the user, with placeholders for arguments + + + execution (mandatory) + how the verb is executed + + + key (optional) + a keyboard key triggering execution + + + shortcut (optional) + an alternate way to call the verb (without + the arguments part) + + + leave_broot (optional) + whether to quit broot on execution + (default: true) + + + from_shell (optional) + whether the verb must be executed from the + parent shell (default: + false) + + + ''; + }; + + package = mkOption { + type = types.package; + default = pkgs.broot; + defaultText = literalExpression "pkgs.broot"; + description = "Package providing broot"; + }; + + skin = mkOption { + type = types.attrsOf types.str; + default = { }; + example = literalExpression '' + { + status_normal_fg = "grayscale(18)"; + status_normal_bg = "grayscale(3)"; + status_error_fg = "red"; + status_error_bg = "yellow"; + tree_fg = "red"; + selected_line_bg = "grayscale(7)"; + permissions_fg = "grayscale(12)"; + size_bar_full_bg = "red"; + size_bar_void_bg = "black"; + directory_fg = "lightyellow"; + input_fg = "cyan"; + flag_value_fg = "lightyellow"; + table_border_fg = "red"; + code_fg = "lightyellow"; + } + ''; + description = '' + Color configuration. + + Complete list of keys (expected to change before the v1 of broot): + + + char_match + code + directory + exe + file + file_error + flag_label + flag_value + input + link + permissions + selected_line + size_bar_full + size_bar_void + size_text + spinner + status_error + status_normal + table_border + tree + unlisted + + + + Add _fg for a foreground color and + _bg for a background colors. + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + + xdg.configFile."broot/conf.toml".source = + tomlFormat.generate "broot-config" brootConf; + + # Dummy file to prevent broot from trying to reinstall itself + xdg.configFile."broot/launcher/installed-v1".text = ""; + + programs.bash.initExtra = mkIf cfg.enableBashIntegration ( + # Using mkAfter to make it more likely to appear after other + # manipulations of the prompt. + mkAfter '' + # This script was automatically generated by the broot function + # More information can be found in https://github.com/Canop/broot + # This function starts broot and executes the command + # it produces, if any. + # It's needed because some shell commands, like `cd`, + # have no useful effect if executed in a subshell. + function br { + f=$(mktemp) + ( + set +e + broot --outcmd "$f" "$@" + code=$? + if [ "$code" != 0 ]; then + rm -f "$f" + exit "$code" + fi + ) + code=$? + if [ "$code" != 0 ]; then + return "$code" + fi + d=$(cat "$f") + rm -f "$f" + eval "$d" + } + ''); + + programs.zsh.initExtra = mkIf cfg.enableZshIntegration '' + # This script was automatically generated by the broot function + # More information can be found in https://github.com/Canop/broot + # This function starts broot and executes the command + # it produces, if any. + # It's needed because some shell commands, like `cd`, + # have no useful effect if executed in a subshell. + function br { + f=$(mktemp) + ( + set +e + broot --outcmd "$f" "$@" + code=$? + if [ "$code" != 0 ]; then + rm -f "$f" + exit "$code" + fi + ) + code=$? + if [ "$code" != 0 ]; then + return "$code" + fi + d=$(cat "$f") + rm -f "$f" + eval "$d" + } + ''; + + programs.fish.shellInit = mkIf cfg.enableFishIntegration '' + # This script was automatically generated by the broot function + # More information can be found in https://github.com/Canop/broot + # This function starts broot and executes the command + # it produces, if any. + # It's needed because some shell commands, like `cd`, + # have no useful effect if executed in a subshell. + function br + set f (mktemp) + broot --outcmd $f $argv + if test $status -ne 0 + rm -f "$f" + return "$code" + end + set d (cat "$f") + rm -f "$f" + eval "$d" + end + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/browserpass.nix b/infra/libkookie/home-manager-stable/modules/programs/browserpass.nix new file mode 100644 index 00000000000..8faf53151b1 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/browserpass.nix @@ -0,0 +1,90 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.programs.browserpass; + browsers = [ "brave" "chrome" "chromium" "firefox" "vivaldi" ]; +in { + options = { + programs.browserpass = { + enable = mkEnableOption "the browserpass extension host application"; + + browsers = mkOption { + type = types.listOf (types.enum browsers); + default = browsers; + example = [ "firefox" ]; + description = "Which browsers to install browserpass for"; + }; + }; + }; + + config = mkIf cfg.enable { + home.file = foldl' (a: b: a // b) { } (concatMap (x: + with pkgs.stdenv; + if x == "brave" then + let + dir = if isDarwin then + "Library/Application Support/BraveSoftware/Brave-Browser/NativeMessagingHosts" + else + ".config/BraveSoftware/Brave-Browser/NativeMessagingHosts"; + in [{ + # Policies are read from `/etc/brave/policies` only + # https://github.com/brave/brave-browser/issues/19052 + "${dir}/com.github.browserpass.native.json".source = + "${pkgs.browserpass}/lib/browserpass/hosts/chromium/com.github.browserpass.native.json"; + }] + else if x == "chrome" then + let + dir = if isDarwin then + "Library/Application Support/Google/Chrome/NativeMessagingHosts" + else + ".config/google-chrome/NativeMessagingHosts"; + in [{ + "${dir}/com.github.browserpass.native.json".source = + "${pkgs.browserpass}/lib/browserpass/hosts/chromium/com.github.browserpass.native.json"; + "${dir}/../policies/managed/com.github.browserpass.native.json".source = + "${pkgs.browserpass}/lib/browserpass/policies/chromium/com.github.browserpass.native.json"; + }] + else if x == "chromium" then + let + dir = if isDarwin then + "Library/Application Support/Chromium/NativeMessagingHosts" + else + ".config/chromium/NativeMessagingHosts"; + in [ + { + "${dir}/com.github.browserpass.native.json".source = + "${pkgs.browserpass}/lib/browserpass/hosts/chromium/com.github.browserpass.native.json"; + } + { + "${dir}/../policies/managed/com.github.browserpass.native.json".source = + "${pkgs.browserpass}/lib/browserpass/policies/chromium/com.github.browserpass.native.json"; + } + ] + else if x == "firefox" then + let + dir = if isDarwin then + "Library/Application Support/Mozilla/NativeMessagingHosts" + else + ".mozilla/native-messaging-hosts"; + in [{ + "${dir}/com.github.browserpass.native.json".source = + "${pkgs.browserpass}/lib/browserpass/hosts/firefox/com.github.browserpass.native.json"; + }] + else if x == "vivaldi" then + let + dir = if isDarwin then + "Library/Application Support/Vivaldi/NativeMessagingHosts" + else + ".config/vivaldi/NativeMessagingHosts"; + in [{ + "${dir}/com.github.browserpass.native.json".source = + "${pkgs.browserpass}/lib/browserpass/hosts/chromium/com.github.browserpass.native.json"; + "${dir}/../policies/managed/com.github.browserpass.native.json".source = + "${pkgs.browserpass}/lib/browserpass/policies/chromium/com.github.browserpass.native.json"; + }] + else + throw "unknown browser ${x}") cfg.browsers); + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/chromium.nix b/infra/libkookie/home-manager-stable/modules/programs/chromium.nix new file mode 100644 index 00000000000..429543c53f9 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/chromium.nix @@ -0,0 +1,204 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + supportedBrowsers = [ + "chromium" + "google-chrome" + "google-chrome-beta" + "google-chrome-dev" + "brave" + "vivaldi" + ]; + + browserModule = defaultPkg: name: visible: + let + browser = (builtins.parseDrvName defaultPkg.name).name; + isProprietaryChrome = hasPrefix "Google Chrome" name; + in { + enable = mkOption { + inherit visible; + type = types.bool; + default = false; + example = true; + description = "Whether to enable ${name}."; + }; + + package = mkOption { + inherit visible; + type = types.package; + default = defaultPkg; + defaultText = literalExpression "pkgs.${browser}"; + description = "The ${name} package to use."; + }; + + commandLineArgs = mkOption { + inherit visible; + type = types.listOf types.str; + default = [ ]; + example = [ "--enable-logging=stderr" "--ignore-gpu-blocklist" ]; + description = '' + List of command-line arguments to be passed to ${name}. + + Note this option does not have any effect when using a + custom package for . + + For a list of common switches, see + Chrome switches. + + To search switches for other components, see + Chromium codesearch. + ''; + }; + } // optionalAttrs (!isProprietaryChrome) { + # Extensions do not work with Google Chrome + # see https://github.com/nix-community/home-manager/issues/1383 + extensions = mkOption { + inherit visible; + type = with types; + let + extensionType = submodule { + options = { + id = mkOption { + type = strMatching "[a-zA-Z]{32}"; + description = '' + The extension's ID from the Chome Web Store url or the unpacked crx. + ''; + default = ""; + }; + + updateUrl = mkOption { + type = str; + description = '' + URL of the extension's update manifest XML file. Linux only. + ''; + default = "https://clients2.google.com/service/update2/crx"; + visible = pkgs.stdenv.isLinux; + readOnly = pkgs.stdenv.isDarwin; + }; + + crxPath = mkOption { + type = nullOr path; + description = '' + Path to the extension's crx file. Linux only. + ''; + default = null; + visible = pkgs.stdenv.isLinux; + }; + + version = mkOption { + type = nullOr str; + description = '' + The extension's version, required for local installation. Linux only. + ''; + default = null; + visible = pkgs.stdenv.isLinux; + }; + }; + }; + in listOf (coercedTo str (v: { id = v; }) extensionType); + default = [ ]; + example = literalExpression '' + [ + { id = "cjpalhdlnbpafiamejdnhcphjbkeiagm"; } # ublock origin + { + id = "dcpihecpambacapedldabdbpakmachpb"; + updateUrl = "https://raw.githubusercontent.com/iamadamdev/bypass-paywalls-chrome/master/updates.xml"; + } + { + id = "aaaaaaaaaabbbbbbbbbbcccccccccc"; + crxPath = "/home/share/extension.crx"; + version = "1.0"; + } + ] + ''; + description = '' + List of ${name} extensions to install. + To find the extension ID, check its URL on the + Chrome Web Store. + + To install extensions outside of the Chrome Web Store set + updateUrl or crxPath and + version as explained in the + Chrome + documentation. + ''; + }; + }; + + browserConfig = cfg: + let + + drvName = (builtins.parseDrvName cfg.package.name).name; + browser = if drvName == "ungoogled-chromium" then "chromium" else drvName; + isProprietaryChrome = hasPrefix "google-chrome" drvName; + + darwinDirs = { + chromium = "Chromium"; + google-chrome = "Google/Chrome"; + google-chrome-beta = "Google/Chrome Beta"; + google-chrome-dev = "Google/Chrome Dev"; + brave = "BraveSoftware/Brave-Browser"; + }; + + linuxDirs = { brave = "BraveSoftware/Brave-Browser"; }; + + configDir = if pkgs.stdenv.isDarwin then + "Library/Application Support/" + (darwinDirs."${browser}" or browser) + else + "${config.xdg.configHome}/" + (linuxDirs."${browser}" or browser); + + extensionJson = ext: + assert ext.crxPath != null -> ext.version != null; + with builtins; { + name = "${configDir}/External Extensions/${ext.id}.json"; + value.text = toJSON (if ext.crxPath != null then { + external_crx = ext.crxPath; + external_version = ext.version; + } else { + external_update_url = ext.updateUrl; + }); + }; + + in mkIf cfg.enable { + home.packages = [ cfg.package ]; + home.file = optionalAttrs (!isProprietaryChrome) + (listToAttrs (map extensionJson cfg.extensions)); + }; + + browserPkgs = genAttrs supportedBrowsers (browser: + let cfg = config.programs.${browser}; + in if cfg.commandLineArgs != [ ] then + pkgs.${browser}.override { + commandLineArgs = concatStringsSep " " cfg.commandLineArgs; + } + else + pkgs.${browser}); + +in { + # Extensions do not work with the proprietary Google Chrome version + # see https://github.com/nix-community/home-manager/issues/1383 + imports = map (flip mkRemovedOptionModule + "The `extensions` option does not work on Google Chrome anymore.") [ + [ "programs" "google-chrome" "extensions" ] + [ "programs" "google-chrome-beta" "extensions" ] + [ "programs" "google-chrome-dev" "extensions" ] + ]; + + options.programs = { + chromium = browserModule browserPkgs.chromium "Chromium" true; + google-chrome = + browserModule browserPkgs.google-chrome "Google Chrome" false; + google-chrome-beta = + browserModule browserPkgs.google-chrome-beta "Google Chrome Beta" false; + google-chrome-dev = + browserModule browserPkgs.google-chrome-dev "Google Chrome Dev" false; + brave = browserModule browserPkgs.brave "Brave Browser" false; + vivaldi = browserModule browserPkgs.vivaldi "Vivaldi Browser" false; + }; + + config = mkMerge + (map (browser: browserConfig config.programs.${browser}) supportedBrowsers); +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/command-not-found/command-not-found.nix b/infra/libkookie/home-manager-stable/modules/programs/command-not-found/command-not-found.nix new file mode 100644 index 00000000000..a4917bbf18c --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/command-not-found/command-not-found.nix @@ -0,0 +1,54 @@ +# Adapted from Nixpkgs. + +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.programs.command-not-found; + commandNotFound = pkgs.substituteAll { + name = "command-not-found"; + dir = "bin"; + src = ./command-not-found.pl; + isExecutable = true; + inherit (cfg) dbPath; + perl = pkgs.perl.withPackages (p: [ p.DBDSQLite p.StringShellQuote ]); + }; + + shInit = commandNotFoundHandlerName: '' + # This function is called whenever a command is not found. + ${commandNotFoundHandlerName}() { + local p=${commandNotFound}/bin/command-not-found + if [ -x $p -a -f ${cfg.dbPath} ]; then + # Run the helper program. + $p "$@" + else + echo "$1: command not found" >&2 + return 127 + fi + } + ''; + +in { + options.programs.command-not-found = { + enable = mkEnableOption "command-not-found hook for interactive shell"; + + dbPath = mkOption { + default = + "/nix/var/nix/profiles/per-user/root/channels/nixos/programs.sqlite"; + description = '' + Absolute path to programs.sqlite. By + default this file will be provided by your channel + (nixexprs.tar.xz). + ''; + type = types.path; + }; + }; + + config = mkIf cfg.enable { + programs.bash.initExtra = shInit "command_not_found_handle"; + programs.zsh.initExtra = shInit "command_not_found_handler"; + + home.packages = [ commandNotFound ]; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/command-not-found/command-not-found.pl b/infra/libkookie/home-manager-stable/modules/programs/command-not-found/command-not-found.pl new file mode 100644 index 00000000000..220d057b7f4 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/command-not-found/command-not-found.pl @@ -0,0 +1,45 @@ +#! @perl@/bin/perl -w + +use strict; +use DBI; +use DBD::SQLite; +use String::ShellQuote; +use Config; + +my $program = $ARGV[0]; + +my $dbPath = "@dbPath@"; + +my $dbh = DBI->connect("dbi:SQLite:dbname=$dbPath", "", "") + or die "cannot open database `$dbPath'"; +$dbh->{RaiseError} = 0; +$dbh->{PrintError} = 0; + +my $system = $ENV{"NIX_SYSTEM"} // $Config{myarchname}; + +my $res = $dbh->selectall_arrayref( + "select package from Programs where system = ? and name = ?", + { Slice => {} }, $system, $program); + +if (!defined $res || scalar @$res == 0) { + print STDERR "$program: command not found\n"; +} elsif (scalar @$res == 1) { + my $package = @$res[0]->{package}; + if ($ENV{"NIX_AUTO_RUN"} // "") { + exec("nix-shell", "-p", $package, "--run", shell_quote("exec", @ARGV)); + } else { + print STDERR <{package}\n" foreach @$res; +} + +exit 127; diff --git a/infra/libkookie/home-manager-stable/modules/programs/dircolors.nix b/infra/libkookie/home-manager-stable/modules/programs/dircolors.nix new file mode 100644 index 00000000000..655d71e57cd --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/dircolors.nix @@ -0,0 +1,223 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.programs.dircolors; + + formatLine = n: v: "${n} ${toString v}"; +in { + meta.maintainers = [ hm.maintainers.justinlovinger ]; + + options.programs.dircolors = { + enable = mkOption { + type = types.bool; + default = false; + description = '' + Whether to manage .dir_colors + and set LS_COLORS. + ''; + }; + + enableBashIntegration = mkOption { + type = types.bool; + default = true; + description = '' + Whether to enable Bash integration. + ''; + }; + + enableFishIntegration = mkOption { + type = types.bool; + default = true; + description = '' + Whether to enable Fish integration. + ''; + }; + + enableZshIntegration = mkOption { + type = types.bool; + default = true; + description = '' + Whether to enable Zsh integration. + ''; + }; + + settings = mkOption { + type = with types; attrsOf str; + default = { }; + description = '' + Options to add to .dir_colors file. + See dircolors --print-database + for options. + ''; + example = literalExpression '' + { + OTHER_WRITABLE = "30;46"; + ".sh" = "01;32"; + ".csh" = "01;32"; + } + ''; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Extra lines added to .dir_colors file. + ''; + }; + }; + + config = mkIf cfg.enable { + # Add default settings from `dircolors --print-database`. + programs.dircolors.settings = { + RESET = mkDefault "0"; + DIR = mkDefault "01;34"; + LINK = mkDefault "01;36"; + MULTIHARDLINK = mkDefault "00"; + FIFO = mkDefault "40;33"; + SOCK = mkDefault "01;35"; + DOOR = mkDefault "01;35"; + BLK = mkDefault "40;33;01"; + CHR = mkDefault "40;33;01"; + ORPHAN = mkDefault "40;31;01"; + MISSING = mkDefault "00"; + SETUID = mkDefault "37;41"; + SETGID = mkDefault "30;43"; + CAPABILITY = mkDefault "30;41"; + STICKY_OTHER_WRITABLE = mkDefault "30;42"; + OTHER_WRITABLE = mkDefault "34;42"; + STICKY = mkDefault "37;44"; + EXEC = mkDefault "01;32"; + ".tar" = mkDefault "01;31"; + ".tgz" = mkDefault "01;31"; + ".arc" = mkDefault "01;31"; + ".arj" = mkDefault "01;31"; + ".taz" = mkDefault "01;31"; + ".lha" = mkDefault "01;31"; + ".lz4" = mkDefault "01;31"; + ".lzh" = mkDefault "01;31"; + ".lzma" = mkDefault "01;31"; + ".tlz" = mkDefault "01;31"; + ".txz" = mkDefault "01;31"; + ".tzo" = mkDefault "01;31"; + ".t7z" = mkDefault "01;31"; + ".zip" = mkDefault "01;31"; + ".z" = mkDefault "01;31"; + ".dz" = mkDefault "01;31"; + ".gz" = mkDefault "01;31"; + ".lrz" = mkDefault "01;31"; + ".lz" = mkDefault "01;31"; + ".lzo" = mkDefault "01;31"; + ".xz" = mkDefault "01;31"; + ".zst" = mkDefault "01;31"; + ".tzst" = mkDefault "01;31"; + ".bz2" = mkDefault "01;31"; + ".bz" = mkDefault "01;31"; + ".tbz" = mkDefault "01;31"; + ".tbz2" = mkDefault "01;31"; + ".tz" = mkDefault "01;31"; + ".deb" = mkDefault "01;31"; + ".rpm" = mkDefault "01;31"; + ".jar" = mkDefault "01;31"; + ".war" = mkDefault "01;31"; + ".ear" = mkDefault "01;31"; + ".sar" = mkDefault "01;31"; + ".rar" = mkDefault "01;31"; + ".alz" = mkDefault "01;31"; + ".ace" = mkDefault "01;31"; + ".zoo" = mkDefault "01;31"; + ".cpio" = mkDefault "01;31"; + ".7z" = mkDefault "01;31"; + ".rz" = mkDefault "01;31"; + ".cab" = mkDefault "01;31"; + ".wim" = mkDefault "01;31"; + ".swm" = mkDefault "01;31"; + ".dwm" = mkDefault "01;31"; + ".esd" = mkDefault "01;31"; + ".jpg" = mkDefault "01;35"; + ".jpeg" = mkDefault "01;35"; + ".mjpg" = mkDefault "01;35"; + ".mjpeg" = mkDefault "01;35"; + ".gif" = mkDefault "01;35"; + ".bmp" = mkDefault "01;35"; + ".pbm" = mkDefault "01;35"; + ".pgm" = mkDefault "01;35"; + ".ppm" = mkDefault "01;35"; + ".tga" = mkDefault "01;35"; + ".xbm" = mkDefault "01;35"; + ".xpm" = mkDefault "01;35"; + ".tif" = mkDefault "01;35"; + ".tiff" = mkDefault "01;35"; + ".png" = mkDefault "01;35"; + ".svg" = mkDefault "01;35"; + ".svgz" = mkDefault "01;35"; + ".mng" = mkDefault "01;35"; + ".pcx" = mkDefault "01;35"; + ".mov" = mkDefault "01;35"; + ".mpg" = mkDefault "01;35"; + ".mpeg" = mkDefault "01;35"; + ".m2v" = mkDefault "01;35"; + ".mkv" = mkDefault "01;35"; + ".webm" = mkDefault "01;35"; + ".ogm" = mkDefault "01;35"; + ".mp4" = mkDefault "01;35"; + ".m4v" = mkDefault "01;35"; + ".mp4v" = mkDefault "01;35"; + ".vob" = mkDefault "01;35"; + ".qt" = mkDefault "01;35"; + ".nuv" = mkDefault "01;35"; + ".wmv" = mkDefault "01;35"; + ".asf" = mkDefault "01;35"; + ".rm" = mkDefault "01;35"; + ".rmvb" = mkDefault "01;35"; + ".flc" = mkDefault "01;35"; + ".avi" = mkDefault "01;35"; + ".fli" = mkDefault "01;35"; + ".flv" = mkDefault "01;35"; + ".gl" = mkDefault "01;35"; + ".dl" = mkDefault "01;35"; + ".xcf" = mkDefault "01;35"; + ".xwd" = mkDefault "01;35"; + ".yuv" = mkDefault "01;35"; + ".cgm" = mkDefault "01;35"; + ".emf" = mkDefault "01;35"; + ".ogv" = mkDefault "01;35"; + ".ogx" = mkDefault "01;35"; + ".aac" = mkDefault "00;36"; + ".au" = mkDefault "00;36"; + ".flac" = mkDefault "00;36"; + ".m4a" = mkDefault "00;36"; + ".mid" = mkDefault "00;36"; + ".midi" = mkDefault "00;36"; + ".mka" = mkDefault "00;36"; + ".mp3" = mkDefault "00;36"; + ".mpc" = mkDefault "00;36"; + ".ogg" = mkDefault "00;36"; + ".ra" = mkDefault "00;36"; + ".wav" = mkDefault "00;36"; + ".oga" = mkDefault "00;36"; + ".opus" = mkDefault "00;36"; + ".spx" = mkDefault "00;36"; + ".xspf" = mkDefault "00;36"; + }; + + home.file.".dir_colors".text = concatStringsSep "\n" ([ ] + ++ mapAttrsToList formatLine cfg.settings ++ [ "" ] + ++ optional (cfg.extraConfig != "") cfg.extraConfig); + + programs.bash.initExtra = mkIf cfg.enableBashIntegration '' + eval $(${pkgs.coreutils}/bin/dircolors -b ~/.dir_colors) + ''; + + programs.fish.shellInit = mkIf cfg.enableFishIntegration '' + eval (${pkgs.coreutils}/bin/dircolors -c ~/.dir_colors) + ''; + + # Set `LS_COLORS` before Oh My Zsh and `initExtra`. + programs.zsh.initExtraBeforeCompInit = mkIf cfg.enableZshIntegration '' + eval $(${pkgs.coreutils}/bin/dircolors -b ~/.dir_colors) + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/direnv.nix b/infra/libkookie/home-manager-stable/modules/programs/direnv.nix new file mode 100644 index 00000000000..03210827aa8 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/direnv.nix @@ -0,0 +1,123 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.direnv; + + tomlFormat = pkgs.formats.toml { }; + +in { + imports = [ + (mkRenamedOptionModule [ + "programs" + "direnv" + "enableNixDirenvIntegration" + ] [ "programs" "direnv" "nix-direnv" "enable" ]) + (mkRemovedOptionModule [ "programs" "direnv" "nix-direnv" "enableFlakes" ] + "Flake support is now always enabled.") + ]; + + meta.maintainers = [ maintainers.rycee ]; + + options.programs.direnv = { + enable = mkEnableOption "direnv, the environment switcher"; + + config = mkOption { + type = tomlFormat.type; + default = { }; + description = '' + Configuration written to + $XDG_CONFIG_HOME/direnv/config.toml. + + See + + direnv.toml + 1 + . + for the full list of options. + ''; + }; + + stdlib = mkOption { + type = types.lines; + default = ""; + description = '' + Custom stdlib written to + $XDG_CONFIG_HOME/direnv/direnvrc. + ''; + }; + + enableBashIntegration = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable Bash integration. + ''; + }; + + enableZshIntegration = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable Zsh integration. + ''; + }; + + enableFishIntegration = mkOption { + default = true; + type = types.bool; + readOnly = true; + description = '' + Whether to enable Fish integration. Note, enabling the direnv module + will always active its functionality for Fish since the direnv package + automatically gets loaded in Fish. If this is not the case try adding + + environment.pathsToLink = [ "/share/fish" ]; + + to the system configuration. + ''; + }; + + nix-direnv = { + enable = mkEnableOption '' + nix-direnv, + a fast, persistent use_nix implementation for direnv''; + }; + + }; + + config = mkIf cfg.enable { + home.packages = [ pkgs.direnv ]; + + xdg.configFile."direnv/config.toml" = mkIf (cfg.config != { }) { + source = tomlFormat.generate "direnv-config" cfg.config; + }; + + xdg.configFile."direnv/direnvrc" = let + text = concatStringsSep "\n" (optional (cfg.stdlib != "") cfg.stdlib + ++ optional cfg.nix-direnv.enable + "source ${pkgs.nix-direnv}/share/nix-direnv/direnvrc"); + in mkIf (text != "") { inherit text; }; + + programs.bash.initExtra = mkIf cfg.enableBashIntegration ( + # Using mkAfter to make it more likely to appear after other + # manipulations of the prompt. + mkAfter '' + eval "$(${pkgs.direnv}/bin/direnv hook bash)" + ''); + + programs.zsh.initExtra = mkIf cfg.enableZshIntegration '' + eval "$(${pkgs.direnv}/bin/direnv hook zsh)" + ''; + + programs.fish.interactiveShellInit = mkIf cfg.enableFishIntegration ( + # Using mkAfter to make it more likely to appear after other + # manipulations of the prompt. + mkAfter '' + ${pkgs.direnv}/bin/direnv hook fish | source + ''); + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/eclipse.nix b/infra/libkookie/home-manager-stable/modules/programs/eclipse.nix new file mode 100644 index 00000000000..4c9328a0116 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/eclipse.nix @@ -0,0 +1,60 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.eclipse; + +in { + meta.maintainers = [ maintainers.rycee ]; + + options = { + programs.eclipse = { + enable = mkEnableOption "Eclipse"; + + package = mkOption { + type = types.package; + default = pkgs.eclipses.eclipse-platform; + defaultText = literalExpression "pkgs.eclipses.eclipse-platform"; + example = literalExpression "pkgs.eclipses.eclipse-java"; + description = '' + The Eclipse package to install. + ''; + }; + + enableLombok = mkOption { + type = types.bool; + default = false; + example = true; + description = '' + Whether to enable the Lombok Java Agent in Eclipse. This is + necessary to use the Lombok class annotations. + ''; + }; + + jvmArgs = mkOption { + type = types.listOf types.str; + default = [ ]; + description = "JVM arguments to use for the Eclipse process."; + }; + + plugins = mkOption { + type = types.listOf types.package; + default = [ ]; + description = "Plugins that should be added to Eclipse."; + }; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ + (pkgs.eclipses.eclipseWithPlugins { + eclipse = cfg.package; + jvmArgs = cfg.jvmArgs ++ optional cfg.enableLombok + "-javaagent:${pkgs.lombok}/share/java/lombok.jar"; + plugins = cfg.plugins; + }) + ]; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/emacs.nix b/infra/libkookie/home-manager-stable/modules/programs/emacs.nix new file mode 100644 index 00000000000..4253cb3b955 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/emacs.nix @@ -0,0 +1,100 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.emacs; + + # Copied from all-packages.nix, with modifications to support + # overrides. + emacsPackages = let epkgs = pkgs.emacsPackagesFor cfg.package; + in epkgs.overrideScope' cfg.overrides; + + emacsWithPackages = emacsPackages.emacsWithPackages; + + extraPackages = epkgs: + let + packages = cfg.extraPackages epkgs; + userConfig = epkgs.trivialBuild { + pname = "default"; + src = pkgs.writeText "default.el" cfg.extraConfig; + packageRequires = packages; + }; + in packages ++ optional (cfg.extraConfig != "") userConfig; + +in { + meta.maintainers = [ maintainers.rycee ]; + + options = { + programs.emacs = { + enable = mkEnableOption "Emacs"; + + package = mkOption { + type = types.package; + default = pkgs.emacs; + defaultText = literalExpression "pkgs.emacs"; + example = literalExpression "pkgs.emacs25-nox"; + description = "The Emacs package to use."; + }; + + # NOTE: The config is placed in default.el instead of ~/.emacs.d so that + # it won't conflict with Emacs configuration frameworks. Users of these + # frameworks would still benefit from this option as it would easily allow + # them to have Nix-computed paths in their configuration. + extraConfig = mkOption { + type = types.lines; + default = ""; + example = '' + (setq standard-indent 2) + ''; + description = '' + Configuration to include in the Emacs default init file. See + + for more. + ''; + }; + + extraPackages = mkOption { + default = self: [ ]; + type = hm.types.selectorFunction; + defaultText = "epkgs: []"; + example = literalExpression "epkgs: [ epkgs.emms epkgs.magit ]"; + description = '' + Extra packages available to Emacs. To get a list of + available packages run: + nix-env -f '<nixpkgs>' -qaP -A emacsPackages. + ''; + }; + + overrides = mkOption { + default = self: super: { }; + type = hm.types.overlayFunction; + defaultText = "self: super: {}"; + example = literalExpression '' + self: super: rec { + haskell-mode = self.melpaPackages.haskell-mode; + # ... + }; + ''; + description = '' + Allows overriding packages within the Emacs package set. + ''; + }; + + finalPackage = mkOption { + type = types.package; + visible = false; + readOnly = true; + description = '' + The Emacs package including any overrides and extra packages. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.finalPackage ]; + programs.emacs.finalPackage = emacsWithPackages extraPackages; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/eww.nix b/infra/libkookie/home-manager-stable/modules/programs/eww.nix new file mode 100644 index 00000000000..9200986d4d2 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/eww.nix @@ -0,0 +1,39 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.eww; + +in { + meta.maintainers = [ hm.maintainers.mainrs ]; + + options.programs.eww = { + enable = mkEnableOption "eww"; + + package = mkOption { + type = types.package; + default = pkgs.eww; + defaultText = literalExpression "pkgs.eww"; + example = literalExpression "pkgs.eww"; + description = '' + The eww package to install. + ''; + }; + + configDir = mkOption { + type = types.path; + example = literalExpression "./eww-config-dir"; + description = '' + The directory that gets symlinked to + $XDG_CONFIG_HOME/eww. + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + xdg.configFile."eww".source = cfg.configDir; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/exa.nix b/infra/libkookie/home-manager-stable/modules/programs/exa.nix new file mode 100644 index 00000000000..a7dfeb2b121 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/exa.nix @@ -0,0 +1,37 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.exa; + + aliases = { + ls = "${pkgs.exa}/bin/exa"; + ll = "${pkgs.exa}/bin/exa -l"; + la = "${pkgs.exa}/bin/exa -a"; + lt = "${pkgs.exa}/bin/exa --tree"; + lla = "${pkgs.exa}/bin/exa -la"; + }; + +in { + meta.maintainers = [ hm.maintainers.kalhauge ]; + + options.programs.exa = { + enable = + mkEnableOption "exa, a modern replacement for ls"; + enableAliases = mkEnableOption "recommended exa aliases"; + }; + + config = mkIf cfg.enable { + home.packages = [ pkgs.exa ]; + + programs.bash.shellAliases = mkIf cfg.enableAliases aliases; + + programs.zsh.shellAliases = mkIf cfg.enableAliases aliases; + + programs.fish.shellAliases = mkIf cfg.enableAliases aliases; + + programs.ion.shellAliases = mkIf cfg.enableAliases aliases; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/feh.nix b/infra/libkookie/home-manager-stable/modules/programs/feh.nix new file mode 100644 index 00000000000..e098342b53c --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/feh.nix @@ -0,0 +1,81 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.feh; + + bindingsOf = t: with types; attrsOf (nullOr (either t (listOf t))); + + renderBindings = bindings: + let + enabled = filterAttrs (n: v: v != null) bindings; + disabled = filterAttrs (n: v: v == null) bindings; + render = mapAttrsToList renderBinding; + in concatStringsSep "\n" (render disabled ++ render enabled); + + renderBinding = func: key: + if key == null then + func + else if isList key then + concatStringsSep " " ([ func ] ++ map toString key) + else + "${func} ${toString key}"; + +in { + options.programs.feh = { + enable = mkEnableOption "feh - a fast and light image viewer"; + + buttons = mkOption { + default = { }; + type = with types; bindingsOf (either str int); + example = { + zoom_in = 4; + zoom_out = "C-4"; + prev_img = [ 3 "C-3" ]; + }; + description = '' + Override feh's default mouse button mapping. If you want to disable an + action, set its value to null. If you want to bind multiple buttons to + an action, set its value to a list. + See for + default bindings and available commands. + ''; + }; + + keybindings = mkOption { + default = { }; + type = bindingsOf types.str; + example = { + zoom_in = "plus"; + zoom_out = "minus"; + prev_img = [ "h" "Left" ]; + }; + description = '' + Override feh's default keybindings. If you want to disable a keybinding + set its value to null. If you want to bind multiple keys to an action, + set its value to a list. + See for + default bindings and available commands. + ''; + }; + }; + + config = mkIf cfg.enable { + assertions = [{ + assertion = ((filterAttrs (n: v: v == "") cfg.keybindings) == { }); + message = + "To disable a keybinding, use `null` instead of an empty string."; + }]; + + home.packages = [ pkgs.feh ]; + + xdg.configFile."feh/buttons" = + mkIf (cfg.buttons != { }) { text = renderBindings cfg.buttons + "\n"; }; + + xdg.configFile."feh/keys" = mkIf (cfg.keybindings != { }) { + text = renderBindings cfg.keybindings + "\n"; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/firefox.nix b/infra/libkookie/home-manager-stable/modules/programs/firefox.nix new file mode 100644 index 00000000000..292bbb91aab --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/firefox.nix @@ -0,0 +1,387 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + inherit (pkgs.stdenv.hostPlatform) isDarwin; + + cfg = config.programs.firefox; + + mozillaConfigPath = + if isDarwin then "Library/Application Support/Mozilla" else ".mozilla"; + + firefoxConfigPath = if isDarwin then + "Library/Application Support/Firefox" + else + "${mozillaConfigPath}/firefox"; + + profilesPath = + if isDarwin then "${firefoxConfigPath}/Profiles" else firefoxConfigPath; + + # The extensions path shared by all profiles; will not be supported + # by future Firefox versions. + extensionPath = "extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"; + + extensionsEnvPkg = pkgs.buildEnv { + name = "hm-firefox-extensions"; + paths = cfg.extensions; + }; + + profiles = flip mapAttrs' cfg.profiles (_: profile: + nameValuePair "Profile${toString profile.id}" { + Name = profile.name; + Path = if isDarwin then "Profiles/${profile.path}" else profile.path; + IsRelative = 1; + Default = if profile.isDefault then 1 else 0; + }) // { + General = { StartWithLastProfile = 1; }; + }; + + profilesIni = generators.toINI { } profiles; + + mkUserJs = prefs: extraPrefs: bookmarks: + let + prefs' = lib.optionalAttrs ({ } != bookmarks) { + "browser.bookmarks.file" = toString (firefoxBookmarksFile bookmarks); + "browser.places.importBookmarksHTML" = true; + } // prefs; + in '' + // Generated by Home Manager. + + ${concatStrings (mapAttrsToList (name: value: '' + user_pref("${name}", ${builtins.toJSON value}); + '') prefs')} + + ${extraPrefs} + ''; + + firefoxBookmarksFile = bookmarks: + let + escapeXML = replaceStrings [ ''"'' "'" "<" ">" "&" ] [ + """ + "'" + "<" + ">" + "&" + ]; + mapper = _: entry: '' +
${escapeXML entry.name} + ''; + bookmarksEntries = lib.attrsets.mapAttrsToList mapper bookmarks; + in pkgs.writeText "firefox-bookmarks.html" '' + + + + Bookmarks +

Bookmarks Menu

+

+ ${concatStrings bookmarksEntries} +

+ ''; + +in { + meta.maintainers = [ maintainers.rycee ]; + + imports = [ + (mkRemovedOptionModule [ "programs" "firefox" "enableAdobeFlash" ] + "Support for this option has been removed.") + (mkRemovedOptionModule [ "programs" "firefox" "enableGoogleTalk" ] + "Support for this option has been removed.") + (mkRemovedOptionModule [ "programs" "firefox" "enableIcedTea" ] + "Support for this option has been removed.") + ]; + + options = { + programs.firefox = { + enable = mkEnableOption "Firefox"; + + package = mkOption { + type = types.package; + default = if versionAtLeast config.home.stateVersion "19.09" then + pkgs.firefox + else + pkgs.firefox-unwrapped; + defaultText = literalExpression "pkgs.firefox"; + example = literalExpression '' + pkgs.firefox.override { + # See nixpkgs' firefox/wrapper.nix to check which options you can use + cfg = { + # Gnome shell native connector + enableGnomeExtensions = true; + # Tridactyl native connector + enableTridactylNative = true; + }; + } + ''; + description = '' + The Firefox package to use. If state version ≥ 19.09 then + this should be a wrapped Firefox package. For earlier state + versions it should be an unwrapped Firefox package. + ''; + }; + + extensions = mkOption { + type = types.listOf types.package; + default = [ ]; + example = literalExpression '' + with pkgs.nur.repos.rycee.firefox-addons; [ + https-everywhere + privacy-badger + ] + ''; + description = '' + List of Firefox add-on packages to install. Some + pre-packaged add-ons are accessible from NUR, + . + Once you have NUR installed run + + + $ nix-env -f '<nixpkgs>' -qaP -A nur.repos.rycee.firefox-addons + + + to list the available Firefox add-ons. + + + + Note that it is necessary to manually enable these + extensions inside Firefox after the first installation. + + + + Extensions listed here will only be available in Firefox + profiles managed through the + programs.firefox.profiles + option. This is due to recent changes in the way Firefox + handles extension side-loading. + ''; + }; + + profiles = mkOption { + type = types.attrsOf (types.submodule ({ config, name, ... }: { + options = { + name = mkOption { + type = types.str; + default = name; + description = "Profile name."; + }; + + id = mkOption { + type = types.ints.unsigned; + default = 0; + description = '' + Profile ID. This should be set to a unique number per profile. + ''; + }; + + settings = mkOption { + type = with types; attrsOf (either bool (either int str)); + default = { }; + example = literalExpression '' + { + "browser.startup.homepage" = "https://nixos.org"; + "browser.search.region" = "GB"; + "browser.search.isUS" = false; + "distribution.searchplugins.defaultLocale" = "en-GB"; + "general.useragent.locale" = "en-GB"; + "browser.bookmarks.showMobileBookmarks" = true; + } + ''; + description = "Attribute set of Firefox preferences."; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Extra preferences to add to user.js. + ''; + }; + + userChrome = mkOption { + type = types.lines; + default = ""; + description = "Custom Firefox user chrome CSS."; + example = '' + /* Hide tab bar in FF Quantum */ + @-moz-document url("chrome://browser/content/browser.xul") { + #TabsToolbar { + visibility: collapse !important; + margin-bottom: 21px !important; + } + + #sidebar-box[sidebarcommand="treestyletab_piro_sakura_ne_jp-sidebar-action"] #sidebar-header { + visibility: collapse !important; + } + } + ''; + }; + + userContent = mkOption { + type = types.lines; + default = ""; + description = "Custom Firefox user content CSS."; + example = '' + /* Hide scrollbar in FF Quantum */ + *{scrollbar-width:none !important} + ''; + }; + + bookmarks = mkOption { + type = types.attrsOf (types.submodule ({ config, name, ... }: { + options = { + name = mkOption { + type = types.str; + default = name; + description = "Bookmark name."; + }; + + keyword = mkOption { + type = types.nullOr types.str; + default = null; + description = "Bookmark search keyword."; + }; + + url = mkOption { + type = types.str; + description = "Bookmark url, use %s for search terms."; + }; + }; + })); + default = { }; + example = literalExpression '' + { + wikipedia = { + keyword = "wiki"; + url = "https://en.wikipedia.org/wiki/Special:Search?search=%s&go=Go"; + }; + "kernel.org" = { + url = "https://www.kernel.org"; + }; + } + ''; + description = '' + Preloaded bookmarks. Note, this may silently overwrite any + previously existing bookmarks! + ''; + }; + + path = mkOption { + type = types.str; + default = name; + description = "Profile path."; + }; + + isDefault = mkOption { + type = types.bool; + default = config.id == 0; + defaultText = "true if profile ID is 0"; + description = "Whether this is a default profile."; + }; + }; + })); + default = { }; + description = "Attribute set of Firefox profiles."; + }; + + enableGnomeExtensions = mkOption { + type = types.bool; + default = false; + description = '' + Whether to enable the GNOME Shell native host connector. Note, you + also need to set the NixOS option + services.gnome3.chrome-gnome-shell.enable to + true. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (let + defaults = + catAttrs "name" (filter (a: a.isDefault) (attrValues cfg.profiles)); + in { + assertion = cfg.profiles == { } || length defaults == 1; + message = "Must have exactly one default Firefox profile but found " + + toString (length defaults) + optionalString (length defaults > 1) + (", namely " + concatStringsSep ", " defaults); + }) + + (let + duplicates = filterAttrs (_: v: length v != 1) (zipAttrs + (mapAttrsToList (n: v: { "${toString v.id}" = n; }) (cfg.profiles))); + + mkMsg = n: v: " - ID ${n} is used by ${concatStringsSep ", " v}"; + in { + assertion = duplicates == { }; + message = '' + Must not have Firefox profiles with duplicate IDs but + '' + concatStringsSep "\n" (mapAttrsToList mkMsg duplicates); + }) + ]; + + warnings = optional (cfg.enableGnomeExtensions or false) '' + Using 'programs.firefox.enableGnomeExtensions' has been deprecated and + will be removed in the future. Please change to overriding the package + configuration using 'programs.firefox.package' instead. You can refer to + its example for how to do this. + ''; + + home.packages = let + # The configuration expected by the Firefox wrapper. + fcfg = { enableGnomeExtensions = cfg.enableGnomeExtensions; }; + + # A bit of hackery to force a config into the wrapper. + browserName = cfg.package.browserName or (builtins.parseDrvName + cfg.package.name).name; + + # The configuration expected by the Firefox wrapper builder. + bcfg = setAttrByPath [ browserName ] fcfg; + + package = if isDarwin then + cfg.package + else if versionAtLeast config.home.stateVersion "19.09" then + cfg.package.override (old: { cfg = old.cfg or { } // fcfg; }) + else + (pkgs.wrapFirefox.override { config = bcfg; }) cfg.package { }; + in [ package ]; + + home.file = mkMerge ([{ + "${mozillaConfigPath}/${extensionPath}" = mkIf (cfg.extensions != [ ]) { + source = "${extensionsEnvPkg}/share/mozilla/${extensionPath}"; + recursive = true; + }; + + "${firefoxConfigPath}/profiles.ini" = + mkIf (cfg.profiles != { }) { text = profilesIni; }; + }] ++ flip mapAttrsToList cfg.profiles (_: profile: { + "${profilesPath}/${profile.path}/.keep".text = ""; + + "${profilesPath}/${profile.path}/chrome/userChrome.css" = + mkIf (profile.userChrome != "") { text = profile.userChrome; }; + + "${profilesPath}/${profile.path}/chrome/userContent.css" = + mkIf (profile.userContent != "") { text = profile.userContent; }; + + "${profilesPath}/${profile.path}/user.js" = mkIf (profile.settings != { } + || profile.extraConfig != "" || profile.bookmarks != { }) { + text = + mkUserJs profile.settings profile.extraConfig profile.bookmarks; + }; + + "${profilesPath}/${profile.path}/extensions" = + mkIf (cfg.extensions != [ ]) { + source = "${extensionsEnvPkg}/share/mozilla/${extensionPath}"; + recursive = true; + force = true; + }; + })); + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/fish.nix b/infra/libkookie/home-manager-stable/modules/programs/fish.nix new file mode 100644 index 00000000000..1fbb9e0710d --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/fish.nix @@ -0,0 +1,441 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.fish; + + pluginModule = types.submodule ({ config, ... }: { + options = { + src = mkOption { + type = types.path; + description = '' + Path to the plugin folder. + + Relevant pieces will be added to the fish function path and + the completion path. The init.fish and + key_binding.fish files are sourced if + they exist. + ''; + }; + + name = mkOption { + type = types.str; + description = '' + The name of the plugin. + ''; + }; + }; + }); + + functionModule = types.submodule { + options = { + body = mkOption { + type = types.lines; + description = '' + The function body. + ''; + }; + + argumentNames = mkOption { + type = with types; nullOr (either str (listOf str)); + default = null; + description = '' + Assigns the value of successive command line arguments to the names + given. + ''; + }; + + description = mkOption { + type = with types; nullOr str; + default = null; + description = '' + A description of what the function does, suitable as a completion + description. + ''; + }; + + wraps = mkOption { + type = with types; nullOr str; + default = null; + description = '' + Causes the function to inherit completions from the given wrapped + command. + ''; + }; + + onEvent = mkOption { + type = with types; nullOr str; + default = null; + description = '' + Tells fish to run this function when the specified named event is + emitted. Fish internally generates named events e.g. when showing the + prompt. + ''; + }; + + onVariable = mkOption { + type = with types; nullOr str; + default = null; + description = '' + Tells fish to run this function when the specified variable changes + value. + ''; + }; + + onJobExit = mkOption { + type = with types; nullOr (either str int); + default = null; + description = '' + Tells fish to run this function when the job with the specified group + ID exits. Instead of a PID, the stringer caller can + be specified. This is only legal when in a command substitution, and + will result in the handler being triggered by the exit of the job + which created this command substitution. + ''; + }; + + onProcessExit = mkOption { + type = with types; nullOr (either str int); + default = null; + example = "$fish_pid"; + description = '' + Tells fish to run this function when the fish child process with the + specified process ID exits. Instead of a PID, for backwards + compatibility, %self can be specified as an alias + for $fish_pid, and the function will be run when + the current fish instance exits. + ''; + }; + + onSignal = mkOption { + type = with types; nullOr (either str int); + default = null; + example = [ "SIGHUP" "HUP" 1 ]; + description = '' + Tells fish to run this function when the specified signal is + delievered. The signal can be a signal number or signal name. + ''; + }; + + noScopeShadowing = mkOption { + type = types.bool; + default = false; + description = '' + Allows the function to access the variables of calling functions. + ''; + }; + + inheritVariable = mkOption { + type = with types; nullOr str; + default = null; + description = '' + Snapshots the value of the specified variable and defines a local + variable with that same name and value when the function is defined. + ''; + }; + }; + }; + + abbrsStr = concatStringsSep "\n" + (mapAttrsToList (k: v: "abbr --add --global -- ${k} ${escapeShellArg v}") + cfg.shellAbbrs); + + aliasesStr = concatStringsSep "\n" + (mapAttrsToList (k: v: "alias ${k} ${escapeShellArg v}") cfg.shellAliases); + +in { + imports = [ + (mkRemovedOptionModule [ "programs" "fish" "promptInit" ] '' + Prompt is now configured through the + + programs.fish.interactiveShellInit + + option. Please change to use that instead. + '') + ]; + + options = { + programs.fish = { + enable = mkEnableOption "fish, the friendly interactive shell"; + + package = mkOption { + type = types.package; + default = pkgs.fish; + defaultText = literalExpression "pkgs.fish"; + description = '' + The fish package to install. May be used to change the version. + ''; + }; + + shellAliases = mkOption { + type = with types; attrsOf str; + default = { }; + example = literalExpression '' + { + g = "git"; + "..." = "cd ../.."; + } + ''; + description = '' + An attribute set that maps aliases (the top level attribute names + in this option) to command strings or directly to build outputs. + ''; + }; + + shellAbbrs = mkOption { + type = with types; attrsOf str; + default = { }; + example = { + l = "less"; + gco = "git checkout"; + }; + description = '' + An attribute set that maps aliases (the top level attribute names + in this option) to abbreviations. Abbreviations are expanded with + the longer phrase after they are entered. + ''; + }; + + shellInit = mkOption { + type = types.lines; + default = ""; + description = '' + Shell script code called during fish shell + initialisation. + ''; + }; + + loginShellInit = mkOption { + type = types.lines; + default = ""; + description = '' + Shell script code called during fish login shell + initialisation. + ''; + }; + + interactiveShellInit = mkOption { + type = types.lines; + default = ""; + description = '' + Shell script code called during interactive fish shell + initialisation. + ''; + }; + }; + + programs.fish.plugins = mkOption { + type = types.listOf pluginModule; + default = [ ]; + example = literalExpression '' + [ + { + name = "z"; + src = pkgs.fetchFromGitHub { + owner = "jethrokuan"; + repo = "z"; + rev = "ddeb28a7b6a1f0ec6dae40c636e5ca4908ad160a"; + sha256 = "0c5i7sdrsp0q3vbziqzdyqn4fmp235ax4mn4zslrswvn8g3fvdyh"; + }; + } + + # oh-my-fish plugins are stored in their own repositories, which + # makes them simple to import into home-manager. + { + name = "fasd"; + src = pkgs.fetchFromGitHub { + owner = "oh-my-fish"; + repo = "plugin-fasd"; + rev = "38a5b6b6011106092009549e52249c6d6f501fba"; + sha256 = "06v37hqy5yrv5a6ssd1p3cjd9y3hnp19d3ab7dag56fs1qmgyhbs"; + }; + } + ] + ''; + description = '' + The plugins to source in + conf.d/99plugins.fish. + ''; + }; + + programs.fish.functions = mkOption { + type = with types; attrsOf (either lines functionModule); + default = { }; + example = literalExpression '' + { + __fish_command_not_found_handler = { + body = "__fish_default_command_not_found_handler $argv[1]"; + onEvent = "fish_command_not_found"; + }; + + gitignore = "curl -sL https://www.gitignore.io/api/$argv"; + } + ''; + description = '' + Basic functions to add to fish. For more information see + . + ''; + }; + + }; + + config = mkIf cfg.enable (mkMerge [ + { + home.packages = [ cfg.package ]; + + xdg.dataFile."fish/home-manager_generated_completions".source = let + # paths later in the list will overwrite those already linked + destructiveSymlinkJoin = args_@{ name, paths, preferLocalBuild ? true + , allowSubstitutes ? false, postBuild ? "", ... }: + let + args = removeAttrs args_ [ "name" "postBuild" ] // { + # pass the defaults + inherit preferLocalBuild allowSubstitutes; + }; + in pkgs.runCommand name args '' + mkdir -p $out + for i in $paths; do + if [ -z "$(find $i -prune -empty)" ]; then + cp -srf $i/* $out + fi + done + ${postBuild} + ''; + + generateCompletions = package: + pkgs.runCommand "${package.name}-fish-completions" { + src = package; + nativeBuildInputs = [ pkgs.python3 ]; + buildInputs = [ cfg.package ]; + preferLocalBuild = true; + } '' + mkdir -p $out + if [ -d $src/share/man ]; then + find $src/share/man -type f \ + | xargs python ${cfg.package}/share/fish/tools/create_manpage_completions.py --directory $out \ + > /dev/null + fi + ''; + in destructiveSymlinkJoin { + name = "${config.home.username}-fish-completions"; + paths = + let cmp = (a: b: (a.meta.priority or 0) > (b.meta.priority or 0)); + in map generateCompletions (sort cmp config.home.packages); + }; + + programs.fish.interactiveShellInit = '' + # add completions generated by Home Manager to $fish_complete_path + begin + set -l joined (string join " " $fish_complete_path) + set -l prev_joined (string replace --regex "[^\s]*generated_completions.*" "" $joined) + set -l post_joined (string replace $prev_joined "" $joined) + set -l prev (string split " " (string trim $prev_joined)) + set -l post (string split " " (string trim $post_joined)) + set fish_complete_path $prev "${config.xdg.dataHome}/fish/home-manager_generated_completions" $post + end + ''; + + xdg.configFile."fish/config.fish".text = '' + # ~/.config/fish/config.fish: DO NOT EDIT -- this file has been generated + # automatically by home-manager. + + # Only execute this file once per shell. + set -q __fish_home_manager_config_sourced; and exit + set -g __fish_home_manager_config_sourced 1 + + set --prepend fish_function_path ${pkgs.fishPlugins.foreign-env}/share/fish/vendor_functions.d + fenv source ${config.home.profileDirectory}/etc/profile.d/hm-session-vars.sh > /dev/null + set -e fish_function_path[1] + + ${cfg.shellInit} + + status --is-login; and begin + + # Login shell initialisation + ${cfg.loginShellInit} + + end + + status --is-interactive; and begin + + # Abbreviations + ${abbrsStr} + + # Aliases + ${aliasesStr} + + # Interactive shell intialisation + ${cfg.interactiveShellInit} + + end + ''; + } + { + xdg.configFile = mapAttrs' (name: def: { + name = "fish/functions/${name}.fish"; + value = { + text = let + modifierStr = n: v: optional (v != null) ''--${n}="${toString v}"''; + modifierStrs = n: v: optional (v != null) "--${n}=${toString v}"; + modifierBool = n: v: optional (v != null && v) "--${n}"; + + mods = with def; + modifierStr "description" description ++ modifierStr "wraps" wraps + ++ modifierStr "on-event" onEvent + ++ modifierStr "on-variable" onVariable + ++ modifierStr "on-job-exit" onJobExit + ++ modifierStr "on-process-exit" onProcessExit + ++ modifierStr "on-signal" onSignal + ++ modifierBool "no-scope-shadowing" noScopeShadowing + ++ modifierStr "inherit-variable" inheritVariable + ++ modifierStrs "argument-names" argumentNames; + + modifiers = if isAttrs def then " ${toString mods}" else ""; + body = if isAttrs def then def.body else def; + in '' + function ${name}${modifiers} + ${body} + end + ''; + }; + }) cfg.functions; + } + + # Each plugin gets a corresponding conf.d/plugin-NAME.fish file to load + # in the paths and any initialization scripts. + (mkIf (length cfg.plugins > 0) { + xdg.configFile = mkMerge ((map (plugin: { + "fish/conf.d/plugin-${plugin.name}.fish".text = '' + # Plugin ${plugin.name} + set -l plugin_dir ${plugin.src} + + # Set paths to import plugin components + if test -d $plugin_dir/functions + set fish_function_path $fish_function_path[1] $plugin_dir/functions $fish_function_path[2..-1] + end + + if test -d $plugin_dir/completions + set fish_complete_path $fish_complete_path[1] $plugin_dir/completions $fish_complete_path[2..-1] + end + + # Source initialization code if it exists. + if test -d $plugin_dir/conf.d + for f in $plugin_dir/conf.d/*.fish + source $f + end + end + + if test -f $plugin_dir/key_bindings.fish + source $plugin_dir/key_bindings.fish + end + + if test -f $plugin_dir/init.fish + source $plugin_dir/init.fish + end + ''; + }) cfg.plugins)); + }) + ]); +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/foot.nix b/infra/libkookie/home-manager-stable/modules/programs/foot.nix new file mode 100644 index 00000000000..2b08f3acd72 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/foot.nix @@ -0,0 +1,81 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.foot; + iniFormat = pkgs.formats.ini { }; + +in { + meta.maintainers = with lib.maintainers; [ plabadens ]; + + options.programs.foot = { + enable = mkEnableOption "Foot terminal"; + + package = mkOption { + type = types.package; + default = pkgs.foot; + defaultText = literalExpression "pkgs.foot"; + description = "The foot package to install"; + }; + + server.enable = mkEnableOption "Foot terminal server"; + + settings = mkOption { + type = iniFormat.type; + default = { }; + description = '' + Configuration written to + $XDG_CONFIG_HOME/foot/foot.ini. See + for a list of available options. + ''; + example = literalExpression '' + { + main = { + term = "xterm-256color"; + + font = "Fira Code:size=11"; + dpi-aware = "yes"; + }; + + mouse = { + hide-when-typing = "yes"; + }; + } + ''; + }; + }; + + config = mkIf cfg.enable { + assertions = + [ (hm.assertions.assertPlatform "programs.foot" pkgs platforms.linux) ]; + + home.packages = [ cfg.package ]; + + xdg.configFile."foot/foot.ini" = mkIf (cfg.settings != { }) { + source = iniFormat.generate "foot.ini" cfg.settings; + }; + + systemd.user.services = mkIf cfg.server.enable { + foot = { + Unit = { + Description = + "Fast, lightweight and minimalistic Wayland terminal emulator."; + Documentation = "man:foot(1)"; + PartOf = [ "graphical-session.target" ]; + After = [ "graphical-session.target" ]; + }; + + Service = { + ExecStart = "${cfg.package}/bin/foot --server"; + Restart = "on-failure"; + OOMPolicy = "continue"; + }; + + Install = { WantedBy = [ "graphical-session.target" ]; }; + }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/fzf.nix b/infra/libkookie/home-manager-stable/modules/programs/fzf.nix new file mode 100644 index 00000000000..d8eef49c1da --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/fzf.nix @@ -0,0 +1,173 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.fzf; + +in { + imports = [ + (mkRemovedOptionModule [ "programs" "fzf" "historyWidgetCommand" ] + "This option is no longer supported by fzf.") + ]; + + options.programs.fzf = { + enable = mkEnableOption "fzf - a command-line fuzzy finder"; + + package = mkOption { + type = types.package; + default = pkgs.fzf; + defaultText = literalExpression "pkgs.fzf"; + description = "Package providing the fzf tool."; + }; + + defaultCommand = mkOption { + type = types.nullOr types.str; + default = null; + example = "fd --type f"; + description = '' + The command that gets executed as the default source for fzf + when running. + ''; + }; + + defaultOptions = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "--height 40%" "--border" ]; + description = '' + Extra command line options given to fzf by default. + ''; + }; + + fileWidgetCommand = mkOption { + type = types.nullOr types.str; + default = null; + example = "fd --type f"; + description = '' + The command that gets executed as the source for fzf for the + CTRL-T keybinding. + ''; + }; + + fileWidgetOptions = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "--preview 'head {}'" ]; + description = '' + Command line options for the CTRL-T keybinding. + ''; + }; + + changeDirWidgetCommand = mkOption { + type = types.nullOr types.str; + default = null; + example = "fd --type d"; + description = '' + The command that gets executed as the source for fzf for the + ALT-C keybinding. + ''; + }; + + changeDirWidgetOptions = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "--preview 'tree -C {} | head -200'" ]; + description = '' + Command line options for the ALT-C keybinding. + ''; + }; + + historyWidgetOptions = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "--sort" "--exact" ]; + description = '' + Command line options for the CTRL-R keybinding. + ''; + }; + + tmux = { + enableShellIntegration = mkEnableOption '' + setting FZF_TMUX=1 which causes shell integration to use fzf-tmux + ''; + + shellIntegrationOptions = mkOption { + type = types.listOf types.str; + default = [ ]; + example = literalExpression ''[ "-d 40%" ]''; + description = '' + If is set to true, + shell integration will use these options for fzf-tmux. + See fzf-tmux --help for available options. + ''; + }; + }; + + enableBashIntegration = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable Bash integration. + ''; + }; + + enableZshIntegration = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable Zsh integration. + ''; + }; + + enableFishIntegration = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable Fish integration. + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + + home.sessionVariables = mapAttrs (n: v: toString v) + (filterAttrs (n: v: v != [ ] && v != null) { + FZF_ALT_C_COMMAND = cfg.changeDirWidgetCommand; + FZF_ALT_C_OPTS = cfg.changeDirWidgetOptions; + FZF_CTRL_R_OPTS = cfg.historyWidgetOptions; + FZF_CTRL_T_COMMAND = cfg.fileWidgetCommand; + FZF_CTRL_T_OPTS = cfg.fileWidgetOptions; + FZF_DEFAULT_COMMAND = cfg.defaultCommand; + FZF_DEFAULT_OPTS = cfg.defaultOptions; + FZF_TMUX = if cfg.tmux.enableShellIntegration then "1" else null; + FZF_TMUX_OPTS = cfg.tmux.shellIntegrationOptions; + }); + + # Note, since fzf unconditionally binds C-r we use `mkOrder` to make the + # initialization show up a bit earlier. This is to make initialization of + # other history managers, like mcfly or atuin, take precedence. + programs.bash.initExtra = mkIf cfg.enableBashIntegration (mkOrder 200 '' + if [[ :$SHELLOPTS: =~ :(vi|emacs): ]]; then + . ${cfg.package}/share/fzf/completion.bash + . ${cfg.package}/share/fzf/key-bindings.bash + fi + ''); + + # Note, since fzf unconditionally binds C-r we use `mkOrder` to make the + # initialization show up a bit earlier. This is to make initialization of + # other history managers, like mcfly or atuin, take precedence. + programs.zsh.initExtra = mkIf cfg.enableZshIntegration (mkOrder 200 '' + if [[ $options[zle] = on ]]; then + . ${cfg.package}/share/fzf/completion.zsh + . ${cfg.package}/share/fzf/key-bindings.zsh + fi + ''); + + programs.fish.shellInit = mkIf cfg.enableFishIntegration '' + source ${cfg.package}/share/fzf/key-bindings.fish && fzf_key_bindings + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/getmail-accounts.nix b/infra/libkookie/home-manager-stable/modules/programs/getmail-accounts.nix new file mode 100644 index 00000000000..24eb4fb588a --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/getmail-accounts.nix @@ -0,0 +1,49 @@ +{ config, lib, ... }: + +with lib; + +{ + options.getmail = { + enable = mkEnableOption "the getmail mail retriever for this account"; + + destinationCommand = mkOption { + type = types.nullOr types.str; + default = null; + example = "\${pkgs.maildrop}/bin/maildrop"; + description = '' + Specify a command delivering the incoming mail to your maildir. + ''; + }; + + mailboxes = mkOption { + type = types.nonEmptyListOf types.str; + default = [ ]; + example = [ "INBOX" "INBOX.spam" ]; + description = '' + A non-empty list of mailboxes. To download all mail you can + use the ALL mailbox. + ''; + }; + + delete = mkOption { + type = types.bool; + default = false; + description = '' + Enable if you want to delete read messages from the server. Most + users should either enable delete or disable + readAll. + ''; + }; + + readAll = mkOption { + type = types.bool; + default = true; + description = '' + Enable if you want to fetch all, even the read messages from the + server. Most users should either enable delete or + disable readAll. + ''; + }; + + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/getmail.nix b/infra/libkookie/home-manager-stable/modules/programs/getmail.nix new file mode 100644 index 00000000000..53e39b4399d --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/getmail.nix @@ -0,0 +1,66 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + accounts = + filter (a: a.getmail.enable) (attrValues config.accounts.email.accounts); + + renderAccountConfig = account: + with account; + let + passCmd = concatMapStringsSep ", " (x: "'${x}'") passwordCommand; + renderedMailboxes = concatMapStrings (x: "'${x}', ") getmail.mailboxes; + retrieverType = if imap.tls.enable then + "SimpleIMAPSSLRetriever" + else + "SimpleIMAPRetriever"; + destination = if getmail.destinationCommand != null then { + destinationType = "MDA_external"; + destinationPath = getmail.destinationCommand; + } else { + destinationType = "Maildir"; + destinationPath = "${maildir.absPath}/"; + }; + renderGetmailBoolean = v: if v then "true" else "false"; + in '' + # Generated by Home-Manager. + [retriever] + type = ${retrieverType} + server = ${imap.host} + ${optionalString (imap.port != null) "port = ${toString imap.port}"} + username = ${userName} + password_command = (${passCmd}) + mailboxes = ( ${renderedMailboxes} ) + + [destination] + type = ${destination.destinationType} + path = ${destination.destinationPath} + + [options] + delete = ${renderGetmailBoolean getmail.delete} + read_all = ${renderGetmailBoolean getmail.readAll} + ''; + getmailEnabled = length (filter (a: a.getmail.enable) accounts) > 0; + # Watch out! This is used by the getmail.service too! + renderConfigFilepath = a: + ".getmail/getmail${if a.primary then "rc" else a.name}"; + +in { + options = { + accounts.email.accounts = mkOption { + type = with types; attrsOf (submodule (import ./getmail-accounts.nix)); + }; + }; + + config = mkIf getmailEnabled { + assertions = [ + (hm.assertions.assertPlatform "programs.getmail" pkgs platforms.linux) + ]; + + home.file = foldl' (a: b: a // b) { } + (map (a: { "${renderConfigFilepath a}".text = renderAccountConfig a; }) + accounts); + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/gh.nix b/infra/libkookie/home-manager-stable/modules/programs/gh.nix new file mode 100644 index 00000000000..ba457c8cbdd --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/gh.nix @@ -0,0 +1,110 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.gh; + + yamlFormat = pkgs.formats.yaml { }; + + settingsType = types.submodule { + freeformType = yamlFormat.type; + # These options are only here for the mkRenamedOptionModule support + options = { + aliases = mkOption { + type = with types; attrsOf str; + default = { }; + example = literalExpression '' + { + co = "pr checkout"; + pv = "pr view"; + } + ''; + description = '' + Aliases that allow you to create nicknames for gh commands. + ''; + }; + editor = mkOption { + type = types.str; + default = ""; + description = '' + The editor that gh should run when creating issues, pull requests, etc. + If blank, will refer to environment. + ''; + }; + git_protocol = mkOption { + type = types.str; + default = "https"; + example = "ssh"; + description = '' + The protocol to use when performing Git operations. + ''; + }; + }; + }; + +in { + meta.maintainers = [ maintainers.gerschtli maintainers.berbiche ]; + + imports = (map (x: + mkRenamedOptionModule [ "programs" "gh" x ] [ + "programs" + "gh" + "settings" + x + ]) [ "aliases" "editor" ]) ++ [ + (mkRenamedOptionModule [ "programs" "gh" "gitProtocol" ] [ + "programs" + "gh" + "settings" + "git_protocol" + ]) + ]; + + options.programs.gh = { + enable = mkEnableOption "GitHub CLI tool"; + + package = mkOption { + type = types.package; + default = pkgs.gh; + defaultText = literalExpression "pkgs.gh"; + description = "Package providing gh."; + }; + + settings = mkOption { + type = settingsType; + default = { }; + description = + "Configuration written to $XDG_CONFIG_HOME/gh/config.yml."; + example = literalExpression '' + { + git_protocol = "ssh"; + + prompt = "enabled"; + + aliases = { + co = "pr checkout"; + pv = "pr view"; + }; + }; + ''; + }; + + enableGitCredentialHelper = + mkEnableOption "the gh git credential helper for github.com" // { + default = true; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + + xdg.configFile."gh/config.yml".source = + yamlFormat.generate "gh-config.yml" cfg.settings; + + programs.git.extraConfig.credential."https://github.com".helper = + mkIf cfg.enableGitCredentialHelper + "${cfg.package}/bin/gh auth git-credential"; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/git.nix b/infra/libkookie/home-manager-stable/modules/programs/git.nix new file mode 100644 index 00000000000..c79bdae2048 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/git.nix @@ -0,0 +1,517 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.git; + + # create [section "subsection"] keys from "section.subsection" attrset names + mkSectionName = name: + let + containsQuote = strings.hasInfix ''"'' name; + sections = splitString "." name; + section = head sections; + subsections = tail sections; + subsection = concatStringsSep "." subsections; + in if containsQuote || subsections == [ ] then + name + else + ''${section} "${subsection}"''; + + mkValueString = v: + let + escapedV = '' + "${ + replaceStrings [ "\n" " " ''"'' "\\" ] [ "\\n" "\\t" ''\"'' "\\\\" ] v + }"''; + in generators.mkValueStringDefault { } (if isString v then escapedV else v); + + # generation for multiple ini values + mkKeyValue = k: v: + let + mkKeyValue = + generators.mkKeyValueDefault { inherit mkValueString; } " = " k; + in concatStringsSep "\n" (map (kv: " " + mkKeyValue kv) (toList v)); + + # converts { a.b.c = 5; } to { "a.b".c = 5; } for toINI + gitFlattenAttrs = let + recurse = path: value: + if isAttrs value then + mapAttrsToList (name: value: recurse ([ name ] ++ path) value) value + else if length path > 1 then { + ${concatStringsSep "." (reverseList (tail path))}.${head path} = value; + } else { + ${head path} = value; + }; + in attrs: foldl recursiveUpdate { } (flatten (recurse [ ] attrs)); + + gitToIni = attrs: + let toIni = generators.toINI { inherit mkKeyValue mkSectionName; }; + in toIni (gitFlattenAttrs attrs); + + gitIniType = with types; + let + primitiveType = either str (either bool int); + multipleType = either primitiveType (listOf primitiveType); + sectionType = attrsOf multipleType; + supersectionType = attrsOf (either multipleType sectionType); + in attrsOf supersectionType; + + signModule = types.submodule { + options = { + key = mkOption { + type = types.nullOr types.str; + description = '' + The default GPG signing key fingerprint. + + Set to null to let GnuPG decide what signing key + to use depending on commit’s author. + ''; + }; + + signByDefault = mkOption { + type = types.bool; + default = false; + description = "Whether commits should be signed by default."; + }; + + gpgPath = mkOption { + type = types.str; + default = "${pkgs.gnupg}/bin/gpg2"; + defaultText = "\${pkgs.gnupg}/bin/gpg2"; + description = "Path to GnuPG binary to use."; + }; + }; + }; + + includeModule = types.submodule ({ config, ... }: { + options = { + condition = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Include this configuration only when condition + matches. Allowed conditions are described in + + git-config + 1 + . + ''; + }; + + path = mkOption { + type = with types; either str path; + description = "Path of the configuration file to include."; + }; + + contents = mkOption { + type = types.attrsOf types.anything; + default = { }; + example = literalExpression '' + { + user = { + email = "bob@work.example.com"; + name = "Bob Work"; + signingKey = "1A2B3C4D5E6F7G8H"; + }; + commit = { + gpgSign = true; + }; + }; + ''; + description = '' + Configuration to include. If empty then a path must be given. + + This follows the configuration structure as described in + + git-config + 1 + . + ''; + }; + }; + + config.path = mkIf (config.contents != { }) + (mkDefault (pkgs.writeText "contents" (gitToIni config.contents))); + }); + +in { + meta.maintainers = [ maintainers.rycee ]; + + options = { + programs.git = { + enable = mkEnableOption "Git"; + + package = mkOption { + type = types.package; + default = pkgs.git; + defaultText = literalExpression "pkgs.git"; + description = '' + Git package to install. Use pkgs.gitAndTools.gitFull + to gain access to git send-email for instance. + ''; + }; + + userName = mkOption { + type = types.nullOr types.str; + default = null; + description = "Default user name to use."; + }; + + userEmail = mkOption { + type = types.nullOr types.str; + default = null; + description = "Default user email to use."; + }; + + aliases = mkOption { + type = types.attrsOf types.str; + default = { }; + example = { co = "checkout"; }; + description = "Git aliases to define."; + }; + + signing = mkOption { + type = types.nullOr signModule; + default = null; + description = "Options related to signing commits using GnuPG."; + }; + + extraConfig = mkOption { + type = types.either types.lines gitIniType; + default = { }; + example = { + core = { whitespace = "trailing-space,space-before-tab"; }; + url."ssh://git@host".insteadOf = "otherhost"; + }; + description = '' + Additional configuration to add. The use of string values is + deprecated and will be removed in the future. + ''; + }; + + iniContent = mkOption { + type = gitIniType; + internal = true; + }; + + ignores = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "*~" "*.swp" ]; + description = "List of paths that should be globally ignored."; + }; + + attributes = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "*.pdf diff=pdf" ]; + description = "List of defining attributes set globally."; + }; + + includes = mkOption { + type = types.listOf includeModule; + default = [ ]; + example = literalExpression '' + [ + { path = "~/path/to/config.inc"; } + { + path = "~/path/to/conditional.inc"; + condition = "gitdir:~/src/dir"; + } + ] + ''; + description = "List of configuration files to include."; + }; + + lfs = { + enable = mkEnableOption "Git Large File Storage"; + + skipSmudge = mkOption { + type = types.bool; + default = false; + description = '' + Skip automatic downloading of objects on clone or pull. + This requires a manual git lfs pull + every time a new commit is checked out on your repository. + ''; + }; + }; + + difftastic = { + enable = mkEnableOption "" // { + description = '' + Enable the difft syntax highlighter. + See . + ''; + }; + + background = mkOption { + type = types.enum [ "light" "dark" ]; + default = "light"; + example = "dark"; + description = '' + Determines whether difftastic should use the lighter or darker colors + for syntax highlithing. + ''; + }; + + color = mkOption { + type = types.enum [ "always" "auto" "never" ]; + default = "auto"; + example = "always"; + description = '' + Determines when difftastic should color its output. + ''; + }; + }; + + delta = { + enable = mkEnableOption "" // { + description = '' + Whether to enable the delta syntax highlighter. + See . + ''; + }; + + options = mkOption { + type = with types; + let + primitiveType = either str (either bool int); + sectionType = attrsOf primitiveType; + in attrsOf (either primitiveType sectionType); + default = { }; + example = { + features = "decorations"; + whitespace-error-style = "22 reverse"; + decorations = { + commit-decoration-style = "bold yellow box ul"; + file-style = "bold yellow ul"; + file-decoration-style = "none"; + }; + }; + description = '' + Options to configure delta. + ''; + }; + }; + + diff-so-fancy = { + enable = mkEnableOption "" // { + description = '' + Enable the diff-so-fancy diff colorizer. + See . + ''; + }; + + markEmptyLines = mkOption { + type = types.bool; + default = true; + example = false; + description = '' + Whether the first block of an empty line should be colored. + ''; + }; + + changeHunkIndicators = mkOption { + type = types.bool; + default = true; + example = false; + description = '' + Simplify git header chunks to a more human readable format. + ''; + }; + + stripLeadingSymbols = mkOption { + type = types.bool; + default = true; + example = false; + description = '' + Whether the + or - at + line-start should be removed. + ''; + }; + + useUnicodeRuler = mkOption { + type = types.bool; + default = true; + example = false; + description = '' + By default, the separator for the file header uses Unicode + line-drawing characters. If this is causing output errors on + your terminal, set this to false to use ASCII characters instead. + ''; + }; + + rulerWidth = mkOption { + type = types.nullOr types.int; + default = null; + example = false; + description = '' + By default, the separator for the file header spans the full + width of the terminal. Use this setting to set the width of + the file header manually. + ''; + }; + }; + }; + }; + + config = mkIf cfg.enable (mkMerge [ + { + home.packages = [ cfg.package ]; + assertions = [{ + assertion = let + enabled = + [ cfg.delta.enable cfg.diff-so-fancy.enable cfg.difftastic.enable ]; + in count id enabled <= 1; + message = + "Only one of 'programs.git.delta.enable' or 'programs.git.difftastic.enable' or 'programs.git.diff-so-fancy.enable' can be set to true at the same time."; + }]; + + programs.git.iniContent.user = { + name = mkIf (cfg.userName != null) cfg.userName; + email = mkIf (cfg.userEmail != null) cfg.userEmail; + }; + + xdg.configFile = { + "git/config".text = gitToIni cfg.iniContent; + + "git/ignore" = mkIf (cfg.ignores != [ ]) { + text = concatStringsSep "\n" cfg.ignores + "\n"; + }; + + "git/attributes" = mkIf (cfg.attributes != [ ]) { + text = concatStringsSep "\n" cfg.attributes + "\n"; + }; + }; + } + + { + programs.git.iniContent = let + hasSmtp = name: account: account.smtp != null; + + genIdentity = name: account: + with account; + nameValuePair "sendemail.${name}" (if account.msmtp.enable then { + smtpServer = "${pkgs.msmtp}/bin/msmtp"; + envelopeSender = "auto"; + from = address; + } else + { + smtpEncryption = if smtp.tls.enable then + (if smtp.tls.useStartTls + || versionOlder config.home.stateVersion "20.09" then + "tls" + else + "ssl") + else + ""; + smtpSslCertPath = + mkIf smtp.tls.enable (toString smtp.tls.certificatesFile); + smtpServer = smtp.host; + smtpUser = userName; + from = address; + } // optionalAttrs (smtp.port != null) { + smtpServerPort = smtp.port; + }); + in mapAttrs' genIdentity + (filterAttrs hasSmtp config.accounts.email.accounts); + } + + (mkIf (cfg.signing != null) { + programs.git.iniContent = { + user.signingKey = mkIf (cfg.signing.key != null) cfg.signing.key; + commit.gpgSign = cfg.signing.signByDefault; + gpg.program = cfg.signing.gpgPath; + }; + }) + + (mkIf (cfg.aliases != { }) { programs.git.iniContent.alias = cfg.aliases; }) + + (mkIf (lib.isAttrs cfg.extraConfig) { + programs.git.iniContent = cfg.extraConfig; + }) + + (mkIf (lib.isString cfg.extraConfig) { + warnings = ['' + Using programs.git.extraConfig as a string option is + deprecated and will be removed in the future. Please + change to using it as an attribute set instead. + '']; + + xdg.configFile."git/config".text = cfg.extraConfig; + }) + + (mkIf (cfg.includes != [ ]) { + xdg.configFile."git/config".text = let + include = i: + with i; + if condition != null then { + includeIf.${condition}.path = "${path}"; + } else { + include.path = "${path}"; + }; + in mkAfter + (concatStringsSep "\n" (map gitToIni (map include cfg.includes))); + }) + + (mkIf cfg.lfs.enable { + home.packages = [ pkgs.git-lfs ]; + + programs.git.iniContent.filter.lfs = + let skipArg = optional cfg.lfs.skipSmudge "--skip"; + in { + clean = "git-lfs clean -- %f"; + process = + concatStringsSep " " ([ "git-lfs" "filter-process" ] ++ skipArg); + required = true; + smudge = concatStringsSep " " + ([ "git-lfs" "smudge" ] ++ skipArg ++ [ "--" "%f" ]); + }; + }) + + (mkIf cfg.difftastic.enable { + home.packages = [ pkgs.difftastic ]; + + programs.git.iniContent = let + difftCommand = + "${pkgs.difftastic}/bin/difft --color ${cfg.difftastic.color} --background ${cfg.difftastic.background}"; + in { + diff.external = difftCommand; + core.pager = "${pkgs.less}/bin/less -XF"; + }; + }) + + (mkIf cfg.delta.enable { + home.packages = [ pkgs.delta ]; + + programs.git.iniContent = let deltaCommand = "${pkgs.delta}/bin/delta"; + in { + core.pager = deltaCommand; + interactive.diffFilter = "${deltaCommand} --color-only"; + delta = cfg.delta.options; + }; + }) + + (mkIf cfg.diff-so-fancy.enable { + home.packages = [ pkgs.diff-so-fancy ]; + + programs.git.iniContent = + let dsfCommand = "${pkgs.diff-so-fancy}/bin/diff-so-fancy"; + in { + core.pager = "${dsfCommand} | ${pkgs.less}/bin/less --tabs=4 -RFX"; + interactive.diffFilter = "${dsfCommand} --patch"; + diff-so-fancy = { + markEmptyLines = cfg.diff-so-fancy.markEmptyLines; + changeHunkIndicators = cfg.diff-so-fancy.changeHunkIndicators; + stripLeadingSymbols = cfg.diff-so-fancy.stripLeadingSymbols; + useUnicodeRuler = cfg.diff-so-fancy.useUnicodeRuler; + rulerWidth = mkIf (cfg.diff-so-fancy.rulerWidth != null) + (cfg.diff-so-fancy.rulerWidth); + }; + }; + }) + ]); +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/gitui.nix b/infra/libkookie/home-manager-stable/modules/programs/gitui.nix new file mode 100644 index 00000000000..ee6572bcaf1 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/gitui.nix @@ -0,0 +1,82 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.gitui; + +in { + meta.maintainers = [ hm.maintainers.mifom ]; + + options.programs.gitui = { + enable = + mkEnableOption "gitui, blazing fast terminal-ui for git written in rust"; + + package = mkOption { + type = types.package; + default = pkgs.gitui; + defaultText = "pkgs.gitui"; + description = "The package to use."; + }; + + keyConfig = mkOption { + type = types.either types.path types.lines; + default = ""; + example = '' + exit: Some(( code: Char('c'), modifiers: ( bits: 2,),)), + quit: Some(( code: Char('q'), modifiers: ( bits: 0,),)), + exit_popup: Some(( code: Esc, modifiers: ( bits: 0,),)), + ''; + description = '' + Key config in Ron file format. This is written to + $XDG_CONFIG_HOME/gitui/key_config.ron. + ''; + }; + + theme = mkOption { + type = types.either types.path types.lines; + default = '' + ( + selected_tab: Reset, + command_fg: White, + selection_bg: Blue, + cmdbar_extra_lines_bg: Blue, + disabled_fg: DarkGray, + diff_line_add: Green, + diff_line_delete: Red, + diff_file_added: LightGreen, + diff_file_removed: LightRed, + diff_file_moved: LightMagenta, + diff_file_modified: Yellow, + commit_hash: Magenta, + commit_time: LightCyan, + commit_author: Green, + danger_fg: Red, + push_gauge_bg: Blue, + push_gauge_fg: Reset, + ) + ''; + description = '' + Theme in Ron file format. This is written to + $XDG_CONFIG_HOME/gitui/theme.ron. + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + + xdg.configFile."gitui/theme.ron".source = + if builtins.isPath cfg.theme || lib.isStorePath cfg.theme then + cfg.theme + else + pkgs.writeText "gitui-theme.ron" cfg.theme; + + xdg.configFile."gitui/key_bindings.ron".source = + if builtins.isPath cfg.keyConfig || lib.isStorePath cfg.keyConfig then + cfg.keyConfig + else + pkgs.writeText "gitui-key-config.ron" cfg.keyConfig; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/gnome-terminal.nix b/infra/libkookie/home-manager-stable/modules/programs/gnome-terminal.nix new file mode 100644 index 00000000000..a9e3b5a758c --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/gnome-terminal.nix @@ -0,0 +1,358 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.gnome-terminal; + + eraseBinding = types.enum [ + "auto" + "ascii-backspace" + "ascii-delete" + "delete-sequence" + "tty" + ]; + + backForeSubModule = types.submodule ({ ... }: { + options = { + foreground = mkOption { + type = types.str; + description = "The foreground color."; + }; + + background = mkOption { + type = types.str; + description = "The background color."; + }; + }; + }); + + profileColorsSubModule = types.submodule ({ ... }: { + options = { + foregroundColor = mkOption { + type = types.str; + description = "The foreground color."; + }; + + backgroundColor = mkOption { + type = types.str; + description = "The background color."; + }; + + boldColor = mkOption { + default = null; + type = types.nullOr types.str; + description = "The bold color, null to use same as foreground."; + }; + + palette = mkOption { + type = types.listOf types.str; + description = "The terminal palette."; + }; + + cursor = mkOption { + default = null; + type = types.nullOr backForeSubModule; + description = "The color for the terminal cursor."; + }; + + highlight = mkOption { + default = null; + type = types.nullOr backForeSubModule; + description = "The colors for the terminal’s highlighted area."; + }; + }; + }); + + profileSubModule = types.submodule ({ name, config, ... }: { + options = { + default = mkOption { + default = false; + type = types.bool; + description = "Whether this should be the default profile."; + }; + + visibleName = mkOption { + type = types.str; + description = "The profile name."; + }; + + colors = mkOption { + default = null; + type = types.nullOr profileColorsSubModule; + description = "The terminal colors, null to use system default."; + }; + + cursorBlinkMode = mkOption { + default = "system"; + type = types.enum [ "system" "on" "off" ]; + description = "The cursor blink mode."; + }; + + cursorShape = mkOption { + default = "block"; + type = types.enum [ "block" "ibeam" "underline" ]; + description = "The cursor shape."; + }; + + font = mkOption { + default = null; + type = types.nullOr types.str; + description = "The font name, null to use system default."; + }; + + allowBold = mkOption { + default = null; + type = types.nullOr types.bool; + description = '' + If true, allow applications in the + terminal to make text boldface. + ''; + }; + + scrollOnOutput = mkOption { + default = true; + type = types.bool; + description = "Whether to scroll when output is written."; + }; + + showScrollbar = mkOption { + default = true; + type = types.bool; + description = "Whether the scroll bar should be visible."; + }; + + scrollbackLines = mkOption { + default = 10000; + type = types.nullOr types.int; + description = '' + The number of scrollback lines to keep, null for infinite. + ''; + }; + + customCommand = mkOption { + default = null; + type = types.nullOr types.str; + description = '' + The command to use to start the shell, or null for default shell. + ''; + }; + + loginShell = mkOption { + default = false; + type = types.bool; + description = "Run command as a login shell."; + }; + + backspaceBinding = mkOption { + default = "ascii-delete"; + type = eraseBinding; + description = '' + Which string the terminal should send to an application when the user + presses the Backspace key. + + + + auto + + Attempt to determine the right value from the terminal's IO settings. + + + + ascii-backspace + + Send an ASCII backspace character (0x08). + + + + ascii-delete + + Send an ASCII delete character (0x7F). + + + + delete-sequence + + Send the @7 control sequence. + + + + tty + + Send terminal’s erase setting. + + + + ''; + }; + + boldIsBright = mkOption { + default = null; + type = types.nullOr types.bool; + description = "Whether bold text is shown in bright colors."; + }; + + deleteBinding = mkOption { + default = "delete-sequence"; + type = eraseBinding; + description = '' + Which string the terminal should send to an application when the user + presses the Delete key. + + + + auto + + Send the @7 control sequence. + + + + ascii-backspace + + Send an ASCII backspace character (0x08). + + + + ascii-delete + + Send an ASCII delete character (0x7F). + + + + delete-sequence + + Send the @7 control sequence. + + + + tty + + Send terminal’s erase setting. + + + + ''; + }; + + audibleBell = mkOption { + default = true; + type = types.bool; + description = "Turn on/off the terminal's bell."; + }; + + transparencyPercent = mkOption { + default = null; + type = types.nullOr (types.ints.between 0 100); + description = "Background transparency in percent."; + }; + }; + }); + + buildProfileSet = pcfg: + { + audible-bell = pcfg.audibleBell; + visible-name = pcfg.visibleName; + scroll-on-output = pcfg.scrollOnOutput; + scrollbar-policy = if pcfg.showScrollbar then "always" else "never"; + scrollback-lines = pcfg.scrollbackLines; + cursor-shape = pcfg.cursorShape; + cursor-blink-mode = pcfg.cursorBlinkMode; + login-shell = pcfg.loginShell; + backspace-binding = pcfg.backspaceBinding; + delete-binding = pcfg.deleteBinding; + } // (if (pcfg.customCommand != null) then { + use-custom-command = true; + custom-command = pcfg.customCommand; + } else { + use-custom-command = false; + }) // (if (pcfg.font == null) then { + use-system-font = true; + } else { + use-system-font = false; + font = pcfg.font; + }) // (if (pcfg.colors == null) then { + use-theme-colors = true; + } else + ({ + use-theme-colors = false; + foreground-color = pcfg.colors.foregroundColor; + background-color = pcfg.colors.backgroundColor; + palette = pcfg.colors.palette; + } // optionalAttrs (pcfg.allowBold != null) { + allow-bold = pcfg.allowBold; + } // (if (pcfg.colors.boldColor == null) then { + bold-color-same-as-fg = true; + } else { + bold-color-same-as-fg = false; + bold-color = pcfg.colors.boldColor; + }) // optionalAttrs (pcfg.boldIsBright != null) { + bold-is-bright = pcfg.boldIsBright; + } // (if (pcfg.colors.cursor != null) then { + cursor-colors-set = true; + cursor-foreground-color = pcfg.colors.cursor.foreground; + cursor-background-color = pcfg.colors.cursor.background; + } else { + cursor-colors-set = false; + }) // (if (pcfg.colors.highlight != null) then { + highlight-colors-set = true; + highlight-foreground-color = pcfg.colors.highlight.foreground; + highlight-background-color = pcfg.colors.highlight.background; + } else { + highlight-colors-set = false; + }) // optionalAttrs (pcfg.transparencyPercent != null) { + background-transparency-percent = pcfg.transparencyPercent; + use-theme-transparency = false; + use-transparent-background = true; + })); + +in { + meta.maintainers = with maintainers; [ kamadorueda rycee ]; + + options = { + programs.gnome-terminal = { + enable = mkEnableOption "Gnome Terminal"; + + showMenubar = mkOption { + default = true; + type = types.bool; + description = "Whether to show the menubar by default"; + }; + + themeVariant = mkOption { + default = "default"; + type = types.enum [ "default" "light" "dark" "system" ]; + description = "The theme variation to request"; + }; + + profile = mkOption { + default = { }; + type = types.attrsOf profileSubModule; + description = "A set of Gnome Terminal profiles."; + }; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ pkgs.gnome.gnome-terminal ]; + + dconf.settings = let dconfPath = "org/gnome/terminal/legacy"; + in { + "${dconfPath}" = { + default-show-menubar = cfg.showMenubar; + theme-variant = cfg.themeVariant; + schema-version = 3; + }; + + "${dconfPath}/profiles:" = { + default = head (attrNames (filterAttrs (n: v: v.default) cfg.profile)); + list = attrNames cfg.profile; + }; + } // mapAttrs' + (n: v: nameValuePair ("${dconfPath}/profiles:/:${n}") (buildProfileSet v)) + cfg.profile; + + programs.bash.enableVteIntegration = true; + programs.zsh.enableVteIntegration = true; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/go.nix b/infra/libkookie/home-manager-stable/modules/programs/go.nix new file mode 100644 index 00000000000..8ec361b3d27 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/go.nix @@ -0,0 +1,105 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.go; + +in { + meta.maintainers = [ maintainers.rvolosatovs ]; + + options = { + programs.go = { + enable = mkEnableOption "Go"; + + package = mkOption { + type = types.package; + default = pkgs.go; + defaultText = literalExpression "pkgs.go"; + description = "The Go package to use."; + }; + + packages = mkOption { + type = with types; attrsOf path; + default = { }; + example = literalExpression '' + { + "golang.org/x/text" = builtins.fetchGit "https://go.googlesource.com/text"; + "golang.org/x/time" = builtins.fetchGit "https://go.googlesource.com/time"; + } + ''; + description = "Packages to add to GOPATH."; + }; + + goPath = mkOption { + type = with types; nullOr str; + default = null; + example = "go"; + description = '' + Primary GOPATH relative to + HOME. It will be exported first and therefore + used by default by the Go tooling. + ''; + }; + + extraGoPaths = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "extraGoPath1" "extraGoPath2" ]; + description = let goPathOpt = "programs.go.goPath"; + in '' + Extra GOPATHs relative to HOME appended + after + ${goPathOpt}, + if that option is set. + ''; + }; + + goBin = mkOption { + type = with types; nullOr str; + default = null; + example = ".local/bin.go"; + description = "GOBIN relative to HOME"; + }; + + goPrivate = mkOption { + type = with types; listOf str; + default = [ ]; + example = [ "*.corp.example.com" "rsc.io/private" ]; + description = '' + The GOPRIVATE environment variable controls + which modules the go command considers to be private (not + available publicly) and should therefore not use the proxy + or checksum database. + ''; + }; + }; + }; + + config = mkIf cfg.enable (mkMerge [ + { + home.packages = [ cfg.package ]; + + home.file = let + goPath = if cfg.goPath != null then cfg.goPath else "go"; + mkSrc = n: v: { "${goPath}/src/${n}".source = v; }; + in foldl' (a: b: a // b) { } (mapAttrsToList mkSrc cfg.packages); + } + + (mkIf (cfg.goPath != null) { + home.sessionVariables.GOPATH = concatStringsSep ":" (map builtins.toPath + (map (path: "${config.home.homeDirectory}/${path}") + ([ cfg.goPath ] ++ cfg.extraGoPaths))); + }) + + (mkIf (cfg.goBin != null) { + home.sessionVariables.GOBIN = + builtins.toPath "${config.home.homeDirectory}/${cfg.goBin}"; + }) + + (mkIf (cfg.goPrivate != [ ]) { + home.sessionVariables.GOPRIVATE = concatStringsSep "," cfg.goPrivate; + }) + ]); +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/gpg.nix b/infra/libkookie/home-manager-stable/modules/programs/gpg.nix new file mode 100644 index 00000000000..4b233dc6b59 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/gpg.nix @@ -0,0 +1,326 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.programs.gpg; + + mkKeyValue = key: value: + if isString value then "${key} ${value}" else optionalString value key; + + cfgText = generators.toKeyValue { + inherit mkKeyValue; + listsAsDuplicateKeys = true; + } cfg.settings; + + scdaemonCfgText = generators.toKeyValue { + inherit mkKeyValue; + listsAsDuplicateKeys = true; + } cfg.scdaemonSettings; + + primitiveType = types.oneOf [ types.str types.bool ]; + + publicKeyOpts = { config, ... }: { + options = { + text = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Text of an OpenPGP public key. + ''; + }; + + source = mkOption { + type = types.path; + description = '' + Path of an OpenPGP public key file. + ''; + }; + + trust = mkOption { + type = types.nullOr (types.enum [ + "unknown" + 1 + "never" + 2 + "marginal" + 3 + "full" + 4 + "ultimate" + 5 + ]); + default = null; + apply = v: + if isString v then + { + unknown = 1; + never = 2; + marginal = 3; + full = 4; + ultimate = 5; + }.${v} + else + v; + description = '' + The amount of trust you have in the key ownership and the care the + owner puts into signing other keys. The available levels are + + + unknown or 1 + I don't know or won't say. + + + never or 2 + I do NOT trust. + + + marginal or 3 + I trust marginally. + + + full or 4 + I trust fully. + + + ultimate or 5 + I trust ultimately. + + + + See + for more. + ''; + }; + }; + + config = { + source = + mkIf (config.text != null) (pkgs.writeText "gpg-pubkey" config.text); + }; + }; + + importTrustBashFunctions = let gpg = "${cfg.package}/bin/gpg"; + in '' + function gpgKeyId() { + ${gpg} --show-key --with-colons "$1" \ + | grep ^pub: \ + | cut -d: -f5 + } + + function importTrust() { + local keyIds trust + IFS='\n' read -ra keyIds <<< "$(gpgKeyId "$1")" + trust="$2" + for id in "''${keyIds[@]}" ; do + { echo trust; echo "$trust"; (( trust == 5 )) && echo y; echo quit; } \ + | ${gpg} --no-tty --command-fd 0 --edit-key "$id" + done + } + + ''; + + keyringFiles = let + gpg = "${cfg.package}/bin/gpg"; + + importKey = { source, trust, ... }: '' + ${gpg} --import ${source} + ${optionalString (trust != null) + ''importTrust "${source}" ${toString trust}''} + ''; + + importKeys = concatMapStringsSep "\n" importKey cfg.publicKeys; + in pkgs.runCommand "gpg-pubring" { buildInputs = [ cfg.package ]; } '' + export GNUPGHOME + GNUPGHOME=$(mktemp -d) + + ${importTrustBashFunctions} + ${importKeys} + + mkdir $out + cp $GNUPGHOME/pubring.kbx $out/pubring.kbx + if [[ -e $GNUPGHOME/trustdb.gpg ]] ; then + cp $GNUPGHOME/trustdb.gpg $out/trustdb.gpg + fi + ''; + +in { + options.programs.gpg = { + enable = mkEnableOption "GnuPG"; + + package = mkOption { + type = types.package; + default = pkgs.gnupg; + defaultText = literalExpression "pkgs.gnupg"; + example = literalExpression "pkgs.gnupg23"; + description = + "The Gnupg package to use (also used the gpg-agent service)."; + }; + + settings = mkOption { + type = + types.attrsOf (types.either primitiveType (types.listOf types.str)); + example = literalExpression '' + { + no-comments = false; + s2k-cipher-algo = "AES128"; + } + ''; + description = '' + GnuPG configuration options. Available options are described + in the gpg manpage: + . + + + Note that lists are converted to duplicate keys. + ''; + }; + + scdaemonSettings = mkOption { + type = + types.attrsOf (types.either primitiveType (types.listOf types.str)); + example = literalExpression '' + { + disable-ccid = true; + } + ''; + description = '' + SCdaemon configuration options. Available options are described + in the gpg scdaemon manpage: + . + ''; + }; + + homedir = mkOption { + type = types.path; + example = literalExpression ''"''${config.xdg.dataHome}/gnupg"''; + default = "${config.home.homeDirectory}/.gnupg"; + defaultText = + literalExpression ''"''${config.home.homeDirectory}/.gnupg"''; + description = "Directory to store keychains and configuration."; + }; + + mutableKeys = mkOption { + type = types.bool; + default = true; + description = '' + If set to true, you may manage your keyring as a user + using the gpg command. Upon activation, the keyring + will have managed keys added without overwriting unmanaged keys. + + If set to false, the path + $GNUPGHOME/pubring.kbx will become an immutable + link to the Nix store, denying modifications. + ''; + }; + + mutableTrust = mkOption { + type = types.bool; + default = true; + description = '' + If set to true, you may manage trust as a user using + the gpg command. Upon activation, trusted keys have + their trust set without overwriting unmanaged keys. + + If set to false, the path + $GNUPGHOME/trustdb.gpg will be + overwritten on each activation, removing trust for + any unmanaged keys. Be careful to make a backup of your old + trustdb.gpg before switching to immutable trust! + ''; + }; + + publicKeys = mkOption { + type = types.listOf (types.submodule publicKeyOpts); + example = literalExpression '' + [ { source = ./pubkeys.txt; } ] + ''; + default = [ ]; + description = '' + A list of public keys to be imported into GnuPG. Note, these key files + will be copied into the world-readable Nix store. + ''; + }; + }; + + config = mkIf cfg.enable { + programs.gpg.settings = { + personal-cipher-preferences = mkDefault "AES256 AES192 AES"; + personal-digest-preferences = mkDefault "SHA512 SHA384 SHA256"; + personal-compress-preferences = mkDefault "ZLIB BZIP2 ZIP Uncompressed"; + default-preference-list = mkDefault + "SHA512 SHA384 SHA256 AES256 AES192 AES ZLIB BZIP2 ZIP Uncompressed"; + cert-digest-algo = mkDefault "SHA512"; + s2k-digest-algo = mkDefault "SHA512"; + s2k-cipher-algo = mkDefault "AES256"; + charset = mkDefault "utf-8"; + fixed-list-mode = mkDefault true; + no-comments = mkDefault true; + no-emit-version = mkDefault true; + keyid-format = mkDefault "0xlong"; + list-options = mkDefault "show-uid-validity"; + verify-options = mkDefault "show-uid-validity"; + with-fingerprint = mkDefault true; + require-cross-certification = mkDefault true; + no-symkey-cache = mkDefault true; + use-agent = mkDefault true; + }; + + programs.gpg.scdaemonSettings = { + # no defaults for scdaemon + }; + + home.packages = [ cfg.package ]; + home.sessionVariables = { GNUPGHOME = cfg.homedir; }; + + home.file."${cfg.homedir}/gpg.conf".text = cfgText; + + home.file."${cfg.homedir}/scdaemon.conf".text = scdaemonCfgText; + + # Link keyring if keys are not mutable + home.file."${cfg.homedir}/pubring.kbx" = + mkIf (!cfg.mutableKeys && cfg.publicKeys != [ ]) { + source = "${keyringFiles}/pubring.kbx"; + }; + + home.activation = { + createGpgHomedir = + hm.dag.entryBetween [ "linkGeneration" ] [ "writeBoundary" ] '' + $DRY_RUN_CMD mkdir -m700 -p $VERBOSE_ARG ${escapeShellArg cfg.homedir} + ''; + + importGpgKeys = let + gpg = "${cfg.package}/bin/gpg"; + + importKey = { source, trust, ... }: + # Import mutable keys + optional cfg.mutableKeys + "$DRY_RUN_CMD ${gpg} $QUIET_ARG --import ${source}" + + # Import mutable trust + ++ optional (trust != null && cfg.mutableTrust) + ''$DRY_RUN_CMD importTrust "${source}" ${toString trust}''; + + anyTrust = any (k: k.trust != null) cfg.publicKeys; + + importKeys = concatStringsSep "\n" (concatMap importKey cfg.publicKeys); + + # If any key/trust should be imported then create the block. Otherwise + # leave it empty. + block = concatStringsSep "\n" (optional (importKeys != "") '' + export GNUPGHOME=${escapeShellArg cfg.homedir} + if [[ ! -v VERBOSE ]]; then + QUIET_ARG="--quiet" + else + QUIET_ARG="" + fi + ${importTrustBashFunctions} + ${importKeys} + unset GNUPGHOME QUIET_ARG keyId importTrust + '' ++ optional (!cfg.mutableTrust && anyTrust) '' + install -m 0700 ${keyringFiles}/trustdb.gpg "${cfg.homedir}/trustdb.gpg"''); + in mkIf (cfg.publicKeys != [ ]) + (lib.hm.dag.entryAfter [ "linkGeneration" ] block); + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/helix.nix b/infra/libkookie/home-manager-stable/modules/programs/helix.nix new file mode 100644 index 00000000000..9d06b65c8b9 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/helix.nix @@ -0,0 +1,151 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.programs.helix; + tomlFormat = pkgs.formats.toml { }; +in { + meta.maintainers = [ hm.maintainers.Philipp-M ]; + + options.programs.helix = { + enable = mkEnableOption "helix text editor"; + + package = mkOption { + type = types.package; + default = pkgs.helix; + defaultText = literalExpression "pkgs.helix"; + description = "The package to use for helix."; + }; + + settings = mkOption { + type = tomlFormat.type; + default = { }; + example = literalExpression '' + { + theme = "base16"; + lsp.display-messages = true; + keys.normal = { + space.space = "file_picker"; + space.w = ":w"; + space.q = ":q"; + }; + } + ''; + description = '' + Configuration written to + $XDG_CONFIG_HOME/helix/config.toml. + + See + for the full list of options. + ''; + }; + + languages = mkOption { + type = types.listOf tomlFormat.type; + default = [ ]; + example = [{ + name = "rust"; + auto-format = false; + }]; + description = '' + Language specific configuration at + $XDG_CONFIG_HOME/helix/languages.toml. + + See + for more information. + ''; + }; + + themes = mkOption { + type = types.attrsOf tomlFormat.type; + default = { }; + example = literalExpression '' + { + base16 = let + transparent = "none"; + gray = "#665c54"; + dark-gray = "#3c3836"; + white = "#fbf1c7"; + black = "#282828"; + red = "#fb4934"; + green = "#b8bb26"; + yellow = "#fabd2f"; + orange = "#fe8019"; + blue = "#83a598"; + magenta = "#d3869b"; + cyan = "#8ec07c"; + in { + "ui.menu" = transparent; + "ui.menu.selected" = { modifiers = [ "reversed" ]; }; + "ui.linenr" = { fg = gray; bg = dark-gray; }; + "ui.popup" = { modifiers = [ "reversed" ]; }; + "ui.linenr.selected" = { fg = white; bg = black; modifiers = [ "bold" ]; }; + "ui.selection" = { fg = black; bg = blue; }; + "ui.selection.primary" = { modifiers = [ "reversed" ]; }; + "comment" = { fg = gray; }; + "ui.statusline" = { fg = white; bg = dark-gray; }; + "ui.statusline.inactive" = { fg = dark-gray; bg = white; }; + "ui.help" = { fg = dark-gray; bg = white; }; + "ui.cursor" = { modifiers = [ "reversed" ]; }; + "variable" = red; + "variable.builtin" = orange; + "constant.numeric" = orange; + "constant" = orange; + "attributes" = yellow; + "type" = yellow; + "ui.cursor.match" = { fg = yellow; modifiers = [ "underlined" ]; }; + "string" = green; + "variable.other.member" = red; + "constant.character.escape" = cyan; + "function" = blue; + "constructor" = blue; + "special" = blue; + "keyword" = magenta; + "label" = magenta; + "namespace" = blue; + "diff.plus" = green; + "diff.delta" = yellow; + "diff.minus" = red; + "diagnostic" = { modifiers = [ "underlined" ]; }; + "ui.gutter" = { bg = black; }; + "info" = blue; + "hint" = dark-gray; + "debug" = dark-gray; + "warning" = yellow; + "error" = red; + }; + } + ''; + description = '' + Each theme is written to + $XDG_CONFIG_HOME/helix/themes/theme-name.toml. + Where the name of each attribute is the theme-name (in the example "base16"). + + See + for the full list of options. + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + + xdg.configFile = let + settings = { + "helix/config.toml" = mkIf (cfg.settings != { }) { + source = tomlFormat.generate "helix-config" cfg.settings; + }; + "helix/languages.toml" = mkIf (cfg.languages != [ ]) { + source = + tomlFormat.generate "helix-config" { language = cfg.languages; }; + }; + }; + + themes = (mapAttrs' (n: v: + nameValuePair "helix/themes/${n}.toml" { + source = tomlFormat.generate "helix-theme-${n}" v; + }) cfg.themes); + in settings // themes; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/hexchat.nix b/infra/libkookie/home-manager-stable/modules/programs/hexchat.nix new file mode 100644 index 00000000000..a23ea622c2c --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/hexchat.nix @@ -0,0 +1,363 @@ +{ config, pkgs, lib, ... }: + +with lib; + +let + cfg = config.programs.hexchat; + + channelOptions = with types; + submodule { + options = { + autoconnect = mkOption { + type = nullOr bool; + default = false; + description = "Autoconnect to network."; + }; + + connectToSelectedServerOnly = mkOption { + type = nullOr bool; + default = true; + description = "Connect to selected server only."; + }; + + bypassProxy = mkOption { + type = nullOr bool; + default = true; + description = "Bypass proxy."; + }; + + forceSSL = mkOption { + type = nullOr bool; + default = false; + description = "Use SSL for all servers."; + }; + + acceptInvalidSSLCertificates = mkOption { + type = nullOr bool; + default = false; + description = "Accept invalid SSL certificates."; + }; + + useGlobalUserInformation = mkOption { + type = nullOr bool; + default = false; + description = "Use global user information."; + }; + }; + }; + + modChannelOption = with types; + submodule { + options = { + autojoin = mkOption { + type = listOf str; + default = [ ]; + example = [ "#home-manager" "#linux" "#nix" ]; + description = "Channels list to autojoin on connecting to server."; + }; + + charset = mkOption { + type = nullOr str; + default = null; + example = "UTF-8 (Unicode)"; + description = "Character set."; + }; + + commands = mkOption { + type = listOf str; + default = [ ]; + example = literalExpression ''[ "ECHO Greetings fellow Nixer! ]''; + description = "Commands to be executed on connecting to server."; + }; + + loginMethod = mkOption { + type = nullOr (enum (attrNames loginMethodMap)); + default = null; + description = '' + The login method. The allowed options are: + + + null + Default + + + "nickServMsg" + NickServ (/MSG NickServ + password) + + + "nickServ" + NickServ (/NICKSERV + password) + + + "challengeAuth" + Challenge Auth (username + password) + + + "sasl" + SASL (username + password) + + + "serverPassword" + Server password (/PASS password) + + + "saslExternal" + SASL EXTERNAL (cert) + + + "customCommands" + + Use "commands" field for auth. For example + + commands = [ "/msg NickServ IDENTIFY my_password" ] + + + + + + ''; + }; + + nickname = mkOption { + type = nullOr str; + default = null; + description = "Primary nickname."; + }; + + nickname2 = mkOption { + type = nullOr str; + default = null; + description = "Secondary nickname."; + }; + + options = mkOption { + type = nullOr channelOptions; + default = null; + example = { + autoconnect = true; + useGlobalUserInformation = true; + }; + description = "Channel options."; + }; + + password = mkOption { + type = nullOr str; + default = null; + description = '' + Password to use. Note this password will be readable by all user's + in the Nix store. + ''; + }; + + realName = mkOption { + type = nullOr str; + default = null; + description = '' + Real name. Is used to populate the real name field that appears when + someone uses the WHOIS command on your nick. + ''; + }; + + userName = mkOption { + type = nullOr str; + default = null; + description = '' + User name. Part of your user@host hostmask that + appears to other on IRC. + ''; + }; + + servers = mkOption { + type = listOf str; + default = [ ]; + example = [ "chat.freenode.net" "irc.freenode.net" ]; + description = "IRC Server Address List."; + }; + }; + }; + + transformField = k: v: if (v != null) then "${k}=${v}" else null; + + listChar = c: l: + if l != [ ] then concatMapStringsSep "\n" (transformField c) l else null; + + computeFieldsValue = channel: + let + ifTrue = p: n: if p then n else 0; + result = with channel.options; + foldl' (a: b: a + b) 0 [ + (ifTrue (!connectToSelectedServerOnly) 1) + (ifTrue useGlobalUserInformation 2) + (ifTrue forceSSL 4) + (ifTrue autoconnect 8) + (ifTrue (!bypassProxy) 16) + (ifTrue acceptInvalidSSLCertificates 32) + ]; + in toString (if channel.options == null then 0 else result); + + loginMethodMap = { + nickServMsg = 1; + nickServ = 2; + challengeAuth = 4; + sasl = 6; + serverPassword = 7; + customCommands = 9; + saslExternal = 10; + }; + + loginMethod = channel: + transformField "L" (optionalString (channel.loginMethod != null) + (toString loginMethodMap.${channel.loginMethod})); + + # Note: Missing option `D=`. + transformChannel = channelName: + let channel = cfg.channels.${channelName}; + in concatStringsSep "\n" (remove null [ + "" # leave a space between one server and another + (transformField "N" channelName) + (loginMethod channel) + (transformField "E" channel.charset) + (transformField "F" (computeFieldsValue channel)) + (transformField "I" channel.nickname) + (transformField "i" channel.nickname2) + (transformField "R" channel.realName) + (transformField "U" channel.userName) + (transformField "P" channel.password) + (listChar "S" channel.servers) + (listChar "J" channel.autojoin) + (listChar "C" channel.commands) + ]); + +in { + meta.maintainers = with maintainers; [ thiagokokada ]; + + options.programs.hexchat = with types; { + enable = mkEnableOption "HexChat, a graphical IRC client"; + + channels = mkOption { + type = attrsOf modChannelOption; + default = { }; + example = literalExpression '' + { + freenode = { + autojoin = [ + "#home-manager" + "#linux" + "#nixos" + ]; + charset = "UTF-8 (Unicode)"; + commands = [ + "ECHO Buzz Lightyear sent you a message: 'To Infinity... and Beyond!'" + ]; + loginMethod = sasl; + nickname = "my_nickname"; + nickname2 = "my_secondchoice"; + options = { + acceptInvalidSSLCertificates = false; + autoconnect = true; + bypassProxy = true; + connectToSelectedServerOnly = true; + useGlobalUserInformation = false; + forceSSL = false; + }; + password = "my_password"; + realName = "my_realname"; + servers = [ + "chat.freenode.net" + "irc.freenode.net" + ]; + userName = "my_username"; + }; + }''; + description = '' + Configures $XDG_CONFIG_HOME/hexchat/servlist.conf. + ''; + }; + + settings = mkOption { + default = null; + type = nullOr (attrsOf str); + example = literalExpression '' + { + irc_nick1 = "mynick"; + irc_username = "bob"; + irc_realname = "Bart Simpson"; + text_font = "Monospace 14"; + }; + ''; + description = '' + Configuration for $XDG_CONFIG_HOME/hexchat/hexchat.conf, see + + for supported values. + ''; + }; + + overwriteConfigFiles = mkOption { + type = nullOr bool; + default = false; + description = '' + Enables overwriting HexChat configuration files + (hexchat.conf, servlist.conf). + Any existing HexChat configuration will be lost. Certify to back-up any + previous configuration before enabling this. + + Enabling this setting is recommended, because everytime HexChat + application is closed it overwrites Nix/Home Manager provided + configuration files, causing: + + + Nix/Home Manager provided configuration to be out of sync with + actual active HexChat configuration. + + + Blocking Nix/Home Manager updates until configuration files are + manually removed. + + + ''; + }; + + theme = mkOption { + type = nullOr package; + default = null; + example = literalExpression '' + source = pkgs.fetchzip { + url = "https://dl.hexchat.net/themes/Monokai.hct#Monokai.zip"; + sha256 = "sha256-WCdgEr8PwKSZvBMs0fN7E2gOjNM0c2DscZGSKSmdID0="; + stripRoot = false; + }; + ''; + description = '' + Theme package for HexChat. Expects a derivation containing decompressed + theme files. Note, .hct files are actually ZIP files, + as seen in example. + ''; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (hm.assertions.assertPlatform "programs.hexchat" pkgs platforms.linux) + ]; + + home.packages = [ pkgs.hexchat ]; + + xdg.configFile."hexchat" = mkIf (cfg.theme != null) { + source = cfg.theme; + recursive = true; + }; + + xdg.configFile."hexchat/hexchat.conf" = mkIf (cfg.settings != null) { + force = cfg.overwriteConfigFiles; + text = concatMapStringsSep "\n" (x: x + " = " + cfg.settings.${x}) + (attrNames cfg.settings); + }; + + xdg.configFile."hexchat/servlist.conf" = mkIf (cfg.channels != { }) { + force = cfg.overwriteConfigFiles; + # Final line breaks is required to avoid cropping last field value. + text = concatMapStringsSep "\n" transformChannel (attrNames cfg.channels) + + "\n\n"; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/himalaya.nix b/infra/libkookie/home-manager-stable/modules/programs/himalaya.nix new file mode 100644 index 00000000000..1faee820260 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/himalaya.nix @@ -0,0 +1,107 @@ +{ config, lib, pkgs, ... }: +let + cfg = config.programs.himalaya; + + enabledAccounts = + lib.filterAttrs (_: a: a.himalaya.enable) (config.accounts.email.accounts); + + tomlFormat = pkgs.formats.toml { }; + + himalayaConfig = let + toHimalayaConfig = account: + { + email = account.address; + name = account.realName; + default = account.primary; + + mailboxes = { + inbox = account.folders.inbox; + sent = account.folders.sent; + draft = account.folders.drafts; + # NOTE: himalaya does not support configuring the name of the trash folder + }; + + # FIXME: does not support disabling TLS altogether + # NOTE: does not accept sequence of strings for password commands + imap-login = account.userName; + imap-passwd-cmd = lib.escapeShellArgs account.passwordCommand; + imap-host = account.imap.host; + imap-port = account.imap.port; + imap-starttls = account.imap.tls.useStartTls; + + smtp-login = account.userName; + smtp-passwd-cmd = lib.escapeShellArgs account.passwordCommand; + smtp-host = account.smtp.host; + smtp-port = account.smtp.port; + smtp-starttls = account.smtp.tls.useStartTls; + } // (lib.optionalAttrs (account.signature.showSignature == "append") { + # FIXME: signature cannot be attached + signature = account.signature.text; + }) // account.himalaya.settings; + in { + # NOTE: will not start without this configured, but each account overrides it + name = ""; + } // cfg.settings // (lib.mapAttrs (_: toHimalayaConfig) enabledAccounts); +in { + meta.maintainers = with lib.hm.maintainers; [ ambroisie ]; + + options = with lib; { + programs.himalaya = { + enable = mkEnableOption "himalaya mail client"; + + package = mkOption { + type = types.package; + default = pkgs.himalaya; + defaultText = literalExpression "pkgs.himalaya"; + description = '' + Package providing the himalaya mail client. + ''; + }; + + settings = mkOption { + type = tomlFormat.type; + default = { }; + example = lib.literalExpression '' + { + default-page-size = 50; + } + ''; + description = '' + Global himalaya configuration values. + ''; + }; + }; + + accounts.email.accounts = mkOption { + type = with types; + attrsOf (submodule { + options.himalaya = { + enable = mkEnableOption '' + the himalaya mail client for this account + ''; + + settings = mkOption { + type = tomlFormat.type; + default = { }; + example = lib.literalExpression '' + { + default-page-size = 50; + } + ''; + description = '' + Extra settings to add to this himalaya + account configuration. + ''; + }; + }; + }); + }; + }; + + config = lib.mkIf cfg.enable { + home.packages = [ cfg.package ]; + + xdg.configFile."himalaya/config.toml".source = + tomlFormat.generate "himalaya-config.toml" himalayaConfig; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/home-manager.nix b/infra/libkookie/home-manager-stable/modules/programs/home-manager.nix new file mode 100644 index 00000000000..cc760baf4d0 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/home-manager.nix @@ -0,0 +1,35 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.home-manager; + +in { + meta.maintainers = [ maintainers.rycee ]; + + options = { + programs.home-manager = { + enable = mkEnableOption "Home Manager"; + + path = mkOption { + type = types.nullOr types.str; + default = null; + example = "$HOME/devel/home-manager"; + description = '' + The default path to use for Home Manager. If this path does + not exist then + $HOME/.config/nixpkgs/home-manager and + $HOME/.nixpkgs/home-manager will be + attempted. + ''; + }; + }; + }; + + config = mkIf (cfg.enable && !config.submoduleSupport.enable) { + home.packages = + [ (pkgs.callPackage ../../home-manager { inherit (cfg) path; }) ]; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/htop.nix b/infra/libkookie/home-manager-stable/modules/programs/htop.nix new file mode 100644 index 00000000000..7141ff34a00 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/htop.nix @@ -0,0 +1,193 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + inherit (pkgs.stdenv.hostPlatform) isDarwin; + + cfg = config.programs.htop; + + formatOption = n: v: + let v' = if isBool v then (if v then "1" else "0") else toString v; + in "${n}=${v'}"; + + formatMeters = side: meters: { + "${side}_meters" = concatMap (mapAttrsToList (x: _: x)) meters; + "${side}_meter_modes" = concatMap (mapAttrsToList (_: y: y)) meters; + }; + leftMeters = formatMeters "left"; + rightMeters = formatMeters "right"; + + fields = { + PID = 0; + COMM = 1; + STATE = 2; + PPID = 3; + PGRP = 4; + SESSION = 5; + TTY_NR = 6; + TPGID = 7; + MINFLT = 9; + MAJFLT = 11; + PRIORITY = 17; + NICE = 18; + STARTTIME = 20; + PROCESSOR = 37; + M_SIZE = 38; + M_RESIDENT = 39; + ST_UID = 45; + PERCENT_CPU = 46; + PERCENT_MEM = 47; + USER = 48; + TIME = 49; + NLWP = 50; + TGID = 51; + CMINFLT = 10; + CMAJFLT = 12; + UTIME = 13; + STIME = 14; + CUTIME = 15; + CSTIME = 16; + M_SHARE = 40; + M_TRS = 41; + M_DRS = 42; + M_LRS = 43; + M_DT = 44; + CTID = 99; + VPID = 100; + VXID = 102; + RCHAR = 102; + WCHAR = 103; + SYSCR = 104; + SYSCW = 105; + RBYTES = 106; + WBYTES = 107; + CNCLWB = 108; + IO_READ_RATE = 109; + IO_WRITE_RATE = 110; + IO_RATE = 111; + CGROUP = 112; + OOM = 113; + IO_PRIORITY = 114; + M_PSS = 118; + M_SWAP = 119; + M_PSSWP = 120; + }; + + defaultFields = with fields; [ + PID + USER + PRIORITY + NICE + M_SIZE + M_RESIDENT + M_SHARE + STATE + PERCENT_CPU + PERCENT_MEM + TIME + COMM + ]; + + modes = { + Bar = 1; + Text = 2; + Graph = 3; + LED = 4; + }; + + # Utilities for constructing meters + meter = mode: name: { ${name} = mode; }; + bar = meter modes.Bar; + text = meter modes.Text; + graph = meter modes.Graph; + led = meter modes.LED; + blank = text "Blank"; + +in { + meta.maintainers = [ hm.maintainers.bjpbakker ]; + + options.programs.htop = { + enable = mkEnableOption "htop"; + + settings = mkOption { + type = types.attrs; + default = { }; + example = literalExpression '' + { + color_scheme = 6; + cpu_count_from_one = 0; + delay = 15; + fields = with config.lib.htop.fields; [ + PID + USER + PRIORITY + NICE + M_SIZE + M_RESIDENT + M_SHARE + STATE + PERCENT_CPU + PERCENT_MEM + TIME + COMM + ]; + highlight_base_name = 1; + highlight_megabytes = 1; + highlight_threads = 1; + } // (with config.lib.htop; leftMeters [ + (bar "AllCPUs2") + (bar "Memory") + (bar "Swap") + (text "Zram") + ]) // (with config.lib.htop; rightMeters [ + (text "Tasks") + (text "LoadAverage") + (text "Uptime") + (text "Systemd") + ]); + ''; + description = '' + Configuration options to add to + $XDG_CONFIG_HOME/htop/htoprc. + ''; + }; + + package = mkOption { + type = types.package; + default = pkgs.htop; + defaultText = literalExpression "pkgs.htop"; + description = "Package containing the htop program."; + }; + }; + + config = mkIf cfg.enable { + lib.htop = { + inherit fields modes leftMeters rightMeters bar text graph led blank; + }; + + home.packages = [ cfg.package ]; + + xdg.configFile."htop/htoprc" = let + defaults = { + fields = if isDarwin then + remove fields.M_SHARE defaultFields + else + defaultFields; + }; + + before = optionalAttrs (cfg.settings ? header_layout) { + inherit (cfg.settings) header_layout; + }; + + settings = defaults // (removeAttrs cfg.settings (attrNames before)); + + formatOptions = mapAttrsToList formatOption; + + in mkIf (cfg.settings != { }) { + text = + concatStringsSep "\n" (formatOptions before ++ formatOptions settings) + + "\n"; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/i3status-rust.nix b/infra/libkookie/home-manager-stable/modules/programs/i3status-rust.nix new file mode 100644 index 00000000000..33f2b146dc8 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/i3status-rust.nix @@ -0,0 +1,267 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.i3status-rust; + + settingsFormat = pkgs.formats.toml { }; + +in { + meta.maintainers = [ maintainers.farlion ]; + + options.programs.i3status-rust = { + enable = mkEnableOption "a replacement for i3-status written in Rust"; + + bars = mkOption { + type = types.attrsOf (types.submodule { + options = { + + blocks = mkOption { + type = settingsFormat.type; + default = [ + { + block = "disk_space"; + path = "/"; + alias = "/"; + info_type = "available"; + unit = "GB"; + interval = 60; + warning = 20.0; + alert = 10.0; + } + { + block = "memory"; + display_type = "memory"; + format_mem = "{mem_used_percents}"; + format_swap = "{swap_used_percents}"; + } + { + block = "cpu"; + interval = 1; + } + { + block = "load"; + interval = 1; + format = "{1m}"; + } + { block = "sound"; } + { + block = "time"; + interval = 60; + format = "%a %d/%m %R"; + } + ]; + description = '' + Configuration blocks to add to i3status-rust + config. See + + for block options. + ''; + example = literalExpression '' + [ + { + block = "disk_space"; + path = "/"; + alias = "/"; + info_type = "available"; + unit = "GB"; + interval = 60; + warning = 20.0; + alert = 10.0; + } + { + block = "sound"; + format = "{output_name} {volume}%"; + on_click = "pavucontrol --tab=3"; + mappings = { + "alsa_output.pci-0000_00_1f.3.analog-stereo" = ""; + "bluez_sink.70_26_05_DA_27_A4.a2dp_sink" = ""; + }; + } + ]; + ''; + }; + + settings = mkOption { + type = settingsFormat.type; + default = { }; + description = '' + Any extra options to add to i3status-rust + config. + ''; + example = literalExpression '' + { + theme = { + name = "solarized-dark"; + overrides = { + idle_bg = "#123456"; + idle_fg = "#abcdef"; + }; + }; + } + ''; + }; + + icons = mkOption { + type = types.str; + default = "none"; + description = '' + The icons set to use. See + + for a list of available icon sets. + ''; + example = "awesome5"; + }; + + theme = mkOption { + type = types.str; + default = "plain"; + description = '' + The theme to use. See + + for a list of available themes. + ''; + example = "gruvbox-dark"; + }; + }; + }); + + default = { + default = { + blocks = [ + { + block = "disk_space"; + path = "/"; + alias = "/"; + info_type = "available"; + unit = "GB"; + interval = 60; + warning = 20.0; + alert = 10.0; + } + { + block = "memory"; + display_type = "memory"; + format_mem = "{mem_used_percents}"; + format_swap = "{swap_used_percents}"; + } + { + block = "cpu"; + interval = 1; + } + { + block = "load"; + interval = 1; + format = "{1m}"; + } + { block = "sound"; } + { + block = "time"; + interval = 60; + format = "%a %d/%m %R"; + } + ]; + }; + }; + description = '' + Attribute set of i3status-rust bars, each with their own configuration. + Each bar name generates a config file suffixed with + the bar's name from the attribute set, like so: + config-name.toml. + + This way, multiple config files can be generated, such as for having a + top and a bottom bar. + + See + + i3status-rust + 1 + + for options. + ''; + example = literalExpression '' + bottom = { + blocks = [ + { + block = "disk_space"; + path = "/"; + alias = "/"; + info_type = "available"; + unit = "GB"; + interval = 60; + warning = 20.0; + alert = 10.0; + } + { + block = "memory"; + display_type = "memory"; + format_mem = "{mem_used_percents}"; + format_swap = "{swap_used_percents}"; + } + { + block = "cpu"; + interval = 1; + } + { + block = "load"; + interval = 1; + format = "{1m}"; + } + { block = "sound"; } + { + block = "time"; + interval = 60; + format = "%a %d/%m %R"; + } + ]; + settings = { + theme = { + name = "solarized-dark"; + overrides = { + idle_bg = "#123456"; + idle_fg = "#abcdef"; + }; + }; + }; + icons = "awesome5"; + theme = "gruvbox-dark"; + }; + ''; + }; + + package = mkOption { + type = types.package; + default = pkgs.i3status-rust; + defaultText = literalExpression "pkgs.i3status-rust"; + description = "Package providing i3status-rust"; + }; + + }; + + config = mkIf cfg.enable { + assertions = [ + (hm.assertions.assertPlatform "programs.i3status-rust" pkgs + platforms.linux) + ]; + + home.packages = [ cfg.package ]; + + xdg.configFile = mapAttrs' (cfgFileSuffix: cfg: + nameValuePair ("i3status-rust/config-${cfgFileSuffix}.toml") ({ + onChange = mkIf config.xsession.windowManager.i3.enable '' + i3Socket="''${XDG_RUNTIME_DIR:-/run/user/$UID}/i3/ipc-socket.*" + if [[ -S $i3Socket ]]; then + ${config.xsession.windowManager.i3.package}/bin/i3-msg -s $i3Socket restart >/dev/null + fi + ''; + + source = settingsFormat.generate ("config-${cfgFileSuffix}.toml") ({ + theme = cfg.theme; + icons = cfg.icons; + block = cfg.blocks; + } // cfg.settings); + })) cfg.bars; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/i3status.nix b/infra/libkookie/home-manager-stable/modules/programs/i3status.nix new file mode 100644 index 00000000000..ca1f133e489 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/i3status.nix @@ -0,0 +1,208 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.programs.i3status; + + enabledModules = filterAttrs (n: v: v.enable) cfg.modules; + + formatOrder = n: ''order += "${n}"''; + + formatModule = n: v: + let + formatLine = n: v: + let + formatValue = v: + if isBool v then + (if v then "true" else "false") + else if isString v then + ''"${v}"'' + else + toString v; + in "${n} = ${formatValue v}"; + in '' + ${n} { + ${concatStringsSep "\n " (mapAttrsToList formatLine v)} + } + ''; + + settingsType = with types; attrsOf (oneOf [ bool int str ]); + + sortAttrNamesByPosition = comparator: set: + let pos = n: set."${n}".position; + in sort (a: b: comparator (pos a) (pos b)) (attrNames set); +in { + meta.maintainers = [ hm.maintainers.justinlovinger ]; + + options.programs.i3status = { + enable = mkEnableOption "i3status"; + + enableDefault = mkOption { + type = types.bool; + default = true; + description = '' + Whether or not to enable + the default configuration. + ''; + }; + + general = mkOption { + type = settingsType; + default = { }; + description = '' + Configuration to add to i3status config + general section. + See + + i3status + 1 + + for options. + ''; + example = literalExpression '' + { + colors = true; + color_good = "#e0e0e0"; + color_degraded = "#d7ae00"; + color_bad = "#f69d6a"; + interval = 1; + } + ''; + }; + + modules = mkOption { + type = types.attrsOf (types.submodule { + options = { + enable = mkOption { + type = types.bool; + default = true; + description = '' + Whether or not to enable this module. + ''; + }; + position = mkOption { + type = with types; either int float; + description = '' + Position of this module in i3status order. + ''; + }; + settings = mkOption { + type = settingsType; + default = { }; + description = '' + Configuration to add to this i3status module. + See + + i3status + 1 + + for options. + ''; + example = literalExpression '' + { + format = "♪ %volume"; + format_muted = "♪ muted (%volume)"; + device = "pulse:1"; + } + ''; + }; + }; + }); + default = { }; + description = '' + Modules to add to i3status config file. + See + + i3status + 1 + + for options. + ''; + example = literalExpression '' + { + "volume master" = { + position = 1; + settings = { + format = "♪ %volume"; + format_muted = "♪ muted (%volume)"; + device = "pulse:1"; + }; + }; + "disk /" = { + position = 2; + settings = { + format = "/ %avail"; + }; + }; + } + ''; + }; + }; + + config = mkIf cfg.enable { + programs.i3status = mkIf cfg.enableDefault { + general = { + colors = mkDefault true; + interval = mkDefault 5; + }; + + modules = { + ipv6 = { position = mkDefault 1; }; + + "wireless _first_" = { + position = mkDefault 2; + settings = { + format_up = mkDefault "W: (%quality at %essid) %ip"; + format_down = mkDefault "W: down"; + }; + }; + + "ethernet _first_" = { + position = mkDefault 3; + settings = { + format_up = mkDefault "E: %ip (%speed)"; + format_down = mkDefault "E: down"; + }; + }; + + "battery all" = { + position = mkDefault 4; + settings = { format = mkDefault "%status %percentage %remaining"; }; + }; + + "disk /" = { + position = mkDefault 5; + settings = { format = mkDefault "%avail"; }; + }; + + load = { + position = mkDefault 6; + settings = { format = mkDefault "%1min"; }; + }; + + memory = { + position = mkDefault 7; + settings = { + format = mkDefault "%used | %available"; + threshold_degraded = mkDefault "1G"; + format_degraded = mkDefault "MEMORY < %available"; + }; + }; + + "tztime local" = { + position = mkDefault 8; + settings = { format = mkDefault "%Y-%m-%d %H:%M:%S"; }; + }; + }; + }; + + home.packages = [ pkgs.i3status ]; + + xdg.configFile."i3status/config".text = concatStringsSep "\n" ([ ] + ++ optional (cfg.general != { }) (formatModule "general" cfg.general) + ++ map formatOrder (sortAttrNamesByPosition lessThan enabledModules) + ++ mapAttrsToList formatModule + (mapAttrs (n: v: v.settings) enabledModules)); + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/info.nix b/infra/libkookie/home-manager-stable/modules/programs/info.nix new file mode 100644 index 00000000000..a7d2692b515 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/info.nix @@ -0,0 +1,63 @@ +# info.nix -- install texinfo and create `dir` file + +# This is a helper for the GNU info documentation system. By default, +# the `info` command (and the Info subsystem within Emacs) gives easy +# access to the info files stored system-wide, but not info files in +# your ~/.nix-profile. + +# Specifically, although info can then find files when you explicitly +# ask for them, it doesn't show them to you in the table of contents +# on startup. To do that requires a `dir` file. NixOS keeps the +# system-wide `dir` file up to date, but ignores files installed in +# user profiles. + +# This module contains extra profile commands that generate the `dir` +# for your home profile. Then when you start info (and both `dir` +# files are in your $INFOPATH), it will *merge* the contents of the +# two files, showing you a unified table of contents for all packages. +# This is really nice. + +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.info; + + # Installs this package -- the interactive just means that it + # includes the curses `info` program. We also use `install-info` + # from this package in the activation script. + infoPkg = pkgs.texinfoInteractive; + +in { + imports = [ + (mkRemovedOptionModule [ "programs" "info" "homeInfoDirLocation" ] '' + The `dir` file is now generated as part of the Home Manager profile and + will no longer be placed in your home directory. + '') + ]; + + options.programs.info.enable = mkEnableOption "GNU Info"; + + config = mkIf cfg.enable { + home.packages = [ + infoPkg + + # Make sure the target directory is a real directory. + (pkgs.runCommandLocal "dummy-info-dir1" { } "mkdir -p $out/share/info") + (pkgs.runCommandLocal "dummy-info-dir2" { } "mkdir -p $out/share/info") + ]; + + home.extraOutputsToInstall = [ "info" ]; + + home.extraProfileCommands = let infoPath = "$out/share/info"; + in '' + if [[ -w "${infoPath}" && ! -e "${infoPath}/dir" ]]; then + PATH="${lib.makeBinPath [ pkgs.gzip infoPkg ]}''${PATH:+:}$PATH" \ + find -L "${infoPath}" \( -name '*.info' -o -name '*.info.gz' \) \ + -exec install-info '{}' "${infoPath}/dir" ';' + fi + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/ion.nix b/infra/libkookie/home-manager-stable/modules/programs/ion.nix new file mode 100644 index 00000000000..0bda85c01e1 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/ion.nix @@ -0,0 +1,59 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.programs.ion; + + aliasesStr = concatStringsSep "\n" + (mapAttrsToList (k: v: "alias ${k} = ${escapeShellArg v}") + cfg.shellAliases); +in { + meta.maintainers = [ maintainers.jo1gi ]; + + options.programs.ion = { + enable = mkEnableOption "the Ion Shell. Compatible with Redox and Linux"; + + package = mkOption { + type = types.package; + default = pkgs.ion; + defaultText = literalExpression "pkgs.ion"; + description = '' + The ion package to install. May be used to change the version. + ''; + }; + + initExtra = mkOption { + type = types.lines; + default = ""; + description = '' + Ion script which is called during ion initialization. + ''; + }; + + shellAliases = mkOption { + type = with types; attrsOf str; + default = { }; + example = literalExpression '' + { + g = "git"; + } + ''; + description = '' + An attribute set that maps aliases (the top level attribute names + in this option) to command strings or directly to build outputs. + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + + xdg.configFile."ion/initrc".text = '' + # Aliases + ${aliasesStr} + + ${cfg.initExtra} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/irssi.nix b/infra/libkookie/home-manager-stable/modules/programs/irssi.nix new file mode 100644 index 00000000000..3d830a4f183 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/irssi.nix @@ -0,0 +1,222 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.irssi; + + quoteStr = s: escape [ ''"'' ] s; + + # Comma followed by newline. + cnl = '' + , + ''; + + assignFormat = set: + concatStringsSep "\n" + (mapAttrsToList (k: v: " ${k} = \"${quoteStr v}\";") set); + + chatnetString = concatStringsSep "\n" (flip mapAttrsToList cfg.networks + (k: v: '' + ${k} = { + type = "${v.type}"; + nick = "${quoteStr v.nick}"; + autosendcmd = "${concatMapStringsSep ";" quoteStr v.autoCommands}"; + }; + '')); + + serversString = concatStringsSep cnl (flip mapAttrsToList cfg.networks + (k: v: '' + { + chatnet = "${k}"; + address = "${v.server.address}"; + port = "${toString v.server.port}"; + use_ssl = "${lib.hm.booleans.yesNo v.server.ssl.enable}"; + ssl_verify = "${lib.hm.booleans.yesNo v.server.ssl.verify}"; + autoconnect = "${lib.hm.booleans.yesNo v.server.autoConnect}"; + ${ + lib.optionalString (v.server.ssl.certificateFile != null) '' + ssl_cert = "${v.server.ssl.certificateFile}"; + '' + } + } + '')); + + channelString = concatStringsSep cnl (concatLists + (flip mapAttrsToList cfg.networks (k: v: + (flip mapAttrsToList v.channels (c: cv: '' + { + chatnet = "${k}"; + name = "${c}"; + autojoin = "${lib.hm.booleans.yesNo cv.autoJoin}"; + } + ''))))); + + channelType = types.submodule { + options = { + name = mkOption { + type = types.nullOr types.str; + visible = false; + default = null; + description = "Name of the channel."; + }; + + autoJoin = mkOption { + type = types.bool; + default = false; + description = "Whether to join this channel on connect."; + }; + }; + }; + + networkType = types.submodule ({ name, ... }: { + options = { + name = mkOption { + visible = false; + default = name; + type = types.str; + }; + + nick = mkOption { + type = types.str; + description = "Nickname in that network."; + }; + + type = mkOption { + type = types.str; + description = "Type of the network."; + default = "IRC"; + }; + + autoCommands = mkOption { + type = types.listOf types.str; + default = [ ]; + description = "List of commands to execute on connect."; + }; + + server = { + address = mkOption { + type = types.str; + description = "Address of the chat server."; + }; + + port = mkOption { + type = types.port; + default = 6667; + description = "Port of the chat server."; + }; + + ssl = { + enable = mkOption { + type = types.bool; + default = true; + description = "Whether SSL should be used."; + }; + + verify = mkOption { + type = types.bool; + default = true; + description = "Whether the SSL certificate should be verified."; + }; + + certificateFile = mkOption { + type = types.nullOr types.path; + default = null; + description = '' + Path to a file containing the certificate used for + client authentication to the server. + ''; + }; + }; + + autoConnect = mkOption { + type = types.bool; + default = false; + description = "Whether Irssi connects to the server on launch."; + }; + }; + + channels = mkOption { + description = "Channels for the given network."; + type = types.attrsOf channelType; + default = { }; + }; + }; + }); + +in { + + options = { + programs.irssi = { + enable = mkEnableOption "the Irssi chat client"; + + extraConfig = mkOption { + default = ""; + description = "These lines are appended to the Irssi configuration."; + type = types.lines; + }; + + aliases = mkOption { + default = { }; + example = { + J = "join"; + BYE = "quit"; + }; + description = "An attribute set that maps aliases to commands."; + type = types.attrsOf types.str; + }; + + networks = mkOption { + default = { }; + example = literalExpression '' + { + freenode = { + nick = "hmuser"; + server = { + address = "chat.freenode.net"; + port = 6697; + autoConnect = true; + }; + channels = { + nixos.autoJoin = true; + }; + }; + } + ''; + description = "An attribute set of chat networks."; + type = types.attrsOf networkType; + }; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ pkgs.irssi ]; + + home.file.".irssi/config".text = '' + settings = { + core = { + settings_autosave = "no"; + }; + }; + + aliases = { + ${assignFormat cfg.aliases} + }; + + chatnets = { + ${chatnetString} + }; + + servers = ( + ${serversString} + ); + + channels = ( + ${channelString} + ); + + ${cfg.extraConfig} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/java.nix b/infra/libkookie/home-manager-stable/modules/programs/java.nix new file mode 100644 index 00000000000..5b2a0129961 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/java.nix @@ -0,0 +1,46 @@ +# This module provides JAVA_HOME, with a different way to install java locally. +# This module is modified from the NixOS module `programs.java` + +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.java; + +in { + meta.maintainers = with maintainers; [ ShamrockLee ]; + + options = { + programs.java = { + enable = mkEnableOption "" // { + description = '' + Install the Java development kit and set the JAVA_HOME + variable. + ''; + }; + + package = mkOption { + type = types.package; + default = pkgs.jdk; + defaultText = "pkgs.jdk"; + description = '' + Java package to install. Typical values are + pkgs.jdk or pkgs.jre. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + + home.sessionVariables = { + JAVA_HOME = fileContents (pkgs.runCommandLocal "java-home" { } '' + source "${cfg.package}/nix-support/setup-hook" + echo "$JAVA_HOME" > $out + ''); + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/jq.nix b/infra/libkookie/home-manager-stable/modules/programs/jq.nix new file mode 100644 index 00000000000..e810f88451a --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/jq.nix @@ -0,0 +1,83 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.jq; + + colorType = mkOption { + type = types.str; + description = "ANSI color definition"; + example = "1;31"; + visible = false; + }; + + colorsType = types.submodule { + options = { + null = colorType; + false = colorType; + true = colorType; + numbers = colorType; + strings = colorType; + arrays = colorType; + objects = colorType; + }; + }; + +in { + options = { + programs.jq = { + enable = mkEnableOption "the jq command-line JSON processor"; + + package = mkOption { + type = types.package; + default = pkgs.jq; + defaultText = literalExpression "pkgs.jq"; + description = "jq package to use."; + }; + + colors = mkOption { + description = '' + The colors used in colored JSON output. + + See . + ''; + + example = literalExpression '' + { + null = "1;30"; + false = "0;31"; + true = "0;32"; + numbers = "0;36"; + strings = "0;33"; + arrays = "1;35"; + objects = "1;37"; + } + ''; + + default = { + null = "1;30"; + false = "0;37"; + true = "0;37"; + numbers = "0;37"; + strings = "0;32"; + arrays = "1;37"; + objects = "1;37"; + }; + + type = colorsType; + }; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + + home.sessionVariables = let c = cfg.colors; + in { + JQ_COLORS = + "${c.null}:${c.false}:${c.true}:${c.numbers}:${c.strings}:${c.arrays}:${c.objects}"; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/just.nix b/infra/libkookie/home-manager-stable/modules/programs/just.nix new file mode 100644 index 00000000000..6d5447c31ef --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/just.nix @@ -0,0 +1,52 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.just; + +in { + meta.maintainers = [ hm.maintainers.maximsmol ]; + + options.programs.just = { + enable = mkEnableOption + "just, a handy way to save and run project-specific commands"; + + package = mkOption { + type = types.package; + default = pkgs.just; + defaultText = literalExpression "pkgs.just"; + description = "Package providing the just tool."; + }; + + enableBashIntegration = mkEnableOption "Bash integration" // { + default = true; + }; + + enableZshIntegration = mkEnableOption "Zsh integration" // { + default = true; + }; + + enableFishIntegration = mkEnableOption "Fish integration" // { + default = true; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + + programs.bash.initExtra = mkIf cfg.enableBashIntegration '' + source ${cfg.package}/share/bash-completion/completions/just.bash + ''; + + programs.zsh.initExtra = mkIf cfg.enableZshIntegration '' + source ${cfg.package}/share/zsh/site-functions/_just + ''; + + programs.fish.shellInit = mkIf cfg.enableFishIntegration '' + source ${cfg.package}/share/fish/vendor_completions.d/just.fish + ''; + + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/kakoune.nix b/infra/libkookie/home-manager-stable/modules/programs/kakoune.nix new file mode 100644 index 00000000000..495ef8e12e7 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/kakoune.nix @@ -0,0 +1,659 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.kakoune; + + hook = types.submodule { + options = { + name = mkOption { + type = types.enum [ + "NormalBegin" + "NormalIdle" + "NormalEnd" + "NormalKey" + "InsertBegin" + "InsertIdle" + "InsertEnd" + "InsertKey" + "InsertChar" + "InsertDelete" + "InsertMove" + "WinCreate" + "WinClose" + "WinResize" + "WinDisplay" + "WinSetOption" + "BufSetOption" + "BufNewFile" + "BufOpenFile" + "BufCreate" + "BufWritePre" + "BufWritePost" + "BufReload" + "BufClose" + "BufOpenFifo" + "BufReadFifo" + "BufCloseFifo" + "RuntimeError" + "ModeChange" + "PromptIdle" + "GlobalSetOption" + "KakBegin" + "KakEnd" + "FocusIn" + "FocusOut" + "RawKey" + "InsertCompletionShow" + "InsertCompletionHide" + "InsertCompletionSelect" + "ModuleLoaded" + ]; + example = "SetOption"; + description = '' + The name of the hook. For a description, see + . + ''; + }; + + once = mkOption { + type = types.bool; + default = false; + description = '' + Remove the hook after running it once. + ''; + }; + + group = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Add the hook to the named group. + ''; + }; + + option = mkOption { + type = types.nullOr types.str; + default = null; + example = "filetype=latex"; + description = '' + Additional option to pass to the hook. + ''; + }; + + commands = mkOption { + type = types.lines; + default = ""; + example = "set-option window indentwidth 2"; + description = '' + Commands to run when the hook is activated. + ''; + }; + }; + }; + + keyMapping = types.submodule { + options = { + mode = mkOption { + type = types.str; + example = "user"; + description = '' + The mode in which the mapping takes effect. + ''; + }; + + docstring = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Optional documentation text to display in info boxes. + ''; + }; + + key = mkOption { + type = types.str; + example = ""; + description = '' + The key to be mapped. See + + for possible values. + ''; + }; + + effect = mkOption { + type = types.str; + example = ":wq"; + description = '' + The sequence of keys to be mapped. + ''; + }; + }; + }; + + configModule = types.submodule { + options = { + colorScheme = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Set the color scheme. To see available schemes, enter + colorscheme at the kakoune prompt. + ''; + }; + + tabStop = mkOption { + type = types.nullOr types.ints.unsigned; + default = null; + description = '' + The width of a tab in spaces. The kakoune default is + 6. + ''; + }; + + indentWidth = mkOption { + type = types.nullOr types.ints.unsigned; + default = null; + description = '' + The width of an indentation in spaces. + The kakoune default is 4. + If 0, a tab will be used instead. + ''; + }; + + incrementalSearch = mkOption { + type = types.bool; + default = true; + description = '' + Execute a search as it is being typed. + ''; + }; + + alignWithTabs = mkOption { + type = types.bool; + default = false; + description = '' + Use tabs for the align command. + ''; + }; + + autoInfo = mkOption { + type = types.nullOr + (types.listOf (types.enum [ "command" "onkey" "normal" ])); + default = null; + example = [ "command" "normal" ]; + description = '' + Contexts in which to display automatic information box. + The kakoune default is [ "command" "onkey" ]. + ''; + }; + + autoComplete = mkOption { + type = types.nullOr (types.listOf (types.enum [ "insert" "prompt" ])); + default = null; + description = '' + Modes in which to display possible completions. + The kakoune default is [ "insert" "prompt" ]. + ''; + }; + + autoReload = mkOption { + type = types.nullOr (types.enum [ "yes" "no" "ask" ]); + default = null; + description = '' + Reload buffers when an external modification is detected. + The kakoune default is "ask". + ''; + }; + + scrollOff = mkOption { + type = types.nullOr (types.submodule { + options = { + lines = mkOption { + type = types.ints.unsigned; + default = 0; + description = '' + The number of lines to keep visible around the cursor. + ''; + }; + + columns = mkOption { + type = types.ints.unsigned; + default = 0; + description = '' + The number of columns to keep visible around the cursor. + ''; + }; + }; + }); + default = null; + description = '' + How many lines and columns to keep visible around the cursor. + ''; + }; + + ui = mkOption { + type = types.nullOr (types.submodule { + options = { + setTitle = mkOption { + type = types.bool; + default = false; + description = '' + Change the title of the terminal emulator. + ''; + }; + + statusLine = mkOption { + type = types.enum [ "top" "bottom" ]; + default = "bottom"; + description = '' + Where to display the status line. + ''; + }; + + assistant = mkOption { + type = types.enum [ "clippy" "cat" "dilbert" "none" ]; + default = "clippy"; + description = '' + The assistant displayed in info boxes. + ''; + }; + + enableMouse = mkOption { + type = types.bool; + default = false; + description = '' + Whether to enable mouse support. + ''; + }; + + changeColors = mkOption { + type = types.bool; + default = true; + description = '' + Change color palette. + ''; + }; + + wheelDownButton = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Button to send for wheel down events. + ''; + }; + + wheelUpButton = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Button to send for wheel up events. + ''; + }; + + shiftFunctionKeys = mkOption { + type = types.nullOr types.ints.unsigned; + default = null; + description = '' + Amount by which shifted function keys are offset. That + is, if the terminal sends F13 for Shift-F1, this + should be 12. + ''; + }; + + useBuiltinKeyParser = mkOption { + type = types.bool; + default = false; + description = '' + Bypass ncurses key parser and use an internal one. + ''; + }; + }; + }); + default = null; + description = '' + Settings for the ncurses interface. + ''; + }; + + showMatching = mkOption { + type = types.bool; + default = false; + description = '' + Highlight the matching char of the character under the + selections' cursor using the MatchingChar + face. + ''; + }; + + wrapLines = mkOption { + type = types.nullOr (types.submodule { + options = { + enable = mkEnableOption "the wrap lines highlighter"; + + word = mkOption { + type = types.bool; + default = false; + description = '' + Wrap at word boundaries instead of codepoint boundaries. + ''; + }; + + indent = mkOption { + type = types.bool; + default = false; + description = '' + Preserve line indentation when wrapping. + ''; + }; + + maxWidth = mkOption { + type = types.nullOr types.ints.unsigned; + default = null; + description = '' + Wrap text at maxWidth, even if the window is wider. + ''; + }; + + marker = mkOption { + type = types.nullOr types.str; + default = null; + example = "⏎"; + description = '' + Prefix wrapped lines with marker text. + If not null, + the marker text will be displayed in the indentation if possible. + ''; + }; + }; + }); + default = null; + description = '' + Settings for the wrap lines highlighter. + ''; + }; + + numberLines = mkOption { + type = types.nullOr (types.submodule { + options = { + enable = mkEnableOption "the number lines highlighter"; + + relative = mkOption { + type = types.bool; + default = false; + description = '' + Show line numbers relative to the main cursor line. + ''; + }; + + highlightCursor = mkOption { + type = types.bool; + default = false; + description = '' + Highlight the cursor line with a separate face. + ''; + }; + + separator = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + String that separates the line number column from the + buffer contents. The kakoune default is + "|". + ''; + }; + }; + }); + default = null; + description = '' + Settings for the number lines highlighter. + ''; + }; + + showWhitespace = mkOption { + type = types.nullOr (types.submodule { + options = { + enable = mkEnableOption "the show whitespace highlighter"; + + lineFeed = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + The character to display for line feeds. + The kakoune default is "¬". + ''; + }; + + space = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + The character to display for spaces. + The kakoune default is "·". + ''; + }; + + nonBreakingSpace = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + The character to display for non-breaking spaces. + The kakoune default is "⍽". + ''; + }; + + tab = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + The character to display for tabs. + The kakoune default is "→". + ''; + }; + + tabStop = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + The character to append to tabs to reach the width of a tabstop. + The kakoune default is " ". + ''; + }; + }; + }); + default = null; + description = '' + Settings for the show whitespaces highlighter. + ''; + }; + + keyMappings = mkOption { + type = types.listOf keyMapping; + default = [ ]; + description = '' + User-defined key mappings. For documentation, see + . + ''; + }; + + hooks = mkOption { + type = types.listOf hook; + default = [ ]; + description = '' + Global hooks. For documentation, see + . + ''; + }; + }; + }; + + kakouneWithPlugins = pkgs.wrapKakoune pkgs.kakoune-unwrapped { + configure = { plugins = cfg.plugins; }; + }; + + configFile = let + wrapOptions = with cfg.config.wrapLines; + concatStrings [ + "${optionalString word " -word"}" + "${optionalString indent " -indent"}" + "${optionalString (marker != null) " -marker ${marker}"}" + "${optionalString (maxWidth != null) " -width ${toString maxWidth}"}" + ]; + + numberLinesOptions = with cfg.config.numberLines; + concatStrings [ + "${optionalString relative " -relative "}" + "${optionalString highlightCursor " -hlcursor"}" + "${optionalString (separator != null) " -separator ${separator}"}" + ]; + + showWhitespaceOptions = with cfg.config.showWhitespace; + let + quoteSep = sep: + if sep == "'" then + ''"'"'' + else if lib.strings.stringLength sep == 1 then + "'${sep}'" + else + sep; # backwards compat, in case sep == "' '", etc. + + in concatStrings [ + (optionalString (tab != null) " -tab ${quoteSep tab}") + (optionalString (tabStop != null) " -tabpad ${quoteSep tabStop}") + (optionalString (space != null) " -spc ${quoteSep space}") + (optionalString (nonBreakingSpace != null) + " -nbsp ${quoteSep nonBreakingSpace}") + (optionalString (lineFeed != null) " -lf ${quoteSep lineFeed}") + ]; + + uiOptions = with cfg.config.ui; + concatStringsSep " " [ + "terminal_set_title=${if setTitle then "true" else "false"}" + "terminal_status_on_top=${ + if (statusLine == "top") then "true" else "false" + }" + "terminal_assistant=${assistant}" + "terminal_enable_mouse=${if enableMouse then "true" else "false"}" + "terminal_change_colors=${if changeColors then "true" else "false"}" + "${optionalString (wheelDownButton != null) + "terminal_wheel_down_button=${wheelDownButton}"}" + "${optionalString (wheelUpButton != null) + "terminal_wheel_up_button=${wheelUpButton}"}" + "${optionalString (shiftFunctionKeys != null) + "terminal_shift_function_key=${toString shiftFunctionKeys}"}" + "terminal_builtin_key_parser=${ + if useBuiltinKeyParser then "true" else "false" + }" + ]; + + userModeString = mode: + optionalString (!builtins.elem mode [ + "insert" + "normal" + "prompt" + "menu" + "user" + "goto" + "view" + "object" + ]) "try %{declare-user-mode ${mode}}"; + + userModeStrings = map userModeString + (lists.unique (map (km: km.mode) cfg.config.keyMappings)); + + keyMappingString = km: + concatStringsSep " " [ + "map global" + "${km.mode} ${km.key} '${km.effect}'" + "${optionalString (km.docstring != null) + "-docstring '${km.docstring}'"}" + ]; + + hookString = h: + concatStringsSep " " [ + "hook" + "${optionalString (h.group != null) "-group ${h.group}"}" + "${optionalString (h.once) "-once"}" + "global" + "${h.name}" + "${optionalString (h.option != null) h.option}" + "%{ ${h.commands} }" + ]; + + cfgStr = with cfg.config; + concatStringsSep "\n" ([ "# Generated by home-manager" ] + ++ optional (colorScheme != null) "colorscheme ${colorScheme}" + ++ optional (tabStop != null) + "set-option global tabstop ${toString tabStop}" + ++ optional (indentWidth != null) + "set-option global indentwidth ${toString indentWidth}" + ++ optional (!incrementalSearch) "set-option global incsearch false" + ++ optional (alignWithTabs) "set-option global aligntab true" + ++ optional (autoInfo != null) + "set-option global autoinfo ${concatStringsSep "|" autoInfo}" + ++ optional (autoComplete != null) + "set-option global autocomplete ${concatStringsSep "|" autoComplete}" + ++ optional (autoReload != null) + "set-option global autoreload ${autoReload}" + ++ optional (wrapLines != null && wrapLines.enable) + "add-highlighter global/ wrap${wrapOptions}" + ++ optional (numberLines != null && numberLines.enable) + "add-highlighter global/ number-lines${numberLinesOptions}" + ++ optional showMatching "add-highlighter global/ show-matching" + ++ optional (showWhitespace != null && showWhitespace.enable) + "add-highlighter global/ show-whitespaces${showWhitespaceOptions}" + ++ optional (scrollOff != null) + "set-option global scrolloff ${toString scrollOff.lines},${ + toString scrollOff.columns + }" + + ++ [ "# UI options" ] + ++ optional (ui != null) "set-option global ui_options ${uiOptions}" + + ++ [ "# User modes" ] ++ userModeStrings ++ [ "# Key mappings" ] + ++ map keyMappingString keyMappings + + ++ [ "# Hooks" ] ++ map hookString hooks); + in pkgs.writeText "kakrc" + (optionalString (cfg.config != null) cfgStr + "\n" + cfg.extraConfig); + +in { + options = { + programs.kakoune = { + enable = mkEnableOption "the kakoune text editor"; + + config = mkOption { + type = types.nullOr configModule; + default = { }; + description = "kakoune configuration options."; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Extra configuration lines to add to + $XDG_CONFIG_HOME/kak/kakrc. + ''; + }; + + plugins = mkOption { + type = with types; listOf package; + default = [ ]; + example = literalExpression "[ pkgs.kakounePlugins.kak-fzf ]"; + description = '' + List of kakoune plugins to install. To get a list of + supported plugins run: + nix-env -f '<nixpkgs>' -qaP -A kakounePlugins. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ kakouneWithPlugins ]; + xdg.configFile."kak/kakrc".source = configFile; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/keychain.nix b/infra/libkookie/home-manager-stable/modules/programs/keychain.nix new file mode 100644 index 00000000000..70b74c91df4 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/keychain.nix @@ -0,0 +1,115 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.keychain; + + flags = cfg.extraFlags ++ optional (cfg.agents != [ ]) + "--agents ${concatStringsSep "," cfg.agents}" + ++ optional (cfg.inheritType != null) "--inherit ${cfg.inheritType}"; + + shellCommand = + "${cfg.package}/bin/keychain --eval ${concatStringsSep " " flags} ${ + concatStringsSep " " cfg.keys + }"; + +in { + meta.maintainers = [ maintainers.marsam ]; + + options.programs.keychain = { + enable = mkEnableOption "keychain"; + + package = mkOption { + type = types.package; + default = pkgs.keychain; + defaultText = literalExpression "pkgs.keychain"; + description = '' + Keychain package to install. + ''; + }; + + keys = mkOption { + type = types.listOf types.str; + default = [ "id_rsa" ]; + description = '' + Keys to add to keychain. + ''; + }; + + agents = mkOption { + type = types.listOf types.str; + default = [ ]; + description = '' + Agents to add. + ''; + }; + + inheritType = mkOption { + type = + types.nullOr (types.enum [ "local" "any" "local-once" "any-once" ]); + default = null; + description = '' + Inherit type to attempt from agent variables from the environment. + ''; + }; + + extraFlags = mkOption { + type = types.listOf types.str; + default = [ "--quiet" ]; + description = '' + Extra flags to pass to keychain. + ''; + }; + + enableBashIntegration = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable Bash integration. + ''; + }; + + enableFishIntegration = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable Fish integration. + ''; + }; + + enableZshIntegration = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable Zsh integration. + ''; + }; + + enableXsessionIntegration = mkOption { + default = true; + type = types.bool; + visible = pkgs.stdenv.hostPlatform.isLinux; + description = '' + Whether to run keychain from your ~/.xsession. + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + programs.bash.initExtra = mkIf cfg.enableBashIntegration '' + SHELL=bash eval "$(${shellCommand})" + ''; + programs.fish.interactiveShellInit = mkIf cfg.enableFishIntegration '' + SHELL=fish eval (${shellCommand}) + ''; + programs.zsh.initExtra = mkIf cfg.enableZshIntegration '' + SHELL=zsh eval "$(${shellCommand})" + ''; + xsession.initExtra = mkIf cfg.enableXsessionIntegration '' + eval "$(${shellCommand})" + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/kitty.nix b/infra/libkookie/home-manager-stable/modules/programs/kitty.nix new file mode 100644 index 00000000000..627cc61f6b4 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/kitty.nix @@ -0,0 +1,169 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.kitty; + + eitherStrBoolInt = with types; either str (either bool int); + + optionalPackage = opt: + optional (opt != null && opt.package != null) opt.package; + + toKittyConfig = generators.toKeyValue { + mkKeyValue = key: value: + let + value' = + (if isBool value then lib.hm.booleans.yesNo else toString) value; + in "${key} ${value'}"; + }; + + toKittyKeybindings = generators.toKeyValue { + mkKeyValue = key: command: "map ${key} ${command}"; + }; + + toKittyEnv = + generators.toKeyValue { mkKeyValue = name: value: "env ${name}=${value}"; }; + +in { + options.programs.kitty = { + enable = mkEnableOption "Kitty terminal emulator"; + + package = mkOption { + type = types.package; + default = pkgs.kitty; + defaultText = literalExpression "pkgs.kitty"; + description = '' + Kitty package to install. + ''; + }; + + darwinLaunchOptions = mkOption { + type = types.nullOr (types.listOf types.str); + default = null; + description = "Command-line options to use when launched by Mac OS GUI"; + example = literalExpression '' + [ + "--single-instance" + "--directory=/tmp/my-dir" + "--listen-on=unix:/tmp/my-socket" + ] + ''; + }; + + settings = mkOption { + type = types.attrsOf eitherStrBoolInt; + default = { }; + example = literalExpression '' + { + scrollback_lines = 10000; + enable_audio_bell = false; + update_check_interval = 0; + } + ''; + description = '' + Configuration written to + $XDG_CONFIG_HOME/kitty/kitty.conf. See + + for the documentation. + ''; + }; + + theme = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Apply a Kitty color theme. This option takes the friendly name of + any theme given by the command kitty +kitten themes. + See + for more details. + ''; + example = "Space Gray Eighties"; + }; + + font = mkOption { + type = types.nullOr hm.types.fontType; + default = null; + description = "The font to use."; + }; + + keybindings = mkOption { + type = types.attrsOf types.str; + default = { }; + description = "Mapping of keybindings to actions."; + example = literalExpression '' + { + "ctrl+c" = "copy_or_interrupt"; + "ctrl+f>2" = "set_font_size 20"; + } + ''; + }; + + environment = mkOption { + type = types.attrsOf types.str; + default = { }; + description = "Environment variables to set or override."; + example = literalExpression '' + { + "LS_COLORS" = "1"; + } + ''; + }; + + extraConfig = mkOption { + default = ""; + type = types.lines; + description = "Additional configuration to add."; + }; + }; + + config = mkIf cfg.enable { + assertions = [{ + assertion = (cfg.darwinLaunchOptions != null) + -> pkgs.stdenv.hostPlatform.isDarwin; + message = '' + The 'programs.kitty.darwinLaunchOptions' option is only available on darwin. + ''; + }]; + + home.packages = [ cfg.package ] ++ optionalPackage cfg.font; + + xdg.configFile."kitty/kitty.conf" = { + text = '' + # Generated by Home Manager. + # See https://sw.kovidgoyal.net/kitty/conf.html + + ${optionalString (cfg.font != null) '' + font_family ${cfg.font.name} + ${optionalString (cfg.font.size != null) + "font_size ${toString cfg.font.size}"} + ''} + + ${optionalString (cfg.theme != null) '' + include ${pkgs.kitty-themes}/${ + (head (filter (x: x.name == cfg.theme) (builtins.fromJSON + (builtins.readFile "${pkgs.kitty-themes}/themes.json")))).file + } + ''} + + ${toKittyConfig cfg.settings} + + ${toKittyKeybindings cfg.keybindings} + + ${toKittyEnv cfg.environment} + + ${cfg.extraConfig} + ''; + } // optionalAttrs pkgs.stdenv.hostPlatform.isLinux { + onChange = '' + ${pkgs.procps}/bin/pkill -USR1 -u $USER kitty || true + ''; + }; + + xdg.configFile."kitty/macos-launch-services-cmdline" = + mkIf (cfg.darwinLaunchOptions != null) { + text = concatStringsSep " " cfg.darwinLaunchOptions; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/kodi.nix b/infra/libkookie/home-manager-stable/modules/programs/kodi.nix new file mode 100644 index 00000000000..36169948108 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/kodi.nix @@ -0,0 +1,255 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.programs.kodi; + + stylesheetCommonHeader = '' + + + + + ''; + + stylesheetCommonFooter = ""; + + stylesheetNestedTags = '' + + + + + + + + + + + + + + + + + + + + 1 + + + + + ''; + + stylesheetTagsAsSettingWithId = '' + + + + + + + + + ''; + + stylesheetAdvancedSettingsRootTag = '' + + Generated by Home Manager. + + + + + ''; + + stylesheetSourcesRootTag = '' + + Generated by Home Manager. + + + + + ''; + + stylesheetAddonSettingsRootTag = '' + + Generated by Home Manager. + + + + + ''; + + attrsetToXml = attrs: name: stylesheet: + pkgs.runCommand name { + # Package splicing for libxslt does not work correctly leading to errors + # when cross-compiling. Use the version from buildPackages explicitely to + # fix this. + nativeBuildInputs = [ pkgs.buildPackages.libxslt.bin ]; + xml = builtins.toXML attrs; + passAsFile = [ "xml" ]; + } '' + xsltproc ${stylesheet} - < "$xmlPath" > "$out" + ''; + + attrsetToAdvancedSettingsXml = attrs: name: + let + stylesheet = builtins.toFile "stylesheet.xsl" '' + ${stylesheetCommonHeader} + ${stylesheetAdvancedSettingsRootTag} + ${stylesheetNestedTags} + ${stylesheetCommonFooter} + ''; + in attrsetToXml attrs name stylesheet; + + attrsetToSourcesXml = attrs: name: + let + stylesheet = builtins.toFile "stylesheet.xsl" '' + ${stylesheetCommonHeader} + ${stylesheetSourcesRootTag} + ${stylesheetNestedTags} + ${stylesheetCommonFooter} + ''; + in attrsetToXml attrs name stylesheet; + + attrsetToAddonSettingsXml = attrs: name: + let + stylesheet = builtins.toFile "stylesheet.xsl" '' + ${stylesheetCommonHeader} + ${stylesheetAddonSettingsRootTag} + ${stylesheetTagsAsSettingWithId} + ${stylesheetCommonFooter} + ''; + in attrsetToXml attrs name stylesheet; + +in { + meta.maintainers = [ hm.maintainers.dwagenk ]; + + options.programs.kodi = { + enable = mkEnableOption "Kodi"; + + package = mkOption { + type = types.package; + default = pkgs.kodi; + defaultText = literalExpression "pkgs.kodi"; + example = literalExpression '' + { pkgs.kodi.withPackages (exts: [ exts.pvr-iptvsimple ]) } + ''; + description = '' + The kodi package to use. + Can be used to specify extensions. + ''; + }; + + datadir = mkOption { + type = types.path; + default = "${config.home.homeDirectory}/.kodi"; + defaultText = + literalExpression ''"''${config.home.homeDirectory}/.kodi"''; + example = literalExpression ''"''${config.xdg.dataHome}/kodi"''; + description = "Directory to store configuration and metadata."; + }; + + settings = mkOption { + type = with types; + let + valueType = either str (attrsOf valueType) // { + description = "attribute sets of strings"; + }; + in nullOr valueType; + default = null; + example = literalExpression '' + { videolibrary.showemptytvshows = "true"; } + ''; + description = '' + Configuration to write to the advancedsettings.xml + file in kodis userdata directory. Settings specified here will be + immutable from inside kodi and be hidden from the GUI settings dialog. + + See as + reference for how settings need to be specified. + + The innermost attributes must be of type str. + ''; + }; + + sources = mkOption { + type = with types; + let + valueType = oneOf [ str (attrsOf valueType) (listOf valueType) ] // { + description = "attribute sets or lists of strings"; + }; + in nullOr valueType; + default = null; + example = literalExpression '' + { + video = { + default = "movies"; + source = [ + { name = "videos"; path = "/path/to/videos"; allowsharing = "true"; } + { name = "movies"; path = "/path/to/movies"; allowsharing = "true"; } + ]; + }; + } + ''; + description = '' + Contents to populate the file sources.xml in kodis + userdata directory. + + See as + reference for how sources need to be specified. + + Kodi will still show the dialogs to modify sources in the GUI and they + appear to be mutable. This however is not the case and the sources will + stay as specified via Home Manager. + + The innermost attributes must be of type str. + ''; + }; + + addonSettings = mkOption { + type = with types; nullOr (attrsOf (attrsOf str)); + default = null; + example = literalExpression '' + { "service.xbmc.versioncheck".versioncheck_enable = "false"; } + ''; + description = '' + Attribute set with the plugin namespace as toplevel key and the plugins + settings as lower level key/value pairs. + + Kodi will still show the settings of plugins configured via this + mechanism in the GUI and they appear to be mutable. This however is + not the case and the settings will stay as specified via Home Manager. + ''; + }; + }; + + config = mkIf cfg.enable (mkMerge [ + { + assertions = [ + (lib.hm.assertions.assertPlatform "programs.kodi" pkgs + lib.platforms.linux) + ]; + + home.packages = [ cfg.package ]; + home.sessionVariables = { KODI_DATA = cfg.datadir; }; + } + + (mkIf (cfg.settings != null) { + home.file."${cfg.datadir}/userdata/advancedsettings.xml".source = + attrsetToAdvancedSettingsXml cfg.settings "kodi-advancedsettings.xml"; + }) + + (mkIf (cfg.sources != null) { + home.file."${cfg.datadir}/userdata/sources.xml".source = + attrsetToSourcesXml cfg.sources "kodi-sources.xml"; + }) + + (mkIf (cfg.addonSettings != null) { + home.file = mapAttrs' (k: v: + attrsets.nameValuePair + ("${cfg.datadir}/userdata/addon_data/${k}/settings.xml") { + source = attrsetToAddonSettingsXml v "kodi-addon-${k}-settings.xml"; + }) cfg.addonSettings; + }) + ]); +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/lazygit.nix b/infra/libkookie/home-manager-stable/modules/programs/lazygit.nix new file mode 100644 index 00000000000..1752b151af8 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/lazygit.nix @@ -0,0 +1,56 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.lazygit; + + yamlFormat = pkgs.formats.yaml { }; + + inherit (pkgs.stdenv.hostPlatform) isDarwin; + +in { + meta.maintainers = [ hm.maintainers.kalhauge ]; + + options.programs.lazygit = { + enable = mkEnableOption "lazygit, a simple terminal UI for git commands"; + + settings = mkOption { + type = yamlFormat.type; + default = { }; + defaultText = literalExpression "{ }"; + example = literalExpression '' + { + gui.theme = { + lightTheme = true; + activeBorderColor = [ "blue" "bold" ]; + inactiveBorderColor = [ "black" ]; + selectedLineBgColor = [ "default" ]; + }; + } + ''; + description = '' + Configuration written to + $XDG_CONFIG_HOME/lazygit/config.yml on Linux + or ~/Library/Application Support/lazygit/config.yml on Darwin. See + + for supported values. + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ pkgs.lazygit ]; + + home.file."Library/Application Support/lazygit/config.yml" = + mkIf (cfg.settings != { } && isDarwin) { + source = yamlFormat.generate "lazygit-config" cfg.settings; + }; + + xdg.configFile."lazygit/config.yml" = + mkIf (cfg.settings != { } && !isDarwin) { + source = yamlFormat.generate "lazygit-config" cfg.settings; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/less.nix b/infra/libkookie/home-manager-stable/modules/programs/less.nix new file mode 100644 index 00000000000..9e6e6720120 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/less.nix @@ -0,0 +1,32 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let cfg = config.programs.less; +in { + meta.maintainers = [ maintainers.pamplemousse ]; + + options = { + programs.less = { + enable = mkEnableOption "less, opposite of more"; + + keys = mkOption { + type = types.lines; + default = ""; + example = '' + s back-line + t forw-line + ''; + description = '' + Extra configuration for less written to + $XDG_CONFIG_HOME/lesskey. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ pkgs.less ]; + xdg.configFile."lesskey".text = cfg.keys; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/lesspipe.nix b/infra/libkookie/home-manager-stable/modules/programs/lesspipe.nix new file mode 100644 index 00000000000..a7a51ffe2a2 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/lesspipe.nix @@ -0,0 +1,19 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + meta.maintainers = [ maintainers.rycee ]; + + options = { + programs.lesspipe = { + enable = mkEnableOption "lesspipe preprocessor for less"; + }; + }; + + config = mkIf config.programs.lesspipe.enable { + home.sessionVariables = { + LESSOPEN = "|${pkgs.lesspipe}/bin/lesspipe.sh %s"; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/lf.nix b/infra/libkookie/home-manager-stable/modules/programs/lf.nix new file mode 100644 index 00000000000..8f0a07cb8bb --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/lf.nix @@ -0,0 +1,227 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.programs.lf; + + knownSettings = { + anchorfind = types.bool; + color256 = types.bool; + dircounts = types.bool; + dirfirst = types.bool; + drawbox = types.bool; + globsearch = types.bool; + icons = types.bool; + hidden = types.bool; + ignorecase = types.bool; + ignoredia = types.bool; + incsearch = types.bool; + preview = types.bool; + reverse = types.bool; + smartcase = types.bool; + smartdia = types.bool; + wrapscan = types.bool; + wrapscroll = types.bool; + number = types.bool; + relativenumber = types.bool; + findlen = types.int; + period = types.int; + scrolloff = types.int; + tabstop = types.int; + errorfmt = types.str; + filesep = types.str; + ifs = types.str; + promptfmt = types.str; + shell = types.str; + sortby = types.str; + timefmt = types.str; + ratios = types.str; + info = types.str; + shellopts = types.str; + }; + + lfSettingsType = types.submodule { + options = let + opt = name: type: + mkOption { + type = types.nullOr type; + default = null; + visible = false; + }; + in mapAttrs opt knownSettings; + }; +in { + meta.maintainers = [ hm.maintainers.owm111 ]; + + options = { + programs.lf = { + enable = mkEnableOption "lf"; + + package = mkOption { + type = types.package; + default = pkgs.lf; + defaultText = literalExpression "pkgs.lf"; + description = '' + lf package to use. + ''; + }; + + settings = mkOption { + type = lfSettingsType; + default = { }; + example = { + tabstop = 4; + number = true; + ratios = "1:1:2"; + }; + description = '' + An attribute set of lf settings. The attribute names and corresponding + values must be among the following supported options. + + + ${concatStringsSep "\n" (mapAttrsToList (n: v: '' + + ${n} + ${v.description} + + '') knownSettings)} + + + See the lf documentation for detailed descriptions of these options. + Note, use previewer to set lf's + previewer option, and + extraConfig for any other option not listed above. + All string options are quoted with double quotes. + ''; + }; + + commands = mkOption { + type = with types; attrsOf (nullOr str); + default = { }; + example = { + get-mime-type = ''%xdg-mime query filetype "$f"''; + open = "$$OPENER $f"; + }; + description = '' + Commands to declare. Commands set to null or an empty string are + deleted. + ''; + }; + + keybindings = mkOption { + type = with types; attrsOf (nullOr str); + default = { }; + example = { + gh = "cd ~"; + D = "trash"; + i = "$less $f"; + U = "!du -sh"; + gg = null; + }; + description = + "Keys to bind. Keys set to null or an empty string are deleted."; + }; + + cmdKeybindings = mkOption { + type = with types; attrsOf (nullOr str); + default = { }; + example = literalExpression ''{ "" = "cmd-escape"; }''; + description = '' + Keys to bind to command line commands which can only be one of the + builtin commands. Keys set to null or an empty string are deleted. + ''; + }; + + previewer.source = mkOption { + type = with types; nullOr path; + default = null; + example = literalExpression '' + pkgs.writeShellScript "pv.sh" ''' + #!/bin/sh + + case "$1" in + *.tar*) tar tf "$1";; + *.zip) unzip -l "$1";; + *.rar) unrar l "$1";; + *.7z) 7z l "$1";; + *.pdf) pdftotext "$1" -;; + *) highlight -O ansi "$1" || cat "$1";; + esac + ''' + ''; + description = '' + Script or executable to use to preview files. Sets lf's + previewer option. + ''; + }; + + previewer.keybinding = mkOption { + type = with types; nullOr str; + default = null; + example = "i"; + description = '' + Key to bind to the script at previewer.source and + pipe through less. Setting to null will not bind any key. + ''; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + example = '' + $mkdir -p ~/.trash + ''; + description = "Custom lfrc lines."; + }; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + + xdg.configFile."lf/lfrc".text = let + fmtSetting = k: v: + optionalString (v != null) "set ${ + if isBool v then + "${optionalString (!v) "no"}${k}" + else + "${k} ${if isInt v then toString v else ''"${v}"''}" + }"; + + settingsStr = concatStringsSep "\n" (remove "" (mapAttrsToList fmtSetting + (builtins.intersectAttrs knownSettings cfg.settings))); + + fmtCmdMap = before: k: v: + "${before} ${k}${optionalString (v != null && v != "") " ${v}"}"; + fmtCmd = fmtCmdMap "cmd"; + fmtMap = fmtCmdMap "map"; + fmtCmap = fmtCmdMap "cmap"; + + commandsStr = concatStringsSep "\n" (mapAttrsToList fmtCmd cfg.commands); + keybindingsStr = + concatStringsSep "\n" (mapAttrsToList fmtMap cfg.keybindings); + cmdKeybindingsStr = + concatStringsSep "\n" (mapAttrsToList fmtCmap cfg.cmdKeybindings); + + previewerStr = optionalString (cfg.previewer.source != null) '' + set previewer ${cfg.previewer.source} + ${optionalString (cfg.previewer.keybinding != null) '' + map ${cfg.previewer.keybinding} ''$${cfg.previewer.source} "$f" | less -R + ''} + ''; + in '' + ${settingsStr} + + ${commandsStr} + + ${keybindingsStr} + + ${cmdKeybindingsStr} + + ${previewerStr} + + ${cfg.extraConfig} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/lieer.nix b/infra/libkookie/home-manager-stable/modules/programs/lieer.nix new file mode 100644 index 00000000000..e0369ffc666 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/lieer.nix @@ -0,0 +1,296 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.programs.lieer; + + lieerAccounts = + filter (a: a.lieer.enable) (attrValues config.accounts.email.accounts); + + nonGmailAccounts = + map (a: a.name) (filter (a: a.flavor != "gmail.com") lieerAccounts); + + nonGmailConfigHelp = + map (name: ''accounts.email.accounts.${name}.flavor = "gmail.com";'') + nonGmailAccounts; + + missingNotmuchAccounts = map (a: a.name) + (filter (a: !a.notmuch.enable && a.lieer.notmuchSetupWarning) + lieerAccounts); + + notmuchConfigHelp = + map (name: "accounts.email.accounts.${name}.notmuch.enable = true;") + missingNotmuchAccounts; + + settingsFormat = pkgs.formats.json { }; + + configFile = account: { + name = "${account.maildir.absPath}/.gmailieer.json"; + value.source = settingsFormat.generate "lieer-${account.address}.json" + ({ account = account.address; } // account.lieer.settings); + }; + + settingsOpts = { + drop_non_existing_label = mkOption { + type = types.bool; + default = false; + description = '' + Allow missing labels on the Gmail side to be dropped. + ''; + }; + + file_extension = mkOption { + type = types.str; + default = ""; + example = "mbox"; + description = '' + Extension to include in local file names, which can be useful + for indexing with third-party programs. + ''; + }; + + ignore_empty_history = mkOption { + type = types.bool; + default = false; + description = '' + Work around a Gmail API quirk where an empty change history + is sometimes returned. + + See this + GitHub issue + for more details. + ''; + }; + + ignore_remote_labels = mkOption { + type = types.listOf types.str; + default = [ + "CATEGORY_FORUMS" + "CATEGORY_PROMOTIONS" + "CATEGORY_UPDATES" + "CATEGORY_SOCIAL" + "CATEGORY_PERSONAL" + ]; + description = '' + Set Gmail labels to ignore when syncing from remote labels to + local tags (before translations). + ''; + }; + + ignore_tags = mkOption { + type = types.listOf types.str; + default = [ ]; + description = '' + Set labels to ignore when syncing from local tags to + remote labels (after translations). + ''; + }; + + local_trash_tag = mkOption { + type = types.str; + default = "trash"; + description = '' + Local tag to which the remote Gmail 'TRASH' label is translated. + ''; + }; + + remove_local_messages = mkOption { + type = types.bool; + default = true; + description = '' + Remove local messages that have been deleted on the remote. + ''; + }; + + replace_slash_with_dot = mkOption { + type = types.bool; + default = false; + description = '' + Replace '/' with '.' in Gmail labels. + ''; + }; + + timeout = mkOption { + type = types.ints.unsigned; + default = 600; + description = '' + HTTP timeout in seconds. 0 means forever or system timeout. + ''; + }; + }; + + syncOpts = { + enable = mkEnableOption "lieer synchronization service"; + + frequency = mkOption { + type = types.str; + default = "*:0/5"; + description = '' + How often to synchronize the account. + + This value is passed to the systemd timer configuration as the + onCalendar option. See + + systemd.time + 7 + + for more information about the format. + ''; + }; + }; + + lieerOpts = { + enable = mkEnableOption "lieer Gmail synchronization for notmuch"; + + notmuchSetupWarning = mkOption { + type = types.bool; + default = true; + description = '' + Warn if Notmuch is not also enabled for this account. + + This can safely be disabled if notmuch init + has been used to configure this account outside of Home + Manager. + ''; + }; + + settings = mkOption { + type = types.submodule { + freeformType = settingsFormat.type; + options = settingsOpts; + }; + default = { }; + description = '' + Settings which are applied to .gmailieer.json + for the account. + + See the lieer manual + for documentation of settings not explicitly covered by this module. + ''; + }; + + sync = syncOpts; + }; + + lieerModule = types.submodule { + imports = [ + (mkRenamedOptionModule [ "lieer" "dropNonExistingLabels" ] [ + "lieer" + "settings" + "drop_non_existing_label" + ]) + (mkRenamedOptionModule [ "lieer" "ignoreTagsRemote" ] [ + "lieer" + "settings" + "ignore_remote_labels" + ]) + (mkRenamedOptionModule [ "lieer" "ignoreTagsLocal" ] [ + "lieer" + "settings" + "ignore_tags" + ]) + (mkRenamedOptionModule [ "lieer" "timeout" ] [ + "lieer" + "settings" + "timeout" + ]) + (mkRenamedOptionModule [ "lieer" "replaceSlashWithDot" ] [ + "lieer" + "settings" + "replace_slash_with_dot" + ]) + ]; + + options = { + lieer = lieerOpts; + + warnings = mkOption { + type = types.listOf types.str; + default = [ ]; + internal = true; + visible = false; + }; + }; + }; + + renamedOptions = account: + let prefix = [ "accounts" "email" "accounts" account.name "lieer" ]; + in [ + (mkRenamedOptionModule (prefix ++ [ "dropNonExistingLabels" ]) + (prefix ++ [ "settings" "drop_non_existing_label" ])) + (mkRenamedOptionModule (prefix ++ [ "ignoreTagsRemote" ]) + (prefix ++ [ "settings" "ignore_remote_labels" ])) + (mkRenamedOptionModule (prefix ++ [ "ignoreTagsLocal" ]) + (prefix ++ [ "settings" "ignore_tags" ])) + (mkRenamedOptionModule (prefix ++ [ "timeout" ]) + (prefix ++ [ "settings" "timeout" ])) + (mkRenamedOptionModule (prefix ++ [ "replaceSlashWithDot" ]) + (prefix ++ [ "settings" "replace_slash_with_dot" ])) + ]; + +in { + meta.maintainers = [ maintainers.tadfisher ]; + + options = { + programs.lieer = { + enable = mkEnableOption "lieer Gmail synchronization for notmuch"; + + package = mkOption { + type = types.package; + default = pkgs.gmailieer; + defaultText = "pkgs.gmailieer"; + description = '' + lieer package to use. + ''; + }; + }; + + accounts.email.accounts = + mkOption { type = with types; attrsOf lieerModule; }; + }; + + config = mkIf cfg.enable (mkMerge [ + (mkIf (missingNotmuchAccounts != [ ]) { + warnings = ['' + lieer is enabled for the following email accounts, but notmuch is not: + + ${concatStringsSep "\n " missingNotmuchAccounts} + + Notmuch can be enabled with: + + ${concatStringsSep "\n " notmuchConfigHelp} + + If you have configured notmuch outside of Home Manager, you can suppress this + warning with: + + programs.lieer.notmuchSetupWarning = false; + '']; + }) + + { + assertions = [{ + assertion = nonGmailAccounts == [ ]; + message = '' + lieer is enabled for non-Gmail accounts: + + ${concatStringsSep "\n " nonGmailAccounts} + + If these accounts are actually Gmail accounts, you can + fix this error with: + + ${concatStringsSep "\n " nonGmailConfigHelp} + ''; + }]; + + warnings = flatten (map (account: account.warnings) lieerAccounts); + + home.packages = [ cfg.package ]; + + # Notmuch should ignore non-mail files created by lieer. + programs.notmuch.new.ignore = [ "/.*[.](json|lock|bak)$/" ]; + + home.file = listToAttrs (map configFile lieerAccounts); + } + ]); +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/lsd.nix b/infra/libkookie/home-manager-stable/modules/programs/lsd.nix new file mode 100644 index 00000000000..0b54abe3de4 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/lsd.nix @@ -0,0 +1,62 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.lsd; + + yamlFormat = pkgs.formats.yaml { }; + + aliases = { + ls = "${pkgs.lsd}/bin/lsd"; + ll = "${pkgs.lsd}/bin/lsd -l"; + la = "${pkgs.lsd}/bin/lsd -a"; + lt = "${pkgs.lsd}/bin/lsd --tree"; + lla = "${pkgs.lsd}/bin/lsd -la"; + }; + +in { + meta.maintainers = [ maintainers.marsam ]; + + options.programs.lsd = { + enable = mkEnableOption "lsd"; + + enableAliases = mkOption { + default = false; + type = types.bool; + description = '' + Whether to enable recommended lsd aliases. + ''; + }; + + settings = mkOption { + type = yamlFormat.type; + default = { }; + example = { + date = "relative"; + ignore-globs = [ ".git" ".hg" ]; + }; + description = '' + Configuration written to + $XDG_CONFIG_HOME/lsd/config.yaml. See + + for supported values. + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ pkgs.lsd ]; + + programs.bash.shellAliases = mkIf cfg.enableAliases aliases; + + programs.zsh.shellAliases = mkIf cfg.enableAliases aliases; + + programs.fish.shellAliases = mkIf cfg.enableAliases aliases; + + xdg.configFile."lsd/config.yaml" = mkIf (cfg.settings != { }) { + source = yamlFormat.generate "lsd-config" cfg.settings; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/man.nix b/infra/libkookie/home-manager-stable/modules/programs/man.nix new file mode 100644 index 00000000000..f3134b37be6 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/man.nix @@ -0,0 +1,80 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let cfg = config.programs.man; +in { + options = { + programs.man = { + enable = mkOption { + type = types.bool; + default = true; + description = '' + Whether to enable manual pages and the man + command. This also includes "man" outputs of all + home.packages. + ''; + }; + + package = mkOption { + type = types.package; + default = pkgs.man; + defaultText = literalExpression "pkgs.man"; + description = "The man package to use."; + }; + + generateCaches = mkOption { + type = types.bool; + default = false; + description = '' + Whether to generate the manual page index caches using + + mandb + 8 + . This allows searching for a page or + keyword using utilities like + apropos + 1 + . + + This feature is disabled by default because it slows down + building. If you don't mind waiting a few more seconds when + Home Manager builds a new generation, you may safely enable + this option. + ''; + }; + }; + }; + + config = mkIf config.programs.man.enable { + home.packages = [ cfg.package ]; + home.extraOutputsToInstall = [ "man" ]; + + # This is mostly copy/pasted/adapted from NixOS' documentation.nix. + home.file = mkIf config.programs.man.generateCaches { + ".manpath".text = let + # Generate a directory containing installed packages' manpages. + manualPages = pkgs.buildEnv { + name = "man-paths"; + paths = config.home.packages; + pathsToLink = [ "/share/man" ]; + extraOutputsToInstall = [ "man" ]; + ignoreCollisions = true; + }; + + # Generate a database of all manpages in ${manualPages}. + manualCache = pkgs.runCommandLocal "man-cache" { } '' + # Generate a temporary man.conf so mandb knows where to + # write cache files. + echo "MANDB_MAP ${manualPages}/share/man $out" > man.conf + + # Run mandb to generate cache files: + ${pkgs.man-db}/bin/mandb -C man.conf --no-straycats --create \ + ${manualPages}/share/man + ''; + in '' + MANDB_MAP ${config.home.profileDirectory}/share/man ${manualCache} + ''; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/mangohud.nix b/infra/libkookie/home-manager-stable/modules/programs/mangohud.nix new file mode 100644 index 00000000000..ca77c07c60b --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/mangohud.nix @@ -0,0 +1,106 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.programs.mangohud; + + settingsType = with types; + (oneOf [ bool int float str path (listOf (oneOf [ int str ])) ]); + + renderOption = option: + rec { + int = toString option; + float = int; + path = int; + bool = "false"; + string = option; + list = concatStringsSep "," (lists.forEach option (x: toString x)); + }.${builtins.typeOf option}; + + renderLine = k: v: (if isBool v && v then k else "${k}=${renderOption v}"); + renderSettings = attrs: + strings.concatStringsSep "\n" (attrsets.mapAttrsToList renderLine attrs) + + "\n"; + +in { + options = { + programs.mangohud = { + enable = mkEnableOption "Mangohud"; + + package = mkOption { + type = types.package; + default = pkgs.mangohud; + defaultText = literalExpression "pkgs.mangohud"; + description = "The Mangohud package to install."; + }; + + enableSessionWide = mkOption { + type = types.bool; + default = false; + description = '' + Sets environment variables so that + MangoHud is started on any application that supports it. + ''; + }; + + settings = mkOption { + type = with types; attrsOf settingsType; + default = { }; + example = literalExpression '' + { + output_folder = ~/Documents/mangohud/; + full = true; + } + ''; + description = '' + Configuration written to + $XDG_CONFIG_HOME/MangoHud/MangoHud.conf. See + + for the default configuration. + ''; + }; + + settingsPerApplication = mkOption { + type = with types; attrsOf (attrsOf settingsType); + default = { }; + example = literalExpression '' + { + mpv = { + no_display = true; + } + } + ''; + description = '' + Sets MangoHud settings per application. + Configuration written to + $XDG_CONFIG_HOME/MangoHud/{application_name}.conf. See + + for the default configuration. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (hm.assertions.assertPlatform "programs.mangohud" pkgs platforms.linux) + ]; + + home.packages = [ cfg.package ]; + + home.sessionVariables = mkIf cfg.enableSessionWide { + MANGOHUD = 1; + MANGOHUD_DLSYM = 1; + }; + + xdg.configFile = { + "MangoHud/MangoHud.conf" = + mkIf (cfg.settings != { }) { text = renderSettings cfg.settings; }; + } // mapAttrs' + (n: v: nameValuePair "MangoHud/${n}.conf" { text = renderSettings v; }) + cfg.settingsPerApplication; + }; + + meta.maintainers = with maintainers; [ zeratax ]; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/matplotlib.nix b/infra/libkookie/home-manager-stable/modules/programs/matplotlib.nix new file mode 100644 index 00000000000..1edb9b12562 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/matplotlib.nix @@ -0,0 +1,59 @@ +{ config, lib, ... }: + +with lib; + +let + + cfg = config.programs.matplotlib; + + formatLine = o: n: v: + let + formatValue = v: + if isBool v then (if v then "True" else "False") else toString v; + in if isAttrs v then + concatStringsSep "\n" (mapAttrsToList (formatLine "${o}${n}.") v) + else + (if v == "" then "" else "${o}${n}: ${formatValue v}"); + +in { + meta.maintainers = [ maintainers.rprospero ]; + + options.programs.matplotlib = { + enable = mkEnableOption "matplotlib, a plotting library for python"; + + config = mkOption { + default = { }; + type = types.attrsOf types.anything; + description = '' + Add terms to the matplotlibrc file to + control the default matplotlib behavior. + ''; + example = literalExpression '' + { + backend = "Qt5Agg"; + axes = { + grid = true; + facecolor = "black"; + edgecolor = "FF9900"; + }; + grid.color = "FF9900"; + } + ''; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Additional commands for matplotlib that will be added to the + matplotlibrc file. + ''; + }; + }; + + config = mkIf cfg.enable { + xdg.configFile."matplotlib/matplotlibrc".text = concatStringsSep "\n" ([ ] + ++ mapAttrsToList (formatLine "") cfg.config + ++ optional (cfg.extraConfig != "") cfg.extraConfig) + "\n"; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/mbsync-accounts.nix b/infra/libkookie/home-manager-stable/modules/programs/mbsync-accounts.nix new file mode 100644 index 00000000000..fa3f00ab332 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/mbsync-accounts.nix @@ -0,0 +1,236 @@ +{ config, lib, ... }: + +with lib; + +let + + extraConfigType = with lib.types; attrsOf (either (either str int) bool); + + perAccountGroups = { name, config, ... }: { + options = { + name = mkOption { + type = types.str; + # Make value of name the same as the name used with the dot prefix + default = name; + readOnly = true; + description = '' + The name of this group for this account. These names are different than + some others, because they will hide channel names that are the same. + ''; + }; + + channels = mkOption { + type = types.attrsOf (types.submodule channel); + default = { }; + description = '' + List of channels that should be grouped together into this group. When + performing a synchronization, the groups are synchronized, rather than + the individual channels. + + Using these channels and then grouping them together allows for you to + define the maildir hierarchy as you see fit. + ''; + }; + }; + }; + + # Options for configuring channel(s) that will be composed together into a group. + channel = { name, config, ... }: { + options = { + name = mkOption { + type = types.str; + default = name; + readOnly = true; + description = '' + The unique name for THIS channel in THIS group. The group will refer to + this channel by this name. + + In addition, you can manually sync just this channel by specifying this + name to mbsync on the command line. + ''; + }; + + farPattern = mkOption { + type = types.str; + default = ""; + example = "[Gmail]/Sent Mail"; + description = '' + IMAP4 patterns for which mailboxes on the remote mail server to sync. + If Patterns are specified, farPattern + is interpreted as a prefix which is not matched against the patterns, + and is not affected by mailbox list overrides. + + If this is left as the default, then mbsync will default to the pattern + INBOX. + ''; + }; + + nearPattern = mkOption { + type = types.str; + default = ""; + example = "Sent"; + description = '' + Name for where mail coming from the remote (far) mail server will end up + locally. The mailbox specified by the far pattern will be placed in + this directory. + + If this is left as the default, then mbsync will default to the pattern + INBOX. + ''; + }; + + patterns = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "INBOX" ]; + description = '' + Instead of synchronizing just the mailboxes that + match the farPattern, use it as a prefix which is + not matched against the patterns, and is not affected by mailbox list + overrides. + ''; + }; + + extraConfig = mkOption { + type = extraConfigType; + default = { }; + example = literalExpression '' + { + Create = "both"; + CopyArrivalDate = "yes"; + MaxMessages = 10000; + MaxSize = "1m"; + } + ''; + description = '' + Extra configuration lines to add to THIS channel's + configuration. + ''; + }; + }; + }; + +in { + options.mbsync = { + enable = mkEnableOption "synchronization using mbsync"; + + flatten = mkOption { + type = types.nullOr types.str; + default = null; + example = "."; + description = '' + If set, flattens the hierarchy within the maildir by + substituting the canonical hierarchy delimiter + / with this value. + ''; + }; + + subFolders = mkOption { + type = types.enum [ "Verbatim" "Maildir++" "Legacy" ]; + default = "Verbatim"; + example = "Maildir++"; + description = '' + The on-disk folder naming style. This option has no + effect when is used. + ''; + }; + + create = mkOption { + type = types.enum [ "none" "maildir" "imap" "both" ]; + default = "none"; + example = "maildir"; + description = '' + Automatically create missing mailboxes within the + given mail store. + ''; + }; + + remove = mkOption { + type = types.enum [ "none" "maildir" "imap" "both" ]; + default = "none"; + example = "imap"; + description = '' + Propagate mailbox deletions to the given mail store. + ''; + }; + + expunge = mkOption { + type = types.enum [ "none" "maildir" "imap" "both" ]; + default = "none"; + example = "both"; + description = '' + Permanently remove messages marked for deletion from + the given mail store. + ''; + }; + + patterns = mkOption { + type = types.listOf types.str; + default = [ "*" ]; + description = '' + Pattern of mailboxes to synchronize. + ''; + }; + + groups = mkOption { + type = types.attrsOf (types.submodule perAccountGroups); + default = { }; + # The default cannot actually be empty, but contains an attribute set where + # the channels set is empty. If a group is specified, then a name is given, + # creating the attribute set. + description = '' + Some email providers (Gmail) have a different directory hierarchy for + synchronized email messages. Namely, when using mbsync without specifying + a set of channels into a group, all synchronized directories end up beneath + the [Gmail]/ directory. + + This option allows you to specify a group, and subsequently channels that + will allow you to sync your mail into an arbitrary hierarchy. + ''; + }; + + extraConfig.channel = mkOption { + type = extraConfigType; + default = { }; + example = literalExpression '' + { + MaxMessages = 10000; + MaxSize = "1m"; + }; + ''; + description = '' + Per channel extra configuration. + ''; + }; + + extraConfig.local = mkOption { + type = extraConfigType; + default = { }; + description = '' + Local store extra configuration. + ''; + }; + + extraConfig.remote = mkOption { + type = extraConfigType; + default = { }; + description = '' + Remote store extra configuration. + ''; + }; + + extraConfig.account = mkOption { + type = extraConfigType; + default = { }; + example = literalExpression '' + { + PipelineDepth = 10; + Timeout = 60; + }; + ''; + description = '' + Account section extra configuration. + ''; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/mbsync.nix b/infra/libkookie/home-manager-stable/modules/programs/mbsync.nix new file mode 100644 index 00000000000..373828a0b24 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/mbsync.nix @@ -0,0 +1,297 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.mbsync; + + # Accounts for which mbsync is enabled. + mbsyncAccounts = + filter (a: a.mbsync.enable) (attrValues config.accounts.email.accounts); + + # Given a SINGLE group's channels attribute set, return true if ANY of the channel's + # patterns use the invalidOption attribute set value name. + channelInvalidOption = channels: invalidOption: + any (c: c) (mapAttrsToList (c: hasAttr invalidOption) channels); + + # Given a SINGLE account's groups attribute set, return true if ANY of the account's group's channel's patterns use the invalidOption attribute set value name. + groupInvalidOption = groups: invalidOption: + any (g: g) (mapAttrsToList (groupName: groupVals: + channelInvalidOption groupVals.channels invalidOption) groups); + + # Given all accounts (ensure that accounts passed in here ARE mbsync-using accounts) + # return true if ANY of the account's groups' channels' patterns use the + # invalidOption attribute set value name. + accountInvalidOption = accounts: invalidOption: + any (a: a) + (map (account: groupInvalidOption account.mbsync.groups invalidOption) + mbsyncAccounts); + + genTlsConfig = tls: + { + SSLType = if !tls.enable then + "None" + else if tls.useStartTls then + "STARTTLS" + else + "IMAPS"; + } // optionalAttrs (tls.enable && tls.certificatesFile != null) { + CertificateFile = toString tls.certificatesFile; + }; + + imports = [ + (mkRenamedOptionModule [ "programs" "mbsync" "masterSlaveMapping" ] [ + "programs" + "mbsync" + "nearFarMapping" + ]) + ]; + + nearFarMapping = { + none = "None"; + imap = "Far"; + maildir = "Near"; + both = "Both"; + }; + + genSection = header: entries: + let + escapeValue = escape [ ''"'' ]; + hasSpace = v: builtins.match ".* .*" v != null; + genValue = n: v: + if isList v then + concatMapStringsSep " " (genValue n) v + else if isBool v then + lib.hm.booleans.yesNo v + else if isInt v then + toString v + else if isString v && hasSpace v then + ''"${escapeValue v}"'' + else if isString v then + v + else + let prettyV = lib.generators.toPretty { } v; + in throw "mbsync: unexpected value for option ${n}: '${prettyV}'"; + in '' + ${header} + ${concatStringsSep "\n" + (mapAttrsToList (n: v: "${n} ${genValue n v}") entries)} + ''; + + genAccountConfig = account: + with account; + genSection "IMAPAccount ${name}" ({ + Host = imap.host; + User = userName; + PassCmd = toString passwordCommand; + } // genTlsConfig imap.tls + // optionalAttrs (imap.port != null) { Port = toString imap.port; } + // mbsync.extraConfig.account) + "\n" + + genSection "IMAPStore ${name}-remote" + ({ Account = name; } // mbsync.extraConfig.remote) + "\n" + + genSection "MaildirStore ${name}-local" ({ + Inbox = "${maildir.absPath}/${folders.inbox}"; + } // optionalAttrs + (mbsync.subFolders != "Maildir++" || mbsync.flatten != null) { + Path = "${maildir.absPath}/"; + } // optionalAttrs (mbsync.flatten == null) { + SubFolders = mbsync.subFolders; + } // optionalAttrs (mbsync.flatten != null) { Flatten = mbsync.flatten; } + // mbsync.extraConfig.local) + "\n" + genChannels account; + + genChannels = account: + with account; + if mbsync.groups == { } then + genAccountWideChannel account + else + genGroupChannelConfig name mbsync.groups + "\n" + + genAccountGroups mbsync.groups; + + # Used when no channels are specified for this account. This will create a + # single channel for the entire account that is then further refined within + # the Group for synchronization. + genAccountWideChannel = account: + with account; + genSection "Channel ${name}" ({ + Far = ":${name}-remote:"; + Near = ":${name}-local:"; + Patterns = mbsync.patterns; + Create = nearFarMapping.${mbsync.create}; + Remove = nearFarMapping.${mbsync.remove}; + Expunge = nearFarMapping.${mbsync.expunge}; + SyncState = "*"; + } // mbsync.extraConfig.channel) + "\n"; + + # Given the attr set of groups, return a string of channels that will direct + # mail to the proper directories, according to the pattern used in channel's + # "far" pattern definition. + genGroupChannelConfig = storeName: groups: + let + # Given the name of the group this channel is part of and the channel + # itself, generate the string for the desired configuration. + genChannelString = groupName: channel: + let + escapeValue = escape [ ''\"'' ]; + hasSpace = v: builtins.match ".* .*" v != null; + # Given a list of patterns, will return the string requested. + # Only prints if the pattern is NOT the empty list, the default. + genChannelPatterns = patterns: + if (length patterns) != 0 then + "Pattern " + concatStringsSep " " + (map (pat: if hasSpace pat then escapeValue pat else pat) + patterns) + "\n" + else + ""; + in genSection "Channel ${groupName}-${channel.name}" ({ + Far = ":${storeName}-remote:${channel.farPattern}"; + Near = ":${storeName}-local:${channel.nearPattern}"; + } // channel.extraConfig) + genChannelPatterns channel.patterns; + # Given the group name, and a attr set of channels within that group, + # Generate a list of strings for each channels' configuration. + genChannelStrings = groupName: channels: + optionals (channels != { }) + (mapAttrsToList (channelName: info: genChannelString groupName info) + channels); + # Given a group, return a string that configures all the channels within + # the group. + genGroupsChannels = group: + concatStringsSep "\n" (genChannelStrings group.name group.channels); + # Generate all channel configurations for all groups for this account. + in concatStringsSep "\n" + (remove "" (mapAttrsToList (name: group: genGroupsChannels group) groups)); + + # Given the attr set of groups, return a string which maps channels to groups + genAccountGroups = groups: + let + # Given the name of the group and the attribute set of channels, make + # make "Channel -" for each channel to list os strings + genChannelStrings = groupName: channels: + mapAttrsToList (name: info: "Channel ${groupName}-${name}") channels; + # Take in 1 group, if the group has channels specified, construct the + # "Group " header and each of the channels. + genGroupChannelString = group: + flatten (optionals (group.channels != { }) ([ "Group ${group.name}" ] + ++ (genChannelStrings group.name group.channels))); + # Given set of groups, generates list of strings, where each string is one + # of the groups and its consituent channels. + genGroupsStrings = mapAttrsToList (name: info: + concatStringsSep "\n" (genGroupChannelString groups.${name})) groups; + # Join all non-empty groups. + combined = concatStringsSep "\n\n" (remove "" genGroupsStrings) + "\n"; + in combined; + + genGroupConfig = name: channels: + let + genGroupChannel = n: boxes: "Channel ${n}:${concatStringsSep "," boxes}"; + in "\n" + concatStringsSep "\n" + ([ "Group ${name}" ] ++ mapAttrsToList genGroupChannel channels); + +in { + meta.maintainers = [ maintainers.KarlJoad ]; + + options = { + programs.mbsync = { + enable = mkEnableOption "mbsync IMAP4 and Maildir mailbox synchronizer"; + + package = mkOption { + type = types.package; + default = pkgs.isync; + defaultText = literalExpression "pkgs.isync"; + example = literalExpression "pkgs.isync"; + description = "The package to use for the mbsync binary."; + }; + + groups = mkOption { + type = types.attrsOf (types.attrsOf (types.listOf types.str)); + default = { }; + example = literalExpression '' + { + inboxes = { + account1 = [ "Inbox" ]; + account2 = [ "Inbox" ]; + }; + } + ''; + description = '' + Definition of groups. + ''; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Extra configuration lines to add to the mbsync configuration. + ''; + }; + }; + + accounts.email.accounts = mkOption { + type = with types; attrsOf (submodule (import ./mbsync-accounts.nix)); + }; + }; + + config = mkIf cfg.enable (mkMerge [ + { + assertions = let + checkAccounts = pred: msg: + let badAccounts = filter pred mbsyncAccounts; + in { + assertion = badAccounts == [ ]; + message = "mbsync: ${msg} for accounts: " + + concatMapStringsSep ", " (a: a.name) badAccounts; + }; + in [ + (checkAccounts (a: a.maildir == null) "Missing maildir configuration") + (checkAccounts (a: a.imap == null) "Missing IMAP configuration") + (checkAccounts (a: a.passwordCommand == null) "Missing passwordCommand") + (checkAccounts (a: a.userName == null) "Missing username") + ]; + } + + (mkIf (accountInvalidOption mbsyncAccounts "masterPattern") { + warnings = [ + "mbsync channels no longer use masterPattern. Use farPattern in its place." + ]; + }) + + (mkIf (accountInvalidOption mbsyncAccounts "slavePattern") { + warnings = [ + "mbsync channels no longer use slavePattern. Use nearPattern in its place." + ]; + }) + + { + home.packages = [ cfg.package ]; + + programs.notmuch.new.ignore = [ ".uidvalidity" ".mbsyncstate" ]; + + home.file.".mbsyncrc".text = let + accountsConfig = map genAccountConfig mbsyncAccounts; + # Only generate this kind of Group configuration if there are ANY accounts + # that do NOT have a per-account groups/channels option(s) specified. + groupsConfig = + if any (account: account.mbsync.groups == { }) mbsyncAccounts then + mapAttrsToList genGroupConfig cfg.groups + else + [ ]; + in '' + # Generated by Home Manager. + + '' + + concatStringsSep "\n" (optional (cfg.extraConfig != "") cfg.extraConfig) + + concatStringsSep "\n\n" accountsConfig + + concatStringsSep "\n" groupsConfig; + + home.activation = mkIf (mbsyncAccounts != [ ]) { + createMaildir = + hm.dag.entryBetween [ "linkGeneration" ] [ "writeBoundary" ] '' + $DRY_RUN_CMD mkdir -m700 -p $VERBOSE_ARG ${ + concatMapStringsSep " " (a: a.maildir.absPath) mbsyncAccounts + } + ''; + }; + } + ]); +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/mcfly.nix b/infra/libkookie/home-manager-stable/modules/programs/mcfly.nix new file mode 100644 index 00000000000..e6b1640bb18 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/mcfly.nix @@ -0,0 +1,86 @@ +{ config, lib, pkgs, ... }: + +with lib; +let + + cfg = config.programs.mcfly; + +in { + meta.maintainers = [ maintainers.marsam ]; + + options.programs.mcfly = { + enable = mkEnableOption "mcfly"; + + keyScheme = mkOption { + type = types.enum [ "emacs" "vim" ]; + default = "emacs"; + description = '' + Key scheme to use. + ''; + }; + + enableLightTheme = mkOption { + default = false; + type = types.bool; + description = '' + Whether to enable light mode theme. + ''; + }; + + enableFuzzySearch = mkOption { + default = false; + type = types.bool; + description = '' + Whether to enable fuzzy searching. + ''; + }; + + enableBashIntegration = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable Bash integration. + ''; + }; + + enableZshIntegration = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable Zsh integration. + ''; + }; + + enableFishIntegration = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable Fish integration. + ''; + }; + }; + + config = mkIf cfg.enable (mkMerge [ + { + home.packages = [ pkgs.mcfly ]; + + programs.bash.initExtra = mkIf cfg.enableBashIntegration '' + eval "$(${pkgs.mcfly}/bin/mcfly init bash)" + ''; + + programs.zsh.initExtra = mkIf cfg.enableZshIntegration '' + eval "$(${pkgs.mcfly}/bin/mcfly init zsh)" + ''; + + programs.fish.shellInit = mkIf cfg.enableFishIntegration '' + ${pkgs.mcfly}/bin/mcfly init fish | source + ''; + + home.sessionVariables.MCFLY_KEY_SCHEME = cfg.keyScheme; + } + + (mkIf cfg.enableLightTheme { home.sessionVariables.MCFLY_LIGHT = "TRUE"; }) + + (mkIf cfg.enableFuzzySearch { home.sessionVariables.MCFLY_FUZZY = "TRUE"; }) + ]); +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/mercurial.nix b/infra/libkookie/home-manager-stable/modules/programs/mercurial.nix new file mode 100644 index 00000000000..07a7d626c6a --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/mercurial.nix @@ -0,0 +1,103 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.mercurial; + + iniFormat = pkgs.formats.ini { }; + +in { + + options = { + programs.mercurial = { + enable = mkEnableOption "Mercurial"; + + package = mkOption { + type = types.package; + default = pkgs.mercurial; + defaultText = literalExpression "pkgs.mercurial"; + description = "Mercurial package to install."; + }; + + userName = mkOption { + type = types.str; + description = "Default user name to use."; + }; + + userEmail = mkOption { + type = types.str; + description = "Default user email to use."; + }; + + aliases = mkOption { + type = types.attrsOf types.anything; + default = { }; + description = "Mercurial aliases to define."; + }; + + extraConfig = mkOption { + type = types.either (types.attrsOf types.anything) types.lines; + default = { }; + description = "Additional configuration to add."; + }; + + iniContent = mkOption { + type = iniFormat.type; + internal = true; + }; + + ignores = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "*~" "*.swp" ]; + description = "List of globs for files to be globally ignored."; + }; + + ignoresRegexp = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "^.*~$" "^.*\\.swp$" ]; + description = + "List of regular expressions for files to be globally ignored."; + }; + }; + }; + + config = mkIf cfg.enable (mkMerge [ + { + home.packages = [ cfg.package ]; + + programs.mercurial.iniContent.ui = { + username = cfg.userName + " <" + cfg.userEmail + ">"; + }; + + xdg.configFile."hg/hgrc".source = + iniFormat.generate "hgrc" cfg.iniContent; + } + + (mkIf (cfg.ignores != [ ] || cfg.ignoresRegexp != [ ]) { + programs.mercurial.iniContent.ui.ignore = + "${config.xdg.configHome}/hg/hgignore_global"; + + xdg.configFile."hg/hgignore_global".text = '' + syntax: glob + '' + concatStringsSep "\n" cfg.ignores + "\n" + '' + syntax: regexp + '' + concatStringsSep "\n" cfg.ignoresRegexp + "\n"; + }) + + (mkIf (cfg.aliases != { }) { + programs.mercurial.iniContent.alias = cfg.aliases; + }) + + (mkIf (lib.isAttrs cfg.extraConfig) { + programs.mercurial.iniContent = cfg.extraConfig; + }) + + (mkIf (lib.isString cfg.extraConfig) { + xdg.configFile."hg/hgrc".text = cfg.extraConfig; + }) + ]); +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/mpv.nix b/infra/libkookie/home-manager-stable/modules/programs/mpv.nix new file mode 100644 index 00000000000..0d7668cfa7a --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/mpv.nix @@ -0,0 +1,190 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + inherit (builtins) typeOf stringLength; + + cfg = config.programs.mpv; + + mpvOption = with types; either str (either int (either bool float)); + mpvOptionDup = with types; either mpvOption (listOf mpvOption); + mpvOptions = with types; attrsOf mpvOptionDup; + mpvProfiles = with types; attrsOf mpvOptions; + mpvBindings = with types; attrsOf str; + mpvDefaultProfiles = with types; listOf str; + + renderOption = option: + rec { + int = toString option; + float = int; + bool = lib.hm.booleans.yesNo option; + string = option; + }.${typeOf option}; + + renderOptionValue = value: + let + rendered = renderOption value; + length = toString (stringLength rendered); + in "%${length}%${rendered}"; + + renderOptions = generators.toKeyValue { + mkKeyValue = + generators.mkKeyValueDefault { mkValueString = renderOptionValue; } "="; + listsAsDuplicateKeys = true; + }; + + renderProfiles = generators.toINI { + mkKeyValue = + generators.mkKeyValueDefault { mkValueString = renderOptionValue; } "="; + listsAsDuplicateKeys = true; + }; + + renderBindings = bindings: + concatStringsSep "\n" + (mapAttrsToList (name: value: "${name} ${value}") bindings); + + renderDefaultProfiles = profiles: + renderOptions { profile = concatStringsSep "," profiles; }; + + mpvPackage = if cfg.scripts == [ ] then + cfg.package + else + pkgs.wrapMpv pkgs.mpv-unwrapped { scripts = cfg.scripts; }; + +in { + options = { + programs.mpv = { + enable = mkEnableOption "mpv"; + + package = mkOption { + type = types.package; + default = pkgs.mpv; + example = literalExpression + "pkgs.wrapMpv (pkgs.mpv-unwrapped.override { vapoursynthSupport = true; }) { youtubeSupport = true; }"; + description = '' + Package providing mpv. + ''; + }; + + finalPackage = mkOption { + type = types.package; + readOnly = true; + visible = false; + description = '' + Resulting mpv package. + ''; + }; + + scripts = mkOption { + type = with types; listOf (either package str); + default = [ ]; + example = literalExpression "[ pkgs.mpvScripts.mpris ]"; + description = '' + List of scripts to use with mpv. + ''; + }; + + config = mkOption { + description = '' + Configuration written to + $XDG_CONFIG_HOME/mpv/mpv.conf. See + + mpv + 1 + + for the full list of options. + ''; + type = mpvOptions; + default = { }; + example = literalExpression '' + { + profile = "gpu-hq"; + force-window = true; + ytdl-format = "bestvideo+bestaudio"; + cache-default = 4000000; + } + ''; + }; + + profiles = mkOption { + description = '' + Sub-configuration options for specific profiles written to + $XDG_CONFIG_HOME/mpv/mpv.conf. See + for more information. + ''; + type = mpvProfiles; + default = { }; + example = literalExpression '' + { + fast = { + vo = "vdpau"; + }; + "protocol.dvd" = { + profile-desc = "profile for dvd:// streams"; + alang = "en"; + }; + } + ''; + }; + + defaultProfiles = mkOption { + description = '' + Profiles to be applied by default. Options set by them are overridden + by options set in . + ''; + type = mpvDefaultProfiles; + default = [ ]; + example = [ "gpu-hq" ]; + }; + + bindings = mkOption { + description = '' + Input configuration written to + $XDG_CONFIG_HOME/mpv/input.conf. See + + mpv + 1 + + for the full list of options. + ''; + type = mpvBindings; + default = { }; + example = literalExpression '' + { + WHEEL_UP = "seek 10"; + WHEEL_DOWN = "seek -10"; + "Alt+0" = "set window-scale 0.5"; + } + ''; + }; + }; + }; + + config = mkIf cfg.enable (mkMerge [ + { + assertions = [{ + assertion = (cfg.scripts == [ ]) || (cfg.package == pkgs.mpv); + message = '' + The programs.mpv "package" option is mutually exclusive with "scripts" option.''; + }]; + } + { + home.packages = [ mpvPackage ]; + programs.mpv.finalPackage = mpvPackage; + } + (mkIf (cfg.config != { } || cfg.profiles != { }) { + xdg.configFile."mpv/mpv.conf".text = '' + ${optionalString (cfg.defaultProfiles != [ ]) + (renderDefaultProfiles cfg.defaultProfiles)} + ${optionalString (cfg.config != { }) (renderOptions cfg.config)} + ${optionalString (cfg.profiles != { }) (renderProfiles cfg.profiles)} + ''; + }) + (mkIf (cfg.bindings != { }) { + xdg.configFile."mpv/input.conf".text = renderBindings cfg.bindings; + }) + ]); + + meta.maintainers = with maintainers; [ tadeokondrak thiagokokada ]; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/msmtp-accounts.nix b/infra/libkookie/home-manager-stable/modules/programs/msmtp-accounts.nix new file mode 100644 index 00000000000..894cef51742 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/msmtp-accounts.nix @@ -0,0 +1,48 @@ +{ config, lib, ... }: + +with lib; + +{ + options.msmtp = { + enable = mkOption { + type = types.bool; + default = false; + description = '' + Whether to enable msmtp. + + If enabled then it is possible to use the + --account command line + option to send a message for a given account using the + msmtp or msmtpq tool. + For example, msmtp --account=private would + send using the account defined in + . If the + --account option is not + given then the primary account will be used. + ''; + }; + + tls.fingerprint = mkOption { + type = + types.nullOr (types.strMatching "([[:alnum:]]{2}:)+[[:alnum:]]{2}"); + default = null; + example = "my:SH:a2:56:ha:sh"; + description = '' + Fingerprint of a trusted TLS certificate. + The fingerprint can be obtained by executing + msmtp --serverinfo --tls --tls-certcheck=off. + ''; + }; + + extraConfig = mkOption { + type = types.attrsOf types.str; + default = { }; + example = { auth = "login"; }; + description = '' + Extra configuration options to add to ~/.msmtprc. + See for + examples. + ''; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/msmtp.nix b/infra/libkookie/home-manager-stable/modules/programs/msmtp.nix new file mode 100644 index 00000000000..e1fc35d2e84 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/msmtp.nix @@ -0,0 +1,90 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.msmtp; + + msmtpAccounts = + filter (a: a.msmtp.enable) (attrValues config.accounts.email.accounts); + + onOff = p: if p then "on" else "off"; + + accountStr = account: + with account; + concatStringsSep "\n" ([ "account ${name}" ] + ++ mapAttrsToList (n: v: n + " " + v) ({ + host = smtp.host; + from = address; + auth = "on"; + user = userName; + tls = onOff smtp.tls.enable; + tls_starttls = onOff smtp.tls.useStartTls; + } // optionalAttrs (msmtp.tls.fingerprint != null) { + tls_fingerprint = msmtp.tls.fingerprint; + } // optionalAttrs (smtp.port != null) { port = toString smtp.port; } + // optionalAttrs (smtp.tls.certificatesFile != null) { + tls_trust_file = smtp.tls.certificatesFile; + } // optionalAttrs (passwordCommand != null) { + passwordeval = toString passwordCommand; + } // msmtp.extraConfig) ++ optional primary '' + + account default : ${name}''); + + configFile = mailAccounts: '' + # Generated by Home Manager. + + ${cfg.extraConfig} + + ${concatStringsSep "\n\n" (map accountStr mailAccounts)} + + ${cfg.extraAccounts} + ''; + +in { + + options = { + programs.msmtp = { + enable = mkEnableOption "msmtp"; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Extra configuration lines to add to ~/.msmtprc. + See for examples. + + Note, if running msmtp fails with the error message "account default + was already defined" then you probably have an account command here. + Account commands should be placed in + . + ''; + }; + + extraAccounts = mkOption { + type = types.lines; + default = ""; + description = '' + Extra configuration lines to add to the end of ~/.msmtprc. + See for examples. + ''; + }; + }; + + accounts.email.accounts = mkOption { + type = with types; attrsOf (submodule (import ./msmtp-accounts.nix)); + }; + }; + + config = mkIf cfg.enable { + home.packages = [ pkgs.msmtp ]; + + xdg.configFile."msmtp/config".text = configFile msmtpAccounts; + + home.sessionVariables = { + MSMTP_QUEUE = "${config.xdg.dataHome}/msmtp/queue"; + MSMTP_LOG = "${config.xdg.dataHome}/msmtp/queue.log"; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/mu.nix b/infra/libkookie/home-manager-stable/modules/programs/mu.nix new file mode 100644 index 00000000000..58b8b3dff91 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/mu.nix @@ -0,0 +1,59 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.mu; + + # Used to generate command line arguments that mu can operate with. + genCmdMaildir = path: "--maildir=" + path; + + # Takes the list of accounts with mu.enable = true, and generates a + # command-line flag for initializing the mu database. + myAddresses = let + # Set of email account sets where mu.enable = true. + muAccounts = + filter (a: a.mu.enable) (attrValues config.accounts.email.accounts); + addrs = map (a: a.address) muAccounts; + # Construct list of lists containing email aliases, and flatten + aliases = flatten (map (a: a.aliases) muAccounts); + # Prefix --my-address= to each account's address AND all defined aliases + addMyAddress = map (addr: "--my-address=" + addr) (addrs ++ aliases); + in concatStringsSep " " addMyAddress; + +in { + meta.maintainers = [ maintainers.KarlJoad ]; + + options = { + programs.mu = { + enable = mkEnableOption "mu, a maildir indexer and searcher"; + + # No options/config file present for mu, and program author will not be + # adding one soon. See https://github.com/djcb/mu/issues/882 for more + # information about this. + }; + + accounts.email.accounts = mkOption { + type = with types; + attrsOf + (submodule { options.mu.enable = mkEnableOption "mu indexing"; }); + }; + }; + + config = mkIf cfg.enable { + home.packages = [ pkgs.mu ]; + + home.activation.runMuInit = let + maildirOption = genCmdMaildir config.accounts.email.maildirBasePath; + dbLocation = config.xdg.cacheHome + "/mu"; + in hm.dag.entryAfter [ "writeBoundary" ] '' + # If the database directory exists, then `mu init` should NOT be run. + # In theory, mu is the only thing that creates that directory, and it is + # only created during the initial index. + if [[ ! -d "${dbLocation}" ]]; then + $DRY_RUN_CMD mu init ${maildirOption} ${myAddresses} $VERBOSE_ARG; + fi + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/navi.nix b/infra/libkookie/home-manager-stable/modules/programs/navi.nix new file mode 100644 index 00000000000..f8d4803286b --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/navi.nix @@ -0,0 +1,86 @@ +{ config, lib, pkgs, ... }: + +with lib; +let + + cfg = config.programs.navi; + + yamlFormat = pkgs.formats.yaml { }; + + configDir = if pkgs.stdenv.isDarwin then + "Library/Application Support" + else + config.xdg.configHome; + +in { + meta.maintainers = [ maintainers.marsam ]; + + options.programs.navi = { + enable = mkEnableOption "Navi"; + + package = mkOption { + type = types.package; + default = pkgs.navi; + defaultText = literalExpression "pkgs.navi"; + description = "The package to use for the navi binary."; + }; + + settings = mkOption { + type = yamlFormat.type; + default = { }; + example = literalExpression '' + { + cheats = { + paths = [ + "~/cheats/" + ]; + }; + } + ''; + description = '' + Configuration written to + $XDG_CONFIG_HOME/navi/config.yaml on Linux or + $HOME/Library/Application Support/navi/config.yaml + on Darwin. See + + for more information. + ''; + }; + + enableBashIntegration = mkEnableOption "Bash integration" // { + default = true; + }; + + enableZshIntegration = mkEnableOption "Zsh integration" // { + default = true; + }; + + enableFishIntegration = mkEnableOption "Fish integration" // { + default = true; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + + programs.bash.initExtra = mkIf cfg.enableBashIntegration '' + if [[ :$SHELLOPTS: =~ :(vi|emacs): ]]; then + eval "$(${cfg.package}/bin/navi widget bash)" + fi + ''; + + programs.zsh.initExtra = mkIf cfg.enableZshIntegration '' + if [[ $options[zle] = on ]]; then + eval "$(${cfg.package}/bin/navi widget zsh)" + fi + ''; + + programs.fish.shellInit = mkIf cfg.enableFishIntegration '' + ${cfg.package}/bin/navi widget fish | source + ''; + + home.file."${configDir}/navi/config.yaml" = mkIf (cfg.settings != { }) { + source = yamlFormat.generate "navi-config" cfg.settings; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/ncmpcpp.nix b/infra/libkookie/home-manager-stable/modules/programs/ncmpcpp.nix new file mode 100644 index 00000000000..e3784951913 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/ncmpcpp.nix @@ -0,0 +1,135 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.ncmpcpp; + + renderSettings = settings: + concatStringsSep "\n" (mapAttrsToList renderSetting settings); + + renderSetting = name: value: "${name}=${renderValue value}"; + + renderValue = option: + { + int = toString option; + bool = lib.hm.booleans.yesNo option; + string = option; + }.${builtins.typeOf option}; + + renderBindings = bindings: concatStringsSep "\n" (map renderBinding bindings); + + renderBinding = { key, command }: + concatStringsSep "\n " ([ ''def_key "${key}"'' ] ++ maybeWrapList command); + + maybeWrapList = xs: if isList xs then xs else [ xs ]; + + valueType = with types; oneOf [ bool int str ]; + + bindingType = types.submodule ({ name, config, ... }: { + options = { + key = mkOption { + type = types.str; + description = "Key to bind."; + example = "j"; + }; + + command = mkOption { + type = with types; either str (listOf str); + description = "Command or sequence of commands to be executed."; + example = "scroll_down"; + }; + }; + }); + +in { + meta.maintainers = [ hm.maintainers.olmokramer ]; + + options.programs.ncmpcpp = { + enable = + mkEnableOption "ncmpcpp - an ncurses Music Player Daemon (MPD) client"; + + package = mkOption { + type = types.package; + default = pkgs.ncmpcpp; + defaultText = literalExpression "pkgs.ncmpcpp"; + description = '' + Package providing the ncmpcpp command. + ''; + example = + literalExpression "pkgs.ncmpcpp.override { visualizerSupport = true; }"; + }; + + mpdMusicDir = mkOption { + type = types.nullOr types.path; + default = let mpdCfg = config.services.mpd; + in if pkgs.stdenv.hostPlatform.isLinux && mpdCfg.enable then + mpdCfg.musicDirectory + else + null; + defaultText = literalExpression '' + if pkgs.stdenv.hostPlatform.isLinux && config.services.mpd.enable then + config.services.mpd.musicDirectory + else + null + ''; + description = '' + Value of the mpd_music_dir setting. On Linux platforms the + value of services.mpd.musicDirectory is used as the + default if services.mpd.enable is + true. + ''; + example = "~/music"; + }; + + settings = mkOption { + type = types.attrsOf valueType; + default = { }; + description = '' + Attribute set from name of a setting to its value. For available options + see + + ncmpcpp + 1 + . + ''; + example = { ncmpcpp_directory = "~/.local/share/ncmpcpp"; }; + }; + + bindings = mkOption { + type = types.listOf bindingType; + default = [ ]; + description = "List of keybindings."; + example = literalExpression '' + [ + { key = "j"; command = "scroll_down"; } + { key = "k"; command = "scroll_up"; } + { key = "J"; command = [ "select_item" "scroll_down" ]; } + { key = "K"; command = [ "select_item" "scroll_up" ]; } + ] + ''; + }; + }; + + config = mkIf cfg.enable { + warnings = mkIf (cfg.settings ? mpd_music_dir && cfg.mpdMusicDir != null) [ + ("programs.ncmpcpp.settings.mpd_music_dir will be overridden by" + + " programs.ncmpcpp.mpdMusicDir.") + ]; + + home.packages = [ cfg.package ]; + + xdg.configFile = { + "ncmpcpp/config" = let + settings = cfg.settings // optionalAttrs (cfg.mpdMusicDir != null) { + mpd_music_dir = toString cfg.mpdMusicDir; + }; + in mkIf (settings != { }) { text = renderSettings settings + "\n"; }; + + "ncmpcpp/bindings" = mkIf (cfg.bindings != [ ]) { + text = renderBindings cfg.bindings + "\n"; + }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/ncspot.nix b/infra/libkookie/home-manager-stable/modules/programs/ncspot.nix new file mode 100644 index 00000000000..3b6d401e61a --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/ncspot.nix @@ -0,0 +1,50 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.ncspot; + + tomlFormat = pkgs.formats.toml { }; + +in { + meta.maintainers = [ maintainers.marsam ]; + + options.programs.ncspot = { + enable = mkEnableOption "ncspot"; + + package = mkOption { + type = types.package; + default = pkgs.ncspot; + defaultText = literalExpression "pkgs.ncspot"; + description = "The package to use for ncspot."; + }; + + settings = mkOption { + type = tomlFormat.type; + default = { }; + example = literalExpression '' + { + shuffle = true; + gapless = true; + } + ''; + description = '' + Configuration written to + $XDG_CONFIG_HOME/ncspot/config.toml. + + See + for the full list of options. + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + + xdg.configFile."ncspot/config.toml" = mkIf (cfg.settings != { }) { + source = tomlFormat.generate "ncspot-config" cfg.settings; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/ne.nix b/infra/libkookie/home-manager-stable/modules/programs/ne.nix new file mode 100644 index 00000000000..1596066bc95 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/ne.nix @@ -0,0 +1,95 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.ne; + + autoPrefFiles = let + autoprefs = cfg.automaticPreferences + // optionalAttrs (cfg.defaultPreferences != "") { + ".default" = cfg.defaultPreferences; + }; + + gen = fileExtension: configText: + nameValuePair ".ne/${fileExtension}#ap" { + text = configText; + }; # Generates [path].text format expected by home.file. + in mapAttrs' gen autoprefs; + +in { + meta.maintainers = [ hm.maintainers.cwyc ]; + + options.programs.ne = { + enable = mkEnableOption "ne"; + + keybindings = mkOption { + type = types.lines; + default = ""; + example = '' + KEY 7f BS + SEQ "\x1b[1;5D" 7f + ''; + description = '' + Keybinding file for ne. + ''; + }; + + defaultPreferences = mkOption { + type = types.lines; + default = ""; + description = '' + Default preferences for ne. + + Equivalent to programs.ne.automaticPreferences.".default". + ''; + }; + + automaticPreferences = mkOption { + type = types.attrsOf types.lines; + default = { }; + example = literalExpression '' + { + nix = ''' + TAB 0 + TS 2 + '''; + js = ''' + TS 4 + '''; + } + ''; + description = '' + Automatic preferences files for ne. + ''; + }; + + menus = mkOption { + type = types.lines; + default = ""; + description = "Menu configuration file for ne."; + }; + + virtualExtensions = mkOption { + type = types.lines; + default = ""; + example = '' + sh 1 ^#!\s*/.*\b(bash|sh|ksh|zsh)\s* + csh 1 ^#!\s*/.*\b(csh|tcsh)\s* + ''; + description = "Virtual extensions configuration file for ne."; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ pkgs.ne ]; + + home.file = { + ".ne/.keys" = mkIf (cfg.keybindings != "") { text = cfg.keybindings; }; + ".ne/.extensions" = + mkIf (cfg.virtualExtensions != "") { text = cfg.virtualExtensions; }; + ".ne/.menus" = mkIf (cfg.menus != "") { text = cfg.menus; }; + } // autoPrefFiles; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/neomutt-accounts.nix b/infra/libkookie/home-manager-stable/modules/programs/neomutt-accounts.nix new file mode 100644 index 00000000000..94f97e914e9 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/neomutt-accounts.nix @@ -0,0 +1,67 @@ +{ config, lib, ... }: + +with lib; + +let + extraMailboxOptions = { + options = { + mailbox = mkOption { + type = types.str; + example = "Sent"; + description = "Name of mailbox folder to be included"; + }; + + name = mkOption { + type = types.nullOr types.str; + example = "Junk"; + default = null; + description = "Name to display"; + }; + }; + }; + +in { + options.neomutt = { + enable = mkEnableOption "NeoMutt"; + + sendMailCommand = mkOption { + type = types.nullOr types.str; + default = if config.msmtp.enable then + "msmtpq --read-envelope-from --read-recipients" + else + null; + defaultText = literalExpression '' + if config.msmtp.enable then + "msmtpq --read-envelope-from --read-recipients" + else + null + ''; + example = "msmtpq --read-envelope-from --read-recipients"; + description = '' + Command to send a mail. If not set, neomutt will be in charge of sending mails. + ''; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + example = "color status cyan default"; + description = '' + Extra lines to add to the folder hook for this account. + ''; + }; + + mailboxName = mkOption { + type = types.nullOr types.str; + default = null; + example = "==== ==="; + description = "Use a different name as mailbox name"; + }; + + extraMailboxes = mkOption { + type = with types; listOf (either str (submodule extraMailboxOptions)); + default = [ ]; + description = "List of extra mailboxes"; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/neomutt.nix b/infra/libkookie/home-manager-stable/modules/programs/neomutt.nix new file mode 100644 index 00000000000..75508303e26 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/neomutt.nix @@ -0,0 +1,380 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.neomutt; + + neomuttAccounts = + filter (a: a.neomutt.enable) (attrValues config.accounts.email.accounts); + + sidebarModule = types.submodule { + options = { + enable = mkEnableOption "sidebar support"; + + width = mkOption { + type = types.int; + default = 22; + description = "Width of the sidebar"; + }; + + shortPath = mkOption { + type = types.bool; + default = true; + description = '' + By default sidebar shows the full path of the mailbox, but + with this enabled only the relative name is shown. + ''; + }; + + format = mkOption { + type = types.str; + default = "%D%?F? [%F]?%* %?N?%N/?%S"; + description = '' + Sidebar format. Check neomutt documentation for details. + ''; + }; + }; + }; + + sortOptions = [ + "date" + "date-received" + "from" + "mailbox-order" + "score" + "size" + "spam" + "subject" + "threads" + "to" + ]; + + bindModule = types.submodule { + options = { + map = mkOption { + type = let + menus = [ + "alias" + "attach" + "browser" + "compose" + "editor" + "generic" + "index" + "mix" + "pager" + "pgp" + "postpone" + "query" + "smime" + ]; + in with types; either (enum menus) (listOf (enum menus)); + default = "index"; + description = "Select the menu to bind the command to."; + }; + + key = mkOption { + type = types.str; + example = ""; + description = "The key to bind."; + }; + + action = mkOption { + type = types.str; + example = "toggle sidebar_visible"; + description = "Specify the action to take."; + }; + }; + }; + + setOption = n: v: if v == null then "unset ${n}" else "set ${n}=${v}"; + escape = replaceStrings [ "%" ] [ "%25" ]; + + accountFilename = account: config.xdg.configHome + "/neomutt/" + account.name; + + genCommonFolderHooks = account: + with account; { + from = "'${address}'"; + realname = "'${realName}'"; + spoolfile = "'+${folders.inbox}'"; + record = if folders.sent == null then null else "'+${folders.sent}'"; + postponed = "'+${folders.drafts}'"; + trash = "'+${folders.trash}'"; + }; + + mtaSection = account: + with account; + let passCmd = concatStringsSep " " passwordCommand; + in if neomutt.sendMailCommand != null then { + sendmail = "'${neomutt.sendMailCommand}'"; + } else + let + smtpProto = if smtp.tls.enable then "smtps" else "smtp"; + smtpPort = if smtp.port != null then ":${toString smtp.port}" else ""; + smtpBaseUrl = + "${smtpProto}://${escape userName}@${smtp.host}${smtpPort}"; + in { + smtp_url = "'${smtpBaseUrl}'"; + smtp_pass = ''"`${passCmd}`"''; + }; + + genMaildirAccountConfig = account: + with account; + let + folderHook = mapAttrsToList setOption (genCommonFolderHooks account + // optionalAttrs cfg.changeFolderWhenSourcingAccount { + folder = "'${account.maildir.absPath}'"; + }); + in '' + ${concatStringsSep "\n" folderHook} + ''; + + registerAccount = account: + let + mailboxes = if account.neomutt.mailboxName == null then + "mailboxes" + else + ''named-mailboxes "${account.neomutt.mailboxName}"''; + extraMailboxes = concatMapStringsSep "\n" (extra: + if isString extra then + ''mailboxes "${account.maildir.absPath}/${extra}"'' + else if extra.name == null then + ''mailboxes "${account.maildir.absPath}/${extra.mailbox}"'' + else + '' + named-mailboxes "${extra.name}" "${account.maildir.absPath}/${extra.mailbox}"'') + account.neomutt.extraMailboxes; + in with account; '' + # register account ${name} + ${mailboxes} "${maildir.absPath}/${folders.inbox}" + ${extraMailboxes} + folder-hook ${maildir.absPath}/ " \ + source ${accountFilename account} " + ''; + + mraSection = account: + with account; + if account.maildir != null then + genMaildirAccountConfig account + else + throw "Only maildir is supported at the moment"; + + optionsStr = attrs: concatStringsSep "\n" (mapAttrsToList setOption attrs); + + sidebarSection = '' + # Sidebar + set sidebar_visible = yes + set sidebar_short_path = ${lib.hm.booleans.yesNo cfg.sidebar.shortPath} + set sidebar_width = ${toString cfg.sidebar.width} + set sidebar_format = '${cfg.sidebar.format}' + ''; + + genBindMapper = bindType: + concatMapStringsSep "\n" (bind: + '' + ${bindType} ${ + concatStringsSep "," (toList bind.map) + } ${bind.key} "${bind.action}"''); + + bindSection = (genBindMapper "bind") cfg.binds; + + macroSection = (genBindMapper "macro") cfg.macros; + + mailCheckSection = '' + set mail_check_stats + set mail_check_stats_interval = ${toString cfg.checkStatsInterval} + ''; + + notmuchSection = account: + with account; '' + # notmuch section + set nm_default_uri = "notmuch://${config.accounts.email.maildirBasePath}" + virtual-mailboxes "My INBOX" "notmuch://?query=tag:inbox" + ''; + + accountStr = account: + with account; + let + signature = if account.signature.showSignature == "none" then + "unset signature" + else if account.signature.command != null then + ''set signature = "${account.signature.command}|"'' + else + "set signature = ${ + pkgs.writeText "signature.txt" account.signature.text + }"; + in '' + # Generated by Home Manager. + set ssl_force_tls = yes + set certificate_file=${toString config.accounts.email.certificatesFile} + + # GPG section + set crypt_use_gpgme = yes + set crypt_autosign = ${lib.hm.booleans.yesNo (gpg.signByDefault or false)} + set crypt_opportunistic_encrypt = ${ + lib.hm.booleans.yesNo (gpg.encryptByDefault or false) + } + set pgp_use_gpg_agent = yes + set mbox_type = ${if maildir != null then "Maildir" else "mbox"} + set sort = "${cfg.sort}" + + # MTA section + ${optionsStr (mtaSection account)} + + ${optionalString (cfg.checkStatsInterval != null) mailCheckSection} + + ${optionalString cfg.sidebar.enable sidebarSection} + + # MRA section + ${mraSection account} + + # Extra configuration + ${account.neomutt.extraConfig} + + ${signature} + '' + optionalString account.notmuch.enable (notmuchSection account); + +in { + options = { + programs.neomutt = { + enable = mkEnableOption "the NeoMutt mail client"; + + package = mkOption { + type = types.package; + default = pkgs.neomutt; + defaultText = literalExpression "pkgs.neomutt"; + description = "The neomutt package to use."; + }; + + sidebar = mkOption { + type = sidebarModule; + default = { }; + description = "Options related to the sidebar."; + }; + + binds = mkOption { + type = types.listOf bindModule; + default = [ ]; + description = "List of keybindings."; + }; + + macros = mkOption { + type = types.listOf bindModule; + default = [ ]; + description = "List of macros."; + }; + + sort = mkOption { + # allow users to choose any option from sortOptions, or any option prefixed with "reverse-" + type = types.enum + (sortOptions ++ (map (option: "reverse-" + option) sortOptions)); + default = "threads"; + description = "Sorting method on messages."; + }; + + vimKeys = mkOption { + type = types.bool; + default = false; + description = "Enable vim-like bindings."; + }; + + checkStatsInterval = mkOption { + type = types.nullOr types.int; + default = null; + example = 60; + description = "Enable and set the interval of automatic mail check."; + }; + + editor = mkOption { + type = types.str; + default = "$EDITOR"; + description = "Select the editor used for writing mail."; + }; + + settings = mkOption { + type = types.attrsOf types.str; + default = { }; + description = "Extra configuration appended to the end."; + }; + + changeFolderWhenSourcingAccount = + mkEnableOption "changing the folder when sourcing an account" // { + default = true; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = "Extra configuration appended to the end."; + }; + }; + + accounts.email.accounts = mkOption { + type = with types; attrsOf (submodule (import ./neomutt-accounts.nix)); + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + home.file = let + rcFile = account: { + "${accountFilename account}".text = accountStr account; + }; + in foldl' (a: b: a // b) { } (map rcFile neomuttAccounts); + + xdg.configFile."neomutt/neomuttrc" = mkIf (neomuttAccounts != [ ]) { + text = let + # Find the primary account, if it has neomutt enabled; + # otherwise use the first neomutt account as primary. + primary = + head (filter (a: a.primary) neomuttAccounts ++ neomuttAccounts); + in '' + # Generated by Home Manager. + set header_cache = "${config.xdg.cacheHome}/neomutt/headers/" + set message_cachedir = "${config.xdg.cacheHome}/neomutt/messages/" + set editor = "${cfg.editor}" + set implicit_autoview = yes + + alternative_order text/enriched text/plain text + + set delete = yes + + # Binds + ${bindSection} + + # Macros + ${macroSection} + + ${optionalString cfg.vimKeys + "source ${pkgs.neomutt}/share/doc/neomutt/vim-keys/vim-keys.rc"} + + # Register accounts + ${concatMapStringsSep "\n" registerAccount neomuttAccounts} + + # Source primary account + source ${accountFilename primary} + + # Extra configuration + ${optionsStr cfg.settings} + + ${cfg.extraConfig} + ''; + }; + + assertions = [{ + assertion = + ((filter (b: (length (toList b.map)) == 0) (cfg.binds ++ cfg.macros)) + == [ ]); + message = + "The 'programs.neomutt.(binds|macros).map' list must contain at least one element."; + }]; + + warnings = + let hasOldBinds = binds: (filter (b: !(isList b.map)) binds) != [ ]; + in mkIf (hasOldBinds (cfg.binds ++ cfg.macros)) [ + "Specifying 'programs.neomutt.(binds|macros).map' as a string is deprecated, use a list of strings instead. See https://github.com/nix-community/home-manager/pull/1885." + ]; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/neovim.nix b/infra/libkookie/home-manager-stable/modules/programs/neovim.nix new file mode 100644 index 00000000000..91d573405c4 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/neovim.nix @@ -0,0 +1,424 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.neovim; + + jsonFormat = pkgs.formats.json { }; + + extraPython3PackageType = mkOptionType { + name = "extra-python3-packages"; + description = "python3 packages in python.withPackages format"; + check = with types; + (x: if isFunction x then isList (x pkgs.python3Packages) else false); + merge = mergeOneOption; + }; + + # Currently, upstream Neovim is pinned on Lua 5.1 for LuaJIT support. + # This will need to be updated if Neovim ever migrates to a newer + # version of Lua. + extraLua51PackageType = mkOptionType { + name = "extra-lua51-packages"; + description = "lua5.1 packages in lua5_1.withPackages format"; + check = with types; + (x: if isFunction x then isList (x pkgs.lua51Packages) else false); + merge = mergeOneOption; + }; + + pluginWithConfigType = types.submodule { + options = { + config = mkOption { + type = types.lines; + description = + "Script to configure this plugin. The scripting language should match type."; + default = ""; + }; + + type = mkOption { + type = + types.either (types.enum [ "lua" "viml" "teal" "fennel" ]) types.str; + description = + "Language used in config. Configurations are aggregated per-language."; + default = "viml"; + }; + + optional = mkEnableOption "optional" // { + description = "Don't load by default (load with :packadd)"; + }; + + plugin = mkOption { + type = types.package; + description = "vim plugin"; + }; + }; + }; + + # A function to get the configuration string (if any) from an element of 'plugins' + pluginConfig = p: + if p ? plugin && (p.config or "") != "" then '' + " ${p.plugin.pname or p.plugin.name} {{{ + ${p.config} + " }}} + '' else + ""; + + allPlugins = cfg.plugins ++ optional cfg.coc.enable { + type = "viml"; + plugin = cfg.coc.package; + config = cfg.coc.pluginConfig; + optional = false; + }; + + moduleConfigure = { + packages.home-manager = { + start = remove null (map + (x: if x ? plugin && x.optional == true then null else (x.plugin or x)) + allPlugins); + opt = remove null + (map (x: if x ? plugin && x.optional == true then x.plugin else null) + allPlugins); + }; + beforePlugins = ""; + }; + + extraMakeWrapperArgs = lib.optionalString (cfg.extraPackages != [ ]) + ''--suffix PATH : "${lib.makeBinPath cfg.extraPackages}"''; + extraMakeWrapperLuaCArgs = lib.optionalString (cfg.extraLuaPackages != [ ]) '' + --suffix LUA_CPATH ";" "${ + lib.concatMapStringsSep ";" pkgs.lua51Packages.getLuaCPath + cfg.extraLuaPackages + }"''; + extraMakeWrapperLuaArgs = lib.optionalString (cfg.extraLuaPackages != [ ]) '' + --suffix LUA_PATH ";" "${ + lib.concatMapStringsSep ";" pkgs.lua51Packages.getLuaPath + cfg.extraLuaPackages + }"''; + +in { + imports = [ + (mkRemovedOptionModule [ "programs" "neovim" "withPython" ] + "Python2 support has been removed from neovim.") + (mkRemovedOptionModule [ "programs" "neovim" "extraPythonPackages" ] + "Python2 support has been removed from neovim.") + ]; + + options = { + programs.neovim = { + enable = mkEnableOption "Neovim"; + + viAlias = mkOption { + type = types.bool; + default = false; + description = '' + Symlink vi to nvim binary. + ''; + }; + + vimAlias = mkOption { + type = types.bool; + default = false; + description = '' + Symlink vim to nvim binary. + ''; + }; + + vimdiffAlias = mkOption { + type = types.bool; + default = false; + description = '' + Alias vimdiff to nvim -d. + ''; + }; + + withNodeJs = mkOption { + type = types.bool; + default = false; + description = '' + Enable node provider. Set to true to + use Node plugins. + ''; + }; + + withRuby = mkOption { + type = types.nullOr types.bool; + default = true; + description = '' + Enable ruby provider. + ''; + }; + + withPython3 = mkOption { + type = types.bool; + default = true; + description = '' + Enable Python 3 provider. Set to true to + use Python 3 plugins. + ''; + }; + + extraPython3Packages = mkOption { + type = with types; either extraPython3PackageType (listOf package); + default = (_: [ ]); + defaultText = "ps: []"; + example = literalExpression "(ps: with ps; [ python-language-server ])"; + description = '' + A function in python.withPackages format, which returns a + list of Python 3 packages required for your plugins to work. + ''; + }; + + extraLuaPackages = mkOption { + type = with types; either extraLua51PackageType (listOf package); + default = [ ]; + defaultText = "[]"; + example = literalExpression "(ps: with ps; [ luautf8 ])"; + description = '' + A function in lua5_1.withPackages format, which returns a + list of Lua packages required for your plugins to work. + ''; + }; + + generatedConfigViml = mkOption { + type = types.lines; + visible = true; + readOnly = true; + description = '' + Generated vimscript config. + ''; + }; + + generatedConfigs = mkOption { + type = types.attrsOf types.lines; + visible = true; + readOnly = true; + example = literalExpression '' + { + viml = ''' + " Generated by home-manager + set packpath^=/nix/store/cn8vvv4ymxjf8cfzg7db15b2838nqqib-vim-pack-dir + set runtimepath^=/nix/store/cn8vvv4ymxjf8cfzg7db15b2838nqqib-vim-pack-dir + '''; + + lua = ''' + -- Generated by home-manager + vim.opt.background = "dark" + '''; + }''; + description = '' + Generated configurations with as key their language (set via type). + ''; + }; + + package = mkOption { + type = types.package; + default = pkgs.neovim-unwrapped; + defaultText = literalExpression "pkgs.neovim-unwrapped"; + description = "The package to use for the neovim binary."; + }; + + finalPackage = mkOption { + type = types.package; + visible = false; + readOnly = true; + description = "Resulting customized neovim package."; + }; + + configure = mkOption { + type = types.attrsOf types.anything; + default = { }; + example = literalExpression '' + configure = { + customRC = $'''' + " here your custom configuration goes! + $''''; + packages.myVimPackage = with pkgs.vimPlugins; { + # loaded on launch + start = [ fugitive ]; + # manually loadable by calling `:packadd $plugin-name` + opt = [ ]; + }; + }; + ''; + description = '' + Deprecated. Please use the other options. + + Generate your init file from your list of plugins and custom commands, + and loads it from the store via nvim -u /nix/store/hash-vimrc + + + + This option is mutually exclusive with extraConfig + and plugins. + ''; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + example = '' + set nocompatible + set nobackup + ''; + description = '' + Custom vimrc lines. + + + + This option is mutually exclusive with configure. + ''; + }; + + extraPackages = mkOption { + type = with types; listOf package; + default = [ ]; + example = "[ pkgs.shfmt ]"; + description = "Extra packages available to nvim."; + }; + + plugins = mkOption { + type = with types; listOf (either package pluginWithConfigType); + default = [ ]; + example = literalExpression '' + with pkgs.vimPlugins; [ + yankring + vim-nix + { plugin = vim-startify; + config = "let g:startify_change_to_vcs_root = 0"; + } + ] + ''; + description = '' + List of vim plugins to install optionally associated with + configuration to be placed in init.vim. + + + + This option is mutually exclusive with configure. + ''; + }; + + coc = { + enable = mkEnableOption "Coc"; + + package = mkOption { + type = types.package; + default = pkgs.vimPlugins.coc-nvim; + defaultText = literalExpression "pkgs.vimPlugins.coc-nvim"; + description = "The package to use for the CoC plugin."; + }; + + settings = mkOption { + type = jsonFormat.type; + default = { }; + example = literalExpression '' + { + "suggest.noselect" = true; + "suggest.enablePreview" = true; + "suggest.enablePreselect" = false; + "suggest.disableKind" = true; + languageserver = { + haskell = { + command = "haskell-language-server-wrapper"; + args = [ "--lsp" ]; + rootPatterns = [ + "*.cabal" + "stack.yaml" + "cabal.project" + "package.yaml" + "hie.yaml" + ]; + filetypes = [ "haskell" "lhaskell" ]; + }; + }; + }; + ''; + description = '' + Extra configuration lines to add to + $XDG_CONFIG_HOME/nvim/coc-settings.json + See + + for options. + ''; + }; + + pluginConfig = mkOption { + type = types.lines; + default = ""; + description = "Script to configure CoC. Must be viml."; + }; + }; + }; + }; + + config = let + # transform all plugins into an attrset + pluginsNormalized = map (x: + if (x ? plugin) then + x + else { + type = x.type or "viml"; + plugin = x; + config = ""; + optional = false; + }) allPlugins; + suppressNotVimlConfig = p: + if p.type != "viml" then p // { config = ""; } else p; + + neovimConfig = pkgs.neovimUtils.makeNeovimConfig { + inherit (cfg) extraPython3Packages withPython3 withRuby viAlias vimAlias; + withNodeJs = cfg.withNodeJs or cfg.coc.enable; + configure = cfg.configure // moduleConfigure; + plugins = map suppressNotVimlConfig pluginsNormalized; + customRC = cfg.extraConfig; + }; + + in mkIf cfg.enable { + warnings = optional (cfg.configure != { }) '' + programs.neovim.configure is deprecated. + Other programs.neovim options can override its settings or ignore them. + Please use the other options at your disposal: + configure.packages.*.opt -> programs.neovim.plugins = [ { plugin = ...; optional = true; }] + configure.packages.*.start -> programs.neovim.plugins = [ { plugin = ...; }] + configure.customRC -> programs.neovim.extraConfig + ''; + + programs.neovim.generatedConfigViml = neovimConfig.neovimRcContent; + + programs.neovim.generatedConfigs = let + grouped = lib.lists.groupBy (x: x.type) pluginsNormalized; + concatConfigs = lib.concatMapStrings (p: p.config); + in mapAttrs (name: vals: concatConfigs vals) grouped; + + home.packages = [ cfg.finalPackage ]; + + xdg.configFile."nvim/init.vim" = mkIf (neovimConfig.neovimRcContent != "") { + text = if hasAttr "lua" config.programs.neovim.generatedConfigs then + neovimConfig.neovimRcContent + '' + + lua require('init-home-manager')'' + else + neovimConfig.neovimRcContent; + }; + xdg.configFile."nvim/lua/init-home-manager.lua" = + mkIf (hasAttr "lua" config.programs.neovim.generatedConfigs) { + text = config.programs.neovim.generatedConfigs.lua; + }; + xdg.configFile."nvim/coc-settings.json" = mkIf cfg.coc.enable { + source = jsonFormat.generate "coc-settings.json" cfg.coc.settings; + }; + + programs.neovim.finalPackage = pkgs.wrapNeovimUnstable cfg.package + (neovimConfig // { + wrapperArgs = (lib.escapeShellArgs neovimConfig.wrapperArgs) + " " + + extraMakeWrapperArgs + " " + extraMakeWrapperLuaCArgs + " " + + extraMakeWrapperLuaArgs; + wrapRc = false; + }); + + programs.bash.shellAliases = mkIf cfg.vimdiffAlias { vimdiff = "nvim -d"; }; + programs.fish.shellAliases = mkIf cfg.vimdiffAlias { vimdiff = "nvim -d"; }; + programs.zsh.shellAliases = mkIf cfg.vimdiffAlias { vimdiff = "nvim -d"; }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/newsboat.nix b/infra/libkookie/home-manager-stable/modules/programs/newsboat.nix new file mode 100644 index 00000000000..ba074a421a2 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/newsboat.nix @@ -0,0 +1,137 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.programs.newsboat; + wrapQuote = x: ''"${x}"''; + + urlsFileContents = let + mkUrlEntry = u: + concatStringsSep " " ([ u.url ] ++ map wrapQuote u.tags + ++ optional (u.title != null) (wrapQuote "~${u.title}")); + urls = map mkUrlEntry cfg.urls; + + mkQueryEntry = n: v: ''"query:${n}:${escape [ ''"'' ] v}"''; + queries = mapAttrsToList mkQueryEntry cfg.queries; + in concatStringsSep "\n" + (if versionAtLeast config.home.stateVersion "20.03" then + queries ++ urls + else + urls ++ queries) + "\n"; + + configFileContents = '' + max-items ${toString cfg.maxItems} + browser ${cfg.browser} + reload-threads ${toString cfg.reloadThreads} + auto-reload ${lib.hm.booleans.yesNo cfg.autoReload} + ${optionalString (cfg.reloadTime != null) + (toString "reload-time ${toString cfg.reloadTime}")} + prepopulate-query-feeds yes + + ${cfg.extraConfig} + ''; + +in { + meta.maintainers = [ maintainers.sumnerevans ]; + + options = { + programs.newsboat = { + enable = mkEnableOption "the Newsboat feed reader"; + + urls = mkOption { + type = types.listOf (types.submodule { + options = { + url = mkOption { + type = types.str; + example = "http://example.com"; + description = "Feed URL."; + }; + + tags = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "foo" "bar" ]; + description = "Feed tags."; + }; + + title = mkOption { + type = types.nullOr types.str; + default = null; + example = "ORF News"; + description = "Feed title."; + }; + }; + }); + default = [ ]; + example = [{ + url = "http://example.com"; + tags = [ "foo" "bar" ]; + }]; + description = "List of news feeds."; + }; + + maxItems = mkOption { + type = types.int; + default = 0; + description = "Maximum number of items per feed, 0 for infinite."; + }; + + reloadThreads = mkOption { + type = types.int; + default = 5; + description = "How many threads to use for updating the feeds."; + }; + + autoReload = mkOption { + type = types.bool; + default = false; + description = '' + Whether to enable automatic reloading while newsboat is running. + ''; + }; + + reloadTime = mkOption { + type = types.nullOr types.int; + default = 60; + description = "Time in minutes between reloads."; + }; + + browser = mkOption { + type = types.str; + default = "${pkgs.xdg-utils}/bin/xdg-open"; + description = "External browser to use."; + }; + + queries = mkOption { + type = types.attrsOf types.str; + default = { }; + example = { "foo" = ''rssurl =~ "example.com"''; }; + description = "A list of queries to use."; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Extra configuration values that will be appended to the end. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ pkgs.newsboat ]; + + # Use ~/.newsboat on stateVersion < 21.05 and use ~/.config/newsboat for + # stateVersion >= 21.05. + home.file = mkIf (versionOlder config.home.stateVersion "21.05") { + ".newsboat/urls".text = urlsFileContents; + ".newsboat/config".text = configFileContents; + }; + xdg.configFile = mkIf (versionAtLeast config.home.stateVersion "21.05") { + "newsboat/urls".text = urlsFileContents; + "newsboat/config".text = configFileContents; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/nix-index.nix b/infra/libkookie/home-manager-stable/modules/programs/nix-index.nix new file mode 100644 index 00000000000..2593d8b7cbc --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/nix-index.nix @@ -0,0 +1,63 @@ +{ config, lib, pkgs, ... }: +let cfg = config.programs.nix-index; +in { + meta.maintainers = with lib.hm.maintainers; [ ambroisie ]; + + options.programs.nix-index = with lib; { + enable = mkEnableOption "nix-index, a file database for nixpkgs"; + + package = mkOption { + type = types.package; + default = pkgs.nix-index; + defaultText = literalExpression "pkgs.nix-index"; + description = "Package providing the nix-index tool."; + }; + + enableBashIntegration = mkEnableOption "Bash integration" // { + default = true; + }; + + enableZshIntegration = mkEnableOption "Zsh integration" // { + default = true; + }; + + enableFishIntegration = mkEnableOption "Fish integration" // { + default = true; + }; + }; + + config = lib.mkIf cfg.enable { + assertions = let + checkOpt = name: { + assertion = cfg.${name} -> !config.programs.command-not-found.enable; + message = '' + The 'programs.command-not-found.enable' option is mutually exclusive + with the 'programs.nix-index.${name}' option. + ''; + }; + in [ (checkOpt "enableBashIntegration") (checkOpt "enableZshIntegration") ]; + + home.packages = [ cfg.package ]; + + programs.bash.initExtra = lib.mkIf cfg.enableBashIntegration '' + source ${cfg.package}/etc/profile.d/command-not-found.sh + ''; + + programs.zsh.initExtra = lib.mkIf cfg.enableZshIntegration '' + source ${cfg.package}/etc/profile.d/command-not-found.sh + ''; + + # See https://github.com/bennofs/nix-index/issues/126 + programs.fish.shellInit = let + wrapper = pkgs.writeScript "command-not-found" '' + #!${pkgs.bash}/bin/bash + source ${cfg.package}/etc/profile.d/command-not-found.sh + command_not_found_handle "$@" + ''; + in lib.mkIf cfg.enableFishIntegration '' + function __fish_command_not_found_handler --on-event fish_command_not_found + ${wrapper} $argv + end + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/nnn.nix b/infra/libkookie/home-manager-stable/modules/programs/nnn.nix new file mode 100644 index 00000000000..a32ac723b85 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/nnn.nix @@ -0,0 +1,129 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.programs.nnn; + + renderSetting = key: value: "${key}:${value}"; + + renderSettings = settings: + concatStringsSep ";" (mapAttrsToList renderSetting settings); + + pluginModule = types.submodule ({ ... }: { + options = { + src = mkOption { + type = with types; nullOr path; + example = literalExpression '' + (pkgs.fetchFromGitHub { + owner = "jarun"; + repo = "nnn"; + rev = "v4.0"; + sha256 = "sha256-Hpc8YaJeAzJoEi7aJ6DntH2VLkoR6ToP6tPYn3llR7k="; + }) + "/plugins"; + ''; + default = null; + description = '' + Path to the plugin folder. + ''; + }; + + mappings = mkOption { + type = with types; attrsOf str; + description = '' + Key mappings to the plugins. + ''; + default = { }; + example = literalExpression '' + { + c = "fzcd"; + f = "finder"; + v = "imgview"; + }; + ''; + }; + }; + }); +in { + meta.maintainers = with maintainers; [ thiagokokada ]; + + options = { + programs.nnn = { + enable = mkEnableOption "nnn"; + + package = mkOption { + type = types.package; + default = pkgs.nnn; + defaultText = literalExpression "pkgs.nnn"; + example = + literalExpression "pkgs.nnn.override ({ withNerdIcons = true; });"; + description = '' + Package containing the nnn program. + ''; + }; + + finalPackage = mkOption { + type = types.package; + readOnly = true; + visible = false; + description = '' + Resulting nnn package. + ''; + }; + + bookmarks = mkOption { + type = with types; attrsOf str; + description = '' + Directory bookmarks. + ''; + example = literalExpression '' + { + d = "~/Documents"; + D = "~/Downloads"; + p = "~/Pictures"; + v = "~/Videos"; + }; + ''; + default = { }; + }; + + extraPackages = mkOption { + type = with types; listOf package; + example = + literalExpression "with pkgs; [ ffmpegthumbnailer mediainfo sxiv ]"; + description = '' + Extra packages available to nnn. + ''; + default = [ ]; + }; + + plugins = mkOption { + type = pluginModule; + description = '' + Manage nnn plugins. + ''; + default = { }; + }; + }; + }; + + config = let + nnnPackage = cfg.package.overrideAttrs (oldAttrs: { + nativeBuildInputs = (oldAttrs.nativeBuildInputs or [ ]) + ++ [ pkgs.makeWrapper ]; + postInstall = '' + ${oldAttrs.postInstall or ""} + + wrapProgram $out/bin/nnn \ + --prefix PATH : "${makeBinPath cfg.extraPackages}" \ + --prefix NNN_BMS : "${renderSettings cfg.bookmarks}" \ + --prefix NNN_PLUG : "${renderSettings cfg.plugins.mappings}" + ''; + }); + in mkIf cfg.enable { + programs.nnn.finalPackage = nnnPackage; + home.packages = [ nnnPackage ]; + xdg.configFile."nnn/plugins" = + mkIf (cfg.plugins.src != null) { source = cfg.plugins.src; }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/noti.nix b/infra/libkookie/home-manager-stable/modules/programs/noti.nix new file mode 100644 index 00000000000..d8affdd53e4 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/noti.nix @@ -0,0 +1,50 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.noti; + +in { + meta.maintainers = [ maintainers.marsam ]; + + options.programs.noti = { + enable = mkEnableOption "Noti"; + + settings = mkOption { + type = types.attrsOf (types.attrsOf types.str); + default = { }; + description = '' + Configuration written to + $XDG_CONFIG_HOME/noti/noti.yaml. + + See + + noti.yaml + 5 + . + for the full list of options. + ''; + example = literalExpression '' + { + say = { + voice = "Alex"; + }; + slack = { + token = "1234567890abcdefg"; + channel = "@jaime"; + }; + } + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ pkgs.noti ]; + + xdg.configFile."noti/noti.yaml" = + mkIf (cfg.settings != { }) { text = generators.toYAML { } cfg.settings; }; + }; + +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/notmuch.nix b/infra/libkookie/home-manager-stable/modules/programs/notmuch.nix new file mode 100644 index 00000000000..9c1c9f5c0e4 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/notmuch.nix @@ -0,0 +1,198 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.notmuch; + + mkIniKeyValue = key: value: + let + tweakVal = v: + if isString v then + v + else if isList v then + concatMapStringsSep ";" tweakVal v + else if isBool v then + (if v then "true" else "false") + else + toString v; + in "${key}=${tweakVal value}"; + + notmuchIni = recursiveUpdate { + database = { path = config.accounts.email.maildirBasePath; }; + + maildir = { synchronize_flags = cfg.maildir.synchronizeFlags; }; + + new = { + ignore = cfg.new.ignore; + tags = cfg.new.tags; + }; + + user = let + accounts = filter (a: a.notmuch.enable) + (attrValues config.accounts.email.accounts); + primary = filter (a: a.primary) accounts; + secondaries = filter (a: !a.primary) accounts; + in { + name = catAttrs "realName" primary; + primary_email = catAttrs "address" primary; + other_email = catAttrs "aliases" primary ++ catAttrs "address" secondaries + ++ catAttrs "aliases" secondaries; + }; + + search = { exclude_tags = cfg.search.excludeTags; }; + } cfg.extraConfig; + +in { + options = { + programs.notmuch = { + enable = mkEnableOption "Notmuch mail indexer"; + + new = mkOption { + type = types.submodule { + options = { + ignore = mkOption { + type = types.listOf types.str; + default = [ ]; + description = '' + A list to specify files and directories that will not be + searched for messages by notmuch new. + ''; + }; + + tags = mkOption { + type = types.listOf types.str; + default = [ "unread" "inbox" ]; + example = [ "new" ]; + description = '' + A list of tags that will be added to all messages + incorporated by notmuch new. + ''; + }; + }; + }; + default = { }; + description = '' + Options related to email processing performed by + notmuch new. + ''; + }; + + extraConfig = mkOption { + type = types.attrsOf (types.attrsOf types.str); + default = { }; + description = '' + Options that should be appended to the notmuch configuration file. + ''; + }; + + hooks = { + preNew = mkOption { + type = types.lines; + default = ""; + example = "mbsync --all"; + description = '' + Bash statements run before scanning or importing new + messages into the database. + ''; + }; + + postNew = mkOption { + type = types.lines; + default = ""; + example = '' + notmuch tag +nixos -- tag:new and from:nixos1@discoursemail.com + ''; + description = '' + Bash statements run after new messages have been imported + into the database and initial tags have been applied. + ''; + }; + + postInsert = mkOption { + type = types.lines; + default = ""; + description = '' + Bash statements run after a message has been inserted + into the database and initial tags have been applied. + ''; + }; + }; + + maildir = { + synchronizeFlags = mkOption { + type = types.bool; + default = true; + description = '' + Whether to synchronize Maildir flags. + ''; + }; + }; + + search = { + excludeTags = mkOption { + type = types.listOf types.str; + default = [ "deleted" "spam" ]; + example = [ "trash" "spam" ]; + description = '' + A list of tags that will be excluded from search results by + default. Using an excluded tag in a query will override that + exclusion. + ''; + }; + }; + }; + + accounts.email.accounts = mkOption { + type = with types; + attrsOf (submodule { + options.notmuch.enable = mkEnableOption "notmuch indexing"; + }); + }; + }; + + config = mkIf cfg.enable { + assertions = [ + { + assertion = notmuchIni.user.name != [ ]; + message = "notmuch: Must have a user name set."; + } + { + assertion = notmuchIni.user.primary_email != [ ]; + message = "notmuch: Must have a user primary email address set."; + } + ]; + + home.packages = [ pkgs.notmuch ]; + + home.sessionVariables = { + NOTMUCH_CONFIG = "${config.xdg.configHome}/notmuch/default/config"; + NMBGIT = "${config.xdg.dataHome}/notmuch/nmbug"; + }; + + xdg.configFile = let + hook = name: cmds: { + "notmuch/default/hooks/${name}".source = pkgs.writeShellScript name '' + export PATH="${pkgs.notmuch}/bin''${PATH:+:}$PATH" + export NOTMUCH_CONFIG="${config.xdg.configHome}/notmuch/default/config" + export NMBGIT="${config.xdg.dataHome}/notmuch/nmbug" + + ${cmds} + ''; + }; + in { + "notmuch/default/config".text = + let toIni = generators.toINI { mkKeyValue = mkIniKeyValue; }; + in '' + # Generated by Home Manager. + + '' + toIni notmuchIni; + } + // optionalAttrs (cfg.hooks.preNew != "") (hook "pre-new" cfg.hooks.preNew) + // optionalAttrs (cfg.hooks.postNew != "") + (hook "post-new" cfg.hooks.postNew) + // optionalAttrs (cfg.hooks.postInsert != "") + (hook "post-insert" cfg.hooks.postInsert); + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/nushell.nix b/infra/libkookie/home-manager-stable/modules/programs/nushell.nix new file mode 100644 index 00000000000..4d6ab43a71b --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/nushell.nix @@ -0,0 +1,60 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.nushell; + + tomlFormat = pkgs.formats.toml { }; + +in { + meta.maintainers = [ maintainers.Philipp-M ]; + + options.programs.nushell = { + enable = mkEnableOption "nushell"; + + package = mkOption { + type = types.package; + default = pkgs.nushell; + defaultText = literalExpression "pkgs.nushell"; + description = "The package to use for nushell."; + }; + + settings = mkOption { + type = with types; + let + prim = oneOf [ bool int str ]; + primOrPrimAttrs = either prim (attrsOf prim); + entry = either prim (listOf primOrPrimAttrs); + entryOrAttrsOf = t: either entry (attrsOf t); + entries = entryOrAttrsOf (entryOrAttrsOf entry); + in attrsOf entries // { description = "Nushell configuration"; }; + default = { }; + example = literalExpression '' + { + edit_mode = "vi"; + startup = [ "alias la [] { ls -a }" "alias e [msg] { echo $msg }" ]; + key_timeout = 10; + completion_mode = "circular"; + no_auto_pivot = true; + } + ''; + description = '' + Configuration written to + $XDG_CONFIG_HOME/nushell/config.toml. + + See for the full list + of options. + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + + xdg.configFile."nu/config.toml" = mkIf (cfg.settings != { }) { + source = tomlFormat.generate "nushell-config" cfg.settings; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/obs-studio.nix b/infra/libkookie/home-manager-stable/modules/programs/obs-studio.nix new file mode 100644 index 00000000000..ba5c891915d --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/obs-studio.nix @@ -0,0 +1,48 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.obs-studio; + +in { + meta.maintainers = [ maintainers.adisbladis ]; + + options = { + programs.obs-studio = { + enable = mkEnableOption "obs-studio"; + + package = mkOption { + type = types.package; + default = pkgs.obs-studio; + defaultText = literalExpression "pkgs.obs-studio"; + description = '' + OBS Studio package to install. + ''; + }; + + finalPackage = mkOption { + type = types.package; + visible = false; + readOnly = true; + description = "Resulting customized OBS Studio package."; + }; + + plugins = mkOption { + default = [ ]; + example = literalExpression "[ pkgs.obs-studio-plugins.wlrobs ]"; + description = "Optional OBS plugins."; + type = types.listOf types.package; + }; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.finalPackage ]; + programs.obs-studio.finalPackage = + pkgs.wrapOBS.override { obs-studio = cfg.package; } { + plugins = cfg.plugins; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/octant.nix b/infra/libkookie/home-manager-stable/modules/programs/octant.nix new file mode 100644 index 00000000000..f3b810c9041 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/octant.nix @@ -0,0 +1,51 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.octant; + + mkPluginEnv = packages: + let + pluginDirs = map (pkg: "${pkg}/bin") packages; + plugins = concatMapStringsSep " " (p: "${p}/*") pluginDirs; + in pkgs.runCommandLocal "octant-plugins" { } '' + mkdir $out + [[ '${plugins}' ]] || exit 0 + for plugin in ${plugins}; do + ln -s "$plugin" $out/ + done + ''; + +in { + meta.maintainers = with maintainers; [ jk ]; + + options = { + programs.octant = { + enable = mkEnableOption "octant"; + + package = mkOption { + type = types.package; + default = pkgs.octant; + defaultText = literalExpression "pkgs.octant"; + example = literalExpression "pkgs.octant-other"; + description = "The Octant package to use."; + }; + + plugins = mkOption { + default = [ ]; + example = literalExpression "[ pkgs.starboard-octant-plugin ]"; + description = "Optional Octant plugins."; + type = types.listOf types.package; + }; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + + xdg.configFile."octant/plugins" = + mkIf (cfg.plugins != [ ]) { source = mkPluginEnv cfg.plugins; }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/offlineimap-accounts.nix b/infra/libkookie/home-manager-stable/modules/programs/offlineimap-accounts.nix new file mode 100644 index 00000000000..afc7a019972 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/offlineimap-accounts.nix @@ -0,0 +1,51 @@ +{ config, lib, ... }: + +with lib; + +let + + extraConfigType = with types; attrsOf (either (either str int) bool); + +in { + options.offlineimap = { + enable = mkEnableOption "OfflineIMAP"; + + extraConfig.account = mkOption { + type = extraConfigType; + default = { }; + example = { autorefresh = 20; }; + description = '' + Extra configuration options to add to the account section. + ''; + }; + + extraConfig.local = mkOption { + type = extraConfigType; + default = { }; + example = { sync_deletes = true; }; + description = '' + Extra configuration options to add to the local account + section. + ''; + }; + + extraConfig.remote = mkOption { + type = extraConfigType; + default = { }; + example = { + maxconnections = 2; + expunge = false; + }; + description = '' + Extra configuration options to add to the remote account + section. + ''; + }; + + postSyncHookCommand = mkOption { + type = types.lines; + default = ""; + description = "Command to run after fetching new mails."; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/offlineimap.nix b/infra/libkookie/home-manager-stable/modules/programs/offlineimap.nix new file mode 100644 index 00000000000..c5b800599e1 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/offlineimap.nix @@ -0,0 +1,187 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.offlineimap; + + accounts = filter (a: a.offlineimap.enable) + (attrValues config.accounts.email.accounts); + + toIni = generators.toINI { + mkKeyValue = key: value: + let + value' = + (if isBool value then lib.hm.booleans.yesNo else toString) value; + in "${key} = ${value'}"; + }; + + # Generates a script to fetch only a specific account. + # + # Note, these scripts are not actually created and installed at the + # moment. It will need some thinking on whether this is a good idea + # and whether other modules should have some similar functionality. + # + # Perhaps have a single tool `email` that wraps the command? + # Something like + # + # $ email + genOfflineImapScript = account: + with account; + pkgs.writeShellScriptBin "offlineimap-${name}" '' + exec ${pkgs.offlineimap}/bin/offlineimap -a${account.name} "$@" + ''; + + accountStr = account: + with account; + let + postSyncHook = optionalAttrs (offlineimap.postSyncHookCommand != "") { + postsynchook = pkgs.writeShellScriptBin "postsynchook" + offlineimap.postSyncHookCommand + "/bin/postsynchook"; + }; + + localType = + if account.flavor == "gmail.com" then "GmailMaildir" else "Maildir"; + + remoteType = if account.flavor == "gmail.com" then "Gmail" else "IMAP"; + + remoteHost = + optionalAttrs (imap.host != null) { remotehost = imap.host; }; + + remotePort = + optionalAttrs ((imap.port or null) != null) { remoteport = imap.port; }; + + ssl = if imap.tls.enable then { + ssl = true; + sslcacertfile = toString imap.tls.certificatesFile; + starttls = imap.tls.useStartTls; + } else { + ssl = false; + }; + + remotePassEval = + let arglist = concatMapStringsSep "," (x: "'${x}'") passwordCommand; + in optionalAttrs (passwordCommand != null) { + remotepasseval = ''get_pass("${name}", [${arglist}]).strip(b"\n")''; + }; + in toIni { + "Account ${name}" = { + localrepository = "${name}-local"; + remoterepository = "${name}-remote"; + } // postSyncHook // offlineimap.extraConfig.account; + + "Repository ${name}-local" = { + type = localType; + localfolders = maildir.absPath; + } // offlineimap.extraConfig.local; + + "Repository ${name}-remote" = { + type = remoteType; + remoteuser = userName; + } // remoteHost // remotePort // remotePassEval // ssl + // offlineimap.extraConfig.remote; + }; + + extraConfigType = with types; attrsOf (either (either str int) bool); + +in { + options = { + programs.offlineimap = { + enable = mkEnableOption "OfflineIMAP"; + + pythonFile = mkOption { + type = types.lines; + default = '' + import subprocess + + def get_pass(service, cmd): + return subprocess.check_output(cmd, ) + ''; + description = '' + Python code that can then be used in other parts of the + configuration. + ''; + }; + + extraConfig.general = mkOption { + type = extraConfigType; + default = { }; + example = { + maxage = 30; + ui = "blinkenlights"; + }; + description = '' + Extra configuration options added to the + section. + ''; + }; + + extraConfig.default = mkOption { + type = extraConfigType; + default = { }; + example = { gmailtrashfolder = "[Gmail]/Papierkorb"; }; + description = '' + Extra configuration options added to the + section. + ''; + }; + + extraConfig.mbnames = mkOption { + type = extraConfigType; + default = { }; + example = literalExpression '' + { + filename = "~/.config/mutt/mailboxes"; + header = "'mailboxes '"; + peritem = "'+%(accountname)s/%(foldername)s'"; + sep = "' '"; + footer = "'\\n'"; + } + ''; + description = '' + Extra configuration options added to the + mbnames section. + ''; + }; + }; + + accounts.email.accounts = mkOption { + type = with types; + attrsOf (submodule (import ./offlineimap-accounts.nix)); + }; + }; + + config = mkIf cfg.enable { + home.packages = [ pkgs.offlineimap ]; + + xdg.configFile."offlineimap/get_settings.py".text = cfg.pythonFile; + xdg.configFile."offlineimap/get_settings.pyc".source = "${ + pkgs.runCommandLocal "get_settings-compile" { + nativeBuildInputs = [ pkgs.offlineimap ]; + pythonFile = cfg.pythonFile; + passAsFile = [ "pythonFile" ]; + } '' + mkdir -p $out/bin + cp $pythonFilePath $out/bin/get_settings.py + python -m py_compile $out/bin/get_settings.py + '' + }/bin/get_settings.pyc"; + + xdg.configFile."offlineimap/config".text = '' + # Generated by Home Manager. + # See https://github.com/OfflineIMAP/offlineimap/blob/master/offlineimap.conf + # for an exhaustive list of options. + '' + toIni ({ + general = { + accounts = concatMapStringsSep "," (a: a.name) accounts; + pythonfile = "${config.xdg.configHome}/offlineimap/get_settings.py"; + metadata = "${config.xdg.dataHome}/offlineimap"; + } // cfg.extraConfig.general; + } // optionalAttrs (cfg.extraConfig.mbnames != { }) { + mbnames = { enabled = true; } // cfg.extraConfig.mbnames; + } // optionalAttrs (cfg.extraConfig.default != { }) { + DEFAULT = cfg.extraConfig.default; + }) + "\n" + concatStringsSep "\n" (map accountStr accounts); + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/opam.nix b/infra/libkookie/home-manager-stable/modules/programs/opam.nix new file mode 100644 index 00000000000..9cd76d9565b --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/opam.nix @@ -0,0 +1,50 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.opam; + +in { + meta.maintainers = [ maintainers.marsam ]; + + options.programs.opam = { + enable = mkEnableOption "Opam"; + + package = mkOption { + type = types.package; + default = pkgs.opam; + defaultText = literalExpression "pkgs.opam"; + description = "Opam package to install."; + }; + + enableBashIntegration = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable Bash integration. + ''; + }; + + enableZshIntegration = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable Zsh integration. + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + + programs.bash.initExtra = mkIf cfg.enableBashIntegration '' + eval "$(${cfg.package}/bin/opam env --shell=bash)" + ''; + + programs.zsh.initExtra = mkIf cfg.enableZshIntegration '' + eval "$(${cfg.package}/bin/opam env --shell=zsh)" + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/pandoc.nix b/infra/libkookie/home-manager-stable/modules/programs/pandoc.nix new file mode 100644 index 00000000000..7f0fa713cdf --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/pandoc.nix @@ -0,0 +1,104 @@ +{ config, lib, pkgs, ... }: + +let + + cfg = config.programs.pandoc; + + inherit (lib) literalExpression mkEnableOption mkIf mkOption types; + + jsonFormat = pkgs.formats.json { }; + + makeTemplateFile = name: file: + lib.nameValuePair "pandoc/templates/${name}" { source = file; }; + + getFileName = file: + # This is actually safe here, since it is just a file name + builtins.unsafeDiscardStringContext (baseNameOf file); + + makeCslFile = file: + lib.nameValuePair "pandoc/csl/${getFileName file}" { source = file; }; + +in { + meta.maintainers = [ lib.maintainers.kirelagin ]; + + options.programs.pandoc = { + enable = mkEnableOption "pandoc"; + + package = mkOption { + type = types.package; + default = pkgs.pandoc; + defaultText = literalExpression "pkgs.pandoc"; + description = "The pandoc package to use."; + }; + + # We wrap the executable to pass some arguments + finalPackage = mkOption { + type = types.package; + readOnly = true; + description = "Resulting package."; + }; + + defaults = mkOption { + type = jsonFormat.type; + default = { }; + example = literalExpression '' + { + metadata = { + author = "John Doe"; + }; + pdf-engine = "xelatex"; + citeproc = true; + } + ''; + description = '' + Options to set by default. + These will be converted to JSON and written to a defaults + file (see Default files in pandoc documentation). + ''; + }; + + defaultsFile = mkOption { + type = types.path; + readOnly = true; + description = "Resulting defaults file."; + }; + + templates = mkOption { + type = types.attrsOf types.path; + default = { }; + example = literalExpression '' + { + "default.latex" = path/to/your/template; + } + ''; + description = "Custom templates."; + }; + + citationStyles = mkOption { + type = types.listOf types.path; + default = [ ]; + example = literalExpression "[ path/to/file.csl ]"; + description = "List of .csl files to install."; + }; + }; + + config = mkIf cfg.enable { + programs.pandoc = { + defaultsFile = jsonFormat.generate "hm.json" cfg.defaults; + + finalPackage = pkgs.symlinkJoin { + name = "pandoc-with-defaults"; + paths = [ cfg.package ]; + nativeBuildInputs = [ pkgs.makeWrapper ]; + postBuild = '' + wrapProgram "$out/bin/pandoc" \ + --add-flags '--defaults "${cfg.defaultsFile}"' + ''; + }; + }; + + home.packages = [ cfg.finalPackage ]; + xdg.dataFile = lib.mapAttrs' makeTemplateFile cfg.templates + // lib.listToAttrs (map makeCslFile cfg.citationStyles); + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/password-store.nix b/infra/libkookie/home-manager-stable/modules/programs/password-store.nix new file mode 100644 index 00000000000..e2f463ece6f --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/password-store.nix @@ -0,0 +1,65 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.password-store; + +in { + meta.maintainers = with maintainers; [ pacien ]; + + options.programs.password-store = { + enable = mkEnableOption "Password store"; + + package = mkOption { + type = types.package; + default = pkgs.pass; + defaultText = literalExpression "pkgs.pass"; + example = literalExpression '' + pkgs.pass.withExtensions (exts: [ exts.pass-otp ]) + ''; + description = '' + The pass package to use. + Can be used to specify extensions. + ''; + }; + + settings = mkOption rec { + type = with types; attrsOf str; + apply = mergeAttrs default; + default = { + PASSWORD_STORE_DIR = "${config.xdg.dataHome}/password-store"; + }; + defaultText = literalExpression '' + { PASSWORD_STORE_DIR = "$XDG_DATA_HOME/password-store"; } + ''; + example = literalExpression '' + { + PASSWORD_STORE_DIR = "/some/directory"; + PASSWORD_STORE_KEY = "12345678"; + PASSWORD_STORE_CLIP_TIME = "60"; + } + ''; + description = '' + The pass environment variables dictionary. + + See the "Environment variables" section of + + pass + 1 + + and the extension man pages for more information about the + available keys. + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + home.sessionVariables = cfg.settings; + + xsession.importedVariables = mkIf config.xsession.enable + (mapAttrsToList (name: value: name) cfg.settings); + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/pazi.nix b/infra/libkookie/home-manager-stable/modules/programs/pazi.nix new file mode 100644 index 00000000000..e1a08eb615a --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/pazi.nix @@ -0,0 +1,55 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.pazi; + +in { + meta.maintainers = [ maintainers.marsam ]; + + options.programs.pazi = { + enable = mkEnableOption "pazi"; + + enableBashIntegration = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable Bash integration. + ''; + }; + + enableZshIntegration = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable Zsh integration. + ''; + }; + + enableFishIntegration = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable Fish integration. + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ pkgs.pazi ]; + + programs.bash.initExtra = mkIf cfg.enableBashIntegration '' + eval "$(${pkgs.pazi}/bin/pazi init bash)" + ''; + + programs.zsh.initExtra = mkIf cfg.enableZshIntegration '' + eval "$(${pkgs.pazi}/bin/pazi init zsh)" + ''; + + programs.fish.shellInit = mkIf cfg.enableFishIntegration '' + ${pkgs.pazi}/bin/pazi init fish | source + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/pet.nix b/infra/libkookie/home-manager-stable/modules/programs/pet.nix new file mode 100644 index 00000000000..e75b10df3a5 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/pet.nix @@ -0,0 +1,106 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.pet; + + format = pkgs.formats.toml { }; + + snippetType = types.submodule { + options = { + description = mkOption { + type = types.str; + default = ""; + example = "Count the number of commits in the current branch"; + description = '' + Description of the snippet. + ''; + }; + + command = mkOption { + type = types.str; + default = ""; + example = "git rev-list --count HEAD"; + description = '' + The command. + ''; + }; + + output = mkOption { + type = types.str; + default = ""; + example = "473"; + description = '' + Example output of the command. + ''; + }; + + tag = mkOption { + type = types.listOf types.str; + default = [ ]; + example = literalExpression ''["git" "nixpkgs"]''; + description = '' + List of tags attached to the command. + ''; + }; + }; + }; + +in { + options.programs.pet = { + enable = mkEnableOption "pet"; + + settings = mkOption { + type = format.type; + default = { }; + description = '' + Settings written to config.toml. See the pet + documentation for details. + ''; + }; + + selectcmdPackage = mkOption { + type = types.package; + default = pkgs.fzf; + defaultText = literalExpression "pkgs.fzf"; + description = '' + The package needed for the settings.selectcmd. + ''; + }; + + snippets = mkOption { + type = types.listOf snippetType; + default = [ ]; + description = '' + The snippets. + ''; + }; + }; + + config = mkIf cfg.enable { + programs.pet.settings = let + defaultGeneral = { + selectcmd = mkDefault "fzf"; + snippetfile = config.xdg.configHome + "/pet/snippet.toml"; + }; + in if versionAtLeast config.home.stateVersion "21.11" then { + General = defaultGeneral; + } else + defaultGeneral; + + home.packages = [ pkgs.pet cfg.selectcmdPackage ]; + + xdg.configFile = { + "pet/config.toml".source = format.generate "config.toml" + (if versionAtLeast config.home.stateVersion "21.11" then + cfg.settings + else { + General = cfg.settings; + }); + "pet/snippet.toml".source = + format.generate "snippet.toml" { snippets = cfg.snippets; }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/pidgin.nix b/infra/libkookie/home-manager-stable/modules/programs/pidgin.nix new file mode 100644 index 00000000000..d7536be717b --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/pidgin.nix @@ -0,0 +1,34 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.pidgin; + +in { + meta.maintainers = [ maintainers.rycee ]; + + options = { + programs.pidgin = { + enable = mkEnableOption "Pidgin messaging client"; + + package = mkOption { + type = types.package; + default = pkgs.pidgin; + defaultText = literalExpression "pkgs.pidgin"; + description = "The Pidgin package to use."; + }; + + plugins = mkOption { + default = [ ]; + example = literalExpression "[ pkgs.pidgin-otr pkgs.pidgin-osd ]"; + description = "Plugins that should be available to Pidgin."; + }; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ (cfg.package.override { inherit (cfg) plugins; }) ]; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/piston-cli.nix b/infra/libkookie/home-manager-stable/modules/programs/piston-cli.nix new file mode 100644 index 00000000000..6315cb5cec4 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/piston-cli.nix @@ -0,0 +1,46 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.programs.piston-cli; + yamlFormat = pkgs.formats.yaml { }; +in { + meta.maintainers = with maintainers; [ ethancedwards8 ]; + + options.programs.piston-cli = { + enable = mkEnableOption "piston-cli, code runner"; + + package = mkOption { + type = types.package; + default = pkgs.piston-cli; + defaultText = literalExpression "pkgs.piston-cli"; + description = "The piston-cli package to use."; + }; + + settings = mkOption { + type = yamlFormat.type; + default = { }; + example = literalExpression '' + { + theme = "emacs"; + box_style = "MINIMAL_DOUBLE_HEAD"; + prompt_continuation = "..."; + prompt_start = ">>>"; + } + ''; + description = '' + Configuration written to + $XDG_CONFIG_HOME/piston-cli/config.yml. + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + + xdg.configFile."piston-cli/config.yml" = mkIf (cfg.settings != { }) { + source = yamlFormat.generate "config.yml" cfg.settings; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/powerline-go.nix b/infra/libkookie/home-manager-stable/modules/programs/powerline-go.nix new file mode 100644 index 00000000000..ec4e45c2777 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/powerline-go.nix @@ -0,0 +1,176 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.powerline-go; + + # Convert an option value to a string to be passed as argument to + # powerline-go: + valueToString = value: + if builtins.isList value then + builtins.concatStringsSep "," (builtins.map valueToString value) + else if builtins.isAttrs value then + valueToString + (mapAttrsToList (key: val: "${valueToString key}=${valueToString val}") + value) + else + builtins.toString value; + + modulesArgument = optionalString (cfg.modules != null) + " -modules ${valueToString cfg.modules}"; + + modulesRightArgument = optionalString (cfg.modulesRight != null) + " -modules-right ${valueToString cfg.modulesRight}"; + + evalMode = cfg.modulesRight != null; + + evalArgument = optionalString (evalMode) " -eval"; + + newlineArgument = optionalString cfg.newline " -newline"; + + pathAliasesArgument = optionalString (cfg.pathAliases != null) + " -path-aliases ${valueToString cfg.pathAliases}"; + + otherSettingPairArgument = name: value: + if value == true then " -${name}" else " -${name} ${valueToString value}"; + + otherSettingsArgument = optionalString (cfg.settings != { }) + (concatStringsSep "" + (mapAttrsToList otherSettingPairArgument cfg.settings)); + + commandLineArguments = '' + ${evalArgument}${modulesArgument}${modulesRightArgument}${newlineArgument}${pathAliasesArgument}${otherSettingsArgument} + ''; + +in { + meta.maintainers = [ maintainers.DamienCassou ]; + + options = { + programs.powerline-go = { + enable = mkEnableOption + "Powerline-go, a beautiful and useful low-latency prompt for your shell"; + + modules = mkOption { + default = null; + type = types.nullOr (types.listOf types.str); + description = '' + List of module names to load. The list of all available + modules as well as the choice of default ones are at + . + ''; + example = [ "host" "ssh" "cwd" "gitlite" "jobs" "exit" ]; + }; + + modulesRight = mkOption { + default = null; + type = types.nullOr (types.listOf types.str); + description = '' + List of module names to load to be displayed on the right side. + Currently not supported by bash. Specifying a value for this + option will force powerline-go to use the eval format to set + the prompt. + ''; + example = [ "host" "venv" "git" ]; + }; + + newline = mkOption { + default = false; + type = types.bool; + description = '' + Set to true if the prompt should be on a line of its own. + ''; + example = true; + }; + + pathAliases = mkOption { + default = null; + type = types.nullOr (types.attrsOf types.str); + description = '' + Pairs of full-path and corresponding desired short name. You + may use '~' to represent your home directory but you should + protect it to avoid shell substitution. + ''; + example = literalExpression '' + { "\\~/projects/home-manager" = "prj:home-manager"; } + ''; + }; + + settings = mkOption { + default = { }; + type = with types; attrsOf (oneOf [ bool int str (listOf str) ]); + description = '' + This can be any key/value pair as described in + . + ''; + example = literalExpression '' + { + hostname-only-if-ssh = true; + numeric-exit-codes = true; + cwd-max-depth = 7; + ignore-repos = [ "/home/me/big-project" "/home/me/huge-project" ]; + } + ''; + }; + + extraUpdatePS1 = mkOption { + default = ""; + description = "Shell code to execute after the prompt is set."; + example = '' + PS1=$PS1"NixOS> "; + ''; + type = types.str; + }; + }; + }; + + config = { + programs.bash.initExtra = + mkIf (cfg.enable && config.programs.bash.enable) '' + function _update_ps1() { + local old_exit_status=$? + ${ + if evalMode then "eval " else "PS1=" + }"$(${pkgs.powerline-go}/bin/powerline-go -error $old_exit_status -shell bash${commandLineArguments})" + ${cfg.extraUpdatePS1} + return $old_exit_status + } + + if [ "$TERM" != "linux" ]; then + PROMPT_COMMAND="_update_ps1;$PROMPT_COMMAND" + fi + ''; + + programs.zsh.initExtra = mkIf (cfg.enable && config.programs.zsh.enable) '' + function powerline_precmd() { + ${ + if evalMode then "eval " else "PS1=" + }"$(${pkgs.powerline-go}/bin/powerline-go -error $? -shell zsh${commandLineArguments})" + ${cfg.extraUpdatePS1} + } + + function install_powerline_precmd() { + for s in "$\{precmd_functions[@]}"; do + if [ "$s" = "powerline_precmd" ]; then + return + fi + done + precmd_functions+=(powerline_precmd) + } + + if [ "$TERM" != "linux" ]; then + install_powerline_precmd + fi + ''; + + # https://github.com/justjanne/powerline-go#fish + programs.fish.interactiveShellInit = + mkIf (cfg.enable && config.programs.fish.enable) '' + function fish_prompt + eval ${pkgs.powerline-go}/bin/powerline-go -error $status -jobs (count (jobs -p))${commandLineArguments} + ${cfg.extraUpdatePS1} + end + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/pubs.nix b/infra/libkookie/home-manager-stable/modules/programs/pubs.nix new file mode 100644 index 00000000000..5a597deabce --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/pubs.nix @@ -0,0 +1,60 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.pubs; + +in { + meta.maintainers = [ hm.maintainers.loicreynier ]; + + options.programs.pubs = { + enable = mkEnableOption "pubs"; + + package = mkOption { + type = types.package; + default = pkgs.pubs; + defaultText = literalExpression "pkgs.pubs"; + description = "The package to use for the pubs script."; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + example = literalExpression '' + ''' + [main] + pubsdir = ''${config.home.homeDirectory}/.pubs + docsdir = ''${config.home.homeDirectory}/.pubs/doc + doc_add = link + open_cmd = xdg-open + + [plugins] + active = git,alias + + [[alias]] + + [[[la]]] + command = list -a + description = lists papers in lexicographic order + + [[git]] + quiet = True + manual = False + force_color = False + '''''; + description = '' + Configuration using syntax written to + $HOME/.pubsrc. + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + + home.file.".pubsrc" = + mkIf (cfg.extraConfig != "") { text = cfg.extraConfig; }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/pylint.nix b/infra/libkookie/home-manager-stable/modules/programs/pylint.nix new file mode 100644 index 00000000000..e6679b985b8 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/pylint.nix @@ -0,0 +1,31 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.pylint; + listToValue = concatMapStringsSep ", " (generators.mkValueStringDefault { }); + iniFormat = pkgs.formats.ini { inherit listToValue; }; +in { + meta.maintainers = [ hm.maintainers.florpe ]; + options.programs.pylint = { + enable = mkEnableOption "the pylint Python linter"; + package = mkOption { + type = types.package; + default = pkgs.python3Packages.pylint; + defaultText = literalExpression "pkgs.python3Packages.pylint"; + description = "The pylint package to use."; + }; + settings = mkOption { + type = iniFormat.type; + default = { }; + defaultText = literalExpression "{}"; + description = "The pylint configuration."; + }; + }; + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + home.file.".pylintrc".source = iniFormat.generate "pylintrc" cfg.settings; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/pywal.nix b/infra/libkookie/home-manager-stable/modules/programs/pywal.nix new file mode 100644 index 00000000000..3f95ebfac33 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/pywal.nix @@ -0,0 +1,76 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let cfg = config.programs.pywal; + +in { + options = { programs.pywal = { enable = mkEnableOption "pywal"; }; }; + + config = mkIf cfg.enable { + + home.packages = [ pkgs.pywal ]; + + programs.zsh.initExtra = '' + # Import colorscheme from 'wal' asynchronously + # & # Run the process in the background. + # ( ) # Hide shell job control messages. + (cat ${config.xdg.cacheHome}/wal/sequences &) + ''; + + programs.kitty.extraConfig = '' + include ${config.xdg.cacheHome}/wal/colors-kitty.conf + ''; + + programs.rofi.theme."@import" = + "${config.xdg.cacheHome}/wal/colors-rofi-dark.rasi"; + + # wal generates and that's the one we should load from /home/teto/.cache/wal/colors.Xresources ~/.Xresources + xsession.windowManager.i3 = { + extraConfig = '' + set_from_resource $bg i3wm.color0 #ff0000 + set_from_resource $bg-alt i3wm.color14 #ff0000 + set_from_resource $fg i3wm.color15 #ff0000 + set_from_resource $fg-alt i3wm.color2 #ff0000 + set_from_resource $hl i3wm.color13 #ff0000 + ''; + + config.colors = { + focused = { + border = "$fg-alt"; + background = "$bg"; + text = "$hl"; + indicator = "$fg-alt"; + childBorder = "$hl"; + }; + + focusedInactive = { + border = "$fg-alt"; + background = "$bg"; + text = "$fg"; + indicator = "$fg-alt"; + childBorder = "$fg-alt"; + }; + + unfocused = { + border = "$fg-alt"; + background = "$bg"; + text = "$fg"; + indicator = "$fg-alt"; + childBorder = "$fg-alt"; + }; + + urgent = { + border = "$fg-alt"; + background = "$bg"; + text = "$fg"; + indicator = "$fg-alt"; + childBorder = "$fg-alt"; + }; + + background = "$bg"; + }; + }; + }; +} + diff --git a/infra/libkookie/home-manager-stable/modules/programs/qutebrowser.nix b/infra/libkookie/home-manager-stable/modules/programs/qutebrowser.nix new file mode 100644 index 00000000000..9220d496aed --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/qutebrowser.nix @@ -0,0 +1,333 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.qutebrowser; + + formatLine = o: n: v: + let + formatValue = v: + if builtins.isNull v then + "None" + else if builtins.isBool v then + (if v then "True" else "False") + else if builtins.isString v then + ''"${v}"'' + else if builtins.isList v then + "[${concatStringsSep ", " (map formatValue v)}]" + else + builtins.toString v; + in if builtins.isAttrs v then + concatStringsSep "\n" (mapAttrsToList (formatLine "${o}${n}.") v) + else + "${o}${n} = ${formatValue v}"; + + formatDictLine = o: n: v: ''${o}['${n}'] = "${v}"''; + + formatKeyBindings = m: b: + let + formatKeyBinding = m: k: c: + ''config.bind("${k}", "${escape [ ''"'' ] c}", mode="${m}")''; + in concatStringsSep "\n" (mapAttrsToList (formatKeyBinding m) b); + + formatQuickmarks = n: s: "${n} ${s}"; + +in { + options.programs.qutebrowser = { + enable = mkEnableOption "qutebrowser"; + + package = mkOption { + type = types.package; + default = pkgs.qutebrowser; + defaultText = literalExpression "pkgs.qutebrowser"; + description = "Qutebrowser package to install."; + }; + + aliases = mkOption { + type = types.attrsOf types.str; + default = { }; + description = '' + Aliases for commands. + ''; + }; + + loadAutoconfig = mkOption { + type = types.bool; + default = false; + description = '' + Load settings configured via the GUI. + ''; + }; + + searchEngines = mkOption { + type = types.attrsOf types.str; + default = { }; + description = '' + Search engines that can be used via the address bar. Maps a search + engine name (such as DEFAULT, or + ddg) to a URL with a {} + placeholder. The placeholder will be replaced by the search term, use + {{ and }} for literal + {/} signs. The search engine named + DEFAULT is used when + url.auto_search is turned on and something else than + a URL was entered to be opened. Other search engines can be used by + prepending the search engine name to the search term, for example + :open google qutebrowser. + ''; + example = literalExpression '' + { + w = "https://en.wikipedia.org/wiki/Special:Search?search={}&go=Go&ns0=1"; + aw = "https://wiki.archlinux.org/?search={}"; + nw = "https://nixos.wiki/index.php?search={}"; + g = "https://www.google.com/search?hl=en&q={}"; + } + ''; + }; + + settings = mkOption { + type = types.attrsOf types.anything; + default = { }; + description = '' + Options to add to qutebrowser config.py file. + See + for options. + ''; + example = literalExpression '' + { + colors = { + hints = { + bg = "#000000"; + fg = "#ffffff"; + }; + tabs.bar.bg = "#000000"; + }; + tabs.tabs_are_windows = true; + } + ''; + }; + + keyMappings = mkOption { + type = types.attrsOf types.str; + default = { }; + description = '' + This setting can be used to map keys to other keys. When the key used + as dictionary-key is pressed, the binding for the key used as + dictionary-value is invoked instead. This is useful for global + remappings of keys, for example to map Ctrl-[ to Escape. Note that when + a key is bound (via bindings.default or + bindings.commands), the mapping is ignored. + ''; + }; + + enableDefaultBindings = mkOption { + type = types.bool; + default = true; + description = '' + Disable to prevent loading default key bindings. + ''; + }; + + keyBindings = mkOption { + type = types.attrsOf (types.attrsOf types.str); + default = { }; + description = '' + Key bindings mapping keys to commands in different modes. This setting + is a dictionary containing mode names and dictionaries mapping keys to + commands: {mode: {key: command}} If you want to map + a key to another key, check the keyMappings setting + instead. For modifiers, you can use either - or + + as delimiters, and these names: + + + + Control: Control, Ctrl + + + Meta: Meta, Windows, + Mod4 + + + Alt: Alt, Mod1 + + + Shift: Shift + + + + For simple keys (no <>-signs), a capital + letter means the key is pressed with Shift. For special keys (with + <>-signs), you need to explicitly add + Shift- to match a key pressed with shift. If you + want a binding to do nothing, bind it to the nop + command. If you want a default binding to be passed through to the + website, bind it to null. Note that some commands which are only useful + for bindings (but not used interactively) are hidden from the command + completion. See :help for a full list of available + commands. The following modes are available: + + + + normal + + Default mode, where most commands are invoked. + + + + insert + + Entered when an input field is focused on a website, or by + pressing i in normal mode. Passes through almost all keypresses + to the website, but has some bindings like + <Ctrl-e> to open an external editor. + Note that single keys can’t be bound in this mode. + + + + hint + + Entered when f is pressed to select links with the keyboard. Note + that single keys can’t be bound in this mode. + + + + passthrough + + Similar to insert mode, but passes through all keypresses except + <Escape> to leave the mode. It might be + useful to bind <Escape> to some other + key in this mode if you want to be able to send an Escape key to + the website as well. Note that single keys can’t be bound in this + mode. + + + + command + + Entered when pressing the : key in order to enter a command. Note + that single keys can’t be bound in this mode. + + + + prompt + + Entered when there’s a prompt to display, like for download + locations or when invoked from JavaScript. + + + + yesno + + Entered when there’s a yes/no prompt displayed. + + + + caret + + Entered when pressing the v mode, used to select text using the + keyboard. + + + + register + + Entered when qutebrowser is waiting for a register name/key for + commands like :set-mark. + + + + ''; + example = literalExpression '' + { + normal = { + "" = "spawn mpv {url}"; + ",p" = "spawn --userscript qute-pass"; + ",l" = '''config-cycle spellcheck.languages ["en-GB"] ["en-US"]'''; + }; + prompt = { + "" = "prompt-yes"; + }; + } + ''; + }; + + quickmarks = mkOption { + type = types.attrsOf types.str; + default = { }; + description = '' + Quickmarks to add to qutebrowser's quickmarks file. + Note that when Home Manager manages your quickmarks, you cannot edit them at runtime. + ''; + example = literalExpression '' + { + nixpkgs = "https://github.com/NixOS/nixpkgs"; + home-manager = "https://github.com/nix-community/home-manager"; + } + ''; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Extra lines added to qutebrowser config.py file. + ''; + }; + }; + + config = let + qutebrowserConfig = concatStringsSep "\n" ([ + (if cfg.loadAutoconfig then + "config.load_autoconfig()" + else + "config.load_autoconfig(False)") + ] ++ mapAttrsToList (formatLine "c.") cfg.settings + ++ mapAttrsToList (formatDictLine "c.aliases") cfg.aliases + ++ mapAttrsToList (formatDictLine "c.url.searchengines") cfg.searchEngines + ++ mapAttrsToList (formatDictLine "c.bindings.key_mappings") + cfg.keyMappings + ++ optional (!cfg.enableDefaultBindings) "c.bindings.default = {}" + ++ mapAttrsToList formatKeyBindings cfg.keyBindings + ++ optional (cfg.extraConfig != "") cfg.extraConfig); + + quickmarksFile = optionals (cfg.quickmarks != { }) concatStringsSep "\n" + ((mapAttrsToList formatQuickmarks cfg.quickmarks)); + in mkIf cfg.enable { + home.packages = [ cfg.package ]; + + home.file.".qutebrowser/config.py" = + mkIf pkgs.stdenv.hostPlatform.isDarwin { text = qutebrowserConfig; }; + + home.file.".qutebrowser/quickmarks" = + mkIf (cfg.quickmarks != { } && pkgs.stdenv.hostPlatform.isDarwin) { + text = quickmarksFile; + }; + + xdg.configFile."qutebrowser/config.py" = + mkIf pkgs.stdenv.hostPlatform.isLinux { + text = qutebrowserConfig; + onChange = '' + hash="$(echo -n "$USER" | md5sum | cut -d' ' -f1)" + socket="''${XDG_RUNTIME_DIR:-/run/user/$UID}/qutebrowser/ipc-$hash" + if [[ -S $socket ]]; then + command=${ + escapeShellArg (builtins.toJSON { + args = [ ":config-source" ]; + target_arg = null; + protocol_version = 1; + }) + } + echo "$command" | ${pkgs.socat}/bin/socat -lf /dev/null - UNIX-CONNECT:"$socket" + fi + unset hash socket command + ''; + }; + + xdg.configFile."qutebrowser/quickmarks" = + mkIf (cfg.quickmarks != { } && pkgs.stdenv.hostPlatform.isLinux) { + text = quickmarksFile; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/rbw.nix b/infra/libkookie/home-manager-stable/modules/programs/rbw.nix new file mode 100644 index 00000000000..204aaa6b6bc --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/rbw.nix @@ -0,0 +1,116 @@ +{ config, lib, pkgs, ... }: +let + cfg = config.programs.rbw; + + jsonFormat = pkgs.formats.json { }; + + inherit (pkgs.stdenv.hostPlatform) isDarwin; + + settingsModule = with lib; + types.submodule { + freeformType = jsonFormat.type; + options = { + email = mkOption { + type = types.str; + example = "name@example.com"; + description = "The email address for your bitwarden account."; + }; + + base_url = mkOption { + type = with types; nullOr str; + default = null; + example = "bitwarden.example.com"; + description = + "The base-url for a self-hosted bitwarden installation."; + }; + + identity_url = mkOption { + type = with types; nullOr str; + default = null; + example = "identity.example.com"; + description = "The identity url for your bitwarden installation."; + }; + + lock_timeout = mkOption { + type = types.ints.unsigned; + default = 3600; + example = 300; + description = '' + The amount of time that your login information should be cached. + ''; + }; + + pinentry = mkOption { + type = with types; either package (enum pkgs.pinentry.flavors); + example = "gnome3"; + default = "gtk2"; + description = '' + Which pinentry interface to use. Beware that + pinentry-gnome3 may not work on non-Gnome + systems. You can fix it by adding the following to your + system configuration: + + services.dbus.packages = [ pkgs.gcr ]; + + For this reason, the default is gtk2 for + now. + ''; + # we want the program in the config + apply = val: + if builtins.isString val then + "${pkgs.pinentry.${val}}/bin/pinentry" + else + "${val}/${val.binaryPath or "bin/pinentry"}"; + }; + }; + }; +in { + meta.maintainers = with lib.hm.maintainers; [ ambroisie ]; + + options.programs.rbw = with lib; { + enable = mkEnableOption "rbw, a CLI Bitwarden client"; + + package = mkOption { + type = types.package; + default = pkgs.rbw; + defaultText = literalExpression "pkgs.rbw"; + description = '' + Package providing the rbw tool and its + rbw-agent daemon. + ''; + }; + + settings = mkOption { + type = types.nullOr settingsModule; + default = null; + example = literalExpression '' + { + email = "name@example.com"; + lock_timeout = 300; + pinentry = "gnome3"; + } + ''; + description = '' + rbw configuration, if not defined the configuration will not be + managed by Home Manager. + ''; + }; + }; + + config = lib.mkIf cfg.enable (lib.mkMerge [ + { + home.packages = [ cfg.package ]; + } + + # Only manage configuration if not empty + (lib.mkIf (cfg.settings != null && !isDarwin) { + xdg.configFile."rbw/config.json".source = + jsonFormat.generate "rbw-config.json" cfg.settings; + }) + + (lib.mkIf (cfg.settings != null && isDarwin) { + home.file."Library/Application Support/rbw/config.json".source = + jsonFormat.generate "rbw-config.json" cfg.settings; + }) + ]); +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/readline.nix b/infra/libkookie/home-manager-stable/modules/programs/readline.nix new file mode 100644 index 00000000000..2658061f229 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/readline.nix @@ -0,0 +1,77 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.readline; + + mkSetVariableStr = n: v: + let + mkValueStr = v: + if v == true then + "on" + else if v == false then + "off" + else if isInt v then + toString v + else if isString v then + v + else + abort ("values ${toPretty v} is of unsupported type"); + in "set ${n} ${mkValueStr v}"; + + mkBindingStr = k: v: ''"${k}": ${v}''; + +in { + options.programs.readline = { + enable = mkEnableOption "readline"; + + bindings = mkOption { + default = { }; + type = types.attrsOf types.str; + example = literalExpression '' + { "\\C-h" = "backward-kill-word"; } + ''; + description = "Readline bindings."; + }; + + variables = mkOption { + type = with types; attrsOf (either str (either int bool)); + default = { }; + example = { expand-tilde = true; }; + description = '' + Readline customization variable assignments. + ''; + }; + + includeSystemConfig = mkOption { + type = types.bool; + default = true; + description = "Whether to include the system-wide configuration."; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Configuration lines appended unchanged to the end of the + ~/.inputrc file. + ''; + }; + }; + + config = mkIf cfg.enable { + home.file.".inputrc".text = let + configStr = concatStringsSep "\n" + (optional cfg.includeSystemConfig "$include /etc/inputrc" + ++ mapAttrsToList mkSetVariableStr cfg.variables + ++ mapAttrsToList mkBindingStr cfg.bindings); + in '' + # Generated by Home Manager. + + ${configStr} + ${cfg.extraConfig} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/rofi-pass.nix b/infra/libkookie/home-manager-stable/modules/programs/rofi-pass.nix new file mode 100644 index 00000000000..da75299e673 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/rofi-pass.nix @@ -0,0 +1,46 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.rofi.pass; + +in { + meta.maintainers = [ maintainers.seylerius ]; + + options.programs.rofi.pass = { + enable = mkEnableOption "rofi integration with password-store"; + + stores = mkOption { + type = types.listOf types.str; + default = [ ]; + description = '' + Directory roots of your password-stores. + ''; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + example = '' + URL_field='url' + USERNAME_field='user' + AUTOTYPE_field='autotype' + ''; + description = '' + Extra configuration to be added at to the rofi-pass config file. + Additional examples can be found at + . + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ pkgs.rofi-pass ]; + + xdg.configFile."rofi-pass/config".text = optionalString (cfg.stores != [ ]) + ("root=" + (concatStringsSep ":" cfg.stores) + "\n") + cfg.extraConfig + + optionalString (cfg.extraConfig != "") "\n"; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/rofi.nix b/infra/libkookie/home-manager-stable/modules/programs/rofi.nix new file mode 100644 index 00000000000..649070737ee --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/rofi.nix @@ -0,0 +1,295 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.rofi; + + mkValueString = value: + if isBool value then + if value then "true" else "false" + else if isInt value then + toString value + else if (value._type or "") == "literal" then + value.value + else if isString value then + ''"${value}"'' + else if isList value then + "[ ${strings.concatStringsSep "," (map mkValueString value)} ]" + else + abort "Unhandled value type ${builtins.typeOf value}"; + + mkKeyValue = { sep ? ": ", end ? ";" }: + name: value: + "${name}${sep}${mkValueString value}${end}"; + + mkRasiSection = name: value: + if isAttrs value then + let + toRasiKeyValue = generators.toKeyValue { mkKeyValue = mkKeyValue { }; }; + # Remove null values so the resulting config does not have empty lines + configStr = toRasiKeyValue (filterAttrs (_: v: v != null) value); + in '' + ${name} { + ${configStr}} + '' + else + (mkKeyValue { + sep = " "; + end = ""; + } name value) + "\n"; + + toRasi = attrs: + concatStringsSep "\n" (concatMap (mapAttrsToList mkRasiSection) [ + (filterAttrs (n: _: n == "@theme") attrs) + (filterAttrs (n: _: n == "@import") attrs) + (removeAttrs attrs [ "@theme" "@import" ]) + ]); + + locationsMap = { + center = 0; + top-left = 1; + top = 2; + top-right = 3; + right = 4; + bottom-right = 5; + bottom = 6; + bottom-left = 7; + left = 8; + }; + + primitive = with types; (oneOf [ str int bool rasiLiteral ]); + + # Either a `section { foo: "bar"; }` or a `@import/@theme "some-text"` + configType = with types; + (either (attrsOf (either primitive (listOf primitive))) str); + + rasiLiteral = types.submodule { + options = { + _type = mkOption { + type = types.enum [ "literal" ]; + internal = true; + }; + + value = mkOption { + type = types.str; + internal = true; + }; + }; + } // { + description = "Rasi literal string"; + }; + + themeType = with types; attrsOf configType; + + themeName = if (cfg.theme == null) then + null + else if (isString cfg.theme) then + cfg.theme + else if (isAttrs cfg.theme) then + "custom" + else + removeSuffix ".rasi" (baseNameOf cfg.theme); + + themePath = if (isString cfg.theme) then + null + else if (isAttrs cfg.theme) then + "custom" + else + cfg.theme; + +in { + options.programs.rofi = { + enable = mkEnableOption + "Rofi: A window switcher, application launcher and dmenu replacement"; + + package = mkOption { + default = pkgs.rofi; + type = types.package; + description = '' + Package providing the rofi binary. + ''; + example = literalExpression '' + pkgs.rofi.override { plugins = [ pkgs.rofi-emoji ]; }; + ''; + }; + + finalPackage = mkOption { + type = types.package; + readOnly = true; + description = '' + Resulting customized rofi package. + ''; + }; + + plugins = mkOption { + default = [ ]; + type = types.listOf types.package; + description = '' + List of rofi plugins to be installed. + ''; + example = literalExpression "[ pkgs.rofi-calc ]"; + }; + + font = mkOption { + default = null; + type = types.nullOr types.str; + example = "Droid Sans Mono 14"; + description = "Font to use."; + }; + + terminal = mkOption { + default = null; + type = types.nullOr types.str; + description = '' + Path to the terminal which will be used to run console applications + ''; + example = "\${pkgs.gnome.gnome_terminal}/bin/gnome-terminal"; + }; + + cycle = mkOption { + default = null; + type = types.nullOr types.bool; + description = "Whether to cycle through the results list."; + }; + + location = mkOption { + default = "center"; + type = types.enum (attrNames locationsMap); + description = "The location rofi appears on the screen."; + }; + + xoffset = mkOption { + default = 0; + type = types.int; + description = '' + Offset in the x-axis in pixels relative to the chosen location. + ''; + }; + + yoffset = mkOption { + default = 0; + type = types.int; + description = '' + Offset in the y-axis in pixels relative to the chosen location. + ''; + }; + + theme = mkOption { + default = null; + type = with types; nullOr (oneOf [ str path themeType ]); + example = literalExpression '' + let + # Use `mkLiteral` for string-like values that should show without + # quotes, e.g.: + # { + # foo = "abc"; => foo: "abc"; + # bar = mkLiteral "abc"; => bar: abc; + # }; + inherit (config.lib.formats.rasi) mkLiteral; + in { + "*" = { + background-color = mkLiteral "#000000"; + foreground-color = mkLiteral "rgba ( 250, 251, 252, 100 % )"; + border-color = mkLiteral "#FFFFFF"; + width = 512; + }; + + "#inputbar" = { + children = map mkLiteral [ "prompt" "entry" ]; + }; + + "#textbox-prompt-colon" = { + expand = false; + str = ":"; + margin = mkLiteral "0px 0.3em 0em 0em"; + text-color = mkLiteral "@foreground-color"; + }; + } + ''; + description = '' + Name of theme or path to theme file in rasi format or attribute set with + theme configuration. Available named themes can be viewed using the + rofi-theme-selector tool. + ''; + }; + + configPath = mkOption { + default = "${config.xdg.configHome}/rofi/config.rasi"; + defaultText = "$XDG_CONFIG_HOME/rofi/config.rasi"; + type = types.str; + description = "Path where to put generated configuration file."; + }; + + extraConfig = mkOption { + default = { }; + example = literalExpression '' + { + modi = "drun,emoji,ssh"; + kb-primary-paste = "Control+V,Shift+Insert"; + kb-secondary-paste = "Control+v,Insert"; + } + ''; + type = configType; + description = "Additional configuration to add."; + }; + + }; + + imports = let + mkRemovedOptionRofi = option: + (mkRemovedOptionModule [ "programs" "rofi" option ] + "Please use a Rofi theme instead."); + in map mkRemovedOptionRofi [ + "width" + "lines" + "borderWidth" + "rowHeight" + "padding" + "separator" + "scrollbar" + "fullscreen" + "colors" + ]; + + config = mkIf cfg.enable { + assertions = + [ (hm.assertions.assertPlatform "programs.rofi" pkgs platforms.linux) ]; + + lib.formats.rasi.mkLiteral = value: { + _type = "literal"; + inherit value; + }; + + programs.rofi.finalPackage = let + rofiWithPlugins = cfg.package.override + (old: rec { plugins = (old.plugins or [ ]) ++ cfg.plugins; }); + in if builtins.hasAttr "override" cfg.package then + rofiWithPlugins + else + cfg.package; + + home.packages = [ cfg.finalPackage ]; + + home.file."${cfg.configPath}".text = toRasi { + configuration = ({ + font = cfg.font; + terminal = cfg.terminal; + cycle = cfg.cycle; + location = (getAttr cfg.location locationsMap); + xoffset = cfg.xoffset; + yoffset = cfg.yoffset; + } // cfg.extraConfig); + # @theme must go after configuration but attrs are output in alphabetical order ('@' first) + } + (optionalString (themeName != null) (toRasi { "@theme" = themeName; })); + + xdg.dataFile = mkIf (themePath != null) (if themePath == "custom" then { + "rofi/themes/${themeName}.rasi".text = toRasi cfg.theme; + } else { + "rofi/themes/${themeName}.rasi".source = themePath; + }); + }; + + meta.maintainers = with maintainers; [ thiagokokada ]; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/rtorrent.nix b/infra/libkookie/home-manager-stable/modules/programs/rtorrent.nix new file mode 100644 index 00000000000..95015e2cbbe --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/rtorrent.nix @@ -0,0 +1,34 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.rtorrent; + +in { + meta.maintainers = [ maintainers.marsam ]; + + options.programs.rtorrent = { + enable = mkEnableOption "rTorrent"; + + settings = mkOption { + type = types.lines; + default = ""; + description = '' + Configuration written to + $XDG_CONFIG_HOME/rtorrent/rtorrent.rc. See + + for explanation about possible values. + ''; + }; + + }; + + config = mkIf cfg.enable { + home.packages = [ pkgs.rtorrent ]; + + xdg.configFile."rtorrent/rtorrent.rc" = + mkIf (cfg.settings != "") { text = cfg.settings; }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/sagemath.nix b/infra/libkookie/home-manager-stable/modules/programs/sagemath.nix new file mode 100644 index 00000000000..b07cec10f80 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/sagemath.nix @@ -0,0 +1,63 @@ +{ config, lib, pkgs, ... }: + +let + + cfg = config.programs.sagemath; + + inherit (lib) literalExpression mkEnableOption mkOption types; + +in { + meta.maintainers = [ lib.maintainers.kirelagin ]; + + options.programs.sagemath = { + enable = mkEnableOption "SageMath, a mathematics software system"; + + package = mkOption { + type = types.package; + default = pkgs.sage; + defaultText = literalExpression "pkgs.sage"; + description = "The SageMath package to use."; + }; + + configDir = mkOption { + type = types.str; + default = "${config.xdg.configHome}/sage"; + defaultText = literalExpression "\${config.xdg.configHome}/sage"; + description = '' + Directory where the sage.init file will be stored. + Note that the upstream default is ~/.sage, + but our default is to follow XDG. + ''; + }; + + dataDir = mkOption { + type = types.str; + default = "${config.xdg.dataHome}/sage"; + defaultText = literalExpression "\${config.xdg.dataHome}/sage"; + description = '' + Location for DOT_SAGE. + Note that the upstream default is ~/.sage, + but our default is to follow XDG. + ''; + }; + + initScript = mkOption { + type = types.lines; + default = ""; + example = "%colors linux"; + description = '' + Contents of the init.sage file that is loaded on startup. + ''; + }; + }; + + config = lib.mkIf cfg.enable { + home.packages = [ cfg.package ]; + + home.file."${cfg.configDir}/init.sage".text = cfg.initScript; + home.sessionVariables = { + DOT_SAGE = cfg.dataDir; + SAGE_STARTUP_FILE = "${cfg.configDir}/init.sage"; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/sbt.nix b/infra/libkookie/home-manager-stable/modules/programs/sbt.nix new file mode 100644 index 00000000000..bf355a80bf6 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/sbt.nix @@ -0,0 +1,141 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + renderPlugin = plugin: '' + addSbtPlugin("${plugin.org}" % "${plugin.artifact}" % "${plugin.version}") + ''; + + renderCredential = cred: '' + credentials += Credentials("${cred.realm}", "${cred.host}", "${cred.user}", "${cred.passwordCommand}".!!.trim) + ''; + + renderCredentials = creds: '' + import scala.sys.process._ + ${concatStrings (map renderCredential creds)}''; + + sbtTypes = { + plugin = types.submodule { + options = { + org = mkOption { + type = types.str; + description = "The organization the artifact is published under."; + }; + + artifact = mkOption { + type = types.str; + description = "The name of the artifact."; + }; + + version = mkOption { + type = types.str; + description = "The version of the plugin."; + }; + }; + }; + + credential = types.submodule { + options = { + realm = mkOption { + type = types.str; + description = "The realm of the repository you're authenticating to."; + }; + + host = mkOption { + type = types.str; + description = + "The hostname of the repository you're authenticating to."; + }; + + user = mkOption { + type = types.str; + description = "The user you're using to authenticate."; + }; + + passwordCommand = mkOption { + type = types.str; + description = '' + The command that provides the password or authentication token for + the repository. + ''; + }; + }; + }; + }; + + cfg = config.programs.sbt; + +in { + meta.maintainers = [ maintainers.kubukoz ]; + + options.programs.sbt = { + enable = mkEnableOption "sbt"; + + package = mkOption { + type = types.package; + default = pkgs.sbt; + defaultText = literalExpression "pkgs.sbt"; + description = "The package with sbt to be installed."; + }; + + baseConfigPath = mkOption { + type = types.str; + default = ".sbt/1.0"; + description = "Where the plugins and credentials should be located."; + }; + + plugins = mkOption { + type = types.listOf (sbtTypes.plugin); + default = [ ]; + example = literalExpression '' + [ + { + org = "net.virtual-void"; + artifact = "sbt-dependency-graph"; + version = "0.10.0-RC1"; + } + { + org = "com.dwijnand"; + artifact = "sbt-project-graph"; + version = "0.4.0"; + } + ] + ''; + description = '' + A list of plugins to place in the sbt configuration directory. + ''; + }; + + credentials = mkOption { + type = types.listOf (sbtTypes.credential); + default = [ ]; + example = literalExpression '' + [{ + realm = "Sonatype Nexus Repository Manager"; + host = "example.com"; + user = "user"; + passwordCommand = "pass show sbt/user@example.com"; + }] + ''; + description = '' + A list of credentials to define in the sbt configuration directory. + ''; + }; + }; + + config = mkIf cfg.enable (mkMerge [ + { home.packages = [ cfg.package ]; } + + (mkIf (cfg.plugins != [ ]) { + home.file."${cfg.baseConfigPath}/plugins/plugins.sbt".text = + concatStrings (map renderPlugin cfg.plugins); + }) + + (mkIf (cfg.credentials != [ ]) { + home.file."${cfg.baseConfigPath}/credentials.sbt".text = + renderCredentials cfg.credentials; + }) + ]); +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/scmpuff.nix b/infra/libkookie/home-manager-stable/modules/programs/scmpuff.nix new file mode 100644 index 00000000000..5f36ca02139 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/scmpuff.nix @@ -0,0 +1,47 @@ +{ config, lib, pkgs, ... }: +with lib; +let cfg = config.programs.scmpuff; +in { + meta.maintainers = [ maintainers.cpcloud ]; + + options.programs.scmpuff = { + enable = mkEnableOption '' + scmpuff, a command line tool that allows you to work quicker with Git by + substituting numeric shortcuts for files''; + + package = mkOption { + type = types.package; + default = pkgs.scmpuff; + defaultText = literalExpression "pkgs.scmpuff"; + description = "Package providing the scmpuff tool."; + }; + + enableBashIntegration = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable Bash integration. + ''; + }; + + enableZshIntegration = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable Zsh integration. + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + + programs.bash.initExtra = mkIf cfg.enableBashIntegration '' + eval "$(${cfg.package}/bin/scmpuff init -s)" + ''; + + programs.zsh.initExtra = mkIf cfg.enableZshIntegration '' + eval "$(${cfg.package}/bin/scmpuff init -s)" + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/senpai.nix b/infra/libkookie/home-manager-stable/modules/programs/senpai.nix new file mode 100644 index 00000000000..6320807114e --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/senpai.nix @@ -0,0 +1,73 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.programs.senpai; + cfgFmt = pkgs.formats.yaml { }; +in { + options.programs.senpai = { + enable = mkEnableOption "senpai"; + package = mkOption { + type = types.package; + default = pkgs.senpai; + defaultText = literalExpression "pkgs.senpai"; + description = "The senpai package to use."; + }; + config = mkOption { + type = types.submodule { + freeformType = cfgFmt.type; + options = { + addr = mkOption { + type = types.str; + description = '' + The address (host[:port]) of the IRC server. senpai uses TLS + connections by default unless you specify no-tls option. TLS + connections default to port 6697, plain-text use port 6667. + ''; + }; + nick = mkOption { + type = types.str; + description = '' + Your nickname, sent with a NICK IRC message. It mustn't contain + spaces or colons (:). + ''; + }; + password = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Your password, used for SASL authentication. Note that it will + reside world-readable in the Nix store. + ''; + }; + no-tls = mkOption { + type = types.bool; + default = false; + description = "Disables TLS encryption."; + }; + }; + }; + example = literalExpression '' + { + addr = "libera.chat:6697"; + nick = "nicholas"; + password = "verysecurepassword"; + } + ''; + description = '' + Configuration for senpai. For a complete list of options, see + senpai + 5. + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + xdg.configFile."senpai/senpai.yaml".source = + cfgFmt.generate "senpai.yaml" cfg.config; + }; + + meta.maintainers = [ hm.maintainers.malvo ]; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/sioyek.nix b/infra/libkookie/home-manager-stable/modules/programs/sioyek.nix new file mode 100644 index 00000000000..9ef32746c1c --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/sioyek.nix @@ -0,0 +1,70 @@ +{ config, lib, pkgs, ... }: +with lib; +let + cfg = config.programs.sioyek; + + renderAttrs = attrs: + concatStringsSep "\n" + (mapAttrsToList (name: value: "${name} ${value}") attrs); +in { + options = { + programs.sioyek = { + enable = mkEnableOption + "Sioyek is a PDF viewer designed for reading research papers and technical books."; + + package = mkOption { + default = pkgs.sioyek; + defaultText = literalExpression "pkgs.sioyek"; + type = types.package; + description = "Package providing the sioyek binary"; + }; + + bindings = mkOption { + description = '' + Input configuration written to + $XDG_CONFIG_HOME/sioyek/keys_user.config. + See . + ''; + type = types.attrsOf types.str; + default = { }; + example = literalExpression '' + { + "move_up" = "k"; + "move_down" = "j"; + "move_left" = "h"; + "move_right" = "l"; + } + ''; + }; + + config = mkOption { + description = '' + Input configuration written to + $XDG_CONFIG_HOME/sioyek/prefs_user.config. + See . + ''; + type = types.attrsOf types.str; + default = { }; + example = literalExpression '' + { + "background_color" = "1.0 1.0 1.0"; + "text_highlight_color" = "1.0 0.0 0.0"; + } + ''; + }; + + }; + }; + + config = mkIf cfg.enable (mkMerge [ + { home.packages = [ cfg.package ]; } + (mkIf (cfg.config != { }) { + xdg.configFile."sioyek/prefs_user.config".text = renderAttrs cfg.config; + }) + (mkIf (cfg.bindings != { }) { + xdg.configFile."sioyek/keys_user.config".text = renderAttrs cfg.bindings; + }) + ]); + + meta.maintainers = [ hm.maintainers.podocarp ]; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/skim.nix b/infra/libkookie/home-manager-stable/modules/programs/skim.nix new file mode 100644 index 00000000000..3d4da74df2e --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/skim.nix @@ -0,0 +1,143 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.skim; + +in { + options.programs.skim = { + enable = mkEnableOption "skim - a command-line fuzzy finder"; + + package = mkOption { + type = types.package; + default = pkgs.skim; + defaultText = literalExpression "pkgs.skim"; + description = "Package providing the skim tool."; + }; + + defaultCommand = mkOption { + type = types.nullOr types.str; + default = null; + example = "fd --type f"; + description = '' + The command that gets executed as the default source for skim + when running. + ''; + }; + + defaultOptions = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "--height 40%" "--prompt ⟫" ]; + description = '' + Extra command line options given to skim by default. + ''; + }; + + fileWidgetCommand = mkOption { + type = types.nullOr types.str; + default = null; + example = "fd --type f"; + description = '' + The command that gets executed as the source for skim for the + CTRL-T keybinding. + ''; + }; + + fileWidgetOptions = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "--preview 'head {}'" ]; + description = '' + Command line options for the CTRL-T keybinding. + ''; + }; + + changeDirWidgetCommand = mkOption { + type = types.nullOr types.str; + default = null; + example = "fd --type d"; + description = '' + The command that gets executed as the source for skim for the + ALT-C keybinding. + ''; + }; + + changeDirWidgetOptions = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "--preview 'tree -C {} | head -200'" ]; + description = '' + Command line options for the ALT-C keybinding. + ''; + }; + + historyWidgetOptions = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "--tac" "--exact" ]; + description = '' + Command line options for the CTRL-R keybinding. + ''; + }; + + enableBashIntegration = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable Bash integration. + ''; + }; + + enableZshIntegration = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable Zsh integration. + ''; + }; + + enableFishIntegration = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable Fish integration. + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + + home.sessionVariables = mapAttrs (n: v: toString v) + (filterAttrs (n: v: v != [ ] && v != null) { + SKIM_ALT_C_COMMAND = cfg.changeDirWidgetCommand; + SKIM_ALT_C_OPTS = cfg.changeDirWidgetOptions; + SKIM_CTRL_R_OPTS = cfg.historyWidgetOptions; + SKIM_CTRL_T_COMMAND = cfg.fileWidgetCommand; + SKIM_CTRL_T_OPTS = cfg.fileWidgetOptions; + SKIM_DEFAULT_COMMAND = cfg.defaultCommand; + SKIM_DEFAULT_OPTIONS = cfg.defaultOptions; + }); + + programs.bash.initExtra = mkIf cfg.enableBashIntegration '' + if [[ :$SHELLOPTS: =~ :(vi|emacs): ]]; then + . ${cfg.package}/share/skim/completion.bash + . ${cfg.package}/share/skim/key-bindings.bash + fi + ''; + + programs.zsh.initExtra = mkIf cfg.enableZshIntegration '' + if [[ $options[zle] = on ]]; then + . ${cfg.package}/share/skim/completion.zsh + . ${cfg.package}/share/skim/key-bindings.zsh + fi + ''; + + programs.fish.shellInit = mkIf cfg.enableFishIntegration '' + source ${cfg.package}/share/skim/key-bindings.fish && skim_key_bindings + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/sm64ex.nix b/infra/libkookie/home-manager-stable/modules/programs/sm64ex.nix new file mode 100644 index 00000000000..48c1cb9beac --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/sm64ex.nix @@ -0,0 +1,128 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.programs.sm64ex; + + # This is required for tests, we cannot overwrite the dummy package. + package = if cfg.region == null && cfg.baserom == null + && cfg.extraCompileFlags == null then + cfg.package + + else + cfg.package.override (attrs: + { } // optionalAttrs (cfg.region != null) { region = cfg.region; } + // optionalAttrs (cfg.baserom != null) { baseRom = cfg.baserom; } + // optionalAttrs (cfg.extraCompileFlags != null) { + compileFlags = cfg.extraCompileFlags; + }); + + mkConfig = key: value: + let + generatedValue = if isBool value then + (if value then "true" else "false") + else if isList value then + concatStringsSep " " value + else + toString value; + in "${key} ${generatedValue}"; + +in { + meta.maintainers = [ maintainers.ivar ]; + + options.programs.sm64ex = { + enable = mkEnableOption "sm64ex"; + + package = mkOption { + type = types.package; + default = pkgs.sm64ex; + description = "The sm64ex package to use."; + }; + + region = mkOption { + type = types.nullOr (types.enum [ "us" "eu" "jp" ]); + default = null; + defaultText = + literalExpression "us"; # This is set both in nixpkgs and upstream + description = '' + Your baserom's region. Note that only "us", "eu", and "jp" are supported. + ''; + example = literalExpression "jp"; + }; + + baserom = mkOption { + type = types.nullOr types.path; + default = null; + description = + "The path to the Super Mario 64 baserom to extract assets from."; + example = literalExpression "/home/foo/baserom.us.z64"; + }; + + extraCompileFlags = mkOption { + type = with types; nullOr (listOf str); + default = null; + description = '' + Extra flags to pass to the compiler. See + + for more information. + ''; + example = literalExpression '' + [ + "BETTERCAMERA=1" + "NODRAWINGDISTANCE=1" + ]; + ''; + }; + + settings = mkOption { + type = with types; + nullOr (attrsOf (either str (either int (either bool (listOf str))))); + default = null; + description = + "Settings for sm64ex's $XDG_DATA_HOME/sm64pc/sm64config.txt file."; + example = literalExpression '' + { + fullscreen = false; + window_x = 0; + window_y = 0; + window_w = 1920; + window_h = 1080; + vsync = 1; + texture_filtering = 1; + master_volume = 127; + music_volume = 127; + sfx_volume = 127; + env_volume = 127; + key_a = [ "0026" "1000" "1103" ]; + key_b = [ "0033" "1002" "1101" ]; + key_start = [ "0039" "1006" "ffff" ]; + key_l = [ "0034" "1007" "1104" ]; + key_r = [ "0036" "100a" "1105" ]; + key_z = [ "0025" "1009" "1102" ]; + key_cup = [ "100b" "ffff" "ffff" ]; + key_cdown = [ "100c" "ffff" "ffff" ]; + key_cleft = [ "100d" "ffff" "ffff" ]; + key_cright = [ "100e" "ffff" "ffff" ]; + key_stickup = [ "0011" "ffff" "ffff" ]; + key_stickdown = [ "001f" "ffff" "ffff" ]; + key_stickleft = [ "001e" "ffff" "ffff" ]; + key_stickright = [ "0020" "ffff" "ffff" ]; + stick_deadzone = 16; + rumble_strength = 10; + skip_intro = 1; + }; + ''; + }; + }; + + config = let + configFile = optionals (cfg.settings != null) + (concatStringsSep "\n" ((mapAttrsToList mkConfig cfg.settings))); + in mkIf cfg.enable { + home.packages = [ package ]; + + xdg.dataFile."sm64pc/sm64config.txt" = + mkIf (cfg.settings != null) { text = configFile; }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/sqls.nix b/infra/libkookie/home-manager-stable/modules/programs/sqls.nix new file mode 100644 index 00000000000..33a8448fff6 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/sqls.nix @@ -0,0 +1,47 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.sqls; + + yamlFormat = pkgs.formats.yaml { }; + +in { + meta.maintainers = [ maintainers.marsam ]; + + options.programs.sqls = { + enable = mkEnableOption "sqls, a SQL language server written in Go"; + + settings = mkOption { + type = yamlFormat.type; + default = { }; + example = literalExpression '' + { + lowercaseKeywords = true; + connections = [ + { + driver = "mysql"; + dataSourceName = "root:root@tcp(127.0.0.1:13306)/world"; + } + ]; + } + ''; + description = '' + Configuration written to + $XDG_CONFIG_HOME/sqls/config.yml. See + + for supported values. + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ pkgs.sqls ]; + + xdg.configFile."sqls/config.yml" = mkIf (cfg.settings != { }) { + source = yamlFormat.generate "sqls-config" cfg.settings; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/ssh.nix b/infra/libkookie/home-manager-stable/modules/programs/ssh.nix new file mode 100644 index 00000000000..05d16a2c41b --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/ssh.nix @@ -0,0 +1,512 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.ssh; + + isPath = x: builtins.substring 0 1 (toString x) == "/"; + + addressPort = entry: + if isPath entry.address + then " ${entry.address}" + else " [${entry.address}]:${toString entry.port}"; + + unwords = builtins.concatStringsSep " "; + + bindOptions = { + address = mkOption { + type = types.str; + default = "localhost"; + example = "example.org"; + description = "The address where to bind the port."; + }; + + port = mkOption { + type = types.nullOr types.port; + default = null; + example = 8080; + description = "Specifies port number to bind on bind address."; + }; + }; + + dynamicForwardModule = types.submodule { + options = bindOptions; + }; + + forwardModule = types.submodule { + options = { + bind = bindOptions; + + host = { + address = mkOption { + type = types.nullOr types.str; + default = null; + example = "example.org"; + description = "The address where to forward the traffic to."; + }; + + port = mkOption { + type = types.nullOr types.port; + default = null; + example = 80; + description = "Specifies port number to forward the traffic to."; + }; + }; + }; + }; + + matchBlockModule = types.submodule ({ dagName, ... }: { + options = { + host = mkOption { + type = types.str; + example = "*.example.org"; + description = '' + The host pattern used by this conditional block. + ''; + }; + + port = mkOption { + type = types.nullOr types.port; + default = null; + description = "Specifies port number to connect on remote host."; + }; + + forwardAgent = mkOption { + default = null; + type = types.nullOr types.bool; + description = '' + Whether the connection to the authentication agent (if any) + will be forwarded to the remote machine. + ''; + }; + + forwardX11 = mkOption { + type = types.bool; + default = false; + description = '' + Specifies whether X11 connections will be automatically redirected + over the secure channel and DISPLAY set. + ''; + }; + + forwardX11Trusted = mkOption { + type = types.bool; + default = false; + description = '' + Specifies whether remote X11 clients will have full access to the + original X11 display. + ''; + }; + + identitiesOnly = mkOption { + type = types.bool; + default = false; + description = '' + Specifies that ssh should only use the authentication + identity explicitly configured in the + ~/.ssh/config files or passed on the + ssh command-line, even if ssh-agent + offers more identities. + ''; + }; + + identityFile = mkOption { + type = with types; either (listOf str) (nullOr str); + default = []; + apply = p: + if p == null then [] + else if isString p then [p] + else p; + description = '' + Specifies files from which the user identity is read. + Identities will be tried in the given order. + ''; + }; + + user = mkOption { + type = types.nullOr types.str; + default = null; + description = "Specifies the user to log in as."; + }; + + hostname = mkOption { + type = types.nullOr types.str; + default = null; + description = "Specifies the real host name to log into."; + }; + + serverAliveInterval = mkOption { + type = types.int; + default = 0; + description = + "Set timeout in seconds after which response will be requested."; + }; + + serverAliveCountMax = mkOption { + type = types.ints.positive; + default = 3; + description = '' + Sets the number of server alive messages which may be sent + without SSH receiving any messages back from the server. + ''; + }; + + sendEnv = mkOption { + type = types.listOf types.str; + default = []; + description = '' + Environment variables to send from the local host to the + server. + ''; + }; + + compression = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + Specifies whether to use compression. Omitted from the host + block when null. + ''; + }; + + checkHostIP = mkOption { + type = types.bool; + default = true; + description = '' + Check the host IP address in the + known_hosts file. + ''; + }; + + proxyCommand = mkOption { + type = types.nullOr types.str; + default = null; + description = "The command to use to connect to the server."; + }; + + proxyJump = mkOption { + type = types.nullOr types.str; + default = null; + description = "The proxy host to use to connect to the server."; + }; + + certificateFile = mkOption { + type = with types; either (listOf str) (nullOr str); + default = []; + apply = p: + if p == null then [] + else if isString p then [p] + else p; + description = '' + Specifies files from which the user certificate is read. + ''; + }; + + addressFamily = mkOption { + default = null; + type = types.nullOr (types.enum ["any" "inet" "inet6"]); + description = '' + Specifies which address family to use when connecting. + ''; + }; + + localForwards = mkOption { + type = types.listOf forwardModule; + default = []; + example = literalExpression '' + [ + { + bind.port = 8080; + host.address = "10.0.0.13"; + host.port = 80; + } + ]; + ''; + description = '' + Specify local port forwardings. See + + ssh_config + 5 + for LocalForward. + ''; + }; + + remoteForwards = mkOption { + type = types.listOf forwardModule; + default = []; + example = literalExpression '' + [ + { + bind.port = 8080; + host.address = "10.0.0.13"; + host.port = 80; + } + ]; + ''; + description = '' + Specify remote port forwardings. See + + ssh_config + 5 + for RemoteForward. + ''; + }; + + dynamicForwards = mkOption { + type = types.listOf dynamicForwardModule; + default = []; + example = literalExpression '' + [ { port = 8080; } ]; + ''; + description = '' + Specify dynamic port forwardings. See + + ssh_config + 5 + for DynamicForward. + ''; + }; + + extraOptions = mkOption { + type = types.attrsOf types.str; + default = {}; + description = "Extra configuration options for the host."; + }; + }; + + config.host = mkDefault dagName; + }); + + matchBlockStr = cf: concatStringsSep "\n" ( + ["Host ${cf.host}"] + ++ optional (cf.port != null) " Port ${toString cf.port}" + ++ optional (cf.forwardAgent != null) " ForwardAgent ${lib.hm.booleans.yesNo cf.forwardAgent}" + ++ optional cf.forwardX11 " ForwardX11 yes" + ++ optional cf.forwardX11Trusted " ForwardX11Trusted yes" + ++ optional cf.identitiesOnly " IdentitiesOnly yes" + ++ optional (cf.user != null) " User ${cf.user}" + ++ optional (cf.hostname != null) " HostName ${cf.hostname}" + ++ optional (cf.addressFamily != null) " AddressFamily ${cf.addressFamily}" + ++ optional (cf.sendEnv != []) " SendEnv ${unwords cf.sendEnv}" + ++ optional (cf.serverAliveInterval != 0) + " ServerAliveInterval ${toString cf.serverAliveInterval}" + ++ optional (cf.serverAliveCountMax != 3) + " ServerAliveCountMax ${toString cf.serverAliveCountMax}" + ++ optional (cf.compression != null) " Compression ${lib.hm.booleans.yesNo cf.compression}" + ++ optional (!cf.checkHostIP) " CheckHostIP no" + ++ optional (cf.proxyCommand != null) " ProxyCommand ${cf.proxyCommand}" + ++ optional (cf.proxyJump != null) " ProxyJump ${cf.proxyJump}" + ++ map (file: " IdentityFile ${file}") cf.identityFile + ++ map (file: " CertificateFile ${file}") cf.certificateFile + ++ map (f: " LocalForward" + addressPort f.bind + addressPort f.host) cf.localForwards + ++ map (f: " RemoteForward" + addressPort f.bind + addressPort f.host) cf.remoteForwards + ++ map (f: " DynamicForward" + addressPort f) cf.dynamicForwards + ++ mapAttrsToList (n: v: " ${n} ${v}") cf.extraOptions + ); + +in + +{ + meta.maintainers = [ maintainers.rycee ]; + + options.programs.ssh = { + enable = mkEnableOption "SSH client configuration"; + + forwardAgent = mkOption { + default = false; + type = types.bool; + description = '' + Whether the connection to the authentication agent (if any) + will be forwarded to the remote machine. + ''; + }; + + compression = mkOption { + default = false; + type = types.bool; + description = "Specifies whether to use compression."; + }; + + serverAliveInterval = mkOption { + type = types.int; + default = 0; + description = '' + Set default timeout in seconds after which response will be requested. + ''; + }; + + serverAliveCountMax = mkOption { + type = types.ints.positive; + default = 3; + description = '' + Sets the default number of server alive messages which may be + sent without SSH receiving any messages back from the server. + ''; + }; + + hashKnownHosts = mkOption { + default = false; + type = types.bool; + description = '' + Indicates that + + ssh + 1 + + should hash host names and addresses when they are added to + the known hosts file. + ''; + }; + + userKnownHostsFile = mkOption { + type = types.str; + default = "~/.ssh/known_hosts"; + description = '' + Specifies one or more files to use for the user host key + database, separated by whitespace. The default is + ~/.ssh/known_hosts. + ''; + }; + + controlMaster = mkOption { + default = "no"; + type = types.enum ["yes" "no" "ask" "auto" "autoask"]; + description = '' + Configure sharing of multiple sessions over a single network connection. + ''; + }; + + controlPath = mkOption { + type = types.str; + default = "~/.ssh/master-%r@%n:%p"; + description = '' + Specify path to the control socket used for connection sharing. + ''; + }; + + controlPersist = mkOption { + type = types.str; + default = "no"; + example = "10m"; + description = '' + Whether control socket should remain open in the background. + ''; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Extra configuration. + ''; + }; + + extraOptionOverrides = mkOption { + type = types.attrsOf types.str; + default = {}; + description = '' + Extra SSH configuration options that take precedence over any + host specific configuration. + ''; + }; + + includes = mkOption { + type = types.listOf types.str; + default = []; + description = '' + File globs of ssh config files that should be included via the + Include directive. + + See + + ssh_config + 5 + + for more information. + ''; + }; + + matchBlocks = mkOption { + type = hm.types.listOrDagOf matchBlockModule; + default = {}; + example = literalExpression '' + { + "john.example.com" = { + hostname = "example.com"; + user = "john"; + }; + foo = lib.hm.dag.entryBefore ["john.example.com"] { + hostname = "example.com"; + identityFile = "/home/john/.ssh/foo_rsa"; + }; + }; + ''; + description = '' + Specify per-host settings. Note, if the order of rules matter + then use the DAG functions to express the dependencies as + shown in the example. + + See + + ssh_config + 5 + + for more information. + ''; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + { + assertion = + let + # `builtins.any`/`lib.lists.any` does not return `true` if there are no elements. + any' = pred: items: if items == [] then true else any pred items; + # Check that if `entry.address` is defined, and is a path, that `entry.port` has not + # been defined. + noPathWithPort = entry: entry.address != null && isPath entry.address -> entry.port == null; + checkDynamic = block: any' noPathWithPort block.dynamicForwards; + checkBindAndHost = fwd: noPathWithPort fwd.bind && noPathWithPort fwd.host; + checkLocal = block: any' checkBindAndHost block.localForwards; + checkRemote = block: any' checkBindAndHost block.remoteForwards; + checkMatchBlock = block: all (fn: fn block) [ checkLocal checkRemote checkDynamic ]; + in any' checkMatchBlock (map (block: block.data) (builtins.attrValues cfg.matchBlocks)); + message = "Forwarded paths cannot have ports."; + } + ]; + + home.file.".ssh/config".text = + let + sortedMatchBlocks = hm.dag.topoSort cfg.matchBlocks; + sortedMatchBlocksStr = builtins.toJSON sortedMatchBlocks; + matchBlocks = + if sortedMatchBlocks ? result + then sortedMatchBlocks.result + else abort "Dependency cycle in SSH match blocks: ${sortedMatchBlocksStr}"; + in '' + ${concatStringsSep "\n" ( + (mapAttrsToList (n: v: "${n} ${v}") cfg.extraOptionOverrides) + ++ (optional (cfg.includes != [ ]) '' + Include ${concatStringsSep " " cfg.includes} + '') + ++ (map (block: matchBlockStr block.data) matchBlocks) + )} + + Host * + ForwardAgent ${lib.hm.booleans.yesNo cfg.forwardAgent} + Compression ${lib.hm.booleans.yesNo cfg.compression} + ServerAliveInterval ${toString cfg.serverAliveInterval} + ServerAliveCountMax ${toString cfg.serverAliveCountMax} + HashKnownHosts ${lib.hm.booleans.yesNo cfg.hashKnownHosts} + UserKnownHostsFile ${cfg.userKnownHostsFile} + ControlMaster ${cfg.controlMaster} + ControlPath ${cfg.controlPath} + ControlPersist ${cfg.controlPersist} + + ${replaceStrings ["\n"] ["\n "] cfg.extraConfig} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/starship.nix b/infra/libkookie/home-manager-stable/modules/programs/starship.nix new file mode 100644 index 00000000000..58ec518afee --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/starship.nix @@ -0,0 +1,125 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.starship; + + tomlFormat = pkgs.formats.toml { }; + + starshipCmd = "${config.home.profileDirectory}/bin/starship"; + +in { + meta.maintainers = [ maintainers.marsam ]; + + options.programs.starship = { + enable = mkEnableOption "starship"; + + package = mkOption { + type = types.package; + default = pkgs.starship; + defaultText = literalExpression "pkgs.starship"; + description = "The package to use for the starship binary."; + }; + + settings = mkOption { + type = with types; + let + prim = either bool (either int str); + primOrPrimAttrs = either prim (attrsOf prim); + entry = either prim (listOf primOrPrimAttrs); + entryOrAttrsOf = t: either entry (attrsOf t); + entries = entryOrAttrsOf (entryOrAttrsOf entry); + in attrsOf entries // { description = "Starship configuration"; }; + default = { }; + example = literalExpression '' + { + add_newline = false; + format = lib.concatStrings [ + "$line_break" + "$package" + "$line_break" + "$character" + ]; + scan_timeout = 10; + character = { + success_symbol = "➜"; + error_symbol = "➜"; + }; + } + ''; + description = '' + Configuration written to + $XDG_CONFIG_HOME/starship.toml. + + See for the full list + of options. + ''; + }; + + enableBashIntegration = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable Bash integration. + ''; + }; + + enableZshIntegration = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable Zsh integration. + ''; + }; + + enableFishIntegration = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable Fish integration. + ''; + }; + + enableIonIntegration = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable Ion integration. + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + + xdg.configFile."starship.toml" = mkIf (cfg.settings != { }) { + source = tomlFormat.generate "starship-config" cfg.settings; + }; + + programs.bash.initExtra = mkIf cfg.enableBashIntegration '' + if [[ $TERM != "dumb" && (-z $INSIDE_EMACS || $INSIDE_EMACS == "vterm") ]]; then + eval "$(${starshipCmd} init bash --print-full-init)" + fi + ''; + + programs.zsh.initExtra = mkIf cfg.enableZshIntegration '' + if [[ $TERM != "dumb" && (-z $INSIDE_EMACS || $INSIDE_EMACS == "vterm") ]]; then + eval "$(${starshipCmd} init zsh)" + fi + ''; + + programs.fish.interactiveShellInit = mkIf cfg.enableFishIntegration '' + if test "$TERM" != "dumb" -a \( -z "$INSIDE_EMACS" -o "$INSIDE_EMACS" = "vterm" \) + eval (${starshipCmd} init fish) + end + ''; + + programs.ion.initExtra = mkIf cfg.enableIonIntegration '' + if test $TERM != "dumb" && not exists -s INSIDE_EMACS || test $INSIDE_EMACS = "vterm" + eval $(${starshipCmd} init ion) + end + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/taskwarrior.nix b/infra/libkookie/home-manager-stable/modules/programs/taskwarrior.nix new file mode 100644 index 00000000000..3eb0013e303 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/taskwarrior.nix @@ -0,0 +1,121 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.taskwarrior; + + formatValue = value: + if isBool value then + if value then "true" else "false" + else if isList value then + concatMapStringsSep "," formatValue value + else + toString value; + + formatLine = key: value: "${key}=${formatValue value}"; + + formatSet = key: values: + (concatStringsSep "\n" + (mapAttrsToList (subKey: subValue: formatPair "${key}.${subKey}" subValue) + values)); + + formatPair = key: value: + if isAttrs value then formatSet key value else formatLine key value; + + homeConf = "${config.xdg.configHome}/task/home-manager-taskrc"; + userConf = "${config.xdg.configHome}/task/taskrc"; +in { + options = { + programs.taskwarrior = { + enable = mkEnableOption "Task Warrior"; + + config = mkOption { + type = types.attrsOf types.anything; + default = { }; + example = literalExpression '' + { + confirmation = false; + report.minimal.filter = "status:pending"; + report.active.columns = [ "id" "start" "entry.age" "priority" "project" "due" "description" ]; + report.active.labels = [ "ID" "Started" "Age" "Priority" "Project" "Due" "Description" ]; + taskd = { + certificate = "/path/to/cert"; + key = "/path/to/key"; + ca = "/path/to/ca"; + server = "host.domain:53589"; + credentials = "Org/First Last/cf31f287-ee9e-43a8-843e-e8bbd5de4294"; + }; + } + ''; + description = '' + Key-value configuration written to + $XDG_CONFIG_HOME/task/taskrc. + ''; + }; + + dataLocation = mkOption { + type = types.str; + default = "${config.xdg.dataHome}/task"; + defaultText = "$XDG_DATA_HOME/task"; + description = '' + Location where Task Warrior will store its data. + + Home Manager will attempt to create this directory. + ''; + }; + + colorTheme = mkOption { + type = with types; nullOr (either str path); + default = null; + example = "dark-blue-256"; + description = '' + Either one of the default provided theme as string, or a + path to a theme configuration file. + ''; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Additional content written at the end of + $XDG_CONFIG_HOME/task/taskrc. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ pkgs.taskwarrior ]; + + home.file."${homeConf}".text = '' + data.location=${cfg.dataLocation} + ${optionalString (cfg.colorTheme != null) (if isString cfg.colorTheme then + "include ${cfg.colorTheme}.theme" + else + "include ${cfg.colorTheme}")} + + ${concatStringsSep "\n" (mapAttrsToList formatPair cfg.config)} + + ${cfg.extraConfig} + ''; + + home.activation.regenDotTaskRc = hm.dag.entryAfter [ "writeBoundary" ] '' + $VERBOSE_ECHO "Ensuring generated taskwarrior config included in taskrc" + + if [[ ! -s "${userConf}" ]]; then + # Ensure file's existence + if [[ -v DRY_RUN ]]; then + $DRY_RUN_CMD echo "include ${homeConf}" ">" "${userConf}" + else + echo "include ${homeConf}" > "${userConf}" + fi + elif ! grep -qF "include ${homeConf}" ${escapeShellArg userConf}; then + # Add include statement for Home Manager generated config. + $DRY_RUN_CMD sed -i '1i include ${homeConf}' ${escapeShellArg userConf} + fi + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/tealdeer.nix b/infra/libkookie/home-manager-stable/modules/programs/tealdeer.nix new file mode 100644 index 00000000000..98ef4d2c8a3 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/tealdeer.nix @@ -0,0 +1,53 @@ +{ config, lib, pkgs, ... }: + +with lib; +let + cfg = config.programs.tealdeer; + + tomlFormat = pkgs.formats.toml { }; + + configDir = if pkgs.stdenv.isDarwin then + "Library/Application Support" + else + config.xdg.configHome; + +in { + meta.maintainers = [ maintainers.marsam ]; + + options.programs.tealdeer = { + enable = mkEnableOption "Tealdeer"; + + settings = mkOption { + type = tomlFormat.type; + default = { }; + defaultText = literalExpression "{ }"; + example = literalExpression '' + { + display = { + compact = false; + use_pager = true; + }; + updates = { + auto_update = false; + }; + }; + ''; + description = '' + Configuration written to + $XDG_CONFIG_HOME/tealdeer/config.toml on Linux or + $HOME/Library/Application Support/tealdeer/config.toml + on Darwin. See + + for more information. + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ pkgs.tealdeer ]; + + home.file."${configDir}/tealdeer/config.toml" = mkIf (cfg.settings != { }) { + source = tomlFormat.generate "tealdeer-config" cfg.settings; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/terminator.nix b/infra/libkookie/home-manager-stable/modules/programs/terminator.nix new file mode 100644 index 00000000000..4a5e367bc12 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/terminator.nix @@ -0,0 +1,75 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.terminator; + + toValue = val: + if val == null then + "None" + else if val == true then + "True" + else if val == false then + "False" + else + ''"${toString val}"''; + + toConfigObject = let + toKey = depth: key: + if depth == 0 then key else toKey (depth - 1) "[${key}]"; + toConfigObjectLevel = depth: obj: + flatten (mapAttrsToList (key: val: + if isAttrs val then + [ (toKey depth key) ] ++ toConfigObjectLevel (depth + 1) val + else + [ "${key} = ${toValue val}" ]) obj); + in obj: concatStringsSep "\n" (toConfigObjectLevel 1 obj); + +in { + meta.maintainers = [ maintainers.chisui ]; + + options.programs.terminator = { + enable = mkEnableOption "terminator, a tiling terminal emulator"; + + package = mkOption { + type = types.package; + default = pkgs.terminator; + example = literalExpression "pkgs.terminator"; + description = "terminator package to install."; + }; + + config = mkOption { + default = { }; + description = '' + configuration for terminator. + + For a list of all possible options refer to the + + terminator_config + 5 + + man page. + ''; + type = types.attrsOf types.anything; + example = literalExpression '' + { + global_config.borderless = true; + profiles.default.background_color = "#002b36"; + } + ''; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (hm.assertions.assertPlatform "programs.terminator" pkgs platforms.linux) + ]; + + home.packages = [ cfg.package ]; + + xdg.configFile."terminator/config" = + mkIf (cfg.config != { }) { text = toConfigObject cfg.config; }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/termite.nix b/infra/libkookie/home-manager-stable/modules/programs/termite.nix new file mode 100644 index 00000000000..ccf3cabb3f3 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/termite.nix @@ -0,0 +1,384 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.termite; + +in { + options = { + programs.termite = { + enable = mkEnableOption "Termite VTE-based terminal"; + + allowBold = mkOption { + default = null; + type = types.nullOr types.bool; + description = '' + Allow the output of bold characters when the bold escape sequence appears. + ''; + }; + + audibleBell = mkOption { + default = null; + type = types.nullOr types.bool; + description = "Have the terminal beep on the terminal bell."; + }; + + clickableUrl = mkOption { + default = null; + type = types.nullOr types.bool; + description = '' + Auto-detected URLs can be clicked on to open them in your browser. + Only enabled if a browser is configured or detected. + ''; + }; + + dynamicTitle = mkOption { + default = null; + type = types.nullOr types.bool; + description = '' + Settings dynamic title allows the terminal and the shell to + update the terminal's title. + ''; + }; + + enableVteIntegration = mkEnableOption "Shell VTE integration" // { + default = true; + }; + + fullscreen = mkOption { + default = null; + type = types.nullOr types.bool; + description = "Enables entering fullscreen mode by pressing F11."; + }; + + mouseAutohide = mkOption { + default = null; + type = types.nullOr types.bool; + description = '' + Automatically hide the mouse pointer when you start typing. + ''; + }; + + scrollOnOutput = mkOption { + default = null; + type = types.nullOr types.bool; + description = "Scroll to the bottom when the shell generates output."; + }; + + scrollOnKeystroke = mkOption { + default = null; + type = types.nullOr types.bool; + description = '' + Scroll to the bottom automatically when a key is pressed. + ''; + }; + + searchWrap = mkOption { + default = null; + type = types.nullOr types.bool; + description = "Search from top again when you hit the bottom."; + }; + + urgentOnBell = mkOption { + default = null; + type = types.nullOr types.bool; + description = "Sets the window as urgent on the terminal bell."; + }; + + font = mkOption { + default = null; + example = "Monospace 12"; + type = types.nullOr types.str; + description = "The font description for the terminal's font."; + }; + + geometry = mkOption { + default = null; + example = "640x480"; + type = types.nullOr types.str; + description = "The default window geometry for new terminal windows."; + }; + + iconName = mkOption { + default = null; + example = "terminal"; + type = types.nullOr types.str; + description = + "The name of the icon to be used for the terminal process."; + }; + + scrollbackLines = mkOption { + default = null; + example = 10000; + type = types.nullOr types.int; + description = + "Set the number of lines to limit the terminal's scrollback."; + }; + + browser = mkOption { + default = null; + type = types.nullOr types.str; + example = "${pkgs.xdg-utils}/xdg-open"; + description = '' + Set the default browser for opening links. If its not set, $BROWSER is read. + If that's not set, url hints will be disabled. + ''; + }; + + cursorBlink = mkOption { + default = null; + example = "system"; + type = types.nullOr (types.enum [ "system" "on" "off" ]); + description = '' + Specify the how the terminal's cursor should behave. + Accepts system to respect the gtk global configuration, + on and off to explicitly enable or disable them. + ''; + }; + + cursorShape = mkOption { + default = null; + example = "block"; + type = types.nullOr (types.enum [ "block" "underline" "ibeam" ]); + description = '' + Specify how the cursor should look. Accepts block, ibeam and underline. + ''; + }; + + filterUnmatchedUrls = mkOption { + default = null; + type = types.nullOr types.bool; + description = + "Whether to hide url hints not matching input in url hints mode."; + }; + + modifyOtherKeys = mkOption { + default = null; + type = types.nullOr types.bool; + description = '' + Emit escape sequences for extra keys, + like the modifyOtherKeys resource for + + xterm + 1 + . + ''; + }; + + sizeHints = mkOption { + default = null; + type = types.nullOr types.bool; + description = '' + Enable size hints. Locks the terminal resizing + to increments of the terminal's cell size. + Requires a window manager that respects scroll hints. + ''; + }; + + scrollbar = mkOption { + default = null; + type = types.nullOr (types.enum [ "off" "left" "right" ]); + description = "Scrollbar position."; + }; + + backgroundColor = mkOption { + default = null; + example = "rgba(63, 63, 63, 0.8)"; + type = types.nullOr types.str; + description = "Background color value."; + }; + + cursorColor = mkOption { + default = null; + example = "#dcdccc"; + type = types.nullOr types.str; + description = "Cursor color value."; + }; + + cursorForegroundColor = mkOption { + default = null; + example = "#dcdccc"; + type = types.nullOr types.str; + description = "Cursor foreground color value."; + }; + + foregroundColor = mkOption { + default = null; + example = "#dcdccc"; + type = types.nullOr types.str; + description = "Foreground color value."; + }; + + foregroundBoldColor = mkOption { + default = null; + example = "#ffffff"; + type = types.nullOr types.str; + description = "Foreground bold color value."; + }; + + highlightColor = mkOption { + default = null; + example = "#2f2f2f"; + type = types.nullOr types.str; + description = "highlight color value."; + }; + + hintsActiveBackgroundColor = mkOption { + default = null; + example = "#3f3f3f"; + type = types.nullOr types.str; + description = "Hints active background color value."; + }; + + hintsActiveForegroundColor = mkOption { + default = null; + example = "#e68080"; + type = types.nullOr types.str; + description = "Hints active foreground color value."; + }; + + hintsBackgroundColor = mkOption { + default = null; + example = "#3f3f3f"; + type = types.nullOr types.str; + description = "Hints background color value."; + }; + + hintsForegroundColor = mkOption { + default = null; + example = "#dcdccc"; + type = types.nullOr types.str; + description = "Hints foreground color value."; + }; + + hintsBorderColor = mkOption { + default = null; + example = "#3f3f3f"; + type = types.nullOr types.str; + description = "Hints border color value."; + }; + + hintsBorderWidth = mkOption { + default = null; + example = "0.5"; + type = types.nullOr types.str; + description = "Hints border width."; + }; + + hintsFont = mkOption { + default = null; + example = "Monospace 12"; + type = types.nullOr types.str; + description = "The font description for the hints font."; + }; + + hintsPadding = mkOption { + default = null; + example = 2; + type = types.nullOr types.int; + description = "Hints padding."; + }; + + hintsRoundness = mkOption { + default = null; + example = "0.2"; + type = types.nullOr types.str; + description = "Hints roundness."; + }; + + optionsExtra = mkOption { + default = ""; + example = "fullscreen = true"; + type = types.lines; + description = + "Extra options that should be added to [options] section."; + }; + + colorsExtra = mkOption { + default = ""; + example = '' + color0 = #3f3f3f + color1 = #705050 + color2 = #60b48a + ''; + type = types.lines; + description = + "Extra colors options that should be added to [colors] section."; + }; + + hintsExtra = mkOption { + default = ""; + example = "border = #3f3f3f"; + type = types.lines; + description = + "Extra hints options that should be added to [hints] section."; + }; + }; + }; + + config = (let + boolToString = v: if v then "true" else "false"; + optionalBoolean = name: val: + lib.optionalString (val != null) "${name} = ${boolToString val}"; + optionalInteger = name: val: + lib.optionalString (val != null) "${name} = ${toString val}"; + optionalString = name: val: + lib.optionalString (val != null) "${name} = ${val}"; + in mkIf cfg.enable { + home.packages = [ pkgs.termite ]; + xdg.configFile."termite/config".text = '' + [options] + ${optionalBoolean "allow_bold" cfg.allowBold} + ${optionalBoolean "audible_bell" cfg.audibleBell} + ${optionalString "browser" cfg.browser} + ${optionalBoolean "clickable_url" cfg.clickableUrl} + ${optionalString "cursor_blink" cfg.cursorBlink} + ${optionalString "cursor_shape" cfg.cursorShape} + ${optionalBoolean "dynamic_title" cfg.dynamicTitle} + ${optionalBoolean "filter_unmatched_urls" cfg.filterUnmatchedUrls} + ${optionalString "font" cfg.font} + ${optionalBoolean "fullscreen" cfg.fullscreen} + ${optionalString "geometry" cfg.geometry} + ${optionalString "icon_name" cfg.iconName} + ${optionalBoolean "modify_other_keys" cfg.modifyOtherKeys} + ${optionalBoolean "mouse_autohide" cfg.mouseAutohide} + ${optionalBoolean "scroll_on_keystroke" cfg.scrollOnKeystroke} + ${optionalBoolean "scroll_on_output" cfg.scrollOnOutput} + ${optionalInteger "scrollback_lines" cfg.scrollbackLines} + ${optionalString "scrollbar" cfg.scrollbar} + ${optionalBoolean "search_wrap" cfg.searchWrap} + ${optionalBoolean "size_hints" cfg.sizeHints} + ${optionalBoolean "urgent_on_bell" cfg.urgentOnBell} + + ${cfg.optionsExtra} + + [colors] + ${optionalString "background" cfg.backgroundColor} + ${optionalString "cursor" cfg.cursorColor} + ${optionalString "cursor_foreground" cfg.cursorForegroundColor} + ${optionalString "foreground" cfg.foregroundColor} + ${optionalString "foreground_bold" cfg.foregroundBoldColor} + ${optionalString "highlight" cfg.highlightColor} + + ${cfg.colorsExtra} + + [hints] + ${optionalString "active_background" cfg.hintsActiveBackgroundColor} + ${optionalString "active_foreground" cfg.hintsActiveForegroundColor} + ${optionalString "background" cfg.hintsBackgroundColor} + ${optionalString "border" cfg.hintsBorderColor} + ${optionalInteger "border_width" cfg.hintsBorderWidth} + ${optionalString "font" cfg.hintsFont} + ${optionalString "foreground" cfg.hintsForegroundColor} + ${optionalInteger "padding" cfg.hintsPadding} + ${optionalInteger "roundness" cfg.hintsRoundness} + + ${cfg.hintsExtra} + ''; + + programs.bash.enableVteIntegration = lib.mkDefault cfg.enableVteIntegration; + programs.zsh.enableVteIntegration = lib.mkDefault cfg.enableVteIntegration; + }); +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/texlive.nix b/infra/libkookie/home-manager-stable/modules/programs/texlive.nix new file mode 100644 index 00000000000..bd17025d476 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/texlive.nix @@ -0,0 +1,53 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.texlive; + + texlive = cfg.packageSet; + texlivePkgs = cfg.extraPackages texlive; + +in { + meta.maintainers = [ maintainers.rycee ]; + + options = { + programs.texlive = { + enable = mkEnableOption "TeX Live"; + + packageSet = mkOption { + default = pkgs.texlive; + defaultText = literalExpression "pkgs.texlive"; + description = "TeX Live package set to use."; + }; + + extraPackages = mkOption { + default = tpkgs: { inherit (tpkgs) collection-basic; }; + defaultText = "tpkgs: { inherit (tpkgs) collection-basic; }"; + example = literalExpression '' + tpkgs: { inherit (tpkgs) collection-fontsrecommended algorithms; } + ''; + description = "Extra packages available to TeX Live."; + }; + + package = mkOption { + type = types.package; + description = "Resulting customized TeX Live package."; + readOnly = true; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [{ + assertion = texlivePkgs != { }; + message = "Must provide at least one extra package in" + + " 'programs.texlive.extraPackages'."; + }]; + + home.packages = [ cfg.package ]; + + programs.texlive.package = texlive.combine texlivePkgs; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/timidity.nix b/infra/libkookie/home-manager-stable/modules/programs/timidity.nix new file mode 100644 index 00000000000..26b9de9829c --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/timidity.nix @@ -0,0 +1,51 @@ +{ config, lib, pkgs, ... }: + +let + + cfg = config.programs.timidity; + +in { + meta.maintainers = [ lib.hm.maintainers.amesgen ]; + + options.programs.timidity = { + enable = lib.mkEnableOption "timidity, a software MIDI renderer"; + + package = lib.mkOption { + type = lib.types.package; + default = pkgs.timidity; + defaultText = lib.literalExpression "pkgs.timidity"; + description = "The timidity package to use."; + }; + + finalPackage = lib.mkOption { + readOnly = true; + type = lib.types.package; + description = "Resulting package."; + }; + + extraConfig = lib.mkOption { + type = lib.types.lines; + default = ""; + example = lib.literalExpression '' + ''' + soundfont ''${pkgs.soundfont-fluid}/share/soundfonts/FluidR3_GM2-2.sf2 + ''' + ''; + description = "Extra configuration."; + }; + }; + + config = lib.mkIf cfg.enable { + home.packages = [ cfg.finalPackage ]; + + programs.timidity.finalPackage = pkgs.symlinkJoin { + name = "timidity-with-config"; + paths = [ cfg.package ]; + nativeBuildInputs = [ pkgs.makeWrapper ]; + postBuild = '' + wrapProgram $out/bin/timidity \ + --add-flags '-c ${pkgs.writeText "timidity.cfg" cfg.extraConfig}' + ''; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/tint2.nix b/infra/libkookie/home-manager-stable/modules/programs/tint2.nix new file mode 100644 index 00000000000..9a55bb1fdff --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/tint2.nix @@ -0,0 +1,41 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.tint2; + +in { + meta.maintainers = [ hm.maintainers.CarlosLoboxyz ]; + + options.programs.tint2 = { + enable = + mkEnableOption "tint2, a simple, unobtrusive and light panel for Xorg"; + + package = mkOption { + type = types.package; + default = pkgs.tint2; + defaultText = literalExpression "pkgs.tint2"; + description = "Tint2 package to install."; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Commands for tint2 that will be add to the tint2rc + file. + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ pkgs.package ]; + + xdg.configFile = { + "tint2/tint2rc" = + mkIf (cfg.extraConfig != "") { text = cfg.extraConfig; }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/tiny.nix b/infra/libkookie/home-manager-stable/modules/programs/tiny.nix new file mode 100644 index 00000000000..d502801f92f --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/tiny.nix @@ -0,0 +1,65 @@ +{ config, lib, pkgs, ... }: + +with lib; +let + cfg = config.programs.tiny; + format = pkgs.formats.yaml { }; + configDir = if pkgs.stdenv.isDarwin then + "Library/Application Support/tiny" + else + "${config.xdg.configHome}/tiny"; +in { + meta.maintainers = [ hm.maintainers.kmaasrud ]; + + options = { + programs.tiny = { + enable = mkEnableOption "tiny, a TUI IRC client written in Rust"; + + package = mkOption { + type = types.package; + default = pkgs.tiny; + defaultText = literalExpression "pkgs.tiny"; + description = "The tiny package to install."; + }; + + settings = mkOption { + type = format.type; + default = { }; + defaultText = literalExpression "{ }"; + example = literalExpression '' + { + servers = [ + { + addr = "irc.libera.chat"; + port = 6697; + tls = true; + realname = "John Doe"; + nicks = [ "tinyuser" ]; + } + ]; + defaults = { + nicks = [ "tinyuser" ]; + realname = "John Doe"; + join = []; + tls = true; + }; + }; + ''; + description = '' + Configuration written to + $XDG_CONFIG_HOME/tiny/config.yml. See + + for the default configuration. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + + home.file."${configDir}/config.yml" = mkIf (cfg.settings != { }) { + source = format.generate "tiny-config" cfg.settings; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/tmux.nix b/infra/libkookie/home-manager-stable/modules/programs/tmux.nix new file mode 100644 index 00000000000..bf98a3f37b2 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/tmux.nix @@ -0,0 +1,342 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.tmux; + + pluginName = p: if types.package.check p then p.pname else p.plugin.pname; + + pluginModule = types.submodule { + options = { + plugin = mkOption { + type = types.package; + description = "Path of the configuration file to include."; + }; + + extraConfig = mkOption { + type = types.lines; + description = "Additional configuration for the associated plugin."; + default = ""; + }; + }; + }; + + defaultKeyMode = "emacs"; + defaultResize = 5; + defaultShortcut = "b"; + defaultTerminal = "screen"; + defaultShell = null; + + boolToStr = value: if value then "on" else "off"; + + tmuxConf = '' + ${optionalString cfg.sensibleOnTop '' + # ============================================= # + # Start with defaults from the Sensible plugin # + # --------------------------------------------- # + run-shell ${pkgs.tmuxPlugins.sensible.rtp} + # ============================================= # + ''} + set -g default-terminal "${cfg.terminal}" + set -g base-index ${toString cfg.baseIndex} + setw -g pane-base-index ${toString cfg.baseIndex} + ${optionalString (cfg.shell != null) '' + # We need to set default-shell before calling new-session + set -g default-shell "${cfg.shell}" + ''} + ${optionalString cfg.newSession "new-session"} + + ${optionalString cfg.reverseSplit '' + bind -N "Split the pane into two, left and right" v split-window -h + bind -N "Split the pane into two, top and bottom" s split-window -v + ''} + + set -g status-keys ${cfg.keyMode} + set -g mode-keys ${cfg.keyMode} + + ${optionalString + (cfg.keyMode == "vi" && cfg.customPaneNavigationAndResize) '' + bind -N "Select pane to the left of the active pane" h select-pane -L + bind -N "Select pane below the active pane" j select-pane -D + bind -N "Select pane above the active pane" k select-pane -U + bind -N "Select pane to the right of the active pane" l select-pane -R + + bind -r -N "Resize the pane left by ${toString cfg.resizeAmount}" \ + H resize-pane -L ${toString cfg.resizeAmount} + bind -r -N "Resize the pane down by ${toString cfg.resizeAmount}" \ + J resize-pane -D ${toString cfg.resizeAmount} + bind -r -N "Resize the pane up by ${toString cfg.resizeAmount}" \ + K resize-pane -U ${toString cfg.resizeAmount} + bind -r -N "Resize the pane right by ${toString cfg.resizeAmount}" \ + L resize-pane -R ${toString cfg.resizeAmount} + ''} + + ${if cfg.prefix != null then '' + # rebind main key: ${cfg.prefix} + unbind C-${defaultShortcut} + set -g prefix ${cfg.prefix} + bind -N "Send the prefix key through to the application" \ + ${cfg.prefix} send-prefix + '' else + optionalString (cfg.shortcut != defaultShortcut) '' + # rebind main key: C-${cfg.shortcut} + unbind C-${defaultShortcut} + set -g prefix C-${cfg.shortcut} + bind -N "Send the prefix key through to the application" \ + ${cfg.shortcut} send-prefix + bind C-${cfg.shortcut} last-window + ''} + + ${optionalString cfg.disableConfirmationPrompt '' + bind-key -N "Kill the current window" & kill-window + bind-key -N "Kill the current pane" x kill-pane + ''} + + setw -g aggressive-resize ${boolToStr cfg.aggressiveResize} + setw -g clock-mode-style ${if cfg.clock24 then "24" else "12"} + set -s escape-time ${toString cfg.escapeTime} + set -g history-limit ${toString cfg.historyLimit} + ''; + + configPlugins = { + assertions = [ + (let + hasBadPluginName = p: !(hasPrefix "tmuxplugin" (pluginName p)); + badPlugins = filter hasBadPluginName cfg.plugins; + in { + assertion = badPlugins == [ ]; + message = ''Invalid tmux plugin (not prefixed with "tmuxplugins"): '' + + concatMapStringsSep ", " pluginName badPlugins; + }) + ]; + + xdg.configFile."tmux/tmux.conf".text = '' + # ============================================= # + # Load plugins with Home Manager # + # --------------------------------------------- # + + ${(concatMapStringsSep "\n\n" (p: '' + # ${pluginName p} + # --------------------- + ${p.extraConfig or ""} + run-shell ${if types.package.check p then p.rtp else p.plugin.rtp} + '') cfg.plugins)} + # ============================================= # + ''; + }; + +in { + options = { + programs.tmux = { + aggressiveResize = mkOption { + default = false; + type = types.bool; + description = '' + Resize the window to the size of the smallest session for + which it is the current window. + ''; + }; + + baseIndex = mkOption { + default = 0; + example = 1; + type = types.ints.unsigned; + description = "Base index for windows and panes."; + }; + + clock24 = mkOption { + default = false; + type = types.bool; + description = "Use 24 hour clock."; + }; + + customPaneNavigationAndResize = mkOption { + default = false; + type = types.bool; + description = '' + Override the hjkl and HJKL bindings for pane navigation and + resizing in VI mode. + ''; + }; + + disableConfirmationPrompt = mkOption { + default = false; + type = types.bool; + description = '' + Disable confirmation prompt before killing a pane or window + ''; + }; + + enable = mkEnableOption "tmux"; + + escapeTime = mkOption { + default = 500; + example = 0; + type = types.ints.unsigned; + description = '' + Time in milliseconds for which tmux waits after an escape is + input. + ''; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Additional configuration to add to + tmux.conf. + ''; + }; + + historyLimit = mkOption { + default = 2000; + example = 5000; + type = types.ints.positive; + description = "Maximum number of lines held in window history."; + }; + + keyMode = mkOption { + default = defaultKeyMode; + example = "vi"; + type = types.enum [ "emacs" "vi" ]; + description = "VI or Emacs style shortcuts."; + }; + + newSession = mkOption { + default = false; + type = types.bool; + description = '' + Automatically spawn a session if trying to attach and none + are running. + ''; + }; + + package = mkOption { + type = types.package; + default = pkgs.tmux; + defaultText = literalExpression "pkgs.tmux"; + example = literalExpression "pkgs.tmux"; + description = "The tmux package to install"; + }; + + reverseSplit = mkOption { + default = false; + type = types.bool; + description = "Reverse the window split shortcuts."; + }; + + resizeAmount = mkOption { + default = defaultResize; + example = 10; + type = types.ints.positive; + description = "Number of lines/columns when resizing."; + }; + + sensibleOnTop = mkOption { + type = types.bool; + default = true; + description = '' + Run the sensible plugin at the top of the configuration. It + is possible to override the sensible settings using the + option. + ''; + }; + + prefix = mkOption { + default = null; + example = "C-a"; + type = types.nullOr types.str; + description = '' + Set the prefix key. Overrules the "shortcut" option when set. + ''; + }; + + shortcut = mkOption { + default = defaultShortcut; + example = "a"; + type = types.str; + description = '' + CTRL following by this key is used as the main shortcut. + ''; + }; + + terminal = mkOption { + default = defaultTerminal; + example = "screen-256color"; + type = types.str; + description = "Set the $TERM variable."; + }; + + shell = mkOption { + default = defaultShell; + example = "\${pkgs.zsh}/bin/zsh"; + type = with types; nullOr str; + description = "Set the default-shell tmux variable."; + }; + + secureSocket = mkOption { + default = pkgs.stdenv.isLinux; + type = types.bool; + description = '' + Store tmux socket under /run, which is more + secure than /tmp, but as a downside it doesn't + survive user logout. + ''; + }; + + tmuxp.enable = mkEnableOption "tmuxp"; + + tmuxinator.enable = mkEnableOption "tmuxinator"; + + plugins = mkOption { + type = with types; + listOf (either package pluginModule) // { + description = "list of plugin packages or submodules"; + }; + description = '' + List of tmux plugins to be included at the end of your tmux + configuration. The sensible plugin, however, is defaulted to + run at the top of your configuration. + ''; + default = [ ]; + example = literalExpression '' + with pkgs; [ + tmuxPlugins.cpu + { + plugin = tmuxPlugins.resurrect; + extraConfig = "set -g @resurrect-strategy-nvim 'session'"; + } + { + plugin = tmuxPlugins.continuum; + extraConfig = ''' + set -g @continuum-restore 'on' + set -g @continuum-save-interval '60' # minutes + '''; + } + ] + ''; + }; + }; + }; + + config = mkIf cfg.enable (mkMerge ([ + { + home.packages = [ cfg.package ] + ++ optional cfg.tmuxinator.enable pkgs.tmuxinator + ++ optional cfg.tmuxp.enable pkgs.tmuxp; + } + + { xdg.configFile."tmux/tmux.conf".text = mkBefore tmuxConf; } + { xdg.configFile."tmux/tmux.conf".text = mkAfter cfg.extraConfig; } + + (mkIf cfg.secureSocket { + home.sessionVariables = { + TMUX_TMPDIR = ''''${XDG_RUNTIME_DIR:-"/run/user/\$(id -u)"}''; + }; + }) + + (mkIf (cfg.plugins != [ ]) configPlugins) + ])); +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/topgrade.nix b/infra/libkookie/home-manager-stable/modules/programs/topgrade.nix new file mode 100644 index 00000000000..ac88643d092 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/topgrade.nix @@ -0,0 +1,60 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.topgrade; + + tomlFormat = pkgs.formats.toml { }; + +in { + + meta.maintainers = [ hm.maintainers.msfjarvis ]; + + options.programs.topgrade = { + enable = mkEnableOption "topgrade"; + + package = mkOption { + type = types.package; + default = pkgs.topgrade; + defaultText = literalExpression "pkgs.topgrade"; + description = "The package to use for the topgrade binary."; + }; + + settings = mkOption { + type = tomlFormat.type; + default = { }; + defaultText = literalExpression "{ }"; + example = literalExpression '' + { + assume_yes = true; + disable = [ + "flutter" + "node" + ]; + set_title = false; + cleanup = true; + commands = { + "Run garbage collection on Nix store" = "nix-collect-garbage"; + }; + } + ''; + description = '' + Configuration written to + $XDG_CONFIG_HOME/topgrade.toml. + + See for the full list + of options. + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + + xdg.configFile."topgrade.toml" = mkIf (cfg.settings != { }) { + source = tomlFormat.generate "topgrade-config" cfg.settings; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/urxvt.nix b/infra/libkookie/home-manager-stable/modules/programs/urxvt.nix new file mode 100644 index 00000000000..905e14c14a1 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/urxvt.nix @@ -0,0 +1,156 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.urxvt; + +in { + options.programs.urxvt = { + enable = mkEnableOption "rxvt-unicode terminal emulator"; + + package = mkOption { + type = types.package; + default = pkgs.rxvt_unicode; + defaultText = literalExpression "pkgs.rxvt_unicode"; + description = "rxvt-unicode package to install."; + }; + + fonts = mkOption { + type = types.listOf types.str; + default = [ ]; + description = "List of fonts to be used."; + example = [ "xft:Droid Sans Mono Nerd Font:size=9" ]; + }; + + keybindings = mkOption { + type = types.attrsOf types.str; + default = { }; + description = "Mapping of keybindings to actions"; + example = literalExpression '' + { + "Shift-Control-C" = "eval:selection_to_clipboard"; + "Shift-Control-V" = "eval:paste_clipboard"; + } + ''; + }; + + iso14755 = mkOption { + type = types.bool; + default = true; + description = + "ISO14755 support for viewing and entering unicode characters."; + }; + + scroll = { + bar = mkOption { + type = types.submodule { + options = { + enable = mkOption { + type = types.bool; + default = true; + description = "Whether to enable the scrollbar"; + }; + + style = mkOption { + type = types.enum [ "rxvt" "plain" "next" "xterm" ]; + default = "plain"; + description = "Scrollbar style."; + }; + + align = mkOption { + type = types.enum [ "top" "bottom" "center" ]; + default = "center"; + description = "Scrollbar alignment."; + }; + + position = mkOption { + type = types.enum [ "left" "right" ]; + default = "right"; + description = "Scrollbar position."; + }; + + floating = mkOption { + type = types.bool; + default = true; + description = + "Whether to display an rxvt scrollbar without a trough."; + }; + }; + }; + default = { }; + description = "Scrollbar settings."; + }; + + lines = mkOption { + type = types.ints.unsigned; + default = 10000; + description = "Number of lines to save in the scrollback buffer."; + }; + + keepPosition = mkOption { + type = types.bool; + default = true; + description = + "Whether to keep a scroll position when TTY receives new lines."; + }; + + scrollOnKeystroke = mkOption { + type = types.bool; + default = true; + description = "Whether to scroll to bottom on keyboard input."; + }; + + scrollOnOutput = mkOption { + type = types.bool; + default = false; + description = "Whether to scroll to bottom on TTY output."; + }; + }; + + transparent = mkOption { + type = types.bool; + default = false; + description = "Whether to enable pseudo-transparency."; + }; + + shading = mkOption { + type = types.ints.between 0 200; + default = 100; + description = + "Darken (0 .. 99) or lighten (101 .. 200) the transparent background."; + }; + + extraConfig = mkOption { + default = { }; + type = types.attrsOf types.anything; + description = "Additional configuration to add."; + example = { "shading" = 15; }; + }; + + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + + xresources.properties = { + "URxvt.scrollBar" = cfg.scroll.bar.enable; + "URxvt.scrollstyle" = cfg.scroll.bar.style; + "URxvt.scrollBar_align" = cfg.scroll.bar.align; + "URxvt.scrollBar_right" = cfg.scroll.bar.position == "right"; + "URxvt.scrollBar_floating" = cfg.scroll.bar.floating; + "URxvt.saveLines" = cfg.scroll.lines; + "URxvt.scrollWithBuffer" = cfg.scroll.keepPosition; + "URxvt.scrollTtyKeypress" = cfg.scroll.scrollOnKeystroke; + "URxvt.scrollTtyOutput" = cfg.scroll.scrollOnOutput; + "URxvt.transparent" = cfg.transparent; + "URxvt.shading" = cfg.shading; + "URxvt.iso14755" = cfg.iso14755; + } // flip mapAttrs' cfg.keybindings + (kb: action: nameValuePair "URxvt.keysym.${kb}" action) + // optionalAttrs (cfg.fonts != [ ]) { + "URxvt.font" = concatStringsSep "," cfg.fonts; + } // flip mapAttrs' cfg.extraConfig (k: v: nameValuePair "URxvt.${k}" v); + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/vim.nix b/infra/libkookie/home-manager-stable/modules/programs/vim.nix new file mode 100644 index 00000000000..46e5f95db10 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/vim.nix @@ -0,0 +1,178 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.vim; + defaultPlugins = [ pkgs.vimPlugins.vim-sensible ]; + + knownSettings = { + background = types.enum [ "dark" "light" ]; + backupdir = types.listOf types.str; + copyindent = types.bool; + directory = types.listOf types.str; + expandtab = types.bool; + hidden = types.bool; + history = types.int; + ignorecase = types.bool; + modeline = types.bool; + mouse = types.enum [ "n" "v" "i" "c" "h" "a" "r" ]; + mousefocus = types.bool; + mousehide = types.bool; + mousemodel = types.enum [ "extend" "popup" "popup_setpos" ]; + number = types.bool; + relativenumber = types.bool; + shiftwidth = types.int; + smartcase = types.bool; + tabstop = types.int; + undodir = types.listOf types.str; + undofile = types.bool; + }; + + vimSettingsType = types.submodule { + options = let + opt = name: type: + mkOption { + type = types.nullOr type; + default = null; + visible = false; + }; + in mapAttrs opt knownSettings; + }; + + setExpr = name: value: + let + v = if isBool value then + (if value then "" else "no") + name + else + "${name}=${ + if isList value then concatStringsSep "," value else toString value + }"; + in optionalString (value != null) ("set " + v); + + plugins = let + vpkgs = pkgs.vimPlugins; + getPkg = p: + if isDerivation p then + [ p ] + else + optional (isString p && hasAttr p vpkgs) vpkgs.${p}; + in concatMap getPkg cfg.plugins; + +in { + options = { + programs.vim = { + enable = mkEnableOption "Vim"; + + plugins = mkOption { + type = with types; listOf (either str package); + default = defaultPlugins; + example = literalExpression "[ pkgs.vimPlugins.YankRing ]"; + description = '' + List of vim plugins to install. To get a list of supported plugins run: + nix-env -f '<nixpkgs>' -qaP -A vimPlugins. + + + + Note: String values are deprecated, please use actual packages. + ''; + }; + + settings = mkOption { + type = vimSettingsType; + default = { }; + example = literalExpression '' + { + expandtab = true; + history = 1000; + background = "dark"; + } + ''; + description = '' + At attribute set of Vim settings. The attribute names and + corresponding values must be among the following supported + options. + + + ${concatStringsSep "\n" (mapAttrsToList (n: v: '' + + ${n} + ${v.description} + + '') knownSettings)} + + + See the Vim documentation for detailed descriptions of these + options. Note, use extraConfig to + manually set any options not listed above. + ''; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + example = '' + set nocompatible + set nobackup + ''; + description = "Custom .vimrc lines"; + }; + + package = mkOption { + type = types.package; + description = "Resulting customized vim package"; + readOnly = true; + }; + + packageConfigurable = mkOption { + type = types.package; + description = "Configurable vim package"; + default = pkgs.vim_configurable; + defaultText = "pkgs.vim_configurable"; + }; + }; + }; + + config = (let + customRC = '' + ${concatStringsSep "\n" (remove "" (mapAttrsToList setExpr + (builtins.intersectAttrs knownSettings cfg.settings)))} + + ${cfg.extraConfig} + ''; + + vim = cfg.packageConfigurable.customize { + name = "vim"; + vimrcConfig = { + inherit customRC; + + packages.home-manager.start = plugins; + }; + }; + in mkIf cfg.enable { + assertions = let + packagesNotFound = + filter (p: isString p && (!hasAttr p pkgs.vimPlugins)) cfg.plugins; + in [{ + assertion = packagesNotFound == [ ]; + message = "Following VIM plugin not found in pkgs.vimPlugins: ${ + concatMapStringsSep ", " (p: ''"${p}"'') packagesNotFound + }"; + }]; + + warnings = let stringPlugins = filter isString cfg.plugins; + in optional (stringPlugins != [ ]) '' + Specifying VIM plugins using strings is deprecated, found ${ + concatMapStringsSep ", " (p: ''"${p}"'') stringPlugins + } as strings. + ''; + + home.packages = [ cfg.package ]; + + programs.vim = { + package = vim; + plugins = defaultPlugins; + }; + }); +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/vscode.nix b/infra/libkookie/home-manager-stable/modules/programs/vscode.nix new file mode 100644 index 00000000000..df1dd237896 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/vscode.nix @@ -0,0 +1,202 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.vscode; + + vscodePname = cfg.package.pname; + + jsonFormat = pkgs.formats.json { }; + + configDir = { + "vscode" = "Code"; + "vscode-insiders" = "Code - Insiders"; + "vscodium" = "VSCodium"; + }.${vscodePname}; + + extensionDir = { + "vscode" = "vscode"; + "vscode-insiders" = "vscode-insiders"; + "vscodium" = "vscode-oss"; + }.${vscodePname}; + + userDir = if pkgs.stdenv.hostPlatform.isDarwin then + "Library/Application Support/${configDir}/User" + else + "${config.xdg.configHome}/${configDir}/User"; + + configFilePath = "${userDir}/settings.json"; + tasksFilePath = "${userDir}/tasks.json"; + keybindingsFilePath = "${userDir}/keybindings.json"; + + # TODO: On Darwin where are the extensions? + extensionPath = ".${extensionDir}/extensions"; + +in { + imports = [ + (mkChangedOptionModule [ "programs" "vscode" "immutableExtensionsDir" ] [ + "programs" + "vscode" + "mutableExtensionsDir" + ] (config: !config.programs.vscode.immutableExtensionsDir)) + ]; + + options = { + programs.vscode = { + enable = mkEnableOption "Visual Studio Code"; + + package = mkOption { + type = types.package; + default = pkgs.vscode; + example = literalExpression "pkgs.vscodium"; + description = '' + Version of Visual Studio Code to install. + ''; + }; + + userSettings = mkOption { + type = jsonFormat.type; + default = { }; + example = literalExpression '' + { + "update.channel" = "none"; + "[nix]"."editor.tabSize" = 2; + } + ''; + description = '' + Configuration written to Visual Studio Code's + settings.json. + ''; + }; + + userTasks = mkOption { + type = jsonFormat.type; + default = { }; + example = literalExpression '' + { + "version": "2.0.0", + "tasks": [ + { + "type": "shell", + "label": "Hello task", + "command": "hello", + } + ] + } + ''; + description = '' + Configuration written to Visual Studio Code's + tasks.json. + ''; + }; + + keybindings = mkOption { + type = types.listOf (types.submodule { + options = { + key = mkOption { + type = types.str; + example = "ctrl+c"; + description = "The key or key-combination to bind."; + }; + + command = mkOption { + type = types.str; + example = "editor.action.clipboardCopyAction"; + description = "The VS Code command to execute."; + }; + + when = mkOption { + type = types.nullOr (types.str); + default = null; + example = "textInputFocus"; + description = "Optional context filter."; + }; + + # https://code.visualstudio.com/docs/getstarted/keybindings#_command-arguments + args = mkOption { + type = types.nullOr (jsonFormat.type); + default = null; + example = { direction = "up"; }; + description = "Optional arguments for a command."; + }; + }; + }); + default = [ ]; + example = literalExpression '' + [ + { + key = "ctrl+c"; + command = "editor.action.clipboardCopyAction"; + when = "textInputFocus"; + } + ] + ''; + description = '' + Keybindings written to Visual Studio Code's + keybindings.json. + ''; + }; + + extensions = mkOption { + type = types.listOf types.package; + default = [ ]; + example = literalExpression "[ pkgs.vscode-extensions.bbenoist.nix ]"; + description = '' + The extensions Visual Studio Code should be started with. + ''; + }; + + mutableExtensionsDir = mkOption { + type = types.bool; + default = true; + example = false; + description = '' + Whether extensions can be installed or updated manually + or by Visual Studio Code. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + + home.file = mkMerge [ + (mkIf (cfg.userSettings != { }) { + "${configFilePath}".source = + jsonFormat.generate "vscode-user-settings" cfg.userSettings; + }) + (mkIf (cfg.userTasks != { }) { + "${tasksFilePath}".source = + jsonFormat.generate "vscode-user-tasks" cfg.userTasks; + }) + (mkIf (cfg.keybindings != [ ]) + (let dropNullFields = filterAttrs (_: v: v != null); + in { + "${keybindingsFilePath}".source = + jsonFormat.generate "vscode-keybindings" + (map dropNullFields cfg.keybindings); + })) + (mkIf (cfg.extensions != [ ]) (let + combinedExtensionsDrv = pkgs.buildEnv { + name = "vscode-extensions"; + paths = cfg.extensions; + }; + + extensionsFolder = "${combinedExtensionsDrv}/share/vscode/extensions"; + + # Adapted from https://discourse.nixos.org/t/vscode-extensions-setup/1801/2 + addSymlinkToExtension = k: { + "${extensionPath}/${k}".source = "${extensionsFolder}/${k}"; + }; + extensions = builtins.attrNames (builtins.readDir extensionsFolder); + in if cfg.mutableExtensionsDir then + mkMerge (map addSymlinkToExtension extensions) + else { + "${extensionPath}".source = extensionsFolder; + })) + ]; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/vscode/haskell.nix b/infra/libkookie/home-manager-stable/modules/programs/vscode/haskell.nix new file mode 100644 index 00000000000..7fe3235d820 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/vscode/haskell.nix @@ -0,0 +1,62 @@ +{ pkgs, config, lib, ... }: + +with lib; + +let + + cfg = config.programs.vscode.haskell; + + defaultHieNixExe = hie-nix.hies + "/bin/hie-wrapper"; + defaultHieNixExeText = + literalExpression ''"''${pkgs.hie-nix.hies}/bin/hie-wrapper"''; + + hie-nix = pkgs.hie-nix or (abort '' + vscode.haskell: pkgs.hie-nix missing. Please add an overlay such as: + ${exampleOverlay} + ''); + + exampleOverlay = '' + nixpkgs.overlays = [ + (self: super: { hie-nix = import ~/src/hie-nix {}; }) + ] + ''; + +in { + options.programs.vscode.haskell = { + enable = mkEnableOption "Haskell integration for Visual Studio Code"; + + hie.enable = mkOption { + type = types.bool; + default = true; + description = "Whether to enable Haskell IDE engine integration."; + }; + + hie.executablePath = mkOption { + type = types.path; + default = defaultHieNixExe; + defaultText = defaultHieNixExeText; + description = '' + The path to the Haskell IDE Engine executable. + + Because hie-nix is not packaged in Nixpkgs, you need to add it as an + overlay or set this option. Example overlay configuration: + ${exampleOverlay} + ''; + example = literalExpression '' + (import ~/src/haskell-ide-engine {}).hies + "/bin/hie-wrapper"; + ''; + }; + }; + + config = mkIf cfg.enable { + programs.vscode.userSettings = mkIf cfg.hie.enable { + "languageServerHaskell.enableHIE" = true; + "languageServerHaskell.hieExecutablePath" = cfg.hie.executablePath; + }; + + programs.vscode.extensions = + [ pkgs.vscode-extensions.justusadam.language-haskell ] + ++ lib.optional cfg.hie.enable + pkgs.vscode-extensions.alanz.vscode-hie-server; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/watson.nix b/infra/libkookie/home-manager-stable/modules/programs/watson.nix new file mode 100644 index 00000000000..54cfbc135f2 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/watson.nix @@ -0,0 +1,94 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.watson; + + iniFormat = pkgs.formats.ini { }; + + configDir = if pkgs.stdenv.hostPlatform.isDarwin then + "Library/Application Support" + else + config.xdg.configHome; + +in { + meta.maintainers = [ maintainers.polykernel ]; + + options.programs.watson = { + enable = mkEnableOption "watson, a wonderful CLI to track your time"; + + package = mkOption { + type = types.package; + default = pkgs.watson; + defaultText = literalExpression "pkgs.watson"; + description = "Package providing the watson."; + }; + + enableBashIntegration = mkEnableOption "watson's bash integration" // { + default = true; + }; + + enableZshIntegration = mkEnableOption "watson's zsh integration" // { + default = true; + }; + + enableFishIntegration = mkEnableOption "watson's fish integration" // { + default = true; + }; + + settings = mkOption { + type = iniFormat.type; + default = { }; + description = '' + Configuration written to + $XDG_CONFIG_HOME/watson/config on Linux or + $HOME/Library/Application Support/watson/config on Darwin. + + See + for an example configuration. + ''; + example = literalExpression '' + { + backend = { + url = "https://api.crick.fr"; + token = "yourapitoken"; + }; + + options = { + stop_on_start = true; + stop_on_restart = false; + date_format = "%Y.%m.%d"; + time_format = "%H:%M:%S%z"; + week_start = "monday"; + log_current = false; + pager = true; + report_current = false; + reverse_log = true; + }; + } + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + + home.file."${configDir}/watson/config" = mkIf (cfg.settings != { }) { + source = iniFormat.generate "watson-config" cfg.settings; + }; + + programs.bash.initExtra = mkIf cfg.enableBashIntegration '' + source ${cfg.package}/share/bash-completion/completions/watson + ''; + + programs.zsh.initExtra = mkIf cfg.enableZshIntegration '' + source ${cfg.package}/share/zsh/site-functions/_watson + ''; + + programs.fish.shellInit = mkIf cfg.enableFishIntegration '' + source ${cfg.package}/share/fish/vendor_completions.d/watson.fish + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/waybar.nix b/infra/libkookie/home-manager-stable/modules/programs/waybar.nix new file mode 100644 index 00000000000..12002d546d7 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/waybar.nix @@ -0,0 +1,330 @@ +{ config, lib, pkgs, ... }: + +let + inherit (lib) + all filterAttrs hasAttr isStorePath literalExpression optionalAttrs types; + inherit (lib.options) mkEnableOption mkOption; + inherit (lib.modules) mkIf mkMerge; + + cfg = config.programs.waybar; + + jsonFormat = pkgs.formats.json { }; + + mkMargin = name: + mkOption { + type = types.nullOr types.int; + default = null; + example = 10; + description = "Margin value without unit."; + }; + + waybarBarConfig = with types; + submodule { + freeformType = jsonFormat.type; + + options = { + layer = mkOption { + type = nullOr (enum [ "top" "bottom" ]); + default = null; + description = '' + Decide if the bar is displayed in front ("top") + of the windows or behind ("bottom"). + ''; + example = "top"; + }; + + output = mkOption { + type = nullOr (either str (listOf str)); + default = null; + example = literalExpression '' + [ "DP-1" "!DP-2" "!DP-3" ] + ''; + description = '' + Specifies on which screen this bar will be displayed. + Exclamation mark(!) can be used to exclude specific output. + ''; + }; + + position = mkOption { + type = nullOr (enum [ "top" "bottom" "left" "right" ]); + default = null; + example = "right"; + description = "Bar position relative to the output."; + }; + + height = mkOption { + type = nullOr ints.unsigned; + default = null; + example = 5; + description = + "Height to be used by the bar if possible. Leave blank for a dynamic value."; + }; + + width = mkOption { + type = nullOr ints.unsigned; + default = null; + example = 5; + description = + "Width to be used by the bar if possible. Leave blank for a dynamic value."; + }; + + modules-left = mkOption { + type = listOf str; + default = [ ]; + description = "Modules that will be displayed on the left."; + example = literalExpression '' + [ "sway/workspaces" "sway/mode" "wlr/taskbar" ] + ''; + }; + + modules-center = mkOption { + type = listOf str; + default = [ ]; + description = "Modules that will be displayed in the center."; + example = literalExpression '' + [ "sway/window" ] + ''; + }; + + modules-right = mkOption { + type = listOf str; + default = [ ]; + description = "Modules that will be displayed on the right."; + example = literalExpression '' + [ "mpd" "custom/mymodule#with-css-id" "temperature" ] + ''; + }; + + modules = mkOption { + type = jsonFormat.type; + visible = false; + default = null; + description = "Modules configuration."; + example = literalExpression '' + { + "sway/window" = { + max-length = 50; + }; + "clock" = { + format-alt = "{:%a, %d. %b %H:%M}"; + }; + } + ''; + }; + + margin = mkOption { + type = nullOr str; + default = null; + description = "Margins value using the CSS format without units."; + example = "20 5"; + }; + + margin-left = mkMargin "left"; + margin-right = mkMargin "right"; + margin-bottom = mkMargin "bottom"; + margin-top = mkMargin "top"; + + name = mkOption { + type = nullOr str; + default = null; + description = + "Optional name added as a CSS class, for styling multiple waybars."; + example = "waybar-1"; + }; + + gtk-layer-shell = mkOption { + type = nullOr bool; + default = null; + example = false; + description = + "Option to disable the use of gtk-layer-shell for popups."; + }; + }; + }; +in { + meta.maintainers = with lib.maintainers; [ berbiche ]; + + options.programs.waybar = with lib.types; { + enable = mkEnableOption "Waybar"; + + package = mkOption { + type = package; + default = pkgs.waybar; + defaultText = literalExpression "pkgs.waybar"; + description = '' + Waybar package to use. Set to null to use the default package. + ''; + }; + + settings = mkOption { + type = either (listOf waybarBarConfig) (attrsOf waybarBarConfig); + default = [ ]; + description = '' + Configuration for Waybar, see + for supported values. + ''; + example = literalExpression '' + { + mainBar = { + layer = "top"; + position = "top"; + height = 30; + output = [ + "eDP-1" + "HDMI-A-1" + ]; + modules-left = [ "sway/workspaces" "sway/mode" "wlr/taskbar" ]; + modules-center = [ "sway/window" "custom/hello-from-waybar" ]; + modules-right = [ "mpd" "custom/mymodule#with-css-id" "temperature" ]; + + "sway/workspaces" = { + disable-scroll = true; + all-outputs = true; + }; + "custom/hello-from-waybar" = { + format = "hello {}"; + max-length = 40; + interval = "once"; + exec = pkgs.writeShellScript "hello-from-waybar" ''' + echo "from within waybar" + '''; + }; + }; + } + ''; + }; + + systemd.enable = mkEnableOption "Waybar systemd integration"; + + systemd.target = mkOption { + type = str; + default = "graphical-session.target"; + example = "sway-session.target"; + description = '' + The systemd target that will automatically start the Waybar service. + + + When setting this value to "sway-session.target", + make sure to also enable , + otherwise the service may never be started. + ''; + }; + + style = mkOption { + type = nullOr (either path str); + default = null; + description = '' + CSS style of the bar. + + + See + for the documentation. + + + If the value is set to a path literal, then the path will be used as the css file. + ''; + example = '' + * { + border: none; + border-radius: 0; + font-family: Source Code Pro; + } + window#waybar { + background: #16191C; + color: #AAB2BF; + } + #workspaces button { + padding: 0 5px; + } + ''; + }; + }; + + config = let + # Removes nulls because Waybar ignores them. + # This is not recursive. + removeTopLevelNulls = filterAttrs (_: v: v != null); + + # Makes the actual valid configuration Waybar accepts + # (strips our custom settings before converting to JSON) + makeConfiguration = configuration: + let + # The "modules" option is not valid in the JSON + # as its descendants have to live at the top-level + settingsWithoutModules = removeAttrs configuration [ "modules" ]; + settingsModules = + optionalAttrs (configuration.modules != null) configuration.modules; + in removeTopLevelNulls (settingsWithoutModules // settingsModules); + + # Allow using attrs for settings instead of a list in order to more easily override + settings = if builtins.isAttrs cfg.settings then + lib.attrValues cfg.settings + else + cfg.settings; + + # The clean list of configurations + finalConfiguration = map makeConfiguration settings; + + configSource = jsonFormat.generate "waybar-config.json" finalConfiguration; + + in mkIf cfg.enable (mkMerge [ + { + assertions = [ + (lib.hm.assertions.assertPlatform "programs.waybar" pkgs + lib.platforms.linux) + ({ + assertion = + if lib.versionAtLeast config.home.stateVersion "22.05" then + all (x: !hasAttr "modules" x || x.modules == null) settings + else + true; + message = '' + The `programs.waybar.settings.[].modules` option has been removed. + It is now possible to declare modules in the configuration without nesting them under the `modules` option. + ''; + }) + ]; + + home.packages = [ cfg.package ]; + + xdg.configFile."waybar/config" = mkIf (settings != [ ]) { + source = configSource; + onChange = '' + ${pkgs.procps}/bin/pkill -u $USER -USR2 waybar || true + ''; + }; + + xdg.configFile."waybar/style.css" = mkIf (cfg.style != null) { + source = if builtins.isPath cfg.style || isStorePath cfg.style then + cfg.style + else + pkgs.writeText "waybar/style.css" cfg.style; + onChange = '' + ${pkgs.procps}/bin/pkill -u $USER -USR2 waybar || true + ''; + }; + } + + (mkIf cfg.systemd.enable { + systemd.user.services.waybar = { + Unit = { + Description = + "Highly customizable Wayland bar for Sway and Wlroots based compositors."; + Documentation = "https://github.com/Alexays/Waybar/wiki"; + PartOf = [ "graphical-session.target" ]; + After = [ "graphical-session.target" ]; + }; + + Service = { + ExecStart = "${cfg.package}/bin/waybar"; + ExecReload = "${pkgs.coreutils}/bin/kill -SIGUSR2 $MAINPID"; + Restart = "on-failure"; + KillMode = "mixed"; + }; + + Install = { WantedBy = [ cfg.systemd.target ]; }; + }; + }) + ]); +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/xmobar.nix b/infra/libkookie/home-manager-stable/modules/programs/xmobar.nix new file mode 100644 index 00000000000..a29bea846a4 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/xmobar.nix @@ -0,0 +1,59 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let cfg = config.programs.xmobar; +in { + options.programs.xmobar = { + enable = mkEnableOption "Xmobar, a minimalistic status bar"; + + package = mkOption { + default = pkgs.haskellPackages.xmobar; + defaultText = literalExpression "pkgs.haskellPackages.xmobar"; + type = types.package; + description = '' + Package providing the xmobar binary. + ''; + }; + + extraConfig = mkOption { + default = ""; + example = literalExpression '' + Config + { font = "Fira Code" + , borderColor = "#d0d0d0" + , border = FullB + , borderWidth = 3 + , bgColor = "#222" + , fgColor = "grey" + , position = TopSize C 99 30 + , commands = + [ Run Cpu ["-t", "cpu: %"] 10 + , Run Network "enp3s0" ["-S", "True", "-t", "eth: /"] 10 + , Run Memory ["-t","mem: %"] 10 + , Run Date "date: %a %d %b %Y %H:%M:%S " "date" 10 + , Run StdinReader + ] + , sepChar = "%" + , alignSep = "}{" + , template = " %StdinReader% | %cpu% | %memory% | %enp3s0% }{%date% " + } + ''; + type = types.lines; + description = '' + Extra configuration lines to add to + $XDG_CONFIG_HOME/xmobar/.xmobarrc. + See + + for options. + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + xdg.configFile."xmobar/.xmobarrc".text = cfg.extraConfig; + }; + + meta.maintainers = [ hm.maintainers.t4ccer ]; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/z-lua.nix b/infra/libkookie/home-manager-stable/modules/programs/z-lua.nix new file mode 100644 index 00000000000..f8ff3b014d1 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/z-lua.nix @@ -0,0 +1,92 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.z-lua; + + aliases = { + zz = "z -c"; # restrict matches to subdirs of $PWD + zi = "z -i"; # cd with interactive selection + zf = "z -I"; # use fzf to select in multiple matches + zb = "z -b"; # quickly cd to the parent directory + zh = "z -I -t ."; # fzf + }; + +in { + meta.maintainers = [ maintainers.marsam ]; + + options.programs.z-lua = { + enable = mkEnableOption "z.lua"; + + options = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "enhanced" "once" "fzf" ]; + description = '' + List of options to pass to z.lua. + ''; + }; + + enableBashIntegration = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable Bash integration. + ''; + }; + + enableZshIntegration = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable Zsh integration. + ''; + }; + + enableFishIntegration = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable Fish integration. + ''; + }; + + enableAliases = mkOption { + default = false; + type = types.bool; + description = '' + Whether to enable recommended z.lua aliases. + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ pkgs.z-lua ]; + + programs.bash.initExtra = mkIf cfg.enableBashIntegration '' + eval "$(${pkgs.z-lua}/bin/z --init bash ${ + concatStringsSep " " cfg.options + })" + ''; + + programs.zsh.initExtra = mkIf cfg.enableZshIntegration '' + eval "$(${pkgs.z-lua}/bin/z --init zsh ${ + concatStringsSep " " cfg.options + })" + ''; + + programs.fish.shellInit = mkIf cfg.enableFishIntegration '' + source (${pkgs.z-lua}/bin/z --init fish ${ + concatStringsSep " " cfg.options + } | psub) + ''; + + programs.bash.shellAliases = mkIf cfg.enableAliases aliases; + + programs.zsh.shellAliases = mkIf cfg.enableAliases aliases; + + programs.fish.shellAliases = mkIf cfg.enableAliases aliases; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/zathura.nix b/infra/libkookie/home-manager-stable/modules/programs/zathura.nix new file mode 100644 index 00000000000..64a77cb3bee --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/zathura.nix @@ -0,0 +1,65 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.zathura; + + formatLine = n: v: + let + formatValue = v: + if isBool v then (if v then "true" else "false") else toString v; + in ''set ${n} "${formatValue v}"''; + +in { + meta.maintainers = [ maintainers.rprospero ]; + + options.programs.zathura = { + enable = mkEnableOption '' + Zathura, a highly customizable and functional document viewer + focused on keyboard interaction''; + + package = mkOption { + type = types.package; + default = pkgs.zathura; + defaultText = "pkgs.zathura"; + description = "The Zathura package to use"; + }; + + options = mkOption { + default = { }; + type = with types; attrsOf (either str (either bool int)); + description = '' + Add command options to zathura and make + them permanent. See + + zathurarc + 5 + + for the full list of options. + ''; + example = { + default-bg = "#000000"; + default-fg = "#FFFFFF"; + }; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Additional commands for zathura that will be added to the + zathurarc file. + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + + xdg.configFile."zathura/zathurarc".text = concatStringsSep "\n" ([ ] + ++ optional (cfg.extraConfig != "") cfg.extraConfig + ++ mapAttrsToList formatLine cfg.options) + "\n"; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/zellij.nix b/infra/libkookie/home-manager-stable/modules/programs/zellij.nix new file mode 100644 index 00000000000..2cfa625daab --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/zellij.nix @@ -0,0 +1,56 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.zellij; + yamlFormat = pkgs.formats.yaml { }; + + configDir = if pkgs.stdenv.isDarwin then + "Library/Application Support/org.Zellij-Contributors.Zellij" + else + "${config.xdg.configHome}/zellij"; + +in { + meta.maintainers = [ hm.maintainers.mainrs ]; + + options.programs.zellij = { + enable = mkEnableOption "zellij"; + + package = mkOption { + type = types.package; + default = pkgs.zellij; + defaultText = literalExpression "pkgs.zellij"; + description = '' + The zellij package to install. + ''; + }; + + settings = mkOption { + type = yamlFormat.type; + default = { }; + example = literalExpression '' + { + theme = "custom"; + themes.custom.fg = 5; + } + ''; + description = '' + Configuration written to + $XDG_CONFIG_HOME/zellij/config.yaml. + + See for the full + list of options. + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + + home.file."${configDir}/config.yaml" = mkIf (cfg.settings != { }) { + source = yamlFormat.generate "zellij.yaml" cfg.settings; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/zoxide.nix b/infra/libkookie/home-manager-stable/modules/programs/zoxide.nix new file mode 100644 index 00000000000..21bc9632ecd --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/zoxide.nix @@ -0,0 +1,79 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.zoxide; + +in { + meta.maintainers = [ maintainers.marsam ]; + + options.programs.zoxide = { + enable = mkEnableOption "zoxide"; + + package = mkOption { + type = types.package; + default = pkgs.zoxide; + defaultText = literalExpression "pkgs.zoxide"; + description = '' + Zoxide package to install. + ''; + }; + + options = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "--no-aliases" ]; + description = '' + List of options to pass to zoxide. + ''; + }; + + enableBashIntegration = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable Bash integration. + ''; + }; + + enableZshIntegration = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable Zsh integration. + ''; + }; + + enableFishIntegration = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable Fish integration. + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + + programs.bash.initExtra = mkIf cfg.enableBashIntegration '' + eval "$(${cfg.package}/bin/zoxide init bash ${ + concatStringsSep " " cfg.options + })" + ''; + + programs.zsh.initExtra = mkIf cfg.enableZshIntegration '' + eval "$(${cfg.package}/bin/zoxide init zsh ${ + concatStringsSep " " cfg.options + })" + ''; + + programs.fish.shellInit = mkIf cfg.enableFishIntegration '' + ${cfg.package}/bin/zoxide init fish ${ + concatStringsSep " " cfg.options + } | source + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/zplug.nix b/infra/libkookie/home-manager-stable/modules/programs/zplug.nix new file mode 100644 index 00000000000..5f2b44311f7 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/zplug.nix @@ -0,0 +1,70 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.zsh.zplug; + + pluginModule = types.submodule ({ config, ... }: { + options = { + name = mkOption { + type = types.str; + description = "The name of the plugin."; + }; + + tags = mkOption { + type = types.listOf types.str; + default = [ ]; + description = "The plugin tags."; + }; + }; + + }); + +in { + options.programs.zsh.zplug = { + enable = mkEnableOption "zplug - a zsh plugin manager"; + + plugins = mkOption { + default = [ ]; + type = types.listOf pluginModule; + description = "List of zplug plugins."; + }; + + zplugHome = mkOption { + type = types.path; + default = "${config.home.homeDirectory}/.zplug"; + defaultText = "~/.zplug"; + apply = toString; + description = "Path to zplug home directory."; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ pkgs.zplug ]; + + programs.zsh.initExtraBeforeCompInit = '' + source ${pkgs.zplug}/init.zsh + + export ZPLUG_HOME=${cfg.zplugHome} + + ${optionalString (cfg.plugins != [ ]) '' + ${concatStrings (map (plugin: '' + zplug "${plugin.name}"${ + optionalString (plugin.tags != [ ]) '' + ${concatStrings (map (tag: ", ${tag}") plugin.tags)} + '' + } + '') cfg.plugins)} + ''} + + if ! zplug check; then + zplug install + fi + + zplug load + ''; + + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/zsh.nix b/infra/libkookie/home-manager-stable/modules/programs/zsh.nix new file mode 100644 index 00000000000..2d81698b6fe --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/zsh.nix @@ -0,0 +1,580 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.zsh; + + relToDotDir = file: (optionalString (cfg.dotDir != null) (cfg.dotDir + "/")) + file; + + pluginsDir = if cfg.dotDir != null then + relToDotDir "plugins" else ".zsh/plugins"; + + envVarsStr = config.lib.zsh.exportAll cfg.sessionVariables; + localVarsStr = config.lib.zsh.defineAll cfg.localVariables; + + aliasesStr = concatStringsSep "\n" ( + mapAttrsToList (k: v: "alias ${k}=${lib.escapeShellArg v}") cfg.shellAliases + ); + + globalAliasesStr = concatStringsSep "\n" ( + mapAttrsToList (k: v: "alias -g ${k}=${lib.escapeShellArg v}") cfg.shellGlobalAliases + ); + + dirHashesStr = concatStringsSep "\n" ( + mapAttrsToList (k: v: ''hash -d ${k}="${v}"'') cfg.dirHashes + ); + + zdotdir = "$HOME/" + cfg.dotDir; + + bindkeyCommands = { + emacs = "bindkey -e"; + viins = "bindkey -v"; + vicmd = "bindkey -a"; + }; + + stateVersion = config.home.stateVersion; + + historyModule = types.submodule ({ config, ... }: { + options = { + size = mkOption { + type = types.int; + default = 10000; + description = "Number of history lines to keep."; + }; + + save = mkOption { + type = types.int; + defaultText = 10000; + default = config.size; + description = "Number of history lines to save."; + }; + + path = mkOption { + type = types.str; + default = if versionAtLeast stateVersion "20.03" + then "$HOME/.zsh_history" + else relToDotDir ".zsh_history"; + defaultText = literalExpression '' + "$HOME/.zsh_history" if state version ≥ 20.03, + "$ZDOTDIR/.zsh_history" otherwise + ''; + example = literalExpression ''"''${config.xdg.dataHome}/zsh/zsh_history"''; + description = "History file location"; + }; + + ignorePatterns = mkOption { + type = types.listOf types.str; + default = []; + example = literalExpression ''[ "rm *" "pkill *" ]''; + description = '' + Do not enter command lines into the history list + if they match any one of the given shell patterns. + ''; + }; + + ignoreDups = mkOption { + type = types.bool; + default = true; + description = '' + Do not enter command lines into the history list + if they are duplicates of the previous event. + ''; + }; + + ignoreSpace = mkOption { + type = types.bool; + default = true; + description = '' + Do not enter command lines into the history list + if the first character is a space. + ''; + }; + + expireDuplicatesFirst = mkOption { + type = types.bool; + default = false; + description = "Expire duplicates first."; + }; + + extended = mkOption { + type = types.bool; + default = false; + description = "Save timestamp into the history file."; + }; + + share = mkOption { + type = types.bool; + default = true; + description = "Share command history between zsh sessions."; + }; + }; + }); + + pluginModule = types.submodule ({ config, ... }: { + options = { + src = mkOption { + type = types.path; + description = '' + Path to the plugin folder. + + Will be added to fpath and PATH. + ''; + }; + + name = mkOption { + type = types.str; + description = '' + The name of the plugin. + + Don't forget to add + if the script name does not follow convention. + ''; + }; + + file = mkOption { + type = types.str; + description = "The plugin script to source."; + }; + }; + + config.file = mkDefault "${config.name}.plugin.zsh"; + }); + + ohMyZshModule = types.submodule { + options = { + enable = mkEnableOption "oh-my-zsh"; + + plugins = mkOption { + default = []; + example = [ "git" "sudo" ]; + type = types.listOf types.str; + description = '' + List of oh-my-zsh plugins + ''; + }; + + custom = mkOption { + default = ""; + type = types.str; + example = "$HOME/my_customizations"; + description = '' + Path to a custom oh-my-zsh package to override config of + oh-my-zsh. See + for more information. + ''; + }; + + theme = mkOption { + default = ""; + example = "robbyrussell"; + type = types.str; + description = '' + Name of the theme to be used by oh-my-zsh. + ''; + }; + + extraConfig = mkOption { + default = ""; + example = '' + zstyle :omz:plugins:ssh-agent identities id_rsa id_rsa2 id_github + ''; + type = types.lines; + description = '' + Extra settings for plugins. + ''; + }; + }; + }; + +in + +{ + options = { + programs.zsh = { + enable = mkEnableOption "Z shell (Zsh)"; + + autocd = mkOption { + default = null; + description = '' + Automatically enter into a directory if typed directly into shell. + ''; + type = types.nullOr types.bool; + }; + + cdpath = mkOption { + default = []; + description = '' + List of paths to autocomplete calls to `cd`. + ''; + type = types.listOf types.str; + }; + + dotDir = mkOption { + default = null; + example = ".config/zsh"; + description = '' + Directory where the zsh configuration and more should be located, + relative to the users home directory. The default is the home + directory. + ''; + type = types.nullOr types.str; + }; + + shellAliases = mkOption { + default = {}; + example = literalExpression '' + { + ll = "ls -l"; + ".." = "cd .."; + } + ''; + description = '' + An attribute set that maps aliases (the top level attribute names in + this option) to command strings or directly to build outputs. + ''; + type = types.attrsOf types.str; + }; + + shellGlobalAliases = mkOption { + default = {}; + example = literalExpression '' + { + UUID = "$(uuidgen | tr -d \\n)"; + G = "| grep"; + } + ''; + description = '' + Similar to opt-programs.zsh.shellAliases, + but are substituted anywhere on a line. + ''; + type = types.attrsOf types.str; + }; + + dirHashes = mkOption { + default = {}; + example = literalExpression '' + { + docs = "$HOME/Documents"; + vids = "$HOME/Videos"; + dl = "$HOME/Downloads"; + } + ''; + description = '' + An attribute set that adds to named directory hash table. + ''; + type = types.attrsOf types.str; + }; + + enableCompletion = mkOption { + default = true; + description = '' + Enable zsh completion. Don't forget to add + + environment.pathsToLink = [ "/share/zsh" ]; + + to your system configuration to get completion for system packages (e.g. systemd). + ''; + type = types.bool; + }; + + completionInit = mkOption { + default = "autoload -U compinit && compinit"; + description = "Initialization commands to run when completion is enabled."; + type = types.lines; + }; + + enableAutosuggestions = mkOption { + default = false; + description = "Enable zsh autosuggestions"; + }; + + enableSyntaxHighlighting = mkOption { + default = false; + description = "Enable zsh syntax highlighting"; + }; + + history = mkOption { + type = historyModule; + default = {}; + description = "Options related to commands history configuration."; + }; + + defaultKeymap = mkOption { + type = types.nullOr (types.enum (attrNames bindkeyCommands)); + default = null; + example = "emacs"; + description = "The default base keymap to use."; + }; + + sessionVariables = mkOption { + default = {}; + type = types.attrs; + example = { MAILCHECK = 30; }; + description = "Environment variables that will be set for zsh session."; + }; + + initExtraBeforeCompInit = mkOption { + default = ""; + type = types.lines; + description = "Extra commands that should be added to .zshrc before compinit."; + }; + + initExtra = mkOption { + default = ""; + type = types.lines; + description = "Extra commands that should be added to .zshrc."; + }; + + initExtraFirst = mkOption { + default = ""; + type = types.lines; + description = "Commands that should be added to top of .zshrc."; + }; + + envExtra = mkOption { + default = ""; + type = types.lines; + description = "Extra commands that should be added to .zshenv."; + }; + + profileExtra = mkOption { + default = ""; + type = types.lines; + description = "Extra commands that should be added to .zprofile."; + }; + + loginExtra = mkOption { + default = ""; + type = types.lines; + description = "Extra commands that should be added to .zlogin."; + }; + + logoutExtra = mkOption { + default = ""; + type = types.lines; + description = "Extra commands that should be added to .zlogout."; + }; + + plugins = mkOption { + type = types.listOf pluginModule; + default = []; + example = literalExpression '' + [ + { + # will source zsh-autosuggestions.plugin.zsh + name = "zsh-autosuggestions"; + src = pkgs.fetchFromGitHub { + owner = "zsh-users"; + repo = "zsh-autosuggestions"; + rev = "v0.4.0"; + sha256 = "0z6i9wjjklb4lvr7zjhbphibsyx51psv50gm07mbb0kj9058j6kc"; + }; + } + { + name = "enhancd"; + file = "init.sh"; + src = pkgs.fetchFromGitHub { + owner = "b4b4r07"; + repo = "enhancd"; + rev = "v2.2.1"; + sha256 = "0iqa9j09fwm6nj5rpip87x3hnvbbz9w9ajgm6wkrd5fls8fn8i5g"; + }; + } + ] + ''; + description = "Plugins to source in .zshrc."; + }; + + oh-my-zsh = mkOption { + type = ohMyZshModule; + default = {}; + description = "Options to configure oh-my-zsh."; + }; + + localVariables = mkOption { + type = types.attrs; + default = {}; + example = { POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=["dir" "vcs"]; }; + description = '' + Extra local variables defined at the top of .zshrc. + ''; + }; + }; + }; + + config = mkIf cfg.enable (mkMerge [ + (mkIf (cfg.envExtra != "") { + home.file."${relToDotDir ".zshenv"}".text = cfg.envExtra; + }) + + (mkIf (cfg.profileExtra != "") { + home.file."${relToDotDir ".zprofile"}".text = cfg.profileExtra; + }) + + (mkIf (cfg.loginExtra != "") { + home.file."${relToDotDir ".zlogin"}".text = cfg.loginExtra; + }) + + (mkIf (cfg.logoutExtra != "") { + home.file."${relToDotDir ".zlogout"}".text = cfg.logoutExtra; + }) + + (mkIf cfg.oh-my-zsh.enable { + home.file."${relToDotDir ".zshenv"}".text = '' + ZSH="${pkgs.oh-my-zsh}/share/oh-my-zsh"; + ZSH_CACHE_DIR="${config.xdg.cacheHome}/oh-my-zsh"; + ''; + }) + + (mkIf (cfg.dotDir != null) { + home.file."${relToDotDir ".zshenv"}".text = '' + ZDOTDIR=${zdotdir} + ''; + + # When dotDir is set, only use ~/.zshenv to source ZDOTDIR/.zshenv, + # This is so that if ZDOTDIR happens to be + # already set correctly (by e.g. spawning a zsh inside a zsh), all env + # vars still get exported + home.file.".zshenv".text = '' + source ${zdotdir}/.zshenv + ''; + }) + + { + home.file."${relToDotDir ".zshenv"}".text = '' + # Environment variables + . "${config.home.profileDirectory}/etc/profile.d/hm-session-vars.sh" + + # Only source this once + if [[ -z "$__HM_ZSH_SESS_VARS_SOURCED" ]]; then + export __HM_ZSH_SESS_VARS_SOURCED=1 + ${envVarsStr} + fi + ''; + } + + { + home.packages = with pkgs; [ zsh ] + ++ optional cfg.enableCompletion nix-zsh-completions + ++ optional cfg.oh-my-zsh.enable oh-my-zsh; + + home.file."${relToDotDir ".zshrc"}".text = '' + ${cfg.initExtraFirst} + + typeset -U path cdpath fpath manpath + + ${optionalString (cfg.cdpath != []) '' + cdpath+=(${concatStringsSep " " cfg.cdpath}) + ''} + + for profile in ''${(z)NIX_PROFILES}; do + fpath+=($profile/share/zsh/site-functions $profile/share/zsh/$ZSH_VERSION/functions $profile/share/zsh/vendor-completions) + done + + HELPDIR="${pkgs.zsh}/share/zsh/$ZSH_VERSION/help" + + ${optionalString (cfg.defaultKeymap != null) '' + # Use ${cfg.defaultKeymap} keymap as the default. + ${getAttr cfg.defaultKeymap bindkeyCommands} + ''} + + ${localVarsStr} + + ${cfg.initExtraBeforeCompInit} + + ${concatStrings (map (plugin: '' + path+="$HOME/${pluginsDir}/${plugin.name}" + fpath+="$HOME/${pluginsDir}/${plugin.name}" + '') cfg.plugins)} + + # Oh-My-Zsh/Prezto calls compinit during initialization, + # calling it twice causes slight start up slowdown + # as all $fpath entries will be traversed again. + ${optionalString (cfg.enableCompletion && !cfg.oh-my-zsh.enable && !cfg.prezto.enable) + cfg.completionInit + } + + ${optionalString cfg.enableAutosuggestions + "source ${pkgs.zsh-autosuggestions}/share/zsh-autosuggestions/zsh-autosuggestions.zsh" + } + + ${optionalString cfg.enableSyntaxHighlighting + "source ${pkgs.zsh-syntax-highlighting}/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh" + } + + ${optionalString cfg.oh-my-zsh.enable '' + # oh-my-zsh extra settings for plugins + ${cfg.oh-my-zsh.extraConfig} + # oh-my-zsh configuration generated by NixOS + ${optionalString (cfg.oh-my-zsh.plugins != []) + "plugins=(${concatStringsSep " " cfg.oh-my-zsh.plugins})" + } + ${optionalString (cfg.oh-my-zsh.custom != "") + "ZSH_CUSTOM=\"${cfg.oh-my-zsh.custom}\"" + } + ${optionalString (cfg.oh-my-zsh.theme != "") + "ZSH_THEME=\"${cfg.oh-my-zsh.theme}\"" + } + source $ZSH/oh-my-zsh.sh + ''} + + ${optionalString cfg.prezto.enable + (builtins.readFile "${pkgs.zsh-prezto}/share/zsh-prezto/runcoms/zshrc")} + + ${concatStrings (map (plugin: '' + if [[ -f "$HOME/${pluginsDir}/${plugin.name}/${plugin.file}" ]]; then + source "$HOME/${pluginsDir}/${plugin.name}/${plugin.file}" + fi + '') cfg.plugins)} + + # History options should be set in .zshrc and after oh-my-zsh sourcing. + # See https://github.com/nix-community/home-manager/issues/177. + HISTSIZE="${toString cfg.history.size}" + SAVEHIST="${toString cfg.history.save}" + ${optionalString (cfg.history.ignorePatterns != []) "HISTORY_IGNORE=${lib.escapeShellArg "(${lib.concatStringsSep "|" cfg.history.ignorePatterns})"}"} + ${if versionAtLeast config.home.stateVersion "20.03" + then ''HISTFILE="${cfg.history.path}"'' + else ''HISTFILE="$HOME/${cfg.history.path}"''} + mkdir -p "$(dirname "$HISTFILE")" + + setopt HIST_FCNTL_LOCK + ${if cfg.history.ignoreDups then "setopt" else "unsetopt"} HIST_IGNORE_DUPS + ${if cfg.history.ignoreSpace then "setopt" else "unsetopt"} HIST_IGNORE_SPACE + ${if cfg.history.expireDuplicatesFirst then "setopt" else "unsetopt"} HIST_EXPIRE_DUPS_FIRST + ${if cfg.history.share then "setopt" else "unsetopt"} SHARE_HISTORY + ${if cfg.history.extended then "setopt" else "unsetopt"} EXTENDED_HISTORY + ${if cfg.autocd != null then "${if cfg.autocd then "setopt" else "unsetopt"} autocd" else ""} + + ${cfg.initExtra} + + # Aliases + ${aliasesStr} + + # Global Aliases + ${globalAliasesStr} + + # Named Directory Hashes + ${dirHashesStr} + ''; + } + + (mkIf cfg.oh-my-zsh.enable { + # Make sure we create a cache directory since some plugins expect it to exist + # See: https://github.com/nix-community/home-manager/issues/761 + home.file."${config.xdg.cacheHome}/oh-my-zsh/.keep".text = ""; + }) + + (mkIf (cfg.plugins != []) { + # Many plugins require compinit to be called + # but allow the user to opt out. + programs.zsh.enableCompletion = mkDefault true; + + home.file = + foldl' (a: b: a // b) {} + (map (plugin: { "${pluginsDir}/${plugin.name}".source = plugin.src; }) + cfg.plugins); + }) + ]); +} diff --git a/infra/libkookie/home-manager-stable/modules/programs/zsh/prezto.nix b/infra/libkookie/home-manager-stable/modules/programs/zsh/prezto.nix new file mode 100644 index 00000000000..17680ff2598 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/programs/zsh/prezto.nix @@ -0,0 +1,543 @@ +{ config, pkgs, lib, ... }: + +with lib; + +let + + cfg = config.programs.zsh.prezto; + + relToDotDir = file: + (optionalString (config.programs.zsh.dotDir != null) + (config.programs.zsh.dotDir + "/")) + file; + + preztoModule = types.submodule { + options = { + enable = mkEnableOption "prezto"; + + caseSensitive = mkOption { + type = types.nullOr types.bool; + default = null; + example = true; + description = + "Set case-sensitivity for completion, history lookup, etc."; + }; + + color = mkOption { + type = types.nullOr types.bool; + default = true; + example = false; + description = "Color output (auto set to 'no' on dumb terminals)"; + }; + + pmoduleDirs = mkOption { + type = types.listOf types.path; + default = [ ]; + example = [ "$HOME/.zprezto-contrib" ]; + description = "Add additional directories to load prezto modules from"; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Additional configuration to add to .zpreztorc. + ''; + }; + + extraModules = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "attr" "stat" ]; + description = "Set the Zsh modules to load (man zshmodules)."; + }; + + extraFunctions = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "zargs" "zmv" ]; + description = "Set the Zsh functions to load (man zshcontrib)."; + }; + + pmodules = mkOption { + type = types.listOf types.str; + default = [ + "environment" + "terminal" + "editor" + "history" + "directory" + "spectrum" + "utility" + "completion" + "prompt" + ]; + description = + "Set the Prezto modules to load (browse modules). The order matters."; + }; + + autosuggestions.color = mkOption { + type = types.nullOr types.str; + default = null; + example = "fg=blue"; + description = "Set the query found color."; + }; + + completions.ignoredHosts = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "0.0.0.0" "127.0.0.1" ]; + description = + "Set the entries to ignore in static */etc/hosts* for host completion."; + }; + + editor = { + keymap = mkOption { + type = types.nullOr (types.enum [ "emacs" "vi" ]); + default = "emacs"; + example = "vi"; + description = "Set the key mapping style to 'emacs' or 'vi'."; + }; + + dotExpansion = mkOption { + type = types.nullOr types.bool; + default = null; + example = true; + description = "Auto convert .... to ../.."; + }; + + promptContext = mkOption { + type = types.nullOr types.bool; + default = null; + example = true; + description = "Allow the zsh prompt context to be shown."; + }; + }; + + git.submoduleIgnore = mkOption { + type = types.nullOr (types.enum [ "dirty" "untracked" "all" "none" ]); + default = null; + example = "all"; + description = + "Ignore submodules when they are 'dirty', 'untracked', 'all', or 'none'."; + }; + + gnuUtility.prefix = mkOption { + type = types.nullOr types.str; + default = null; + example = "g"; + description = "Set the command prefix on non-GNU systems."; + }; + + historySubstring = { + foundColor = mkOption { + type = types.nullOr types.str; + default = null; + example = "fg=blue"; + description = "Set the query found color."; + }; + + notFoundColor = mkOption { + type = types.nullOr types.str; + default = null; + example = "fg=red"; + description = "Set the query not found color."; + }; + + globbingFlags = mkOption { + type = types.nullOr types.str; + default = null; + description = "Set the search globbing flags."; + }; + }; + + macOS.dashKeyword = mkOption { + type = types.nullOr types.str; + default = null; + example = "manpages"; + description = + "Set the keyword used by `mand` to open man pages in Dash.app"; + }; + + prompt = { + theme = mkOption { + type = types.nullOr types.str; + default = "sorin"; + example = "pure"; + description = '' + Set the prompt theme to load. Setting it to 'random' + loads a random theme. Auto set to 'off' on dumb terminals.''; + }; + + pwdLength = mkOption { + type = types.nullOr (types.enum [ "short" "long" "full" ]); + default = null; + example = "short"; + description = '' + Set the working directory prompt display length. By + default, it is set to 'short'. Set it to 'long' (without '~' expansion) for + longer or 'full' (with '~' expansion) for even longer prompt display.''; + }; + + showReturnVal = mkOption { + type = types.nullOr types.bool; + default = null; + example = true; + description = '' + Set the prompt to display the return code along with an + indicator for non-zero return codes. This is not supported by all prompts.''; + }; + }; + + python = { + virtualenvAutoSwitch = mkOption { + type = types.nullOr types.bool; + default = null; + example = true; + description = "Auto switch to Python virtualenv on directory change."; + }; + + virtualenvInitialize = mkOption { + type = types.nullOr types.bool; + default = null; + example = true; + description = + "Automatically initialize virtualenvwrapper if pre-requisites are met."; + }; + }; + + ruby.chrubyAutoSwitch = mkOption { + type = types.nullOr types.bool; + default = null; + example = true; + description = "Auto switch the Ruby version on directory change."; + }; + + screen = { + autoStartLocal = mkOption { + type = types.nullOr types.bool; + default = null; + example = true; + description = + "Auto start a session when Zsh is launched in a local terminal."; + }; + + autoStartRemote = mkOption { + type = types.nullOr types.bool; + default = null; + example = true; + description = + "Auto start a session when Zsh is launched in a SSH connection."; + }; + }; + + ssh.identities = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "id_rsa" "id_rsa2" "id_github" ]; + description = "Set the SSH identities to load into the agent."; + }; + + syntaxHighlighting = { + highlighters = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "main" "brackets" "pattern" "line" "cursor" "root" ]; + description = '' + Set syntax highlighters. By default, only the main + highlighter is enabled.''; + }; + + styles = mkOption { + type = types.attrsOf types.str; + default = { }; + example = { + builtin = "bg=blue"; + command = "bg=blue"; + function = "bg=blue"; + }; + description = "Set syntax highlighting styles."; + }; + + pattern = mkOption { + type = types.attrsOf types.str; + default = { }; + example = { "rm*-rf*" = "fg=white,bold,bg=red"; }; + description = "Set syntax pattern styles."; + }; + }; + + terminal = { + autoTitle = mkOption { + type = types.nullOr types.bool; + default = null; + example = true; + description = "Auto set the tab and window titles."; + }; + + windowTitleFormat = mkOption { + type = types.nullOr types.str; + default = null; + example = "%n@%m: %s"; + description = "Set the window title format."; + }; + + tabTitleFormat = mkOption { + type = types.nullOr types.str; + default = null; + example = "%m: %s"; + description = "Set the tab title format."; + }; + + multiplexerTitleFormat = mkOption { + type = types.nullOr types.str; + default = null; + example = "%s"; + description = "Set the multiplexer title format."; + }; + }; + + tmux = { + autoStartLocal = mkOption { + type = types.nullOr types.bool; + default = null; + example = true; + description = + "Auto start a session when Zsh is launched in a local terminal."; + }; + + autoStartRemote = mkOption { + type = types.nullOr types.bool; + default = null; + example = true; + description = + "Auto start a session when Zsh is launched in a SSH connection."; + }; + + itermIntegration = mkOption { + type = types.nullOr types.bool; + default = null; + example = true; + description = "Integrate with iTerm2."; + }; + + defaultSessionName = mkOption { + type = types.nullOr types.str; + default = null; + example = "YOUR DEFAULT SESSION NAME"; + description = "Set the default session name."; + }; + }; + + utility.safeOps = mkOption { + type = types.nullOr types.bool; + default = null; + example = true; + description = '' + Enabled safe options. This aliases cp, ln, mv and rm so + that they prompt before deleting or overwriting files. Set to 'no' to disable + this safer behavior.''; + }; + }; + }; + +in { + options = { + programs.zsh = { + prezto = mkOption { + type = preztoModule; + default = { }; + description = "Options to configure prezto."; + }; + }; + }; + config = mkIf cfg.enable (mkMerge [{ + home.file."${relToDotDir ".zprofile"}".text = + builtins.readFile "${pkgs.zsh-prezto}/share/zsh-prezto/runcoms/zprofile"; + home.file."${relToDotDir ".zlogin"}".text = + builtins.readFile "${pkgs.zsh-prezto}/share/zsh-prezto/runcoms/zlogin"; + home.file."${relToDotDir ".zlogout"}".text = + builtins.readFile "${pkgs.zsh-prezto}/share/zsh-prezto/runcoms/zlogout"; + home.packages = with pkgs; [ zsh-prezto ]; + + home.file."${relToDotDir ".zshenv"}".text = + builtins.readFile "${pkgs.zsh-prezto}/share/zsh-prezto/runcoms/zshenv"; + home.file."${relToDotDir ".zpreztorc"}".text = '' + # Generated by Nix + ${optionalString (cfg.caseSensitive != null) '' + zstyle ':prezto:*:*' case-sensitive '${ + lib.hm.booleans.yesNo cfg.caseSensitive + }' + ''} + ${optionalString (cfg.color != null) '' + zstyle ':prezto:*:*' color '${lib.hm.booleans.yesNo cfg.color}' + ''} + ${optionalString (cfg.pmoduleDirs != [ ]) '' + zstyle ':prezto:load' pmodule-dirs ${ + builtins.concatStringsSep " " cfg.pmoduleDirs + } + ''} + ${optionalString (cfg.extraModules != [ ]) '' + zstyle ':prezto:load' zmodule ${ + strings.concatMapStringsSep " " strings.escapeShellArg + cfg.extraModules + } + ''} + ${optionalString (cfg.extraFunctions != [ ]) '' + zstyle ':prezto:load' zfunction ${ + strings.concatMapStringsSep " " strings.escapeShellArg + cfg.extraFunctions + } + ''} + ${optionalString (cfg.pmodules != [ ]) '' + zstyle ':prezto:load' pmodule \ + ${ + strings.concatMapStringsSep " \\\n " strings.escapeShellArg + cfg.pmodules + } + ''} + ${optionalString (cfg.autosuggestions.color != null) '' + zstyle ':prezto:module:autosuggestions:color' found '${cfg.autosuggestions.color}' + ''} + ${optionalString (cfg.completions.ignoredHosts != [ ]) '' + zstyle ':prezto:module:completion:*:hosts' etc-host-ignores \ + ${ + strings.concatMapStringsSep " " strings.escapeShellArg + cfg.completions.ignoredHosts + } + ''} + ${optionalString (cfg.editor.keymap != null) '' + zstyle ':prezto:module:editor' key-bindings '${cfg.editor.keymap}' + ''} + ${optionalString (cfg.editor.dotExpansion != null) '' + zstyle ':prezto:module:editor' dot-expansion '${ + lib.hm.booleans.yesNo cfg.editor.dotExpansion + }' + ''} + ${optionalString (cfg.editor.promptContext != null) '' + zstyle ':prezto:module:editor' ps-context '${ + lib.hm.booleans.yesNo cfg.editor.promptContext + }' + ''} + ${optionalString (cfg.git.submoduleIgnore != null) '' + zstyle ':prezto:module:git:status:ignore' submodules '${cfg.git.submoduleIgnore}' + ''} + ${optionalString (cfg.gnuUtility.prefix != null) '' + zstyle ':prezto:module:gnu-utility' prefix '${cfg.gnuUtility.prefix}' + ''} + ${optionalString (cfg.historySubstring.foundColor != null) '' + zstyle ':prezto:module:history-substring-search:color' found '${cfg.historySubstring.foundColor}' + ''} + ${optionalString (cfg.historySubstring.notFoundColor != null) '' + zstyle ':prezto:module:history-substring-search:color' not-found '${cfg.historySubstring.notFoundColor}' + ''} + ${optionalString (cfg.historySubstring.globbingFlags != null) '' + zstyle ':prezto:module:history-substring-search:color' globbing-flags '${cfg.historySubstring.globbingFlags}' + ''} + ${optionalString (cfg.macOS.dashKeyword != null) '' + zstyle ':prezto:module:osx:man' dash-keyword '${cfg.macOS.dashKeyword}' + ''} + ${optionalString (cfg.prompt.theme != null) '' + zstyle ':prezto:module:prompt' theme '${cfg.prompt.theme}' + ''} + ${optionalString (cfg.prompt.pwdLength != null) '' + zstyle ':prezto:module:prompt' pwd-length '${cfg.prompt.pwdLength}' + ''} + ${optionalString (cfg.prompt.showReturnVal != null) '' + zstyle ':prezto:module:prompt' show-return-val '${cfg.prompt.showReturnVal}' + ''} + ${optionalString (cfg.python.virtualenvAutoSwitch != null) '' + zstyle ':prezto:module:python:virtualenv' auto-switch '${ + lib.hm.booleans.yesNo cfg.python.virtualenvAutoSwitch + }' + ''} + ${optionalString (cfg.python.virtualenvInitialize != null) '' + zstyle ':prezto:module:python:virtualenv' initialize '${ + lib.hm.booleans.yesNo cfg.python.virtualenvInitialize + }' + ''} + ${optionalString (cfg.ruby.chrubyAutoSwitch != null) '' + zstyle ':prezto:module:ruby:chruby' auto-switch '${ + lib.hm.booleans.yesNo cfg.ruby.chrubyAutoSwitch + }' + ''} + ${optionalString (cfg.screen.autoStartLocal != null) '' + zstyle ':prezto:module:screen:auto-start' local '${ + lib.hm.booleans.yesNo cfg.screen.autoStartLocal + }' + ''} + ${optionalString (cfg.screen.autoStartRemote != null) '' + zstyle ':prezto:module:screen:auto-start' remote '${ + lib.hm.booleans.yesNo cfg.screen.autoStartRemote + }' + ''} + ${optionalString (cfg.ssh.identities != [ ]) '' + zstyle ':prezto:module:ssh:load' identities \ + ${ + strings.concatMapStringsSep " " strings.escapeShellArg + cfg.ssh.identities + } + ''} + ${optionalString (cfg.syntaxHighlighting.highlighters != [ ]) '' + zstyle ':prezto:module:syntax-highlighting' highlighters \ + ${ + strings.concatMapStringsSep " \\\n " strings.escapeShellArg + cfg.syntaxHighlighting.highlighters + } + ''} + ${optionalString (cfg.syntaxHighlighting.styles != { }) '' + zstyle ':prezto:module:syntax-highlighting' styles \ + ${ + builtins.concatStringsSep " \\\n" (attrsets.mapAttrsToList + (k: v: strings.escapeShellArg k + " " + strings.escapeShellArg v) + cfg.syntaxHighlighting.styles) + } + ''} + ${optionalString (cfg.syntaxHighlighting.pattern != { }) '' + zstyle ':prezto:module:syntax-highlighting' pattern \ + ${ + builtins.concatStringsSep " \\\n" (attrsets.mapAttrsToList + (k: v: strings.escapeShellArg k + " " + strings.escapeShellArg v) + cfg.syntaxHighlighting.pattern) + } + ''} + ${optionalString (cfg.terminal.autoTitle != null) '' + zstyle ':prezto:module:terminal' auto-title '${ + lib.hm.booleans.yesNo cfg.terminal.autoTitle + }' + ''} + ${optionalString (cfg.terminal.windowTitleFormat != null) '' + zstyle ':prezto:module:terminal:window-title' format '${cfg.terminal.windowTitleFormat}' + ''} + ${optionalString (cfg.terminal.tabTitleFormat != null) '' + zstyle ':prezto:module:terminal:tab-title' format '${cfg.terminal.tabTitleFormat}' + ''} + ${optionalString (cfg.terminal.multiplexerTitleFormat != null) '' + zstyle ':prezto:module:terminal:multiplexer-title' format '${cfg.terminal.multiplexerTitleFormat}' + ''} + ${optionalString (cfg.tmux.autoStartLocal != null) '' + zstyle ':prezto:module:tmux:auto-start' local '${ + lib.hm.booleans.yesNo cfg.tmux.autoStartLocal + }' + ''} + ${optionalString (cfg.tmux.autoStartRemote != null) '' + zstyle ':prezto:module:tmux:auto-start' remote '${ + lib.hm.booleans.yesNo cfg.tmux.autoStartRemote + }' + ''} + ${optionalString (cfg.tmux.itermIntegration != null) '' + zstyle ':prezto:module:tmux:iterm' integrate '${ + lib.hm.booleans.yesNo cfg.tmux.itermIntegration + }' + ''} + ${optionalString (cfg.tmux.defaultSessionName != null) '' + zstyle ':prezto:module:tmux:session' name '${cfg.tmux.defaultSessionName}' + ''} + ${optionalString (cfg.utility.safeOps != null) '' + zstyle ':prezto:module:utility' safe-ops '${ + lib.hm.booleans.yesNo cfg.utility.safeOps + }' + ''} + ${cfg.extraConfig} + ''; + }]); +} diff --git a/infra/libkookie/home-manager-stable/modules/services/barrier.nix b/infra/libkookie/home-manager-stable/modules/services/barrier.nix new file mode 100644 index 00000000000..21364b7a3cc --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/barrier.nix @@ -0,0 +1,79 @@ +{ config, lib, pkgs, ... }: + +with lib; +let cfg = config.services.barrier; +in { + + meta.maintainers = with maintainers; [ kritnich ]; + + imports = [ + (mkRemovedOptionModule [ "services" "barrier" "client" "tray" ] '' + The tray option is non-functional and has been removed. + '') + ]; + + options.services.barrier = { + + client = { + + enable = mkEnableOption "Barrier Client daemon"; + + name = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Screen name of client. Defaults to hostname. + ''; + }; + + server = mkOption { + type = types.str; + description = '' + Server to connect to formatted as + <host>[:<port>]. + Port defaults to 24800. + ''; + }; + + enableCrypto = mkEnableOption "crypto (SSL) plugin" // { + default = true; + }; + + enableDragDrop = mkEnableOption "file drag & drop"; + + extraFlags = mkOption { + type = types.listOf types.str; + default = [ "-f" ]; + defaultText = literalExpression ''[ "-f" ]''; + description = '' + Additional flags to pass to barrierc. + See barrierc --help. + ''; + }; + + }; + }; + + config = mkIf cfg.client.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.barrier" pkgs + lib.platforms.linux) + ]; + + systemd.user.services.barrierc = { + Unit = { + Description = "Barrier Client daemon"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + }; + Install.WantedBy = [ "graphical-session.target" ]; + Service.ExecStart = with cfg.client; + toString ([ "${pkgs.barrier}/bin/barrierc" ] + ++ optional (name != null) "--name ${name}" + ++ optional enableCrypto "--enable-crypto" + ++ optional enableDragDrop "--enable-drag-drop" ++ extraFlags + ++ [ server ]); + }; + }; + +} diff --git a/infra/libkookie/home-manager-stable/modules/services/betterlockscreen.nix b/infra/libkookie/home-manager-stable/modules/services/betterlockscreen.nix new file mode 100644 index 00000000000..b4b28b5f98c --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/betterlockscreen.nix @@ -0,0 +1,55 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let cfg = config.services.betterlockscreen; + +in { + meta.maintainers = with maintainers; [ sebtm ]; + + options = { + services.betterlockscreen = { + enable = mkEnableOption "betterlockscreen, a screen-locker module"; + + package = mkOption { + type = types.package; + default = pkgs.betterlockscreen; + defaultText = literalExpression "pkgs.betterlockscreen"; + description = "Package providing betterlockscreen."; + }; + + arguments = mkOption { + type = types.listOf types.str; + default = [ ]; + description = + "List of arguments appended to ./betterlockscreen --lock [args]"; + }; + + inactiveInterval = mkOption { + type = types.int; + default = 10; + description = '' + Value used for . + ''; + }; + + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.betterlockscreen" pkgs + lib.platforms.linux) + ]; + + home.packages = [ cfg.package ]; + + services.screen-locker = { + enable = true; + inactiveInterval = cfg.inactiveInterval; + lockCmd = "${cfg.package}/bin/betterlockscreen --lock ${ + concatStringsSep " " cfg.arguments + }"; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/blueman-applet.nix b/infra/libkookie/home-manager-stable/modules/services/blueman-applet.nix new file mode 100644 index 00000000000..460dd1677c5 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/blueman-applet.nix @@ -0,0 +1,37 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + options = { + services.blueman-applet = { + enable = mkEnableOption "" // { + description = '' + Whether to enable the Blueman applet. + + Note, for the applet to work, the 'blueman' service should + be enabled system-wide. You can enable it in the system + configuration using + + services.blueman.enable = true; + + ''; + }; + }; + }; + + config = mkIf config.services.blueman-applet.enable { + systemd.user.services.blueman-applet = { + Unit = { + Description = "Blueman applet"; + Requires = [ "tray.target" ]; + After = [ "graphical-session-pre.target" "tray.target" ]; + PartOf = [ "graphical-session.target" ]; + }; + + Install = { WantedBy = [ "graphical-session.target" ]; }; + + Service = { ExecStart = "${pkgs.blueman}/bin/blueman-applet"; }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/caffeine.nix b/infra/libkookie/home-manager-stable/modules/services/caffeine.nix new file mode 100644 index 00000000000..28ebc7f13b3 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/caffeine.nix @@ -0,0 +1,38 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.caffeine; + +in { + meta.maintainers = [ maintainers.uvnikita ]; + + options = { + services.caffeine = { enable = mkEnableOption "Caffeine service"; }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.caffeine" pkgs + lib.platforms.linux) + ]; + + systemd.user.services.caffeine = { + Unit = { Description = "caffeine"; }; + + Install = { WantedBy = [ "graphical-session.target" ]; }; + + Service = { + Restart = "on-failure"; + PrivateTmp = true; + ProtectSystem = "full"; + ProtectHome = "yes"; + Type = "exec"; + Slice = "session.slice"; + ExecStart = "${pkgs.caffeine-ng}/bin/caffeine"; + }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/cbatticon.nix b/infra/libkookie/home-manager-stable/modules/services/cbatticon.nix new file mode 100644 index 00000000000..1216878ca0d --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/cbatticon.nix @@ -0,0 +1,124 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.cbatticon; + + package = pkgs.cbatticon; + + makeCommand = commandName: commandArg: + optional (commandArg != null) + (let cmd = pkgs.writeShellScript commandName commandArg; + in "--${commandName} ${cmd}"); + + commandLine = concatStringsSep " " ([ "${package}/bin/cbatticon" ] + ++ makeCommand "command-critical-level" cfg.commandCriticalLevel + ++ makeCommand "command-left-click" cfg.commandLeftClick + ++ optional (cfg.iconType != null) "--icon-type ${cfg.iconType}" + ++ optional (cfg.lowLevelPercent != null) + "--low-level ${toString cfg.lowLevelPercent}" + ++ optional (cfg.criticalLevelPercent != null) + "--critical-level ${toString cfg.criticalLevelPercent}" + ++ optional (cfg.updateIntervalSeconds != null) + "--update-interval ${toString cfg.updateIntervalSeconds}" + ++ optional (cfg.hideNotification != null && cfg.hideNotification) + "--hide-notification"); + +in { + meta.maintainers = [ maintainers.pmiddend ]; + + options = { + services.cbatticon = { + enable = mkEnableOption "cbatticon"; + + commandCriticalLevel = mkOption { + type = types.nullOr types.lines; + default = null; + example = '' + notify-send "battery critical!" + ''; + description = '' + Command to execute when the critical battery level is reached. + ''; + }; + + commandLeftClick = mkOption { + type = types.nullOr types.lines; + default = null; + description = '' + Command to execute when left clicking on the tray icon. + ''; + }; + + iconType = mkOption { + type = + types.nullOr (types.enum [ "standard" "notification" "symbolic" ]); + default = null; + example = "symbolic"; + description = "Icon type to display in the system tray."; + }; + + lowLevelPercent = mkOption { + type = types.nullOr (types.ints.between 0 100); + default = null; + example = 20; + description = '' + Low level percentage of the battery in percent (without the + percent symbol). + ''; + }; + + criticalLevelPercent = mkOption { + type = types.nullOr (types.ints.between 0 100); + default = null; + example = 5; + description = '' + Critical level percentage of the battery in percent (without + the percent symbol). + ''; + }; + + updateIntervalSeconds = mkOption { + type = types.nullOr types.ints.positive; + default = null; + example = 5; + description = '' + Number of seconds between updates of the battery information. + ''; + }; + + hideNotification = mkOption { + type = types.nullOr types.bool; + default = null; + description = "Hide the notification popups."; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.cbatticon" pkgs + lib.platforms.linux) + ]; + + home.packages = [ package ]; + + systemd.user.services.cbatticon = { + Unit = { + Description = "cbatticon system tray battery icon"; + Requires = [ "tray.target" ]; + After = [ "graphical-session-pre.target" "tray.target" ]; + PartOf = [ "graphical-session.target" ]; + }; + + Install = { WantedBy = [ "graphical-session.target" ]; }; + + Service = { + ExecStart = commandLine; + Restart = "on-abort"; + }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/clipmenu.nix b/infra/libkookie/home-manager-stable/modules/services/clipmenu.nix new file mode 100644 index 00000000000..3f2055c9aca --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/clipmenu.nix @@ -0,0 +1,48 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.clipmenu; + +in { + meta.maintainers = [ maintainers.DamienCassou ]; + + options.services.clipmenu = { + enable = mkEnableOption "clipmenu, the clipboard management daemon"; + + package = mkOption { + type = types.package; + default = pkgs.clipmenu; + defaultText = "pkgs.clipmenu"; + description = "clipmenu derivation to use."; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.clipmenu" pkgs + lib.platforms.linux) + ]; + + home.packages = [ cfg.package ]; + + systemd.user.services.clipmenu = { + Unit = { + Description = "Clipboard management daemon"; + After = [ "graphical-session.target" ]; + }; + + Service = { + ExecStart = "${cfg.package}/bin/clipmenud"; + Environment = "PATH=${ + makeBinPath + (with pkgs; [ coreutils findutils gnugrep gnused systemd ]) + }"; + }; + + Install = { WantedBy = [ "graphical-session.target" ]; }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/compton.nix b/infra/libkookie/home-manager-stable/modules/services/compton.nix new file mode 100644 index 00000000000..0b8e7232b45 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/compton.nix @@ -0,0 +1,43 @@ +{ config, lib, pkgs, ... }: + +with lib; { + imports = let + old = n: [ "services" "compton" n ]; + new = n: [ "services" "picom" n ]; + in [ + (mkRenamedOptionModule (old "activeOpacity") (new "activeOpacity")) + (mkRenamedOptionModule (old "backend") (new "backend")) + (mkRenamedOptionModule (old "blur") (new "blur")) + (mkRenamedOptionModule (old "blurExclude") (new "blurExclude")) + (mkRenamedOptionModule (old "extraOptions") (new "extraOptions")) + (mkRenamedOptionModule (old "fade") (new "fade")) + (mkRenamedOptionModule (old "fadeDelta") (new "fadeDelta")) + (mkRenamedOptionModule (old "fadeExclude") (new "fadeExclude")) + (mkRenamedOptionModule (old "fadeSteps") (new "fadeSteps")) + (mkRenamedOptionModule (old "inactiveDim") (new "inactiveDim")) + (mkRenamedOptionModule (old "inactiveOpacity") (new "inactiveOpacity")) + (mkRenamedOptionModule (old "menuOpacity") (new "menuOpacity")) + (mkRenamedOptionModule (old "noDNDShadow") (new "noDNDShadow")) + (mkRenamedOptionModule (old "noDockShadow") (new "noDockShadow")) + (mkRenamedOptionModule (old "opacityRule") (new "opacityRule")) + (mkRenamedOptionModule (old "package") (new "package")) + (mkRenamedOptionModule (old "refreshRate") (new "refreshRate")) + (mkRenamedOptionModule (old "shadow") (new "shadow")) + (mkRenamedOptionModule (old "shadowExclude") (new "shadowExclude")) + (mkRenamedOptionModule (old "shadowOffsets") (new "shadowOffsets")) + (mkRenamedOptionModule (old "shadowOpacity") (new "shadowOpacity")) + (mkChangedOptionModule (old "vSync") (new "vSync") (v: v != "none")) + ]; + + options.services.compton.enable = mkEnableOption "Compton X11 compositor" // { + visible = false; + }; + + config = mkIf config.services.compton.enable { + warnings = [ + "Obsolete option `services.compton.enable' is used. It was renamed to `services.picom.enable'." + ]; + + services.picom.enable = true; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/devilspie2.nix b/infra/libkookie/home-manager-stable/modules/services/devilspie2.nix new file mode 100644 index 00000000000..fa77153e7f7 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/devilspie2.nix @@ -0,0 +1,47 @@ +{ config, lib, pkgs, ... }: + +with lib; +let cfg = config.services.devilspie2; +in { + meta.maintainers = [ maintainers.dawidsowa ]; + + options = { + services.devilspie2 = { + enable = mkEnableOption '' + Devilspie2, a window matching utility, allowing the user to + perform scripted actions on windows as they are created''; + + config = mkOption { + type = types.lines; + default = ""; + description = '' + Content of file placed in the devilspie2 config directory. + ''; + example = '' + if (get_window_class() == "Gnome-terminal") then + make_always_on_top(); + end + ''; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.devilspie2" pkgs + lib.platforms.linux) + ]; + + systemd.user.services.devilspie2 = { + Service.ExecStart = "${pkgs.devilspie2}/bin/devilspie2"; + Unit = { + Description = "devilspie2"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + }; + Install.WantedBy = [ "graphical-session.target" ]; + }; + + xdg.configFile."devilspie2/config.lua".text = cfg.config; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/dropbox.nix b/infra/libkookie/home-manager-stable/modules/services/dropbox.nix new file mode 100644 index 00000000000..941f4d82e97 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/dropbox.nix @@ -0,0 +1,82 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.dropbox; + baseDir = ".dropbox-hm"; + dropboxCmd = "${pkgs.dropbox-cli}/bin/dropbox"; + homeBaseDir = "${config.home.homeDirectory}/${baseDir}"; + +in { + meta.maintainers = [ maintainers.eyjhb ]; + + options = { + services.dropbox = { + enable = mkEnableOption "Dropbox daemon"; + + path = mkOption { + type = types.path; + default = "${config.home.homeDirectory}/Dropbox"; + defaultText = + literalExpression ''"''${config.home.homeDirectory}/Dropbox"''; + apply = toString; # Prevent copies to Nix store. + description = "Where to put the Dropbox directory."; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.dropbox" pkgs + lib.platforms.linux) + ]; + + home.packages = [ pkgs.dropbox-cli ]; + + systemd.user.services.dropbox = { + Unit = { Description = "dropbox"; }; + + Install = { WantedBy = [ "default.target" ]; }; + + Service = { + Environment = [ "HOME=${homeBaseDir}" "DISPLAY=" ]; + + Type = "forking"; + PIDFile = "${homeBaseDir}/.dropbox/dropbox.pid"; + + Restart = "on-failure"; + PrivateTmp = true; + ProtectSystem = "full"; + Nice = 10; + + ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; + ExecStop = "${dropboxCmd} stop"; + ExecStart = toString (pkgs.writeShellScript "dropbox-start" '' + # ensure we have the dirs we need + $DRY_RUN_CMD ${pkgs.coreutils}/bin/mkdir $VERBOSE_ARG -p \ + ${homeBaseDir}/{.dropbox,.dropbox-dist,Dropbox} + + # symlink them as needed + if [[ ! -d ${config.home.homeDirectory}/.dropbox ]]; then + $DRY_RUN_CMD ${pkgs.coreutils}/bin/ln $VERBOSE_ARG -s \ + ${homeBaseDir}/.dropbox ${config.home.homeDirectory}/.dropbox + fi + + if [[ ! -d ${escapeShellArg cfg.path} ]]; then + $DRY_RUN_CMD ${pkgs.coreutils}/bin/ln $VERBOSE_ARG -s \ + ${homeBaseDir}/Dropbox ${escapeShellArg cfg.path} + fi + + # get the dropbox bins if needed + if [[ ! -f $HOME/.dropbox-dist/VERSION ]]; then + ${pkgs.coreutils}/bin/yes | ${dropboxCmd} update + fi + + ${dropboxCmd} start + ''); + }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/dunst.nix b/infra/libkookie/home-manager-stable/modules/services/dunst.nix new file mode 100644 index 00000000000..083ff2b3a4e --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/dunst.nix @@ -0,0 +1,200 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.dunst; + + eitherStrBoolIntList = with types; + either str (either bool (either int (listOf str))); + + toDunstIni = generators.toINI { + mkKeyValue = key: value: + let + value' = if isBool value then + (lib.hm.booleans.yesNo value) + else if isString value then + ''"${value}"'' + else + toString value; + in "${key}=${value'}"; + }; + + themeType = types.submodule { + options = { + package = mkOption { + type = types.package; + example = literalExpression "pkgs.gnome.adwaita-icon-theme"; + description = "Package providing the theme."; + }; + + name = mkOption { + type = types.str; + example = "Adwaita"; + description = "The name of the theme within the package."; + }; + + size = mkOption { + type = types.str; + default = "32x32"; + example = "16x16"; + description = "The desired icon size."; + }; + }; + }; + + hicolorTheme = { + package = pkgs.hicolor-icon-theme; + name = "hicolor"; + size = "32x32"; + }; + +in { + meta.maintainers = [ maintainers.rycee ]; + + options = { + services.dunst = { + enable = mkEnableOption "the dunst notification daemon"; + + package = mkOption { + type = types.package; + default = pkgs.dunst; + defaultText = literalExpression "pkgs.dunst"; + description = "Package providing dunst."; + }; + + configFile = mkOption { + type = with types; either str path; + default = "${config.xdg.configHome}/dunst/dunstrc"; + defaultText = "$XDG_CONFIG_HOME/dunst/dunstrc"; + description = '' + Path to the configuration file read by dunst. + + Note that the configuration generated by Home Manager will be + written to $XDG_CONFIG_HOME/dunst/dunstrc + regardless. This allows using a mutable configuration file generated + from the immutable one, useful in scenarios where live reloading is + desired. + ''; + }; + + iconTheme = mkOption { + type = themeType; + default = hicolorTheme; + description = "Set the icon theme."; + }; + + waylandDisplay = mkOption { + type = types.str; + default = ""; + description = + "Set the service's WAYLAND_DISPLAY environment variable."; + }; + + settings = mkOption { + type = types.submodule { + freeformType = with types; attrsOf (attrsOf eitherStrBoolIntList); + options = { + global.icon_path = mkOption { + type = types.separatedString ":"; + description = "Paths where dunst will look for icons."; + }; + }; + }; + default = { }; + description = + "Configuration written to $XDG_CONFIG_HOME/dunst/dunstrc."; + example = literalExpression '' + { + global = { + geometry = "300x5-30+50"; + transparency = 10; + frame_color = "#eceff1"; + font = "Droid Sans 9"; + }; + + urgency_normal = { + background = "#37474f"; + foreground = "#eceff1"; + timeout = 10; + }; + }; + ''; + }; + }; + }; + + config = mkIf cfg.enable (mkMerge [ + { + home.packages = [ cfg.package ]; + + xdg.dataFile."dbus-1/services/org.knopwob.dunst.service".source = + "${pkgs.dunst}/share/dbus-1/services/org.knopwob.dunst.service"; + + services.dunst.settings.global.icon_path = let + useCustomTheme = cfg.iconTheme.package != hicolorTheme.package + || cfg.iconTheme.name != hicolorTheme.name || cfg.iconTheme.size + != hicolorTheme.size; + + basePaths = [ + "/run/current-system/sw" + config.home.profileDirectory + cfg.iconTheme.package + ] ++ optional useCustomTheme hicolorTheme.package; + + themes = [ cfg.iconTheme ] ++ optional useCustomTheme + (hicolorTheme // { size = cfg.iconTheme.size; }); + + categories = [ + "actions" + "animations" + "apps" + "categories" + "devices" + "emblems" + "emotes" + "filesystem" + "intl" + "legacy" + "mimetypes" + "places" + "status" + "stock" + ]; + + mkPath = { basePath, theme, category }: + "${basePath}/share/icons/${theme.name}/${theme.size}/${category}"; + in concatMapStringsSep ":" mkPath (cartesianProductOfSets { + basePath = basePaths; + theme = themes; + category = categories; + }); + + systemd.user.services.dunst = { + Unit = { + Description = "Dunst notification daemon"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + }; + + Service = { + Type = "dbus"; + BusName = "org.freedesktop.Notifications"; + ExecStart = "${cfg.package}/bin/dunst -config ${cfg.configFile}"; + Environment = optionalString (cfg.waylandDisplay != "") + "WAYLAND_DISPLAY=${cfg.waylandDisplay}"; + }; + }; + } + + (mkIf (cfg.settings != { }) { + xdg.configFile."dunst/dunstrc" = { + text = toDunstIni cfg.settings; + onChange = '' + ${pkgs.procps}/bin/pkill -u "$USER" ''${VERBOSE+-e} dunst || true + ''; + }; + }) + ]); +} diff --git a/infra/libkookie/home-manager-stable/modules/services/dwm-status.nix b/infra/libkookie/home-manager-stable/modules/services/dwm-status.nix new file mode 100644 index 00000000000..c3295faac69 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/dwm-status.nix @@ -0,0 +1,72 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.dwm-status; + + jsonFormat = pkgs.formats.json { }; + + features = [ "audio" "backlight" "battery" "cpu_load" "network" "time" ]; + + finalConfig = { inherit (cfg) order; } // cfg.extraConfig; + + configFile = jsonFormat.generate "dwm-status.json" finalConfig; + +in { + options = { + services.dwm-status = { + enable = mkEnableOption "dwm-status user service"; + + package = mkOption { + type = types.package; + default = pkgs.dwm-status; + defaultText = literalExpression "pkgs.dwm-status"; + example = "pkgs.dwm-status.override { enableAlsaUtils = false; }"; + description = "Which dwm-status package to use."; + }; + + order = mkOption { + type = types.listOf (types.enum features); + description = "List of enabled features in order."; + }; + + extraConfig = mkOption { + type = jsonFormat.type; + default = { }; + example = literalExpression '' + { + separator = "#"; + + battery = { + notifier_levels = [ 2 5 10 15 20 ]; + }; + + time = { + format = "%H:%M"; + }; + } + ''; + description = "Extra config of dwm-status."; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.dwm-status" pkgs + lib.platforms.linux) + ]; + + systemd.user.services.dwm-status = { + Unit = { + Description = "DWM status service"; + PartOf = [ "graphical-session.target" ]; + }; + + Install = { WantedBy = [ "graphical-session.target" ]; }; + + Service = { ExecStart = "${cfg.package}/bin/dwm-status ${configFile}"; }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/easyeffects.nix b/infra/libkookie/home-manager-stable/modules/services/easyeffects.nix new file mode 100644 index 00000000000..001ff5d025a --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/easyeffects.nix @@ -0,0 +1,62 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.easyeffects; + + presetOpts = optionalString (cfg.preset != "") "--load-preset ${cfg.preset}"; + +in { + meta.maintainers = [ maintainers.fufexan ]; + + options.services.easyeffects = { + enable = mkEnableOption '' + Easyeffects daemon. + Note, it is necessary to add + + programs.dconf.enable = true; + + to your system configuration for the daemon to work correctly''; + + preset = mkOption { + type = types.str; + default = ""; + description = '' + Which preset to use when starting easyeffects. + Will likely need to launch easyeffects to initially create preset. + ''; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (hm.assertions.assertPlatform "services.easyeffects" pkgs platforms.linux) + ]; + + # running easyeffects will just attach itself to gapplication service + # at-spi2-core is to minimize journalctl noise of: + # "AT-SPI: Error retrieving accessibility bus address: org.freedesktop.DBus.Error.ServiceUnknown: The name org.a11y.Bus was not provided by any .service files" + home.packages = with pkgs; [ easyeffects at-spi2-core ]; + + systemd.user.services.easyeffects = { + Unit = { + Description = "Easyeffects daemon"; + Requires = [ "dbus.service" ]; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" "pipewire.service" ]; + }; + + Install.WantedBy = [ "graphical-session.target" ]; + + Service = { + ExecStart = + "${pkgs.easyeffects}/bin/easyeffects --gapplication-service ${presetOpts}"; + ExecStop = "${pkgs.easyeffects}/bin/easyeffects --quit"; + Restart = "on-failure"; + RestartSec = 5; + }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/emacs.nix b/infra/libkookie/home-manager-stable/modules/services/emacs.nix new file mode 100644 index 00000000000..382671515e1 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/emacs.nix @@ -0,0 +1,183 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.emacs; + emacsCfg = config.programs.emacs; + emacsBinPath = "${cfg.package}/bin"; + emacsVersion = getVersion cfg.package; + + clientWMClass = + if versionAtLeast emacsVersion "28" then "Emacsd" else "Emacs"; + + # Adapted from upstream emacs.desktop + clientDesktopItem = pkgs.writeTextDir "share/applications/emacsclient.desktop" + (generators.toINI { } { + "Desktop Entry" = { + Type = "Application"; + Exec = "${emacsBinPath}/emacsclient ${ + concatStringsSep " " cfg.client.arguments + } %F"; + Terminal = false; + Name = "Emacs Client"; + Icon = "emacs"; + Comment = "Edit text"; + GenericName = "Text Editor"; + MimeType = + "text/english;text/plain;text/x-makefile;text/x-c++hdr;text/x-c++src;text/x-chdr;text/x-csrc;text/x-java;text/x-moc;text/x-pascal;text/x-tcl;text/x-tex;application/x-shellscript;text/x-c;text/x-c++;"; + Categories = "Development;TextEditor;"; + Keywords = "Text;Editor;"; + StartupWMClass = clientWMClass; + }; + }); + + # Match the default socket path for the Emacs version so emacsclient continues + # to work without wrapping it. + socketDir = "%t/emacs"; + socketPath = "${socketDir}/server"; + +in { + meta.maintainers = [ maintainers.tadfisher ]; + + options.services.emacs = { + enable = mkEnableOption "the Emacs daemon"; + + package = mkOption { + type = types.package; + default = if emacsCfg.enable then emacsCfg.finalPackage else pkgs.emacs; + defaultText = literalExpression '' + if config.programs.emacs.enable then config.programs.emacs.finalPackage + else pkgs.emacs + ''; + description = "The Emacs package to use."; + }; + + extraOptions = mkOption { + type = with types; listOf str; + default = [ ]; + example = [ "-f" "exwm-enable" ]; + description = '' + Extra command-line arguments to pass to emacs. + ''; + }; + + client = { + enable = mkEnableOption "generation of Emacs client desktop file"; + arguments = mkOption { + type = with types; listOf str; + default = [ "-c" ]; + description = '' + Command-line arguments to pass to emacsclient. + ''; + }; + }; + + # Attrset for forward-compatibility; there may be a need to customize the + # socket path, though allowing for such is not easy to do as systemd socket + # units don't perform variable expansion for 'ListenStream'. + socketActivation = { + enable = mkEnableOption "systemd socket activation for the Emacs service"; + }; + + defaultEditor = mkOption rec { + type = types.bool; + default = false; + example = !default; + description = '' + Whether to configure emacsclient as the default + editor using the EDITOR environment variable. + ''; + }; + }; + + config = mkIf cfg.enable (mkMerge [ + { + assertions = [ + (lib.hm.assertions.assertPlatform "services.emacs" pkgs + lib.platforms.linux) + ]; + + systemd.user.services.emacs = { + Unit = { + Description = "Emacs text editor"; + Documentation = + "info:emacs man:emacs(1) https://gnu.org/software/emacs/"; + + # Avoid killing the Emacs session, which may be full of + # unsaved buffers. + X-RestartIfChanged = false; + } // optionalAttrs (cfg.socketActivation.enable) { + # Emacs deletes its socket when shutting down, which systemd doesn't + # handle, resulting in a server without a socket. + # See https://github.com/nix-community/home-manager/issues/2018 + RefuseManualStart = true; + }; + + Service = { + Type = "notify"; + + # We wrap ExecStart in a login shell so Emacs starts with the user's + # environment, most importantly $PATH and $NIX_PROFILES. It may be + # worth investigating a more targeted approach for user services to + # import the user environment. + ExecStart = '' + ${pkgs.runtimeShell} -l -c "${emacsBinPath}/emacs --fg-daemon${ + # In case the user sets 'server-directory' or 'server-name' in + # their Emacs config, we want to specify the socket path explicitly + # so launching 'emacs.service' manually doesn't break emacsclient + # when using socket activation. + optionalString cfg.socketActivation.enable + "=${escapeShellArg socketPath}" + } ${escapeShellArgs cfg.extraOptions}"''; + + # Emacs will exit with status 15 after having received SIGTERM, which + # is the default "KillSignal" value systemd uses to stop services. + SuccessExitStatus = 15; + + Restart = "on-failure"; + } // optionalAttrs (cfg.socketActivation.enable) { + # Use read-only directory permissions to prevent emacs from + # deleting systemd's socket file before exiting. + ExecStartPost = + "${pkgs.coreutils}/bin/chmod --changes -w ${socketDir}"; + ExecStopPost = + "${pkgs.coreutils}/bin/chmod --changes +w ${socketDir}"; + }; + } // optionalAttrs (!cfg.socketActivation.enable) { + Install = { WantedBy = [ "default.target" ]; }; + }; + + home = { + packages = optional cfg.client.enable (hiPrio clientDesktopItem); + + sessionVariables = mkIf cfg.defaultEditor { + EDITOR = getBin (pkgs.writeShellScript "editor" '' + exec ${ + getBin cfg.package + }/bin/emacsclient "''${@:---create-frame}"''); + }; + }; + } + + (mkIf cfg.socketActivation.enable { + systemd.user.sockets.emacs = { + Unit = { + Description = "Emacs text editor"; + Documentation = + "info:emacs man:emacs(1) https://gnu.org/software/emacs/"; + }; + + Socket = { + ListenStream = socketPath; + FileDescriptorName = "server"; + SocketMode = "0600"; + DirectoryMode = "0700"; + }; + + Install = { WantedBy = [ "sockets.target" ]; }; + }; + }) + ]); +} diff --git a/infra/libkookie/home-manager-stable/modules/services/espanso.nix b/infra/libkookie/home-manager-stable/modules/services/espanso.nix new file mode 100644 index 00000000000..3d66a59874f --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/espanso.nix @@ -0,0 +1,86 @@ +{ pkgs, config, lib, ... }: + +let + + inherit (lib) + mkOption mkEnableOption mkIf maintainers literalExpression types platforms; + + inherit (lib.hm.assertions) assertPlatform; + + cfg = config.services.espanso; + + yaml = pkgs.formats.yaml { }; + +in { + meta.maintainers = with maintainers; [ lucasew ]; + + options = { + services.espanso = { + enable = mkEnableOption "Espanso: cross platform text expander in Rust"; + + package = mkOption { + type = types.package; + description = "Which espanso package to use"; + default = pkgs.espanso; + defaultText = literalExpression "pkgs.espanso"; + }; + + settings = mkOption { + type = yaml.type; + default = { matches = [ ]; }; + example = literalExpression '' + { + matches = [ + { # Simple text replacement + trigger = ":espanso"; + replace = "Hi there!"; + } + { # Dates + trigger = ":date"; + replace = "{{mydate}}"; + vars = [{ + name = "mydate"; + type = "date"; + params = { format = "%m/%d/%Y"; }; + }]; + } + { # Shell commands + trigger = ":shell"; + replace = "{{output}}"; + vars = [{ + name = "output"; + type = "shell"; + params = { cmd = "echo Hello from your shell"; }; + }]; + } + ]; + } + ''; + description = '' + The Espanso configuration to use. See + + for a description of available options. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ (assertPlatform "services.espanso" pkgs platforms.linux) ]; + + home.packages = [ cfg.package ]; + + xdg.configFile."espanso/default.yml".source = + yaml.generate "espanso-default.yml" cfg.settings; + + systemd.user.services.espanso = { + Unit = { Description = "Espanso: cross platform text expander in Rust"; }; + Service = { + Type = "exec"; + ExecStart = "${cfg.package}/bin/espanso daemon"; + Restart = "on-failure"; + }; + Install = { WantedBy = [ "default.target" ]; }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/etesync-dav.nix b/infra/libkookie/home-manager-stable/modules/services/etesync-dav.nix new file mode 100644 index 00000000000..5fd58d09260 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/etesync-dav.nix @@ -0,0 +1,67 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.etesync-dav; + + toEnvironmentCfg = vars: + (concatStringsSep " " + (mapAttrsToList (k: v: "${k}=${escapeShellArg v}") vars)); + +in { + meta.maintainers = [ maintainers.valodim ]; + + options.services.etesync-dav = { + enable = mkEnableOption "etesync-dav"; + + package = mkOption { + type = types.package; + default = pkgs.etesync-dav; + defaultText = "pkgs.etesync-dav"; + description = "The etesync-dav derivation to use."; + }; + + serverUrl = mkOption { + type = types.str; + default = "https://api.etesync.com/"; + description = "The URL to the etesync server."; + }; + + settings = mkOption { + type = types.attrsOf (types.oneOf [ types.str types.int ]); + default = { }; + example = literalExpression '' + { + ETESYNC_LISTEN_ADDRESS = "localhost"; + ETESYNC_LISTEN_PORT = 37358; + } + ''; + description = '' + Settings for etesync-dav, passed as environment variables. + ''; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.etesync-dav" pkgs + lib.platforms.linux) + ]; + + home.packages = [ cfg.package ]; + + systemd.user.services.etesync-dav = { + Unit = { Description = "etesync-dav"; }; + + Service = { + ExecStart = "${cfg.package}/bin/etesync-dav"; + Environment = + toEnvironmentCfg ({ ETESYNC_URL = cfg.serverUrl; } // cfg.settings); + }; + + Install = { WantedBy = [ "default.target" ]; }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/flameshot.nix b/infra/libkookie/home-manager-stable/modules/services/flameshot.nix new file mode 100644 index 00000000000..2de0d547dda --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/flameshot.nix @@ -0,0 +1,82 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.flameshot; + + iniFormat = pkgs.formats.ini { }; + + iniFile = iniFormat.generate "flameshot.ini" cfg.settings; + +in { + meta.maintainers = [ maintainers.hamhut1066 ]; + + options.services.flameshot = { + enable = mkEnableOption "Flameshot"; + + package = mkOption { + type = types.package; + default = pkgs.flameshot; + defaultText = literalExpression "pkgs.flameshot"; + description = "Package providing flameshot."; + }; + + settings = mkOption { + type = iniFormat.type; + default = { }; + example = { + General = { + disabledTrayIcon = true; + showStartupLaunchMessage = false; + }; + }; + description = '' + Configuration to use for Flameshot. See + + for available options. + ''; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.flameshot" pkgs + lib.platforms.linux) + ]; + + home.packages = [ cfg.package ]; + + xdg.configFile = mkIf (cfg.settings != { }) { + "flameshot/flameshot.ini".source = iniFile; + }; + + systemd.user.services.flameshot = { + Unit = { + Description = "Flameshot screenshot tool"; + Requires = [ "tray.target" ]; + After = [ "graphical-session-pre.target" "tray.target" ]; + PartOf = [ "graphical-session.target" ]; + X-Restart-Triggers = mkIf (cfg.settings != { }) [ "${iniFile}" ]; + }; + + Install = { WantedBy = [ "graphical-session.target" ]; }; + + Service = { + Environment = "PATH=${config.home.profileDirectory}/bin"; + ExecStart = "${cfg.package}/bin/flameshot"; + Restart = "on-abort"; + + # Sandboxing. + LockPersonality = true; + MemoryDenyWriteExecute = true; + NoNewPrivileges = true; + PrivateUsers = true; + RestrictNamespaces = true; + SystemCallArchitectures = "native"; + SystemCallFilter = "@system-service"; + }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/fluidsynth.nix b/infra/libkookie/home-manager-stable/modules/services/fluidsynth.nix new file mode 100644 index 00000000000..bf1b76a0dd3 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/fluidsynth.nix @@ -0,0 +1,71 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.fluidsynth; + +in { + meta.maintainers = [ maintainers.valodim ]; + + options = { + services.fluidsynth = { + enable = mkEnableOption "fluidsynth midi synthesizer"; + + soundFont = mkOption { + type = types.path; + default = "${pkgs.soundfont-fluid}/share/soundfonts/FluidR3_GM2-2.sf2"; + description = '' + The soundfont file to use, in SoundFont 2 format. + ''; + }; + + soundService = mkOption { + type = types.enum [ "jack" "pipewire-pulse" "pulseaudio" ]; + default = "pulseaudio"; + example = "pipewire-pulse"; + description = '' + The systemd sound service to depend on. + ''; + }; + + extraOptions = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "--sample-rate 96000" ]; + description = '' + Extra arguments, added verbatim to the fluidsynth command. See + + fluidsynth.conf + 1 + . + ''; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.fluidsynth" pkgs + lib.platforms.linux) + ]; + + systemd.user.services.fluidsynth = { + Unit = { + Description = "FluidSynth Daemon"; + Documentation = "man:fluidsynth(1)"; + BindsTo = [ (cfg.soundService + ".service") ]; + After = [ (cfg.soundService + ".service") ]; + }; + + Install = { WantedBy = [ "default.target" ]; }; + + Service = { + ExecStart = "${pkgs.fluidsynth}/bin/fluidsynth -a pulseaudio -si ${ + lib.concatStringsSep " " cfg.extraOptions + } ${cfg.soundFont}"; + }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/fnott.nix b/infra/libkookie/home-manager-stable/modules/services/fnott.nix new file mode 100644 index 00000000000..f90a0851e4d --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/fnott.nix @@ -0,0 +1,113 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.fnott; + + concatStringsSep' = sep: list: concatStringsSep sep (remove "" list); + + iniFormat = pkgs.formats.ini { }; +in { + meta.maintainers = with maintainers; [ polykernel ]; + + options = { + services.fnott = { + enable = mkEnableOption '' + fnott, a lightweight Wayland notification daemon for wlroots-based compositors + ''; + + package = mkOption { + type = types.package; + default = pkgs.fnott; + defaultText = literalExpression "pkgs.fnott"; + description = "Package providing fnott."; + }; + + extraFlags = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "-s" ]; + description = '' + Extra arguments to use for executing fnott. + ''; + }; + + configFile = mkOption { + type = types.either types.str types.path; + default = "${config.xdg.configHome}/fnott/fnott.ini"; + defaultText = "$XDG_CONFIG_HOME/fnott/fnott.ini"; + description = '' + Path to the configuration file read by fnott. + + Note that environment variables in the path won't be properly expanded. + + The configuration specified under + will be generated and + written to $XDG_CONFIG_HOME/fnott/fnott.ini + regardless of this option. This allows using a mutable configuration file + generated from the immutable one, useful in scenarios where live reloading is desired. + ''; + }; + + settings = mkOption { + type = iniFormat.type; + default = { }; + description = '' + Configuration written to + $XDG_CONFIG_HOME/fnott/fnott.ini. + + See + + fnott.ini + 5 + for a list of avaliable options and + for an example configuration. + ''; + example = literalExpression '' + { + main = { + notification-margin = 5; + }; + + low = { + timeout = 5; + title-font = "Dina:weight=bold:slant=italic"; + title-color = "ffffff"; + }; + } + ''; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = + [ (hm.assertions.assertPlatform "services.fnott" pkgs platforms.linux) ]; + + home.packages = [ cfg.package ]; + + systemd.user.services.fnott = { + Unit = { + Description = "Fnott notification daemon"; + Documentation = "man:fnott(1)"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + }; + + Service = { + Type = "dbus"; + BusName = "org.freedesktop.Notifications"; + ExecStart = concatStringsSep' " " [ + "${cfg.package}/bin/fnott" + "-c ${escapeShellArg cfg.configFile}" + (escapeShellArgs cfg.extraFlags) + ]; + }; + }; + + xdg.configFile."fnott/fnott.ini".source = + iniFormat.generate "fnott.ini" cfg.settings; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/fusuma.nix b/infra/libkookie/home-manager-stable/modules/services/fusuma.nix new file mode 100644 index 00000000000..3a853b51381 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/fusuma.nix @@ -0,0 +1,138 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.fusuma; + + yamlFormat = pkgs.formats.yaml { }; + + configJson = pkgs.writeText "config.json" (builtins.toJSON cfg.settings); + + configYamlRaw = pkgs.runCommand "config.yaml.raw" { } '' + ${pkgs.remarshal}/bin/json2yaml -i ${configJson} -o $out; + ''; + + # convert keys into literal numbers where necessary, + # fusuma does not support string type finger count. + strToInt = pkgs.writers.writePython3 "str2int" { + libraries = [ pkgs.python3Packages.pyyaml ]; + } '' + import yaml + from yaml import FullLoader + + + def str2int(config): + if type(config) is not dict: + return + + for key in list(config): + if type(config[key]) is dict and key.isdigit(): + t = config[key] + del config[key] + config[int(key)] = t + else: + str2int(config[key]) + + + if __name__ == '__main__': + path = "${configYamlRaw}" + with open(path) as f: + config = yaml.load(f, Loader=FullLoader) + str2int(config) + print(yaml.dump(config)) + ''; + + configYaml = pkgs.stdenv.mkDerivation { + name = "config.yaml"; + buildCommand = '' + ${strToInt} > $out + ''; + }; + + makeBinPath = packages: + foldl (a: b: if a == "" then b else "${a}:${b}") "" + (map (pkg: "${pkg}/bin") packages); + +in { + meta.maintainers = [ hm.maintainers.iosmanthus ]; + + options.services.fusuma = { + enable = mkEnableOption + "the fusuma systemd service to automatically enable touchpad gesture"; + + package = mkOption { + type = types.package; + default = pkgs.fusuma; + defaultText = literalExpression "pkgs.fusuma"; + description = "Package providing fusuma."; + }; + + settings = mkOption { + type = yamlFormat.type; + example = literalExpression '' + { + enable = true; + extraPackages = with pkgs;[ xdotool ]; + config = { + threshold = { + swipe = 0.1; + }; + interval = { + swipe = 0.7; + }; + swipe = { + "3" = { + left = { + # GNOME: Switch to left workspace + command = "xdotool key ctrl+alt+Right"; + }; + }; + }; + }; + }; + ''; + description = '' + YAML config that will override the default fusuma configuration. + ''; + }; + + extraPackages = mkOption { + type = types.listOf types.package; + default = with pkgs; [ coreutils ]; + defaultText = literalExpression "pkgs.coreutils"; + example = literalExpression '' + with pkgs; [ coreutils xdotool ]; + ''; + description = '' + Extra packages needs to bring to the scope of fusuma service. + ''; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.fusuma" pkgs + lib.platforms.linux) + ]; + + xdg.configFile."fusuma/config.yaml".source = configYaml; + + systemd.user.services.fusuma = { + Unit = { + Description = "Fusuma services"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + }; + + Service = { + Environment = with pkgs; "PATH=${makeBinPath cfg.extraPackages}"; + ExecStart = + "${cfg.package}/bin/fusuma -c ${config.xdg.configHome}/fusuma/config.yaml"; + }; + + Install = { WantedBy = [ "graphical-session.target" ]; }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/getmail.nix b/infra/libkookie/home-manager-stable/modules/services/getmail.nix new file mode 100644 index 00000000000..83ed4ed4569 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/getmail.nix @@ -0,0 +1,60 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.getmail; + + accounts = + filter (a: a.getmail.enable) (attrValues config.accounts.email.accounts); + + # Note: The getmail service does not expect a path, but just the filename! + renderConfigFilepath = a: + if a.primary then "getmailrc" else "getmail${a.name}"; + configFiles = + concatMapStringsSep " " (a: " --rcfile ${renderConfigFilepath a}") accounts; +in { + options = { + services.getmail = { + enable = mkEnableOption + "the getmail systemd service to automatically retrieve mail"; + + frequency = mkOption { + type = types.str; + default = "*:0/5"; + example = "hourly"; + description = '' + The refresh frequency. Check man systemd.time for + more information on the syntax. If you use a gpg-agent in + combination with the passwordCommand, keep the poll + frequency below the cache-ttl value (as set by the + default) to avoid pinentry asking + permanently for a password. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.getmail" pkgs + lib.platforms.linux) + ]; + + systemd.user.services.getmail = { + Unit = { Description = "getmail email fetcher"; }; + Service = { ExecStart = "${pkgs.getmail}/bin/getmail ${configFiles}"; }; + }; + + systemd.user.timers.getmail = { + Unit = { Description = "getmail email fetcher"; }; + Timer = { + OnCalendar = "${cfg.frequency}"; + Unit = "getmail.service"; + }; + Install = { WantedBy = [ "timers.target" ]; }; + }; + + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/git-sync.nix b/infra/libkookie/home-manager-stable/modules/services/git-sync.nix new file mode 100644 index 00000000000..07a7927126c --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/git-sync.nix @@ -0,0 +1,100 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.git-sync; + + mkUnit = name: repo: { + Unit.Description = "Git Sync ${name}"; + + Install.WantedBy = [ "default.target" ]; + + Service = { + Environment = [ + "GIT_SYNC_DIRECTORY=${repo.path}" + "GIT_SYNC_COMMAND=${cfg.package}/bin/git-sync" + "GIT_SYNC_REPOSITORY=${repo.uri}" + "GIT_SYNC_INTERVAL=${toString repo.interval}" + ]; + ExecStart = "${cfg.package}/bin/git-sync-on-inotify"; + Restart = "on-abort"; + }; + }; + + services = mapAttrs' (name: repo: { + name = "git-sync-${name}"; + value = mkUnit name repo; + }) cfg.repositories; + + repositoryType = types.submodule ({ name, ... }: { + options = { + name = mkOption { + internal = true; + default = name; + type = types.str; + description = "The name that should be given to this unit."; + }; + + path = mkOption { + type = types.path; + description = "The path at which to sync the repository"; + }; + + uri = mkOption { + type = types.str; + example = "git+ssh://user@example.com:/~[user]/path/to/repo.git"; + description = '' + The URI of the remote to be synchronized. This is only used in the + event that the directory does not already exist. See + + for the supported URIs. + ''; + }; + + interval = mkOption { + type = types.int; + default = 500; + description = '' + The interval, specified in seconds, at which the synchronization will + be triggered even without filesystem changes. + ''; + }; + }; + }); + +in { + meta.maintainers = [ maintainers.imalison ]; + + options = { + services.git-sync = { + enable = mkEnableOption "git-sync services"; + + package = mkOption { + type = types.package; + default = pkgs.git-sync; + defaultText = literalExpression "pkgs.git-sync"; + description = '' + Package containing the git-sync program. + ''; + }; + + repositories = mkOption { + type = with types; attrsOf repositoryType; + description = '' + The repositories that should be synchronized. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.git-sync" pkgs + lib.platforms.linux) + ]; + + systemd.user.services = services; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/gnome-keyring.nix b/infra/libkookie/home-manager-stable/modules/services/gnome-keyring.nix new file mode 100644 index 00000000000..7267129d7e6 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/gnome-keyring.nix @@ -0,0 +1,51 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.gnome-keyring; + +in { + meta.maintainers = [ maintainers.rycee ]; + + options = { + services.gnome-keyring = { + enable = mkEnableOption "GNOME Keyring"; + + components = mkOption { + type = types.listOf (types.enum [ "pkcs11" "secrets" "ssh" ]); + default = [ ]; + description = '' + The GNOME keyring components to start. If empty then the + default set of components will be started. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.gnome-keyring" pkgs + lib.platforms.linux) + ]; + + systemd.user.services.gnome-keyring = { + Unit = { + Description = "GNOME Keyring"; + PartOf = [ "graphical-session-pre.target" ]; + }; + + Service = { + ExecStart = let + args = concatStringsSep " " ([ "--start" "--foreground" ] + ++ optional (cfg.components != [ ]) + ("--components=" + concatStringsSep "," cfg.components)); + in "${pkgs.gnome.gnome-keyring}/bin/gnome-keyring-daemon ${args}"; + Restart = "on-abort"; + }; + + Install = { WantedBy = [ "graphical-session-pre.target" ]; }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/gpg-agent.nix b/infra/libkookie/home-manager-stable/modules/services/gpg-agent.nix new file mode 100644 index 00000000000..21303ee8e5d --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/gpg-agent.nix @@ -0,0 +1,335 @@ +{ config, options, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.gpg-agent; + gpgPkg = config.programs.gpg.package; + + homedir = config.programs.gpg.homedir; + + gpgInitStr = '' + GPG_TTY="$(tty)" + export GPG_TTY + '' + optionalString cfg.enableSshSupport + "${gpgPkg}/bin/gpg-connect-agent updatestartuptty /bye > /dev/null"; + + # mimic `gpgconf` output for use in `systemd` unit definitions. + # we cannot use `gpgconf` directly because it heavily depends on system + # state, but we need the values at build time. original: + # https://github.com/gpg/gnupg/blob/c6702d77d936b3e9d91b34d8fdee9599ab94ee1b/common/homedir.c#L672-L681 + gpgconf = dir: + let + hash = + substring 0 24 (hexStringToBase32 (builtins.hashString "sha1" homedir)); + in if homedir == options.programs.gpg.homedir.default then + "%t/gnupg/${dir}" + else + "%t/gnupg/d.${hash}/${dir}"; + + # Act like `xxd -r -p | base32` but with z-base-32 alphabet and no trailing padding. + # Written in Nix for purity. + hexStringToBase32 = let + mod = a: b: a - a / b * b; + pow2 = elemAt [ 1 2 4 8 16 32 64 128 256 ]; + splitChars = s: init (tail (splitString "" s)); + + base32Alphabet = splitChars "ybndrfg8ejkmcpqxot1uwisza345h769"; + hexToIntTable = listToAttrs (genList (x: { + name = toLower (toHexString x); + value = x; + }) 16); + + initState = { + ret = ""; + buf = 0; + bufBits = 0; + }; + go = { ret, buf, bufBits }: + hex: + let + buf' = buf * pow2 4 + hexToIntTable.${hex}; + bufBits' = bufBits + 4; + extraBits = bufBits' - 5; + in if bufBits >= 5 then { + ret = ret + elemAt base32Alphabet (buf' / pow2 extraBits); + buf = mod buf' (pow2 extraBits); + bufBits = bufBits' - 5; + } else { + ret = ret; + buf = buf'; + bufBits = bufBits'; + }; + in hexString: (foldl' go initState (splitChars hexString)).ret; + +in { + meta.maintainers = [ maintainers.rycee ]; + + options = { + services.gpg-agent = { + enable = mkEnableOption "GnuPG private key agent"; + + defaultCacheTtl = mkOption { + type = types.nullOr types.int; + default = null; + description = '' + Set the time a cache entry is valid to the given number of + seconds. + ''; + }; + + defaultCacheTtlSsh = mkOption { + type = types.nullOr types.int; + default = null; + description = '' + Set the time a cache entry used for SSH keys is valid to the + given number of seconds. + ''; + }; + + maxCacheTtl = mkOption { + type = types.nullOr types.int; + default = null; + description = '' + Set the maximum time a cache entry is valid to n seconds. After this + time a cache entry will be expired even if it has been accessed + recently or has been set using gpg-preset-passphrase. The default is + 2 hours (7200 seconds). + ''; + }; + + maxCacheTtlSsh = mkOption { + type = types.nullOr types.int; + default = null; + description = '' + Set the maximum time a cache entry used for SSH keys is valid to n + seconds. After this time a cache entry will be expired even if it has + been accessed recently or has been set using gpg-preset-passphrase. + The default is 2 hours (7200 seconds). + ''; + }; + + enableSshSupport = mkOption { + type = types.bool; + default = false; + description = '' + Whether to use the GnuPG key agent for SSH keys. + ''; + }; + + sshKeys = mkOption { + type = types.nullOr (types.listOf types.str); + default = null; + description = '' + Which GPG keys (by keygrip) to expose as SSH keys. + ''; + }; + + enableExtraSocket = mkOption { + type = types.bool; + default = false; + description = '' + Whether to enable extra socket of the GnuPG key agent (useful for GPG + Agent forwarding). + ''; + }; + + verbose = mkOption { + type = types.bool; + default = false; + description = '' + Whether to produce verbose output. + ''; + }; + + grabKeyboardAndMouse = mkOption { + type = types.bool; + default = true; + description = '' + Tell the pinentry to grab the keyboard and mouse. This + option should in general be used to avoid X-sniffing + attacks. When disabled, this option passes + setting to gpg-agent. + ''; + }; + + enableScDaemon = mkOption { + type = types.bool; + default = true; + description = '' + Make use of the scdaemon tool. This option has the effect of + enabling the ability to do smartcard operations. When + disabled, this option passes + setting to gpg-agent. + ''; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + example = '' + allow-emacs-pinentry + allow-loopback-pinentry + ''; + description = '' + Extra configuration lines to append to the gpg-agent + configuration file. + ''; + }; + + pinentryFlavor = mkOption { + type = types.nullOr (types.enum pkgs.pinentry.flavors); + example = "gnome3"; + default = "gtk2"; + description = '' + Which pinentry interface to use. If not + null, it sets + in + gpg-agent.conf. Beware that + pinentry-gnome3 may not work on non-Gnome + systems. You can fix it by adding the following to your + system configuration: + + services.dbus.packages = [ pkgs.gcr ]; + + For this reason, the default is gtk2 for + now. + ''; + }; + + enableBashIntegration = mkEnableOption "Bash integration" // { + default = true; + }; + + enableZshIntegration = mkEnableOption "Zsh integration" // { + default = true; + }; + + enableFishIntegration = mkEnableOption "Fish integration" // { + default = true; + }; + }; + }; + + config = mkIf cfg.enable (mkMerge [ + { + home.file."${homedir}/gpg-agent.conf".text = concatStringsSep "\n" + (optional (cfg.enableSshSupport) "enable-ssh-support" + ++ optional (!cfg.grabKeyboardAndMouse) "no-grab" + ++ optional (!cfg.enableScDaemon) "disable-scdaemon" + ++ optional (cfg.defaultCacheTtl != null) + "default-cache-ttl ${toString cfg.defaultCacheTtl}" + ++ optional (cfg.defaultCacheTtlSsh != null) + "default-cache-ttl-ssh ${toString cfg.defaultCacheTtlSsh}" + ++ optional (cfg.maxCacheTtl != null) + "max-cache-ttl ${toString cfg.maxCacheTtl}" + ++ optional (cfg.maxCacheTtlSsh != null) + "max-cache-ttl-ssh ${toString cfg.maxCacheTtlSsh}" + ++ optional (cfg.pinentryFlavor != null) + "pinentry-program ${pkgs.pinentry.${cfg.pinentryFlavor}}/bin/pinentry" + ++ [ cfg.extraConfig ]); + + home.sessionVariablesExtra = optionalString cfg.enableSshSupport '' + if [[ -z "$SSH_AUTH_SOCK" ]]; then + export SSH_AUTH_SOCK="$(${gpgPkg}/bin/gpgconf --list-dirs agent-ssh-socket)" + fi + ''; + + programs.bash.initExtra = mkIf cfg.enableBashIntegration gpgInitStr; + programs.zsh.initExtra = mkIf cfg.enableZshIntegration gpgInitStr; + programs.fish.interactiveShellInit = mkIf cfg.enableFishIntegration '' + set -gx GPG_TTY (tty) + ''; + } + + (mkIf (cfg.sshKeys != null) { + # Trailing newlines are important + home.file."${homedir}/sshcontrol".text = concatMapStrings (s: '' + ${s} + '') cfg.sshKeys; + }) + + # The systemd units below are direct translations of the + # descriptions in the + # + # ${gpgPkg}/share/doc/gnupg/examples/systemd-user + # + # directory. + { + systemd.user.services.gpg-agent = { + Unit = { + Description = "GnuPG cryptographic agent and passphrase cache"; + Documentation = "man:gpg-agent(1)"; + Requires = "gpg-agent.socket"; + After = "gpg-agent.socket"; + # This is a socket-activated service: + RefuseManualStart = true; + }; + + Service = { + ExecStart = "${gpgPkg}/bin/gpg-agent --supervised" + + optionalString cfg.verbose " --verbose"; + ExecReload = "${gpgPkg}/bin/gpgconf --reload gpg-agent"; + Environment = "GNUPGHOME=${homedir}"; + }; + }; + + systemd.user.sockets.gpg-agent = { + Unit = { + Description = "GnuPG cryptographic agent and passphrase cache"; + Documentation = "man:gpg-agent(1)"; + }; + + Socket = { + ListenStream = gpgconf "S.gpg-agent"; + FileDescriptorName = "std"; + SocketMode = "0600"; + DirectoryMode = "0700"; + }; + + Install = { WantedBy = [ "sockets.target" ]; }; + }; + } + + (mkIf cfg.enableSshSupport { + systemd.user.sockets.gpg-agent-ssh = { + Unit = { + Description = "GnuPG cryptographic agent (ssh-agent emulation)"; + Documentation = + "man:gpg-agent(1) man:ssh-add(1) man:ssh-agent(1) man:ssh(1)"; + }; + + Socket = { + ListenStream = gpgconf "S.gpg-agent.ssh"; + FileDescriptorName = "ssh"; + Service = "gpg-agent.service"; + SocketMode = "0600"; + DirectoryMode = "0700"; + }; + + Install = { WantedBy = [ "sockets.target" ]; }; + }; + }) + + (mkIf cfg.enableExtraSocket { + systemd.user.sockets.gpg-agent-extra = { + Unit = { + Description = + "GnuPG cryptographic agent and passphrase cache (restricted)"; + Documentation = "man:gpg-agent(1) man:ssh(1)"; + }; + + Socket = { + ListenStream = gpgconf "S.gpg-agent.extra"; + FileDescriptorName = "extra"; + Service = "gpg-agent.service"; + SocketMode = "0600"; + DirectoryMode = "0700"; + }; + + Install = { WantedBy = [ "sockets.target" ]; }; + }; + }) + ]); +} diff --git a/infra/libkookie/home-manager-stable/modules/services/grobi.nix b/infra/libkookie/home-manager-stable/modules/services/grobi.nix new file mode 100644 index 00000000000..d90b7244a9d --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/grobi.nix @@ -0,0 +1,102 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.grobi; + + eitherStrBoolIntList = with types; + either str (either bool (either int (listOf str))); + +in { + meta.maintainers = [ maintainers.mbrgm ]; + + options = { + services.grobi = { + enable = mkEnableOption "the grobi display setup daemon"; + + executeAfter = mkOption { + type = with types; listOf str; + default = [ ]; + example = [ "setxkbmap dvorak" ]; + description = '' + Commands to be run after an output configuration was + changed. The Nix value declared here will be translated to + JSON and written to the key + in $XDG_CONFIG_HOME/grobi.conf. + ''; + }; + + rules = mkOption { + type = with types; listOf (attrsOf eitherStrBoolIntList); + default = [ ]; + example = literalExpression '' + [ + { + name = "Home"; + outputs_connected = [ "DP-2" ]; + configure_single = "DP-2"; + primary = true; + atomic = true; + execute_after = [ + "${pkgs.xorg.xrandr}/bin/xrandr --dpi 96" + "${pkgs.xmonad-with-packages}/bin/xmonad --restart"; + ]; + } + { + name = "Mobile"; + outputs_disconnected = [ "DP-2" ]; + configure_single = "eDP-1"; + primary = true; + atomic = true; + execute_after = [ + "${pkgs.xorg.xrandr}/bin/xrandr --dpi 120" + "${pkgs.xmonad-with-packages}/bin/xmonad --restart"; + ]; + } + ] + ''; + description = '' + These are the rules grobi tries to match to the current + output configuration. The rules are evaluated top to bottom, + the first matching rule is applied and processing stops. See + + for more information. The Nix value declared here will be + translated to JSON and written to the + key in $XDG_CONFIG_HOME/grobi.conf. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.grobi" pkgs + lib.platforms.linux) + ]; + + systemd.user.services.grobi = { + Unit = { + Description = "grobi display auto config daemon"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + }; + + Service = { + Type = "simple"; + ExecStart = "${pkgs.grobi}/bin/grobi watch -v"; + Restart = "always"; + RestartSec = "2s"; + Environment = "PATH=${pkgs.xorg.xrandr}/bin:${pkgs.bash}/bin"; + }; + + Install = { WantedBy = [ "graphical-session.target" ]; }; + }; + + xdg.configFile."grobi.conf".text = builtins.toJSON { + execute_after = cfg.executeAfter; + rules = cfg.rules; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/gromit-mpx.nix b/infra/libkookie/home-manager-stable/modules/services/gromit-mpx.nix new file mode 100644 index 00000000000..7a85cf7647a --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/gromit-mpx.nix @@ -0,0 +1,234 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.gromit-mpx; + + # Select the appropriate hot key: + hotkey = if isInt cfg.hotKey then + "--keycode ${toString cfg.hotKey}" + else if cfg.hotKey != null then + "--key ${cfg.hotKey}" + else + "--key none"; + + # Select the appropriate undo key: + undokey = if isInt cfg.undoKey then + "--undo-keycode ${toString cfg.undoKey}" + else if cfg.undoKey != null then + "--undo-key ${cfg.undoKey}" + else + "--undo-key none"; + + # The command line to send to gromit-mpx: + commandArgs = concatStringsSep " " [ hotkey undokey ]; + + # Gromit reads and writes from this file to store it's run time + # state. That will break our config so we set it manually which, + # thanks to the read-only Nix store, prevents Gromit from writing to + # it. + keyFile = generators.toINI { } { + General.ShowIntroOnStartup = false; + Drawing.Opacity = cfg.opacity; + }; + + # Allowed modifiers: + modsAndButtons = [ "1" "2" "3" "4" "5" "SHIFT" "CONTROL" "ALT" "META" ]; + + # Create a string of tool attributes: + toolAttrs = tool: + concatStringsSep " " ([ "size=${toString tool.size}" ] + ++ optional (tool.type != "eraser") ''color="${tool.color}"'' + ++ optional (tool.arrowSize != null) + "arrowsize=${toString tool.arrowSize}"); + + # Optional tool modifier string: + toolMod = tool: + if tool.modifiers != [ ] then + "[" + concatStringsSep ", " tool.modifiers + "]" + else + ""; + + # A single tool configuration: + toolToCfg = n: tool: '' + "tool-${toString n}" = ${toUpper tool.type} (${toolAttrs tool}); + "${tool.device}"${toolMod tool} = "tool-${toString n}"; + ''; + + # Per-tool options: + toolOptions = { + options = { + device = mkOption { + type = types.str; + example = "default"; + description = '' + Use this tool with the given xinput device. The device with + the name default works with any input. + ''; + }; + + type = mkOption { + type = types.enum [ "pen" "eraser" "recolor" ]; + default = "pen"; + example = "eraser"; + description = "Which type of tool this is."; + }; + + color = mkOption { + type = types.str; + default = "red"; + example = "#ff00ff"; + description = "The stroke (or recolor) color of the tool."; + }; + + size = mkOption { + type = types.ints.positive; + default = 5; + example = 3; + description = "The tool size."; + }; + + arrowSize = mkOption { + type = types.nullOr types.ints.positive; + default = null; + example = 2; + description = '' + If not null, automatically draw an arrow + at the end of a stroke with the given size. + ''; + }; + + modifiers = mkOption { + type = types.listOf (types.enum modsAndButtons); + default = [ ]; + example = [ "SHIFT" ]; + description = '' + Only activate this tool if the given modifiers are also active. + ''; + }; + }; + }; + +in { + meta.maintainers = [ maintainers.pjones ]; + + options.services.gromit-mpx = { + enable = mkEnableOption "Gromit-MPX annotation tool"; + + package = mkOption { + type = types.package; + default = pkgs.gromit-mpx; + defaultText = "pkgs.gromit-mpx"; + description = "The gromit-mpx package to use."; + }; + + hotKey = mkOption { + type = with types; nullOr (either str ints.positive); + default = "F9"; + example = "Insert"; + description = '' + A keysym or raw keycode that toggles the activation state of + gromit-mpx. Set to null to disable the + hotkey in which case you'll have to activate gromit-mpx + manually using the command line. + ''; + }; + + undoKey = mkOption { + type = with types; nullOr (either str ints.positive); + default = "F10"; + description = '' + A keysym or raw keycode that causes gromit-mpx to undo the + last stroke. Use this key along with the shift key to redo an + undone stoke. Set to null to disable the + undo hotkey. + ''; + }; + + opacity = mkOption { + type = types.addCheck types.float (f: f >= 0.0 && f <= 1.0) // { + description = "float between 0.0 and 1.0 (inclusive)"; + }; + default = 0.75; + example = 1.0; + description = "Opacity of the drawing overlay."; + }; + + tools = mkOption { + type = types.listOf (types.submodule toolOptions); + default = [ + { + device = "default"; + type = "pen"; + size = 5; + color = "red"; + } + { + device = "default"; + type = "pen"; + size = 5; + color = "blue"; + modifiers = [ "SHIFT" ]; + } + { + device = "default"; + type = "pen"; + size = 5; + color = "yellow"; + modifiers = [ "CONTROL" ]; + } + { + device = "default"; + type = "pen"; + size = 6; + color = "green"; + arrowSize = 1; + modifiers = [ "2" ]; + } + { + device = "default"; + type = "eraser"; + size = 75; + modifiers = [ "3" ]; + } + ]; + description = '' + Tool definitions for gromit-mpx to use. + ''; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.gromit-mpx" pkgs + lib.platforms.linux) + ]; + + xdg.configFile."gromit-mpx.ini".text = keyFile; + xdg.configFile."gromit-mpx.cfg".text = + concatStringsSep "\n" (imap1 toolToCfg cfg.tools); + + home.packages = [ cfg.package ]; + + systemd.user.services.gromit-mpx = { + Unit = { + Description = "Gromit-MPX"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + X-Restart-Triggers = [ + "${config.xdg.configFile."gromit-mpx.cfg".source}" + "${config.xdg.configFile."gromit-mpx.ini".source}" + ]; + }; + + Service = { + Type = "simple"; + ExecStart = "${cfg.package}/bin/gromit-mpx ${commandArgs}"; + }; + + Install = { WantedBy = [ "graphical-session.target" ]; }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/home-manager-auto-upgrade.nix b/infra/libkookie/home-manager-stable/modules/services/home-manager-auto-upgrade.nix new file mode 100644 index 00000000000..2f975ef1bae --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/home-manager-auto-upgrade.nix @@ -0,0 +1,69 @@ +{ config, lib, pkgs, ... }: + +let + + cfg = config.services.home-manager.autoUpgrade; + + homeManagerPackage = pkgs.callPackage ../../home-manager { + path = config.programs.home-manager.path; + }; + +in { + meta.maintainers = [ lib.hm.maintainers.pinage404 ]; + + options = { + services.home-manager.autoUpgrade = { + enable = lib.mkEnableOption '' + the Home Manager upgrade service that periodically updates your Nix + channels before running home-manager switch''; + + frequency = lib.mkOption { + type = lib.types.str; + example = "weekly"; + description = '' + The interval at which the Home Manager auto upgrade is run. + This value is passed to the systemd timer configuration + as the OnCalendar option. + The format is described in + + systemd.time + 7 + . + ''; + }; + }; + }; + + config = lib.mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.home-manager.autoUpgrade" pkgs + lib.platforms.linux) + ]; + + systemd.user = { + timers.home-manager-auto-upgrade = { + Unit.Description = "Home Manager upgrade timer"; + + Install.WantedBy = [ "timers.target" ]; + + Timer = { + OnCalendar = cfg.frequency; + Unit = "home-manager-auto-upgrade.service"; + Persistent = true; + }; + }; + + services.home-manager-auto-upgrade = { + Unit.Description = "Home Manager upgrade"; + + Service.ExecStart = toString + (pkgs.writeShellScript "home-manager-auto-upgrade" '' + echo "Update Nix's channels" + ${pkgs.nix}/bin/nix-channel --update + echo "Upgrade Home Manager" + ${homeManagerPackage}/bin/home-manager switch + ''); + }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/hound.nix b/infra/libkookie/home-manager-stable/modules/services/hound.nix new file mode 100644 index 00000000000..ff18a381ad8 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/hound.nix @@ -0,0 +1,81 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.hound; + + jsonFormat = pkgs.formats.json { }; + + configFile = jsonFormat.generate "hound-config.json" { + max-concurrent-indexers = cfg.maxConcurrentIndexers; + dbpath = cfg.databasePath; + repos = cfg.repositories; + health-check-url = "/healthz"; + }; + + houndOptions = [ "--addr ${cfg.listenAddress}" "--conf ${configFile}" ]; + +in { + meta.maintainers = [ maintainers.adisbladis ]; + + options.services.hound = { + enable = mkEnableOption "hound"; + + maxConcurrentIndexers = mkOption { + type = types.ints.positive; + default = 2; + description = "Limit the amount of concurrent indexers."; + }; + + databasePath = mkOption { + type = types.path; + default = "${config.xdg.dataHome}/hound"; + defaultText = "$XDG_DATA_HOME/hound"; + description = "The Hound database path."; + }; + + listenAddress = mkOption { + type = types.str; + default = "localhost:6080"; + description = "Listen address of the Hound daemon."; + }; + + repositories = mkOption { + type = types.attrsOf jsonFormat.type; + default = { }; + example = literalExpression '' + { + SomeGitRepo = { + url = "https://www.github.com/YourOrganization/RepoOne.git"; + ms-between-poll = 10000; + exclude-dot-files = true; + }; + } + ''; + description = "The repository configuration."; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.hound" pkgs + lib.platforms.linux) + ]; + + home.packages = [ pkgs.hound ]; + + systemd.user.services.hound = { + Unit = { Description = "Hound source code search engine"; }; + + Install = { WantedBy = [ "default.target" ]; }; + + Service = { + Environment = "PATH=${makeBinPath [ pkgs.mercurial pkgs.git ]}"; + ExecStart = + "${pkgs.hound}/bin/houndd ${concatStringsSep " " houndOptions}"; + }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/imapnotify-accounts.nix b/infra/libkookie/home-manager-stable/modules/services/imapnotify-accounts.nix new file mode 100644 index 00000000000..5d8418310ad --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/imapnotify-accounts.nix @@ -0,0 +1,40 @@ +{ lib, ... }: + +with lib; + +{ + options.imapnotify = { + enable = mkEnableOption "imapnotify"; + + onNotify = mkOption { + type = with types; either str (attrsOf str); + default = ""; + example = "\${pkgs.isync}/bin/mbsync test-%s"; + description = "Shell commands to run on any event."; + }; + + onNotifyPost = mkOption { + type = with types; either str (attrsOf str); + default = ""; + example = { + mail = + "\${pkgs.notmuch}/bin/notmuch new && \${pkgs.libnotify}/bin/notify-send 'New mail arrived'"; + }; + description = "Shell commands to run after onNotify event."; + }; + + boxes = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "Inbox" "[Gmail]/MyLabel" ]; + description = "IMAP folders to watch."; + }; + + extraConfig = mkOption { + type = with types; attrsOf (oneOf [ bool int str ]); + default = { }; + example = { wait = 10; }; + description = "Additional configuration to add for this account."; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/imapnotify.nix b/infra/libkookie/home-manager-stable/modules/services/imapnotify.nix new file mode 100644 index 00000000000..6a464ec8c58 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/imapnotify.nix @@ -0,0 +1,92 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.imapnotify; + + safeName = lib.replaceChars [ "@" ":" "\\" "[" "]" ] [ "-" "-" "-" "" "" ]; + + imapnotifyAccounts = + filter (a: a.imapnotify.enable) (attrValues config.accounts.email.accounts); + + genAccountUnit = account: + let name = safeName account.name; + in { + name = "imapnotify-${name}"; + value = { + Unit = { Description = "imapnotify for ${name}"; }; + + Service = { + ExecStart = "${pkgs.goimapnotify}/bin/goimapnotify -conf ${ + genAccountConfig account + }"; + Restart = "always"; + RestartSec = 30; + Type = "simple"; + } // optionalAttrs account.notmuch.enable { + Environment = + "NOTMUCH_CONFIG=${config.xdg.configHome}/notmuch/default/config"; + }; + + Install = { WantedBy = [ "default.target" ]; }; + }; + }; + + genAccountConfig = account: + pkgs.writeText "imapnotify-${safeName account.name}-config.json" (let + port = if account.imap.port != null then + account.imap.port + else if account.imap.tls.enable then + 993 + else + 143; + + toJSON = builtins.toJSON; + in toJSON ({ + inherit (account.imap) host; + inherit port; + tls = account.imap.tls.enable; + username = account.userName; + passwordCmd = + lib.concatMapStringsSep " " lib.escapeShellArg account.passwordCommand; + inherit (account.imapnotify) boxes; + } // optionalAttrs (account.imapnotify.onNotify != "") { + onNewMail = account.imapnotify.onNotify; + } // optionalAttrs (account.imapnotify.onNotifyPost != "") { + onNewMailPost = account.imapnotify.onNotifyPost; + } // account.imapnotify.extraConfig)); + +in { + meta.maintainers = [ maintainers.nickhu ]; + + options = { + services.imapnotify = { enable = mkEnableOption "imapnotify"; }; + + accounts.email.accounts = mkOption { + type = with types; attrsOf (submodule (import ./imapnotify-accounts.nix)); + }; + }; + + config = mkIf cfg.enable { + assertions = let + checkAccounts = pred: msg: + let badAccounts = filter pred imapnotifyAccounts; + in { + assertion = badAccounts == [ ]; + message = "imapnotify: Missing ${msg} for accounts: " + + concatMapStringsSep ", " (a: a.name) badAccounts; + }; + in [ + (lib.hm.assertions.assertPlatform "services.imapnotify" pkgs + lib.platforms.linux) + (checkAccounts (a: a.maildir == null) "maildir configuration") + (checkAccounts (a: a.imap == null) "IMAP configuration") + (checkAccounts (a: a.passwordCommand == null) "password command") + (checkAccounts (a: a.userName == null) "username") + ]; + + systemd.user.services = listToAttrs (map genAccountUnit imapnotifyAccounts); + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/kanshi.nix b/infra/libkookie/home-manager-stable/modules/services/kanshi.nix new file mode 100644 index 00000000000..3d4451e9e9f --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/kanshi.nix @@ -0,0 +1,221 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.kanshi; + + outputModule = types.submodule { + options = { + + criteria = mkOption { + type = types.str; + description = '' + The criteria can either be an output name, an output description or "*". + The latter can be used to match any output. + + On + + sway + 1 + , + output names and descriptions can be obtained via + swaymsg -t get_outputs. + ''; + }; + + status = mkOption { + type = types.nullOr (types.enum [ "enable" "disable" ]); + default = null; + description = '' + Enables or disables the specified output. + ''; + }; + + mode = mkOption { + type = types.nullOr types.str; + default = null; + example = "1920x1080@60Hz"; + description = '' + <width>x<height>[@<rate>[Hz]] + + Configures the specified output to use the specified mode. + Modes are a combination of width and height (in pixels) and + a refresh rate (in Hz) that your display can be configured to use. + ''; + }; + + position = mkOption { + type = types.nullOr types.str; + default = null; + example = "1600,0"; + description = '' + <x>,<y> + + Places the output at the specified position in the global coordinates + space. + ''; + }; + + scale = mkOption { + type = types.nullOr types.float; + default = null; + example = 2; + description = '' + Scales the output by the specified scale factor. + ''; + }; + + transform = mkOption { + type = types.nullOr (types.enum [ + "normal" + "90" + "180" + "270" + "flipped" + "flipped-90" + "flipped-180" + "flipped-270" + ]); + default = null; + description = '' + Sets the output transform. + ''; + }; + }; + }; + + outputStr = { criteria, status, mode, position, scale, transform, ... }: + ''output "${criteria}"'' + optionalString (status != null) " ${status}" + + optionalString (mode != null) " mode ${mode}" + + optionalString (position != null) " position ${position}" + + optionalString (scale != null) " scale ${toString scale}" + + optionalString (transform != null) " transform ${transform}"; + + profileModule = types.submodule { + options = { + outputs = mkOption { + type = types.listOf outputModule; + default = [ ]; + description = '' + Outputs configuration. + ''; + }; + + exec = mkOption { + type = with types; coercedTo str singleton (listOf str); + default = [ ]; + example = + "[ \${pkg.sway}/bin/swaymsg workspace 1, move workspace to eDP-1 ]"; + description = '' + Commands executed after the profile is succesfully applied. + Note that if you provide multiple commands, they will be + executed asynchronously with no guaranteed ordering. + ''; + }; + }; + }; + + profileStr = name: + { outputs, exec, ... }: '' + profile ${name} { + ${ + concatStringsSep "\n " + (map outputStr outputs ++ map (cmd: "exec ${cmd}") exec) + } + } + ''; +in { + + meta.maintainers = [ hm.maintainers.nurelin ]; + + options.services.kanshi = { + enable = mkEnableOption + "kanshi, a Wayland daemon that automatically configures outputs"; + + package = mkOption { + type = types.package; + default = pkgs.kanshi; + defaultText = literalExpression "pkgs.kanshi"; + description = '' + kanshi derivation to use. + ''; + }; + + profiles = mkOption { + type = types.attrsOf profileModule; + default = { }; + description = '' + List of profiles. + ''; + example = literalExpression '' + undocked = { + outputs = [ + { + criteria = "eDP-1"; + } + ]; + }; + docked = { + outputs = [ + { + criteria = "eDP-1"; + } + { + criteria = "Some Company ASDF 4242"; + transform = "90"; + } + ]; + }; + ''; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Extra configuration lines to append to the kanshi + configuration file. + ''; + }; + + systemdTarget = mkOption { + type = types.str; + default = "sway-session.target"; + description = '' + Systemd target to bind to. + ''; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.kanshi" pkgs + lib.platforms.linux) + ]; + + xdg.configFile."kanshi/config".text = '' + ${concatStringsSep "\n" (mapAttrsToList profileStr cfg.profiles)} + ${cfg.extraConfig} + ''; + + systemd.user.services.kanshi = { + Unit = { + Description = "Dynamic output configuration"; + Documentation = "man:kanshi(1)"; + PartOf = cfg.systemdTarget; + Requires = cfg.systemdTarget; + After = cfg.systemdTarget; + }; + + Service = { + Type = "simple"; + ExecStart = "${cfg.package}/bin/kanshi"; + Restart = "always"; + }; + + Install = { WantedBy = [ cfg.systemdTarget ]; }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/kbfs.nix b/infra/libkookie/home-manager-stable/modules/services/kbfs.nix new file mode 100644 index 00000000000..4f1bfd8bfb4 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/kbfs.nix @@ -0,0 +1,64 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.kbfs; + +in { + options = { + services.kbfs = { + enable = mkEnableOption "Keybase File System"; + + mountPoint = mkOption { + type = types.str; + default = "keybase"; + description = '' + Mount point for the Keybase filesystem, relative to + HOME. + ''; + }; + + extraFlags = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "-label kbfs" "-mount-type normal" ]; + description = '' + Additional flags to pass to the Keybase filesystem on launch. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.kbfs" pkgs + lib.platforms.linux) + ]; + + systemd.user.services.kbfs = { + Unit = { + Description = "Keybase File System"; + Requires = [ "keybase.service" ]; + After = [ "keybase.service" ]; + }; + + Service = let mountPoint = ''"%h/${cfg.mountPoint}"''; + in { + Environment = "PATH=/run/wrappers/bin KEYBASE_SYSTEMD=1"; + ExecStartPre = "${pkgs.coreutils}/bin/mkdir -p ${mountPoint}"; + ExecStart = + "${pkgs.kbfs}/bin/kbfsfuse ${toString cfg.extraFlags} ${mountPoint}"; + ExecStopPost = "/run/wrappers/bin/fusermount -u ${mountPoint}"; + Restart = "on-failure"; + PrivateTmp = true; + }; + + Install.WantedBy = [ "default.target" ]; + }; + + home.packages = [ pkgs.kbfs ]; + services.keybase.enable = true; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/kdeconnect.nix b/infra/libkookie/home-manager-stable/modules/services/kdeconnect.nix new file mode 100644 index 00000000000..82de1f0eb7c --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/kdeconnect.nix @@ -0,0 +1,72 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.kdeconnect; + package = pkgs.kdeconnect; + +in { + meta.maintainers = [ maintainers.adisbladis ]; + + options = { + services.kdeconnect = { + enable = mkEnableOption "KDE connect"; + + indicator = mkOption { + type = types.bool; + default = false; + description = "Whether to enable kdeconnect-indicator service."; + }; + + }; + }; + + config = mkMerge [ + (mkIf cfg.enable { + home.packages = [ package ]; + + systemd.user.services.kdeconnect = { + Unit = { + Description = + "Adds communication between your desktop and your smartphone"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + }; + + Install = { WantedBy = [ "graphical-session.target" ]; }; + + Service = { + Environment = "PATH=${config.home.profileDirectory}/bin"; + ExecStart = "${package}/libexec/kdeconnectd"; + Restart = "on-abort"; + }; + }; + }) + + (mkIf cfg.indicator { + systemd.user.services.kdeconnect-indicator = { + Unit = { + Description = "kdeconnect-indicator"; + After = [ + "graphical-session-pre.target" + "polybar.service" + "taffybar.service" + "stalonetray.service" + ]; + PartOf = [ "graphical-session.target" ]; + }; + + Install = { WantedBy = [ "graphical-session.target" ]; }; + + Service = { + Environment = "PATH=${config.home.profileDirectory}/bin"; + ExecStart = "${package}/bin/kdeconnect-indicator"; + Restart = "on-abort"; + }; + }; + }) + + ]; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/keepassx.nix b/infra/libkookie/home-manager-stable/modules/services/keepassx.nix new file mode 100644 index 00000000000..dc37066e20c --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/keepassx.nix @@ -0,0 +1,27 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + meta.maintainers = [ maintainers.rycee ]; + + options = { + services.keepassx = { + enable = mkEnableOption "the KeePassX password manager"; + }; + }; + + config = mkIf config.services.keepassx.enable { + systemd.user.services.keepassx = { + Unit = { + Description = "KeePassX password manager"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + }; + + Install = { WantedBy = [ "graphical-session.target" ]; }; + + Service = { ExecStart = "${pkgs.keepassx}/bin/keepassx -min -lock"; }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/keybase.nix b/infra/libkookie/home-manager-stable/modules/services/keybase.nix new file mode 100644 index 00000000000..f6e40086620 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/keybase.nix @@ -0,0 +1,32 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.keybase; + +in { + options.services.keybase.enable = mkEnableOption "Keybase"; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.keybase" pkgs + lib.platforms.linux) + ]; + + home.packages = [ pkgs.keybase ]; + + systemd.user.services.keybase = { + Unit.Description = "Keybase service"; + + Service = { + ExecStart = "${pkgs.keybase}/bin/keybase service --auto-forked"; + Restart = "on-failure"; + PrivateTmp = true; + }; + + Install.WantedBy = [ "default.target" ]; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/keynav.nix b/infra/libkookie/home-manager-stable/modules/services/keynav.nix new file mode 100644 index 00000000000..d83252e53b6 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/keynav.nix @@ -0,0 +1,34 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.keynav; + +in { + options.services.keynav = { enable = mkEnableOption "keynav"; }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.keynav" pkgs + lib.platforms.linux) + ]; + + systemd.user.services.keynav = { + Unit = { + Description = "keynav"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + }; + + Service = { + ExecStart = "${pkgs.keynav}/bin/keynav"; + RestartSec = 3; + Restart = "always"; + }; + + Install = { WantedBy = [ "graphical-session.target" ]; }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/lieer.nix b/infra/libkookie/home-manager-stable/modules/services/lieer.nix new file mode 100644 index 00000000000..e5f3076169a --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/lieer.nix @@ -0,0 +1,67 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.lieer; + + syncAccounts = filter (a: a.lieer.enable && a.lieer.sync.enable) + (attrValues config.accounts.email.accounts); + + escapeUnitName = name: + let + good = upperChars ++ lowerChars ++ stringToCharacters "0123456789-_"; + subst = c: if any (x: x == c) good then c else "-"; + in stringAsChars subst name; + + serviceUnit = account: { + name = escapeUnitName "lieer-${account.name}"; + value = { + Unit = { + Description = "lieer Gmail synchronization for ${account.name}"; + ConditionPathExists = "${account.maildir.absPath}/.gmailieer.json"; + }; + + Service = { + Type = "oneshot"; + ExecStart = "${config.programs.lieer.package}/bin/gmi sync"; + WorkingDirectory = account.maildir.absPath; + Environment = + "NOTMUCH_CONFIG=${config.xdg.configHome}/notmuch/default/config"; + }; + }; + }; + + timerUnit = account: { + name = escapeUnitName "lieer-${account.name}"; + value = { + Unit = { + Description = "lieer Gmail synchronization for ${account.name}"; + }; + + Timer = { + OnCalendar = account.lieer.sync.frequency; + RandomizedDelaySec = 30; + }; + + Install = { WantedBy = [ "timers.target" ]; }; + }; + }; + +in { + meta.maintainers = [ maintainers.tadfisher ]; + + options.services.lieer.enable = + mkEnableOption "lieer Gmail synchronization service"; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.lieer" pkgs + lib.platforms.linux) + ]; + + programs.lieer.enable = true; + systemd.user.services = listToAttrs (map serviceUnit syncAccounts); + systemd.user.timers = listToAttrs (map timerUnit syncAccounts); + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/lorri.nix b/infra/libkookie/home-manager-stable/modules/services/lorri.nix new file mode 100644 index 00000000000..0a49cb54542 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/lorri.nix @@ -0,0 +1,65 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.lorri; + +in { + meta.maintainers = [ maintainers.gerschtli ]; + + options.services.lorri = { + enable = mkEnableOption "lorri build daemon"; + + package = mkOption { + type = types.package; + default = pkgs.lorri; + defaultText = literalExpression "pkgs.lorri"; + description = "Which lorri package to install."; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.lorri" pkgs + lib.platforms.linux) + ]; + + home.packages = [ cfg.package ]; + + systemd.user = { + services.lorri = { + Unit = { + Description = "lorri build daemon"; + Requires = "lorri.socket"; + After = "lorri.socket"; + RefuseManualStart = true; + }; + + Service = { + ExecStart = "${cfg.package}/bin/lorri daemon"; + PrivateTmp = true; + ProtectSystem = "strict"; + ProtectHome = "read-only"; + Restart = "on-failure"; + Environment = let + path = with pkgs; + makeSearchPath "bin" [ nix gitMinimal gnutar gzip ]; + in [ "PATH=${path}" ]; + }; + }; + + sockets.lorri = { + Unit = { Description = "Socket for lorri build daemon"; }; + + Socket = { + ListenStream = "%t/lorri/daemon.socket"; + RuntimeDirectory = "lorri"; + }; + + Install = { WantedBy = [ "sockets.target" ]; }; + }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/mako.nix b/infra/libkookie/home-manager-stable/modules/services/mako.nix new file mode 100644 index 00000000000..88068e0ba52 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/mako.nix @@ -0,0 +1,343 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.mako; + +in { + meta.maintainers = [ maintainers.onny ]; + + options = { + programs.mako = { + enable = mkEnableOption '' + Mako, lightweight notification daemon for Wayland + ''; + + package = mkOption { + type = types.package; + default = pkgs.mako; + defaultText = literalExpression "pkgs.mako"; + description = "The mako package to use."; + }; + + maxVisible = mkOption { + default = 5; + type = types.nullOr types.int; + description = '' + Set maximum number of visible notifications. Set -1 to show all. + ''; + }; + + sort = mkOption { + default = "-time"; + type = + types.nullOr (types.enum [ "+time" "-time" "+priority" "-priority" ]); + description = '' + Sorts incoming notifications by time and/or priority in ascending(+) + or descending(-) order. + ''; + }; + + output = mkOption { + default = null; + type = types.nullOr types.str; + description = '' + Show notifications on the specified output. If empty, notifications + will appear on the focused output. Requires the compositor to support + the Wayland protocol xdg-output-unstable-v1 version 2. + ''; + }; + + layer = mkOption { + default = "top"; + type = + types.nullOr (types.enum [ "background" "bottom" "top" "overlay" ]); + description = '' + Arrange mako at the specified layer, relative to normal windows. + Supported values are background, bottom, top, and overlay. Using + overlay will cause notifications to be displayed above fullscreen + windows, though this may also occur at top depending on your + compositor. + ''; + }; + + anchor = mkOption { + default = "top-right"; + type = types.nullOr (types.enum [ + "top-right" + "top-center" + "top-left" + "bottom-right" + "bottom-center" + "bottom-left" + "center" + ]); + description = '' + Show notifications at the specified position on the output. + Supported values are top-right, top-center, top-left, bottom-right, + bottom-center, bottom-left, and center. + ''; + }; + + font = mkOption { + default = "monospace 10"; + type = types.nullOr types.str; + description = '' + Font to use, in Pango format. + ''; + }; + + backgroundColor = mkOption { + default = "#285577FF"; + type = types.nullOr types.str; + description = '' + Set popup background color to a specific color, represented in hex + color code. + ''; + }; + + textColor = mkOption { + default = "#FFFFFFFF"; + type = types.nullOr types.str; + description = '' + Set popup text color to a specific color, represented in hex color + code. + ''; + }; + + width = mkOption { + default = 300; + type = types.nullOr types.int; + description = '' + Set width of notification popups in specified number of pixels. + ''; + }; + + height = mkOption { + default = 100; + type = types.nullOr types.int; + description = '' + Set maximum height of notification popups. Notifications whose text + takes up less space are shrunk to fit. + ''; + }; + + margin = mkOption { + default = "10"; + type = types.nullOr types.str; + description = '' + Set margin of each edge specified in pixels. Specify single value to + apply margin on all sides. Two comma-seperated values will set + vertical and horizontal edges seperately. Four comma-seperated will + give each edge a seperate value. + For example: 10,20,5 will set top margin to 10, left and right to 20 + and bottom to five. + ''; + }; + + padding = mkOption { + default = "5"; + type = types.nullOr types.str; + description = '' + Set padding of each edge specified in pixels. Specify single value to + apply margin on all sides. Two comma-seperated values will set + vertical and horizontal edges seperately. Four comma-seperated will + give each edge a seperate value. + For example: 10,20,5 will set top margin to 10, left and right to 20 + and bottom to five. + ''; + }; + + borderSize = mkOption { + default = 1; + type = types.nullOr types.int; + description = '' + Set popup border size to the specified number of pixels. + ''; + }; + + borderColor = mkOption { + default = "#4C7899FF"; + type = types.nullOr types.str; + description = '' + Set popup border color to a specific color, represented in hex color + code. + ''; + }; + + borderRadius = mkOption { + default = 0; + type = types.nullOr types.int; + description = '' + Set popup corner radius to the specified number of pixels. + ''; + }; + + progressColor = mkOption { + default = "over #5588AAFF"; + type = types.nullOr types.str; + description = '' + Set popup progress indicator color to a specific color, + represented in hex color code. To draw the progress + indicator on top of the background color, use the + over attribute. To replace the background + color, use the source attribute (this can + be useful when the notification is semi-transparent). + ''; + }; + + icons = mkOption { + default = true; + type = types.nullOr types.bool; + description = '' + Whether or not to show icons in notifications. + ''; + }; + + maxIconSize = mkOption { + default = 64; + type = types.nullOr types.int; + description = '' + Set maximum icon size to the specified number of pixels. + ''; + }; + + iconPath = mkOption { + default = null; + type = types.nullOr types.str; + description = '' + Paths to search for icons when a notification specifies a name + instead of a full path. Colon-delimited. This approximates the search + algorithm used by the XDG Icon Theme Specification, but does not + support any of the theme metadata. Therefore, if you want to search + parent themes, you'll need to add them to the path manually. + + The /usr/share/icons/hicolor and + /usr/share/pixmaps directories are + always searched. + ''; + }; + + markup = mkOption { + default = true; + type = types.nullOr types.bool; + description = '' + If 1, enable Pango markup. If 0, disable Pango markup. If enabled, + Pango markup will be interpreted in your format specifier and in the + body of notifications. + ''; + }; + + actions = mkOption { + default = true; + type = types.nullOr types.bool; + description = '' + Applications may request an action to be associated with activating a + notification. Disabling this will cause mako to ignore these requests. + ''; + }; + + format = mkOption { + default = "%s\\n%b"; + type = types.nullOr types.str; + description = '' + Set notification format string to format. See FORMAT SPECIFIERS for + more information. To change this for grouped notifications, set it + within a grouped criteria. + ''; + }; + + defaultTimeout = mkOption { + default = 0; + type = types.nullOr types.int; + description = '' + Set the default timeout to timeout in milliseconds. To disable the + timeout, set it to zero. + ''; + }; + + ignoreTimeout = mkOption { + default = false; + type = types.nullOr types.bool; + description = '' + If set, mako will ignore the expire timeout sent by notifications + and use the one provided by default-timeout instead. + ''; + }; + + groupBy = mkOption { + default = null; + type = types.nullOr types.str; + description = '' + A comma-separated list of criteria fields that will be compared to + other visible notifications to determine if this one should form a + group with them. All listed criteria must be exactly equal for two + notifications to group. + ''; + }; + + extraConfig = mkOption { + default = ""; + type = types.lines; + example = literalExpression '' + [urgency=low] + border-color=#b8bb26 + ''; + description = "Additional configuration."; + }; + }; + }; + + config = let + boolToString = v: if v then "true" else "false"; + optionalBoolean = name: val: + lib.optionalString (val != null) "${name}=${boolToString val}"; + optionalInteger = name: val: + lib.optionalString (val != null) "${name}=${toString val}"; + optionalString = name: val: + lib.optionalString (val != null) "${name}=${val}"; + in mkIf cfg.enable { + assertions = + [ (hm.assertions.assertPlatform "services.mako" pkgs platforms.linux) ]; + + home.packages = [ cfg.package ]; + + xdg.configFile."mako/config" = { + onChange = '' + ${cfg.package}/bin/makoctl reload || true + ''; + text = '' + ${optionalInteger "max-visible" cfg.maxVisible} + ${optionalString "sort" cfg.sort} + ${optionalString "output" cfg.output} + ${optionalString "layer" cfg.layer} + ${optionalString "anchor" cfg.anchor} + + ${optionalString "font" cfg.font} + ${optionalString "background-color" cfg.backgroundColor} + ${optionalString "text-color" cfg.textColor} + ${optionalInteger "width" cfg.width} + ${optionalInteger "height" cfg.height} + ${optionalString "margin" cfg.margin} + ${optionalString "padding" cfg.padding} + ${optionalInteger "border-size" cfg.borderSize} + ${optionalString "border-color" cfg.borderColor} + ${optionalInteger "border-radius" cfg.borderRadius} + ${optionalString "progress-color" cfg.progressColor} + ${optionalBoolean "icons" cfg.icons} + ${optionalInteger "max-icon-size" cfg.maxIconSize} + ${optionalString "icon-path" cfg.iconPath} + ${optionalBoolean "markup" cfg.markup} + ${optionalBoolean "actions" cfg.actions} + ${optionalString "format" cfg.format} + ${optionalInteger "default-timeout" cfg.defaultTimeout} + ${optionalBoolean "ignore-timeout" cfg.ignoreTimeout} + ${optionalString "group-by" cfg.groupBy} + + ${cfg.extraConfig} + ''; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/mbsync.nix b/infra/libkookie/home-manager-stable/modules/services/mbsync.nix new file mode 100644 index 00000000000..bdeda0ec9f8 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/mbsync.nix @@ -0,0 +1,109 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.mbsync; + + mbsyncOptions = [ "--all" ] ++ optional (cfg.verbose) "--verbose" + ++ optional (cfg.configFile != null) "--config ${cfg.configFile}"; + +in { + meta.maintainers = [ maintainers.pjones ]; + + options.services.mbsync = { + enable = mkEnableOption "mbsync"; + + package = mkOption { + type = types.package; + default = pkgs.isync; + defaultText = literalExpression "pkgs.isync"; + example = literalExpression "pkgs.isync"; + description = "The package to use for the mbsync binary."; + }; + + frequency = mkOption { + type = types.str; + default = "*:0/5"; + description = '' + How often to run mbsync. This value is passed to the systemd + timer configuration as the onCalendar option. See + + systemd.time + 7 + + for more information about the format. + ''; + }; + + verbose = mkOption { + type = types.bool; + default = true; + description = '' + Whether mbsync should produce verbose output. + ''; + }; + + configFile = mkOption { + type = types.nullOr types.path; + default = null; + description = '' + Optional configuration file to link to use instead of + the default file (~/.mbsyncrc). + ''; + }; + + preExec = mkOption { + type = types.nullOr types.str; + default = null; + example = "mkdir -p %h/mail"; + description = '' + An optional command to run before mbsync executes. This is + useful for creating the directories mbsync is going to use. + ''; + }; + + postExec = mkOption { + type = types.nullOr types.str; + default = null; + example = "\${pkgs.mu}/bin/mu index"; + description = '' + An optional command to run after mbsync executes successfully. + This is useful for running mailbox indexing tools. + ''; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.mbsync" pkgs + lib.platforms.linux) + ]; + + systemd.user.services.mbsync = { + Unit = { Description = "mbsync mailbox synchronization"; }; + + Service = { + Type = "oneshot"; + ExecStart = + "${cfg.package}/bin/mbsync ${concatStringsSep " " mbsyncOptions}"; + } // (optionalAttrs (cfg.postExec != null) { + ExecStartPost = cfg.postExec; + }) // (optionalAttrs (cfg.preExec != null) { + ExecStartPre = cfg.preExec; + }); + }; + + systemd.user.timers.mbsync = { + Unit = { Description = "mbsync mailbox synchronization"; }; + + Timer = { + OnCalendar = cfg.frequency; + Unit = "mbsync.service"; + }; + + Install = { WantedBy = [ "timers.target" ]; }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/mopidy.nix b/infra/libkookie/home-manager-stable/modules/services/mopidy.nix new file mode 100644 index 00000000000..32862542b36 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/mopidy.nix @@ -0,0 +1,136 @@ +{ config, options, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.mopidy; + + # The configuration format of Mopidy. It seems to use configparser with + # some quirky handling of its types. You can see how they're handled in + # `mopidy/config/types.py` from the source code. + toMopidyConf = generators.toINI { + mkKeyValue = generators.mkKeyValueDefault { + mkValueString = v: + if isList v then + "\n " + concatStringsSep "\n " v + else + generators.mkValueStringDefault { } v; + } " = "; + }; + + mopidyEnv = pkgs.buildEnv { + name = "mopidy-with-extensions-${pkgs.mopidy.version}"; + paths = closePropagation cfg.extensionPackages; + pathsToLink = [ "/${pkgs.mopidyPackages.python.sitePackages}" ]; + buildInputs = [ pkgs.makeWrapper ]; + postBuild = '' + makeWrapper ${pkgs.mopidy}/bin/mopidy $out/bin/mopidy \ + --prefix PYTHONPATH : $out/${pkgs.mopidyPackages.python.sitePackages} + ''; + }; + + # Nix-representable format for Mopidy config. + mopidyConfFormat = { }: { + type = with types; + let + valueType = nullOr (oneOf [ bool float int str (listOf valueType) ]) + // { + description = "Mopidy config value"; + }; + in attrsOf (attrsOf valueType); + + generate = name: value: pkgs.writeText name (toMopidyConf value); + }; + + settingsFormat = mopidyConfFormat { }; + +in { + meta.maintainers = [ hm.maintainers.foo-dogsquared ]; + + options.services.mopidy = { + enable = mkEnableOption "Mopidy music player daemon"; + + extensionPackages = mkOption { + type = with types; listOf package; + default = [ ]; + example = literalExpression + "with pkgs; [ mopidy-spotify mopidy-mpd mopidy-mpris ]"; + description = '' + Mopidy extensions that should be loaded by the service. + ''; + }; + + settings = mkOption { + type = settingsFormat.type; + default = { }; + example = literalExpression '' + { + file = { + media_dirs = [ + "$XDG_MUSIC_DIR|Music" + "~/library|Library" + ]; + follow_symlinks = true; + excluded_file_extensions = [ + ".html" + ".zip" + ".jpg" + ".jpeg" + ".png" + ]; + }; + + # Please don't put your mopidy-spotify configuration in the public. :) + # Think of your Spotify Premium subscription! + spotify = { + client_id = "CLIENT_ID"; + client_secret = "CLIENT_SECRET"; + }; + } + ''; + description = '' + Configuration written to + $XDG_CONFIG_HOME/mopidy/mopidy.conf. + + See for + more details. + ''; + }; + }; + + config = mkIf cfg.enable { + assertions = + [ (hm.assertions.assertPlatform "services.mopidy" pkgs platforms.linux) ]; + + xdg.configFile."mopidy/mopidy.conf".source = + settingsFormat.generate "mopidy-${config.home.username}" cfg.settings; + + systemd.user.services.mopidy = { + Unit = { + Description = "mopidy music player daemon"; + Documentation = [ "https://mopidy.com/" ]; + After = [ "network.target" "sound.target" ]; + }; + + Service = { ExecStart = "${mopidyEnv}/bin/mopidy"; }; + + Install.WantedBy = [ "default.target" ]; + }; + + systemd.user.services.mopidy-scan = { + Unit = { + Description = "mopidy local files scanner"; + Documentation = [ "https://mopidy.com/" ]; + After = [ "network.target" "sound.target" ]; + }; + + Service = { + ExecStart = "${mopidyEnv}/bin/mopidy local scan"; + Type = "oneshot"; + }; + + Install.WantedBy = [ "default.target" ]; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/mpd-discord-rpc.nix b/infra/libkookie/home-manager-stable/modules/services/mpd-discord-rpc.nix new file mode 100644 index 00000000000..23cf1b5ec45 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/mpd-discord-rpc.nix @@ -0,0 +1,55 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.mpd-discord-rpc; + tomlFormat = pkgs.formats.toml { }; + configFile = tomlFormat.generate "config.toml" cfg.settings; +in { + meta.maintainers = [ maintainers.kranzes ]; + + options.services.mpd-discord-rpc = { + enable = mkEnableOption "the mpd-discord-rpc service"; + + settings = mkOption { + type = tomlFormat.type; + default = { }; + example = literalExpression '' + { + hosts = [ "localhost:6600" ]; + format = { + details = "$title"; + state = "On $album by $artist"; + }; + } + ''; + description = '' + Configuration included in config.toml. + For available options see + ''; + }; + + package = mkOption { + type = types.package; + default = pkgs.mpd-discord-rpc; + defaultText = literalExpression "pkgs.mpd-discord-rpc"; + description = "mpd-discord-rpc package to use."; + }; + }; + + config = mkIf cfg.enable { + xdg.configFile."discord-rpc/config.toml".source = configFile; + + systemd.user.services.mpd-discord-rpc = { + Unit = { + Description = "Discord Rich Presence for MPD"; + Documentation = "https://github.com/JakeStanger/mpd-discord-rpc"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.desktop" ]; + }; + Service.ExecStart = "${cfg.package}/bin/mpd-discord-rpc"; + Install.WantedBy = [ "graphical-session.target" ]; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/mpd.nix b/infra/libkookie/home-manager-stable/modules/services/mpd.nix new file mode 100644 index 00000000000..f71d96a447b --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/mpd.nix @@ -0,0 +1,184 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + name = "mpd"; + + cfg = config.services.mpd; + + mpdConf = pkgs.writeText "mpd.conf" '' + music_directory "${cfg.musicDirectory}" + playlist_directory "${cfg.playlistDirectory}" + ${lib.optionalString (cfg.dbFile != null) '' + db_file "${cfg.dbFile}" + ''} + state_file "${cfg.dataDir}/state" + sticker_file "${cfg.dataDir}/sticker.sql" + + ${optionalString (cfg.network.listenAddress != "any") + ''bind_to_address "${cfg.network.listenAddress}"''} + ${optionalString (cfg.network.port != 6600) + ''port "${toString cfg.network.port}"''} + + ${cfg.extraConfig} + ''; + +in { + + ###### interface + + options = { + + services.mpd = { + + enable = mkOption { + type = types.bool; + default = false; + description = '' + Whether to enable MPD, the music player daemon. + ''; + }; + + package = mkOption { + type = types.package; + default = pkgs.mpd; + defaultText = "pkgs.mpd"; + description = '' + The MPD package to run. + ''; + }; + + musicDirectory = mkOption { + type = with types; either path str; + default = "${config.home.homeDirectory}/music"; + defaultText = "$HOME/music"; + apply = toString; # Prevent copies to Nix store. + description = '' + The directory where mpd reads music from. + ''; + }; + + playlistDirectory = mkOption { + type = types.path; + default = "${cfg.dataDir}/playlists"; + defaultText = "\${dataDir}/playlists"; + apply = toString; # Prevent copies to Nix store. + description = '' + The directory where mpd stores playlists. + ''; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Extra directives added to to the end of MPD's configuration + file, mpd.conf. Basic configuration + like file location and uid/gid is added automatically to the + beginning of the file. For available options see + + mpd.conf + 5 + . + ''; + }; + + dataDir = mkOption { + type = types.path; + default = "${config.xdg.dataHome}/${name}"; + defaultText = "$XDG_DATA_HOME/mpd"; + apply = toString; # Prevent copies to Nix store. + description = '' + The directory where MPD stores its state, tag cache, + playlists etc. + ''; + }; + + network = { + startWhenNeeded = mkOption { + type = types.bool; + default = false; + description = '' + Enable systemd socket activation. + ''; + }; + + listenAddress = mkOption { + type = types.str; + default = "127.0.0.1"; + example = "any"; + description = '' + The address for the daemon to listen on. + Use any to listen on all addresses. + ''; + }; + + port = mkOption { + type = types.port; + default = 6600; + description = '' + The TCP port on which the the daemon will listen. + ''; + }; + + }; + + dbFile = mkOption { + type = types.nullOr types.str; + default = "${cfg.dataDir}/tag_cache"; + defaultText = "\${dataDir}/tag_cache"; + description = '' + The path to MPD's database. If set to + null the parameter is omitted from the + configuration. + ''; + }; + }; + + }; + + ###### implementation + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.mpd" pkgs lib.platforms.linux) + ]; + + systemd.user.services.mpd = { + Unit = { + After = [ "network.target" "sound.target" ]; + Description = "Music Player Daemon"; + }; + + Install = mkIf (!cfg.network.startWhenNeeded) { + WantedBy = [ "default.target" ]; + }; + + Service = { + Environment = "PATH=${config.home.profileDirectory}/bin"; + ExecStart = "${cfg.package}/bin/mpd --no-daemon ${mpdConf}"; + Type = "notify"; + ExecStartPre = '' + ${pkgs.bash}/bin/bash -c "${pkgs.coreutils}/bin/mkdir -p '${cfg.dataDir}' '${cfg.playlistDirectory}'"''; + }; + }; + systemd.user.sockets.mpd = mkIf cfg.network.startWhenNeeded { + Socket = { + ListenStream = let + listen = if cfg.network.listenAddress == "any" then + toString cfg.network.port + else + "${cfg.network.listenAddress}:${toString cfg.network.port}"; + in [ listen "%t/mpd/socket" ]; + + Backlog = 5; + KeepAlive = true; + }; + + Install = { WantedBy = [ "sockets.target" ]; }; + }; + }; + +} diff --git a/infra/libkookie/home-manager-stable/modules/services/mpdris2.nix b/infra/libkookie/home-manager-stable/modules/services/mpdris2.nix new file mode 100644 index 00000000000..79f2709fc54 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/mpdris2.nix @@ -0,0 +1,111 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.mpdris2; + + toIni = generators.toINI { + mkKeyValue = key: value: + let + value' = if isBool value then + (if value then "True" else "False") + else + toString value; + in "${key} = ${value'}"; + }; + + mpdris2Conf = { + Connection = { + host = cfg.mpd.host; + port = cfg.mpd.port; + music_dir = cfg.mpd.musicDirectory; + } // optionalAttrs (cfg.mpd.password != null) { + password = cfg.mpd.password; + }; + + Bling = { + notify = cfg.notifications; + mmkeys = cfg.multimediaKeys; + }; + }; + +in { + meta.maintainers = [ maintainers.pjones ]; + + options.services.mpdris2 = { + enable = mkEnableOption "mpDris2 the MPD to MPRIS2 bridge"; + notifications = mkEnableOption "song change notifications"; + multimediaKeys = mkEnableOption "multimedia key support"; + + package = mkOption { + type = types.package; + default = pkgs.mpdris2; + defaultText = literalExpression "pkgs.mpdris2"; + description = "The mpDris2 package to use."; + }; + + mpd = { + host = mkOption { + type = types.str; + default = config.services.mpd.network.listenAddress; + defaultText = "config.services.mpd.network.listenAddress"; + example = "192.168.1.1"; + description = "The address where MPD is listening for connections."; + }; + + port = mkOption { + type = types.port; + default = config.services.mpd.network.port; + defaultText = "config.services.mpd.network.port"; + description = '' + The port number where MPD is listening for connections. + ''; + }; + + musicDirectory = mkOption { + type = types.nullOr types.path; + default = config.services.mpd.musicDirectory; + defaultText = "config.services.mpd.musicDirectory"; + description = '' + If set, mpDris2 will use this directory to access music artwork. + ''; + }; + + password = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + The password to connect to MPD. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.mpdris2" pkgs + lib.platforms.linux) + ]; + + xdg.configFile."mpDris2/mpDris2.conf".text = toIni mpdris2Conf; + + systemd.user.services.mpdris2 = { + Install = { WantedBy = [ "default.target" ]; }; + + Unit = { + Description = "MPRIS 2 support for MPD"; + After = [ "mpd.service" ]; + }; + + Service = { + Type = "simple"; + Restart = "on-failure"; + RestartSec = "5s"; + ExecStart = "${cfg.package}/bin/mpDris2"; + BusName = "org.mpris.MediaPlayer2.mpd"; + }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/mpris-proxy.nix b/infra/libkookie/home-manager-stable/modules/services/mpris-proxy.nix new file mode 100644 index 00000000000..9996b1376f6 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/mpris-proxy.nix @@ -0,0 +1,37 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.mpris-proxy; + +in { + meta.maintainers = [ maintainers.thibautmarty ]; + + options.services.mpris-proxy.enable = mkEnableOption + "a proxy forwarding Bluetooth MIDI controls via MPRIS2 to control media players"; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.mpris-proxy" pkgs + lib.platforms.linux) + ]; + + systemd.user.services.mpris-proxy = { + Unit = { + Description = + "Proxy forwarding Bluetooth MIDI controls via MPRIS2 to control media players"; + BindsTo = [ "bluetooth.target" ]; + After = [ "bluetooth.target" ]; + }; + + Install.WantedBy = [ "bluetooth.target" ]; + + Service = { + Type = "simple"; + ExecStart = "${pkgs.bluez}/bin/mpris-proxy"; + }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/muchsync.nix b/infra/libkookie/home-manager-stable/modules/services/muchsync.nix new file mode 100644 index 00000000000..8c9e27014b0 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/muchsync.nix @@ -0,0 +1,207 @@ +{ config, lib, pkgs, ... }: + +with lib; + +# Documentation was partially copied from the muchsync manual. +# See http://www.muchsync.org/muchsync.html + +let + cfg = config.services.muchsync; + syncOptions = { + options = { + frequency = mkOption { + type = types.str; + default = "*:0/5"; + description = '' + How often to run muchsync. This + value is passed to the systemd timer configuration as the + OnCalendar option. See + + systemd.time + 7 + + for more information about the format. + ''; + }; + + sshCommand = mkOption { + type = types.str; + default = "${pkgs.openssh}/bin/ssh -CTaxq"; + defaultText = "ssh -CTaxq"; + description = '' + Specifies a command line to pass to /bin/sh + to execute a command on another machine. + + Note that because this string is passed to the shell, + special characters including spaces may need to be escaped. + ''; + }; + + upload = mkOption { + type = types.bool; + default = true; + description = '' + Whether to propagate local changes to the remote. + ''; + }; + + local = { + checkForModifiedFiles = mkOption { + type = types.bool; + default = false; + description = '' + Check for locally modified files. + Without this option, muchsync assumes that files in a maildir are + never edited. + + disables certain + optimizations so as to make muchsync at least check the timestamp on + every file, which will detect modified files at the cost of a longer + startup time. + + This option is useful if your software regularly modifies the + contents of mail files (e.g., because you are running offlineimap + with "synclabels = yes"). + ''; + }; + + importNew = mkOption { + type = types.bool; + default = true; + description = '' + Whether to begin the synchronisation by running + notmuch new locally. + ''; + }; + }; + + remote = { + host = mkOption { + type = types.str; + description = '' + Remote SSH host to synchronize with. + ''; + }; + + muchsyncPath = mkOption { + type = types.str; + default = ""; + defaultText = "$PATH/muchsync"; + description = '' + Specifies the path to muchsync on the server. + Ordinarily, muchsync should be in the default PATH on the server + so this option is not required. + However, this option is useful if you have to install muchsync in + a non-standard place or wish to test development versions of the + code. + ''; + }; + + checkForModifiedFiles = mkOption { + type = types.bool; + default = false; + description = '' + Check for modified files on the remote side. + Without this option, muchsync assumes that files in a maildir are + never edited. + + disables certain + optimizations so as to make muchsync at least check the timestamp on + every file, which will detect modified files at the cost of a longer + startup time. + + This option is useful if your software regularly modifies the + contents of mail files (e.g., because you are running offlineimap + with "synclabels = yes"). + ''; + }; + + importNew = mkOption { + type = types.bool; + default = true; + description = '' + Whether to begin the synchronisation by running + notmuch new on the remote side. + ''; + }; + }; + }; + }; + +in { + meta.maintainers = with maintainers; [ pacien ]; + + options.services.muchsync = { + remotes = mkOption { + type = with types; attrsOf (submodule syncOptions); + default = { }; + example = literalExpression '' + { + server = { + frequency = "*:0/10"; + remote.host = "server.tld"; + }; + } + ''; + description = '' + Muchsync remotes to synchronise with. + ''; + }; + }; + + config = let + mapRemotes = gen: + with attrsets; + mapAttrs' + (name: remoteCfg: nameValuePair "muchsync-${name}" (gen name remoteCfg)) + cfg.remotes; + in mkIf (cfg.remotes != { }) { + assertions = [ + (hm.assertions.assertPlatform "services.muchsync" pkgs platforms.linux) + + { + assertion = config.programs.notmuch.enable; + message = '' + The muchsync module requires 'programs.notmuch.enable = true'. + ''; + } + ]; + + systemd.user.services = mapRemotes (name: remoteCfg: { + Unit = { Description = "muchsync sync service (${name})"; }; + Service = { + CPUSchedulingPolicy = "idle"; + IOSchedulingClass = "idle"; + Environment = [ + ''"PATH=${pkgs.notmuch}/bin"'' + ''"NOTMUCH_CONFIG=${config.home.sessionVariables.NOTMUCH_CONFIG}"'' + ''"NMBGIT=${config.home.sessionVariables.NMBGIT}"'' + ]; + ExecStart = concatStringsSep " " ([ "${pkgs.muchsync}/bin/muchsync" ] + ++ [ "-s ${escapeShellArg remoteCfg.sshCommand}" ] + ++ optional (!remoteCfg.upload) "--noup" + + # local configuration + ++ optional remoteCfg.local.checkForModifiedFiles "-F" + ++ optional (!remoteCfg.local.importNew) "--nonew" + + # remote configuration + ++ [ (escapeShellArg remoteCfg.remote.host) ] + ++ optional (remoteCfg.remote.muchsyncPath != "") + "-r ${escapeShellArg remoteCfg.remote.muchsyncPath}" + ++ optional remoteCfg.remote.checkForModifiedFiles "-F" + ++ optional (!remoteCfg.remote.importNew) "--nonew"); + }; + }); + + systemd.user.timers = mapRemotes (name: remoteCfg: { + Unit = { Description = "muchsync periodic sync (${name})"; }; + Timer = { + Unit = "muchsync-${name}.service"; + OnCalendar = remoteCfg.frequency; + Persistent = true; + }; + Install = { WantedBy = [ "timers.target" ]; }; + }); + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/network-manager-applet.nix b/infra/libkookie/home-manager-stable/modules/services/network-manager-applet.nix new file mode 100644 index 00000000000..f4abe86e0ae --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/network-manager-applet.nix @@ -0,0 +1,42 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.network-manager-applet; + +in { + meta.maintainers = [ maintainers.rycee ]; + + options = { + services.network-manager-applet = { + enable = mkEnableOption "the Network Manager applet"; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.network-manager-applet" pkgs + lib.platforms.linux) + ]; + + systemd.user.services.network-manager-applet = { + Unit = { + Description = "Network Manager applet"; + Requires = [ "tray.target" ]; + After = [ "graphical-session-pre.target" "tray.target" ]; + PartOf = [ "graphical-session.target" ]; + }; + + Install = { WantedBy = [ "graphical-session.target" ]; }; + + Service = { + ExecStart = toString + ([ "${pkgs.networkmanagerapplet}/bin/nm-applet" "--sm-disable" ] + ++ optional config.xsession.preferStatusNotifierItems + "--indicator"); + }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/nextcloud-client.nix b/infra/libkookie/home-manager-stable/modules/services/nextcloud-client.nix new file mode 100644 index 00000000000..b436488d166 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/nextcloud-client.nix @@ -0,0 +1,52 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.nextcloud-client; + +in { + options = { + services.nextcloud-client = { + enable = mkEnableOption "Nextcloud Client"; + + package = mkOption { + type = types.package; + default = pkgs.nextcloud-client; + defaultText = literalExpression "pkgs.nextcloud-client"; + description = "The package to use for the nextcloud client binary."; + }; + + startInBackground = mkOption { + type = types.bool; + default = false; + description = + "Whether to start the Nextcloud client in the background."; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.nextcloud-client" pkgs + lib.platforms.linux) + ]; + + systemd.user.services.nextcloud-client = { + Unit = { + Description = "Nextcloud Client"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + }; + + Service = { + Environment = "PATH=${config.home.profileDirectory}/bin"; + ExecStart = "${cfg.package}/bin/nextcloud" + + (optionalString cfg.startInBackground " --background"); + }; + + Install = { WantedBy = [ "graphical-session.target" ]; }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/notify-osd.nix b/infra/libkookie/home-manager-stable/modules/services/notify-osd.nix new file mode 100644 index 00000000000..6a75ce6e6f5 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/notify-osd.nix @@ -0,0 +1,48 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.notify-osd; + +in { + meta.maintainers = [ maintainers.imalison ]; + + options = { + services.notify-osd = { + enable = mkEnableOption "notify-osd"; + + package = mkOption { + type = types.package; + default = pkgs.notify-osd; + defaultText = literalExpression "pkgs.notify-osd"; + description = '' + Package containing the notify-osd program. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.notify-osd" pkgs + lib.platforms.linux) + ]; + + systemd.user.services.notify-osd = { + Unit = { + Description = "notify-osd"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + }; + + Install.WantedBy = [ "graphical-session.target" ]; + + Service = { + ExecStart = "${cfg.package}/bin/notify-osd"; + Restart = "on-abort"; + }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/opensnitch-ui.nix b/infra/libkookie/home-manager-stable/modules/services/opensnitch-ui.nix new file mode 100644 index 00000000000..a086554cad2 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/opensnitch-ui.nix @@ -0,0 +1,38 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.opensnitch-ui; + +in { + + meta.maintainers = [ maintainers.onny ]; + + options = { + services.opensnitch-ui = { enable = mkEnableOption "Opensnitch client"; }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.opensnitch-ui" pkgs + lib.platforms.linux) + ]; + + systemd.user.services.opensnitch-ui = { + Unit = { + Description = "Opensnitch ui"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + }; + + Service = { + Environment = "PATH=${config.home.profileDirectory}/bin"; + ExecStart = "${pkgs.opensnitch-ui}/bin/opensnitch-ui"; + }; + + Install = { WantedBy = [ "graphical-session.target" ]; }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/owncloud-client.nix b/infra/libkookie/home-manager-stable/modules/services/owncloud-client.nix new file mode 100644 index 00000000000..d55d8ffa2a4 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/owncloud-client.nix @@ -0,0 +1,26 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + options = { + services.owncloud-client = { enable = mkEnableOption "Owncloud Client"; }; + }; + + config = mkIf config.services.owncloud-client.enable { + systemd.user.services.owncloud-client = { + Unit = { + Description = "Owncloud Client"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + }; + + Service = { + Environment = "PATH=${config.home.profileDirectory}/bin"; + ExecStart = "${pkgs.owncloud-client}/bin/owncloud"; + }; + + Install = { WantedBy = [ "graphical-session.target" ]; }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/pantalaimon.nix b/infra/libkookie/home-manager-stable/modules/services/pantalaimon.nix new file mode 100644 index 00000000000..d833d45397e --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/pantalaimon.nix @@ -0,0 +1,84 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.pantalaimon; + + iniFmt = pkgs.formats.ini { }; +in { + meta.maintainers = [ maintainers.jojosch ]; + + options = { + services.pantalaimon = { + enable = mkEnableOption + "Pantalaimon, an E2EE aware proxy daemon for matrix clients"; + + package = mkOption { + type = types.package; + default = pkgs.pantalaimon; + defaultText = literalExpression "pkgs.pantalaimon"; + description = + "Package providing the pantalaimon executable to use."; + }; + + settings = mkOption { + type = iniFmt.type; + default = { }; + defaultText = literalExpression "{ }"; + example = literalExpression '' + { + Default = { + LogLevel = "Debug"; + SSL = true; + }; + local-matrix = { + Homeserver = "https://matrix.org"; + ListenAddress = "127.0.0.1"; + ListenPort = 8008; + }; + } + ''; + description = '' + Configuration written to + $XDG_CONFIG_HOME/pantalaimon/pantalaimon.conf. + + See or + + pantalaimon + 5 + + for options. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.pantalaimon" pkgs + lib.platforms.linux) + ]; + + home.packages = [ cfg.package ]; + + systemd.user.services = { + pantalaimon = { + Unit = { + Description = + "Pantalaimon - E2EE aware proxy daemon for matrix clients"; + After = [ "network-online.target" ]; + }; + + Service = { + ExecStart = "${cfg.package}/bin/pantalaimon -c ${ + iniFmt.generate "pantalaimon.conf" cfg.settings + }"; + Restart = "on-failure"; + }; + + Install.WantedBy = [ "default.target" ]; + }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/parcellite.nix b/infra/libkookie/home-manager-stable/modules/services/parcellite.nix new file mode 100644 index 00000000000..6ed9946b4df --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/parcellite.nix @@ -0,0 +1,48 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.parcellite; + +in { + meta.maintainers = [ maintainers.gleber ]; + + options.services.parcellite = { + enable = mkEnableOption "Parcellite"; + + package = mkOption { + type = types.package; + default = pkgs.parcellite; + defaultText = literalExpression "pkgs.parcellite"; + example = literalExpression "pkgs.clipit"; + description = "Parcellite derivation to use."; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.parcellite" pkgs + lib.platforms.linux) + ]; + + home.packages = [ cfg.package ]; + + systemd.user.services.parcellite = { + Unit = { + Description = "Lightweight GTK+ clipboard manager"; + Requires = [ "tray.target" ]; + After = [ "graphical-session-pre.target" "tray.target" ]; + PartOf = [ "graphical-session.target" ]; + }; + + Install = { WantedBy = [ "graphical-session.target" ]; }; + + Service = { + ExecStart = "${cfg.package}/bin/${cfg.package.pname}"; + Restart = "on-abort"; + }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/pass-secret-service.nix b/infra/libkookie/home-manager-stable/modules/services/pass-secret-service.nix new file mode 100644 index 00000000000..06b5be1f882 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/pass-secret-service.nix @@ -0,0 +1,33 @@ +{ pkgs, config, lib, ... }: + +with lib; + +let serviceCfg = config.services.pass-secret-service; +in { + meta.maintainers = [ maintainers.cab404 ]; + options.services.pass-secret-service = { + enable = mkEnableOption "Pass libsecret service"; + }; + config = mkIf serviceCfg.enable { + assertions = [ + (hm.assertions.assertPlatform "services.pass-secret-service" pkgs + platforms.linux) + + { + assertion = config.programs.password-store.enable; + message = "The 'services.pass-secret-service' module requires" + + " 'programs.password-store.enable = true'."; + } + ]; + + systemd.user.services.pass-secret-service = { + Unit = { Description = "Pass libsecret service"; }; + Service = { + # pass-secret-service doesn't use environment variables for some reason. + ExecStart = + "${pkgs.pass-secret-service}/bin/pass_secret_service --path ${config.programs.password-store.settings.PASSWORD_STORE_DIR}"; + }; + Install = { WantedBy = [ "default.target" ]; }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/password-store-sync.nix b/infra/libkookie/home-manager-stable/modules/services/password-store-sync.nix new file mode 100644 index 00000000000..c8dbe808fb1 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/password-store-sync.nix @@ -0,0 +1,76 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + serviceCfg = config.services.password-store-sync; + programCfg = config.programs.password-store; + +in { + meta.maintainers = with maintainers; [ pacien ]; + + options.services.password-store-sync = { + enable = mkEnableOption "Password store periodic sync"; + + frequency = mkOption { + type = types.str; + default = "*:0/5"; + description = '' + How often to synchronise the password store git repository with its + default upstream. + + This value is passed to the systemd timer configuration as the + onCalendar option. + See + + systemd.time + 7 + + for more information about the format. + ''; + }; + }; + + config = mkIf serviceCfg.enable { + assertions = [ + (hm.assertions.assertPlatform "services.password-store-sync" pkgs + platforms.linux) + + { + assertion = programCfg.enable; + message = "The 'services.password-store-sync' module requires" + + " 'programs.password-store.enable = true'."; + } + ]; + + systemd.user.services.password-store-sync = { + Unit = { Description = "Password store sync"; }; + + Service = { + CPUSchedulingPolicy = "idle"; + IOSchedulingClass = "idle"; + Environment = let + makeEnvironmentPairs = + mapAttrsToList (key: value: "${key}=${builtins.toJSON value}"); + in makeEnvironmentPairs programCfg.settings; + ExecStart = toString (pkgs.writeShellScript "password-store-sync" '' + ${pkgs.pass}/bin/pass git pull --rebase && \ + ${pkgs.pass}/bin/pass git push + ''); + }; + }; + + systemd.user.timers.password-store-sync = { + Unit = { Description = "Password store periodic sync"; }; + + Timer = { + Unit = "password-store-sync.service"; + OnCalendar = serviceCfg.frequency; + Persistent = true; + }; + + Install = { WantedBy = [ "timers.target" ]; }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/pasystray.nix b/infra/libkookie/home-manager-stable/modules/services/pasystray.nix new file mode 100644 index 00000000000..15c951e137e --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/pasystray.nix @@ -0,0 +1,31 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + meta.maintainers = [ hm.maintainers.pltanton ]; + + options = { + services.pasystray = { enable = mkEnableOption "PulseAudio system tray"; }; + }; + + config = mkIf config.services.pasystray.enable { + systemd.user.services.pasystray = { + Unit = { + Description = "PulseAudio system tray"; + Requires = [ "tray.target" ]; + After = [ "graphical-session-pre.target" "tray.target" ]; + PartOf = [ "graphical-session.target" ]; + }; + + Install = { WantedBy = [ "graphical-session.target" ]; }; + + Service = { + Environment = + let toolPaths = makeBinPath [ pkgs.paprefs pkgs.pavucontrol ]; + in [ "PATH=${toolPaths}" ]; + ExecStart = "${pkgs.pasystray}/bin/pasystray"; + }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/pbgopy.nix b/infra/libkookie/home-manager-stable/modules/services/pbgopy.nix new file mode 100644 index 00000000000..487aa4f36bc --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/pbgopy.nix @@ -0,0 +1,73 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.pbgopy; + package = pkgs.pbgopy; + + commandLine = concatStringsSep " " ([ + "${package}/bin/pbgopy serve" + "--port ${toString cfg.port}" + "--ttl ${cfg.cache.ttl}" + ] ++ optional (cfg.httpAuth != null) + "--basic-auth ${escapeShellArg cfg.httpAuth}"); + +in { + meta.maintainers = [ maintainers.ivar ]; + + options.services.pbgopy = { + enable = mkEnableOption "pbgopy"; + + port = mkOption { + type = types.port; + default = 9090; + example = 8080; + description = '' + The port to host the pbgopy server on. + ''; + }; + + cache.ttl = mkOption { + type = types.str; + default = "24h"; + example = "10m"; + description = '' + The TTL for the cache. Use "0s" to disable it. + ''; + }; + + httpAuth = mkOption { + type = types.nullOr types.str; + default = null; + example = "user:pass"; + description = '' + Basic HTTP authentication's username and password. Both the username and + password are escaped. + ''; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.pbgopy" pkgs + lib.platforms.linux) + ]; + + home.packages = [ package ]; + + systemd.user.services.pbgopy = { + Unit = { + Description = "pbgopy server for sharing the clipboard between devices"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + }; + Service = { + ExecStart = commandLine; + Restart = "on-abort"; + }; + Install = { WantedBy = [ "graphical-session.target" ]; }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/picom.nix b/infra/libkookie/home-manager-stable/modules/services/picom.nix new file mode 100644 index 00000000000..9ea052ec0fc --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/picom.nix @@ -0,0 +1,310 @@ +{ config, lib, pkgs, ... }: + +let + inherit (builtins) toJSON toString; + inherit (lib) + concatStringsSep elemAt literalExpression mkEnableOption mkIf mkOption + mkRemovedOptionModule optional optionalAttrs optionalString types; + + cfg = config.services.picom; + + configFile = optionalString cfg.fade '' + # fading + fading = true; + fade-delta = ${toString cfg.fadeDelta}; + fade-in-step = ${elemAt cfg.fadeSteps 0}; + fade-out-step = ${elemAt cfg.fadeSteps 1}; + fade-exclude = ${toJSON cfg.fadeExclude}; + '' + optionalString cfg.shadow '' + + # shadows + shadow = true; + shadow-offset-x = ${toString (elemAt cfg.shadowOffsets 0)}; + shadow-offset-y = ${toString (elemAt cfg.shadowOffsets 1)}; + shadow-opacity = ${cfg.shadowOpacity}; + shadow-exclude = ${toJSON cfg.shadowExclude}; + '' + optionalString cfg.blur '' + + # blur + blur-background = true; + blur-background-exclude = ${toJSON cfg.blurExclude}; + '' + '' + + # opacity + active-opacity = ${cfg.activeOpacity}; + inactive-opacity = ${cfg.inactiveOpacity}; + inactive-dim = ${cfg.inactiveDim}; + opacity-rule = ${toJSON cfg.opacityRule}; + + wintypes: + { + dock = { shadow = ${toJSON (!cfg.noDockShadow)}; }; + dnd = { shadow = ${toJSON (!cfg.noDNDShadow)}; }; + popup_menu = { opacity = ${cfg.menuOpacity}; }; + dropdown_menu = { opacity = ${cfg.menuOpacity}; }; + }; + + # other options + backend = ${toJSON cfg.backend}; + vsync = ${toJSON cfg.vSync}; + '' + cfg.extraOptions; + +in { + + options.services.picom = { + enable = mkEnableOption "Picom X11 compositor"; + + blur = mkOption { + type = types.bool; + default = false; + description = '' + Enable background blur on transparent windows. + ''; + }; + + blurExclude = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "class_g = 'slop'" "class_i = 'polybar'" ]; + description = '' + List of windows to exclude background blur. + See the + + picom + 1 + + man page for more examples. + ''; + }; + + experimentalBackends = mkOption { + type = types.bool; + default = false; + description = '' + Whether to use the new experimental backends. + ''; + }; + + fade = mkOption { + type = types.bool; + default = false; + description = '' + Fade windows in and out. + ''; + }; + + fadeDelta = mkOption { + type = types.int; + default = 10; + example = 5; + description = '' + Time between fade animation step (in ms). + ''; + }; + + fadeSteps = mkOption { + type = types.listOf types.str; + default = [ "0.028" "0.03" ]; + example = [ "0.04" "0.04" ]; + description = '' + Opacity change between fade steps (in and out). + ''; + }; + + fadeExclude = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "window_type *= 'menu'" "name ~= 'Firefox$'" "focused = 1" ]; + description = '' + List of conditions of windows that should not be faded. + See the + + picom + 1 + + man page for more examples. + ''; + }; + + shadow = mkOption { + type = types.bool; + default = false; + description = '' + Draw window shadows. + ''; + }; + + shadowOffsets = mkOption { + type = types.listOf types.int; + default = [ (-15) (-15) ]; + example = [ (-10) (-15) ]; + description = '' + Horizontal and vertical offsets for shadows (in pixels). + ''; + }; + + shadowOpacity = mkOption { + type = types.str; + default = "0.75"; + example = "0.8"; + description = '' + Window shadows opacity (number in range 0 - 1). + ''; + }; + + shadowExclude = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "window_type *= 'menu'" "name ~= 'Firefox$'" "focused = 1" ]; + description = '' + List of conditions of windows that should have no shadow. + See the + + picom + 1 + + man page for more examples. + ''; + }; + + noDockShadow = mkOption { + type = types.bool; + default = true; + description = '' + Avoid shadow on docks. + ''; + }; + + noDNDShadow = mkOption { + type = types.bool; + default = true; + description = '' + Avoid shadow on drag-and-drop windows. + ''; + }; + + activeOpacity = mkOption { + type = types.str; + default = "1.0"; + example = "0.8"; + description = '' + Opacity of active windows. + ''; + }; + + inactiveDim = mkOption { + type = types.str; + default = "0.0"; + example = "0.2"; + description = '' + Dim inactive windows. + ''; + }; + + inactiveOpacity = mkOption { + type = types.str; + default = "1.0"; + example = "0.8"; + description = '' + Opacity of inactive windows. + ''; + }; + + menuOpacity = mkOption { + type = types.str; + default = "1.0"; + example = "0.8"; + description = '' + Opacity of dropdown and popup menu. + ''; + }; + + opacityRule = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "87:class_i ?= 'scratchpad'" "91:class_i ?= 'xterm'" ]; + description = '' + List of opacity rules. + See the + + picom + 1 + + man page for more examples. + ''; + }; + + backend = mkOption { + type = types.str; + default = "glx"; + description = '' + Backend to use: glx or xrender. + ''; + }; + + vSync = mkOption { + type = types.bool; + default = false; + description = '' + Enable vertical synchronization. + ''; + }; + + package = mkOption { + type = types.package; + default = pkgs.picom; + defaultText = literalExpression "pkgs.picom"; + example = literalExpression "pkgs.picom"; + description = '' + picom derivation to use. + ''; + }; + + extraOptions = mkOption { + type = types.lines; + default = ""; + example = '' + unredir-if-possible = true; + dbe = true; + ''; + description = '' + Additional Picom configuration. + ''; + }; + }; + + imports = [ + (mkRemovedOptionModule [ "services" "picom" "refreshRate" ] + "The option `refresh-rate` has been deprecated by upstream.") + ]; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.picom" pkgs + lib.platforms.linux) + ]; + + home.packages = [ cfg.package ]; + + xdg.configFile."picom/picom.conf".text = configFile; + + systemd.user.services.picom = { + Unit = { + Description = "Picom X11 compositor"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + }; + + Install = { WantedBy = [ "graphical-session.target" ]; }; + + Service = { + ExecStart = concatStringsSep " " ([ + "${cfg.package}/bin/picom" + "--config ${config.xdg.configFile."picom/picom.conf".source}" + ] ++ optional cfg.experimentalBackends "--experimental-backends"); + Restart = "always"; + RestartSec = 3; + }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/plan9port.nix b/infra/libkookie/home-manager-stable/modules/services/plan9port.nix new file mode 100644 index 00000000000..249804724ff --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/plan9port.nix @@ -0,0 +1,38 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.plan9port; + +in { + meta.maintainers = [ maintainers.ehmry ]; + + options.services.plan9port = { + fontsrv.enable = + mkEnableOption "the Plan 9 file system access to host fonts"; + plumber.enable = + mkEnableOption "the Plan 9 file system for interprocess messaging"; + }; + + config = mkIf (cfg.fontsrv.enable || cfg.plumber.enable) { + assertions = [ + (hm.assertions.assertPlatform "services.plan9port" pkgs platforms.linux) + ]; + + systemd.user.services.fontsrv = mkIf cfg.fontsrv.enable { + Unit.Description = "the Plan 9 file system access to host fonts"; + Install.WantedBy = [ "default.target" ]; + Service.ExecStart = "${pkgs.plan9port}/bin/9 fontsrv"; + }; + + systemd.user.services.plumber = mkIf cfg.plumber.enable { + Unit.Description = "file system for interprocess messaging"; + Install.WantedBy = [ "default.target" ]; + Service.ExecStart = "${pkgs.plan9port}/bin/9 plumber -f"; + }; + + }; + +} diff --git a/infra/libkookie/home-manager-stable/modules/services/playerctld.nix b/infra/libkookie/home-manager-stable/modules/services/playerctld.nix new file mode 100644 index 00000000000..5fed8f2b436 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/playerctld.nix @@ -0,0 +1,41 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.playerctld; + +in { + meta.maintainers = [ hm.maintainers.fendse ]; + + options.services.playerctld = { + enable = mkEnableOption "playerctld daemon"; + + package = mkOption { + type = types.package; + default = pkgs.playerctl; + defaultText = literalExpression "pkgs.playerctl"; + description = "The playerctl package to use."; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.playerctld" pkgs + lib.platforms.linux) + ]; + + systemd.user.services.playerctld = { + Unit.Description = "MPRIS media player daemon"; + + Install.WantedBy = [ "default.target" ]; + + Service = { + ExecStart = "${cfg.package}/bin/playerctld"; + Type = "dbus"; + BusName = "org.mpris.MediaPlayer2.playerctld"; + }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/plex-mpv-shim.nix b/infra/libkookie/home-manager-stable/modules/services/plex-mpv-shim.nix new file mode 100644 index 00000000000..b5fb621838e --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/plex-mpv-shim.nix @@ -0,0 +1,70 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + jsonFormat = pkgs.formats.json { }; + cfg = config.services.plex-mpv-shim; + +in { + meta.maintainers = [ maintainers.starcraft66 ]; + + options = { + services.plex-mpv-shim = { + enable = mkEnableOption "Plex mpv shim"; + + package = mkOption { + type = types.package; + default = pkgs.plex-mpv-shim; + defaultText = literalExpression "pkgs.plex-mpv-shim"; + description = "The package to use for the Plex mpv shim."; + }; + + settings = mkOption { + type = jsonFormat.type; + default = { }; + example = literalExpression '' + { + adaptive_transcode = false; + allow_http = false; + always_transcode = false; + audio_ac3passthrough = false; + audio_dtspassthrough = false; + auto_play = true; + auto_transcode = true; + } + ''; + description = '' + Configuration written to + $XDG_CONFIG_HOME/plex-mpv-shim/config.json. See + + for the configuration documentation. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.plex-mpv-shim" pkgs + lib.platforms.linux) + ]; + + xdg.configFile."plex-mpv-shim/conf.json" = mkIf (cfg.settings != { }) { + source = jsonFormat.generate "conf.json" cfg.settings; + }; + + systemd.user.services.plex-mpv-shim = { + Unit = { + Description = "Plex mpv shim"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + }; + + Service = { ExecStart = "${cfg.package}/bin/plex-mpv-shim"; }; + + Install = { WantedBy = [ "graphical-session.target" ]; }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/polybar.nix b/infra/libkookie/home-manager-stable/modules/services/polybar.nix new file mode 100644 index 00000000000..7912d8988ff --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/polybar.nix @@ -0,0 +1,225 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.polybar; + + eitherStrBoolIntList = with types; + either str (either bool (either int (listOf str))); + + # Convert a key/val pair to the insane format that polybar uses. + # Each input key/val pair may return several output key/val pairs. + convertPolybarKeyVal = key: val: + # Convert { foo = [ "a" "b" ]; } + # to { + # foo-0 = "a"; + # foo-1 = "b"; + # } + if isList val then + concatLists (imap0 (i: convertPolybarKeyVal "${key}-${toString i}") val) + # Convert { + # foo.text = "a"; + # foo.font = 1; + # } to { + # foo = "a"; + # foo-font = 1; + # } + else if isAttrs val && !lib.isDerivation val then + concatLists (mapAttrsToList + (k: convertPolybarKeyVal (if k == "text" then key else "${key}-${k}")) + val) + # Base case + else + [ (nameValuePair key val) ]; + + convertPolybarSection = _: attrs: + listToAttrs (concatLists (mapAttrsToList convertPolybarKeyVal attrs)); + + # Converts an attrset to INI text, quoting values as expected by polybar. + # This does no more fancy conversion. + toPolybarIni = generators.toINI { + mkKeyValue = key: value: + let + quoted = v: + if hasPrefix " " v || hasSuffix " " v then ''"${v}"'' else v; + + value' = if isBool value then + (if value then "true" else "false") + else if (isString value && key != "include-file") then + quoted value + else + toString value; + in "${key}=${value'}"; + }; + + configFile = pkgs.writeText "polybar.conf" '' + ${toPolybarIni cfg.config} + ${toPolybarIni (mapAttrs convertPolybarSection cfg.settings)} + ${cfg.extraConfig} + ''; + +in { + options = { + services.polybar = { + enable = mkEnableOption "Polybar status bar"; + + package = mkOption { + type = types.package; + default = pkgs.polybar; + defaultText = literalExpression "pkgs.polybar"; + description = "Polybar package to install."; + example = literalExpression '' + pkgs.polybar.override { + i3GapsSupport = true; + alsaSupport = true; + iwSupport = true; + githubSupport = true; + } + ''; + }; + + config = mkOption { + type = types.coercedTo types.path + (p: { "section/base" = { include-file = "${p}"; }; }) + (types.attrsOf (types.attrsOf eitherStrBoolIntList)); + description = '' + Polybar configuration. Can be either path to a file, or set of attributes + that will be used to create the final configuration. + See also for a more nix-friendly format. + ''; + default = { }; + example = literalExpression '' + { + "bar/top" = { + monitor = "\''${env:MONITOR:eDP1}"; + width = "100%"; + height = "3%"; + radius = 0; + modules-center = "date"; + }; + + "module/date" = { + type = "internal/date"; + internal = 5; + date = "%d.%m.%y"; + time = "%H:%M"; + label = "%time% %date%"; + }; + } + ''; + }; + + settings = mkOption { + type = with types; + let ty = oneOf [ bool int float str (listOf ty) (attrsOf ty) ]; + in attrsOf (attrsOf ty // { description = "attribute sets"; }); + description = '' + Polybar configuration. This takes a nix attrset and converts it to the + strange data format that polybar uses. + Each entry will be converted to a section in the output file. + Several things are treated specially: nested keys are converted + to dash-separated keys; the special text key is ignored as a nested key, + to allow mixing different levels of nesting; and lists are converted to + polybar's foo-0, foo-1, ... format. + + For example: + + "module/volume" = { + type = "internal/pulseaudio"; + format.volume = "<ramp-volume> <label-volume>"; + label.muted.text = "🔇"; + label.muted.foreground = "#666"; + ramp.volume = ["🔈" "🔉" "🔊"]; + click.right = "pavucontrol &"; + } + + becomes: + + [module/volume] + type=internal/pulseaudio + format-volume=<ramp-volume> <label-volume> + label-muted=🔇 + label-muted-foreground=#666 + ramp-volume-0=🔈 + ramp-volume-1=🔉 + ramp-volume-2=🔊 + click-right=pavucontrol & + + ''; + default = { }; + example = literalExpression '' + { + "module/volume" = { + type = "internal/pulseaudio"; + format.volume = " "; + label.muted.text = "🔇"; + label.muted.foreground = "#666"; + ramp.volume = ["🔈" "🔉" "🔊"]; + click.right = "pavucontrol &"; + }; + } + ''; + }; + + extraConfig = mkOption { + type = types.lines; + description = "Additional configuration to add."; + default = ""; + example = '' + [module/date] + type = internal/date + interval = 5 + date = "%d.%m.%y" + time = %H:%M + format-prefix-foreground = \''${colors.foreground-alt} + label = %time% %date% + ''; + }; + + script = mkOption { + type = types.lines; + description = '' + This script will be used to start the polybars. + Set all necessary environment variables here and start all bars. + It can be assumed that polybar executable is in the PATH. + + Note, this script must start all bars in the background and then terminate. + ''; + example = "polybar bar &"; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.polybar" pkgs + lib.platforms.linux) + ]; + + home.packages = [ cfg.package ]; + xdg.configFile."polybar/config".source = configFile; + + systemd.user.services.polybar = { + Unit = { + Description = "Polybar status bar"; + PartOf = [ "tray.target" ]; + X-Restart-Triggers = + [ "${config.xdg.configFile."polybar/config".source}" ]; + }; + + Service = { + Type = "forking"; + Environment = "PATH=${cfg.package}/bin:/run/wrappers/bin"; + ExecStart = + let scriptPkg = pkgs.writeShellScriptBin "polybar-start" cfg.script; + in "${scriptPkg}/bin/polybar-start"; + Restart = "on-failure"; + }; + + Install = { WantedBy = [ "tray.target" ]; }; + }; + }; + +} diff --git a/infra/libkookie/home-manager-stable/modules/services/poweralertd.nix b/infra/libkookie/home-manager-stable/modules/services/poweralertd.nix new file mode 100644 index 00000000000..cae44c753c1 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/poweralertd.nix @@ -0,0 +1,36 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let cfg = config.services.poweralertd; + +in { + meta.maintainers = [ maintainers.thibautmarty ]; + + options.services.poweralertd.enable = + mkEnableOption "the Upower-powered power alerterd"; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.poweralertd" pkgs + lib.platforms.linux) + ]; + + systemd.user.services.poweralertd = { + Unit = { + Description = "UPower-powered power alerter"; + Documentation = "man:poweralertd(1)"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + }; + + Install.WantedBy = [ "graphical-session.target" ]; + + Service = { + Type = "simple"; + ExecStart = "${pkgs.poweralertd}/bin/poweralertd"; + Restart = "always"; + }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/pulseeffects.nix b/infra/libkookie/home-manager-stable/modules/services/pulseeffects.nix new file mode 100644 index 00000000000..0181e39be90 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/pulseeffects.nix @@ -0,0 +1,70 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.pulseeffects; + + presetOpts = optionalString (cfg.preset != "") "--load-preset ${cfg.preset}"; + +in { + meta.maintainers = [ maintainers.jonringer ]; + + options.services.pulseeffects = { + enable = mkEnableOption '' + Pulseeffects daemon + Note, it is necessary to add + + programs.dconf.enable = true; + + to your system configuration for the daemon to work correctly''; + + package = mkOption { + type = types.package; + default = pkgs.pulseeffects-legacy; + defaultText = literalExpression "pkgs.pulseeffects-legacy"; + description = "Pulseeffects package to use."; + }; + + preset = mkOption { + type = types.str; + default = ""; + description = '' + Which preset to use when starting pulseeffects. + Will likely need to launch pulseeffects to initially create preset. + ''; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.pulseeffects" pkgs + lib.platforms.linux) + ]; + + # running pulseeffects will just attach itself to gapplication service + # at-spi2-core is to minimize journalctl noise of: + # "AT-SPI: Error retrieving accessibility bus address: org.freedesktop.DBus.Error.ServiceUnknown: The name org.a11y.Bus was not provided by any .service files" + home.packages = [ cfg.package pkgs.at-spi2-core ]; + + systemd.user.services.pulseeffects = { + Unit = { + Description = "Pulseeffects daemon"; + Requires = [ "dbus.service" ]; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" "pulseaudio.service" ]; + }; + + Install = { WantedBy = [ "graphical-session.target" ]; }; + + Service = { + ExecStart = + "${cfg.package}/bin/pulseeffects --gapplication-service ${presetOpts}"; + ExecStop = "${cfg.package}/bin/pulseeffects --quit"; + Restart = "on-failure"; + RestartSec = 5; + }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/random-background.nix b/infra/libkookie/home-manager-stable/modules/services/random-background.nix new file mode 100644 index 00000000000..9deee8deb5c --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/random-background.nix @@ -0,0 +1,97 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.random-background; + + flags = lib.concatStringsSep " " + ([ "--bg-${cfg.display}" "--no-fehbg" "--randomize" ] + ++ lib.optional (!cfg.enableXinerama) "--no-xinerama"); + +in { + meta.maintainers = [ maintainers.rycee ]; + + options = { + services.random-background = { + enable = mkEnableOption "" // { + description = '' + Whether to enable random desktop background. + + Note, if you are using NixOS and have set up a custom + desktop manager session for Home Manager, then the session + configuration must have the + option set to true or the background + image set by this module may be overwritten. + ''; + }; + + imageDirectory = mkOption { + type = types.str; + example = "%h/backgrounds"; + description = '' + The directory of images from which a background should be + chosen. Should be formatted in a way understood by systemd, + e.g., '%h' is the home directory. + ''; + }; + + display = mkOption { + type = types.enum [ "center" "fill" "max" "scale" "tile" ]; + default = "fill"; + description = "Display background images according to this option."; + }; + + interval = mkOption { + default = null; + type = types.nullOr types.str; + example = "1h"; + description = '' + The duration between changing background image, set to null + to only set background when logging in. Should be formatted + as a duration understood by systemd. + ''; + }; + + enableXinerama = mkOption { + default = true; + type = types.bool; + description = '' + Will place a separate image per screen when enabled, + otherwise a single image will be stretched across all + screens. + ''; + }; + }; + }; + + config = mkIf cfg.enable (mkMerge ([ + { + systemd.user.services.random-background = { + Unit = { + Description = "Set random desktop background using feh"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + }; + + Service = { + Type = "oneshot"; + ExecStart = "${pkgs.feh}/bin/feh ${flags} ${cfg.imageDirectory}"; + IOSchedulingClass = "idle"; + }; + + Install = { WantedBy = [ "graphical-session.target" ]; }; + }; + } + (mkIf (cfg.interval != null) { + systemd.user.timers.random-background = { + Unit = { Description = "Set random desktop background using feh"; }; + + Timer = { OnUnitActiveSec = cfg.interval; }; + + Install = { WantedBy = [ "timers.target" ]; }; + }; + }) + ])); +} diff --git a/infra/libkookie/home-manager-stable/modules/services/redshift-gammastep/gammastep.nix b/infra/libkookie/home-manager-stable/modules/services/redshift-gammastep/gammastep.nix new file mode 100644 index 00000000000..0a7f785a249 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/redshift-gammastep/gammastep.nix @@ -0,0 +1,25 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + commonOptions = import ./lib/options.nix { + inherit config lib pkgs; + + moduleName = "gammastep"; + programName = "Gammastep"; + # https://gitlab.com/chinstrap/gammastep/-/commit/1608ed61154cc652b087e85c4ce6125643e76e2f + mainSection = "general"; + defaultPackage = pkgs.gammastep; + examplePackage = "pkgs.gammastep"; + mainExecutable = "gammastep"; + appletExecutable = "gammastep-indicator"; + xdgConfigFilePath = "gammastep/config.ini"; + serviceDocumentation = "https://gitlab.com/chinstrap/gammastep/"; + }; + +in { + inherit (commonOptions) imports meta; + options.services.gammastep = commonOptions.options; + config = mkIf config.services.gammastep.enable commonOptions.config; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/redshift-gammastep/lib/options.nix b/infra/libkookie/home-manager-stable/modules/services/redshift-gammastep/lib/options.nix new file mode 100644 index 00000000000..475cca57c30 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/redshift-gammastep/lib/options.nix @@ -0,0 +1,206 @@ +{ config, lib, pkgs, moduleName, mainSection, programName, defaultPackage +, examplePackage, mainExecutable, appletExecutable, xdgConfigFilePath +, serviceDocumentation }: + +with lib; + +let + + cfg = config.services.${moduleName}; + settingsFormat = pkgs.formats.ini { }; + +in { + meta = { + maintainers = with maintainers; [ rycee petabyteboy thiagokokada ]; + }; + + imports = let + mkRenamed = old: new: + mkRenamedOptionModule ([ "services" moduleName ] ++ old) [ + "services" + moduleName + "settings" + mainSection + new + ]; + in [ + (mkRemovedOptionModule [ "services" moduleName "extraOptions" ] + "All ${programName} configuration is now available through services.${moduleName}.settings instead.") + (mkRenamed [ "brightness" "day" ] "brightness-day") + (mkRenamed [ "brightness" "night" ] "brightness-night") + ]; + + options = { + enable = mkEnableOption programName; + + dawnTime = mkOption { + type = types.nullOr types.str; + default = null; + example = "6:00-7:45"; + description = '' + Set the time interval of dawn manually. + The times must be specified as HH:MM in 24-hour format. + ''; + }; + + duskTime = mkOption { + type = types.nullOr types.str; + default = null; + example = "18:35-20:15"; + description = '' + Set the time interval of dusk manually. + The times must be specified as HH:MM in 24-hour format. + ''; + }; + + latitude = mkOption { + type = with types; nullOr (either str float); + default = null; + description = '' + Your current latitude, between -90.0 and + 90.0. Must be provided along with + longitude. + ''; + }; + + longitude = mkOption { + type = with types; nullOr (either str float); + default = null; + description = '' + Your current longitude, between -180.0 and + 180.0. Must be provided along with + latitude. + ''; + }; + + provider = mkOption { + type = types.enum [ "manual" "geoclue2" ]; + default = "manual"; + description = '' + The location provider to use for determining your location. If set to + manual you must also provide latitude/longitude. + If set to geoclue2, you must also enable the global + geoclue2 service. + ''; + }; + + temperature = { + day = mkOption { + type = types.int; + default = 5500; + description = '' + Colour temperature to use during the day, between + 1000 and 25000 K. + ''; + }; + night = mkOption { + type = types.int; + default = 3700; + description = '' + Colour temperature to use at night, between + 1000 and 25000 K. + ''; + }; + }; + + package = mkOption { + type = types.package; + default = defaultPackage; + defaultText = literalExpression examplePackage; + description = '' + ${programName} derivation to use. + ''; + }; + + tray = mkOption { + type = types.bool; + default = false; + example = true; + description = '' + Start the ${appletExecutable} tray applet. + ''; + }; + + settings = mkOption { + type = types.submodule { freeformType = settingsFormat.type; }; + default = { }; + example = literalExpression '' + { + ${mainSection} = { + adjustment-method = "randr"; + }; + randr = { + screen = 0; + }; + }; + ''; + description = '' + The configuration to pass to ${programName}. + Available options for ${programName} described in + + ${moduleName} + 1 + . + ''; + }; + }; + + config = { + assertions = [ + (hm.assertions.assertPlatform "services.${moduleName}" pkgs + platforms.linux) + + { + assertion = (cfg.settings ? ${mainSection}.dawn-time || cfg.settings + ? ${mainSection}.dusk-time) + || (cfg.settings.${mainSection}.location-provider) == "geoclue2" + || ((cfg.settings.${mainSection}.location-provider) == "manual" + && (cfg.settings ? manual.lat || cfg.settings ? manual.lon)); + message = '' + In order for ${programName} to know the time of action, you need to set one of + - services.${moduleName}.provider = "geoclue2" for automatically inferring your location + (you also need to enable Geoclue2 service separately) + - services.${moduleName}.longitude and .latitude for specifying your location manually + - services.${moduleName}.dawnTime and .duskTime for specifying the times manually + ''; + } + ]; + + services.${moduleName}.settings = { + ${mainSection} = { + temp-day = cfg.temperature.day; + temp-night = cfg.temperature.night; + location-provider = cfg.provider; + dawn-time = mkIf (cfg.dawnTime != null) cfg.dawnTime; + dusk-time = mkIf (cfg.duskTime != null) cfg.duskTime; + }; + manual = mkIf (cfg.provider == "manual") { + lat = mkIf (cfg.latitude != null) (toString cfg.latitude); + lon = mkIf (cfg.longitude != null) (toString cfg.longitude); + }; + }; + + xdg.configFile.${xdgConfigFilePath}.source = + settingsFormat.generate xdgConfigFilePath cfg.settings; + + systemd.user.services.${moduleName} = { + Unit = { + Description = "${programName} colour temperature adjuster"; + Documentation = serviceDocumentation; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + }; + + Install = { WantedBy = [ "graphical-session.target" ]; }; + + Service = { + ExecStart = let + command = if cfg.tray then appletExecutable else mainExecutable; + configFullPath = config.xdg.configHome + "/${xdgConfigFilePath}"; + in "${cfg.package}/bin/${command} -v -c ${configFullPath}"; + RestartSec = 3; + Restart = "on-failure"; + }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/redshift-gammastep/redshift.nix b/infra/libkookie/home-manager-stable/modules/services/redshift-gammastep/redshift.nix new file mode 100644 index 00000000000..ffccb35cec6 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/redshift-gammastep/redshift.nix @@ -0,0 +1,24 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + commonOptions = import ./lib/options.nix { + inherit config lib pkgs; + + moduleName = "redshift"; + programName = "Redshift"; + mainSection = "redshift"; + defaultPackage = pkgs.redshift; + examplePackage = "pkgs.redshift"; + mainExecutable = "redshift"; + appletExecutable = "redshift-gtk"; + xdgConfigFilePath = "redshift/redshift.conf"; + serviceDocumentation = "http://jonls.dk/redshift/"; + }; + +in { + inherit (commonOptions) imports meta; + options.services.redshift = commonOptions.options; + config = mkIf config.services.redshift.enable commonOptions.config; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/rsibreak.nix b/infra/libkookie/home-manager-stable/modules/services/rsibreak.nix new file mode 100644 index 00000000000..351632a0260 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/rsibreak.nix @@ -0,0 +1,38 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.rsibreak; + +in { + options.services.rsibreak = { + + enable = mkEnableOption "rsibreak"; + + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.rsibreak" pkgs + lib.platforms.linux) + ]; + + home.packages = [ pkgs.rsibreak ]; + systemd.user.services.rsibreak = { + Unit = { + Description = "RSI break timer"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + }; + + Install = { WantedBy = [ "graphical-session.target" ]; }; + + Service = { + Environment = "PATH=${config.home.profileDirectory}/bin"; + ExecStart = "${pkgs.rsibreak}/bin/rsibreak"; + }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/screen-locker.nix b/infra/libkookie/home-manager-stable/modules/services/screen-locker.nix new file mode 100644 index 00000000000..3ea84ebedb7 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/screen-locker.nix @@ -0,0 +1,160 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.screen-locker; + +in { + meta.maintainers = [ lib.hm.maintainers.jrobsonchase ]; + + imports = let + origOpt = name: [ "services" "screen-locker" name ]; + xautolockOpt = name: [ "services" "screen-locker" "xautolock" name ]; + xssLockOpt = name: [ "services" "screen-locker" "xss-lock" name ]; + in [ + (mkRenamedOptionModule (origOpt "xssLockExtraOptions") + (xssLockOpt "extraOptions")) + (mkRenamedOptionModule (origOpt "xautolockExtraOptions") + (xautolockOpt "extraOptions")) + (mkRenamedOptionModule (origOpt "enableDetectSleep") + (xautolockOpt "detectSleep")) + ]; + + options.services.screen-locker = { + enable = mkEnableOption "screen locker for X session"; + + lockCmd = mkOption { + type = types.str; + description = "Locker command to run."; + example = "\${pkgs.i3lock}/bin/i3lock -n -c 000000"; + }; + + inactiveInterval = mkOption { + type = types.int; + default = 10; + description = '' + Inactive time interval in minutes after which session will be locked. + The minimum is 1 minute, and the maximum is 1 hour. + If is true, it will use this setting. + See . + Otherwise, this will be used with xset to configure + the X server's screensaver timeout. + ''; + }; + + xautolock = { + enable = mkOption { + type = types.bool; + default = true; + description = "Use xautolock for time-based locking."; + }; + + package = mkOption { + type = types.package; + default = pkgs.xautolock; + description = '' + Package providing the xautolock binary. + ''; + }; + + detectSleep = mkOption { + type = types.bool; + default = true; + description = '' + Whether to reset xautolock timers when awaking from sleep. + No effect if is false. + ''; + }; + + extraOptions = mkOption { + type = types.listOf types.str; + default = [ ]; + description = '' + Extra command-line arguments to pass to xautolock. + No effect if is false. + ''; + }; + }; + + xss-lock = { + package = mkOption { + type = types.package; + default = pkgs.xss-lock; + description = '' + Package providing the xss-lock binary. + ''; + }; + + extraOptions = mkOption { + type = types.listOf types.str; + default = [ ]; + description = '' + Extra command-line arguments to pass to xss-lock. + ''; + }; + + screensaverCycle = mkOption { + type = types.int; + default = 600; + description = '' + X server's screensaver cycle value expresed as seconds. + This will be used with xset to configure + the cycle along with timeout. + ''; + }; + }; + }; + + config = mkIf cfg.enable (mkMerge [ + { + assertions = [ + (lib.hm.assertions.assertPlatform "services.screen-locker" pkgs + lib.platforms.linux) + ]; + + systemd.user.services.xss-lock = { + Unit = { + Description = "xss-lock, session locker service"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + }; + + Install = { WantedBy = [ "graphical-session.target" ]; }; + + Service = { + ExecStart = concatStringsSep " " + ([ "${cfg.xss-lock.package}/bin/xss-lock" "-s \${XDG_SESSION_ID}" ] + ++ cfg.xss-lock.extraOptions ++ [ "-- ${cfg.lockCmd}" ]); + }; + }; + } + (mkIf (!cfg.xautolock.enable) { + systemd.user.services.xss-lock.Service.ExecStartPre = + "${pkgs.xorg.xset}/bin/xset s ${toString (cfg.inactiveInterval * 60)} ${ + toString cfg.xss-lock.screensaverCycle + }"; + }) + (mkIf cfg.xautolock.enable { + systemd.user.services.xautolock-session = { + Unit = { + Description = "xautolock, session locker service"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + }; + + Install = { WantedBy = [ "graphical-session.target" ]; }; + + Service = { + ExecStart = concatStringsSep " " ([ + "${cfg.xautolock.package}/bin/xautolock" + "-time ${toString cfg.inactiveInterval}" + "-locker '${pkgs.systemd}/bin/loginctl lock-session \${XDG_SESSION_ID}'" + ] ++ optional cfg.xautolock.detectSleep "-detectsleep" + ++ cfg.xautolock.extraOptions); + }; + }; + }) + ]); +} diff --git a/infra/libkookie/home-manager-stable/modules/services/spotifyd.nix b/infra/libkookie/home-manager-stable/modules/services/spotifyd.nix new file mode 100644 index 00000000000..b06749a359e --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/spotifyd.nix @@ -0,0 +1,69 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.spotifyd; + + tomlFormat = pkgs.formats.toml { }; + + configFile = tomlFormat.generate "spotifyd.conf" cfg.settings; + +in { + options.services.spotifyd = { + enable = mkEnableOption "SpotifyD connect"; + + package = mkOption { + type = types.package; + default = pkgs.spotifyd; + defaultText = literalExpression "pkgs.spotifyd"; + example = + literalExpression "(pkgs.spotifyd.override { withKeyring = true; })"; + description = '' + The spotifyd package to use. + Can be used to specify extensions. + ''; + }; + + settings = mkOption { + type = tomlFormat.type; + default = { }; + description = "Configuration for spotifyd"; + example = literalExpression '' + { + global = { + username = "Alex"; + password = "foo"; + device_name = "nix"; + }; + } + ''; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.spotifyd" pkgs + lib.platforms.linux) + ]; + + home.packages = [ cfg.package ]; + + systemd.user.services.spotifyd = { + Unit = { + Description = "spotify daemon"; + Documentation = "https://github.com/Spotifyd/spotifyd"; + }; + + Install.WantedBy = [ "default.target" ]; + + Service = { + ExecStart = + "${cfg.package}/bin/spotifyd --no-daemon --config-path ${configFile}"; + Restart = "always"; + RestartSec = 12; + }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/stalonetray.nix b/infra/libkookie/home-manager-stable/modules/services/stalonetray.nix new file mode 100644 index 00000000000..93fff3e7b5f --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/stalonetray.nix @@ -0,0 +1,89 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.stalonetray; + +in { + options = { + services.stalonetray = { + enable = mkEnableOption "Stalonetray system tray"; + + package = mkOption { + default = pkgs.stalonetray; + defaultText = literalExpression "pkgs.stalonetray"; + type = types.package; + example = literalExpression "pkgs.stalonetray"; + description = "The package to use for the Stalonetray binary."; + }; + + config = mkOption { + type = with types; attrsOf (nullOr (either str (either bool int))); + description = '' + Stalonetray configuration as a set of attributes. + ''; + default = { }; + example = { + geometry = "3x1-600+0"; + decorations = null; + icon_size = 30; + sticky = true; + background = "#cccccc"; + }; + }; + + extraConfig = mkOption { + type = types.lines; + description = "Additional configuration lines for stalonetrayrc."; + default = ""; + example = '' + geometry 3x1-600+0 + decorations none + icon_size 30 + sticky true + background "#cccccc" + ''; + }; + }; + }; + + config = mkIf cfg.enable (mkMerge [ + { + home.packages = [ cfg.package ]; + + systemd.user.services.stalonetray = { + Unit = { + Description = "Stalonetray system tray"; + PartOf = [ "tray.target" ]; + }; + + Install = { WantedBy = [ "tray.target" ]; }; + + Service = { + ExecStart = "${cfg.package}/bin/stalonetray"; + Restart = "on-failure"; + }; + }; + } + + (mkIf (cfg.config != { }) { + home.file.".stalonetrayrc".text = let + valueToString = v: + if isBool v then + (if v then "true" else "false") + else if (v == null) then + "none" + else + ''"${toString v}"''; + in concatStrings (mapAttrsToList (k: v: '' + ${k} ${valueToString v} + '') cfg.config); + }) + + (mkIf (cfg.extraConfig != "") { + home.file.".stalonetrayrc".text = cfg.extraConfig; + }) + ]); +} diff --git a/infra/libkookie/home-manager-stable/modules/services/status-notifier-watcher.nix b/infra/libkookie/home-manager-stable/modules/services/status-notifier-watcher.nix new file mode 100644 index 00000000000..c6fe08da6d0 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/status-notifier-watcher.nix @@ -0,0 +1,50 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.status-notifier-watcher; + +in { + meta.maintainers = [ hm.maintainers.pltanton ]; + + options = { + services.status-notifier-watcher = { + enable = mkEnableOption "Status Notifier Watcher"; + + package = mkOption { + default = pkgs.haskellPackages.status-notifier-item; + defaultText = + literalExpression "pkgs.haskellPackages.status-notifier-item"; + type = types.package; + example = literalExpression "pkgs.haskellPackages.status-notifier-item"; + description = + "The package to use for the status notifier watcher binary."; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.status-notifier-watcher" pkgs + lib.platforms.linux) + ]; + + systemd.user.services.status-notifier-watcher = { + Unit = { + Description = "SNI watcher"; + PartOf = [ "tray.target" ]; + Before = [ "taffybar.service" ]; + }; + + Service = { + Type = "dbus"; + BusName = "org.kde.StatusNotifierWatcher"; + ExecStart = "${cfg.package}/bin/status-notifier-watcher"; + }; + + Install = { WantedBy = [ "tray.target" "taffybar.service" ]; }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/swayidle.nix b/infra/libkookie/home-manager-stable/modules/services/swayidle.nix new file mode 100644 index 00000000000..217fb435493 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/swayidle.nix @@ -0,0 +1,118 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.swayidle; + + mkTimeout = t: + [ "timeout" (toString t.timeout) (escapeShellArg t.command) ] + ++ optionals (t.resumeCommand != null) [ + "resume" + (escapeShellArg t.resumeCommand) + ]; + + mkEvent = e: [ e.event (escapeShellArg e.command) ]; + + args = cfg.extraArgs ++ (concatMap mkTimeout cfg.timeouts) + ++ (concatMap mkEvent cfg.events); + +in { + meta.maintainers = [ maintainers.c0deaddict ]; + + options.services.swayidle = let + + timeoutModule = { ... }: { + options = { + timeout = mkOption { + type = types.ints.positive; + example = 60; + description = "Timeout in seconds."; + }; + + command = mkOption { + type = types.str; + description = "Command to run after timeout seconds of inactivity."; + }; + + resumeCommand = mkOption { + type = with types; nullOr str; + default = null; + description = "Command to run when there is activity again."; + }; + }; + }; + + eventModule = { ... }: { + options = { + event = mkOption { + type = types.enum [ "before-sleep" "after-resume" "lock" "unlock" ]; + description = "Event name."; + }; + + command = mkOption { + type = types.str; + description = "Command to run when event occurs."; + }; + }; + }; + + in { + enable = mkEnableOption "idle manager for Wayland"; + + package = mkOption { + type = types.package; + default = pkgs.swayidle; + defaultText = literalExpression "pkgs.swayidle"; + description = "Swayidle package to install."; + }; + + timeouts = mkOption { + type = with types; listOf (submodule timeoutModule); + default = [ ]; + example = literalExpression '' + [ + { timeout = 60; command = "swaylock -fF"; } + ] + ''; + description = "List of commands to run after idle timeout."; + }; + + events = mkOption { + type = with types; listOf (submodule eventModule); + default = [ ]; + example = literalExpression '' + [ + { event = "before-sleep"; command = "swaylock"; } + { event = "lock"; command = "lock"; } + ] + ''; + description = "Run command on occurence of a event."; + }; + + extraArgs = mkOption { + type = with types; listOf str; + default = [ ]; + description = "Extra arguments to pass to swayidle."; + }; + }; + + config = mkIf cfg.enable { + systemd.user.services.swayidle = { + Unit = { + Description = "Idle manager for Wayland"; + Documentation = "man:swayidle(1)"; + PartOf = [ "graphical-session.target" ]; + }; + + Service = { + Type = "simple"; + ExecStart = + "${cfg.package}/bin/swayidle -w ${concatStringsSep " " args}"; + }; + + Install = { WantedBy = [ "sway-session.target" ]; }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/sxhkd.nix b/infra/libkookie/home-manager-stable/modules/services/sxhkd.nix new file mode 100644 index 00000000000..79f17e3cd38 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/sxhkd.nix @@ -0,0 +1,81 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.sxhkd; + + keybindingsStr = concatStringsSep "\n" (mapAttrsToList (hotkey: command: + optionalString (command != null) '' + ${hotkey} + ${command} + '') cfg.keybindings); + +in { + imports = [ + (mkRemovedOptionModule [ "services" "sxhkd" "extraPath" ] + "This option is no longer needed and can be removed.") + ]; + + options.services.sxhkd = { + enable = mkEnableOption "simple X hotkey daemon"; + + package = mkOption { + type = types.package; + default = pkgs.sxhkd; + defaultText = "pkgs.sxhkd"; + description = + "Package containing the sxhkd executable."; + }; + + extraOptions = mkOption { + type = types.listOf types.str; + default = [ ]; + description = + "Command line arguments to invoke sxhkd with."; + example = literalExpression ''[ "-m 1" ]''; + }; + + keybindings = mkOption { + type = types.attrsOf (types.nullOr types.str); + default = { }; + description = "An attribute set that assigns hotkeys to commands."; + example = literalExpression '' + { + "super + shift + {r,c}" = "i3-msg {restart,reload}"; + "super + {s,w}" = "i3-msg {stacking,tabbed}"; + } + ''; + }; + + extraConfig = mkOption { + default = ""; + type = types.lines; + description = "Additional configuration to add."; + example = literalExpression '' + super + {_,shift +} {1-9,0} + i3-msg {workspace,move container to workspace} {1-10} + ''; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.sxhkd" pkgs + lib.platforms.linux) + ]; + + home.packages = [ cfg.package ]; + + xdg.configFile."sxhkd/sxhkdrc".text = + concatStringsSep "\n" [ keybindingsStr cfg.extraConfig ]; + + xsession.initExtra = let + sxhkdCommand = "${cfg.package}/bin/sxhkd ${toString cfg.extraOptions}"; + in '' + systemctl --user stop sxhkd.scope 2> /dev/null || true + systemd-cat -t sxhkd systemd-run --user --scope -u sxhkd ${sxhkdCommand} & + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/syncthing.nix b/infra/libkookie/home-manager-stable/modules/services/syncthing.nix new file mode 100644 index 00000000000..97ad586294f --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/syncthing.nix @@ -0,0 +1,137 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.syncthing; + +in { + meta.maintainers = [ maintainers.rycee ]; + + options = { + services.syncthing = { + enable = mkEnableOption "Syncthing continuous file synchronization"; + + extraOptions = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "--gui-apikey=apiKey" ]; + description = '' + Extra command-line arguments to pass to syncthing. + ''; + }; + + tray = mkOption { + type = with types; + either bool (submodule { + options = { + enable = mkOption { + type = types.bool; + default = false; + description = "Whether to enable a syncthing tray service."; + }; + + command = mkOption { + type = types.str; + default = "syncthingtray"; + defaultText = literalExpression "syncthingtray"; + example = literalExpression "qsyncthingtray"; + description = "Syncthing tray command to use."; + }; + + package = mkOption { + type = types.package; + default = pkgs.syncthingtray-minimal; + defaultText = literalExpression "pkgs.syncthingtray-minimal"; + example = literalExpression "pkgs.qsyncthingtray"; + description = "Syncthing tray package to use."; + }; + }; + }); + default = { enable = false; }; + description = "Syncthing tray service configuration."; + }; + }; + }; + + config = mkMerge [ + (mkIf cfg.enable { + home.packages = [ (getOutput "man" pkgs.syncthing) ]; + + systemd.user.services = { + syncthing = { + Unit = { + Description = + "Syncthing - Open Source Continuous File Synchronization"; + Documentation = "man:syncthing(1)"; + After = [ "network.target" ]; + }; + + Service = { + ExecStart = + "${pkgs.syncthing}/bin/syncthing -no-browser -no-restart -logflags=0" + + optionalString (cfg.extraOptions != [ ]) + (" " + escapeShellArgs cfg.extraOptions); + Restart = "on-failure"; + SuccessExitStatus = [ 3 4 ]; + RestartForceExitStatus = [ 3 4 ]; + + # Sandboxing. + LockPersonality = true; + MemoryDenyWriteExecute = true; + NoNewPrivileges = true; + PrivateUsers = true; + RestrictNamespaces = true; + SystemCallArchitectures = "native"; + SystemCallFilter = "@system-service"; + }; + + Install = { WantedBy = [ "default.target" ]; }; + }; + }; + }) + + (mkIf (isAttrs cfg.tray && cfg.tray.enable) { + systemd.user.services = { + ${cfg.tray.package.pname} = { + Unit = { + Description = cfg.tray.package.pname; + Requires = [ "tray.target" ]; + After = [ "graphical-session-pre.target" "tray.target" ]; + PartOf = [ "graphical-session.target" ]; + }; + + Service = { + ExecStart = "${cfg.tray.package}/bin/${cfg.tray.command}"; + }; + + Install = { WantedBy = [ "graphical-session.target" ]; }; + }; + }; + }) + + # deprecated + (mkIf (isBool cfg.tray && cfg.tray) { + systemd.user.services = { + "syncthingtray" = { + Unit = { + Description = "syncthingtray"; + Requires = [ "tray.target" ]; + After = [ "graphical-session-pre.target" "tray.target" ]; + PartOf = [ "graphical-session.target" ]; + }; + + Service = { + ExecStart = "${pkgs.syncthingtray-minimal}/bin/syncthingtray"; + }; + + Install = { WantedBy = [ "graphical-session.target" ]; }; + }; + }; + warnings = [ + "Specifying 'services.syncthing.tray' as a boolean is deprecated, set 'services.syncthing.tray.enable' instead. See https://github.com/nix-community/home-manager/pull/1257." + ]; + }) + ]; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/systembus-notify.nix b/infra/libkookie/home-manager-stable/modules/services/systembus-notify.nix new file mode 100644 index 00000000000..1b8f1be837e --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/systembus-notify.nix @@ -0,0 +1,27 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + meta.maintainers = [ maintainers.asymmetric ]; + + options = { + services.systembus-notify = { + enable = + mkEnableOption "systembus-notify - system bus notification daemon"; + }; + }; + + config = mkIf config.services.systembus-notify.enable { + assertions = [ + (hm.assertions.assertPlatform "services.systembus-notify" pkgs + platforms.linux) + ]; + + systemd.user.services.systembus-notify = { + Unit.Description = "systembus-notify daemon"; + Install.WantedBy = [ "graphical-session.target" ]; + Service.ExecStart = "${pkgs.systembus-notify}/bin/systembus-notify"; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/taffybar.nix b/infra/libkookie/home-manager-stable/modules/services/taffybar.nix new file mode 100644 index 00000000000..088827b9554 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/taffybar.nix @@ -0,0 +1,45 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.taffybar; + +in { + meta.maintainers = [ maintainers.rycee ]; + + options = { + services.taffybar = { + enable = mkEnableOption "Taffybar"; + + package = mkOption { + default = pkgs.taffybar; + defaultText = literalExpression "pkgs.taffybar"; + type = types.package; + example = literalExpression "pkgs.taffybar"; + description = "The package to use for the Taffybar binary."; + }; + }; + }; + + config = mkIf config.services.taffybar.enable { + systemd.user.services.taffybar = { + Unit = { + Description = "Taffybar desktop bar"; + PartOf = [ "tray.target" ]; + }; + + Service = { + Type = "dbus"; + BusName = "org.taffybar.Bar"; + ExecStart = "${cfg.package}/bin/taffybar"; + Restart = "on-failure"; + }; + + Install = { WantedBy = [ "tray.target" ]; }; + }; + + xsession.importedVariables = [ "GDK_PIXBUF_MODULE_FILE" ]; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/tahoe-lafs.nix b/infra/libkookie/home-manager-stable/modules/services/tahoe-lafs.nix new file mode 100644 index 00000000000..742b779b270 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/tahoe-lafs.nix @@ -0,0 +1,19 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + meta.maintainers = [ maintainers.rycee ]; + + options = { + services.tahoe-lafs = { enable = mkEnableOption "Tahoe-LAFS"; }; + }; + + config = mkIf config.services.tahoe-lafs.enable { + systemd.user.services.tahoe-lafs = { + Unit = { Description = "Tahoe-LAFS"; }; + + Service = { ExecStart = "${pkgs.tahoelafs}/bin/tahoe run -C %h/.tahoe"; }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/taskwarrior-sync.nix b/infra/libkookie/home-manager-stable/modules/services/taskwarrior-sync.nix new file mode 100644 index 00000000000..ddce6d6f0b4 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/taskwarrior-sync.nix @@ -0,0 +1,55 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.taskwarrior-sync; + +in { + meta.maintainers = with maintainers; [ minijackson pacien ]; + + options.services.taskwarrior-sync = { + enable = mkEnableOption "Taskwarrior periodic sync"; + + frequency = mkOption { + type = types.str; + default = "*:0/5"; + description = '' + How often to run taskwarrior sync. This + value is passed to the systemd timer configuration as the + OnCalendar option. See + + systemd.time + 7 + + for more information about the format. + ''; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.taskwarrior-sync" pkgs + lib.platforms.linux) + ]; + + systemd.user.services.taskwarrior-sync = { + Unit = { Description = "Taskwarrior sync"; }; + Service = { + CPUSchedulingPolicy = "idle"; + IOSchedulingClass = "idle"; + ExecStart = "${pkgs.taskwarrior}/bin/task synchronize"; + }; + }; + + systemd.user.timers.taskwarrior-sync = { + Unit = { Description = "Taskwarrior periodic sync"; }; + Timer = { + Unit = "taskwarrior-sync.service"; + OnCalendar = cfg.frequency; + }; + Install = { WantedBy = [ "timers.target" ]; }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/trayer.nix b/infra/libkookie/home-manager-stable/modules/services/trayer.nix new file mode 100644 index 00000000000..0621c55e600 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/trayer.nix @@ -0,0 +1,183 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + boolTrue = { + type = types.bool; + values = "true|false"; + default = "true"; + }; + + number0 = { + type = types.int; + values = "number"; + default = "0"; + }; + + knownSettings = { + edge = { + type = types.str; + values = "left|right|top|bottom|none"; + default = "bottom"; + }; + + align = { + type = types.str; + values = "left|right|center"; + default = "center"; + }; + + margin = number0; + widthtype = { + type = types.str; + values = "request|pixel|percent"; + default = "percent"; + }; + + width = { + type = types.int; + values = "number"; + default = "100"; + }; + + heighttype = { + type = types.str; + values = "request|pixel"; + default = "pixel"; + }; + + height = { + type = types.int; + values = "number"; + default = "26"; + }; + + SetDockType = boolTrue; + + SetPartialStrut = boolTrue; + + transparent = { + type = types.bool; + values = "true|false"; + default = "false"; + }; + + alpha = { + type = types.int; + values = "number"; + default = "127"; + }; + + tint = { + type = types.str; + values = "int"; + default = "0xFFFFFFFF"; + }; + + distance = number0; + + distancefrom = { + type = types.str; + values = "left|right|top|bottom"; + default = "top"; + }; + + expand = boolTrue; + + padding = number0; + + monitor = { + values = "number|primary"; + type = types.str; + default = "0"; + }; + + iconspacing = number0; + }; + + cfg = config.services.trayer; + +in { + meta.maintainers = [ hm.maintainers.mager ]; + + options = { + services.trayer = { + enable = mkEnableOption + "trayer, the lightweight GTK2+ systray for UNIX desktops"; + + package = mkOption { + default = pkgs.trayer; + defaultText = literalExpression "pkgs.trayer"; + type = types.package; + example = literalExpression "pkgs.trayer"; + description = "The package to use for the trayer binary."; + }; + + settings = mkOption { + type = with types; attrsOf (nullOr (either str (either bool int))); + description = '' + Trayer configuration as a set of attributes. Further details can be + found at . + + + + + Property Name + Type + Values + Default + + + ${concatStringsSep "\n" (mapAttrsToList (n: v: '' + + ${n} + ${v.type.description} + ${v.values} + ${v.default} + + '') knownSettings)} + + ''; + default = { }; + example = literalExpression '' + { + edge = "top"; + padding = 6; + SetDockType = true; + tint = "0x282c34"; + } + ''; + }; + }; + }; + + config = mkIf cfg.enable ({ + assertions = [ + (lib.hm.assertions.assertPlatform "services.trayer" pkgs + lib.platforms.linux) + ]; + + home.packages = [ cfg.package ]; + + systemd.user.services.trayer = let + valueToString = v: + if isBool v then (if v then "true" else "false") else "${toString v}"; + parameter = k: v: "--${k} ${valueToString v}"; + parameters = concatStringsSep " " (mapAttrsToList parameter cfg.settings); + in { + Unit = { + Description = "trayer -- lightweight GTK2+ systray for UNIX desktops"; + PartOf = [ "tray.target" ]; + }; + + Install.WantedBy = [ "tray.target" ]; + + Service = { + ExecStart = "${cfg.package}/bin/trayer ${parameters}"; + Restart = "on-failure"; + }; + }; + }); +} diff --git a/infra/libkookie/home-manager-stable/modules/services/twmn.nix b/infra/libkookie/home-manager-stable/modules/services/twmn.nix new file mode 100644 index 00000000000..d4c12682938 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/twmn.nix @@ -0,0 +1,380 @@ +{ config, lib, pkgs, stdenv, ... }: + +with lib; + +let + + cfg = config.services.twmn; + + animationOpts = { + curve = mkOption { + type = types.ints.between 0 40; + default = 38; + example = 19; + description = '' + The qt easing-curve animation to use for the animation. See + + QEasingCurve documentation. + ''; + }; + + duration = mkOption { + type = types.ints.unsigned; + default = 1000; + example = 618; + description = "The animation duration in milliseconds."; + }; + }; + +in { + meta.maintainers = [ hm.maintainers.austreelis ]; + + options.services.twmn = { + enable = mkEnableOption "twmn, a tiling window manager notification daemon"; + + duration = mkOption { + type = types.ints.unsigned; + default = 3000; + example = 5000; + description = '' + The time each notification remains visible, in milliseconds. + ''; + }; + + extraConfig = mkOption { + type = types.attrs; + default = { }; + example = literalExpression + ''{ main.activation_command = "\${pkgs.hello}/bin/hello"; }''; + description = '' + Extra configuration options to add to the twmnd config file. See + + for details. + ''; + }; + + host = mkOption { + type = types.str; + default = "127.0.0.1"; + example = "laptop.lan"; + description = "Host address to listen on for notifications."; + }; + + icons = { + critical = mkOption { + type = types.nullOr types.path; + default = null; + description = "Path to the critical notifications' icon."; + }; + + info = mkOption { + type = types.nullOr types.path; + default = null; + description = "Path to the informative notifications' icon."; + }; + + warning = mkOption { + type = types.nullOr types.path; + default = null; + description = "Path to the warning notifications' icon."; + }; + }; + + port = mkOption { + type = types.port; + default = 9797; + description = "UDP port to listen on for notifications."; + }; + + screen = mkOption { + type = types.nullOr types.int; + default = null; + example = 0; + description = '' + Screen number to display notifications on when using a multi-head + desktop. + ''; + }; + + soundCommand = mkOption { + type = types.str; + default = ""; + description = "Command to execute to play a notification's sound."; + }; + + text = { + color = mkOption { + type = types.str; + default = "#999999"; + example = "lightgray"; + description = '' + Notification's text color. RGB hex and keywords (e.g. lightgray) + are supported. + ''; + }; + + font = { + package = mkOption { + type = types.nullOr types.package; + default = null; + example = literalExpression "pkgs.dejavu_fonts"; + description = '' + Notification text's font package. If null then + the font is assumed to already be available in your profile. + ''; + }; + + family = mkOption { + type = types.str; + default = "Sans"; + example = "Noto Sans"; + description = "Notification text's font family."; + }; + + size = mkOption { + type = types.ints.unsigned; + default = 13; + example = 42; + description = "Notification text's font size."; + }; + + variant = mkOption { + # These are the font variant supported by twmn + # See https://github.com/sboli/twmn/blob/master/README.md?plain=1#L42 + type = types.enum [ + "oblique" + "italic" + "ultra-light" + "light" + "medium" + "semi-bold" + "bold" + "ultra-bold" + "heavy" + "ultra-condensed" + "extra-condensed" + "condensed" + "semi-condensed" + "semi-expanded" + "expanded" + "extra-expanded" + "ultra-expanded" + ]; + default = "medium"; + example = "heavy"; + description = "Notification text's font variant."; + }; + }; + + maxLength = mkOption { + type = types.nullOr types.ints.unsigned; + default = null; + example = 80; + description = '' + Maximum length of the text before it is cut and suffixed with "...". + Never cuts if null. + ''; + }; + }; + + window = { + alwaysOnTop = + mkEnableOption "forcing the notification window to always be on top"; + + animation = { + easeIn = mkOption { + type = types.submodule { options = animationOpts; }; + default = { }; + example = literalExpression '' + { + curve = 19; + duration = 618; + } + ''; + description = "Options for the notification appearance's animation."; + }; + + easeOut = mkOption { + type = types.submodule { options = animationOpts; }; + default = { }; + example = literalExpression '' + { + curve = 19; + duration = 618; + } + ''; + description = + "Options for the notification disappearance's animation."; + }; + + bounce = { + enable = mkEnableOption + "notification bounce when displaying next notification directly."; + + duration = mkOption { + type = types.ints.unsigned; + default = 500; + example = 618; + description = "The bounce animation duration in milliseconds."; + }; + }; + }; + + color = mkOption { + type = types.str; + default = "#000000"; + example = "lightgray"; + description = '' + Notification's background color. RGB hex and keywords (e.g. + lightgray) are supported. + ''; + }; + + height = mkOption { + type = types.ints.unsigned; + default = 18; + example = 42; + description = '' + Height of the slide bar. Useful to match your tiling window + manager's bar. + ''; + }; + + offset = { + x = mkOption { + type = types.int; + default = 0; + example = 50; + description = '' + Offset of the notification's slide starting point in pixels on the + horizontal axis (positive is rightward). + ''; + }; + + y = mkOption { + type = types.int; + default = 0; + example = -100; + description = '' + Offset of the notification's slide starting point in pixels on the + vertical axis (positive is upward). + ''; + }; + }; + + opacity = mkOption { + type = types.ints.between 0 100; + default = 100; + example = 80; + description = "The notification window's opacity."; + }; + + position = mkOption { + type = types.enum [ + "tr" + "top_right" + "tl" + "top_left" + "br" + "bottom_right" + "bl" + "bottom_left" + "tc" + "top_center" + "bc" + "bottom_center" + "c" + "center" + ]; + default = "top_right"; + example = "bottom_left"; + description = '' + Position of the notification slide. The notification will slide + in vertically from the border if placed in + top_center or bottom_center, + horizontally otherwise. + ''; + }; + }; + }; + + ################# + # Implementation + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.twmn" pkgs + lib.platforms.linux) + ]; + + home.packages = + lib.optional (!isNull cfg.text.font.package) cfg.text.font.package + ++ [ pkgs.twmn ]; + + xdg.configFile."twmn/twmn.conf".text = let + conf = recursiveUpdate { + gui = { + always_on_top = if cfg.window.alwaysOnTop then "true" else "false"; + background_color = cfg.window.color; + bounce = + if cfg.window.animation.bounce.enable then "true" else "false"; + bounce_duration = toString cfg.window.animation.bounce.duration; + font = cfg.text.font.family; + font_size = toString cfg.text.font.size; + font_variant = cfg.text.font.variant; + foreground_color = cfg.text.color; + height = toString cfg.window.height; + in_animation = toString cfg.window.animation.easeIn.curve; + in_animation_duration = toString cfg.window.animation.easeIn.duration; + max_length = toString + (if isNull cfg.text.maxLength then -1 else cfg.text.maxLength); + offset_x = with cfg.window.offset; + if x < 0 then toString x else "+${toString x}"; + offset_y = with cfg.window.offset; + if y < 0 then toString y else "+${toString y}"; + opacity = toString cfg.window.opacity; + out_animation = toString cfg.window.animation.easeOut.curve; + out_animation_duration = + toString cfg.window.animation.easeOut.duration; + position = cfg.window.position; + screen = toString cfg.screen; + }; + # map null values to empty strings because formats.toml generator fails + # when encountering a null. + icons = mapAttrs (_: toString) cfg.icons; + main = { + duration = toString cfg.duration; + host = cfg.host; + port = toString cfg.port; + sound_command = cfg.soundCommand; + }; + } cfg.extraConfig; + + mkLine = name: value: "${name}=${value}"; + + mkSection = section: conf: '' + [${section}] + ${concatStringsSep "\n" (mapAttrsToList mkLine conf)} + ''; + in concatStringsSep "\n" (mapAttrsToList mkSection conf) + "\n"; + + systemd.user.services.twmnd = { + Unit = { + Description = "twmn daemon"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + X-Restart-Triggers = + [ "${config.xdg.configFile."twmn/twmn.conf".source}" ]; + }; + + Install.WantedBy = [ "graphical-session.target" ]; + + Service = { + ExecStart = "${pkgs.twmn}/bin/twmnd"; + Restart = "on-failure"; + Type = "simple"; + StandardOutput = "null"; + }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/udiskie.nix b/infra/libkookie/home-manager-stable/modules/services/udiskie.nix new file mode 100644 index 00000000000..331e65ffc83 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/udiskie.nix @@ -0,0 +1,90 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.udiskie; + + commandArgs = concatStringsSep " " (map (opt: "-" + opt) [ + (if cfg.automount then "a" else "A") + (if cfg.notify then "n" else "N") + ({ + always = "t"; + auto = "s"; + never = "T"; + }.${cfg.tray}) + ] ++ optional config.xsession.preferStatusNotifierItems "--appindicator"); + +in { + meta.maintainers = [ maintainers.rycee ]; + + imports = [ + (mkRemovedOptionModule [ "services" "udiskie" "sni" ] '' + Support for Status Notifier Items is now configured globally through the + + xsession.preferStatusNotifierItems + + option. Please change to use that instead. + '') + ]; + + options = { + services.udiskie = { + enable = mkEnableOption "udiskie mount daemon"; + + automount = mkOption { + type = types.bool; + default = true; + description = "Whether to automatically mount new devices."; + }; + + notify = mkOption { + type = types.bool; + default = true; + description = "Whether to show pop-up notifications."; + }; + + tray = mkOption { + type = types.enum [ "always" "auto" "never" ]; + default = "auto"; + description = '' + Whether to display tray icon. + + The options are + + + always + Always show tray icon. + + + auto + + Show tray icon only when there is a device available. + + + + never + Never show tray icon. + + + ''; + }; + }; + }; + + config = mkIf config.services.udiskie.enable { + systemd.user.services.udiskie = { + Unit = { + Description = "udiskie mount daemon"; + Requires = [ "tray.target" ]; + After = [ "graphical-session-pre.target" "tray.target" ]; + PartOf = [ "graphical-session.target" ]; + }; + + Service = { ExecStart = "${pkgs.udiskie}/bin/udiskie ${commandArgs}"; }; + + Install = { WantedBy = [ "graphical-session.target" ]; }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/unclutter.nix b/infra/libkookie/home-manager-stable/modules/services/unclutter.nix new file mode 100644 index 00000000000..e08c23eb3ef --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/unclutter.nix @@ -0,0 +1,66 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let cfg = config.services.unclutter; + +in { + options.services.unclutter = { + + enable = mkEnableOption "unclutter"; + + package = mkOption { + description = "unclutter derivation to use."; + type = types.package; + default = pkgs.unclutter-xfixes; + defaultText = literalExpression "pkgs.unclutter-xfixes"; + }; + + timeout = mkOption { + description = "Number of seconds before the cursor is marked inactive."; + type = types.int; + default = 1; + }; + + threshold = mkOption { + description = "Minimum number of pixels considered cursor movement."; + type = types.int; + default = 1; + }; + + extraOptions = mkOption { + description = "More arguments to pass to the unclutter command."; + type = types.listOf types.str; + default = [ ]; + example = [ "exclude-root" "ignore-scrolling" ]; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.unclutter" pkgs + lib.platforms.linux) + ]; + + systemd.user.services.unclutter = { + Unit = { + Description = "unclutter"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + }; + + Service = { + ExecStart = '' + ${cfg.package}/bin/unclutter \ + --timeout ${toString cfg.timeout} \ + --jitter ${toString (cfg.threshold - 1)} \ + ${concatMapStrings (x: " --${x}") cfg.extraOptions} + ''; + RestartSec = 3; + Restart = "always"; + }; + + Install = { WantedBy = [ "graphical-session.target" ]; }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/unison.nix b/infra/libkookie/home-manager-stable/modules/services/unison.nix new file mode 100644 index 00000000000..d7f8a628a59 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/unison.nix @@ -0,0 +1,128 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.unison; + + pairOf = t: + let list = types.addCheck (types.listOf t) (l: length l == 2); + in list // { description = list.description + " of length 2"; }; + + pairOptions = { + options = { + stateDirectory = mkOption { + type = types.path; + default = "${config.xdg.dataHome}/unison"; + defaultText = "$XDG_DATA_HOME/unison"; + description = '' + Unison state directory to use. + ''; + }; + + commandOptions = mkOption rec { + type = with types; attrsOf str; + apply = mergeAttrs default; + default = { + repeat = "watch"; + sshcmd = "${pkgs.openssh}/bin/ssh"; + ui = "text"; + auto = "true"; + batch = "true"; + log = "false"; # don't log to file, handled by systemd + }; + description = '' + Additional command line options as a dictionary to pass to the + unison program. + + See + + unison + 1 + + for a list of available options. + ''; + }; + + roots = mkOption { + type = pairOf types.str; + example = literalExpression '' + [ + "/home/user/documents" + "ssh://remote/documents" + ] + ''; + description = '' + Pair of roots to synchronise. + ''; + }; + }; + }; + + serialiseArg = key: val: escapeShellArg "-${key}=${escape [ "=" ] val}"; + + serialiseArgs = args: concatStringsSep " " (mapAttrsToList serialiseArg args); + + makeDefs = gen: + mapAttrs' + (name: pairCfg: nameValuePair "unison-pair-${name}" (gen name pairCfg)) + cfg.pairs; + +in { + meta.maintainers = with maintainers; [ pacien ]; + + options.services.unison = { + enable = mkEnableOption "Unison synchronisation"; + + pairs = mkOption { + type = with types; attrsOf (submodule pairOptions); + default = { }; + example = literalExpression '' + { + "my-documents" = { + roots = [ + "/home/user/documents" + "ssh://remote/documents" + ]; + }; + } + ''; + description = '' + Unison root pairs to keep synchronised. + ''; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.unison" pkgs + lib.platforms.linux) + ]; + + systemd.user.services = makeDefs (name: pairCfg: { + Unit = { + Description = "Unison pair sync (${name})"; + # Retry forever, useful in case of network disruption. + StartLimitIntervalSec = 0; + }; + + Service = { + Restart = "always"; + RestartSec = 60; + + CPUSchedulingPolicy = "idle"; + IOSchedulingClass = "idle"; + + Environment = [ "UNISON='${toString pairCfg.stateDirectory}'" ]; + ExecStart = '' + ${pkgs.unison}/bin/unison \ + ${serialiseArgs pairCfg.commandOptions} \ + ${strings.concatMapStringsSep " " escapeShellArg pairCfg.roots} + ''; + }; + + Install = { WantedBy = [ "default.target" ]; }; + }); + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/volnoti.nix b/infra/libkookie/home-manager-stable/modules/services/volnoti.nix new file mode 100644 index 00000000000..016fe7ab762 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/volnoti.nix @@ -0,0 +1,43 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.volnoti; + +in { + meta.maintainers = [ maintainers.imalison ]; + + options = { + services.volnoti = { + enable = mkEnableOption "Volnoti volume HUD daemon"; + + package = mkOption { + type = types.package; + default = pkgs.volnoti; + defaultText = literalExpression "pkgs.volnoti"; + description = '' + Package containing the volnoti program. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.volnoti" pkgs + lib.platforms.linux) + ]; + + home.packages = [ cfg.package ]; + + systemd.user.services.volnoti = { + Unit = { Description = "volnoti"; }; + + Install = { WantedBy = [ "graphical-session.target" ]; }; + + Service = { ExecStart = "${pkgs.volnoti}/bin/volnoti -v -n"; }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/window-managers/awesome.nix b/infra/libkookie/home-manager-stable/modules/services/window-managers/awesome.nix new file mode 100644 index 00000000000..a012a03c678 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/window-managers/awesome.nix @@ -0,0 +1,58 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.xsession.windowManager.awesome; + awesome = cfg.package; + getLuaPath = lib: dir: "${lib}/${dir}/lua/${pkgs.luaPackages.lua.luaversion}"; + makeSearchPath = lib.concatMapStrings (path: + " --search ${getLuaPath path "share"}" + + " --search ${getLuaPath path "lib"}"); + +in { + options = { + xsession.windowManager.awesome = { + enable = mkEnableOption "Awesome window manager"; + + package = mkOption { + type = types.package; + default = pkgs.awesome; + defaultText = literalExpression "pkgs.awesome"; + description = "Package to use for running the Awesome WM."; + }; + + luaModules = mkOption { + default = [ ]; + type = types.listOf types.package; + description = '' + List of lua packages available for being + used in the Awesome configuration. + ''; + example = literalExpression "[ pkgs.luaPackages.vicious ]"; + }; + + noArgb = mkOption { + default = false; + type = types.bool; + description = '' + Disable client transparency support, which can be greatly + detrimental to performance in some setups + ''; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (hm.assertions.assertPlatform "xsession.windowManager.awesome" pkgs + platforms.linux) + ]; + + home.packages = [ awesome ]; + + xsession.windowManager.command = "${awesome}/bin/awesome " + + optionalString cfg.noArgb "--no-argb " + makeSearchPath cfg.luaModules; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/window-managers/bspwm/default.nix b/infra/libkookie/home-manager-stable/modules/services/window-managers/bspwm/default.nix new file mode 100644 index 00000000000..f20c0122110 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/window-managers/bspwm/default.nix @@ -0,0 +1,89 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.xsession.windowManager.bspwm; + + camelToSnake = + builtins.replaceStrings upperChars (map (c: "_${c}") lowerChars); + + formatMonitor = monitor: desktops: + let + resetDesktops = + "bspc monitor ${escapeShellArg monitor} -d ${escapeShellArgs desktops}"; + defaultDesktopName = + "Desktop"; # https://github.com/baskerville/bspwm/blob/master/src/desktop.h + in if cfg.alwaysResetDesktops then + resetDesktops + else '' + if [[ $(bspc query --desktops --names --monitor ${ + escapeShellArg monitor + }) == ${defaultDesktopName} ]]; then + ${resetDesktops} + fi''; + + formatValue = v: + if isList v then + concatMapStringsSep "," formatValue v + else if isBool v then + if v then "on" else "off" + else if isInt v || isFloat v then + toString v + else if isString v then + v + else + throw "unsupported type"; # should not happen + + formatSetting = n: v: "bspc config ${escapeShellArgs [ n (formatValue v) ]}"; + + formatRule = target: directives: + let + formatDirective = n: v: "${camelToSnake n}=${formatValue v}"; + + directivesStr = escapeShellArgs (mapAttrsToList formatDirective + (filterAttrs (n: v: v != null) directives)); + in "bspc rule -a ${escapeShellArg target} ${directivesStr}"; + + formatStartupProgram = s: "${s} &"; + +in { + meta.maintainers = [ maintainers.ncfavier ]; + + options = import ./options.nix { inherit pkgs lib; }; + + config = mkIf cfg.enable { + assertions = [ + (hm.assertions.assertPlatform "xsession.windowManager.bspwm" pkgs + platforms.linux) + ]; + + home.packages = [ cfg.package ]; + + xdg.configFile."bspwm/bspwmrc".source = pkgs.writeShellScript "bspwmrc" '' + ${concatStringsSep "\n" (mapAttrsToList formatMonitor cfg.monitors)} + + ${concatStringsSep "\n" (mapAttrsToList formatSetting cfg.settings)} + + bspc rule -r '*' + ${concatStringsSep "\n" (mapAttrsToList formatRule cfg.rules)} + + # java gui fixes + export _JAVA_AWT_WM_NONREPARENTING=1 + bspc rule -a sun-awt-X11-XDialogPeer state=floating + + ${cfg.extraConfig} + ${concatMapStringsSep "\n" formatStartupProgram cfg.startupPrograms} + ''; + + # for applications not started by bspwm, e.g. sxhkd + xsession.profileExtra = '' + # java gui fixes + export _JAVA_AWT_WM_NONREPARENTING=1 + ''; + + xsession.windowManager.command = + "${cfg.package}/bin/bspwm -c ${config.xdg.configHome}/bspwm/bspwmrc"; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/window-managers/bspwm/options.nix b/infra/libkookie/home-manager-stable/modules/services/window-managers/bspwm/options.nix new file mode 100644 index 00000000000..57a1d874ad4 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/window-managers/bspwm/options.nix @@ -0,0 +1,230 @@ +{ pkgs, lib }: + +with lib; + +let + + rule = types.submodule { + options = { + monitor = mkOption { + type = types.nullOr types.str; + default = null; + description = "The monitor where the rule should be applied."; + example = "HDMI-0"; + }; + + desktop = mkOption { + type = types.nullOr types.str; + default = null; + description = "The desktop where the rule should be applied."; + example = "^8"; + }; + + node = mkOption { + type = types.nullOr types.str; + default = null; + description = "The node where the rule should be applied."; + example = "1"; + }; + + state = mkOption { + type = types.nullOr + (types.enum [ "tiled" "pseudo_tiled" "floating" "fullscreen" ]); + default = null; + description = "The state in which a new window should spawn."; + example = "floating"; + }; + + layer = mkOption { + type = types.nullOr (types.enum [ "below" "normal" "above" ]); + default = null; + description = "The layer where a new window should spawn."; + example = "above"; + }; + + splitDir = mkOption { + type = types.nullOr (types.enum [ "north" "west" "south" "east" ]); + default = null; + description = "The direction where the container is going to be split."; + example = "south"; + }; + + splitRatio = mkOption { + type = types.nullOr types.float; + default = null; + description = '' + The ratio between the new window and the previous existing window in + the desktop. + ''; + example = 0.65; + }; + + hidden = mkOption { + type = types.nullOr types.bool; + default = null; + description = "Whether the node should occupy any space."; + example = true; + }; + + sticky = mkOption { + type = types.nullOr types.bool; + default = null; + description = "Whether the node should stay on the focused desktop."; + example = true; + }; + + private = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + Whether the node should stay in the same tiling position and size. + ''; + example = true; + }; + + locked = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + Whether the node should ignore node --close + messages. + ''; + example = true; + }; + + marked = mkOption { + type = types.nullOr types.bool; + default = null; + description = "Whether the node will be marked for deferred actions."; + example = true; + }; + + center = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + Whether the node will be put in the center, in floating mode. + ''; + example = true; + }; + + follow = mkOption { + type = types.nullOr types.bool; + default = null; + description = "Whether focus should follow the node when it is moved."; + example = true; + }; + + manage = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + Whether the window should be managed by bspwm. If false, the window + will be ignored by bspwm entirely. This is useful for overlay apps, + e.g. screenshot tools. + ''; + example = true; + }; + + focus = mkOption { + type = types.nullOr types.bool; + default = null; + description = "Whether the node should gain focus on creation."; + example = true; + }; + + border = mkOption { + type = types.nullOr types.bool; + default = null; + description = "Whether the node should have border."; + example = true; + }; + }; + }; + +in { + xsession.windowManager.bspwm = { + enable = mkEnableOption "bspwm window manager"; + + package = mkOption { + type = types.package; + default = pkgs.bspwm; + defaultText = literalExpression "pkgs.bspwm"; + description = "The bspwm package to use."; + example = literalExpression "pkgs.bspwm-unstable"; + }; + + settings = mkOption { + type = with types; + let primitive = either bool (either int (either float str)); + in attrsOf (either primitive (listOf primitive)); + default = { }; + description = "General settings given to bspc config."; + example = { + "border_width" = 2; + "split_ratio" = 0.52; + "gapless_monocle" = true; + }; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = + "Additional shell commands to be run at the end of the config file."; + example = '' + bspc subscribe all > ~/bspc-report.log & + ''; + }; + + monitors = mkOption { + type = types.attrsOf (types.listOf types.str); + default = { }; + description = + "Specifies the names of desktops to create on each monitor."; + example = { "HDMI-0" = [ "web" "terminal" "III" "IV" ]; }; + }; + + alwaysResetDesktops = mkOption { + type = types.bool; + default = true; + description = '' + If set to true, desktops configured in will be reset + every time the config is run. + + If set to false, desktops will only be configured the first time the config is run. + This is useful if you want to dynamically add desktops and you don't want them to be destroyed if you + re-run bspwmrc. + ''; + }; + + rules = mkOption { + type = types.attrsOf rule; + default = { }; + description = + "Rule configuration. The keys of the attribute set are the targets of the rules."; + example = literalExpression '' + { + "Gimp" = { + desktop = "^8"; + state = "floating"; + follow = true; + }; + "Kupfer.py" = { + focus = true; + }; + "Screenkey" = { + manage = false; + }; + } + ''; + }; + + startupPrograms = mkOption { + type = types.listOf types.str; + default = [ ]; + description = "Programs to be executed during startup."; + example = [ "numlockx on" "tilda" ]; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/window-managers/herbstluftwm.nix b/infra/libkookie/home-manager-stable/modules/services/window-managers/herbstluftwm.nix new file mode 100644 index 00000000000..cbbe3cefd05 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/window-managers/herbstluftwm.nix @@ -0,0 +1,171 @@ +{ config, lib, pkgs, ... }: + +let + + cfg = config.xsession.windowManager.herbstluftwm; + + renderValue = val: + if lib.isBool val then + if val then "true" else "false" + else + lib.escapeShellArg val; + + renderSettings = settings: + lib.concatStringsSep "\n" (lib.mapAttrsToList + (name: value: "herbstclient set ${name} ${renderValue value}") settings); + + renderKeybinds = keybinds: + lib.concatStringsSep "\n" + (lib.mapAttrsToList (key: cmd: "herbstclient keybind ${key} ${cmd}") + keybinds); + + renderMousebinds = mousebinds: + lib.concatStringsSep "\n" + (lib.mapAttrsToList (btn: cmd: "herbstclient mousebind ${btn} ${cmd}") + mousebinds); + + renderRules = rules: + lib.concatStringsSep "\n" (map (rule: "herbstclient rule ${rule}") rules); + + settingType = lib.types.oneOf [ lib.types.bool lib.types.int lib.types.str ]; + +in { + meta.maintainers = [ lib.hm.maintainers.olmokramer ]; + + options.xsession.windowManager.herbstluftwm = { + enable = lib.mkEnableOption "herbstluftwm window manager"; + + package = lib.mkOption { + type = lib.types.package; + default = pkgs.herbstluftwm; + defaultText = lib.literalExpression "pkgs.herbstluftwm"; + description = '' + Package providing the herbstluftwm and + herbstclient commands. + ''; + }; + + settings = lib.mkOption { + type = lib.types.attrsOf settingType; + default = { }; + example = lib.literalExpression '' + { + gapless_grid = false; + window_border_width = 1; + window_border_active_color = "#FF0000"; + } + ''; + description = "Herbstluftwm settings."; + }; + + keybinds = lib.mkOption { + type = lib.types.attrsOf lib.types.str; + default = { }; + example = lib.literalExpression '' + { + Mod4-o = "split right"; + Mod4-u = "split bottom"; + } + ''; + description = "Herbstluftwm keybinds."; + }; + + mousebinds = lib.mkOption { + type = lib.types.attrsOf lib.types.str; + default = { }; + example = lib.literalExpression '' + { + Mod4-B1 = "move"; + Mod4-B3 = "resize"; + } + ''; + description = "Herbstluftwm mousebinds."; + }; + + rules = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = [ ]; + example = lib.literalExpression '' + [ + "windowtype~'_NET_WM_WINDOW_TYPE_(DIALOG|UTILITY|SPLASH)' focus=on pseudotile=on" + "windowtype~'_NET_WM_WINDOW_TYPE_(NOTIFICATION|DOCK|DESKTOP)' manage=off" + ] + ''; + description = "Herbstluftwm rules."; + }; + + tags = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = [ ]; + example = lib.literalExpression '' + [ "work" "browser" "music" "gaming" ] + ''; + description = "Tags to create on startup."; + }; + + extraConfig = lib.mkOption { + type = lib.types.lines; + default = ""; + example = '' + herbstclient set_layout max + herbstclient detect_monitors + ''; + description = '' + Extra configuration lines to add verbatim to + $XDG_CONFIG_HOME/herbstluftwm/autostart. + ''; + }; + }; + + config = lib.mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "xsession.windowManager.herbstluftwm" + pkgs lib.platforms.linux) + ]; + + home.packages = [ cfg.package ]; + + xsession.windowManager.command = "${cfg.package}/bin/herbstluftwm --locked"; + + xdg.configFile."herbstluftwm/autostart".source = + pkgs.writeShellScript "herbstluftwm-autostart" '' + shopt -s expand_aliases + + # shellcheck disable=SC2142 + alias herbstclient='set -- "$@" ";"' + set -- + + herbstclient emit_hook reload + + # Reset everything. + herbstclient attr theme.tiling.reset 1 + herbstclient attr theme.floating.reset 1 + herbstclient keyunbind --all + herbstclient unrule --all + + ${renderSettings cfg.settings} + + if ${cfg.package}/bin/herbstclient object_tree tags.by-name | ${pkgs.gnugrep}/bin/grep default; then + herbstclient rename default ${ + lib.escapeShellArg (builtins.head cfg.tags) + } + fi + + for tag in ${lib.escapeShellArgs cfg.tags}; do + herbstclient add "$tag" + done + + ${renderKeybinds cfg.keybinds} + + ${renderMousebinds cfg.mousebinds} + + ${renderRules cfg.rules} + + ${cfg.extraConfig} + + herbstclient unlock + + ${cfg.package}/bin/herbstclient chain ";" "$@" + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/window-managers/i3-sway/i3.nix b/infra/libkookie/home-manager-stable/modules/services/window-managers/i3-sway/i3.nix new file mode 100644 index 00000000000..16e82d1638d --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/window-managers/i3-sway/i3.nix @@ -0,0 +1,283 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.xsession.windowManager.i3; + + commonOptions = import ./lib/options.nix { + inherit config lib cfg pkgs; + moduleName = "i3"; + isGaps = cfg.package == pkgs.i3-gaps; + }; + + configModule = types.submodule { + options = { + inherit (commonOptions) + fonts window floating focus assigns modifier workspaceLayout + workspaceAutoBackAndForth keycodebindings colors bars startup gaps menu + terminal defaultWorkspace workspaceOutputAssign; + + keybindings = mkOption { + type = types.attrsOf (types.nullOr types.str); + default = mapAttrs (n: mkOptionDefault) { + "${cfg.config.modifier}+Return" = "exec ${cfg.config.terminal}"; + "${cfg.config.modifier}+Shift+q" = "kill"; + "${cfg.config.modifier}+d" = "exec ${cfg.config.menu}"; + + "${cfg.config.modifier}+Left" = "focus left"; + "${cfg.config.modifier}+Down" = "focus down"; + "${cfg.config.modifier}+Up" = "focus up"; + "${cfg.config.modifier}+Right" = "focus right"; + + "${cfg.config.modifier}+Shift+Left" = "move left"; + "${cfg.config.modifier}+Shift+Down" = "move down"; + "${cfg.config.modifier}+Shift+Up" = "move up"; + "${cfg.config.modifier}+Shift+Right" = "move right"; + + "${cfg.config.modifier}+h" = "split h"; + "${cfg.config.modifier}+v" = "split v"; + "${cfg.config.modifier}+f" = "fullscreen toggle"; + + "${cfg.config.modifier}+s" = "layout stacking"; + "${cfg.config.modifier}+w" = "layout tabbed"; + "${cfg.config.modifier}+e" = "layout toggle split"; + + "${cfg.config.modifier}+Shift+space" = "floating toggle"; + "${cfg.config.modifier}+space" = "focus mode_toggle"; + + "${cfg.config.modifier}+a" = "focus parent"; + + "${cfg.config.modifier}+Shift+minus" = "move scratchpad"; + "${cfg.config.modifier}+minus" = "scratchpad show"; + + "${cfg.config.modifier}+1" = "workspace number 1"; + "${cfg.config.modifier}+2" = "workspace number 2"; + "${cfg.config.modifier}+3" = "workspace number 3"; + "${cfg.config.modifier}+4" = "workspace number 4"; + "${cfg.config.modifier}+5" = "workspace number 5"; + "${cfg.config.modifier}+6" = "workspace number 6"; + "${cfg.config.modifier}+7" = "workspace number 7"; + "${cfg.config.modifier}+8" = "workspace number 8"; + "${cfg.config.modifier}+9" = "workspace number 9"; + "${cfg.config.modifier}+0" = "workspace number 10"; + + "${cfg.config.modifier}+Shift+1" = + "move container to workspace number 1"; + "${cfg.config.modifier}+Shift+2" = + "move container to workspace number 2"; + "${cfg.config.modifier}+Shift+3" = + "move container to workspace number 3"; + "${cfg.config.modifier}+Shift+4" = + "move container to workspace number 4"; + "${cfg.config.modifier}+Shift+5" = + "move container to workspace number 5"; + "${cfg.config.modifier}+Shift+6" = + "move container to workspace number 6"; + "${cfg.config.modifier}+Shift+7" = + "move container to workspace number 7"; + "${cfg.config.modifier}+Shift+8" = + "move container to workspace number 8"; + "${cfg.config.modifier}+Shift+9" = + "move container to workspace number 9"; + "${cfg.config.modifier}+Shift+0" = + "move container to workspace number 10"; + + "${cfg.config.modifier}+Shift+c" = "reload"; + "${cfg.config.modifier}+Shift+r" = "restart"; + "${cfg.config.modifier}+Shift+e" = + "exec i3-nagbar -t warning -m 'Do you want to exit i3?' -b 'Yes' 'i3-msg exit'"; + + "${cfg.config.modifier}+r" = "mode resize"; + }; + defaultText = "Default i3 keybindings."; + description = '' + An attribute set that assigns a key press to an action using a key symbol. + See . + + Consider to use lib.mkOptionDefault function to extend or override + default keybindings instead of specifying all of them from scratch. + ''; + example = literalExpression '' + let + modifier = config.xsession.windowManager.i3.config.modifier; + in lib.mkOptionDefault { + "''${modifier}+Return" = "exec i3-sensible-terminal"; + "''${modifier}+Shift+q" = "kill"; + "''${modifier}+d" = "exec \${pkgs.dmenu}/bin/dmenu_run"; + } + ''; + }; + + modes = mkOption { + type = types.attrsOf (types.attrsOf types.str); + default = { + resize = { + "Left" = "resize shrink width 10 px or 10 ppt"; + "Down" = "resize grow height 10 px or 10 ppt"; + "Up" = "resize shrink height 10 px or 10 ppt"; + "Right" = "resize grow width 10 px or 10 ppt"; + "Escape" = "mode default"; + "Return" = "mode default"; + }; + }; + description = '' + An attribute set that defines binding modes and keybindings + inside them + + Only basic keybinding is supported (bindsym keycomb action), + for more advanced setup use 'i3.extraConfig'. + ''; + }; + }; + }; + + commonFunctions = import ./lib/functions.nix { + inherit config cfg lib; + moduleName = "i3"; + }; + + inherit (commonFunctions) + keybindingsStr keycodebindingsStr modeStr assignStr barStr gapsStr + floatingCriteriaStr windowCommandsStr colorSetStr windowBorderString + fontConfigStr keybindingDefaultWorkspace keybindingsRest workspaceOutputStr; + + startupEntryStr = { command, always, notification, workspace, ... }: + concatStringsSep " " [ + (if always then "exec_always" else "exec") + (if (notification && workspace == null) then "" else "--no-startup-id") + (if (workspace == null) then + command + else + "i3-msg 'workspace ${workspace}; exec ${command}'") + ]; + + configFile = pkgs.writeText "i3.conf" (concatStringsSep "\n" + ((if cfg.config != null then + with cfg.config; + ([ + (fontConfigStr fonts) + "floating_modifier ${floating.modifier}" + (windowBorderString window floating) + "hide_edge_borders ${window.hideEdgeBorders}" + "force_focus_wrapping ${lib.hm.booleans.yesNo focus.forceWrapping}" + "focus_follows_mouse ${lib.hm.booleans.yesNo focus.followMouse}" + "focus_on_window_activation ${focus.newWindow}" + "mouse_warping ${if focus.mouseWarping then "output" else "none"}" + "workspace_layout ${workspaceLayout}" + "workspace_auto_back_and_forth ${ + lib.hm.booleans.yesNo workspaceAutoBackAndForth + }" + "client.focused ${colorSetStr colors.focused}" + "client.focused_inactive ${colorSetStr colors.focusedInactive}" + "client.unfocused ${colorSetStr colors.unfocused}" + "client.urgent ${colorSetStr colors.urgent}" + "client.placeholder ${colorSetStr colors.placeholder}" + "client.background ${colors.background}" + (keybindingsStr { keybindings = keybindingDefaultWorkspace; }) + (keybindingsStr { keybindings = keybindingsRest; }) + (keycodebindingsStr keycodebindings) + ] ++ mapAttrsToList (modeStr false) modes + ++ mapAttrsToList assignStr assigns ++ map barStr bars + ++ optional (gaps != null) gapsStr + ++ map floatingCriteriaStr floating.criteria + ++ map windowCommandsStr window.commands ++ map startupEntryStr startup + ++ map workspaceOutputStr workspaceOutputAssign) + else + [ ]) ++ [ cfg.extraConfig ])); + + # Validates the i3 configuration + checkI3Config = + pkgs.runCommandLocal "i3-config" { buildInputs = [ cfg.package ]; } '' + # We have to make sure the wrapper does not start a dbus session + export DBUS_SESSION_BUS_ADDRESS=1 + + # A zero exit code means i3 succesfully validated the configuration + i3 -c ${configFile} -C -d all || { + echo "i3 configuration validation failed" + echo "For a verbose log of the failure, run 'i3 -c ${configFile} -C -d all'" + exit 1 + }; + cp ${configFile} $out + ''; + +in { + meta.maintainers = with maintainers; [ sumnerevans sebtm ]; + + options = { + xsession.windowManager.i3 = { + enable = mkEnableOption "i3 window manager"; + + package = mkOption { + type = types.package; + default = pkgs.i3; + defaultText = literalExpression "pkgs.i3"; + example = literalExpression "pkgs.i3-gaps"; + description = '' + i3 package to use. + If 'i3.config.gaps' settings are specified, 'pkgs.i3-gaps' will be set as a default package. + ''; + }; + + config = mkOption { + type = types.nullOr configModule; + default = { }; + description = "i3 configuration options."; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = + "Extra configuration lines to add to ~/.config/i3/config."; + }; + }; + }; + + config = mkIf cfg.enable (mkMerge [ + { + assertions = [ + (hm.assertions.assertPlatform "xsession.windowManager.i3" pkgs + platforms.linux) + ]; + + home.packages = [ cfg.package ]; + + xsession.windowManager.command = "${cfg.package}/bin/i3"; + + xdg.configFile."i3/config" = { + source = checkI3Config; + onChange = '' + i3Socket=''${XDG_RUNTIME_DIR:-/run/user/$UID}/i3/ipc-socket.* + if [ -S $i3Socket ]; then + ${cfg.package}/bin/i3-msg -s $i3Socket reload >/dev/null + fi + ''; + }; + } + + (mkIf (cfg.config != null) { + xsession.windowManager.i3.package = + mkDefault (if (cfg.config.gaps != null) then pkgs.i3-gaps else pkgs.i3); + }) + + (mkIf (cfg.config != null) { + warnings = (optional (isList cfg.config.fonts) + "Specifying i3.config.fonts as a list is deprecated. Use the attrset version instead.") + ++ flatten (map (b: + optional (isList b.fonts) + "Specifying i3.config.bars[].fonts as a list is deprecated. Use the attrset version instead.") + cfg.config.bars); + }) + + (mkIf (cfg.config != null + && (any (s: s.workspace != null) cfg.config.startup)) { + warnings = [ + ("'xsession.windowManager.i3.config.startup.*.workspace' is deprecated, " + + "use 'xsession.windowManager.i3.config.assigns' instead." + + "See https://github.com/nix-community/home-manager/issues/265.") + ]; + }) + ]); +} diff --git a/infra/libkookie/home-manager-stable/modules/services/window-managers/i3-sway/lib/functions.nix b/infra/libkookie/home-manager-stable/modules/services/window-managers/i3-sway/lib/functions.nix new file mode 100644 index 00000000000..c6a6ada1564 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/window-managers/i3-sway/lib/functions.nix @@ -0,0 +1,173 @@ +{ cfg, config, lib, moduleName }: + +with lib; + +rec { + criteriaStr = criteria: + let + toCriteria = k: v: + if builtins.isBool v then + (if v then "${k}" else "") + else + ''${k}="${v}"''; + in "[${concatStringsSep " " (mapAttrsToList toCriteria criteria)}]"; + + keybindingDefaultWorkspace = filterAttrs (n: v: + cfg.config.defaultWorkspace != null && v == cfg.config.defaultWorkspace) + cfg.config.keybindings; + + keybindingsRest = filterAttrs (n: v: + cfg.config.defaultWorkspace == null || v != cfg.config.defaultWorkspace) + cfg.config.keybindings; + + keybindingsStr = { keybindings, bindsymArgs ? "", indent ? "" }: + concatStringsSep "\n" (mapAttrsToList (keycomb: action: + optionalString (action != null) "${indent}bindsym ${ + lib.optionalString (bindsymArgs != "") "${bindsymArgs} " + }${keycomb} ${action}") keybindings); + + keycodebindingsStr = keycodebindings: + concatStringsSep "\n" (mapAttrsToList (keycomb: action: + optionalString (action != null) "bindcode ${keycomb} ${action}") + keycodebindings); + + colorSetStr = c: + concatStringsSep " " [ + c.border + c.background + c.text + c.indicator + c.childBorder + ]; + barColorSetStr = c: concatStringsSep " " [ c.border c.background c.text ]; + + modeStr = bindkeysToCode: name: keybindings: '' + mode "${name}" { + ${keybindingsStr { + inherit keybindings; + bindsymArgs = lib.optionalString bindkeysToCode "--to-code"; + indent = " "; + }} + } + ''; + + assignStr = workspace: criteria: + concatStringsSep "\n" + (map (c: "assign ${criteriaStr c} ${workspace}") criteria); + + fontConfigStr = let + toFontStr = { names, style ? "", size ? "" }: + optionalString (names != [ ]) concatStringsSep " " + (remove "" [ "font" "pango:${concatStringsSep ", " names}" style size ]); + in fontCfg: + if isList fontCfg then + toFontStr { names = fontCfg; } + else + toFontStr { + inherit (fontCfg) names style; + size = toString fontCfg.size; + }; + + barStr = { id, fonts, mode, hiddenState, position, workspaceButtons + , workspaceNumbers, command, statusCommand, colors, trayOutput, extraConfig + , ... }: + let colorsNotNull = lib.filterAttrs (n: v: v != null) colors != { }; + in '' + bar { + ${ + concatStringsSep "\n" (indent (lists.subtractLists [ "" null ] + (flatten [ + (optionalString (id != null) "id ${id}") + (fontConfigStr fonts) + (optionalString (mode != null) "mode ${mode}") + (optionalString (hiddenState != null) + "hidden_state ${hiddenState}") + (optionalString (position != null) "position ${position}") + (optionalString (statusCommand != null) + "status_command ${statusCommand}") + "${moduleName}bar_command ${command}" + (optionalString (workspaceButtons != null) + "workspace_buttons ${lib.hm.booleans.yesNo workspaceButtons}") + (optionalString (workspaceNumbers != null) + "strip_workspace_numbers ${ + lib.hm.booleans.yesNo (!workspaceNumbers) + }") + (optionalString (trayOutput != null) "tray_output ${trayOutput}") + (optionals colorsNotNull (indent + (lists.subtractLists [ "" null ] [ + "colors {" + (optionalString (colors.background != null) + "background ${colors.background}") + (optionalString (colors.statusline != null) + "statusline ${colors.statusline}") + (optionalString (colors.separator != null) + "separator ${colors.separator}") + (optionalString (colors.focusedBackground != null) + "focused_background ${colors.focusedBackground}") + (optionalString (colors.focusedStatusline != null) + "focused_statusline ${colors.focusedStatusline}") + (optionalString (colors.focusedSeparator != null) + "focused_separator ${colors.focusedSeparator}") + (optionalString (colors.focusedWorkspace != null) + "focused_workspace ${ + barColorSetStr colors.focusedWorkspace + }") + (optionalString (colors.activeWorkspace != null) + "active_workspace ${barColorSetStr colors.activeWorkspace}") + (optionalString (colors.inactiveWorkspace != null) + "inactive_workspace ${ + barColorSetStr colors.inactiveWorkspace + }") + (optionalString (colors.urgentWorkspace != null) + "urgent_workspace ${barColorSetStr colors.urgentWorkspace}") + (optionalString (colors.bindingMode != null) + "binding_mode ${barColorSetStr colors.bindingMode}") + "}" + ]) { })) + extraConfig + ])) { }) + } + } + ''; + + gapsStr = with cfg.config.gaps; + concatStringsSep "\n" (lists.subtractLists [ "" null ] [ + (optionalString (inner != null) "gaps inner ${toString inner}") + (optionalString (outer != null) "gaps outer ${toString outer}") + (optionalString (horizontal != null) + "gaps horizontal ${toString horizontal}") + (optionalString (vertical != null) "gaps vertical ${toString vertical}") + (optionalString (top != null) "gaps top ${toString top}") + (optionalString (bottom != null) "gaps bottom ${toString bottom}") + (optionalString (left != null) "gaps left ${toString left}") + (optionalString (right != null) "gaps right ${toString right}") + (optionalString smartGaps "smart_gaps on") + (optionalString (smartBorders != "off") "smart_borders ${smartBorders}") + ]); + + windowBorderString = window: floating: + let + titlebarString = { titlebar, border, ... }: + "${if titlebar then "normal" else "pixel"} ${toString border}"; + in concatStringsSep "\n" [ + "default_border ${titlebarString window}" + "default_floating_border ${titlebarString floating}" + ]; + + floatingCriteriaStr = criteria: + "for_window ${criteriaStr criteria} floating enable"; + windowCommandsStr = { command, criteria, ... }: + "for_window ${criteriaStr criteria} ${command}"; + workspaceOutputStr = item: + ''workspace "${item.workspace}" output ${item.output}''; + + indent = list: + { includesWrapper ? true, level ? 1 }: + let prefix = concatStringsSep "" (lib.genList (x: " ") (level * 2)); + + in (lib.imap1 (i: v: + "${if includesWrapper && (i == 1 || i == (lib.length list)) then + v + else + "${prefix}${v}"}") list); +} diff --git a/infra/libkookie/home-manager-stable/modules/services/window-managers/i3-sway/lib/options.nix b/infra/libkookie/home-manager-stable/modules/services/window-managers/i3-sway/lib/options.nix new file mode 100644 index 00000000000..7027e21d071 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/window-managers/i3-sway/lib/options.nix @@ -0,0 +1,895 @@ +{ config, lib, moduleName, cfg, pkgs, capitalModuleName ? moduleName +, isGaps ? true }: + +with lib; + +let + isI3 = moduleName == "i3"; + isSway = !isI3; + + fontOptions = types.submodule { + options = { + names = mkOption { + type = types.listOf types.str; + default = [ "monospace" ]; + defaultText = literalExpression ''[ "monospace" ]''; + description = '' + List of font names list used for window titles. Only FreeType fonts are supported. + The order here is important (e.g. icons font should go before the one used for text). + ''; + example = literalExpression ''[ "FontAwesome" "Terminus" ]''; + }; + + style = mkOption { + type = types.str; + default = ""; + description = '' + The font style to use for window titles. + ''; + example = "Bold Semi-Condensed"; + }; + + size = mkOption { + type = types.float; + default = 8.0; + description = '' + The font size to use for window titles. + ''; + example = 11.5; + }; + }; + }; + + startupModule = types.submodule { + options = { + command = mkOption { + type = types.str; + description = "Command that will be executed on startup."; + }; + + always = mkOption { + type = types.bool; + default = false; + description = "Whether to run command on each ${moduleName} restart."; + }; + } // optionalAttrs isI3 { + notification = mkOption { + type = types.bool; + default = true; + description = '' + Whether to enable startup-notification support for the command. + See option description in the i3 user guide. + ''; + }; + + workspace = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Launch application on a particular workspace. DEPRECATED: + Use xsession.windowManager.i3.config.assigns + instead. See . + ''; + }; + }; + + }; + + barModule = types.submodule { + options = let + versionAtLeast2009 = versionAtLeast config.home.stateVersion "20.09"; + mkNullableOption = { type, default, ... }@args: + mkOption (args // { + type = types.nullOr type; + default = if versionAtLeast2009 then null else default; + defaultText = literalExpression '' + null for state version ≥ 20.09, as example otherwise + ''; + example = default; + }); + in { + fonts = mkOption { + type = with types; either (listOf str) fontOptions; + default = { }; + example = literalExpression '' + { + names = [ "DejaVu Sans Mono" "FontAwesome5Free" ]; + style = "Bold Semi-Condensed"; + size = 11.0; + } + ''; + description = "Font configuration for this bar."; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = "Extra configuration lines for this bar."; + }; + + id = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Specifies the bar ID for the configured bar instance. + If this option is missing, the ID is set to bar-x, where x corresponds + to the position of the embedding bar block in the config file. + ''; + }; + + mode = mkNullableOption { + type = types.enum [ "dock" "hide" "invisible" ]; + default = "dock"; + description = "Bar visibility mode."; + }; + + hiddenState = mkNullableOption { + type = types.enum [ "hide" "show" ]; + default = "hide"; + description = "The default bar mode when 'bar.mode' == 'hide'."; + }; + + position = mkNullableOption { + type = types.enum [ "top" "bottom" ]; + default = "bottom"; + description = "The edge of the screen ${moduleName}bar should show up."; + }; + + workspaceButtons = mkNullableOption { + type = types.bool; + default = true; + description = "Whether workspace buttons should be shown or not."; + }; + + workspaceNumbers = mkNullableOption { + type = types.bool; + default = true; + description = + "Whether workspace numbers should be displayed within the workspace buttons."; + }; + + command = mkOption { + type = types.str; + default = let + # If the user uses the "system" Sway (i.e. cfg.package == null) then the bar has + # to come from a different package + pkg = if isSway && isNull cfg.package then pkgs.sway else cfg.package; + in "${pkg}/bin/${moduleName}bar"; + defaultText = "i3bar"; + description = "Command that will be used to start a bar."; + example = if isI3 then + "\${pkgs.i3-gaps}/bin/i3bar -t" + else + "\${pkgs.waybar}/bin/waybar"; + }; + + statusCommand = mkNullableOption { + type = types.str; + default = "${pkgs.i3status}/bin/i3status"; + description = "Command that will be used to get status lines."; + }; + + colors = mkOption { + type = types.submodule { + options = { + background = mkNullableOption { + type = types.str; + default = "#000000"; + description = "Background color of the bar."; + }; + + statusline = mkNullableOption { + type = types.str; + default = "#ffffff"; + description = "Text color to be used for the statusline."; + }; + + separator = mkNullableOption { + type = types.str; + default = "#666666"; + description = "Text color to be used for the separator."; + }; + + focusedBackground = mkOption { + type = types.nullOr types.str; + default = null; + description = + "Background color of the bar on the currently focused monitor output."; + example = "#000000"; + }; + + focusedStatusline = mkOption { + type = types.nullOr types.str; + default = null; + description = + "Text color to be used for the statusline on the currently focused monitor output."; + example = "#ffffff"; + }; + + focusedSeparator = mkOption { + type = types.nullOr types.str; + default = null; + description = + "Text color to be used for the separator on the currently focused monitor output."; + example = "#666666"; + }; + + focusedWorkspace = mkNullableOption { + type = barColorSetModule; + default = { + border = "#4c7899"; + background = "#285577"; + text = "#ffffff"; + }; + description = '' + Border, background and text color for a workspace button when the workspace has focus. + ''; + }; + + activeWorkspace = mkNullableOption { + type = barColorSetModule; + default = { + border = "#333333"; + background = "#5f676a"; + text = "#ffffff"; + }; + description = '' + Border, background and text color for a workspace button when the workspace is active. + ''; + }; + + inactiveWorkspace = mkNullableOption { + type = barColorSetModule; + default = { + border = "#333333"; + background = "#222222"; + text = "#888888"; + }; + description = '' + Border, background and text color for a workspace button when the workspace does not + have focus and is not active. + ''; + }; + + urgentWorkspace = mkNullableOption { + type = barColorSetModule; + default = { + border = "#2f343a"; + background = "#900000"; + text = "#ffffff"; + }; + description = '' + Border, background and text color for a workspace button when the workspace contains + a window with the urgency hint set. + ''; + }; + + bindingMode = mkNullableOption { + type = barColorSetModule; + default = { + border = "#2f343a"; + background = "#900000"; + text = "#ffffff"; + }; + description = + "Border, background and text color for the binding mode indicator"; + }; + }; + }; + default = { }; + description = '' + Bar color settings. All color classes can be specified using submodules + with 'border', 'background', 'text', fields and RGB color hex-codes as values. + See default values for the reference. + Note that 'background', 'status', and 'separator' parameters take a single RGB value. + + See . + ''; + }; + + trayOutput = mkNullableOption { + type = types.str; + default = "primary"; + description = "Where to output tray."; + }; + }; + }; + + barColorSetModule = types.submodule { + options = { + border = mkOption { + type = types.str; + visible = false; + }; + + background = mkOption { + type = types.str; + visible = false; + }; + + text = mkOption { + type = types.str; + visible = false; + }; + }; + }; + + colorSetModule = types.submodule { + options = { + border = mkOption { + type = types.str; + visible = false; + }; + + childBorder = mkOption { + type = types.str; + visible = false; + }; + + background = mkOption { + type = types.str; + visible = false; + }; + + text = mkOption { + type = types.str; + visible = false; + }; + + indicator = mkOption { + type = types.str; + visible = false; + }; + }; + }; + + windowCommandModule = types.submodule { + options = { + command = mkOption { + type = types.str; + description = "${capitalModuleName}wm command to execute."; + example = "border pixel 1"; + }; + + criteria = mkOption { + type = criteriaModule; + description = '' + Criteria of the windows on which command should be executed. + + A value of true is equivalent to using an empty + criteria (which is different from an empty string criteria). + ''; + example = literalExpression '' + { + title = "x200: ~/work"; + floating = true; + }; + ''; + }; + }; + }; + + criteriaModule = types.attrsOf (types.either types.str types.bool); +in { + fonts = mkOption { + type = with types; either (listOf str) fontOptions; + default = { }; + example = literalExpression '' + { + names = [ "DejaVu Sans Mono" "FontAwesome5Free" ]; + style = "Bold Semi-Condensed"; + size = 11.0; + } + ''; + description = "Font configuration for window titles, nagbar..."; + }; + + window = mkOption { + type = types.submodule { + options = { + titlebar = mkOption { + type = types.bool; + default = !isGaps; + defaultText = if isI3 then + "xsession.windowManager.i3.package != nixpkgs.i3-gaps (titlebar should be disabled for i3-gaps)" + else + "false"; + description = "Whether to show window titlebars."; + }; + + border = mkOption { + type = types.int; + default = 2; + description = "Window border width."; + }; + + hideEdgeBorders = mkOption { + type = types.enum [ "none" "vertical" "horizontal" "both" "smart" ]; + default = "none"; + description = "Hide window borders adjacent to the screen edges."; + }; + + commands = mkOption { + type = types.listOf windowCommandModule; + default = [ ]; + description = '' + List of commands that should be executed on specific windows. + See ${moduleName}wm option documentation. + ''; + example = [{ + command = "border pixel 1"; + criteria = { class = "XTerm"; }; + }]; + }; + }; + }; + default = { }; + description = "Window titlebar and border settings."; + }; + + floating = mkOption { + type = types.submodule { + options = { + titlebar = mkOption { + type = types.bool; + default = !isGaps; + defaultText = if isI3 then + "xsession.windowManager.i3.package != nixpkgs.i3-gaps (titlebar should be disabled for i3-gaps)" + else + "false"; + description = "Whether to show floating window titlebars."; + }; + + border = mkOption { + type = types.int; + default = 2; + description = "Floating windows border width."; + }; + + modifier = mkOption { + type = + types.enum [ "Shift" "Control" "Mod1" "Mod2" "Mod3" "Mod4" "Mod5" ]; + default = cfg.config.modifier; + defaultText = "${moduleName}.config.modifier"; + description = + "Modifier key that can be used to drag floating windows."; + example = "Mod4"; + }; + + criteria = mkOption { + type = types.listOf criteriaModule; + default = [ ]; + description = + "List of criteria for windows that should be opened in a floating mode."; + example = [ + { "title" = "Steam - Update News"; } + { "class" = "Pavucontrol"; } + ]; + }; + }; + }; + default = { }; + description = "Floating window settings."; + }; + + focus = mkOption { + type = types.submodule { + options = { + newWindow = mkOption { + type = types.enum [ "smart" "urgent" "focus" "none" ]; + default = "smart"; + description = '' + This option modifies focus behavior on new window activation. + + See + ''; + example = "none"; + }; + + followMouse = mkOption { + type = if isSway then + types.either (types.enum [ "yes" "no" "always" ]) types.bool + else + types.bool; + default = if isSway then "yes" else true; + description = "Whether focus should follow the mouse."; + apply = val: + if (isSway && isBool val) then (lib.hm.booleans.yesNo val) else val; + }; + + forceWrapping = mkOption { + type = types.bool; + default = false; + description = '' + Whether to force focus wrapping in tabbed or stacked container. + + See + ''; + }; + + mouseWarping = mkOption { + type = types.bool; + default = true; + description = '' + Whether mouse cursor should be warped to the center of the window when switching focus + to a window on a different output. + ''; + }; + }; + }; + default = { }; + description = "Focus related settings."; + }; + + assigns = mkOption { + type = types.attrsOf (types.listOf criteriaModule); + default = { }; + description = '' + An attribute set that assigns applications to workspaces based + on criteria. + ''; + example = literalExpression '' + { + "1: web" = [{ class = "^Firefox$"; }]; + "0: extra" = [{ class = "^Firefox$"; window_role = "About"; }]; + } + ''; + }; + + modifier = mkOption { + type = types.enum [ "Shift" "Control" "Mod1" "Mod2" "Mod3" "Mod4" "Mod5" ]; + default = "Mod1"; + description = "Modifier key that is used for all default keybindings."; + example = "Mod4"; + }; + + workspaceLayout = mkOption { + type = types.enum [ "default" "stacking" "tabbed" ]; + default = "default"; + example = "tabbed"; + description = '' + The mode in which new containers on workspace level will + start. + ''; + }; + + workspaceAutoBackAndForth = mkOption { + type = types.bool; + default = false; + example = true; + description = '' + Assume you are on workspace "1: www" and switch to "2: IM" using + mod+2 because somebody sent you a message. You don’t need to remember + where you came from now, you can just press $mod+2 again to switch + back to "1: www". + ''; + }; + + keycodebindings = mkOption { + type = types.attrsOf (types.nullOr types.str); + default = { }; + description = '' + An attribute set that assigns keypress to an action using key code. + See . + ''; + example = { "214" = "exec /bin/script.sh"; }; + }; + + colors = mkOption { + type = types.submodule { + options = { + background = mkOption { + type = types.str; + default = "#ffffff"; + description = '' + Background color of the window. Only applications which do not cover + the whole area expose the color. + ''; + }; + + focused = mkOption { + type = colorSetModule; + default = { + border = "#4c7899"; + background = "#285577"; + text = "#ffffff"; + indicator = "#2e9ef4"; + childBorder = "#285577"; + }; + description = "A window which currently has the focus."; + }; + + focusedInactive = mkOption { + type = colorSetModule; + default = { + border = "#333333"; + background = "#5f676a"; + text = "#ffffff"; + indicator = "#484e50"; + childBorder = "#5f676a"; + }; + description = '' + A window which is the focused one of its container, + but it does not have the focus at the moment. + ''; + }; + + unfocused = mkOption { + type = colorSetModule; + default = { + border = "#333333"; + background = "#222222"; + text = "#888888"; + indicator = "#292d2e"; + childBorder = "#222222"; + }; + description = "A window which is not focused."; + }; + + urgent = mkOption { + type = colorSetModule; + default = { + border = "#2f343a"; + background = "#900000"; + text = "#ffffff"; + indicator = "#900000"; + childBorder = "#900000"; + }; + description = "A window which has its urgency hint activated."; + }; + + placeholder = mkOption { + type = colorSetModule; + default = { + border = "#000000"; + background = "#0c0c0c"; + text = "#ffffff"; + indicator = "#000000"; + childBorder = "#0c0c0c"; + }; + description = '' + Background and text color are used to draw placeholder window + contents (when restoring layouts). Border and indicator are ignored. + ''; + }; + }; + }; + default = { }; + description = '' + Color settings. All color classes can be specified using submodules + with 'border', 'background', 'text', 'indicator' and 'childBorder' fields + and RGB color hex-codes as values. See default values for the reference. + Note that '${moduleName}.config.colors.background' parameter takes a single RGB value. + + See . + ''; + }; + + bars = mkOption { + type = types.listOf barModule; + default = if versionAtLeast config.home.stateVersion "20.09" then [{ + mode = "dock"; + hiddenState = "hide"; + position = "bottom"; + workspaceButtons = true; + workspaceNumbers = true; + statusCommand = "${pkgs.i3status}/bin/i3status"; + fonts = { + names = [ "monospace" ]; + size = 8.0; + }; + trayOutput = "primary"; + colors = { + background = "#000000"; + statusline = "#ffffff"; + separator = "#666666"; + focusedWorkspace = { + border = "#4c7899"; + background = "#285577"; + text = "#ffffff"; + }; + activeWorkspace = { + border = "#333333"; + background = "#5f676a"; + text = "#ffffff"; + }; + inactiveWorkspace = { + border = "#333333"; + background = "#222222"; + text = "#888888"; + }; + urgentWorkspace = { + border = "#2f343a"; + background = "#900000"; + text = "#ffffff"; + }; + bindingMode = { + border = "#2f343a"; + background = "#900000"; + text = "#ffffff"; + }; + }; + }] else + [ { } ]; + defaultText = literalExpression "see code"; + description = '' + ${capitalModuleName} bars settings blocks. Set to empty list to remove bars completely. + ''; + }; + + startup = mkOption { + type = types.listOf startupModule; + default = [ ]; + description = '' + Commands that should be executed at startup. + + See . + ''; + example = if isI3 then + literalExpression '' + [ + { command = "systemctl --user restart polybar"; always = true; notification = false; } + { command = "dropbox start"; notification = false; } + { command = "firefox"; workspace = "1: web"; } + ]; + '' + else + literalExpression '' + [ + { command = "systemctl --user restart waybar"; always = true; } + { command = "dropbox start"; } + { command = "firefox"; } + ] + ''; + }; + + gaps = mkOption { + type = types.nullOr (types.submodule { + options = { + inner = mkOption { + type = types.nullOr types.int; + default = null; + description = "Inner gaps value."; + example = 12; + }; + + outer = mkOption { + type = types.nullOr types.int; + default = null; + description = "Outer gaps value."; + example = 5; + }; + + horizontal = mkOption { + type = types.nullOr types.int; + default = null; + description = "Horizontal gaps value."; + example = 5; + }; + + vertical = mkOption { + type = types.nullOr types.int; + default = null; + description = "Vertical gaps value."; + example = 5; + }; + + top = mkOption { + type = types.nullOr types.int; + default = null; + description = "Top gaps value."; + example = 5; + }; + + left = mkOption { + type = types.nullOr types.int; + default = null; + description = "Left gaps value."; + example = 5; + }; + + bottom = mkOption { + type = types.nullOr types.int; + default = null; + description = "Bottom gaps value."; + example = 5; + }; + + right = mkOption { + type = types.nullOr types.int; + default = null; + description = "Right gaps value."; + example = 5; + }; + + smartGaps = mkOption { + type = types.bool; + default = false; + description = '' + This option controls whether to disable all gaps (outer and inner) + on workspace with a single container. + ''; + example = true; + }; + + smartBorders = mkOption { + type = types.enum [ "on" "off" "no_gaps" ]; + default = "off"; + description = '' + This option controls whether to disable container borders on + workspace with a single container. + ''; + }; + }; + }); + default = null; + description = if isSway then '' + Gaps related settings. + '' else '' + i3Gaps related settings. The i3-gaps package must be used for these features to work. + ''; + }; + + terminal = mkOption { + type = types.str; + default = if isI3 then + "i3-sensible-terminal" + else + "${pkgs.rxvt-unicode-unwrapped}/bin/urxvt"; + description = "Default terminal to run."; + example = "alacritty"; + }; + + menu = mkOption { + type = types.str; + default = if isSway then + "${pkgs.dmenu}/bin/dmenu_path | ${pkgs.dmenu}/bin/dmenu | ${pkgs.findutils}/bin/xargs swaymsg exec --" + else + "${pkgs.dmenu}/bin/dmenu_run"; + description = "Default launcher to use."; + example = "bemenu-run"; + }; + + defaultWorkspace = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + The default workspace to show when ${ + if isSway then "sway" else "i3" + } is launched. + This must to correspond to the value of the keybinding of the default workspace. + ''; + example = "workspace number 9"; + }; + + workspaceOutputAssign = mkOption { + type = with types; + let + workspaceOutputOpts = submodule { + options = { + workspace = mkOption { + type = str; + default = ""; + example = "Web"; + description = '' + Name of the workspace to assign. + ''; + }; + + output = mkOption { + type = str; + default = ""; + example = "eDP"; + description = '' + Name of the output from + ${if isSway then "swaymsg" else "i3-msg"} -t get_outputs + . + ''; + }; + }; + }; + in listOf workspaceOutputOpts; + default = [ ]; + description = "Assign workspaces to outputs."; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/window-managers/i3-sway/sway.nix b/infra/libkookie/home-manager-stable/modules/services/window-managers/i3-sway/sway.nix new file mode 100644 index 00000000000..f8ad577b998 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/window-managers/i3-sway/sway.nix @@ -0,0 +1,464 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.wayland.windowManager.sway; + + commonOptions = import ./lib/options.nix { + inherit config lib cfg pkgs; + moduleName = "sway"; + capitalModuleName = "Sway"; + }; + + configModule = types.submodule { + options = { + inherit (commonOptions) + fonts window floating focus assigns workspaceLayout + workspaceAutoBackAndForth modifier keycodebindings colors bars startup + gaps menu terminal defaultWorkspace workspaceOutputAssign; + + left = mkOption { + type = types.str; + default = "h"; + description = "Home row direction key for moving left."; + }; + + down = mkOption { + type = types.str; + default = "j"; + description = "Home row direction key for moving down."; + }; + + up = mkOption { + type = types.str; + default = "k"; + description = "Home row direction key for moving up."; + }; + + right = mkOption { + type = types.str; + default = "l"; + description = "Home row direction key for moving right."; + }; + + keybindings = mkOption { + type = types.attrsOf (types.nullOr types.str); + default = mapAttrs (n: mkOptionDefault) { + "${cfg.config.modifier}+Return" = "exec ${cfg.config.terminal}"; + "${cfg.config.modifier}+Shift+q" = "kill"; + "${cfg.config.modifier}+d" = "exec ${cfg.config.menu}"; + + "${cfg.config.modifier}+${cfg.config.left}" = "focus left"; + "${cfg.config.modifier}+${cfg.config.down}" = "focus down"; + "${cfg.config.modifier}+${cfg.config.up}" = "focus up"; + "${cfg.config.modifier}+${cfg.config.right}" = "focus right"; + + "${cfg.config.modifier}+Left" = "focus left"; + "${cfg.config.modifier}+Down" = "focus down"; + "${cfg.config.modifier}+Up" = "focus up"; + "${cfg.config.modifier}+Right" = "focus right"; + + "${cfg.config.modifier}+Shift+${cfg.config.left}" = "move left"; + "${cfg.config.modifier}+Shift+${cfg.config.down}" = "move down"; + "${cfg.config.modifier}+Shift+${cfg.config.up}" = "move up"; + "${cfg.config.modifier}+Shift+${cfg.config.right}" = "move right"; + + "${cfg.config.modifier}+Shift+Left" = "move left"; + "${cfg.config.modifier}+Shift+Down" = "move down"; + "${cfg.config.modifier}+Shift+Up" = "move up"; + "${cfg.config.modifier}+Shift+Right" = "move right"; + + "${cfg.config.modifier}+b" = "splith"; + "${cfg.config.modifier}+v" = "splitv"; + "${cfg.config.modifier}+f" = "fullscreen toggle"; + "${cfg.config.modifier}+a" = "focus parent"; + + "${cfg.config.modifier}+s" = "layout stacking"; + "${cfg.config.modifier}+w" = "layout tabbed"; + "${cfg.config.modifier}+e" = "layout toggle split"; + + "${cfg.config.modifier}+Shift+space" = "floating toggle"; + "${cfg.config.modifier}+space" = "focus mode_toggle"; + + "${cfg.config.modifier}+1" = "workspace number 1"; + "${cfg.config.modifier}+2" = "workspace number 2"; + "${cfg.config.modifier}+3" = "workspace number 3"; + "${cfg.config.modifier}+4" = "workspace number 4"; + "${cfg.config.modifier}+5" = "workspace number 5"; + "${cfg.config.modifier}+6" = "workspace number 6"; + "${cfg.config.modifier}+7" = "workspace number 7"; + "${cfg.config.modifier}+8" = "workspace number 8"; + "${cfg.config.modifier}+9" = "workspace number 9"; + + "${cfg.config.modifier}+Shift+1" = + "move container to workspace number 1"; + "${cfg.config.modifier}+Shift+2" = + "move container to workspace number 2"; + "${cfg.config.modifier}+Shift+3" = + "move container to workspace number 3"; + "${cfg.config.modifier}+Shift+4" = + "move container to workspace number 4"; + "${cfg.config.modifier}+Shift+5" = + "move container to workspace number 5"; + "${cfg.config.modifier}+Shift+6" = + "move container to workspace number 6"; + "${cfg.config.modifier}+Shift+7" = + "move container to workspace number 7"; + "${cfg.config.modifier}+Shift+8" = + "move container to workspace number 8"; + "${cfg.config.modifier}+Shift+9" = + "move container to workspace number 9"; + + "${cfg.config.modifier}+Shift+minus" = "move scratchpad"; + "${cfg.config.modifier}+minus" = "scratchpad show"; + + "${cfg.config.modifier}+Shift+c" = "reload"; + "${cfg.config.modifier}+Shift+e" = + "exec swaynag -t warning -m 'You pressed the exit shortcut. Do you really want to exit sway? This will end your Wayland session.' -b 'Yes, exit sway' 'swaymsg exit'"; + + "${cfg.config.modifier}+r" = "mode resize"; + }; + defaultText = "Default sway keybindings."; + description = '' + An attribute set that assigns a key press to an action using a key symbol. + See . + + Consider to use lib.mkOptionDefault function to extend or override + default keybindings instead of specifying all of them from scratch. + ''; + example = literalExpression '' + let + modifier = config.wayland.windowManager.sway.config.modifier; + in lib.mkOptionDefault { + "''${modifier}+Return" = "exec ${cfg.config.terminal}"; + "''${modifier}+Shift+q" = "kill"; + "''${modifier}+d" = "exec ${cfg.config.menu}"; + } + ''; + }; + + bindkeysToCode = mkOption { + type = types.bool; + default = false; + example = true; + description = '' + Whether to make use of in keybindings. + ''; + }; + + input = mkOption { + type = types.attrsOf (types.attrsOf types.str); + default = { }; + example = { "*" = { xkb_variant = "dvorak"; }; }; + description = '' + An attribute set that defines input modules. See + + sway-input + 5 + + for options. + ''; + }; + + output = mkOption { + type = types.attrsOf (types.attrsOf types.str); + default = { }; + example = { "HDMI-A-2" = { bg = "~/path/to/background.png fill"; }; }; + description = '' + An attribute set that defines output modules. See + + sway-output + 5 + + for options. + ''; + }; + + seat = mkOption { + type = types.attrsOf (types.attrsOf types.str); + default = { }; + example = { "*" = { hide_cursor = "when-typing enable"; }; }; + description = '' + An attribute set that defines seat modules. See + + sway-input + 5 + + for options. + ''; + }; + + modes = mkOption { + type = types.attrsOf (types.attrsOf types.str); + default = { + resize = { + "${cfg.config.left}" = "resize shrink width 10 px"; + "${cfg.config.down}" = "resize grow height 10 px"; + "${cfg.config.up}" = "resize shrink height 10 px"; + "${cfg.config.right}" = "resize grow width 10 px"; + "Left" = "resize shrink width 10 px"; + "Down" = "resize grow height 10 px"; + "Up" = "resize shrink height 10 px"; + "Right" = "resize grow width 10 px"; + "Escape" = "mode default"; + "Return" = "mode default"; + }; + }; + description = '' + An attribute set that defines binding modes and keybindings + inside them + + Only basic keybinding is supported (bindsym keycomb action), + for more advanced setup use 'sway.extraConfig'. + ''; + }; + }; + }; + + wrapperOptions = types.submodule { + options = let + mkWrapperFeature = default: description: + mkOption { + type = types.bool; + inherit default; + example = !default; + description = "Whether to make use of the ${description}"; + }; + in { + base = mkWrapperFeature true '' + base wrapper to execute extra session commands and prepend a + dbus-run-session to the sway command. + ''; + gtk = mkWrapperFeature false '' + wrapGAppsHook wrapper to execute sway with required environment + variables for GTK applications. + ''; + }; + }; + + commonFunctions = import ./lib/functions.nix { + inherit config cfg lib; + moduleName = "sway"; + }; + + inherit (commonFunctions) + keybindingsStr keycodebindingsStr modeStr assignStr barStr gapsStr + floatingCriteriaStr windowCommandsStr colorSetStr windowBorderString + fontConfigStr keybindingDefaultWorkspace keybindingsRest workspaceOutputStr; + + startupEntryStr = { command, always, ... }: '' + ${if always then "exec_always" else "exec"} ${command} + ''; + + moduleStr = moduleType: name: attrs: '' + ${moduleType} "${name}" { + ${concatStringsSep "\n" + (mapAttrsToList (name: value: "${name} ${value}") attrs)} + } + ''; + inputStr = moduleStr "input"; + outputStr = moduleStr "output"; + seatStr = moduleStr "seat"; + + configFile = pkgs.writeText "sway.conf" (concatStringsSep "\n" + ((if cfg.config != null then + with cfg.config; + ([ + (fontConfigStr fonts) + "floating_modifier ${floating.modifier}" + (windowBorderString window floating) + "hide_edge_borders ${window.hideEdgeBorders}" + "focus_wrapping ${lib.hm.booleans.yesNo focus.forceWrapping}" + "focus_follows_mouse ${focus.followMouse}" + "focus_on_window_activation ${focus.newWindow}" + "mouse_warping ${if focus.mouseWarping then "output" else "none"}" + "workspace_layout ${workspaceLayout}" + "workspace_auto_back_and_forth ${ + lib.hm.booleans.yesNo workspaceAutoBackAndForth + }" + "client.focused ${colorSetStr colors.focused}" + "client.focused_inactive ${colorSetStr colors.focusedInactive}" + "client.unfocused ${colorSetStr colors.unfocused}" + "client.urgent ${colorSetStr colors.urgent}" + "client.placeholder ${colorSetStr colors.placeholder}" + "client.background ${colors.background}" + (keybindingsStr { + keybindings = keybindingDefaultWorkspace; + bindsymArgs = + lib.optionalString (cfg.config.bindkeysToCode) "--to-code"; + }) + (keybindingsStr { + keybindings = keybindingsRest; + bindsymArgs = + lib.optionalString (cfg.config.bindkeysToCode) "--to-code"; + }) + (keycodebindingsStr keycodebindings) + ] ++ mapAttrsToList inputStr input + ++ mapAttrsToList outputStr output # outputs + ++ mapAttrsToList seatStr seat # seats + ++ mapAttrsToList (modeStr cfg.config.bindkeysToCode) modes # modes + ++ mapAttrsToList assignStr assigns # assigns + ++ map barStr bars # bars + ++ optional (gaps != null) gapsStr # gaps + ++ map floatingCriteriaStr floating.criteria # floating + ++ map windowCommandsStr window.commands # window commands + ++ map startupEntryStr startup # startup + ++ map workspaceOutputStr workspaceOutputAssign # custom mapping + ) + else + [ ]) ++ (optional cfg.systemdIntegration '' + exec "systemctl --user import-environment; systemctl --user start sway-session.target"'') + ++ (optional (!cfg.xwayland) "xwayland disable") ++ [ cfg.extraConfig ])); + + defaultSwayPackage = pkgs.sway.override { + extraSessionCommands = cfg.extraSessionCommands; + extraOptions = cfg.extraOptions; + withBaseWrapper = cfg.wrapperFeatures.base; + withGtkWrapper = cfg.wrapperFeatures.gtk; + }; + +in { + meta.maintainers = with maintainers; [ alexarice sumnerevans sebtm ]; + + options.wayland.windowManager.sway = { + enable = mkEnableOption "sway wayland compositor"; + + package = mkOption { + type = with types; nullOr package; + default = defaultSwayPackage; + defaultText = literalExpression "${pkgs.sway}"; + description = '' + Sway package to use. Will override the options + 'wrapperFeatures', 'extraSessionCommands', and 'extraOptions'. + Set to null to not add any Sway package to your + path. This should be done if you want to use the NixOS Sway + module to install Sway. + ''; + }; + + systemdIntegration = mkOption { + type = types.bool; + default = pkgs.stdenv.isLinux; + example = false; + description = '' + Whether to enable sway-session.target on + sway startup. This links to + graphical-session.target. + ''; + }; + + xwayland = mkOption { + type = types.bool; + default = true; + description = '' + Enable xwayland, which is needed for the default configuration of sway. + ''; + }; + + wrapperFeatures = mkOption { + type = wrapperOptions; + default = { }; + example = { gtk = true; }; + description = '' + Attribute set of features to enable in the wrapper. + ''; + }; + + extraSessionCommands = mkOption { + type = types.lines; + default = ""; + example = '' + export SDL_VIDEODRIVER=wayland + # needs qt5.qtwayland in systemPackages + export QT_QPA_PLATFORM=wayland + export QT_WAYLAND_DISABLE_WINDOWDECORATION="1" + # Fix for some Java AWT applications (e.g. Android Studio), + # use this if they aren't displayed properly: + export _JAVA_AWT_WM_NONREPARENTING=1 + ''; + description = '' + Shell commands executed just before Sway is started. + ''; + }; + + extraOptions = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ + "--verbose" + "--debug" + "--unsupported-gpu" + "--my-next-gpu-wont-be-nvidia" + ]; + description = '' + Command line arguments passed to launch Sway. Please DO NOT report + issues if you use an unsupported GPU (proprietary drivers). + ''; + }; + + config = mkOption { + type = types.nullOr configModule; + default = { }; + description = "Sway configuration options."; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = + "Extra configuration lines to add to ~/.config/sway/config."; + }; + }; + + config = mkIf cfg.enable (mkMerge [ + (mkIf (cfg.config != null) { + warnings = (optional (isList cfg.config.fonts) + "Specifying sway.config.fonts as a list is deprecated. Use the attrset version instead.") + ++ flatten (map (b: + optional (isList b.fonts) + "Specifying sway.config.bars[].fonts as a list is deprecated. Use the attrset version instead.") + cfg.config.bars); + }) + + { + assertions = [ + (hm.assertions.assertPlatform "wayland.windowManager.sway" pkgs + platforms.linux) + ]; + + home.packages = optional (cfg.package != null) cfg.package + ++ optional cfg.xwayland pkgs.xwayland; + + xdg.configFile."sway/config" = let + swayPackage = if cfg.package == null then pkgs.sway else cfg.package; + in { + source = configFile; + onChange = '' + swaySocket="''${XDG_RUNTIME_DIR:-/run/user/$UID}/sway-ipc.$UID.$(${pkgs.procps}/bin/pgrep --uid $UID -x sway || true).sock" + if [ -S "$swaySocket" ]; then + ${swayPackage}/bin/swaymsg -s $swaySocket reload + fi + ''; + }; + + systemd.user.targets.sway-session = mkIf cfg.systemdIntegration { + Unit = { + Description = "sway compositor session"; + Documentation = [ "man:systemd.special(7)" ]; + BindsTo = [ "graphical-session.target" ]; + Wants = [ "graphical-session-pre.target" ]; + After = [ "graphical-session-pre.target" ]; + }; + }; + + systemd.user.targets.tray = { + Unit = { + Description = "Home Manager System Tray"; + Requires = [ "graphical-session-pre.target" ]; + }; + }; + } + ]); +} diff --git a/infra/libkookie/home-manager-stable/modules/services/window-managers/i3-sway/swaynag.nix b/infra/libkookie/home-manager-stable/modules/services/window-managers/i3-sway/swaynag.nix new file mode 100644 index 00000000000..97d6f47381b --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/window-managers/i3-sway/swaynag.nix @@ -0,0 +1,70 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.wayland.windowManager.sway.swaynag; + + iniFormat = pkgs.formats.ini { }; + + confFormat = with types; + let + confAtom = nullOr (oneOf [ bool int float str ]) // { + description = "Swaynag config atom (null, bool, int, float, str)"; + }; + in attrsOf confAtom; +in { + meta.maintainers = with maintainers; [ polykernel ]; + + options = { + wayland.windowManager.sway.swaynag = { + enable = mkEnableOption + "configuration of swaynag, a lightweight error bar for sway"; + + settings = mkOption { + type = types.attrsOf confFormat; + default = { }; + description = '' + Configuration written to + $XDG_CONFIG_HOME/swaynag/config. + + See + + swaynag + 5 + + for a list of avaliable options and an example configuration. + Note, configurations declared under <config> + will override the default type values of swaynag. + ''; + example = literalExpression '' + { + "" = { + edge = "bottom"; + font = "Dina 12"; + }; + + green = { + edge = "top"; + background = "00AA00"; + text = "FFFFFF"; + button-background = "00CC00"; + message-padding = 10; + }; + } + ''; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (hm.assertions.assertPlatform "wayland.windowManager.sway.swaynag" pkgs + platforms.linux) + ]; + + xdg.configFile."swaynag/config" = mkIf (cfg.settings != { }) { + source = iniFormat.generate "swaynag.conf" cfg.settings; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/window-managers/xmonad.nix b/infra/libkookie/home-manager-stable/modules/services/window-managers/xmonad.nix new file mode 100644 index 00000000000..8066bae2ccf --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/window-managers/xmonad.nix @@ -0,0 +1,178 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.xsession.windowManager.xmonad; + + xmonad = pkgs.xmonad-with-packages.override { + ghcWithPackages = cfg.haskellPackages.ghcWithPackages; + packages = self: + cfg.extraPackages self ++ optionals cfg.enableContribAndExtras [ + self.xmonad-contrib + self.xmonad-extras + ]; + }; + +in { + options = { + xsession.windowManager.xmonad = { + enable = mkEnableOption "xmonad window manager"; + + haskellPackages = mkOption { + default = pkgs.haskellPackages; + defaultText = literalExpression "pkgs.haskellPackages"; + example = literalExpression "pkgs.haskell.packages.ghc784"; + description = '' + The haskellPackages used to build xmonad + and other packages. This can be used to change the GHC + version used to build xmonad and the packages listed in + extraPackages. + ''; + }; + + extraPackages = mkOption { + default = self: [ ]; + defaultText = "self: []"; + example = literalExpression '' + haskellPackages: [ + haskellPackages.xmonad-contrib + haskellPackages.monad-logger + ] + ''; + description = '' + Extra packages available to GHC when rebuilding xmonad. The + value must be a function which receives the attribute set + defined in haskellPackages as the sole + argument. + ''; + }; + + enableContribAndExtras = mkOption { + default = false; + type = types.bool; + description = "Enable xmonad-{contrib,extras} in xmonad."; + }; + + config = mkOption { + type = types.nullOr types.path; + default = null; + example = literalExpression '' + pkgs.writeText "xmonad.hs" ''' + import XMonad + main = xmonad defaultConfig + { terminal = "urxvt" + , modMask = mod4Mask + , borderWidth = 3 + } + ''' + ''; + description = '' + The configuration file to be used for xmonad. This must be + an absolute path or null in which case + ~/.xmonad/xmonad.hs will not be managed + by Home Manager. + + + If this option is set to a non-null value, + recompilation of xmonad outside of Home Manager (e.g. via + xmonad --recompile) will fail. + ''; + }; + + libFiles = mkOption { + type = types.attrsOf (types.oneOf [ types.path ]); + default = { }; + example = literalExpression '' + { + "Tools.hs" = pkgs.writeText "Tools.hs" ''' + module Tools where + screenshot = "scrot" + '''; + } + ''; + description = '' + Additional files that will be saved in + ~/.xmonad/lib/ and included in the configuration + build. The keys are the file names while the values are paths to the + contents of the files. + ''; + }; + }; + }; + + config = let + + xmonadBin = "${ + pkgs.runCommandLocal "xmonad-compile" { + nativeBuildInputs = [ xmonad ]; + } '' + mkdir -p $out/bin + + export XMONAD_CONFIG_DIR="$(pwd)/xmonad-config" + export XMONAD_DATA_DIR="$(pwd)/data" + export XMONAD_CACHE_DIR="$(pwd)/cache" + + mkdir -p "$XMONAD_CONFIG_DIR/lib" "$XMONAD_CACHE_DIR" "$XMONAD_DATA_DIR" + + cp ${cfg.config} xmonad-config/xmonad.hs + + declare -A libFiles + libFiles=(${ + concatStringsSep " " + (mapAttrsToList (name: value: "['${name}']='${value}'") + cfg.libFiles) + }) + for key in "''${!libFiles[@]}"; do + cp "''${libFiles[$key]}" "xmonad-config/lib/$key"; + done + + xmonad --recompile + + # The resulting binary name depends on the arch and os + # https://github.com/xmonad/xmonad/blob/56b0f850bc35200ec23f05c079eca8b0a1f90305/src/XMonad/Core.hs#L565-L572 + if [ -f "$XMONAD_DATA_DIR/xmonad-${pkgs.stdenv.hostPlatform.system}" ]; then + # xmonad 0.15.0 + mv "$XMONAD_DATA_DIR/xmonad-${pkgs.stdenv.hostPlatform.system}" $out/bin/ + else + # xmonad 0.17.0 (https://github.com/xmonad/xmonad/commit/9813e218b034009b0b6d09a70650178980e05d54) + mv "$XMONAD_CACHE_DIR/xmonad-${pkgs.stdenv.hostPlatform.system}" $out/bin/ + fi + '' + }/bin/xmonad-${pkgs.stdenv.hostPlatform.system}"; + + in mkIf cfg.enable (mkMerge [ + { + assertions = [ + (hm.assertions.assertPlatform "xsession.windowManager.xmonad" pkgs + platforms.linux) + ]; + + home.packages = [ (lowPrio xmonad) ]; + + home.file = mapAttrs' (name: value: + attrsets.nameValuePair (".xmonad/lib/" + name) { source = value; }) + cfg.libFiles; + } + + (mkIf (cfg.config == null) { + xsession.windowManager.command = "${xmonad}/bin/xmonad"; + }) + + (mkIf (cfg.config != null) { + xsession.windowManager.command = xmonadBin; + home.file.".xmonad/xmonad.hs".source = cfg.config; + home.file.".xmonad/xmonad-${pkgs.stdenv.hostPlatform.system}" = { + source = xmonadBin; + onChange = '' + # Attempt to restart xmonad if X is running. + if [[ -v DISPLAY ]]; then + ${config.xsession.windowManager.command} --restart + fi + ''; + }; + }) + + ]); +} diff --git a/infra/libkookie/home-manager-stable/modules/services/wlsunset.nix b/infra/libkookie/home-manager-stable/modules/services/wlsunset.nix new file mode 100644 index 00000000000..6cd45ed5e4d --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/wlsunset.nix @@ -0,0 +1,102 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let cfg = config.services.wlsunset; + +in { + meta.maintainers = [ hm.maintainers.matrss ]; + + options.services.wlsunset = { + enable = mkEnableOption "wlsunset"; + + package = mkOption { + type = types.package; + default = pkgs.wlsunset; + defaultText = "pkgs.wlsunset"; + description = '' + wlsunset derivation to use. + ''; + }; + + latitude = mkOption { + type = types.str; + description = '' + Your current latitude, between -90.0 and + 90.0. + ''; + }; + + longitude = mkOption { + type = types.str; + description = '' + Your current longitude, between -180.0 and + 180.0. + ''; + }; + + temperature = { + day = mkOption { + type = types.int; + default = 6500; + description = '' + Colour temperature to use during the day, in Kelvin (K). + This value must be greater than temperature.night. + ''; + }; + + night = mkOption { + type = types.int; + default = 4000; + description = '' + Colour temperature to use during the night, in Kelvin (K). + This value must be smaller than temperature.day. + ''; + }; + }; + + gamma = mkOption { + type = types.str; + default = "1.0"; + description = '' + Gamma value to use. + ''; + }; + + systemdTarget = mkOption { + type = types.str; + default = "graphical-session.target"; + description = '' + Systemd target to bind to. + ''; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.wlsunset" pkgs + lib.platforms.linux) + ]; + + systemd.user.services.wlsunset = { + Unit = { + Description = "Day/night gamma adjustments for Wayland compositors."; + PartOf = [ "graphical-session.target" ]; + }; + + Service = { + ExecStart = let + args = [ + "-l ${cfg.latitude}" + "-L ${cfg.longitude}" + "-t ${toString cfg.temperature.night}" + "-T ${toString cfg.temperature.day}" + "-g ${cfg.gamma}" + ]; + in "${cfg.package}/bin/wlsunset ${concatStringsSep " " args}"; + }; + + Install = { WantedBy = [ cfg.systemdTarget ]; }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/xcape.nix b/infra/libkookie/home-manager-stable/modules/services/xcape.nix new file mode 100644 index 00000000000..72b8303bb48 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/xcape.nix @@ -0,0 +1,86 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.xcape; + +in { + meta.maintainers = [ maintainers.nickhu ]; + + options = { + services.xcape = { + enable = mkEnableOption "xcape"; + + timeout = mkOption { + type = types.nullOr types.int; + default = null; + example = 500; + description = '' + If you hold a key longer than this timeout, xcape will not + generate a key event. Default is 500 ms. + ''; + }; + + mapExpression = mkOption { + type = types.attrsOf types.str; + default = { }; + example = { + Shift_L = "Escape"; + Control_L = "Control_L|O"; + }; + description = '' + The value has the grammar Key[|OtherKey]. + + + The list of key names is found in the header file + X11/keysymdef.h (remove the + XK_ prefix). Note that due to limitations + of X11 shifted keys must be specified as a shift key + followed by the key to be pressed rather than the actual + name of the character. For example to generate "{" the + expression Shift_L|bracketleft could be + used (assuming that you have a key with "{" above "["). + + + You can also specify keys in decimal (prefix #), octal (#0), + or hexadecimal (#0x). They will be interpreted as keycodes + unless no corresponding key name is found. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.xcape" pkgs + lib.platforms.linux) + ]; + + systemd.user.services.xcape = { + Unit = mkMerge [ + { + Description = "xcape"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + } + (mkIf (config.home.keyboard != null && config.home.keyboard != { }) { + After = [ "graphical-session-pre.target" "setxkbmap.service" ]; + }) + ]; + + Service = { + Type = "forking"; + ExecStart = "${pkgs.xcape}/bin/xcape" + + optionalString (cfg.timeout != null) " -t ${toString cfg.timeout}" + + optionalString (cfg.mapExpression != { }) " -e '${ + builtins.concatStringsSep ";" + (attrsets.mapAttrsToList (n: v: "${n}=${v}") cfg.mapExpression) + }'"; + }; + + Install = { WantedBy = [ "graphical-session.target" ]; }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/xembed-sni-proxy.nix b/infra/libkookie/home-manager-stable/modules/services/xembed-sni-proxy.nix new file mode 100644 index 00000000000..54ea0599cbd --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/xembed-sni-proxy.nix @@ -0,0 +1,50 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.xembed-sni-proxy; + +in { + meta.maintainers = [ maintainers.rycee ]; + + options = { + services.xembed-sni-proxy = { + enable = mkEnableOption "XEmbed SNI Proxy"; + + package = mkOption { + type = types.package; + default = pkgs.plasma-workspace; + defaultText = literalExpression "pkgs.plasma-workspace"; + description = '' + Package containing the xembedsniproxy + program. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.xembed-sni-proxy" pkgs + lib.platforms.linux) + ]; + + systemd.user.services.xembed-sni-proxy = { + Unit = { + Description = "XEmbed SNI Proxy"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + }; + + Install = { WantedBy = [ "graphical-session.target" ]; }; + + Service = { + Environment = "PATH=${config.home.profileDirectory}/bin"; + ExecStart = "${cfg.package}/bin/xembedsniproxy"; + Restart = "on-abort"; + }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/xidlehook.nix b/infra/libkookie/home-manager-stable/modules/services/xidlehook.nix new file mode 100644 index 00000000000..f2925047568 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/xidlehook.nix @@ -0,0 +1,154 @@ +# Wrapper around xidlehook. + +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.xidlehook; + + notEmpty = list: filter (x: x != "" && x != null) (flatten list); + + timers = let + toTimer = timer: + "--timer ${toString timer.delay} ${ + escapeShellArgs [ timer.command timer.canceller ] + }"; + in map toTimer (filter (timer: timer.command != null) cfg.timers); + + script = pkgs.writeShellScript "xidlehook" '' + ${concatStringsSep "\n" + (mapAttrsToList (name: value: "export ${name}=${value}") + cfg.environment or { })} + ${concatStringsSep " " (notEmpty [ + "${cfg.package}/bin/xidlehook" + (optionalString cfg.once "--once") + (optionalString cfg.not-when-fullscreen "--not-when-fullscreen") + (optionalString cfg.not-when-audio "--not-when-audio") + timers + ])} + ''; +in { + meta.maintainers = [ maintainers.dschrempf ]; + + options.services.xidlehook = { + enable = mkEnableOption "xidlehook systemd service"; + + package = mkOption { + type = types.package; + default = pkgs.xidlehook; + defaultText = "pkgs.xidlehook"; + description = "The package to use for xidlehook."; + }; + + environment = mkOption { + type = types.attrsOf types.str; + default = { }; + example = literalExpression '' + { + "primary-display" = "$(xrandr | awk '/ primary/{print $1}')"; + } + ''; + description = '' + Extra environment variables to be exported in the script. + These options are passed unescaped as export name=value. + ''; + }; + + not-when-fullscreen = mkOption { + type = types.bool; + default = false; + example = true; + description = "Disable locking when a fullscreen application is in use."; + }; + + not-when-audio = mkOption { + type = types.bool; + default = false; + example = true; + description = "Disable locking when audio is playing."; + }; + + once = mkEnableOption "running the program once and exiting"; + + timers = mkOption { + type = types.listOf (types.submodule { + options = { + delay = mkOption { + type = types.ints.unsigned; + example = 60; + description = "Time before executing the command."; + }; + command = mkOption { + type = types.nullOr types.str; + example = literalExpression '' + ''${pkgs.libnotify}/bin/notify-send "Idle" "Sleeping in 1 minute" + ''; + description = '' + Command executed after the idle timeout is reached. + Path to executables are accepted. + The command is automatically escaped. + ''; + }; + canceller = mkOption { + type = types.str; + default = ""; + example = literalExpression '' + ''${pkgs.libnotify}/bin/notify-send "Idle" "Resuming activity" + ''; + description = '' + Command executed when the user becomes active again. + This is only executed if the next timer has not been reached. + Path to executables are accepted. + The command is automatically escaped. + ''; + }; + }; + }); + default = [ ]; + example = literalExpression '' + [ + { + delay = 60; + command = "xrandr --output \"$PRIMARY_DISPLAY\" --brightness .1"; + canceller = "xrandr --output \"$PRIMARY_DISPLAY\" --brightness 1"; + } + { + delay = 120; + command = "''${pkgs.writeShellScript "my-script" ''' + # A complex script to run + '''}"; + } + ] + ''; + description = '' + A set of commands to be executed after a specific idle timeout. + The commands specified in command and canceller + are passed escaped to the script. + To use or re-use environment variables that are script-dependent, specify them + in the environment section. + ''; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.xidlehook" pkgs + lib.platforms.linux) + ]; + + systemd.user.services.xidlehook = { + Unit = { + Description = "xidlehook service"; + PartOf = [ "graphical-session.target" ]; + After = [ "graphical-session.target" ]; + ConditionEnvironment = [ "DISPLAY" ]; + }; + Service = { + Type = if cfg.once then "oneshot" else "simple"; + ExecStart = "${script}"; + }; + Install.WantedBy = [ "graphical-session.target" ]; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/xscreensaver.nix b/infra/libkookie/home-manager-stable/modules/services/xscreensaver.nix new file mode 100644 index 00000000000..3ae92658f03 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/xscreensaver.nix @@ -0,0 +1,62 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.xscreensaver; + +in { + meta.maintainers = [ maintainers.rycee ]; + + options = { + services.xscreensaver = { + enable = mkEnableOption "XScreenSaver"; + + settings = mkOption { + type = with types; attrsOf (either bool (either int str)); + default = { }; + example = { + mode = "blank"; + lock = false; + fadeTicks = 20; + }; + description = '' + The settings to use for XScreenSaver. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.xscreensaver" pkgs + lib.platforms.linux) + ]; + + # To make the xscreensaver-command tool available. + home.packages = [ pkgs.xscreensaver ]; + + xresources.properties = + mapAttrs' (n: nameValuePair "xscreensaver.${n}") cfg.settings; + + systemd.user.services.xscreensaver = { + Unit = { + Description = "XScreenSaver"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + + # Make sure the service is restarted if the settings change. + X-Restart-Triggers = + [ (builtins.hashString "md5" (builtins.toJSON cfg.settings)) ]; + }; + + Service = { + ExecStart = "${pkgs.xscreensaver}/bin/xscreensaver -no-splash"; + Environment = "PATH=${makeBinPath [ pkgs.xscreensaver ]}"; + }; + + Install = { WantedBy = [ "graphical-session.target" ]; }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/xsettingsd.nix b/infra/libkookie/home-manager-stable/modules/services/xsettingsd.nix new file mode 100644 index 00000000000..58eb2665ee7 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/xsettingsd.nix @@ -0,0 +1,93 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.xsettingsd; + + renderSettings = settings: + concatStrings (mapAttrsToList renderSetting settings); + + renderSetting = key: value: '' + ${key} ${renderValue value} + ''; + + renderValue = value: + { + int = toString value; + bool = if value then "1" else "0"; + string = ''"${value}"''; + }.${builtins.typeOf value}; + +in { + meta.maintainers = [ maintainers.imalison ]; + + options = { + services.xsettingsd = { + enable = mkEnableOption "xsettingsd"; + + package = mkOption { + type = types.package; + default = pkgs.xsettingsd; + defaultText = literalExpression "pkgs.xsettingsd"; + description = '' + Package containing the xsettingsd program. + ''; + }; + + settings = mkOption { + type = with types; attrsOf (oneOf [ bool int str ]); + default = { }; + example = literalExpression '' + { + "Net/ThemeName" = "Numix"; + "Xft/Antialias" = true; + "Xft/Hinting" = true; + "Xft/RGBA" = "rgb"; + } + ''; + description = '' + Xsettingsd options for configuration file. See + + for documentation on these values. + ''; + }; + + configFile = mkOption { + type = types.nullOr types.package; + internal = true; + readOnly = true; + default = if cfg.settings == { } then + null + else + pkgs.writeText "xsettingsd.conf" (renderSettings cfg.settings); + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.xsettingsd" pkgs + lib.platforms.linux) + ]; + + systemd.user.services.xsettingsd = { + Unit = { + Description = "xsettingsd"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + }; + + Install.WantedBy = [ "graphical-session.target" ]; + + Service = { + Environment = "PATH=${config.home.profileDirectory}/bin"; + ExecStart = "${cfg.package}/bin/xsettingsd" + + optionalString (cfg.configFile != null) + " -c ${escapeShellArg cfg.configFile}"; + Restart = "on-abort"; + }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/services/xsuspender.nix b/infra/libkookie/home-manager-stable/modules/services/xsuspender.nix new file mode 100644 index 00000000000..54f13c8d5a7 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/services/xsuspender.nix @@ -0,0 +1,200 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.xsuspender; + + iniFormat = pkgs.formats.ini { }; + + xsuspenderOptions = types.submodule { + options = { + matchWmClassContains = mkOption { + description = "Match windows that wm class contains string."; + type = types.nullOr types.str; + default = null; + }; + + matchWmClassGroupContains = mkOption { + description = "Match windows where wm class group contains string."; + type = types.nullOr types.str; + default = null; + }; + + matchWmNameContains = mkOption { + description = "Match windows where wm name contains string."; + type = types.nullOr types.str; + default = null; + }; + + suspendDelay = mkOption { + description = "Initial suspend delay in seconds."; + type = types.int; + default = 5; + }; + + resumeEvery = mkOption { + description = "Resume interval in seconds."; + type = types.int; + default = 50; + }; + + resumeFor = mkOption { + description = "Resume duration in seconds."; + type = types.int; + default = 5; + }; + + execSuspend = mkOption { + description = '' + Before suspending, execute this shell script. If it fails, + abort suspension. + ''; + type = types.nullOr types.str; + default = null; + example = ''echo "suspending window $XID of process $PID"''; + }; + + execResume = mkOption { + description = '' + Before resuming, execute this shell script. Resume the + process regardless script failure. + ''; + type = types.nullOr types.str; + default = null; + example = "echo resuming ..."; + }; + + sendSignals = mkOption { + description = '' + Whether to send SIGSTOP / SIGCONT signals or not. + If false just the exec scripts are run. + ''; + type = types.bool; + default = true; + }; + + suspendSubtreePattern = mkOption { + description = + "Also suspend descendant processes that match this regex."; + type = types.nullOr types.str; + default = null; + }; + + onlyOnBattery = mkOption { + description = "Whether to enable process suspend only on battery."; + type = types.bool; + default = false; + }; + + autoSuspendOnBattery = mkOption { + description = '' + Whether to auto-apply rules when switching to battery + power even if the window(s) didn't just lose focus. + ''; + type = types.bool; + default = true; + }; + + downclockOnBattery = mkOption { + description = '' + Limit CPU consumption for this factor when on battery power. + Value 1 means 50% decrease, 2 means 66%, 3 means 75% etc. + ''; + type = types.int; + default = 0; + }; + }; + }; + +in { + meta.maintainers = [ maintainers.offline ]; + + options = { + services.xsuspender = { + enable = mkEnableOption "XSuspender"; + + defaults = mkOption { + description = "XSuspender defaults."; + type = xsuspenderOptions; + default = { }; + }; + + rules = mkOption { + description = "Attribute set of XSuspender rules."; + type = types.attrsOf xsuspenderOptions; + default = { }; + example = { + Chromium = { + suspendDelay = 10; + matchWmClassContains = "chromium-browser"; + suspendSubtreePattern = "chromium"; + }; + }; + }; + + debug = mkOption { + description = "Whether to enable debug output."; + type = types.bool; + default = false; + }; + + iniContent = mkOption { + type = iniFormat.type; + internal = true; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.xsuspender" pkgs + lib.platforms.linux) + ]; + + services.xsuspender.iniContent = let + mkSection = values: + filterAttrs (_: v: v != null) { + match_wm_class_contains = values.matchWmClassContains; + match_wm_class_group_contains = values.matchWmClassGroupContains; + match_wm_name_contains = values.matchWmNameContains; + suspend_delay = values.suspendDelay; + resume_every = values.resumeEvery; + resume_for = values.resumeFor; + exec_suspend = values.execSuspend; + exec_resume = values.execResume; + send_signals = values.sendSignals; + suspend_subtree_pattern = values.suspendSubtreePattern; + only_on_battery = values.onlyOnBattery; + auto_suspend_on_battery = values.autoSuspendOnBattery; + downclock_on_battery = values.downclockOnBattery; + }; + in { + Default = mkSection cfg.defaults; + } // mapAttrs (_: mkSection) cfg.rules; + + # To make the xsuspender tool available. + home.packages = [ pkgs.xsuspender ]; + + xdg.configFile."xsuspender.conf".source = + iniFormat.generate "xsuspender.conf" cfg.iniContent; + + systemd.user.services.xsuspender = { + Unit = { + Description = "XSuspender"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + X-Restart-Triggers = + [ "${config.xdg.configFile."xsuspender.conf".source}" ]; + }; + + Service = { + ExecStart = "${pkgs.xsuspender}/bin/xsuspender"; + Environment = mkIf cfg.debug [ "G_MESSAGE_DEBUG=all" ]; + }; + + Install = { WantedBy = [ "graphical-session.target" ]; }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/systemd-activate.rb b/infra/libkookie/home-manager-stable/modules/systemd-activate.rb new file mode 100644 index 00000000000..31d06d8fc19 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/systemd-activate.rb @@ -0,0 +1,216 @@ +require 'set' +require 'open3' + +@dry_run = ENV['DRY_RUN'] +@verbose = ENV['VERBOSE'] + +UnitsDir = 'home-files/.config/systemd/user' + +# 1. Stop all services from the old generation that are not present in the new generation. +# 2. Ensure all services from the new generation that are wanted by active targets are running: +# - Start services that are not already running. +# - Restart services whose unit config files have changed between generations. +# 3. If any services were (re)started, wait 'start_timeout_ms' and report services +# that failed to start. This helps debugging quickly failing services. +# +# Whenever service failures are detected, show the output of +# 'systemd --user status' for the affected services. +# +def setup_services(old_gen_path, new_gen_path, start_timeout_ms_string) + start_timeout_ms = start_timeout_ms_string.to_i + + old_units_path = File.join(old_gen_path, UnitsDir) unless old_gen_path.empty? + new_units_path = File.join(new_gen_path, UnitsDir) + + old_services = get_services(old_units_path) + new_services = get_services(new_units_path) + + exit if old_services.empty? && new_services.empty? + + all_services = get_active_targets_units(new_units_path) + maybe_changed = all_services & old_services + changed_services = get_changed_services(old_units_path, new_units_path, maybe_changed) + unchanged_oneshots = get_oneshot_services(maybe_changed - changed_services) + + # These services should be running when this script is finished + services_to_run = all_services - unchanged_oneshots + + # Only stop active services, otherwise we might get a 'service not loaded' error + # for inactive services that were removed in the current generation. + to_stop = get_active_units(old_services - new_services) + to_restart = changed_services + to_start = get_inactive_units(services_to_run - to_restart) + + raise "daemon-reload failed" unless run_cmd('systemctl', '--user', 'daemon-reload') + + # Exclude units that shouldn't be (re)started or stopped + no_manual_start, no_manual_stop, no_restart = get_restricted_units(to_stop + to_restart + to_start) + notify_skipped_units(to_restart & no_restart) + to_stop -= no_manual_stop + to_restart -= no_manual_stop + no_manual_start + no_restart + to_start -= no_manual_start + + if to_stop.empty? && to_start.empty? && to_restart.empty? + print_service_msg("All services are already running", services_to_run) + else + puts "Setting up services" if @verbose + systemctl_action('stop', to_stop) + systemctl_action('start', to_start) + systemctl_action('restart', to_restart) + started_services = to_start + to_restart + if start_timeout_ms > 0 && !started_services.empty? && !@dry_run + failed = wait_and_get_failed_services(started_services, start_timeout_ms) + if failed.empty? + print_service_msg("All services are running", services_to_run) + else + puts + puts "Error. These services failed to start:", failed + show_failed_services_status(failed) + exit 1 + end + end + end +end + +def get_services(dir) + services = get_service_files(dir) if dir && Dir.exists?(dir) + Set.new(services) +end + +def get_service_files(dir) + Dir.chdir(dir) { Dir['*[^@].{service,socket,timer}'] } +end + +def get_changed_services(dir_a, dir_b, services) + services.select do |service| + a = File.join(dir_a, service) + b = File.join(dir_b, service) + (File.size(a) != File.size(b)) || (File.read(a) != File.read(b)) + end +end + +TargetDirRegexp = /^(.*\.target)\.wants$/ + +# @return all units wanted by active targets +def get_active_targets_units(units_dir) + return Set.new unless Dir.exists?(units_dir) + targets = Dir.entries(units_dir).map { |entry| entry[TargetDirRegexp, 1] }.compact + active_targets = get_active_units(targets) + active_units = active_targets.map do |target| + get_service_files(File.join(units_dir, "#{target}.wants")) + end.flatten + Set.new(active_units) +end + +# @return true on success +def run_cmd(*cmd) + print_cmd cmd + @dry_run || system(*cmd) +end + +def systemctl_action(cmd, services) + return if services.empty? + + verb = (cmd == 'stop') ? 'Stopping' : "#{cmd.capitalize}ing" + puts "#{verb}: #{services.join(' ')}" + + cmd = ['systemctl', '--user', cmd, *services] + if @dry_run + puts cmd.join(' ') + return + end + + output, status = Open3.capture2e(*cmd) + print output + # Show status for failed services + unless status.success? + # Due to a bug in systemd, the '--user' argument is not always provided + output.scan(/systemctl (?:--user )?(status .*?)['"]/).flatten.each do |status_cmd| + puts + run_cmd("systemctl --user #{status_cmd}") + end + exit 1 + end +end + +def systemctl(*cmd) + output, _ = Open3.capture2('systemctl', '--user', *cmd) + output +end + +def print_cmd(cmd) + puts [*cmd].join(' ') if @verbose || @dry_run +end + +def get_active_units(units) + filter_units(units) { |state| state == 'active' } +end + +def get_inactive_units(units) + filter_units(units) { |state| state != 'active' } +end + +def get_failed_units(units) + filter_units(units) { |state| state == 'failed' } +end + +def filter_units(units) + return [] if units.empty? + states = systemctl('is-active', *units).split + units.select.with_index { |_, i| yield states[i] } +end + +def get_oneshot_services(units) + return [] if units.empty? + types = systemctl('show', '-p', 'Type', *units).split + units.select.with_index do |_, i| + types[i] == 'Type=oneshot' + end +end + +def get_restricted_units(units) + infos = systemctl('show', '-p', 'RefuseManualStart', '-p', 'RefuseManualStop', *units) + .split("\n\n") + no_manual_start = [] + no_manual_stop = [] + infos.zip(units).each do |info, unit| + no_start, no_stop = info.split("\n") + no_manual_start << unit if no_start.end_with?('yes') + no_manual_stop << unit if no_stop.end_with?('yes') + end + # Get units that should not be restarted even if a change has been detected. + no_restart_regexp = /^\s*X-RestartIfChanged\s*=\s*false\b/ + no_restart = units.select { |unit| systemctl('cat', unit) =~ no_restart_regexp } + [no_manual_start, no_manual_stop, no_restart] +end + +def wait_and_get_failed_services(services, start_timeout_ms) + puts "Waiting #{start_timeout_ms} ms for services to fail" + # Force the previous message to always be visible before sleeping + STDOUT.flush + sleep(start_timeout_ms / 1000.0) + get_failed_units(services) +end + +def show_failed_services_status(services) + puts + services.each do |service| + run_cmd('systemctl', '--user', 'status', service) + puts + end +end + +def print_service_msg(msg, services) + return if services.empty? + if @verbose + puts "#{msg}:", services.to_a + else + puts msg + end +end + +def notify_skipped_units(no_restart) + puts "Not restarting: #{no_restart.join(' ')}" unless no_restart.empty? +end + +setup_services(*ARGV) diff --git a/infra/libkookie/home-manager-stable/modules/systemd-activate.sh b/infra/libkookie/home-manager-stable/modules/systemd-activate.sh new file mode 100644 index 00000000000..1c464693cfc --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/systemd-activate.sh @@ -0,0 +1,114 @@ +#!/usr/bin/env bash + +function isStartable() { + local service="$1" + [[ $(systemctl --user show -p RefuseManualStart "$service") == *=no ]] +} + +function isStoppable() { + if [[ -v oldGenPath ]] ; then + local service="$1" + [[ $(systemctl --user show -p RefuseManualStop "$service") == *=no ]] + fi +} + +function systemdPostReload() { + local workDir + workDir="$(mktemp -d)" + + if [[ -v oldGenPath ]] ; then + local oldUserServicePath="$oldGenPath/home-files/.config/systemd/user" + fi + + local newUserServicePath="$newGenPath/home-files/.config/systemd/user" + local oldServiceFiles="$workDir/old-files" + local newServiceFiles="$workDir/new-files" + local servicesDiffFile="$workDir/diff-files" + + if [[ ! (-v oldUserServicePath && -d "$oldUserServicePath") \ + && ! -d "$newUserServicePath" ]]; then + return + fi + + if [[ ! (-v oldUserServicePath && -d "$oldUserServicePath") ]]; then + touch "$oldServiceFiles" + else + find "$oldUserServicePath" \ + -maxdepth 1 -name '*.service' -exec basename '{}' ';' \ + | sort \ + > "$oldServiceFiles" + fi + + if [[ ! -d "$newUserServicePath" ]]; then + touch "$newServiceFiles" + else + find "$newUserServicePath" \ + -maxdepth 1 -name '*.service' -exec basename '{}' ';' \ + | sort \ + > "$newServiceFiles" + fi + + diff \ + --new-line-format='+%L' \ + --old-line-format='-%L' \ + --unchanged-line-format=' %L' \ + "$oldServiceFiles" "$newServiceFiles" \ + > "$servicesDiffFile" || true + + local -a maybeRestart=( $(grep '^ ' "$servicesDiffFile" | cut -c2-) ) + local -a maybeStop=( $(grep '^-' "$servicesDiffFile" | cut -c2-) ) + local -a maybeStart=( $(grep '^+' "$servicesDiffFile" | cut -c2-) ) + local -a toRestart=( ) + local -a toStop=( ) + local -a toStart=( ) + + for f in "${maybeRestart[@]}" ; do + if isStoppable "$f" \ + && isStartable "$f" \ + && systemctl --quiet --user is-active "$f" \ + && ! cmp --quiet \ + "$oldUserServicePath/$f" \ + "$newUserServicePath/$f" ; then + toRestart+=("$f") + fi + done + + for f in "${maybeStop[@]}" ; do + if isStoppable "$f" ; then + toStop+=("$f") + fi + done + + for f in "${maybeStart[@]}" ; do + if isStartable "$f" ; then + toStart+=("$f") + fi + done + + rm -r "$workDir" + + local sugg="" + + if [[ -n "${toRestart[@]}" ]] ; then + sugg="${sugg}systemctl --user restart ${toRestart[@]}\n" + fi + + if [[ -n "${toStop[@]}" ]] ; then + sugg="${sugg}systemctl --user stop ${toStop[@]}\n" + fi + + if [[ -n "${toStart[@]}" ]] ; then + sugg="${sugg}systemctl --user start ${toStart[@]}\n" + fi + + if [[ -n "$sugg" ]] ; then + echo "Suggested commands:" + echo -n -e "$sugg" + fi +} + +oldGenPath="$1" +newGenPath="$2" + +$DRY_RUN_CMD systemctl --user daemon-reload +systemdPostReload diff --git a/infra/libkookie/home-manager-stable/modules/systemd.nix b/infra/libkookie/home-manager-stable/modules/systemd.nix new file mode 100644 index 00000000000..0be586d7c63 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/systemd.nix @@ -0,0 +1,329 @@ +{ config, lib, pkgs, ... }: + +let + + cfg = config.systemd.user; + + inherit (lib) getAttr hm isBool literalExpression mkIf mkMerge mkOption types; + + # From + mkPathSafeName = + lib.replaceChars [ "@" ":" "\\" "[" "]" ] [ "-" "-" "-" "" "" ]; + + enabled = cfg.services != { } # \ + || cfg.slices != { } # \ + || cfg.sockets != { } # \ + || cfg.targets != { } # \ + || cfg.timers != { } # \ + || cfg.paths != { } # \ + || cfg.mounts != { } # \ + || cfg.automounts != { } # \ + || cfg.sessionVariables != { }; + + toSystemdIni = lib.generators.toINI { + listsAsDuplicateKeys = true; + mkKeyValue = key: value: + let + value' = if isBool value then + (if value then "true" else "false") + else + toString value; + in "${key}=${value'}"; + }; + + buildService = style: name: serviceCfg: + let + filename = "${name}.${style}"; + pathSafeName = mkPathSafeName filename; + + # Needed because systemd derives unit names from the ultimate + # link target. + source = pkgs.writeTextFile { + name = pathSafeName; + text = toSystemdIni serviceCfg; + destination = "/${filename}"; + } + "/${filename}"; + + wantedBy = target: { + name = "systemd/user/${target}.wants/${filename}"; + value = { inherit source; }; + }; + in lib.singleton { + name = "systemd/user/${filename}"; + value = { inherit source; }; + } ++ map wantedBy (serviceCfg.Install.WantedBy or [ ]); + + buildServices = style: serviceCfgs: + lib.concatLists (lib.mapAttrsToList (buildService style) serviceCfgs); + + servicesStartTimeoutMs = builtins.toString cfg.servicesStartTimeoutMs; + + unitType = unitKind: + with types; + let primitive = either bool (either int str); + in attrsOf (attrsOf (attrsOf (either primitive (listOf primitive)))) // { + description = "systemd ${unitKind} unit configuration"; + }; + + unitDescription = type: '' + Definition of systemd per-user ${type} units. Attributes are + merged recursively. + + Note that the attributes follow the capitalization and naming used + by systemd. More details can be found in + + systemd.${type} + 5 + . + ''; + + unitExample = type: + literalExpression '' + { + ${lib.toLower type}-name = { + Unit = { + Description = "Example description"; + Documentation = [ "man:example(1)" "man:example(5)" ]; + }; + + ${type} = { + … + }; + }; + }; + ''; + + sessionVariables = mkIf (cfg.sessionVariables != { }) { + "environment.d/10-home-manager.conf".text = lib.concatStringsSep "\n" + (lib.mapAttrsToList (n: v: "${n}=${toString v}") cfg.sessionVariables) + + "\n"; + }; + +in { + meta.maintainers = [ lib.maintainers.rycee ]; + + options = { + systemd.user = { + systemctlPath = mkOption { + default = "${pkgs.systemd}/bin/systemctl"; + defaultText = "\${pkgs.systemd}/bin/systemctl"; + type = types.str; + description = '' + Absolute path to the systemctl tool. This + option may need to be set if running Home Manager on a + non-NixOS distribution. + ''; + }; + + services = mkOption { + default = { }; + type = unitType "service"; + description = unitDescription "service"; + example = unitExample "Service"; + }; + + slices = mkOption { + default = { }; + type = unitType "slices"; + description = unitDescription "slices"; + example = unitExample "Slices"; + }; + + sockets = mkOption { + default = { }; + type = unitType "socket"; + description = unitDescription "socket"; + example = unitExample "Socket"; + }; + + targets = mkOption { + default = { }; + type = unitType "target"; + description = unitDescription "target"; + example = unitExample "Target"; + }; + + timers = mkOption { + default = { }; + type = unitType "timer"; + description = unitDescription "timer"; + example = unitExample "Timer"; + }; + + paths = mkOption { + default = { }; + type = unitType "path"; + description = unitDescription "path"; + example = unitExample "Path"; + }; + + mounts = mkOption { + default = { }; + type = unitType "mount"; + description = unitDescription "mount"; + example = unitExample "Mount"; + }; + + automounts = mkOption { + default = { }; + type = unitType "automount"; + description = unitDescription "automount"; + example = unitExample "Automount"; + }; + + startServices = mkOption { + default = "suggest"; + type = with types; + either bool (enum [ "suggest" "legacy" "sd-switch" ]); + apply = p: if isBool p then if p then "legacy" else "suggest" else p; + description = '' + Whether new or changed services that are wanted by active targets + should be started. Additionally, stop obsolete services from the + previous generation. + + The alternatives are + + + suggest (or false) + + Use a very simple shell script to print suggested + systemctl commands to run. You will have to + manually run those commands after the switch. + + + + legacy (or true) + + Use a Ruby script to, in a more robust fashion, determine the + necessary changes and automatically run the + systemctl commands. + + + + sd-switch + + Use sd-switch, a third party application, to perform the service + updates. This tool offers more features while having a small + closure size. Note, it requires a fully functional user D-Bus + session. Once tested and deemed sufficiently robust, this will + become the default. + + + + ''; + }; + + servicesStartTimeoutMs = mkOption { + default = 0; + type = types.ints.unsigned; + description = '' + How long to wait for started services to fail until their start is + considered successful. The value 0 indicates no timeout. + ''; + }; + + sessionVariables = mkOption { + default = { }; + type = with types; attrsOf (either int str); + example = { EDITOR = "vim"; }; + description = '' + Environment variables that will be set for the user session. + The variable values must be as described in + + environment.d + 5 + . + ''; + }; + }; + }; + + config = mkMerge [ + { + assertions = [{ + assertion = enabled -> pkgs.stdenv.isLinux; + message = let + names = lib.concatStringsSep ", " (lib.attrNames ( # \ + cfg.services # \ + // cfg.slices # \ + // cfg.sockets # \ + // cfg.targets # \ + // cfg.timers # \ + // cfg.paths # \ + // cfg.mounts # \ + // cfg.sessionVariables)); + in "Must use Linux for modules that require systemd: " + names; + }]; + } + + # If we run under a Linux system we assume that systemd is + # available, in particular we assume that systemctl is in PATH. + # Do not install any user services if username is root. + (mkIf (pkgs.stdenv.isLinux && config.home.username != "root") { + xdg.configFile = mkMerge [ + (lib.listToAttrs ((buildServices "service" cfg.services) + ++ (buildServices "slices" cfg.slices) + ++ (buildServices "socket" cfg.sockets) + ++ (buildServices "target" cfg.targets) + ++ (buildServices "timer" cfg.timers) + ++ (buildServices "path" cfg.paths) + ++ (buildServices "mount" cfg.mounts) + ++ (buildServices "automount" cfg.automounts))) + + sessionVariables + ]; + + # Run systemd service reload if user is logged in. If we're + # running this from the NixOS module then XDG_RUNTIME_DIR is not + # set and systemd commands will fail. We'll therefore have to + # set it ourselves in that case. + home.activation.reloadSystemd = hm.dag.entryAfter [ "linkGeneration" ] + (let + cmd = { + suggest = '' + PATH=${dirOf cfg.systemctlPath}:$PATH \ + bash ${./systemd-activate.sh} "''${oldGenPath=}" "$newGenPath" + ''; + legacy = '' + PATH=${dirOf cfg.systemctlPath}:$PATH \ + ${pkgs.ruby}/bin/ruby ${./systemd-activate.rb} \ + "''${oldGenPath=}" "$newGenPath" "${servicesStartTimeoutMs}" + ''; + sd-switch = let + timeoutArg = if cfg.servicesStartTimeoutMs != 0 then + "--timeout " + servicesStartTimeoutMs + else + ""; + in '' + ${pkgs.sd-switch}/bin/sd-switch \ + ''${DRY_RUN:+--dry-run} $VERBOSE_ARG ${timeoutArg} \ + ''${oldGenPath:+--old-units $oldGenPath/home-files/.config/systemd/user} \ + --new-units $newGenPath/home-files/.config/systemd/user + ''; + }; + + ensureRuntimeDir = + "XDG_RUNTIME_DIR=\${XDG_RUNTIME_DIR:-/run/user/$(id -u)}"; + + systemctl = "${ensureRuntimeDir} ${cfg.systemctlPath}"; + in '' + systemdStatus=$(${systemctl} --user is-system-running 2>&1 || true) + + if [[ $systemdStatus == 'running' || $systemdStatus == 'degraded' ]]; then + if [[ $systemdStatus == 'degraded' ]]; then + warnEcho "The user systemd session is degraded:" + ${systemctl} --user --no-pager --state=failed + warnEcho "Attempting to reload services anyway..." + fi + + ${ensureRuntimeDir} \ + ${getAttr cfg.startServices cmd} + else + echo "User systemd daemon not running. Skipping reload." + fi + + unset systemdStatus + ''); + }) + ]; +} diff --git a/infra/libkookie/home-manager-stable/modules/targets/darwin/default.nix b/infra/libkookie/home-manager-stable/modules/targets/darwin/default.nix new file mode 100644 index 00000000000..4cf295daa06 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/targets/darwin/default.nix @@ -0,0 +1,76 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.targets.darwin; + + toDefaultsFile = domain: attrs: + pkgs.writeText "${domain}.plist" (lib.generators.toPlist { } attrs); + + toActivationCmd = domain: attrs: + "$DRY_RUN_CMD defaults import ${escapeShellArg domain} ${ + toDefaultsFile domain attrs + }"; + + nonNullDefaults = + mapAttrs (domain: attrs: (filterAttrs (n: v: v != null) attrs)) + cfg.defaults; + writableDefaults = filterAttrs (domain: attrs: attrs != { }) nonNullDefaults; + activationCmds = mapAttrsToList toActivationCmd writableDefaults; +in { + meta.maintainers = [ maintainers.midchildan ]; + + imports = [ ./fonts.nix ./keybindings.nix ./linkapps.nix ./search.nix ]; + + options.targets.darwin.defaults = mkOption { + type = types.submodule ./options.nix; + default = { }; + example = { + "com.apple.desktopservices" = { + DSDontWriteNetworkStores = true; + DSDontWriteUSBStores = true; + }; + }; + description = '' + Set macOS user defaults. Values set to null are + ignored. + + + + Some settings might require a re-login to take effect. + + + ''; + }; + + config = mkIf (activationCmds != [ ]) { + assertions = [ + (hm.assertions.assertPlatform "targets.darwin.defaults" pkgs + platforms.darwin) + ]; + + warnings = let + batteryPercentage = + attrByPath [ "com.apple.menuextra.battery" "ShowPercent" ] null + cfg.defaults; + webkitDevExtras = attrByPath [ + "com.apple.Safari" + "com.apple.Safari.ContentPageGroupIdentifier.WebKit2DeveloperExtrasEnabled" + ] null cfg.defaults; + in optional (batteryPercentage != null) '' + The option 'com.apple.menuextra.battery.ShowPercent' no longer works on + macOS 11 and later. Instead, open System Preferences, go to "Dock & + Menu Bar", select "Battery", and toggle the checkbox labeled "Show + Percentage." + '' ++ optional (webkitDevExtras != null) '' + The option 'com.apple.Safari.com.apple.Safari.ContentPageGroupIdentifier.WebKit2DeveloperExtrasEnabled' + is no longer present in recent versions of Safari. + ''; + + home.activation.setDarwinDefaults = hm.dag.entryAfter [ "writeBoundary" ] '' + $VERBOSE_ECHO "Configuring macOS user defaults" + ${concatStringsSep "\n" activationCmds} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/targets/darwin/fonts.nix b/infra/libkookie/home-manager-stable/modules/targets/darwin/fonts.nix new file mode 100644 index 00000000000..2c558227879 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/targets/darwin/fonts.nix @@ -0,0 +1,29 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + homeDir = config.home.homeDirectory; + fontsEnv = pkgs.buildEnv { + name = "home-manager-fonts"; + paths = config.home.packages; + pathsToLink = "/share/fonts"; + }; + fonts = "${fontsEnv}/share/fonts"; +in { + # macOS won't recognize symlinked fonts + config = mkIf pkgs.stdenv.hostPlatform.isDarwin { + home.activation.copyFonts = hm.dag.entryAfter [ "writeBoundary" ] '' + copyFonts() { + rm -rf ${homeDir}/Library/Fonts/HomeManager || : + + local f + find -L "${fonts}" -type f -printf '%P\0' | while IFS= read -rd "" f; do + $DRY_RUN_CMD install $VERBOSE_ARG -Dm644 -T \ + "${fonts}/$f" "${homeDir}/Library/Fonts/HomeManager/$f" + done + } + copyFonts + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/targets/darwin/keybindings.nix b/infra/libkookie/home-manager-stable/modules/targets/darwin/keybindings.nix new file mode 100644 index 00000000000..824daa57213 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/targets/darwin/keybindings.nix @@ -0,0 +1,47 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.targets.darwin; + homeDir = config.home.homeDirectory; + confFile = pkgs.writeText "DefaultKeybinding.dict" + (lib.generators.toPlist { } cfg.keybindings); +in { + options.targets.darwin.keybindings = mkOption { + type = with types; attrsOf anything; + default = { }; + example = { + "^u" = "deleteToBeginningOfLine:"; + "^w" = "deleteWordBackward:"; + }; + description = '' + This will configure the default keybindings for text fields in macOS + applications. See + Apple's documentation + for more details. + + + + Existing keybinding configuration will be wiped when using this + option. + + + ''; + }; + + config = mkIf (cfg.keybindings != { }) { + assertions = [ + (hm.assertions.assertPlatform "targets.darwin.keybindings" pkgs + platforms.darwin) + ]; + + # NOTE: just copy the files because symlinks won't be recognized by macOS + home.activation.setCocoaKeybindings = + hm.dag.entryAfter [ "writeBoundary" ] '' + $VERBOSE_ECHO "Configuring keybindings for the Cocoa Text System" + $DRY_RUN_CMD install -Dm644 $VERBOSE_ARG \ + "${confFile}" "${homeDir}/Library/KeyBindings/DefaultKeyBinding.dict" + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/targets/darwin/linkapps.nix b/infra/libkookie/home-manager-stable/modules/targets/darwin/linkapps.nix new file mode 100644 index 00000000000..118321e8f11 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/targets/darwin/linkapps.nix @@ -0,0 +1,16 @@ +{ config, lib, pkgs, ... }: + +{ + # Disabled for now due to conflicting behavior with nix-darwin. See + # https://github.com/nix-community/home-manager/issues/1341#issuecomment-687286866 + config = lib.mkIf (false && pkgs.stdenv.hostPlatform.isDarwin) { + # Install MacOS applications to the user environment. + home.file."Applications/Home Manager Apps".source = let + apps = pkgs.buildEnv { + name = "home-manager-applications"; + paths = config.home.packages; + pathsToLink = "/Applications"; + }; + in "${apps}/Applications"; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/targets/darwin/options.nix b/infra/libkookie/home-manager-stable/modules/targets/darwin/options.nix new file mode 100644 index 00000000000..65ce4e01144 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/targets/darwin/options.nix @@ -0,0 +1,213 @@ +{ config, lib, ... }: + +with lib; + +let + mkNullableOption = args: + lib.mkOption (args // { + type = types.nullOr args.type; + default = null; + }); + + mkNullableEnableOption = name: + lib.mkOption { + type = with types; nullOr bool; + default = null; + example = true; + description = "Whether to enable ${name}."; + }; + + safari = config."com.apple.Safari"; +in { + freeformType = with types; attrsOf (attrsOf anything); + + options = { + NSGlobalDomain = { + AppleLanguages = mkNullableOption { + type = with types; listOf str; + example = [ "en" ]; + description = "Sets the language to use in the preferred order."; + }; + + AppleLocale = mkNullableOption { + type = types.str; + example = "en_US"; + description = "Configures the user locale."; + }; + + AppleMeasurementUnits = mkNullableOption { + type = types.enum [ "Centimeters" "Inches" ]; + example = "Centimeters"; + description = "Sets the measurement unit."; + }; + + AppleTemperatureUnit = mkNullableOption { + type = types.enum [ "Celsius" "Fahrenheit" ]; + example = "Celsius"; + description = "Sets the temperature unit."; + }; + + AppleMetricUnits = mkNullableEnableOption "the metric system"; + + NSAutomaticCapitalizationEnabled = + mkNullableEnableOption "automatic captilization"; + + NSAutomaticDashSubstitutionEnabled = + mkNullableEnableOption "smart dashes"; + + NSAutomaticPeriodSubstitutionEnabled = + mkNullableEnableOption "period with double space"; + + NSAutomaticQuoteSubstitutionEnabled = + mkNullableEnableOption "smart quotes"; + + NSAutomaticSpellingCorrectionEnabled = + mkNullableEnableOption "spelling correction"; + }; + + "com.apple.desktopservices" = { + DSDontWriteNetworkStores = mkNullableOption { + type = types.bool; + example = false; + description = '' + Disable use of .DS_Store files on network shares. + See the + official article for more info. + ''; + }; + DSDontWriteUSBStores = mkNullableOption { + type = types.bool; + example = false; + description = '' + Disable use of .DS_Store files on thumb drives. + ''; + }; + }; + + "com.apple.dock" = { + tilesize = mkNullableOption { + type = types.int; + example = 64; + description = "Sets the size of the dock."; + }; + size-immutable = mkNullableEnableOption "locking of the dock size"; + expose-group-apps = mkNullableEnableOption + "grouping of windows by application in Mission Control"; + }; + + "com.apple.menuextra.battery".ShowPercent = mkNullableOption { + type = types.enum [ "YES" "NO" ]; + example = "NO"; + description = '' + This option no longer works on macOS 11 and later. Instead, open System + Preferences, go to "Dock & Menu Bar", select "Battery", and toggle + the checkbox labeled "Show Percentage." + + Whether to show battery percentage in the menu bar. + ''; + }; + + "com.apple.Safari" = { + AutoOpenSafeDownloads = + mkNullableEnableOption "opening of downloaded files"; + AutoFillPasswords = + mkNullableEnableOption "autofill of usernames and passwords"; + AutoFillCreditCardData = + mkNullableEnableOption "autofill of credit card numbers"; + IncludeDevelopMenu = + mkNullableEnableOption ''"Develop" menu in the menu bar''; + ShowOverlayStatusBar = mkNullableEnableOption "status bar"; + + WebKitDeveloperExtrasEnabledPreferenceKey = mkNullableOption { + type = types.bool; + description = '' + Configures the web inspector. + + + + Instead of setting this option directly, set + instead. + + + ''; + }; + "WebKitPreferences.developerExtrasEnabled" = mkNullableOption { + type = types.bool; + description = '' + Configures the web inspector. + + + + Instead of setting this option directly, set + instead. + + + ''; + }; + }; + + "com.apple.Safari.SandboxBroker" = { + ShowDevelopMenu = mkNullableOption { + type = types.bool; + description = '' + Show the "Develop" menu in Safari's menubar. + + + + Instead of setting this option directly, set + instead. + + + ''; + }; + }; + + "com.googlecode.iterm2" = { + AddNewTabAtEndOfTabs = mkNullableEnableOption + "placement of new tabs at the end of the tab bar"; + + AlternateMouseScroll = mkNullableEnableOption + "arrow keys when scrolling in alternate screen mode"; + + CopySelection = + mkNullableEnableOption "copy to clipboard upon selecting text"; + + OpenTmuxWindowsIn = mkNullableOption { + type = types.int; + example = 2; + description = '' + Configures how to restore tmux windows when attaching to a session. + + Possible Values + + 0 + Native windows + + + 1 + Native tabs in a new window + + + 2 + Tabs in the attaching window + + + ''; + }; + + ExperimentalKeyHandling = mkNullableEnableOption + "experimental key handling for AquaSKK compatibility"; + }; + }; + + config = { + "com.apple.Safari" = mkIf (safari.IncludeDevelopMenu != null) { + WebKitDeveloperExtrasEnabledPreferenceKey = safari.IncludeDevelopMenu; + "WebKitPreferences.developerExtrasEnabled" = safari.IncludeDevelopMenu; + }; + "com.apple.Safari.SandboxBroker" = + mkIf (safari.IncludeDevelopMenu != null) { + ShowDevelopMenu = safari.IncludeDevelopMenu; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/targets/darwin/search.nix b/infra/libkookie/home-manager-stable/modules/targets/darwin/search.nix new file mode 100644 index 00000000000..8e0df3b2037 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/targets/darwin/search.nix @@ -0,0 +1,38 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.targets.darwin; + searchEngines = { + Bing = "com.bing.www"; + DuckDuckGo = "com.duckduckgo"; + Ecosia = "org.ecosia.www"; + Google = "com.google.www"; + Yahoo = "com.yahoo.www"; + }; + searchId = getAttr cfg.search searchEngines; +in { + options.targets.darwin.search = mkOption { + type = with types; nullOr (enum (attrNames searchEngines)); + default = null; + description = "Default search engine."; + }; + + config = mkIf (cfg.search != null) { + assertions = [ + (hm.assertions.assertPlatform "targets.darwin.search" pkgs + platforms.darwin) + ]; + + targets.darwin.defaults = { + NSGlobalDomain.NSPreferredWebServices = { + NSWebServicesProviderWebSearch = { + NSDefaultDisplayName = cfg.search; + NSProviderIdentifier = searchId; + }; + }; + "com.apple.Safari".SearchProviderIdentifier = searchId; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/targets/generic-linux.nix b/infra/libkookie/home-manager-stable/modules/targets/generic-linux.nix new file mode 100644 index 00000000000..aad74afb6fb --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/targets/generic-linux.nix @@ -0,0 +1,105 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.targets.genericLinux; + + profileDirectory = config.home.profileDirectory; + +in { + imports = [ + (mkRenamedOptionModule [ "targets" "genericLinux" "extraXdgDataDirs" ] [ + "xdg" + "systemDirs" + "data" + ]) + ]; + + options.targets.genericLinux = { + enable = mkEnableOption "" // { + description = '' + Whether to enable settings that make Home Manager work better on + GNU/Linux distributions other than NixOS. + ''; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (hm.assertions.assertPlatform "targets.genericLinux" pkgs platforms.linux) + ]; + + xdg.systemDirs.data = [ + # Nix profiles + "\${NIX_STATE_DIR:-/nix/var/nix}/profiles/default/share" + "${profileDirectory}/share" + + # Distribution-specific + "/usr/share/ubuntu" + "/usr/local/share" + "/usr/share" + "/var/lib/snapd/desktop" + ]; + + # We need to append system-wide FHS directories due to the default prefix + # resolving to the Nix store. + # https://github.com/nix-community/home-manager/pull/2891#issuecomment-1101064521 + home.sessionVariables = { + XCURSOR_PATH = "$XCURSOR_PATH\${XCURSOR_PATH:+:}" + concatStringsSep ":" [ + "${config.home.profileDirectory}/share/icons" + "/usr/share/icons" + "/usr/share/pixmaps" + ]; + }; + + home.sessionVariablesExtra = '' + . "${pkgs.nix}/etc/profile.d/nix.sh" + + # reset TERM with new TERMINFO available (if any) + export TERM="$TERM" + ''; + + # We need to source both nix.sh and hm-session-vars.sh as noted in + # https://github.com/nix-community/home-manager/pull/797#issuecomment-544783247 + programs.bash.initExtra = '' + . "${pkgs.nix}/etc/profile.d/nix.sh" + . "${profileDirectory}/etc/profile.d/hm-session-vars.sh" + ''; + + programs.zsh.envExtra = '' + # Make system functions available to zsh + () { + setopt LOCAL_OPTIONS CASE_GLOB EXTENDED_GLOB + + local system_fpaths=( + # Package default + /usr/share/zsh/site-functions(/-N) + + # Debian + /usr/share/zsh/functions/**/*(/-N) + /usr/share/zsh/vendor-completions/(/-N) + /usr/share/zsh/vendor-functions/(/-N) + ) + fpath=(''${fpath} ''${system_fpaths}) + } + ''; + + systemd.user.sessionVariables = let + # https://github.com/archlinux/svntogit-packages/blob/packages/ncurses/trunk/PKGBUILD + # https://salsa.debian.org/debian/ncurses/-/blob/master/debian/rules + # https://src.fedoraproject.org/rpms/ncurses/blob/main/f/ncurses.spec + # https://gitweb.gentoo.org/repo/gentoo.git/tree/sys-libs/ncurses/ncurses-6.2-r1.ebuild + distroTerminfoDirs = concatStringsSep ":" [ + "/etc/terminfo" # debian, fedora, gentoo + "/lib/terminfo" # debian + "/usr/share/terminfo" # package default, all distros + ]; + in { + NIX_PATH = "$HOME/.nix-defexpr/channels\${NIX_PATH:+:}$NIX_PATH"; + TERMINFO_DIRS = + "${profileDirectory}/share/terminfo:$TERMINFO_DIRS\${TERMINFO_DIRS:+:}${distroTerminfoDirs}"; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/xresources.nix b/infra/libkookie/home-manager-stable/modules/xresources.nix new file mode 100644 index 00000000000..31eb6eaadd5 --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/xresources.nix @@ -0,0 +1,104 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.xresources; + + formatLine = n: v: + let + formatList = x: + if isList x then + throw "can not convert 2-dimensional lists to Xresources format" + else + formatValue x; + + formatValue = v: + if isBool v then + (if v then "true" else "false") + else if isList v then + concatMapStringsSep ", " formatList v + else + toString v; + in "${n}: ${formatValue v}"; + + xrdbMerge = "${pkgs.xorg.xrdb}/bin/xrdb -merge ${cfg.path}"; + +in { + meta.maintainers = [ maintainers.rycee ]; + + options = { + xresources.properties = mkOption { + type = with types; + let + prim = either bool (either int str); + entry = either prim (listOf prim); + in nullOr (attrsOf entry); + default = null; + example = literalExpression '' + { + "Emacs*toolBar" = 0; + "XTerm*faceName" = "dejavu sans mono"; + "XTerm*charClass" = [ "37:48" "45-47:48" "58:48" "64:48" "126:48" ]; + } + ''; + description = '' + X server resources that should be set. + Booleans are formatted as "true" or "false" respectively. + List elements are recursively formatted as a string and joined by commas. + All other values are directly formatted using builtins.toString. + Note, that 2-dimensional lists are not supported and specifying one will throw an exception. + If this and all other xresources options are + null, then this feature is disabled and no + ~/.Xresources link is produced. + ''; + }; + + xresources.extraConfig = mkOption { + type = types.lines; + default = ""; + example = literalExpression '' + builtins.readFile ( + pkgs.fetchFromGitHub { + owner = "solarized"; + repo = "xresources"; + rev = "025ceddbddf55f2eb4ab40b05889148aab9699fc"; + sha256 = "0lxv37gmh38y9d3l8nbnsm1mskcv10g3i83j0kac0a2qmypv1k9f"; + } + "/Xresources.dark" + ) + ''; + description = '' + Additional X server resources contents. + If this and all other xresources options are + null, then this feature is disabled and no + ~/.Xresources link is produced. + ''; + }; + + xresources.path = mkOption { + type = types.str; + default = "${config.home.homeDirectory}/.Xresources"; + defaultText = "$HOME/.Xresources"; + description = + "Path where Home Manager should link the .Xresources file."; + }; + }; + + config = mkIf ((cfg.properties != null && cfg.properties != { }) + || cfg.extraConfig != "") { + home.file.${cfg.path} = { + text = concatStringsSep "\n" ([ ] + ++ optional (cfg.extraConfig != "") cfg.extraConfig + ++ optionals (cfg.properties != null) + (mapAttrsToList formatLine cfg.properties)) + "\n"; + onChange = '' + if [[ -v DISPLAY ]]; then + ${xrdbMerge} + fi + ''; + }; + + xsession.initExtra = xrdbMerge; + }; +} diff --git a/infra/libkookie/home-manager-stable/modules/xsession.nix b/infra/libkookie/home-manager-stable/modules/xsession.nix new file mode 100644 index 00000000000..7ba9b54e93d --- /dev/null +++ b/infra/libkookie/home-manager-stable/modules/xsession.nix @@ -0,0 +1,218 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.xsession; + +in { + meta.maintainers = [ maintainers.rycee ]; + + options = { + xsession = { + enable = mkEnableOption "X Session"; + + scriptPath = mkOption { + type = types.str; + default = ".xsession"; + example = ".xsession-hm"; + description = '' + Path, relative to HOME, where Home Manager + should write the X session script. + ''; + }; + + profilePath = mkOption { + type = types.str; + default = ".xprofile"; + example = ".xprofile-hm"; + description = '' + Path, relative to HOME, where Home Manager + should write the X profile script. + ''; + }; + + windowManager.command = mkOption { + type = types.str; + example = literalExpression '' + let + xmonad = pkgs.xmonad-with-packages.override { + packages = self: [ self.xmonad-contrib self.taffybar ]; + }; + in + "''${xmonad}/bin/xmonad"; + ''; + default = ''test -n "$1" && eval "$@"''; + description = '' + Command to use to start the window manager. + + The default value allows integration with NixOS' generated xserver configuration. + + Extra actions and commands can be specified in . + ''; + }; + + preferStatusNotifierItems = mkOption { + type = types.bool; + default = false; + example = true; + description = '' + Whether tray applets should prefer using the Status Notifier + Items (SNI) protocol, commonly called App Indicators. Note, + not all tray applets or status bars support SNI. + ''; + }; + + profileExtra = mkOption { + type = types.lines; + default = ""; + description = "Extra shell commands to run before session start."; + }; + + initExtra = mkOption { + type = types.lines; + default = ""; + description = "Extra shell commands to run during initialization."; + }; + + importedVariables = mkOption { + type = types.listOf (types.strMatching "[a-zA-Z_][a-zA-Z0-9_]*"); + example = [ "GDK_PIXBUF_ICON_LOADER" ]; + visible = false; + description = '' + Environment variables to import into the user systemd + session. The will be available for use by graphical + services. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = + [ (hm.assertions.assertPlatform "xsession" pkgs platforms.linux) ]; + + xsession.importedVariables = [ + "DBUS_SESSION_BUS_ADDRESS" + "DISPLAY" + "SSH_AUTH_SOCK" + "XAUTHORITY" + "XDG_DATA_DIRS" + "XDG_RUNTIME_DIR" + "XDG_SESSION_ID" + ]; + + systemd.user = { + services = mkIf (config.home.keyboard != null) { + setxkbmap = { + Unit = { + Description = "Set up keyboard in X"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + }; + + Install = { WantedBy = [ "graphical-session.target" ]; }; + + Service = { + Type = "oneshot"; + RemainAfterExit = true; + ExecStart = with config.home.keyboard; + let + args = optional (layout != null) "-layout '${layout}'" + ++ optional (variant != null) "-variant '${variant}'" + ++ optional (model != null) "-model '${model}'" + ++ [ "-option ''" ] ++ map (v: "-option '${v}'") options; + in "${pkgs.xorg.setxkbmap}/bin/setxkbmap ${toString args}"; + }; + }; + + xplugd = { + Unit = { + Description = "Rerun setxkbmap.service when I/O is changed"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + }; + + Install = { WantedBy = [ "graphical-session.target" ]; }; + + Service = { + Type = "forking"; + ExecStart = let + script = pkgs.writeShellScript "xplugrc" '' + case "$1,$3" in + keyboard,connected) + systemctl --user restart setxkbmap.service + ;; + esac + ''; + in "${pkgs.xplugd}/bin/xplugd ${script}"; + }; + }; + }; + + targets = { + # A basic graphical session target for Home Manager. + hm-graphical-session = { + Unit = { + Description = "Home Manager X session"; + Requires = [ "graphical-session-pre.target" ]; + BindsTo = [ "graphical-session.target" "tray.target" ]; + }; + }; + + tray = { + Unit = { + Description = "Home Manager System Tray"; + Requires = [ "graphical-session-pre.target" ]; + }; + }; + }; + }; + + home.file.${cfg.profilePath}.text = '' + . "${config.home.profileDirectory}/etc/profile.d/hm-session-vars.sh" + + if [ -e "$HOME/.profile" ]; then + . "$HOME/.profile" + fi + + # If there are any running services from a previous session. + # Need to run this in xprofile because the NixOS xsession + # script starts up graphical-session.target. + systemctl --user stop graphical-session.target graphical-session-pre.target + + ${optionalString (cfg.importedVariables != [ ]) + ("systemctl --user import-environment " + + toString (unique cfg.importedVariables))} + + ${cfg.profileExtra} + + export HM_XPROFILE_SOURCED=1 + ''; + + home.file.${cfg.scriptPath} = { + executable = true; + text = '' + if [ -z "$HM_XPROFILE_SOURCED" ]; then + . "${config.home.homeDirectory}/${cfg.profilePath}" + fi + unset HM_XPROFILE_SOURCED + + systemctl --user start hm-graphical-session.target + + ${cfg.initExtra} + + ${cfg.windowManager.command} + + systemctl --user stop graphical-session.target + systemctl --user stop graphical-session-pre.target + + # Wait until the units actually stop. + while [ -n "$(systemctl --user --no-legend --state=deactivating list-units)" ]; do + sleep 0.5 + done + ''; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/nix-darwin/default.nix b/infra/libkookie/home-manager-stable/nix-darwin/default.nix new file mode 100644 index 00000000000..57f7559a317 --- /dev/null +++ b/infra/libkookie/home-manager-stable/nix-darwin/default.nix @@ -0,0 +1,145 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.home-manager; + + extendedLib = import ../modules/lib/stdlib-extended.nix pkgs.lib; + + hmModule = types.submoduleWith { + specialArgs = { + lib = extendedLib; + darwinConfig = config; + osConfig = config; + modulesPath = builtins.toString ../modules; + } // cfg.extraSpecialArgs; + modules = [ + ({ name, ... }: { + imports = import ../modules/modules.nix { + inherit pkgs; + lib = extendedLib; + useNixpkgsModule = !cfg.useGlobalPkgs; + }; + + config = { + submoduleSupport.enable = true; + submoduleSupport.externalPackageInstall = cfg.useUserPackages; + + home.username = config.users.users.${name}.name; + home.homeDirectory = config.users.users.${name}.home; + + # Make activation script use same version of Nix as system as a whole. + # This avoids problems with Nix not being in PATH. + home.extraActivationPath = [ config.nix.package ]; + }; + }) + ] ++ cfg.sharedModules; + }; + +in + +{ + options = { + home-manager = { + useUserPackages = mkEnableOption '' + installation of user packages through the + option. + ''; + + useGlobalPkgs = mkEnableOption '' + using the system configuration's pkgs + argument in Home Manager. This disables the Home Manager + options + ''; + + backupFileExtension = mkOption { + type = types.nullOr types.str; + default = null; + example = "backup"; + description = '' + On activation move existing files by appending the given + file extension rather than exiting with an error. + ''; + }; + + extraSpecialArgs = mkOption { + type = types.attrs; + default = { }; + example = literalExpression "{ inherit emacs-overlay; }"; + description = '' + Extra specialArgs passed to Home Manager. This + option can be used to pass additional arguments to all modules. + ''; + }; + + sharedModules = mkOption { + type = with types; + # TODO: use types.raw once this PR is merged: https://github.com/NixOS/nixpkgs/pull/132448 + listOf (mkOptionType { + name = "submodule"; + inherit (submodule { }) check; + merge = lib.options.mergeOneOption; + description = "Home Manager modules"; + }); + default = [ ]; + example = literalExpression "[ { home.packages = [ nixpkgs-fmt ]; } ]"; + description = '' + Extra modules added to all users. + ''; + }; + + verbose = mkEnableOption "verbose output on activation"; + + users = mkOption { + type = types.attrsOf hmModule; + default = {}; + # Set as not visible to prevent the entire submodule being included in + # the documentation. + visible = false; + description = '' + Per-user Home Manager configuration. + ''; + }; + }; + }; + + config = mkIf (cfg.users != {}) { + warnings = + flatten (flip mapAttrsToList cfg.users (user: config: + flip map config.warnings (warning: + "${user} profile: ${warning}" + ) + )); + + assertions = + flatten (flip mapAttrsToList cfg.users (user: config: + flip map config.assertions (assertion: + { + inherit (assertion) assertion; + message = "${user} profile: ${assertion.message}"; + } + ) + )); + + users.users = mkIf cfg.useUserPackages ( + mapAttrs (username: usercfg: { + packages = [ usercfg.home.path ]; + }) cfg.users + ); + + environment.pathsToLink = mkIf cfg.useUserPackages [ "/etc/profile.d" ]; + + system.activationScripts.postActivation.text = + concatStringsSep "\n" (mapAttrsToList (username: usercfg: '' + echo Activating home-manager configuration for ${username} + sudo -u ${username} -s --set-home ${pkgs.writeShellScript "activation-${username}" '' + ${lib.optionalString (cfg.backupFileExtension != null) + "export HOME_MANAGER_BACKUP_EXT=${lib.escapeShellArg cfg.backupFileExtension}"} + ${lib.optionalString cfg.verbose "export VERBOSE=1"} + exec ${usercfg.home.activationPackage}/activate + ''} + '') cfg.users); + }; +} diff --git a/infra/libkookie/home-manager-stable/nixos/default.nix b/infra/libkookie/home-manager-stable/nixos/default.nix new file mode 100644 index 00000000000..766ce76f9cf --- /dev/null +++ b/infra/libkookie/home-manager-stable/nixos/default.nix @@ -0,0 +1,185 @@ +{ config, lib, pkgs, utils, ... }: + +with lib; + +let + + cfg = config.home-manager; + + extendedLib = import ../modules/lib/stdlib-extended.nix pkgs.lib; + + hmModule = types.submoduleWith { + specialArgs = { + lib = extendedLib; + nixosConfig = config; + osConfig = config; + modulesPath = builtins.toString ../modules; + } // cfg.extraSpecialArgs; + modules = [ + ({ name, ... }: { + imports = import ../modules/modules.nix { + inherit pkgs; + lib = extendedLib; + useNixpkgsModule = !cfg.useGlobalPkgs; + }; + + config = { + submoduleSupport.enable = true; + submoduleSupport.externalPackageInstall = cfg.useUserPackages; + + # The per-user directory inside /etc/profiles is not known by + # fontconfig by default. + fonts.fontconfig.enable = cfg.useUserPackages + && config.fonts.fontconfig.enable; + + home.username = config.users.users.${name}.name; + home.homeDirectory = config.users.users.${name}.home; + + # Make activation script use same version of Nix as system as a whole. + # This avoids problems with Nix not being in PATH. + home.extraActivationPath = [ config.nix.package ]; + }; + }) + ] ++ cfg.sharedModules; + }; + + serviceEnvironment = optionalAttrs (cfg.backupFileExtension != null) { + HOME_MANAGER_BACKUP_EXT = cfg.backupFileExtension; + } // optionalAttrs cfg.verbose { VERBOSE = "1"; }; + +in { + options = { + home-manager = { + useUserPackages = mkEnableOption '' + installation of user packages through the + option + ''; + + useGlobalPkgs = mkEnableOption '' + using the system configuration's pkgs + argument in Home Manager. This disables the Home Manager + options + ''; + + backupFileExtension = mkOption { + type = types.nullOr types.str; + default = null; + example = "backup"; + description = '' + On activation move existing files by appending the given + file extension rather than exiting with an error. + ''; + }; + + extraSpecialArgs = mkOption { + type = types.attrs; + default = { }; + example = literalExpression "{ inherit emacs-overlay; }"; + description = '' + Extra specialArgs passed to Home Manager. This + option can be used to pass additional arguments to all modules. + ''; + }; + + sharedModules = mkOption { + type = with types; + # TODO: use types.raw once this PR is merged: https://github.com/NixOS/nixpkgs/pull/132448 + listOf (mkOptionType { + name = "submodule"; + inherit (submodule { }) check; + merge = lib.options.mergeOneOption; + description = "Home Manager modules"; + }); + default = [ ]; + example = literalExpression "[ { home.packages = [ nixpkgs-fmt ]; } ]"; + description = '' + Extra modules added to all users. + ''; + }; + + verbose = mkEnableOption "verbose output on activation"; + + users = mkOption { + type = types.attrsOf hmModule; + default = { }; + # Set as not visible to prevent the entire submodule being included in + # the documentation. + visible = false; + description = '' + Per-user Home Manager configuration. + ''; + }; + }; + }; + + config = mkIf (cfg.users != { }) { + warnings = flatten (flip mapAttrsToList cfg.users (user: config: + flip map config.warnings (warning: "${user} profile: ${warning}"))); + + assertions = flatten (flip mapAttrsToList cfg.users (user: config: + flip map config.assertions (assertion: { + inherit (assertion) assertion; + message = "${user} profile: ${assertion.message}"; + }))); + + users.users = mkIf cfg.useUserPackages + (mapAttrs (username: usercfg: { packages = [ usercfg.home.path ]; }) + cfg.users); + + environment.pathsToLink = mkIf cfg.useUserPackages [ "/etc/profile.d" ]; + + systemd.services = mapAttrs' (_: usercfg: + let username = usercfg.home.username; + in nameValuePair ("home-manager-${utils.escapeSystemdPath username}") { + description = "Home Manager environment for ${username}"; + wantedBy = [ "multi-user.target" ]; + wants = [ "nix-daemon.socket" ]; + after = [ "nix-daemon.socket" ]; + before = [ "systemd-user-sessions.service" ]; + + environment = serviceEnvironment; + + unitConfig = { RequiresMountsFor = usercfg.home.homeDirectory; }; + + stopIfChanged = false; + + serviceConfig = { + User = usercfg.home.username; + Type = "oneshot"; + RemainAfterExit = "yes"; + TimeoutStartSec = 90; + SyslogIdentifier = "hm-activate-${username}"; + + ExecStart = let + systemctl = + "XDG_RUNTIME_DIR=\${XDG_RUNTIME_DIR:-/run/user/$UID} systemctl"; + + sed = "${pkgs.gnused}/bin/sed"; + + exportedSystemdVariables = concatStringsSep "|" [ + "DBUS_SESSION_BUS_ADDRESS" + "DISPLAY" + "WAYLAND_DISPLAY" + "XAUTHORITY" + "XDG_RUNTIME_DIR" + ]; + + setupEnv = pkgs.writeScript "hm-setup-env" '' + #! ${pkgs.runtimeShell} -el + + # The activation script is run by a login shell to make sure + # that the user is given a sane environment. + # If the user is logged in, import variables from their current + # session environment. + eval "$( + ${systemctl} --user show-environment 2> /dev/null \ + | ${sed} -En '/^(${exportedSystemdVariables})=/s/^/export /p' + )" + + exec "$1/activate" + ''; + in "${setupEnv} ${usercfg.home.activationPackage}"; + }; + }) cfg.users; + }; +} diff --git a/infra/libkookie/home-manager-stable/overlay.nix b/infra/libkookie/home-manager-stable/overlay.nix new file mode 100644 index 00000000000..78fcb60ce3c --- /dev/null +++ b/infra/libkookie/home-manager-stable/overlay.nix @@ -0,0 +1,3 @@ +final: prev: { + home-manager = prev.callPackage ./home-manager { path = toString ./.; }; +} diff --git a/infra/libkookie/home-manager-stable/tests/asserts.nix b/infra/libkookie/home-manager-stable/tests/asserts.nix new file mode 100644 index 00000000000..c1fe177ee61 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/asserts.nix @@ -0,0 +1,81 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + options.test.asserts = { + warnings = { + enable = mkOption { + type = types.bool; + default = true; + description = "Whether warning asserts are enabled."; + }; + + expected = mkOption { + type = types.listOf types.str; + default = [ ]; + description = '' + List of expected warnings. + ''; + }; + }; + + assertions = { + enable = mkOption { + type = types.bool; + default = true; + description = "Whether assertion asserts are enabled."; + }; + + expected = mkOption { + type = types.listOf types.str; + default = [ ]; + description = '' + List of expected assertions. + ''; + }; + }; + }; + + config = mkMerge [ + (mkIf config.test.asserts.warnings.enable { + home.file = { + "asserts/warnings.actual".text = concatStringsSep '' + + -- + '' config.warnings; + }; + + nmt.script = '' + assertFileContent \ + home-files/asserts/warnings.actual \ + ${ + pkgs.writeText "warnings.expected" (concatStringsSep '' + + -- + '' config.test.asserts.warnings.expected) + } + ''; + }) + + (mkIf config.test.asserts.assertions.enable { + home.file = { + "asserts/assertions.actual".text = concatStringsSep '' + + -- + '' (map (x: x.message) (filter (x: !x.assertion) config.assertions)); + }; + + nmt.script = '' + assertFileContent \ + home-files/asserts/assertions.actual \ + ${ + pkgs.writeText "assertions.expected" (concatStringsSep '' + + -- + '' config.test.asserts.assertions.expected) + } + ''; + }) + ]; +} diff --git a/infra/libkookie/home-manager-stable/tests/big-test.nix b/infra/libkookie/home-manager-stable/tests/big-test.nix new file mode 100644 index 00000000000..421eaebbd86 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/big-test.nix @@ -0,0 +1,13 @@ +{ lib, ... }: + +{ + options.test.enableBig = lib.mkOption { + type = lib.types.bool; + default = true; + description = '' + Whether to enable big tests. These are tests that require + more resources than typical tests. For example, tests that depend on large + packages or tests that take long to run. + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/default.nix b/infra/libkookie/home-manager-stable/tests/default.nix new file mode 100644 index 00000000000..141b2edd4c9 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/default.nix @@ -0,0 +1,180 @@ +{ pkgs ? import {}, enableBig ? true }: + +let + + lib = import ../modules/lib/stdlib-extended.nix pkgs.lib; + + nmt = pkgs.fetchFromGitLab { + owner = "rycee"; + repo = "nmt"; + rev = "d83601002c99b78c89ea80e5e6ba21addcfe12ae"; + sha256 = "1xzwwxygzs1cmysg97hzd285r7n1g1lwx5y1ar68gwq07a1rczmv"; + }; + + modules = import ../modules/modules.nix { + inherit lib pkgs; + check = false; + } ++ [ + { + # Fix impurities. Without these some of the user's environment + # will leak into the tests through `builtins.getEnv`. + xdg.enable = true; + home.username = "hm-user"; + home.homeDirectory = "/home/hm-user"; + + # Avoid including documentation since this will cause + # unnecessary rebuilds of the tests. + manual.manpages.enable = false; + + imports = [ ./asserts.nix ./big-test.nix ./stubs.nix ]; + + test.enableBig = enableBig; + } + ]; + + isDarwin = pkgs.stdenv.hostPlatform.isDarwin; + isLinux = pkgs.stdenv.hostPlatform.isLinux; + +in + +import nmt { + inherit lib pkgs modules; + testedAttrPath = [ "home" "activationPackage" ]; + tests = builtins.foldl' (a: b: a // (import b)) { } ([ + ./lib/types + ./modules/files + ./modules/home-environment + ./modules/misc/fontconfig + ./modules/misc/nix + ./modules/misc/specialization + ./modules/programs/alacritty + ./modules/programs/alot + ./modules/programs/aria2 + ./modules/programs/atuin + ./modules/programs/autojump + ./modules/programs/bash + ./modules/programs/bat + ./modules/programs/bottom + ./modules/programs/broot + ./modules/programs/browserpass + ./modules/programs/dircolors + ./modules/programs/direnv + ./modules/programs/emacs + ./modules/programs/feh + ./modules/programs/fish + ./modules/programs/gh + ./modules/programs/git + ./modules/programs/gpg + ./modules/programs/helix + ./modules/programs/himalaya + ./modules/programs/htop + ./modules/programs/i3status + ./modules/programs/irssi + ./modules/programs/kakoune + ./modules/programs/kitty + ./modules/programs/less + ./modules/programs/lf + ./modules/programs/lieer + ./modules/programs/man + ./modules/programs/mbsync + ./modules/programs/mpv + ./modules/programs/mu + ./modules/programs/ncmpcpp + ./modules/programs/ne + ./modules/programs/neomutt + ./modules/programs/newsboat + ./modules/programs/nix-index + ./modules/programs/nnn + ./modules/programs/nushell + ./modules/programs/pandoc + ./modules/programs/pet + ./modules/programs/powerline-go + ./modules/programs/pubs + ./modules/programs/qutebrowser + ./modules/programs/readline + ./modules/programs/sagemath + ./modules/programs/sbt + ./modules/programs/scmpuff + ./modules/programs/sm64ex + ./modules/programs/ssh + ./modules/programs/starship + ./modules/programs/taskwarrior + ./modules/programs/texlive + ./modules/programs/tmux + ./modules/programs/topgrade + ./modules/programs/vscode + ./modules/programs/watson + ./modules/programs/zplug + ./modules/programs/zsh + ./modules/xresources + ] ++ lib.optionals isDarwin [ + ./modules/launchd + ./modules/targets-darwin + ] ++ lib.optionals isLinux [ + ./modules/config/i18n + ./modules/i18n/input-method + ./modules/misc/debug + ./modules/misc/gtk + ./modules/misc/numlock + ./modules/misc/pam + ./modules/misc/qt + ./modules/misc/xdg + ./modules/misc/xsession + ./modules/programs/abook + ./modules/programs/autorandr + ./modules/programs/firefox + ./modules/programs/foot + ./modules/programs/getmail + ./modules/programs/gnome-terminal + ./modules/programs/hexchat + ./modules/programs/i3status-rust + ./modules/programs/kodi + ./modules/programs/mangohud + ./modules/programs/ncmpcpp-linux + ./modules/programs/neovim # Broken package dependency on Darwin. + ./modules/programs/rbw + ./modules/programs/rofi + ./modules/programs/rofi-pass + ./modules/programs/terminator + ./modules/programs/waybar + ./modules/programs/xmobar + ./modules/services/barrier + ./modules/services/devilspie2 + ./modules/services/dropbox + ./modules/services/emacs + ./modules/services/espanso + ./modules/services/flameshot + ./modules/services/fluidsynth + ./modules/services/fnott + ./modules/services/fusuma + ./modules/services/git-sync + ./modules/services/gpg-agent + ./modules/services/gromit-mpx + ./modules/services/home-manager-auto-upgrade + ./modules/services/kanshi + ./modules/services/lieer + ./modules/services/mopidy + ./modules/services/mpd + ./modules/services/mpdris2 + ./modules/services/pantalaimon + ./modules/services/pbgopy + ./modules/services/picom + ./modules/services/playerctld + ./modules/services/polybar + ./modules/services/redshift-gammastep + ./modules/services/screen-locker + ./modules/services/swayidle + ./modules/services/sxhkd + ./modules/services/syncthing + ./modules/services/trayer + ./modules/services/twmn + ./modules/services/window-managers/bspwm + ./modules/services/window-managers/herbstluftwm + ./modules/services/window-managers/i3 + ./modules/services/window-managers/sway + ./modules/services/wlsunset + ./modules/services/xsettingsd + ./modules/systemd + ./modules/targets-linux + ]); +} diff --git a/infra/libkookie/home-manager-stable/tests/lib/types/dag-merge-result.txt b/infra/libkookie/home-manager-stable/tests/lib/types/dag-merge-result.txt new file mode 100644 index 00000000000..9779ef13c0f --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/lib/types/dag-merge-result.txt @@ -0,0 +1,3 @@ +before:before +between:between +after:after diff --git a/infra/libkookie/home-manager-stable/tests/lib/types/dag-merge.nix b/infra/libkookie/home-manager-stable/tests/lib/types/dag-merge.nix new file mode 100644 index 00000000000..0b41ec8a0c4 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/lib/types/dag-merge.nix @@ -0,0 +1,35 @@ +{ config, lib, pkgs, ... }: + +let + inherit (lib) concatStringsSep hm mkIf mkMerge mkOption types; + + dag = lib.hm.dag; + + result = let + sorted = dag.topoSort config.tested.dag; + data = map (e: "${e.name}:${e.data}") sorted.result; + in concatStringsSep "\n" data + "\n"; + +in { + options.tested.dag = mkOption { type = hm.types.dagOf types.str; }; + + config = { + tested.dag = mkMerge [ + { never = mkIf false "never"; } + { after = mkMerge [ "after" (mkIf false "neither") ]; } + { before = dag.entryBefore [ "after" ] (mkIf true "before"); } + { + between = + mkIf true (dag.entryBetween [ "after" ] [ "before" ] "between"); + } + ]; + + home.file."result.txt".text = result; + + nmt.script = '' + assertFileContent \ + home-files/result.txt \ + ${./dag-merge-result.txt} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/lib/types/dag-submodule.nix b/infra/libkookie/home-manager-stable/tests/lib/types/dag-submodule.nix new file mode 100644 index 00000000000..809b1a59b6f --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/lib/types/dag-submodule.nix @@ -0,0 +1,42 @@ +{ config, lib, pkgs, ... }: + +let + inherit (lib) concatStringsSep hm mkOption types; + + dag = lib.hm.dag; + + result = let + sorted = dag.topoSort config.tested.dag; + data = map (e: "${e.name}:${e.data.name}") sorted.result; + in concatStringsSep "\n" data + "\n"; + +in { + options.tested.dag = mkOption { + type = hm.types.dagOf (types.submodule ({ dagName, ... }: { + options.name = mkOption { type = types.str; }; + config.name = "dn-${dagName}"; + })); + }; + + config = { + tested.dag = { + after = { }; + before = dag.entryBefore [ "after" ] { }; + between = dag.entryBetween [ "after" ] [ "before" ] { }; + }; + + home.file."result.txt".text = result; + + nmt.script = '' + assertFileContent \ + home-files/result.txt \ + ${ + pkgs.writeText "result.txt" '' + before:dn-before + between:dn-between + after:dn-after + '' + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/lib/types/default.nix b/infra/libkookie/home-manager-stable/tests/lib/types/default.nix new file mode 100644 index 00000000000..acb56501272 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/lib/types/default.nix @@ -0,0 +1,7 @@ +{ + lib-types-dag-submodule = ./dag-submodule.nix; + lib-types-dag-merge = ./dag-merge.nix; + lib-types-list-or-dag-merge = ./list-or-dag-merge.nix; + + lib-types-gvariant-merge = ./gvariant-merge.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/lib/types/gvariant-merge.nix b/infra/libkookie/home-manager-stable/tests/lib/types/gvariant-merge.nix new file mode 100644 index 00000000000..c4de6827f8b --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/lib/types/gvariant-merge.nix @@ -0,0 +1,86 @@ +{ config, lib, pkgs, ... }: + +let inherit (lib) concatStringsSep hm mapAttrsToList mkMerge mkOption types; +in { + options.examples = mkOption { type = types.attrsOf hm.types.gvariant; }; + + config = { + examples = with hm.gvariant; + mkMerge [ + { bool = true; } + { bool = true; } + + { float = 3.14; } + + { int = -42; } + { int = -42; } + + { uint32 = mkUint32 42; } + { uint32 = mkUint32 42; } + + { int16 = mkInt16 (-42); } + { int16 = mkInt16 (-42); } + + { uint16 = mkUint16 42; } + { uint16 = mkUint16 42; } + + { int64 = mkInt64 (-42); } + { int64 = mkInt64 (-42); } + + { uint64 = mkUint64 42; } + { uint64 = mkUint64 42; } + + { array1 = [ "one" ]; } + { array1 = mkArray type.string [ "two" ]; } + { array2 = mkArray type.uint32 [ 1 ]; } + { array2 = mkArray type.uint32 [ 2 ]; } + + { emptyArray1 = [ ]; } + { emptyArray2 = mkEmptyArray type.uint32; } + + { string = "foo"; } + { string = "foo"; } + { + escapedString = '' + '\ + ''; + } + + { tuple = mkTuple [ 1 [ "foo" ] ]; } + + { maybe1 = mkNothing type.string; } + { maybe2 = mkJust (mkUint32 4); } + ]; + + home.file."result.txt".text = let + mkLine = n: v: "${n} = ${toString (hm.gvariant.mkValue v)}"; + result = concatStringsSep "\n" (mapAttrsToList mkLine config.examples); + in result + "\n"; + + nmt.script = '' + assertFileContent \ + home-files/result.txt \ + ${ + pkgs.writeText "expected.txt" '' + array1 = @as ['one','two'] + array2 = @au [1,2] + bool = true + emptyArray1 = @as [] + emptyArray2 = @au [] + escapedString = '\'\\\n' + float = 3.140000 + int = -42 + int16 = @n -42 + int64 = @x -42 + maybe1 = @ms nothing + maybe2 = just @u 4 + string = 'foo' + tuple = @(ias) (1,@as ['foo']) + uint16 = @q 42 + uint32 = @u 42 + uint64 = @t 42 + '' + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/lib/types/list-or-dag-merge-result.txt b/infra/libkookie/home-manager-stable/tests/lib/types/list-or-dag-merge-result.txt new file mode 100644 index 00000000000..5fb67a5101c --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/lib/types/list-or-dag-merge-result.txt @@ -0,0 +1,15 @@ +before:before +between:between +after:after +unnamed-1.1:k +unnamed-1.2:l +unnamed-2.01:a +unnamed-2.02:b +unnamed-2.03:c +unnamed-2.04:d +unnamed-2.05:e +unnamed-2.06:f +unnamed-2.07:g +unnamed-2.08:h +unnamed-2.09:i +unnamed-2.10:j diff --git a/infra/libkookie/home-manager-stable/tests/lib/types/list-or-dag-merge.nix b/infra/libkookie/home-manager-stable/tests/lib/types/list-or-dag-merge.nix new file mode 100644 index 00000000000..4706c5cedef --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/lib/types/list-or-dag-merge.nix @@ -0,0 +1,33 @@ +{ config, lib, pkgs, ... }: + +let + inherit (lib) concatStringsSep hm mkMerge mkOption types; + + dag = lib.hm.dag; + + result = let + sorted = dag.topoSort config.tested.dag; + data = map (e: "${e.name}:${e.data}") sorted.result; + in concatStringsSep "\n" data + "\n"; + +in { + options.tested.dag = mkOption { type = hm.types.listOrDagOf types.str; }; + + config = { + tested = mkMerge [ + { dag = [ "k" "l" ]; } + { dag = [ "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" ]; } + { dag.after = "after"; } + { dag.before = dag.entryBefore [ "after" ] "before"; } + { dag.between = dag.entryBetween [ "after" ] [ "before" ] "between"; } + ]; + + home.file."result.txt".text = result; + + nmt.script = '' + assertFileContent \ + home-files/result.txt \ + ${./list-or-dag-merge-result.txt} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/accounts/email-test-accounts.nix b/infra/libkookie/home-manager-stable/tests/modules/accounts/email-test-accounts.nix new file mode 100644 index 00000000000..e66e58949ee --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/accounts/email-test-accounts.nix @@ -0,0 +1,29 @@ +{ ... }: + +{ + accounts.email = { + maildirBasePath = "Mail"; + + accounts = { + "hm@example.com" = { + primary = true; + address = "hm@example.com"; + userName = "home.manager"; + realName = "H. M. Test"; + passwordCommand = "password-command"; + imap.host = "imap.example.com"; + smtp.host = "smtp.example.com"; + }; + + hm-account = { + address = "hm@example.org"; + userName = "home.manager.jr"; + realName = "H. M. Test Jr."; + passwordCommand = "password-command 2"; + imap.host = "imap.example.org"; + smtp.host = "smtp.example.org"; + smtp.tls.useStartTls = true; + }; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/config/i18n/default.nix b/infra/libkookie/home-manager-stable/tests/modules/config/i18n/default.nix new file mode 100644 index 00000000000..10b35b6f46b --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/config/i18n/default.nix @@ -0,0 +1,17 @@ +{ + i18n = { ... }: { + config = { + nmt.script = '' + hmEnvFile=home-path/etc/profile.d/hm-session-vars.sh + assertFileExists $hmEnvFile + assertFileRegex $hmEnvFile \ + '^export LOCALE_ARCHIVE_._..=".*/lib/locale/locale-archive"$' + + envFile=home-files/.config/environment.d/10-home-manager.conf + assertFileExists $envFile + assertFileRegex $envFile \ + '^LOCALE_ARCHIVE_._..=.*/lib/locale/locale-archive$' + ''; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/files/.hidden b/infra/libkookie/home-manager-stable/tests/modules/files/.hidden new file mode 100644 index 00000000000..ca05448e7a0 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/files/.hidden @@ -0,0 +1 @@ +The name of this file has a dot prefix. diff --git a/infra/libkookie/home-manager-stable/tests/modules/files/default.nix b/infra/libkookie/home-manager-stable/tests/modules/files/default.nix new file mode 100644 index 00000000000..52e44d22b1c --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/files/default.nix @@ -0,0 +1,9 @@ +{ + files-executable = ./executable.nix; + files-hidden-source = ./hidden-source.nix; + files-out-of-store-symlink = ./out-of-store-symlink.nix; + files-source-with-spaces = ./source-with-spaces.nix; + files-target-conflict = ./target-conflict.nix; + files-target-with-shellvar = ./target-with-shellvar.nix; + files-text = ./text.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/files/executable.nix b/infra/libkookie/home-manager-stable/tests/modules/files/executable.nix new file mode 100644 index 00000000000..b286c2b499f --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/files/executable.nix @@ -0,0 +1,17 @@ +{ config, lib, ... }: + +with lib; + +{ + config = { + home.file."executable" = { + text = ""; + executable = true; + }; + + nmt.script = '' + assertFileExists home-files/executable + assertFileIsExecutable home-files/executable; + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/files/hidden-source.nix b/infra/libkookie/home-manager-stable/tests/modules/files/hidden-source.nix new file mode 100644 index 00000000000..8169fedcd7f --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/files/hidden-source.nix @@ -0,0 +1,19 @@ +{ config, lib, ... }: + +with lib; + +{ + config = { + home.file.".hidden".source = ./.hidden; + + nmt.script = '' + assertFileExists home-files/.hidden; + assertFileContent home-files/.hidden ${ + builtins.path { + path = ./.hidden; + name = "expected"; + } + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/files/out-of-store-symlink.nix b/infra/libkookie/home-manager-stable/tests/modules/files/out-of-store-symlink.nix new file mode 100644 index 00000000000..af274aaebec --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/files/out-of-store-symlink.nix @@ -0,0 +1,29 @@ +{ config, lib, ... }: + +with lib; + +let + + filePath = ./. + "/source with spaces!"; + +in { + config = { + home.file."oos".source = config.lib.file.mkOutOfStoreSymlink filePath; + + nmt.script = '' + assertLinkExists "home-files/oos" + + storePath="$(readlink $TESTED/home-files/oos)" + + if [[ ! -L $storePath ]]; then + fail "Expected $storePath to be a symbolic link, but it was not." + fi + + actual="$(readlink "$storePath")" + expected="${toString filePath}" + if [[ $actual != $expected ]]; then + fail "Symlink home-files/oos should point to $expected via the Nix store, but it actually points to $actual." + fi + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/files/source with spaces! b/infra/libkookie/home-manager-stable/tests/modules/files/source with spaces! new file mode 100644 index 00000000000..e1ace404174 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/files/source with spaces! @@ -0,0 +1 @@ +Source with spaces! diff --git a/infra/libkookie/home-manager-stable/tests/modules/files/source-with-spaces.nix b/infra/libkookie/home-manager-stable/tests/modules/files/source-with-spaces.nix new file mode 100644 index 00000000000..1d593c64256 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/files/source-with-spaces.nix @@ -0,0 +1,20 @@ +{ config, lib, ... }: + +with lib; + +{ + config = { + home.file."source with spaces!".source = ./. + "/source with spaces!"; + + nmt.script = '' + assertFileExists 'home-files/source with spaces!'; + assertFileContent 'home-files/source with spaces!' \ + ${ + builtins.path { + path = ./. + "/source with spaces!"; + name = "source-with-spaces-expected"; + } + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/files/target-conflict.nix b/infra/libkookie/home-manager-stable/tests/modules/files/target-conflict.nix new file mode 100644 index 00000000000..dbcee80a008 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/files/target-conflict.nix @@ -0,0 +1,26 @@ +{ ... }: + +{ + config = { + home.file = { + conflict1 = { + text = ""; + target = "baz"; + }; + conflict2 = { + source = ./target-conflict.nix; + target = "baz"; + }; + }; + + test.asserts.assertions.expected = ['' + Conflicting managed target files: baz + + This may happen, for example, if you have a configuration similar to + + home.file = { + conflict1 = { source = ./foo.nix; target = "baz"; }; + conflict2 = { source = ./bar.nix; target = "baz"; }; + }'']; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/files/target-with-shellvar.nix b/infra/libkookie/home-manager-stable/tests/modules/files/target-with-shellvar.nix new file mode 100644 index 00000000000..c54946eb9eb --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/files/target-with-shellvar.nix @@ -0,0 +1,15 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + home.file."$HOME/$FOO/bar baz".text = "blah"; + + nmt.script = '' + assertFileExists 'home-files/$HOME/$FOO/bar baz'; + assertFileContent 'home-files/$HOME/$FOO/bar baz' \ + ${pkgs.writeText "expected" "blah"} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/files/text-expected.txt b/infra/libkookie/home-manager-stable/tests/modules/files/text-expected.txt new file mode 100644 index 00000000000..b3a0ff2db12 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/files/text-expected.txt @@ -0,0 +1,2 @@ +This is the +expected text. diff --git a/infra/libkookie/home-manager-stable/tests/modules/files/text.nix b/infra/libkookie/home-manager-stable/tests/modules/files/text.nix new file mode 100644 index 00000000000..6fc9a26fcb4 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/files/text.nix @@ -0,0 +1,18 @@ +{ config, lib, ... }: + +with lib; + +{ + config = { + home.file."using-text".text = '' + This is the + expected text. + ''; + + nmt.script = '' + assertFileExists home-files/using-text + assertFileIsNotExecutable home-files/using-text + assertFileContent home-files/using-text ${./text-expected.txt} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/home-environment/default.nix b/infra/libkookie/home-manager-stable/tests/modules/home-environment/default.nix new file mode 100644 index 00000000000..e76e248a164 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/home-environment/default.nix @@ -0,0 +1,4 @@ +{ + home-session-variables = ./session-variables.nix; + home-session-path = ./session-path.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/home-environment/session-path.nix b/infra/libkookie/home-manager-stable/tests/modules/home-environment/session-path.nix new file mode 100644 index 00000000000..57cfeceda34 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/home-environment/session-path.nix @@ -0,0 +1,15 @@ +{ config, lib, pkgs, ... }: + +{ + imports = [ + ({ ... }: { config.home.sessionPath = [ "foo" ]; }) + ({ ... }: { config.home.sessionPath = [ "bar" "baz" ]; }) + ]; + + nmt.script = '' + hmSessVars=home-path/etc/profile.d/hm-session-vars.sh + assertFileExists $hmSessVars + assertFileContains $hmSessVars \ + 'export PATH="$PATH''${PATH:+:}bar:baz:foo"' + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/home-environment/session-variables-expected.txt b/infra/libkookie/home-manager-stable/tests/modules/home-environment/session-variables-expected.txt new file mode 100644 index 00000000000..a96f61956b4 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/home-environment/session-variables-expected.txt @@ -0,0 +1,9 @@ +# Only source this once. +if [ -n "$__HM_SESS_VARS_SOURCED" ]; then return; fi +export __HM_SESS_VARS_SOURCED=1 +@exportLocaleVar@ +export V1="v1" +export V2="v2-v1" +export XDG_CACHE_HOME="/home/hm-user/.cache" +export XDG_CONFIG_HOME="/home/hm-user/.config" +export XDG_DATA_HOME="/home/hm-user/.local/share" diff --git a/infra/libkookie/home-manager-stable/tests/modules/home-environment/session-variables.nix b/infra/libkookie/home-manager-stable/tests/modules/home-environment/session-variables.nix new file mode 100644 index 00000000000..08c988d2bbe --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/home-environment/session-variables.nix @@ -0,0 +1,50 @@ +{ config, lib, pkgs, ... }: + +let + + inherit (pkgs.stdenv.hostPlatform) isDarwin; + + linuxExpected = '' + # Only source this once. + if [ -n "$__HM_SESS_VARS_SOURCED" ]; then return; fi + export __HM_SESS_VARS_SOURCED=1 + + export LOCALE_ARCHIVE_2_27="${pkgs.glibcLocales}/lib/locale/locale-archive" + export V1="v1" + export V2="v2-v1" + export XDG_CACHE_HOME="/home/hm-user/.cache" + export XDG_CONFIG_HOME="/home/hm-user/.config" + export XDG_DATA_HOME="/home/hm-user/.local/share" + export XDG_STATE_HOME="/home/hm-user/.local/state" + ''; + + darwinExpected = '' + # Only source this once. + if [ -n "$__HM_SESS_VARS_SOURCED" ]; then return; fi + export __HM_SESS_VARS_SOURCED=1 + + export V1="v1" + export V2="v2-v1" + export XDG_CACHE_HOME="/home/hm-user/.cache" + export XDG_CONFIG_HOME="/home/hm-user/.config" + export XDG_DATA_HOME="/home/hm-user/.local/share" + export XDG_STATE_HOME="/home/hm-user/.local/state" + ''; + + expected = pkgs.writeText "expected" + (if isDarwin then darwinExpected else linuxExpected); + +in { + config = { + home.sessionVariables = { + V1 = "v1"; + V2 = "v2-${config.home.sessionVariables.V1}"; + }; + + nmt.script = '' + assertFileExists home-path/etc/profile.d/hm-session-vars.sh + assertFileContent home-path/etc/profile.d/hm-session-vars.sh \ + ${expected} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/i18n/input-method/default.nix b/infra/libkookie/home-manager-stable/tests/modules/i18n/input-method/default.nix new file mode 100644 index 00000000000..a9d5764dfd0 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/i18n/input-method/default.nix @@ -0,0 +1,4 @@ +{ + input-method-fcitx5-configuration = ./fcitx5-configuration.nix; + input-method-kime-configuration = ./kime-configuration.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/i18n/input-method/fcitx5-configuration.nix b/infra/libkookie/home-manager-stable/tests/modules/i18n/input-method/fcitx5-configuration.nix new file mode 100644 index 00000000000..59738fb01af --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/i18n/input-method/fcitx5-configuration.nix @@ -0,0 +1,14 @@ +{ config, pkgs, ... }: + +{ + imports = [ ./fcitx5-stubs.nix ]; + + i18n.inputMethod = { + enabled = "fcitx5"; + fcitx5.addons = with pkgs; [ fcitx5-chinese-addons ]; + }; + + nmt.script = '' + assertFileExists home-files/.config/systemd/user/fcitx5-daemon.service + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/i18n/input-method/fcitx5-stubs.nix b/infra/libkookie/home-manager-stable/tests/modules/i18n/input-method/fcitx5-stubs.nix new file mode 100644 index 00000000000..cdf707de6c4 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/i18n/input-method/fcitx5-stubs.nix @@ -0,0 +1,27 @@ +{ + test.stubs = { + fcitx5 = { + version = "0"; + outPath = null; + buildScript = '' + mkdir -p $out/bin $out/share/applications $out/etc/xdg/autostart + touch $out/bin/fcitx5 \ + $out/share/applications/org.fcitx.Fcitx5.desktop \ + $out/etc/xdg/autostart/org.fcitx.Fcitx5.desktop + chmod +x $out/bin/fcitx5 + ''; + }; + fcitx5-configtool = { outPath = null; }; + fcitx5-lua = { outPath = null; }; + fcitx5-qt = { outPath = null; }; + fcitx5-gtk = { outPath = null; }; + fcitx5-chinese-addons = { outPath = null; }; + }; + + nixpkgs.overlays = [ + (self: super: { + fcitx5-with-addons = + super.fcitx5-with-addons.override { inherit (self) fcitx5-qt; }; + }) + ]; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/i18n/input-method/kime-configuration.nix b/infra/libkookie/home-manager-stable/tests/modules/i18n/input-method/kime-configuration.nix new file mode 100644 index 00000000000..fe50273fbca --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/i18n/input-method/kime-configuration.nix @@ -0,0 +1,14 @@ +{ config, pkgs, ... }: + +{ + i18n.inputMethod = { + enabled = "kime"; + kime.config = { engine = { hangul = { layout = "dubeolsik"; }; }; }; + }; + + test.stubs.kime = { outPath = null; }; + + nmt.script = '' + assertFileExists home-files/.config/systemd/user/kime-daemon.service + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/launchd/agents.nix b/infra/libkookie/home-manager-stable/tests/modules/launchd/agents.nix new file mode 100644 index 00000000000..cbcff6b5a27 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/launchd/agents.nix @@ -0,0 +1,25 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + launchd.agents."test-service" = { + enable = true; + config = { + ProgramArguments = [ "/some/command" "--with-arguments" "foo" ]; + KeepAlive = { + Crashed = true; + SuccessfulExit = false; + }; + ProcessType = "Background"; + }; + }; + + nmt.script = '' + serviceFile=LaunchAgents/org.nix-community.home.test-service.plist + assertFileExists $serviceFile + assertFileContent $serviceFile ${./expected-agent.plist} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/launchd/default.nix b/infra/libkookie/home-manager-stable/tests/modules/launchd/default.nix new file mode 100644 index 00000000000..09549ee7b31 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/launchd/default.nix @@ -0,0 +1 @@ +{ launchd-agents = ./agents.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/launchd/expected-agent.plist b/infra/libkookie/home-manager-stable/tests/modules/launchd/expected-agent.plist new file mode 100644 index 00000000000..c56ad4da44f --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/launchd/expected-agent.plist @@ -0,0 +1,23 @@ + + + + + KeepAlive + + Crashed + + SuccessfulExit + + + Label + org.nix-community.home.test-service + ProcessType + Background + ProgramArguments + + /some/command + --with-arguments + foo + + + \ No newline at end of file diff --git a/infra/libkookie/home-manager-stable/tests/modules/misc/debug/default.nix b/infra/libkookie/home-manager-stable/tests/modules/misc/debug/default.nix new file mode 100644 index 00000000000..19ff4e2b818 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/misc/debug/default.nix @@ -0,0 +1,26 @@ +{ + debug = { pkgs, config, lib, ... }: + lib.mkIf config.test.enableBig { + home.enableDebugInfo = true; + home.packages = with pkgs; [ curl gdb ]; + + nmt.script = '' + [ -L $TESTED/home-path/lib/debug/curl ] \ + || fail "Debug-symbols for pkgs.curl should exist in \`/home-path/lib/debug'!" + + #source $TESTED/home-path/etc/profile.d/hm-session-vars.sh + #[[ "$NIX_DEBUG_INFO_DIRS" =~ /lib/debug$ ]] \ + #|| fail "Invalid NIX_DEBUG_INFO_DIRS!" + assertFileExists home-path/etc/profile.d/hm-session-vars.sh + assertFileRegex home-path/etc/profile.d/hm-session-vars.sh \ + 'NIX_DEBUG_INFO_DIRS=.*/lib/debug' + + # We need to override NIX_DEBUG_INFO_DIRS here as $HOME evalutes to the home + # of the user who executes this testcase :/ + { echo quit | PATH="$TESTED/home-path/bin''${PATH:+:}$PATH" NIX_DEBUG_INFO_DIRS=$TESTED/home-path/lib/debug \ + gdb curl 2>&1 | \ + grep 'Reading symbols from ${builtins.storeDir}/'; \ + } || fail "Failed to read debug symbols from curl in gdb" + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/misc/fontconfig/default.nix b/infra/libkookie/home-manager-stable/tests/modules/misc/fontconfig/default.nix new file mode 100644 index 00000000000..bea306165c4 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/misc/fontconfig/default.nix @@ -0,0 +1,22 @@ +{ + fontconfig-no-font-package = ./no-font-package.nix; + fontconfig-single-font-package = ./single-font-package.nix; + # Disabled due to test failing with message + # + # Expected directory home-path/lib/fontconfig/cache to exist but it was not found. + # + # Verbose output from fc-cache: + # + # Font directories: + # /nix/store/da…g5-home-manager-path/lib/X11/fonts + # /nix/store/da…g5-home-manager-path/share/fonts + # /nix/store/da…g5-home-manager-path/share/fonts/truetype + # /nix/store/da…g5-home-manager-path/lib/X11/fonts: skipping, no such directory + # /nix/store/da…g5-home-manager-path/share/fonts: caching, new cache contents: 1 fonts, 1 dirs + # /nix/store/da…g5-home-manager-path/share/fonts/truetype: caching, new cache contents: 3 fonts, 0 dirs + # /nix/store/da…g5-home-manager-path/share/fonts/truetype: skipping, looped directory detected + # /nix/store/da…g5-home-manager-path/lib/fontconfig/cache: cleaning cache directory + # /nix/store/da…g5-home-manager-path/lib/fontconfig/cache: invalid cache file: 786068e7df13f7c2105017ef3d78e351-x86_64.cache-7 + # /nix/store/da…g5-home-manager-path/lib/fontconfig/cache: invalid cache file: 4766193978ddda4bd196f2b98c00fb00-x86_64.cache-7 + #fontconfig-multiple-font-packages = ./multiple-font-packages.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/misc/fontconfig/multiple-font-packages.nix b/infra/libkookie/home-manager-stable/tests/modules/misc/fontconfig/multiple-font-packages.nix new file mode 100644 index 00000000000..3845b4ba4b1 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/misc/fontconfig/multiple-font-packages.nix @@ -0,0 +1,15 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + home.packages = [ pkgs.comic-relief pkgs.unifont ]; + + fonts.fontconfig.enable = true; + + nmt.script = '' + assertDirectoryNotEmpty home-path/lib/fontconfig/cache + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/misc/fontconfig/no-font-package.nix b/infra/libkookie/home-manager-stable/tests/modules/misc/fontconfig/no-font-package.nix new file mode 100644 index 00000000000..c4c687a1320 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/misc/fontconfig/no-font-package.nix @@ -0,0 +1,17 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + home.packages = [ + # Look, no font! + ]; + + fonts.fontconfig.enable = true; + + nmt.script = '' + assertPathNotExists home-path/lib/fontconfig/cache + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/misc/fontconfig/single-font-package.nix b/infra/libkookie/home-manager-stable/tests/modules/misc/fontconfig/single-font-package.nix new file mode 100644 index 00000000000..b70bdf8a9a7 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/misc/fontconfig/single-font-package.nix @@ -0,0 +1,15 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + home.packages = [ pkgs.comic-relief ]; + + fonts.fontconfig.enable = true; + + nmt.script = '' + assertDirectoryNotEmpty home-path/lib/fontconfig/cache + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/misc/gtk/default.nix b/infra/libkookie/home-manager-stable/tests/modules/misc/gtk/default.nix new file mode 100644 index 00000000000..a812d4ad32d --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/misc/gtk/default.nix @@ -0,0 +1,6 @@ +{ + gtk2-basic-config = ./gtk2-basic-config.nix; + gtk2-config-file-location = ./gtk2-config-file-location.nix; + gtk3-basic-settings = ./gtk3-basic-settings.nix; +} + diff --git a/infra/libkookie/home-manager-stable/tests/modules/misc/gtk/gtk2-basic-config-expected.conf b/infra/libkookie/home-manager-stable/tests/modules/misc/gtk/gtk2-basic-config-expected.conf new file mode 100644 index 00000000000..4096a84775f --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/misc/gtk/gtk2-basic-config-expected.conf @@ -0,0 +1,2 @@ +gtk-theme-name = "Adwaita" +gtk-can-change-accels = 1 diff --git a/infra/libkookie/home-manager-stable/tests/modules/misc/gtk/gtk2-basic-config.nix b/infra/libkookie/home-manager-stable/tests/modules/misc/gtk/gtk2-basic-config.nix new file mode 100644 index 00000000000..5671ac93e68 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/misc/gtk/gtk2-basic-config.nix @@ -0,0 +1,25 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + gtk = { + enable = true; + theme.name = "Adwaita"; + gtk2.extraConfig = "gtk-can-change-accels = 1"; + }; + + test.stubs.dconf = { }; + + nmt.script = '' + assertFileExists home-files/.gtkrc-2.0 + + assertFileContent home-files/.gtkrc-2.0 \ + ${./gtk2-basic-config-expected.conf} + + assertFileRegex home-path/etc/profile.d/hm-session-vars.sh \ + 'GTK2_RC_FILES=.*/.gtkrc-2.0' + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/misc/gtk/gtk2-config-file-location.nix b/infra/libkookie/home-manager-stable/tests/modules/misc/gtk/gtk2-config-file-location.nix new file mode 100644 index 00000000000..a0899838421 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/misc/gtk/gtk2-config-file-location.nix @@ -0,0 +1,18 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + gtk.enable = true; + gtk.gtk2.configLocation = "${config.xdg.configHome}/gtk-2.0/gtkrc"; + + test.stubs.dconf = { }; + + nmt.script = '' + assertFileExists home-files/.config/gtk-2.0/gtkrc + assertFileRegex home-path/etc/profile.d/hm-session-vars.sh \ + 'GTK2_RC_FILES=.*/\.config/gtk-2.0/gtkrc' + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/misc/gtk/gtk3-basic-settings-expected.ini b/infra/libkookie/home-manager-stable/tests/modules/misc/gtk/gtk3-basic-settings-expected.ini new file mode 100644 index 00000000000..f1218b06932 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/misc/gtk/gtk3-basic-settings-expected.ini @@ -0,0 +1,3 @@ +[Settings] +gtk-cursor-blink=false +gtk-recent-files-limit=20 diff --git a/infra/libkookie/home-manager-stable/tests/modules/misc/gtk/gtk3-basic-settings.nix b/infra/libkookie/home-manager-stable/tests/modules/misc/gtk/gtk3-basic-settings.nix new file mode 100644 index 00000000000..058dd85b29e --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/misc/gtk/gtk3-basic-settings.nix @@ -0,0 +1,24 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + gtk = { + enable = true; + gtk3.extraConfig = { + gtk-cursor-blink = false; + gtk-recent-files-limit = 20; + }; + }; + + test.stubs.dconf = { }; + + nmt.script = '' + assertFileExists home-files/.config/gtk-3.0/settings.ini + + assertFileContent home-files/.config/gtk-3.0/settings.ini \ + ${./gtk3-basic-settings-expected.ini} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/misc/nix/default.nix b/infra/libkookie/home-manager-stable/tests/modules/misc/nix/default.nix new file mode 100644 index 00000000000..b0370c2e464 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/misc/nix/default.nix @@ -0,0 +1,5 @@ +{ + nix-empty-settings = ./empty-settings.nix; + nix-example-settings = ./example-settings.nix; + nix-example-registry = ./example-registry.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/misc/nix/empty-settings.nix b/infra/libkookie/home-manager-stable/tests/modules/misc/nix/empty-settings.nix new file mode 100644 index 00000000000..18f1ab4301d --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/misc/nix/empty-settings.nix @@ -0,0 +1,13 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + nix = { package = config.lib.test.mkStubPackage { }; }; + + nmt.script = '' + assertPathNotExists home-files/.config/nix + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/misc/nix/example-registry-expected.json b/infra/libkookie/home-manager-stable/tests/modules/misc/nix/example-registry-expected.json new file mode 100644 index 00000000000..cf5cee2292b --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/misc/nix/example-registry-expected.json @@ -0,0 +1,17 @@ +{ + "flakes": [ + { + "exact": true, + "from": { + "id": "nixpkgs", + "type": "indirect" + }, + "to": { + "owner": "my-org", + "repo": "my-nixpkgs", + "type": "github" + } + } + ], + "version": 2 +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/misc/nix/example-registry.nix b/infra/libkookie/home-manager-stable/tests/modules/misc/nix/example-registry.nix new file mode 100644 index 00000000000..1875b34d3c4 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/misc/nix/example-registry.nix @@ -0,0 +1,25 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + nix = { + registry = { + nixpkgs = { + to = { + type = "github"; + owner = "my-org"; + repo = "my-nixpkgs"; + }; + }; + }; + }; + + nmt.script = '' + assertFileContent \ + home-files/.config/nix/registry.json \ + ${./example-registry-expected.json} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/misc/nix/example-settings-expected.conf b/infra/libkookie/home-manager-stable/tests/modules/misc/nix/example-settings-expected.conf new file mode 100644 index 00000000000..2c2587fd697 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/misc/nix/example-settings-expected.conf @@ -0,0 +1,7 @@ +# WARNING: this file is generated from the nix.settings option in +# your Home Manager configuration at $XDG_CONFIG_HOME/nix/nix.conf. +# Do not edit it! +show-trace = true +system-features = big-parallel kvm recursive-nix +use-sandbox = true + diff --git a/infra/libkookie/home-manager-stable/tests/modules/misc/nix/example-settings.nix b/infra/libkookie/home-manager-stable/tests/modules/misc/nix/example-settings.nix new file mode 100644 index 00000000000..6cbcd9dfa43 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/misc/nix/example-settings.nix @@ -0,0 +1,33 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + nix = { + package = config.lib.test.mkStubPackage { + version = lib.getVersion pkgs.nixVersions.stable; + buildScript = '' + target=$out/bin/nix + mkdir -p "$(dirname "$target")" + + echo -n "true" > "$target" + + chmod +x "$target" + ''; + }; + + settings = { + use-sandbox = true; + show-trace = true; + system-features = [ "big-parallel" "kvm" "recursive-nix" ]; + }; + }; + + nmt.script = '' + assertFileContent \ + home-files/.config/nix/nix.conf \ + ${./example-settings-expected.conf} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/misc/numlock/default.nix b/infra/libkookie/home-manager-stable/tests/modules/misc/numlock/default.nix new file mode 100644 index 00000000000..47ca563fec0 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/misc/numlock/default.nix @@ -0,0 +1 @@ +{ numlock = ./numlock.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/misc/numlock/numlock.nix b/infra/libkookie/home-manager-stable/tests/modules/misc/numlock/numlock.nix new file mode 100644 index 00000000000..5616de1c573 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/misc/numlock/numlock.nix @@ -0,0 +1,16 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + xsession.numlock.enable = true; + + test.stubs.numlockx = { }; + + nmt.script = '' + serviceFile=home-files/.config/systemd/user/numlockx.service + assertFileExists $serviceFile + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/misc/pam/default.nix b/infra/libkookie/home-manager-stable/tests/modules/misc/pam/default.nix new file mode 100644 index 00000000000..a5707389562 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/misc/pam/default.nix @@ -0,0 +1,5 @@ +{ + pam-session-variables = ./session-variables.nix; + pam-yubico-with-ids = ./yubico-with-ids.nix; + pam-yubico-no-ids = ./yubico-with-ids.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/misc/pam/session-variables-expected.txt b/infra/libkookie/home-manager-stable/tests/modules/misc/pam/session-variables-expected.txt new file mode 100644 index 00000000000..b84a12b7675 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/misc/pam/session-variables-expected.txt @@ -0,0 +1,2 @@ +V1 OVERRIDE="v1" +V2 OVERRIDE="v2-v1" diff --git a/infra/libkookie/home-manager-stable/tests/modules/misc/pam/session-variables.nix b/infra/libkookie/home-manager-stable/tests/modules/misc/pam/session-variables.nix new file mode 100644 index 00000000000..4fbec4163b5 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/misc/pam/session-variables.nix @@ -0,0 +1,19 @@ +{ config, lib, ... }: + +with lib; + +{ + config = { + pam.sessionVariables = { + V1 = "v1"; + V2 = "v2-${config.pam.sessionVariables.V1}"; + }; + + nmt.script = '' + assertFileExists home-files/.pam_environment + assertFileContent \ + home-files/.pam_environment \ + ${./session-variables-expected.txt} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/misc/pam/yubico-no-ids.nix b/infra/libkookie/home-manager-stable/tests/modules/misc/pam/yubico-no-ids.nix new file mode 100644 index 00000000000..0236ccd593b --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/misc/pam/yubico-no-ids.nix @@ -0,0 +1,7 @@ +{ + config = { + nmt.script = '' + assertPathNotExists home-files/.yubico/authorized_yubikeys + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/misc/pam/yubico-with-ids.nix b/infra/libkookie/home-manager-stable/tests/modules/misc/pam/yubico-with-ids.nix new file mode 100644 index 00000000000..af722e95b66 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/misc/pam/yubico-with-ids.nix @@ -0,0 +1,15 @@ +{ + config = { + pam.yubico.authorizedYubiKeys.ids = [ "abcdefghijkl" "012345678912" ]; + + nmt.script = '' + assertFileExists home-files/.yubico/authorized_yubikeys + assertFileContent \ + home-files/.yubico/authorized_yubikeys \ + ${ + builtins.toFile "yubico-with-ids-expected.txt" + "hm-user:abcdefghijkl:012345678912" + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/misc/qt/default.nix b/infra/libkookie/home-manager-stable/tests/modules/misc/qt/default.nix new file mode 100644 index 00000000000..c676b784e55 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/misc/qt/default.nix @@ -0,0 +1,4 @@ +{ + qt-platform-theme-gtk = ./qt-platform-theme-gtk.nix; + qt-platform-theme-gnome = ./qt-platform-theme-gnome.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/misc/qt/qt-platform-theme-gnome.nix b/infra/libkookie/home-manager-stable/tests/modules/misc/qt/qt-platform-theme-gnome.nix new file mode 100644 index 00000000000..80baeae6f4e --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/misc/qt/qt-platform-theme-gnome.nix @@ -0,0 +1,23 @@ +{ config, lib, pkgs, ... }: + +{ + config = { + qt = { + enable = true; + platformTheme = "gnome"; + style = { + name = "adwaita"; + package = config.lib.test.mkStubPackage { }; + }; + }; + + test.stubs.qgnomeplatform = { }; + + nmt.script = '' + assertFileRegex home-path/etc/profile.d/hm-session-vars.sh \ + 'QT_QPA_PLATFORMTHEME="gnome"' + assertFileRegex home-path/etc/profile.d/hm-session-vars.sh \ + 'QT_STYLE_OVERRIDE="adwaita"' + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/misc/qt/qt-platform-theme-gtk.nix b/infra/libkookie/home-manager-stable/tests/modules/misc/qt/qt-platform-theme-gtk.nix new file mode 100644 index 00000000000..d332465283a --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/misc/qt/qt-platform-theme-gtk.nix @@ -0,0 +1,15 @@ +{ config, lib, pkgs, ... }: + +{ + config = { + qt = { + enable = true; + platformTheme = "gtk"; + }; + + nmt.script = '' + assertFileRegex home-path/etc/profile.d/hm-session-vars.sh \ + 'QT_QPA_PLATFORMTHEME="gtk2"' + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/misc/specialization/default.nix b/infra/libkookie/home-manager-stable/tests/modules/misc/specialization/default.nix new file mode 100644 index 00000000000..ddbc22c6ac8 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/misc/specialization/default.nix @@ -0,0 +1 @@ +{ specialization = ./specialization.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/misc/specialization/specialization.nix b/infra/libkookie/home-manager-stable/tests/modules/misc/specialization/specialization.nix new file mode 100644 index 00000000000..9d6149a0a5d --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/misc/specialization/specialization.nix @@ -0,0 +1,18 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + home.file.testfile.text = "not special"; + specialization.test.configuration = { + home.file.testfile.text = "very special"; + }; + + nmt.script = '' + assertFileExists home-files/testfile + assertFileContains home-files/testfile "not special" + + assertFileExists specialization/test/home-files/testfile + assertFileContains specialization/test/home-files/testfile "not special" + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/misc/xdg/default-locations.nix b/infra/libkookie/home-manager-stable/tests/modules/misc/xdg/default-locations.nix new file mode 100644 index 00000000000..1f6b36cc8b2 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/misc/xdg/default-locations.nix @@ -0,0 +1,35 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + # Test fallback behavior for stateVersion >= 20.09, which is pure. + xdg.enable = lib.mkForce false; + home.stateVersion = "20.09"; + + xdg.configFile.test.text = "config"; + xdg.dataFile.test.text = "data"; + home.file."${config.xdg.cacheHome}/test".text = "cache"; + home.file."${config.xdg.stateHome}/test".text = "state"; + + nmt.script = '' + assertFileExists home-files/.config/test + assertFileExists home-files/.local/share/test + assertFileExists home-files/.cache/test + assertFileExists home-files/.local/state/test + assertFileContent \ + home-files/.config/test \ + ${builtins.toFile "test" "config"} + assertFileContent \ + home-files/.local/share/test \ + ${builtins.toFile "test" "data"} + assertFileContent \ + home-files/.cache/test \ + ${builtins.toFile "test" "cache"} + assertFileContent \ + home-files/.local/state/test \ + ${builtins.toFile "test" "state"} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/misc/xdg/default.nix b/infra/libkookie/home-manager-stable/tests/modules/misc/xdg/default.nix new file mode 100644 index 00000000000..f3fef092912 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/misc/xdg/default.nix @@ -0,0 +1,7 @@ +{ + xdg-mime-apps-basics = ./mime-apps-basics.nix; + xdg-system-dirs = ./system-dirs.nix; + xdg-desktop-entries = ./desktop-entries.nix; + xdg-file-gen = ./file-gen.nix; + xdg-default-locations = ./default-locations.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/misc/xdg/desktop-entries.nix b/infra/libkookie/home-manager-stable/tests/modules/misc/xdg/desktop-entries.nix new file mode 100644 index 00000000000..541a7cc53f8 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/misc/xdg/desktop-entries.nix @@ -0,0 +1,86 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + xdg.desktopEntries = { + full = { # full definition + type = "Application"; + exec = "test --option"; + icon = "test"; + comment = "My Application"; + terminal = true; + name = "Test"; + genericName = "Web Browser"; + mimeType = [ "text/html" "text/xml" ]; + categories = [ "Network" "WebBrowser" ]; + startupNotify = false; + noDisplay = false; + prefersNonDefaultGPU = false; + settings = { + Keywords = "calc;math"; + DBusActivatable = "false"; + }; + actions = { + "New-Window" = { + name = "New Window"; + exec = "test --new-window"; + icon = "test"; + }; + "Default" = { exec = "test --default"; }; + }; + }; + min = { # minimal definition + exec = "test --option"; + name = "Test"; + }; + deprecated = { + exec = "test --option"; + name = "Test"; + # Deprecated options + fileValidation = true; + extraConfig = '' + [X-ExtraSection] + Exec=foo -o + ''; + }; + }; + + #testing that preexisting entries in the store are overridden + home.packages = [ + (pkgs.makeDesktopItem { + name = "full"; + desktopName = "We don't want this"; + exec = "no"; + }) + (pkgs.makeDesktopItem { + name = "min"; + desktopName = "We don't want this"; + exec = "no"; + }) + ]; + + test.asserts.assertions.expected = + let currentFile = toString ./desktop-entries.nix; + in [ + '' + The option definition `fileValidation' in `${currentFile}' no longer has any effect; please remove it. + Validation of the desktop file is always enabled. + '' + '' + The option definition `extraConfig' in `${currentFile}' no longer has any effect; please remove it. + The `extraConfig` option of `xdg.desktopEntries` has been removed following a change in Nixpkgs. + '' + ]; + + nmt.script = '' + assertFileExists home-path/share/applications/full.desktop + assertFileExists home-path/share/applications/min.desktop + assertFileContent home-path/share/applications/full.desktop \ + ${./desktop-full-expected.desktop} + assertFileContent home-path/share/applications/min.desktop \ + ${./desktop-min-expected.desktop} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/misc/xdg/desktop-full-expected.desktop b/infra/libkookie/home-manager-stable/tests/modules/misc/xdg/desktop-full-expected.desktop new file mode 100644 index 00000000000..b40f96c21f4 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/misc/xdg/desktop-full-expected.desktop @@ -0,0 +1,26 @@ +[Desktop Entry] +Actions=Default;New-Window +Categories=Network;WebBrowser +Comment=My Application +DBusActivatable=false +Exec=test --option +GenericName=Web Browser +Icon=test +Keywords=calc;math +MimeType=text/html;text/xml +Name=Test +NoDisplay=false +PrefersNonDefaultGPU=false +StartupNotify=false +Terminal=true +Type=Application +Version=1.4 + +[Desktop Action Default] +Exec=test --default +Name=Default + +[Desktop Action New-Window] +Exec=test --new-window +Icon=test +Name=New Window diff --git a/infra/libkookie/home-manager-stable/tests/modules/misc/xdg/desktop-min-expected.desktop b/infra/libkookie/home-manager-stable/tests/modules/misc/xdg/desktop-min-expected.desktop new file mode 100644 index 00000000000..1b36b57c679 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/misc/xdg/desktop-min-expected.desktop @@ -0,0 +1,6 @@ +[Desktop Entry] +Exec=test --option +Name=Test +Terminal=false +Type=Application +Version=1.4 diff --git a/infra/libkookie/home-manager-stable/tests/modules/misc/xdg/file-gen.nix b/infra/libkookie/home-manager-stable/tests/modules/misc/xdg/file-gen.nix new file mode 100644 index 00000000000..47a3102c275 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/misc/xdg/file-gen.nix @@ -0,0 +1,36 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + xdg.configHome = /. + "${config.home.homeDirectory}/.dummy-config"; + xdg.dataHome = /. + "${config.home.homeDirectory}/.dummy-data"; + xdg.cacheHome = /. + "${config.home.homeDirectory}/.dummy-cache"; + xdg.stateHome = /. + "${config.home.homeDirectory}/.dummy-state"; + + xdg.configFile.test.text = "config"; + xdg.dataFile.test.text = "data"; + home.file."${config.xdg.cacheHome}/test".text = "cache"; + home.file."${config.xdg.stateHome}/test".text = "state"; + + nmt.script = '' + assertFileExists home-files/.dummy-config/test + assertFileExists home-files/.dummy-cache/test + assertFileExists home-files/.dummy-data/test + assertFileExists home-files/.dummy-state/test + assertFileContent \ + home-files/.dummy-config/test \ + ${builtins.toFile "test" "config"} + assertFileContent \ + home-files/.dummy-data/test \ + ${builtins.toFile "test" "data"} + assertFileContent \ + home-files/.dummy-cache/test \ + ${builtins.toFile "test" "cache"} + assertFileContent \ + home-files/.dummy-state/test \ + ${builtins.toFile "test" "state"} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/misc/xdg/mime-apps-basics-expected.ini b/infra/libkookie/home-manager-stable/tests/modules/misc/xdg/mime-apps-basics-expected.ini new file mode 100644 index 00000000000..c27181eb58f --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/misc/xdg/mime-apps-basics-expected.ini @@ -0,0 +1,9 @@ +[Added Associations] +mimetype1=foo1.desktop;foo2.desktop;foo3.desktop +mimetype2=foo4.desktop + +[Default Applications] +mimetype1=default1.desktop;default2.desktop + +[Removed Associations] +mimetype1=foo5.desktop diff --git a/infra/libkookie/home-manager-stable/tests/modules/misc/xdg/mime-apps-basics.nix b/infra/libkookie/home-manager-stable/tests/modules/misc/xdg/mime-apps-basics.nix new file mode 100644 index 00000000000..e181e8206f6 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/misc/xdg/mime-apps-basics.nix @@ -0,0 +1,28 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + xdg.mimeApps = { + enable = true; + associations = { + added = { + "mimetype1" = [ "foo1.desktop" "foo2.desktop" "foo3.desktop" ]; + "mimetype2" = "foo4.desktop"; + }; + removed = { mimetype1 = "foo5.desktop"; }; + }; + defaultApplications = { + "mimetype1" = [ "default1.desktop" "default2.desktop" ]; + }; + }; + + nmt.script = '' + assertFileExists home-files/.config/mimeapps.list + assertFileContent \ + home-files/.config/mimeapps.list \ + ${./mime-apps-basics-expected.ini} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/misc/xdg/system-dirs.nix b/infra/libkookie/home-manager-stable/tests/modules/misc/xdg/system-dirs.nix new file mode 100644 index 00000000000..fa34ae0b5f5 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/misc/xdg/system-dirs.nix @@ -0,0 +1,31 @@ +{ config, lib, pkgs, ... }: + +{ + config = { + xdg.systemDirs.config = [ "/etc/xdg" "/foo/bar" ]; + xdg.systemDirs.data = [ "/usr/local/share" "/usr/share" "/baz/quux" ]; + + nmt.script = '' + envFile=home-files/.config/environment.d/10-home-manager.conf + assertFileExists $envFile + assertFileContent $envFile ${ + pkgs.writeText "expected" '' + LOCALE_ARCHIVE_2_27=${pkgs.glibcLocales}/lib/locale/locale-archive + XDG_CACHE_HOME=/home/hm-user/.cache + XDG_CONFIG_DIRS=/etc/xdg:/foo/bar''${XDG_CONFIG_DIRS:+:$XDG_CONFIG_DIRS} + XDG_CONFIG_HOME=/home/hm-user/.config + XDG_DATA_DIRS=/usr/local/share:/usr/share:/baz/quux''${XDG_DATA_DIRS:+:$XDG_DATA_DIRS} + XDG_DATA_HOME=/home/hm-user/.local/share + XDG_STATE_HOME=/home/hm-user/.local/state + '' + } + + sessionVarsFile=home-path/etc/profile.d/hm-session-vars.sh + assertFileExists $sessionVarsFile + assertFileContains $sessionVarsFile \ + 'export XDG_CONFIG_DIRS="/etc/xdg:/foo/bar''${XDG_CONFIG_DIRS:+:$XDG_CONFIG_DIRS}"' + assertFileContains $sessionVarsFile \ + 'export XDG_DATA_DIRS="/usr/local/share:/usr/share:/baz/quux''${XDG_DATA_DIRS:+:$XDG_DATA_DIRS}"' + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/misc/xsession/basic-setxkbmap-expected.service b/infra/libkookie/home-manager-stable/tests/modules/misc/xsession/basic-setxkbmap-expected.service new file mode 100644 index 00000000000..980721171fb --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/misc/xsession/basic-setxkbmap-expected.service @@ -0,0 +1,12 @@ +[Install] +WantedBy=graphical-session.target + +[Service] +ExecStart=@setxkbmap@/bin/setxkbmap -layout 'us' -variant '' -option '' +RemainAfterExit=true +Type=oneshot + +[Unit] +After=graphical-session-pre.target +Description=Set up keyboard in X +PartOf=graphical-session.target diff --git a/infra/libkookie/home-manager-stable/tests/modules/misc/xsession/basic-xprofile-expected.txt b/infra/libkookie/home-manager-stable/tests/modules/misc/xsession/basic-xprofile-expected.txt new file mode 100644 index 00000000000..282f8f5c5de --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/misc/xsession/basic-xprofile-expected.txt @@ -0,0 +1,16 @@ +. "/home/hm-user/.nix-profile/etc/profile.d/hm-session-vars.sh" + +if [ -e "$HOME/.profile" ]; then + . "$HOME/.profile" +fi + +# If there are any running services from a previous session. +# Need to run this in xprofile because the NixOS xsession +# script starts up graphical-session.target. +systemctl --user stop graphical-session.target graphical-session-pre.target + +systemctl --user import-environment DBUS_SESSION_BUS_ADDRESS DISPLAY SSH_AUTH_SOCK XAUTHORITY XDG_DATA_DIRS XDG_RUNTIME_DIR XDG_SESSION_ID EXTRA_IMPORTED_VARIABLE + +profile extra commands + +export HM_XPROFILE_SOURCED=1 diff --git a/infra/libkookie/home-manager-stable/tests/modules/misc/xsession/basic-xsession-expected.txt b/infra/libkookie/home-manager-stable/tests/modules/misc/xsession/basic-xsession-expected.txt new file mode 100644 index 00000000000..423e7779c14 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/misc/xsession/basic-xsession-expected.txt @@ -0,0 +1,18 @@ +if [ -z "$HM_XPROFILE_SOURCED" ]; then + . "/home/hm-user/.xprofile" +fi +unset HM_XPROFILE_SOURCED + +systemctl --user start hm-graphical-session.target + +init extra commands + +window manager command + +systemctl --user stop graphical-session.target +systemctl --user stop graphical-session-pre.target + +# Wait until the units actually stop. +while [ -n "$(systemctl --user --no-legend --state=deactivating list-units)" ]; do + sleep 0.5 +done diff --git a/infra/libkookie/home-manager-stable/tests/modules/misc/xsession/basic.nix b/infra/libkookie/home-manager-stable/tests/modules/misc/xsession/basic.nix new file mode 100644 index 00000000000..d6756291cfe --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/misc/xsession/basic.nix @@ -0,0 +1,40 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + xsession = { + enable = true; + windowManager.command = "window manager command"; + importedVariables = [ "EXTRA_IMPORTED_VARIABLE" ]; + initExtra = "init extra commands"; + profileExtra = "profile extra commands"; + }; + + nixpkgs.overlays = [ + (self: super: { + xorg = super.xorg // { + setxkbmap = super.xorg.setxkbmap // { outPath = "@setxkbmap@"; }; + }; + }) + ]; + + nmt.script = '' + assertFileExists home-files/.xprofile + assertFileContent \ + home-files/.xprofile \ + ${./basic-xprofile-expected.txt} + + assertFileExists home-files/.xsession + assertFileContent \ + home-files/.xsession \ + ${./basic-xsession-expected.txt} + + assertFileExists home-files/.config/systemd/user/setxkbmap.service + assertFileContent \ + home-files/.config/systemd/user/setxkbmap.service \ + ${./basic-setxkbmap-expected.service} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/misc/xsession/default.nix b/infra/libkookie/home-manager-stable/tests/modules/misc/xsession/default.nix new file mode 100644 index 00000000000..2ddbf47efac --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/misc/xsession/default.nix @@ -0,0 +1,4 @@ +{ + xsession-basic = ./basic.nix; + xsession-keyboard-without-layout = ./keyboard-without-layout.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/misc/xsession/keyboard-without-layout-expected.service b/infra/libkookie/home-manager-stable/tests/modules/misc/xsession/keyboard-without-layout-expected.service new file mode 100644 index 00000000000..4dbc100452c --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/misc/xsession/keyboard-without-layout-expected.service @@ -0,0 +1,12 @@ +[Install] +WantedBy=graphical-session.target + +[Service] +ExecStart=@setxkbmap@/bin/setxkbmap -option '' -option 'ctrl:nocaps' -option 'altwin:no_win' +RemainAfterExit=true +Type=oneshot + +[Unit] +After=graphical-session-pre.target +Description=Set up keyboard in X +PartOf=graphical-session.target diff --git a/infra/libkookie/home-manager-stable/tests/modules/misc/xsession/keyboard-without-layout.nix b/infra/libkookie/home-manager-stable/tests/modules/misc/xsession/keyboard-without-layout.nix new file mode 100644 index 00000000000..90038cfd034 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/misc/xsession/keyboard-without-layout.nix @@ -0,0 +1,34 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + home.stateVersion = "19.09"; + + home.keyboard = { options = [ "ctrl:nocaps" "altwin:no_win" ]; }; + + xsession = { + enable = true; + windowManager.command = "window manager command"; + importedVariables = [ "EXTRA_IMPORTED_VARIABLE" ]; + initExtra = "init extra commands"; + profileExtra = "profile extra commands"; + }; + + nixpkgs.overlays = [ + (self: super: { + xorg = super.xorg // { + setxkbmap = super.xorg.setxkbmap // { outPath = "@setxkbmap@"; }; + }; + }) + ]; + + nmt.script = '' + assertFileExists home-files/.config/systemd/user/setxkbmap.service + assertFileContent \ + home-files/.config/systemd/user/setxkbmap.service \ + ${./keyboard-without-layout-expected.service} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/abook/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/abook/default.nix new file mode 100644 index 00000000000..12ad238ed25 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/abook/default.nix @@ -0,0 +1,4 @@ +{ + abook-no-settings = ./no-settings.nix; + abook-with-settings = ./with-settings.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/abook/no-settings.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/abook/no-settings.nix new file mode 100644 index 00000000000..f8b096fb18d --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/abook/no-settings.nix @@ -0,0 +1,15 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.abook.enable = true; + + test.stubs.abook = { }; + + nmt.script = '' + assertPathNotExists home-files/.config/abook/abookrc + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/abook/with-settings.cfg b/infra/libkookie/home-manager-stable/tests/modules/programs/abook/with-settings.cfg new file mode 100644 index 00000000000..d73445f4d83 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/abook/with-settings.cfg @@ -0,0 +1,21 @@ +# Generated by Home Manager. +# See http://abook.sourceforge.net/ + +# Defining a new custom field +# ----------------------------- + +field pager = Pager +field address_lines = Address, list +field birthday = Birthday, date + +# Defining a view/tab +# --------------------- + +view CONTACT = name, email +view ADDRESS = address_lines, city, state, zip, country +view PHONE = phone, workphone, pager, mobile, fax +view OTHER = url, birthday + +# Automatically save database on exit +set autosave=true + diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/abook/with-settings.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/abook/with-settings.nix new file mode 100644 index 00000000000..e89ad7dad63 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/abook/with-settings.nix @@ -0,0 +1,38 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.abook = { + enable = true; + + extraConfig = '' + # Defining a new custom field + # ----------------------------- + + field pager = Pager + field address_lines = Address, list + field birthday = Birthday, date + + # Defining a view/tab + # --------------------- + + view CONTACT = name, email + view ADDRESS = address_lines, city, state, zip, country + view PHONE = phone, workphone, pager, mobile, fax + view OTHER = url, birthday + + # Automatically save database on exit + set autosave=true + ''; + }; + + test.stubs.abook = { }; + + nmt.script = '' + assertFileExists home-files/.config/abook/abookrc + assertFileContent home-files/.config/abook/abookrc ${./with-settings.cfg} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/alacritty/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/alacritty/default.nix new file mode 100644 index 00000000000..3ccd9a91f33 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/alacritty/default.nix @@ -0,0 +1,5 @@ +{ + alacritty-example-settings = ./example-settings.nix; + alacritty-empty-settings = ./empty-settings.nix; + alacritty-merging-settings = ./settings-merging.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/alacritty/empty-settings.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/alacritty/empty-settings.nix new file mode 100644 index 00000000000..ecc6df35a7b --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/alacritty/empty-settings.nix @@ -0,0 +1,15 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.alacritty.enable = true; + + test.stubs.alacritty = { }; + + nmt.script = '' + assertPathNotExists home-files/.config/alacritty + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/alacritty/example-settings-expected.yml b/infra/libkookie/home-manager-stable/tests/modules/programs/alacritty/example-settings-expected.yml new file mode 100644 index 00000000000..061624192c3 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/alacritty/example-settings-expected.yml @@ -0,0 +1 @@ +{"key_bindings":[{"chars":"\x0c","key":"K","mods":"Control"}],"window":{"dimensions":{"columns":200,"lines":3}}} \ No newline at end of file diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/alacritty/example-settings.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/alacritty/example-settings.nix new file mode 100644 index 00000000000..61b8b4b4e5b --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/alacritty/example-settings.nix @@ -0,0 +1,31 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.alacritty = { + enable = true; + package = config.lib.test.mkStubPackage { }; + + settings = { + window.dimensions = { + lines = 3; + columns = 200; + }; + + key_bindings = [{ + key = "K"; + mods = "Control"; + chars = "\\x0c"; + }]; + }; + }; + + nmt.script = '' + assertFileContent \ + home-files/.config/alacritty/alacritty.yml \ + ${./example-settings-expected.yml} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/alacritty/settings-merging-expected.yml b/infra/libkookie/home-manager-stable/tests/modules/programs/alacritty/settings-merging-expected.yml new file mode 100644 index 00000000000..49d92a614e8 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/alacritty/settings-merging-expected.yml @@ -0,0 +1 @@ +{"font":{"bold":{"family":"SFMono"},"normal":{"family":"SFMono"}},"key_bindings":[{"chars":"\x0c","key":"K","mods":"Control"}],"window":{"dimensions":{"columns":200,"lines":3}}} \ No newline at end of file diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/alacritty/settings-merging.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/alacritty/settings-merging.nix new file mode 100644 index 00000000000..c7962fb52f5 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/alacritty/settings-merging.nix @@ -0,0 +1,39 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.alacritty = { + enable = true; + package = config.lib.test.mkStubPackage { }; + + settings = { + window.dimensions = { + lines = 3; + columns = 200; + }; + + key_bindings = [{ + key = "K"; + mods = "Control"; + chars = "\\x0c"; + }]; + + font = let + defaultFont = + lib.mkMerge [ (lib.mkIf true "SFMono") (lib.mkIf false "Iosevka") ]; + in { + normal.family = defaultFont; + bold.family = defaultFont; + }; + }; + }; + + nmt.script = '' + assertFileContent \ + home-files/.config/alacritty/alacritty.yml \ + ${./settings-merging-expected.yml} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/alot/alot-expected.conf b/infra/libkookie/home-manager-stable/tests/modules/programs/alot/alot-expected.conf new file mode 100644 index 00000000000..6d3ace4a372 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/alot/alot-expected.conf @@ -0,0 +1,37 @@ +# Generated by Home Manager. +# See http://alot.readthedocs.io/en/latest/configuration/config_options.html + +auto_remove_unread = True +handle_mouse = True +initial_command = search tag:inbox AND NOT tag:killed +prefer_plaintext = True + + +[tags] +[bindings] + + +[[bufferlist]] + +[[search]] + +[[envelope]] + +[[taglist]] + +[[thread]] + + +[accounts] + +[[hm@example.com]] +address=hm@example.com +draft_box=maildir:///home/hm-user/Mail/hm@example.com/Drafts +realname=H. M. Test +sendmail_command= +sent_box=maildir:///home/hm-user/Mail/hm@example.com/Sent +auto_remove_unread = True +ask_subject = False +handle_mouse = True + +[[[abook]]] diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/alot/alot.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/alot/alot.nix new file mode 100644 index 00000000000..6316fbd76e6 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/alot/alot.nix @@ -0,0 +1,34 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + imports = [ ../../accounts/email-test-accounts.nix ]; + + config = { + accounts.email.accounts = { + "hm@example.com" = { + notmuch.enable = true; + alot = { + contactCompletion = { }; + extraConfig = '' + auto_remove_unread = True + ask_subject = False + handle_mouse = True + ''; + }; + imap.port = 993; + }; + }; + + programs.alot = { enable = true; }; + + test.stubs.alot = { }; + + nmt.script = '' + assertFileExists home-files/.config/alot/config + assertFileContent home-files/.config/alot/config ${./alot-expected.conf} + ''; + }; +} + diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/alot/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/alot/default.nix new file mode 100644 index 00000000000..9c912fdb43a --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/alot/default.nix @@ -0,0 +1 @@ +{ alot = ./alot.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/aria2/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/aria2/default.nix new file mode 100644 index 00000000000..2964841d098 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/aria2/default.nix @@ -0,0 +1 @@ +{ aria2-settings = ./settings.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/aria2/settings.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/aria2/settings.nix new file mode 100644 index 00000000000..346de967945 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/aria2/settings.nix @@ -0,0 +1,40 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.aria2 = { + enable = true; + + settings = { + listen-port = 60000; + dht-listen-port = 60000; + seed-ratio = 1.0; + max-upload-limit = "50K"; + ftp-pasv = true; + }; + + extraConfig = '' + # Extra aria2 configuration. + ''; + }; + + test.stubs.aria2 = { }; + + nmt.script = '' + assertFileContent \ + home-files/.config/aria2/aria2.conf \ + ${ + pkgs.writeText "aria2-expected-config.conf" '' + dht-listen-port=60000 + ftp-pasv=true + listen-port=60000 + max-upload-limit=50K + seed-ratio=1.000000 + # Extra aria2 configuration. + '' + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/atuin/bash.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/atuin/bash.nix new file mode 100644 index 00000000000..f8c31409986 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/atuin/bash.nix @@ -0,0 +1,20 @@ +{ ... }: + +{ + programs = { + atuin.enable = true; + bash.enable = true; + }; + + test.stubs = { + atuin = { }; + bash-preexec = { }; + }; + + nmt.script = '' + assertFileExists home-files/.bashrc + assertFileContains \ + home-files/.bashrc \ + 'eval "$(@atuin@/bin/atuin init bash)"' + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/atuin/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/atuin/default.nix new file mode 100644 index 00000000000..ee22818a353 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/atuin/default.nix @@ -0,0 +1,8 @@ +{ + atuin-bash = ./bash.nix; + atuin-empty-settings = ./empty-settings.nix; + atuin-example-settings = ./example-settings.nix; + atuin-fish = ./fish.nix; + atuin-no-shell = ./no-shell.nix; + atuin-zsh = ./zsh.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/atuin/empty-settings.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/atuin/empty-settings.nix new file mode 100644 index 00000000000..58f126965dd --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/atuin/empty-settings.nix @@ -0,0 +1,14 @@ +{ ... }: + +{ + programs.atuin.enable = true; + + test.stubs = { + atuin = { }; + bash-preexec = { }; + }; + + nmt.script = '' + assertPathNotExists home-files/.config/atuin/config.toml + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/atuin/example-settings-expected.toml b/infra/libkookie/home-manager-stable/tests/modules/programs/atuin/example-settings-expected.toml new file mode 100644 index 00000000000..c1e92f14638 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/atuin/example-settings-expected.toml @@ -0,0 +1,4 @@ +db_path = "~/.atuin-history.db" +dialect = "us" +auto_sync = true +search-mode = "fulltext" \ No newline at end of file diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/atuin/example-settings.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/atuin/example-settings.nix new file mode 100644 index 00000000000..f2d3a887691 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/atuin/example-settings.nix @@ -0,0 +1,32 @@ +{ ... }: + +{ + programs.atuin = { + enable = true; + + settings = { + db_path = "~/.atuin-history.db"; + dialect = "us"; + auto_sync = true; + search-mode = "fulltext"; + }; + }; + + test.stubs = { + atuin = { }; + bash-preexec = { }; + }; + + nmt.script = '' + assertFileContent \ + home-files/.config/atuin/config.toml \ + ${ + builtins.toFile "example-settings-expected.toml" '' + auto_sync = true + db_path = "~/.atuin-history.db" + dialect = "us" + search-mode = "fulltext" + '' + } + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/atuin/fish.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/atuin/fish.nix new file mode 100644 index 00000000000..77232dbae49 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/atuin/fish.nix @@ -0,0 +1,25 @@ +{ lib, ... }: + +{ + programs = { + atuin.enable = true; + fish.enable = true; + }; + + # Needed to avoid error with dummy fish package. + xdg.dataFile."fish/home-manager_generated_completions".source = + lib.mkForce (builtins.toFile "empty" ""); + + test.stubs = { + atuin = { }; + bash-preexec = { }; + fish = { }; + }; + + nmt.script = '' + assertFileExists home-files/.config/fish/config.fish + assertFileContains \ + home-files/.config/fish/config.fish \ + 'atuin init fish | source' + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/atuin/no-shell.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/atuin/no-shell.nix new file mode 100644 index 00000000000..b636f7c0dff --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/atuin/no-shell.nix @@ -0,0 +1,31 @@ +{ lib, ... }: + +{ + programs = { + atuin = { + enable = true; + enableBashIntegration = false; + enableZshIntegration = false; + enableFishIntegration = false; + }; + bash.enable = true; + zsh.enable = true; + fish.enable = true; + }; + + # Needed to avoid error with dummy fish package. + xdg.dataFile."fish/home-manager_generated_completions".source = + lib.mkForce (builtins.toFile "empty" ""); + + test.stubs = { + atuin = { }; + bash-preexec = { }; + fish = { }; + }; + + nmt.script = '' + assertFileNotRegex home-files/.zshrc 'atuin init zsh' + assertFileNotRegex home-files/.bashrc 'atuin init bash' + assertFileNotRegex home-files/.config/fish/config.fish 'atuin init fish' + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/atuin/zsh.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/atuin/zsh.nix new file mode 100644 index 00000000000..45f0254ca9b --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/atuin/zsh.nix @@ -0,0 +1,20 @@ +{ ... }: + +{ + programs = { + atuin.enable = true; + zsh.enable = true; + }; + + test.stubs = { + atuin = { }; + bash-preexec = { }; + }; + + nmt.script = '' + assertFileExists home-files/.zshrc + assertFileContains \ + home-files/.zshrc \ + 'eval "$(@atuin@/bin/atuin init zsh)"' + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/autojump/default-settings.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/autojump/default-settings.nix new file mode 100644 index 00000000000..2cca7de88cd --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/autojump/default-settings.nix @@ -0,0 +1,17 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.autojump.enable = true; + + test.stubs.autojump = { + buildScript = "mkdir -p $out/bin; touch $out/bin/autojump"; + }; + + nmt.script = '' + assertFileExists home-path/bin/autojump + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/autojump/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/autojump/default.nix new file mode 100644 index 00000000000..eaaaba3b4b2 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/autojump/default.nix @@ -0,0 +1 @@ +{ autojump = ./default-settings.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/autorandr/basic-configuration.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/autorandr/basic-configuration.nix new file mode 100644 index 00000000000..e650f6005a5 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/autorandr/basic-configuration.nix @@ -0,0 +1,59 @@ +{ config, pkgs, ... }: + +{ + config = { + programs.autorandr = { + enable = true; + profiles = { + default = { + fingerprint = { + DP1 = "XXX"; + DP2 = "YYY"; + }; + config = { + DP1.enable = false; + DP2 = { + crtc = 0; + primary = true; + position = "0x0"; + mode = "1920x1080"; + filter = "nearest"; + transform = [ + [ 0.6 0.0 0.0 ] # a b c + [ 0.0 0.6 0.0 ] # d e f + [ 0.0 0.0 1.0 ] # g h i + ]; + }; + }; + }; + }; + }; + + test.stubs.autorandr = { }; + + nmt.script = '' + config=home-files/.config/autorandr/default/config + setup=home-files/.config/autorandr/default/setup + + assertFileExists $setup + assertFileRegex $setup 'DP1 XXX' + assertFileRegex $setup 'DP2 YYY' + + assertFileExists $config + assertFileContent $config \ + ${ + pkgs.writeText "basic-configuration.conf" '' + output DP1 + off + + output DP2 + pos 0x0 + crtc 0 + primary + mode 1920x1080 + filter nearest + transform 0.600000,0.000000,0.000000,0.000000,0.600000,0.000000,0.000000,0.000000,1.000000'' + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/autorandr/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/autorandr/default.nix new file mode 100644 index 00000000000..bb7b279ee27 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/autorandr/default.nix @@ -0,0 +1,4 @@ +{ + autorandr-basic-configuration = ./basic-configuration.nix; + autorandr-scale = ./scale.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/autorandr/scale.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/autorandr/scale.nix new file mode 100644 index 00000000000..095778a43ec --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/autorandr/scale.nix @@ -0,0 +1,34 @@ +{ config, pkgs, ... }: + +{ + config = { + programs.autorandr = { + enable = true; + profiles = { + default = { + fingerprint.DP1 = "XXX"; + config.DP1 = { + scale = { + x = 2; + y = 4; + }; + }; + }; + }; + }; + + test.stubs.autorandr = { }; + + nmt.script = '' + config=home-files/.config/autorandr/default/config + + assertFileExists $config + assertFileContent $config \ + ${ + pkgs.writeText "scale-expected.conf" '' + output DP1 + scale 2x4'' + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/bash/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/bash/default.nix new file mode 100644 index 00000000000..e9f431cd2b9 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/bash/default.nix @@ -0,0 +1,4 @@ +{ + bash-logout = ./logout.nix; + bash-session-variables = ./session-variables.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/bash/logout.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/bash/logout.nix new file mode 100644 index 00000000000..a342928582e --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/bash/logout.nix @@ -0,0 +1,26 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.bash = { + enable = true; + + logoutExtra = '' + clear-console + ''; + }; + + nmt.script = '' + assertFileExists home-files/.bash_logout + assertFileContent \ + home-files/.bash_logout \ + ${ + builtins.toFile "logout-expected" '' + clear-console + '' + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/bash/session-variables.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/bash/session-variables.nix new file mode 100644 index 00000000000..09c69814d1a --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/bash/session-variables.nix @@ -0,0 +1,32 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.bash = { + enable = true; + + sessionVariables = { + V1 = "v1"; + V2 = "v2-${config.programs.bash.sessionVariables.V1}"; + }; + }; + + nmt.script = '' + assertFileExists home-files/.profile + assertFileContent \ + home-files/.profile \ + ${ + builtins.toFile "session-variables-expected" '' + . "/home/hm-user/.nix-profile/etc/profile.d/hm-session-vars.sh" + + export V1="v1" + export V2="v2-v1" + + + '' + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/bat/bat.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/bat/bat.nix new file mode 100644 index 00000000000..e9861292237 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/bat/bat.nix @@ -0,0 +1,42 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.bat = { + enable = true; + + config = { + theme = "TwoDark"; + pager = "less -FR"; + map-syntax = [ "*.jenkinsfile:Groovy" "*.props:Java Properties" ]; + }; + + themes.testtheme = '' + This is a test theme. + ''; + }; + + test.stubs.bat = { }; + + nmt.script = '' + assertFileExists home-files/.config/bat/config + assertFileContent home-files/.config/bat/config ${ + pkgs.writeText "bat.expected" '' + --map-syntax='*.jenkinsfile:Groovy' + --map-syntax='*.props:Java Properties' + --pager='less -FR' + --theme='TwoDark' + '' + } + + assertFileExists home-files/.config/bat/themes/testtheme.tmTheme + assertFileContent home-files/.config/bat/themes/testtheme.tmTheme ${ + pkgs.writeText "bat.expected" '' + This is a test theme. + '' + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/bat/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/bat/default.nix new file mode 100644 index 00000000000..001d4bca6e1 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/bat/default.nix @@ -0,0 +1 @@ +{ bat = ./bat.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/bottom/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/bottom/default.nix new file mode 100644 index 00000000000..ed6e241fc8d --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/bottom/default.nix @@ -0,0 +1,4 @@ +{ + bottom-empty-settings = ./empty-settings.nix; + bottom-example-settings = ./example-settings.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/bottom/empty-settings.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/bottom/empty-settings.nix new file mode 100644 index 00000000000..15c03c11a28 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/bottom/empty-settings.nix @@ -0,0 +1,21 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.bottom = { + enable = true; + package = config.lib.test.mkStubPackage { }; + }; + + nmt.script = let + configDir = if pkgs.stdenv.isDarwin then + "home-files/Library/Application Support" + else + "home-files/.config"; + in '' + assertPathNotExists ${configDir}/bottom + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/bottom/example-settings-expected.toml b/infra/libkookie/home-manager-stable/tests/modules/programs/bottom/example-settings-expected.toml new file mode 100644 index 00000000000..019a1825313 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/bottom/example-settings-expected.toml @@ -0,0 +1,6 @@ +[colors] +low_battery_color = "red" + +[flags] +avg_cpu = true +temperature_type = "c" diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/bottom/example-settings.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/bottom/example-settings.nix new file mode 100644 index 00000000000..1777b5264b9 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/bottom/example-settings.nix @@ -0,0 +1,32 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.bottom = { + enable = true; + package = config.lib.test.mkStubPackage { }; + + settings = { + flags = { + avg_cpu = true; + temperature_type = "c"; + }; + + colors = { low_battery_color = "red"; }; + }; + }; + + nmt.script = let + configDir = if pkgs.stdenv.isDarwin then + "home-files/Library/Application Support" + else + "home-files/.config"; + in '' + assertFileContent \ + "${configDir}/bottom/bottom.toml" \ + ${./example-settings-expected.toml} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/broot/broot.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/broot/broot.nix new file mode 100644 index 00000000000..a2dddca38d8 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/broot/broot.nix @@ -0,0 +1,42 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.broot = { + enable = true; + modal = true; + }; + + test.stubs.broot = { }; + + nmt.script = '' + assertFileExists home-files/.config/broot/conf.toml + assertFileContent home-files/.config/broot/conf.toml ${ + pkgs.writeText "broot.expected" '' + modal = true + + [[verbs]] + execution = ":parent" + invocation = "p" + + [[verbs]] + execution = "$EDITOR {file}" + invocation = "edit" + shortcut = "e" + + [[verbs]] + execution = "$EDITOR {directory}/{subpath}" + invocation = "create {subpath}" + + [[verbs]] + execution = "less {file}" + invocation = "view" + + [skin] + '' + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/broot/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/broot/default.nix new file mode 100644 index 00000000000..4f991f68bf7 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/broot/default.nix @@ -0,0 +1 @@ +{ broot = ./broot.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/browserpass/browserpass.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/browserpass/browserpass.nix new file mode 100644 index 00000000000..2e1ca65e894 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/browserpass/browserpass.nix @@ -0,0 +1,32 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.browserpass = { + enable = true; + browsers = [ "brave" "chrome" "chromium" "firefox" "vivaldi" ]; + }; + + nmt.script = if pkgs.stdenv.hostPlatform.isDarwin then '' + for dir in "BraveSoftware/Brave-Browser" "Google/Chrome" "Chromium" "Mozilla" "Vivaldi"; do + assertFileExists "home-files/Library/Application Support/$dir/NativeMessagingHosts/com.github.browserpass.native.json" + done + + for dir in "Google/Chrome" "Chromium" "Vivaldi"; do + assertFileExists "home-files/Library/Application Support/$dir/policies/managed/com.github.browserpass.native.json" + done + '' else '' + for dir in "BraveSoftware/Brave-Browser" "google-chrome" "chromium" "vivaldi"; do + assertFileExists "home-files/.config/$dir/NativeMessagingHosts/com.github.browserpass.native.json" + done + + for dir in "google-chrome" "chromium" "vivaldi"; do + assertFileExists "home-files/.config/$dir/policies/managed/com.github.browserpass.native.json" + done + + assertFileExists "home-files/.mozilla/native-messaging-hosts/com.github.browserpass.native.json" + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/browserpass/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/browserpass/default.nix new file mode 100644 index 00000000000..fa40ddcab31 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/browserpass/default.nix @@ -0,0 +1 @@ +{ browserpass = ./browserpass.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/dircolors/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/dircolors/default.nix new file mode 100644 index 00000000000..a82e2b859af --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/dircolors/default.nix @@ -0,0 +1 @@ +{ dircolors-settings = ./settings.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/dircolors/settings-expected.conf b/infra/libkookie/home-manager-stable/tests/modules/programs/dircolors/settings-expected.conf new file mode 100644 index 00000000000..d490081b37a --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/dircolors/settings-expected.conf @@ -0,0 +1,133 @@ +.7z 01;31 +.aac 00;36 +.ace 01;31 +.alz 01;31 +.arc 01;31 +.arj 01;31 +.asf 01;35 +.au 00;36 +.avi 01;35 +.bmp 01;35 +.bz 01;31 +.bz2 01;31 +.cab 01;31 +.cgm 01;35 +.cpio 01;31 +.csh 01;32 +.deb 01;31 +.dl 01;35 +.dwm 01;31 +.dz 01;31 +.ear 01;31 +.emf 01;35 +.esd 01;31 +.flac 00;36 +.flc 01;35 +.fli 01;35 +.flv 01;35 +.gif 01;35 +.gl 01;35 +.gz 01;31 +.jar 01;31 +.jpeg 01;35 +.jpg 01;35 +.lha 01;31 +.lrz 01;31 +.lz 01;31 +.lz4 01;31 +.lzh 01;31 +.lzma 01;31 +.lzo 01;31 +.m2v 01;35 +.m4a 00;36 +.m4v 01;35 +.mid 00;36 +.midi 00;36 +.mjpeg 01;35 +.mjpg 01;35 +.mka 00;36 +.mkv 01;35 +.mng 01;35 +.mov 01;35 +.mp3 00;36 +.mp4 01;35 +.mp4v 01;35 +.mpc 00;36 +.mpeg 01;35 +.mpg 01;35 +.nuv 01;35 +.oga 00;36 +.ogg 00;36 +.ogm 01;35 +.ogv 01;35 +.ogx 01;35 +.opus 00;36 +.pbm 01;35 +.pcx 01;35 +.pgm 01;35 +.png 01;35 +.ppm 01;35 +.qt 01;35 +.ra 00;36 +.rar 01;31 +.rm 01;35 +.rmvb 01;35 +.rpm 01;31 +.rz 01;31 +.sar 01;31 +.sh 01;32 +.spx 00;36 +.svg 01;35 +.svgz 01;35 +.swm 01;31 +.t7z 01;31 +.tar 01;31 +.taz 01;31 +.tbz 01;31 +.tbz2 01;31 +.tga 01;35 +.tgz 01;31 +.tif 01;35 +.tiff 01;35 +.tlz 01;31 +.txz 01;31 +.tz 01;31 +.tzo 01;31 +.tzst 01;31 +.vob 01;35 +.war 01;31 +.wav 00;36 +.webm 01;35 +.wim 01;31 +.wmv 01;35 +.xbm 01;35 +.xcf 01;35 +.xpm 01;35 +.xspf 00;36 +.xwd 01;35 +.xz 01;31 +.yuv 01;35 +.z 01;31 +.zip 01;31 +.zoo 01;31 +.zst 01;31 +BLK 40;33;01 +CAPABILITY 30;41 +CHR 40;33;01 +DIR 01;34 +DOOR 01;35 +EXEC 01;32 +FIFO 40;33 +LINK 01;36 +MISSING 00 +MULTIHARDLINK 00 +ORPHAN 40;31;01 +OTHER_WRITABLE 30;46 +RESET 0 +SETGID 30;43 +SETUID 37;41 +SOCK 01;35 +STICKY 37;44 +STICKY_OTHER_WRITABLE 30;42 + +# Extra dircolors configuration. diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/dircolors/settings.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/dircolors/settings.nix new file mode 100644 index 00000000000..9ca676ef9c0 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/dircolors/settings.nix @@ -0,0 +1,27 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.dircolors = { + enable = true; + + settings = { + OTHER_WRITABLE = "30;46"; + ".sh" = "01;32"; + ".csh" = "01;32"; + }; + + extraConfig = '' + # Extra dircolors configuration. + ''; + }; + + nmt.script = '' + assertFileContent \ + home-files/.dir_colors \ + ${./settings-expected.conf} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/direnv/bash.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/direnv/bash.nix new file mode 100644 index 00000000000..db0d6b391f5 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/direnv/bash.nix @@ -0,0 +1,17 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.bash.enable = true; + programs.direnv.enable = true; + + nmt.script = '' + assertFileExists home-files/.bashrc + assertFileRegex \ + home-files/.bashrc \ + 'eval "\$(/nix/store/.*direnv.*/bin/direnv hook bash)"' + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/direnv/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/direnv/default.nix new file mode 100644 index 00000000000..3efad2b6945 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/direnv/default.nix @@ -0,0 +1,6 @@ +{ + direnv-bash = ./bash.nix; + direnv-nix-direnv = ./nix-direnv.nix; + direnv-stdlib = ./stdlib.nix; + direnv-stdlib-and-nix-direnv = ./stdlib-and-nix-direnv.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/direnv/nix-direnv.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/direnv/nix-direnv.nix new file mode 100644 index 00000000000..4c173097730 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/direnv/nix-direnv.nix @@ -0,0 +1,18 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.bash.enable = true; + programs.direnv.enable = true; + programs.direnv.nix-direnv.enable = true; + + nmt.script = '' + assertFileExists home-files/.bashrc + assertFileRegex \ + home-files/.config/direnv/direnvrc \ + 'source /nix/store/.*nix-direnv.*/share/nix-direnv/direnvrc' + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/direnv/stdlib-and-nix-direnv.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/direnv/stdlib-and-nix-direnv.nix new file mode 100644 index 00000000000..4e5efb8732e --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/direnv/stdlib-and-nix-direnv.nix @@ -0,0 +1,23 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let expectedContent = "something important"; +in { + config = { + programs.bash.enable = true; + programs.direnv.enable = true; + programs.direnv.nix-direnv.enable = true; + programs.direnv.stdlib = expectedContent; + + nmt.script = '' + assertFileExists home-files/.bashrc + assertFileRegex \ + home-files/.config/direnv/direnvrc \ + 'source /nix/store/.*nix-direnv.*/share/nix-direnv/direnvrc' + assertFileRegex \ + home-files/.config/direnv/direnvrc \ + '${expectedContent}' + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/direnv/stdlib.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/direnv/stdlib.nix new file mode 100644 index 00000000000..1d06a0bc2a9 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/direnv/stdlib.nix @@ -0,0 +1,19 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let expectedContent = "something important"; +in { + config = { + programs.bash.enable = true; + programs.direnv.enable = true; + programs.direnv.stdlib = expectedContent; + + nmt.script = '' + assertFileExists home-files/.bashrc + assertFileRegex \ + home-files/.config/direnv/direnvrc \ + '${expectedContent}' + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/emacs/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/emacs/default.nix new file mode 100644 index 00000000000..b1b0c566d74 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/emacs/default.nix @@ -0,0 +1 @@ +{ emacs-extra-config = ./extra-config.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/emacs/extra-config.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/emacs/extra-config.nix new file mode 100644 index 00000000000..52e83de5c9e --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/emacs/extra-config.nix @@ -0,0 +1,42 @@ +{ config, lib, pkgs, ... }: + +let + + testScript = pkgs.writeText "test.el" '' + ;; Emacs won't automatically load default.el when --script is specified + (load "default") + (let* ((test-load-config (eq hm 'home-manager)) + (test-load-package (eq (hm-test-fn) 'success)) + (is-ok (and test-load-config test-load-package))) + (kill-emacs (if is-ok 0 1))) + ''; + + emacsBin = "${config.programs.emacs.finalPackage}/bin/emacs"; + + mkTestPackage = epkgs: + epkgs.trivialBuild { + pname = "hm-test"; + src = pkgs.writeText "hm-test.el" '' + (defun hm-test-fn () 'success) + (provide 'hm-test) + ''; + }; + +in lib.mkIf config.test.enableBig { + programs.emacs = { + enable = true; + package = pkgs.emacs-nox; + extraConfig = '' + (require 'hm-test) + (setq hm 'home-manager) + ''; + extraPackages = epkgs: [ (mkTestPackage epkgs) ]; + }; + + # running emacs with --script would enable headless mode + nmt.script = '' + if ! ${emacsBin} --script ${testScript}; then + fail "Failed to load default.el." + fi + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/feh/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/feh/default.nix new file mode 100644 index 00000000000..48bab8ab6e7 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/feh/default.nix @@ -0,0 +1,4 @@ +{ + feh-empty-config = ./feh-empty-settings.nix; + feh-bindings = ./feh-bindings.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/feh/feh-bindings-expected-buttons b/infra/libkookie/home-manager-stable/tests/modules/programs/feh/feh-bindings-expected-buttons new file mode 100644 index 00000000000..f285ada64f2 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/feh/feh-bindings-expected-buttons @@ -0,0 +1,4 @@ +zoom_in +next_img C-4 +prev_img 3 C-3 +zoom_out 4 diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/feh/feh-bindings-expected-keys b/infra/libkookie/home-manager-stable/tests/modules/programs/feh/feh-bindings-expected-keys new file mode 100644 index 00000000000..ad558e6aa7c --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/feh/feh-bindings-expected-keys @@ -0,0 +1,3 @@ +zoom_in +prev_img h Left +zoom_out minus diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/feh/feh-bindings.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/feh/feh-bindings.nix new file mode 100644 index 00000000000..787b02d7ce6 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/feh/feh-bindings.nix @@ -0,0 +1,32 @@ +{ pkgs, ... }: + +{ + config = { + programs.feh.enable = true; + + programs.feh.buttons = { + zoom_in = null; + zoom_out = 4; + next_img = "C-4"; + prev_img = [ 3 "C-3" ]; + }; + + programs.feh.keybindings = { + zoom_in = null; + zoom_out = "minus"; + prev_img = [ "h" "Left" ]; + }; + + test.stubs.feh = { }; + + nmt.script = '' + assertFileContent \ + home-files/.config/feh/buttons \ + ${./feh-bindings-expected-buttons} + + assertFileContent \ + home-files/.config/feh/keys \ + ${./feh-bindings-expected-keys} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/feh/feh-empty-settings.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/feh/feh-empty-settings.nix new file mode 100644 index 00000000000..62feb8230e1 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/feh/feh-empty-settings.nix @@ -0,0 +1,14 @@ +{ pkgs, ... }: + +{ + config = { + programs.feh.enable = true; + + test.stubs.feh = { }; + + nmt.script = '' + assertPathNotExists home-files/.config/feh/buttons + assertPathNotExists home-files/.config/feh/keys + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/firefox/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/firefox/default.nix new file mode 100644 index 00000000000..cc8e2fc4669 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/firefox/default.nix @@ -0,0 +1,5 @@ +{ + firefox-profile-settings = ./profile-settings.nix; + firefox-state-version-19_09 = ./state-version-19_09.nix; + firefox-deprecated-native-messenger = ./deprecated-native-messenger.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/firefox/deprecated-native-messenger.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/firefox/deprecated-native-messenger.nix new file mode 100644 index 00000000000..796389f1169 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/firefox/deprecated-native-messenger.nix @@ -0,0 +1,36 @@ +{ config, lib, pkgs, ... }: + +with lib; + +lib.mkIf config.test.enableBig { + programs.firefox = { + enable = true; + enableGnomeExtensions = true; + }; + + nixpkgs.overlays = [ + (self: super: { + firefox-unwrapped = pkgs.runCommandLocal "firefox-0" { + meta.description = "I pretend to be Firefox"; + passthru.gtk3 = null; + } '' + mkdir -p "$out"/{bin,lib} + touch "$out/bin/firefox" + chmod 755 "$out/bin/firefox" + ''; + + chrome-gnome-shell = + pkgs.runCommandLocal "dummy-chrome-gnome-shell" { } '' + mkdir -p $out/lib/mozilla/native-messaging-hosts + touch $out/lib/mozilla/native-messaging-hosts/dummy + ''; + }) + ]; + + test.asserts.warnings.expected = ['' + Using 'programs.firefox.enableGnomeExtensions' has been deprecated and + will be removed in the future. Please change to overriding the package + configuration using 'programs.firefox.package' instead. You can refer to + its example for how to do this. + '']; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/firefox/profile-settings-expected-bookmarks-user.js b/infra/libkookie/home-manager-stable/tests/modules/programs/firefox/profile-settings-expected-bookmarks-user.js new file mode 100644 index 00000000000..922d3651e2f --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/firefox/profile-settings-expected-bookmarks-user.js @@ -0,0 +1,8 @@ +// Generated by Home Manager. + +user_pref("browser.bookmarks.file", "/nix/store/00000000000000000000000000000000-firefox-bookmarks.html"); +user_pref("browser.places.importBookmarksHTML", true); +user_pref("general.smoothScroll", false); + + + diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/firefox/profile-settings-expected-bookmarks.html b/infra/libkookie/home-manager-stable/tests/modules/programs/firefox/profile-settings-expected-bookmarks.html new file mode 100644 index 00000000000..15ce487b0e9 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/firefox/profile-settings-expected-bookmarks.html @@ -0,0 +1,12 @@ + + + +Bookmarks +

Bookmarks Menu

+

+

kernel.org +
wikipedia + +

diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/firefox/profile-settings-expected-user.js b/infra/libkookie/home-manager-stable/tests/modules/programs/firefox/profile-settings-expected-user.js new file mode 100644 index 00000000000..0edd47b9101 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/firefox/profile-settings-expected-user.js @@ -0,0 +1,6 @@ +// Generated by Home Manager. + +user_pref("general.smoothScroll", false); + + + diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/firefox/profile-settings.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/firefox/profile-settings.nix new file mode 100644 index 00000000000..c74be20d1e1 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/firefox/profile-settings.nix @@ -0,0 +1,68 @@ +{ config, lib, pkgs, ... }: + +with lib; + +lib.mkIf config.test.enableBig { + programs.firefox = { + enable = true; + profiles.basic.isDefault = true; + + profiles.test = { + id = 1; + settings = { "general.smoothScroll" = false; }; + }; + + profiles.bookmarks = { + id = 2; + settings = { "general.smoothScroll" = false; }; + bookmarks = { + wikipedia = { + keyword = "wiki"; + url = "https://en.wikipedia.org/wiki/Special:Search?search=%s&go=Go"; + }; + "kernel.org" = { url = "https://www.kernel.org"; }; + }; + }; + }; + + nixpkgs.overlays = [ + (self: super: { + firefox-unwrapped = pkgs.runCommand "firefox-0" { + meta.description = "I pretend to be Firefox"; + preferLocalBuild = true; + passthru.gtk3 = null; + } '' + mkdir -p "$out"/{bin,lib} + touch "$out/bin/firefox" + chmod 755 "$out/bin/firefox" + ''; + }) + ]; + + nmt.script = '' + assertFileRegex \ + home-path/bin/firefox \ + MOZ_APP_LAUNCHER + + assertDirectoryExists home-files/.mozilla/firefox/basic + + assertFileContent \ + home-files/.mozilla/firefox/test/user.js \ + ${./profile-settings-expected-user.js} + + bookmarksUserJs=$(normalizeStorePaths \ + home-files/.mozilla/firefox/bookmarks/user.js) + + assertFileContent \ + $bookmarksUserJs \ + ${./profile-settings-expected-bookmarks-user.js} + + bookmarksFile="$(sed -n \ + '/browser.bookmarks.file/ {s|^.*\(/nix/store[^"]*\).*|\1|;p}' \ + $TESTED/home-files/.mozilla/firefox/bookmarks/user.js)" + + assertFileContent \ + $bookmarksFile \ + ${./profile-settings-expected-bookmarks.html} + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/firefox/state-version-19_09.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/firefox/state-version-19_09.nix new file mode 100644 index 00000000000..bf0b95f05cb --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/firefox/state-version-19_09.nix @@ -0,0 +1,29 @@ +{ config, lib, pkgs, ... }: + +with lib; + +lib.mkIf config.test.enableBig { + home.stateVersion = "19.09"; + + programs.firefox.enable = true; + + nixpkgs.overlays = [ + (self: super: { + firefox-unwrapped = pkgs.runCommand "firefox-0" { + meta.description = "I pretend to be Firefox"; + preferLocalBuild = true; + passthru.gtk3 = null; + } '' + mkdir -p "$out"/{bin,lib} + touch "$out/bin/firefox" + chmod 755 "$out/bin/firefox" + ''; + }) + ]; + + nmt.script = '' + assertFileRegex \ + home-path/bin/firefox \ + MOZ_APP_LAUNCHER + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/fish/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/fish/default.nix new file mode 100644 index 00000000000..99fe8136700 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/fish/default.nix @@ -0,0 +1,5 @@ +{ + fish-functions = ./functions.nix; + fish-no-functions = ./no-functions.nix; + fish-plugins = ./plugins.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/fish/functions.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/fish/functions.nix new file mode 100644 index 00000000000..67f8ba0d563 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/fish/functions.nix @@ -0,0 +1,54 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + func = pkgs.writeText "func.fish" '' + function func + echo "Hello" + end + ''; + + funcEvent = pkgs.writeText "func-event.fish" '' + function func-event --on-event="fish_command_not_found" + echo "Not found!" + end + ''; + +in { + config = { + programs.fish = { + enable = true; + + functions = { + func = ''echo "Hello"''; + func-event = { + body = ''echo "Not found!"''; + onEvent = "fish_command_not_found"; + }; + }; + }; + + # Needed to avoid error with dummy fish package. + xdg.dataFile."fish/home-manager_generated_completions".source = + lib.mkForce (builtins.toFile "empty" ""); + + test.stubs.fish = { }; + + nmt = { + description = + "if fish.function is set, check file exists and contents match"; + script = '' + assertFileExists home-files/.config/fish/functions/func.fish + echo ${func} + assertFileContent home-files/.config/fish/functions/func.fish ${func} + + assertFileExists home-files/.config/fish/functions/func-event.fish + echo ${funcEvent} + assertFileContent home-files/.config/fish/functions/func-event.fish ${funcEvent} + ''; + + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/fish/no-functions.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/fish/no-functions.nix new file mode 100644 index 00000000000..0ab38a09e79 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/fish/no-functions.nix @@ -0,0 +1,28 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.fish = { + enable = true; + + functions = { }; + }; + + # Needed to avoid error with dummy fish package. + xdg.dataFile."fish/home-manager_generated_completions".source = + lib.mkForce (builtins.toFile "empty" ""); + + test.stubs.fish = { }; + + nmt = { + description = + "if fish.functions is blank, the functions folder should not exist."; + script = '' + assertPathNotExists home-files/.config/fish/functions + ''; + + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/fish/plugins.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/fish/plugins.nix new file mode 100644 index 00000000000..6b02dd46f04 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/fish/plugins.nix @@ -0,0 +1,66 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + fooPluginSrc = pkgs.writeText "fooPluginSrc" ""; + + generatedConfdFile = pkgs.writeText "plugin-foo.fish" '' + # Plugin foo + set -l plugin_dir ${fooPluginSrc} + + # Set paths to import plugin components + if test -d $plugin_dir/functions + set fish_function_path $fish_function_path[1] $plugin_dir/functions $fish_function_path[2..-1] + end + + if test -d $plugin_dir/completions + set fish_complete_path $fish_complete_path[1] $plugin_dir/completions $fish_complete_path[2..-1] + end + + # Source initialization code if it exists. + if test -d $plugin_dir/conf.d + for f in $plugin_dir/conf.d/*.fish + source $f + end + end + + if test -f $plugin_dir/key_bindings.fish + source $plugin_dir/key_bindings.fish + end + + if test -f $plugin_dir/init.fish + source $plugin_dir/init.fish + end + ''; + +in { + config = { + programs.fish = { + enable = true; + + plugins = [{ + name = "foo"; + src = fooPluginSrc; + }]; + }; + + # Needed to avoid error with dummy fish package. + xdg.dataFile."fish/home-manager_generated_completions".source = + lib.mkForce (builtins.toFile "empty" ""); + + test.stubs.fish = { }; + + nmt = { + description = + "if fish.plugins set, check conf.d file exists and contents match"; + script = '' + assertDirectoryExists home-files/.config/fish/conf.d + assertFileExists home-files/.config/fish/conf.d/plugin-foo.fish + assertFileContent home-files/.config/fish/conf.d/plugin-foo.fish ${generatedConfdFile} + ''; + + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/foot/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/foot/default.nix new file mode 100644 index 00000000000..329e0f1f223 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/foot/default.nix @@ -0,0 +1,5 @@ +{ + foot-example-settings = ./example-settings.nix; + foot-empty-settings = ./empty-settings.nix; + foot-systemd-user-service = ./systemd-user-service.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/foot/empty-settings.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/foot/empty-settings.nix new file mode 100644 index 00000000000..26b82e7fbc5 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/foot/empty-settings.nix @@ -0,0 +1,15 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.foot.enable = true; + + test.stubs.foot = { }; + + nmt.script = '' + assertPathNotExists home-files/.config/foot + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/foot/example-settings-expected.ini b/infra/libkookie/home-manager-stable/tests/modules/programs/foot/example-settings-expected.ini new file mode 100644 index 00000000000..f5e12d80b45 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/foot/example-settings-expected.ini @@ -0,0 +1,7 @@ +[main] +dpi-aware=yes +font=Fira Code:size=11 +term=xterm-256color + +[mouse] +hide-when-typing=yes diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/foot/example-settings.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/foot/example-settings.nix new file mode 100644 index 00000000000..8390305eac1 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/foot/example-settings.nix @@ -0,0 +1,29 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.foot = { + enable = true; + package = config.lib.test.mkStubPackage { }; + + settings = { + main = { + term = "xterm-256color"; + + font = "Fira Code:size=11"; + dpi-aware = "yes"; + }; + + mouse = { hide-when-typing = "yes"; }; + }; + }; + + nmt.script = '' + assertFileContent \ + home-files/.config/foot/foot.ini \ + ${./example-settings-expected.ini} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/foot/systemd-user-service-expected.service b/infra/libkookie/home-manager-stable/tests/modules/programs/foot/systemd-user-service-expected.service new file mode 100644 index 00000000000..517344e531d --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/foot/systemd-user-service-expected.service @@ -0,0 +1,13 @@ +[Install] +WantedBy=graphical-session.target + +[Service] +ExecStart=@foot@/bin/foot --server +OOMPolicy=continue +Restart=on-failure + +[Unit] +After=graphical-session.target +Description=Fast, lightweight and minimalistic Wayland terminal emulator. +Documentation=man:foot(1) +PartOf=graphical-session.target diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/foot/systemd-user-service.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/foot/systemd-user-service.nix new file mode 100644 index 00000000000..5ebd9067503 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/foot/systemd-user-service.nix @@ -0,0 +1,19 @@ +{ config, lib, pkgs, ... }: + +{ + config = { + programs.foot = { + package = config.lib.test.mkStubPackage { outPath = "@foot@"; }; + enable = true; + server.enable = true; + }; + + nmt.script = '' + assertPathNotExists home-files/.config/foot/foot.ini + + assertFileContent \ + home-files/.config/systemd/user/foot.service \ + ${./systemd-user-service-expected.service} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/getmail/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/getmail/default.nix new file mode 100644 index 00000000000..cb789a90d64 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/getmail/default.nix @@ -0,0 +1 @@ +{ getmail = ./getmail.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/getmail/getmail-expected.conf b/infra/libkookie/home-manager-stable/tests/modules/programs/getmail/getmail-expected.conf new file mode 100644 index 00000000000..a91522a5deb --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/getmail/getmail-expected.conf @@ -0,0 +1,16 @@ +# Generated by Home-Manager. +[retriever] +type = SimpleIMAPSSLRetriever +server = imap.example.com +port = 993 +username = home.manager +password_command = ('password-command') +mailboxes = ( 'INBOX', 'Sent', 'Work', ) + +[destination] +type = MDA_external +path = /bin/maildrop + +[options] +delete = false +read_all = true diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/getmail/getmail.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/getmail/getmail.nix new file mode 100644 index 00000000000..c460a37e76e --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/getmail/getmail.nix @@ -0,0 +1,26 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + imports = [ ../../accounts/email-test-accounts.nix ]; + + config = { + accounts.email.accounts = { + "hm@example.com" = { + getmail = { + enable = true; + mailboxes = [ "INBOX" "Sent" "Work" ]; + destinationCommand = "/bin/maildrop"; + delete = false; + }; + imap.port = 993; + }; + }; + + nmt.script = '' + assertFileExists home-files/.getmail/getmailrc + assertFileContent home-files/.getmail/getmailrc ${./getmail-expected.conf} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/gh/config-file.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/gh/config-file.nix new file mode 100644 index 00000000000..58600e7f4bc --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/gh/config-file.nix @@ -0,0 +1,25 @@ +{ config, lib, pkgs, ... }: + +{ + config = { + programs.gh = { + enable = true; + settings.aliases = { co = "pr checkout"; }; + settings.editor = "vim"; + }; + + test.stubs.gh = { }; + + nmt.script = '' + assertFileExists home-files/.config/gh/config.yml + assertFileContent home-files/.config/gh/config.yml ${ + builtins.toFile "config-file.yml" '' + aliases: + co: pr checkout + editor: vim + git_protocol: https + '' + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/gh/credential-helper.git.conf b/infra/libkookie/home-manager-stable/tests/modules/programs/gh/credential-helper.git.conf new file mode 100644 index 00000000000..ea2c61ee464 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/gh/credential-helper.git.conf @@ -0,0 +1,2 @@ +[credential "https://github.com"] + helper = "@gh@/bin/gh auth git-credential" diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/gh/credential-helper.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/gh/credential-helper.nix new file mode 100644 index 00000000000..0c5ed872f3e --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/gh/credential-helper.nix @@ -0,0 +1,18 @@ +{ config, lib, pkgs, ... }: + +{ + programs.gh = { + enable = true; + enableGitCredentialHelper = true; + }; + + programs.git.enable = true; + + test.stubs.gh = { }; + + nmt.script = '' + assertFileExists home-files/.config/git/config + assertFileContent home-files/.config/git/config \ + ${./credential-helper.git.conf} + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/gh/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/gh/default.nix new file mode 100644 index 00000000000..c683b484e63 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/gh/default.nix @@ -0,0 +1,5 @@ +{ + gh-config-file = ./config-file.nix; + gh-credential-helper = ./credential-helper.nix; + gh-warnings = ./warnings.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/gh/warnings.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/gh/warnings.nix new file mode 100644 index 00000000000..53937a7c013 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/gh/warnings.nix @@ -0,0 +1,35 @@ +{ config, options, lib, pkgs, ... }: + +{ + config = { + programs.gh = { + enable = true; + aliases = { co = "pr checkout"; }; + editor = "vim"; + }; + + test.stubs.gh = { }; + + test.asserts.warnings.expected = [ + "The option `programs.gh.editor' defined in ${ + lib.showFiles options.programs.gh.editor.files + } has been renamed to `programs.gh.settings.editor'." + "The option `programs.gh.aliases' defined in ${ + lib.showFiles options.programs.gh.aliases.files + } has been renamed to `programs.gh.settings.aliases'." + ]; + test.asserts.warnings.enable = true; + + nmt.script = '' + assertFileExists home-files/.config/gh/config.yml + assertFileContent home-files/.config/gh/config.yml ${ + builtins.toFile "config-file.yml" '' + aliases: + co: pr checkout + editor: vim + git_protocol: https + '' + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/git/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/git/default.nix new file mode 100644 index 00000000000..3d401d8fc29 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/git/default.nix @@ -0,0 +1,8 @@ +{ + git-with-email = ./git-with-email.nix; + git-with-most-options = ./git.nix; + git-with-msmtp = ./git-with-msmtp.nix; + git-with-str-extra-config = ./git-with-str-extra-config.nix; + git-with-signing-key-id = ./git-with-signing-key-id.nix; + git-without-signing-key-id = ./git-without-signing-key-id.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/git/git-expected-include.conf b/infra/libkookie/home-manager-stable/tests/modules/programs/git/git-expected-include.conf new file mode 100644 index 00000000000..f05c7b6c7fc --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/git/git-expected-include.conf @@ -0,0 +1,3 @@ +[user] + email = "user@example.org" + name = "John Doe" diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/git/git-expected.conf b/infra/libkookie/home-manager-stable/tests/modules/programs/git/git-expected.conf new file mode 100644 index 00000000000..fe258a0d3be --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/git/git-expected.conf @@ -0,0 +1,58 @@ +[alias] + a1 = "foo" + a2 = "baz" + escapes = "\"\\n\t" + +[commit] + gpgSign = true + +[core] + pager = "@delta@/bin/delta" + +[delta] + features = "decorations" + whitespace-error-style = "22 reverse" + +[delta "decorations"] + commit-decoration-style = "bold yellow box ul" + file-decoration-style = "none" + file-style = "bold yellow ul" + +[extra] + boolean = true + integer = 38 + multiple = 1 + multiple = 2 + name = "value" + +[extra "backcompat.with.dots"] + previously = "worked" + +[extra "subsection"] + value = "test" + +[filter "lfs"] + clean = "git-lfs clean -- %f" + process = "git-lfs filter-process" + required = true + smudge = "git-lfs smudge -- %f" + +[gpg] + program = "path-to-gpg" + +[interactive] + diffFilter = "@delta@/bin/delta --color-only" + +[user] + email = "user@example.org" + name = "John Doe" + signingKey = "00112233445566778899AABBCCDDEEFF" + +[include] + path = "~/path/to/config.inc" + +[includeIf "gitdir:~/src/dir"] + path = "~/path/to/conditional.inc" + +[includeIf "gitdir:~/src/dir"] + path = "@git_include_path@" diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/git/git-with-email-expected.conf b/infra/libkookie/home-manager-stable/tests/modules/programs/git/git-with-email-expected.conf new file mode 100644 index 00000000000..c34ab1d79e3 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/git/git-with-email-expected.conf @@ -0,0 +1,17 @@ +[sendemail "hm-account"] + from = "hm@example.org" + smtpEncryption = "tls" + smtpServer = "smtp.example.org" + smtpSslCertPath = "/etc/test/certificates.crt" + smtpUser = "home.manager.jr" + +[sendemail "hm@example.com"] + from = "hm@example.com" + smtpEncryption = "ssl" + smtpServer = "smtp.example.com" + smtpSslCertPath = "/etc/ssl/certs/ca-certificates.crt" + smtpUser = "home.manager" + +[user] + email = "hm@example.com" + name = "H. M. Test" diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/git/git-with-email.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/git/git-with-email.nix new file mode 100644 index 00000000000..ec18ecb92e0 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/git/git-with-email.nix @@ -0,0 +1,40 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + imports = [ ../../accounts/email-test-accounts.nix ]; + + config = { + accounts.email.accounts.hm-account.smtp.tls.certificatesFile = + "/etc/test/certificates.crt"; + programs.git = { + enable = true; + package = pkgs.gitMinimal; + userEmail = "hm@example.com"; + userName = "H. M. Test"; + }; + + home.stateVersion = "20.09"; + + nmt.script = '' + function assertGitConfig() { + local value + value=$(${pkgs.gitMinimal}/bin/git config \ + --file $TESTED/home-files/.config/git/config \ + --get $1) + if [[ $value != $2 ]]; then + fail "Expected option '$1' to have value '$2' but it was '$value'" + fi + } + + assertFileExists home-files/.config/git/config + assertFileContent home-files/.config/git/config ${ + ./git-with-email-expected.conf + } + + assertGitConfig "sendemail.hm@example.com.from" "hm@example.com" + assertGitConfig "sendemail.hm-account.from" "hm@example.org" + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/git/git-with-msmtp-expected.conf b/infra/libkookie/home-manager-stable/tests/modules/programs/git/git-with-msmtp-expected.conf new file mode 100644 index 00000000000..1f2c7b794b9 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/git/git-with-msmtp-expected.conf @@ -0,0 +1,15 @@ +[sendemail "hm-account"] + from = "hm@example.org" + smtpEncryption = "tls" + smtpServer = "smtp.example.org" + smtpSslCertPath = "/etc/ssl/certs/ca-certificates.crt" + smtpUser = "home.manager.jr" + +[sendemail "hm@example.com"] + envelopeSender = "auto" + from = "hm@example.com" + smtpServer = "@msmtp@/bin/msmtp" + +[user] + email = "hm@example.com" + name = "H. M. Test" diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/git/git-with-msmtp.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/git/git-with-msmtp.nix new file mode 100644 index 00000000000..dc6ba465e9d --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/git/git-with-msmtp.nix @@ -0,0 +1,42 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + imports = [ ../../accounts/email-test-accounts.nix ]; + + config = { + accounts.email.accounts."hm@example.com".msmtp.enable = true; + programs.git = { + enable = true; + package = pkgs.gitMinimal; + userEmail = "hm@example.com"; + userName = "H. M. Test"; + }; + + home.stateVersion = "20.09"; + + test.stubs.msmtp = { }; + + nmt.script = '' + function assertGitConfig() { + local value + value=$(${pkgs.gitMinimal}/bin/git config \ + --file $TESTED/home-files/.config/git/config \ + --get $1) + if [[ $value != $2 ]]; then + fail "Expected option '$1' to have value '$2' but it was '$value'" + fi + } + + assertFileExists home-files/.config/git/config + assertFileContent home-files/.config/git/config \ + ${./git-with-msmtp-expected.conf} + + assertGitConfig "sendemail.hm@example.com.from" "hm@example.com" + assertGitConfig "sendemail.hm-account.from" "hm@example.org" + assertGitConfig "sendemail.hm@example.com.smtpServer" "${pkgs.msmtp}/bin/msmtp" + assertGitConfig "sendemail.hm@example.com.envelopeSender" "auto" + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/git/git-with-signing-key-id-expected.conf b/infra/libkookie/home-manager-stable/tests/modules/programs/git/git-with-signing-key-id-expected.conf new file mode 100644 index 00000000000..4a428990207 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/git/git-with-signing-key-id-expected.conf @@ -0,0 +1,10 @@ +[commit] + gpgSign = true + +[gpg] + program = "path-to-gpg" + +[user] + email = "user@example.org" + name = "John Doe" + signingKey = "00112233445566778899AABBCCDDEEFF" diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/git/git-with-signing-key-id.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/git/git-with-signing-key-id.nix new file mode 100644 index 00000000000..8d182505fb6 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/git/git-with-signing-key-id.nix @@ -0,0 +1,22 @@ +{ pkgs, ... }: { + config = { + programs.git = { + enable = true; + userName = "John Doe"; + userEmail = "user@example.org"; + + signing = { + gpgPath = "path-to-gpg"; + key = "00112233445566778899AABBCCDDEEFF"; + signByDefault = true; + }; + }; + + nmt.script = '' + assertFileExists home-files/.config/git/config + assertFileContent home-files/.config/git/config ${ + ./git-with-signing-key-id-expected.conf + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/git/git-with-str-extra-config-expected.conf b/infra/libkookie/home-manager-stable/tests/modules/programs/git/git-with-str-extra-config-expected.conf new file mode 100644 index 00000000000..071268e831c --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/git/git-with-str-extra-config-expected.conf @@ -0,0 +1,5 @@ +This can be anything. + +[user] + email = "user@example.org" + name = "John Doe" diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/git/git-with-str-extra-config.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/git/git-with-str-extra-config.nix new file mode 100644 index 00000000000..b2294c65b23 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/git/git-with-str-extra-config.nix @@ -0,0 +1,29 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.git = { + enable = true; + package = pkgs.gitMinimal; + extraConfig = '' + This can be anything. + ''; + userEmail = "user@example.org"; + userName = "John Doe"; + }; + + test.asserts.warnings.expected = ['' + Using programs.git.extraConfig as a string option is + deprecated and will be removed in the future. Please + change to using it as an attribute set instead. + '']; + + nmt.script = '' + assertFileExists home-files/.config/git/config + assertFileContent home-files/.config/git/config \ + ${./git-with-str-extra-config-expected.conf} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/git/git-without-signing-key-id-expected.conf b/infra/libkookie/home-manager-stable/tests/modules/programs/git/git-without-signing-key-id-expected.conf new file mode 100644 index 00000000000..7564b350214 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/git/git-without-signing-key-id-expected.conf @@ -0,0 +1,9 @@ +[commit] + gpgSign = true + +[gpg] + program = "path-to-gpg" + +[user] + email = "user@example.org" + name = "John Doe" diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/git/git-without-signing-key-id.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/git/git-without-signing-key-id.nix new file mode 100644 index 00000000000..3428c40d79e --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/git/git-without-signing-key-id.nix @@ -0,0 +1,22 @@ +{ pkgs, ... }: { + config = { + programs.git = { + enable = true; + userName = "John Doe"; + userEmail = "user@example.org"; + + signing = { + gpgPath = "path-to-gpg"; + key = null; + signByDefault = true; + }; + }; + + nmt.script = '' + assertFileExists home-files/.config/git/config + assertFileContent home-files/.config/git/config ${ + ./git-without-signing-key-id-expected.conf + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/git/git.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/git/git.nix new file mode 100644 index 00000000000..6c7320604b5 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/git/git.nix @@ -0,0 +1,94 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + gitInclude = { + user = { + name = "John Doe"; + email = "user@example.org"; + }; + }; + + substituteExpected = path: + pkgs.substituteAll { + src = path; + git_include_path = pkgs.writeText "contents" + (builtins.readFile ./git-expected-include.conf); + }; + +in { + config = { + programs.git = mkMerge [ + { + enable = true; + package = pkgs.gitMinimal; + aliases = { + a1 = "foo"; + a2 = "bar"; + escapes = ''"\n ''; + }; + extraConfig = { + extra = { + name = "value"; + multiple = [ 1 ]; + }; + }; + ignores = [ "*~" "*.swp" ]; + includes = [ + { path = "~/path/to/config.inc"; } + { + path = "~/path/to/conditional.inc"; + condition = "gitdir:~/src/dir"; + } + { + condition = "gitdir:~/src/dir"; + contents = gitInclude; + } + ]; + signing = { + gpgPath = "path-to-gpg"; + key = "00112233445566778899AABBCCDDEEFF"; + signByDefault = true; + }; + userEmail = "user@example.org"; + userName = "John Doe"; + lfs.enable = true; + delta = { + enable = true; + options = { + features = "decorations"; + whitespace-error-style = "22 reverse"; + decorations = { + commit-decoration-style = "bold yellow box ul"; + file-style = "bold yellow ul"; + file-decoration-style = "none"; + }; + }; + }; + } + + { + aliases.a2 = mkForce "baz"; + extraConfig."extra \"backcompat.with.dots\"".previously = "worked"; + extraConfig.extra.boolean = true; + extraConfig.extra.integer = 38; + extraConfig.extra.multiple = [ 2 ]; + extraConfig.extra.subsection.value = "test"; + } + ]; + + test.stubs = { + git-lfs = { }; + delta = { }; + }; + + nmt.script = '' + assertFileExists home-files/.config/git/config + assertFileContent home-files/.config/git/config ${ + substituteExpected ./git-expected.conf + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/gnome-terminal/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/gnome-terminal/default.nix new file mode 100644 index 00000000000..2cfb4923618 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/gnome-terminal/default.nix @@ -0,0 +1 @@ +{ gnome-terminal-1 = ./gnome-terminal-1.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/gnome-terminal/gnome-terminal-1.conf b/infra/libkookie/home-manager-stable/tests/modules/programs/gnome-terminal/gnome-terminal-1.conf new file mode 100644 index 00000000000..d44376449f2 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/gnome-terminal/gnome-terminal-1.conf @@ -0,0 +1,34 @@ +[org/gnome/terminal/legacy] +default-show-menubar=false +schema-version=3 +theme-variant='default' + +[org/gnome/terminal/legacy/profiles:] +default='e0b782ed-6aca-44eb-8c75-62b3706b6220' +list=@as ['e0b782ed-6aca-44eb-8c75-62b3706b6220'] + +[org/gnome/terminal/legacy/profiles:/:e0b782ed-6aca-44eb-8c75-62b3706b6220] +allow-bold=true +audible-bell=true +background-color='#2E3436' +background-transparency-percent=5 +backspace-binding='ascii-delete' +bold-color-same-as-fg=true +bold-is-bright=true +cursor-blink-mode='off' +cursor-colors-set=false +cursor-shape='underline' +delete-binding='delete-sequence' +foreground-color='#D3D7C1' +highlight-colors-set=false +login-shell=false +palette=@as ['#000000','#AA0000','#00AA00','#AA5500','#0000AA','#AA00AA','#00AAAA','#AAAAAA','#555555','#FF5555','#55FF55','#FFFF55','#5555FF','#FF55FF','#55FFFF','#FFFFFF'] +scroll-on-output=false +scrollback-lines=1000000 +scrollbar-policy='never' +use-custom-command=false +use-system-font=true +use-theme-colors=false +use-theme-transparency=false +use-transparent-background=true +visible-name='kamadorueda' diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/gnome-terminal/gnome-terminal-1.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/gnome-terminal/gnome-terminal-1.nix new file mode 100644 index 00000000000..bb58983feb4 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/gnome-terminal/gnome-terminal-1.nix @@ -0,0 +1,64 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.gnome-terminal = { + enable = true; + profile = { + "e0b782ed-6aca-44eb-8c75-62b3706b6220" = { + allowBold = true; + audibleBell = true; + backspaceBinding = "ascii-delete"; + boldIsBright = true; + colors = { + backgroundColor = "#2E3436"; + foregroundColor = "#D3D7C1"; + palette = [ + "#000000" + "#AA0000" + "#00AA00" + "#AA5500" + "#0000AA" + "#AA00AA" + "#00AAAA" + "#AAAAAA" + "#555555" + "#FF5555" + "#55FF55" + "#FFFF55" + "#5555FF" + "#FF55FF" + "#55FFFF" + "#FFFFFF" + ]; + }; + cursorBlinkMode = "off"; + cursorShape = "underline"; + default = true; + deleteBinding = "delete-sequence"; + scrollbackLines = 1000000; + scrollOnOutput = false; + showScrollbar = false; + transparencyPercent = 5; + visibleName = "kamadorueda"; + }; + }; + showMenubar = false; + }; + + nixpkgs.overlays = [ + (self: super: { + gnome.gnome-terminal = config.lib.test.mkStubPackage { }; + }) + ]; + + test.stubs.dconf = { }; + + nmt.script = '' + dconfIni=$(grep -oPm 1 '/nix/store/[a-z0-9]*?-hm-dconf.ini' $TESTED/activate) + assertFileContent $dconfIni ${./gnome-terminal-1.conf} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/gpg/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/gpg/default.nix new file mode 100644 index 00000000000..a3949b18601 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/gpg/default.nix @@ -0,0 +1,5 @@ +{ + gpg-immutable-keyfiles = ./immutable-keyfiles.nix; + gpg-mutable-keyfiles = ./mutable-keyfiles.nix; + gpg-override-defaults = ./override-defaults.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/gpg/immutable-keyfiles.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/gpg/immutable-keyfiles.nix new file mode 100644 index 00000000000..b66d770f19b --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/gpg/immutable-keyfiles.nix @@ -0,0 +1,52 @@ +{ config, lib, pkgs, ... }: + +{ + programs.gpg = { + enable = true; + + mutableKeys = false; + mutableTrust = false; + + publicKeys = [ + { + source = pkgs.fetchurl { + url = + "https://keybase.io/rycee/pgp_keys.asc?fingerprint=36cacf52d098cc0e78fb0cb13573356c25c424d4"; + sha256 = "082mjy6llvrdry6i9r5gx97nw9d89blnam7bghza4ynsjk1mmx6c"; + }; + trust = 1; # "unknown" + } + { + source = pkgs.fetchurl { + url = "https://www.rsync.net/resources/pubkey.txt"; + sha256 = "16nzqfb1kvsxjkq919hxsawx6ydvip3md3qyhdmw54qx6drnxckl"; + }; + trust = "never"; + } + ]; + }; + + nmt.script = '' + assertFileNotRegex activate "^export GNUPGHOME='/home/hm-user/.gnupg'$" + + assertFileRegex activate \ + '^install -m 0700 /nix/store/[0-9a-z]*-gpg-pubring/trustdb.gpg "/home/hm-user/.gnupg/trustdb.gpg"$' + + # Setup GPGHOME + export GNUPGHOME=$(mktemp -d) + cp -r $TESTED/home-files/.gnupg/* $GNUPGHOME + TRUSTDB=$(grep -o '/nix/store/[0-9a-z]*-gpg-pubring/trustdb.gpg' $TESTED/activate) + install -m 0700 $TRUSTDB $GNUPGHOME/trustdb.gpg + + # Export Trust + export WORKDIR=$(mktemp -d) + ${pkgs.gnupg}/bin/gpg -q --export-ownertrust > $WORKDIR/gpgtrust.txt + + # Check Trust + assertFileRegex $WORKDIR/gpgtrust.txt \ + '^36CACF52D098CC0E78FB0CB13573356C25C424D4:2:$' + + assertFileRegex $WORKDIR/gpgtrust.txt \ + '^BB847B5A69EF343CEF511B29073C282D7D6F806C:3:$' + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/gpg/mutable-keyfiles.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/gpg/mutable-keyfiles.nix new file mode 100644 index 00000000000..588c9070488 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/gpg/mutable-keyfiles.nix @@ -0,0 +1,30 @@ +{ config, lib, pkgs, ... }: + +{ + programs.gpg = { + enable = true; + + publicKeys = [ + { + source = builtins.toFile "key1" "key1"; + trust = 1; + } + { source = builtins.toFile "key2" "key2"; } + ]; + }; + + test.stubs.gnupg = { }; + + nmt.script = '' + assertFileContains activate "export GNUPGHOME='/home/hm-user/.gnupg'" + + assertFileContains activate "unset GNUPGHOME QUIET_ARG keyId importTrust" + + assertFileRegex activate \ + '^\$DRY_RUN_CMD @gnupg@/bin/gpg \$QUIET_ARG --import /nix/store/[0-9a-z]*-key1$' + assertFileRegex activate \ + '^\$DRY_RUN_CMD importTrust "/nix/store/[0-9a-z]*-key1" 1$' + assertFileRegex activate \ + '^\$DRY_RUN_CMD @gnupg@/bin/gpg \$QUIET_ARG --import /nix/store/[0-9a-z]*-key2$' + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/gpg/override-defaults-expected.conf b/infra/libkookie/home-manager-stable/tests/modules/programs/gpg/override-defaults-expected.conf new file mode 100644 index 00000000000..4b4f132d002 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/gpg/override-defaults-expected.conf @@ -0,0 +1,21 @@ +cert-digest-algo SHA512 +charset utf-8 +default-preference-list SHA512 SHA384 SHA256 AES256 AES192 AES ZLIB BZIP2 ZIP Uncompressed +fixed-list-mode +keyid-format 0xlong +list-options show-uid-validity + +no-emit-version +no-symkey-cache +personal-cipher-preferences AES256 AES192 AES +personal-compress-preferences ZLIB BZIP2 ZIP Uncompressed +personal-digest-preferences SHA512 SHA384 SHA256 +require-cross-certification +s2k-cipher-algo AES128 +s2k-digest-algo SHA512 +throw-keyids +trusted-key 0xXXXXXXXXXXXXX +trusted-key 0xYYYYYYYYYYYYY +use-agent +verify-options show-uid-validity +with-fingerprint diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/gpg/override-defaults.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/gpg/override-defaults.nix new file mode 100644 index 00000000000..e410433956f --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/gpg/override-defaults.nix @@ -0,0 +1,29 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.gpg = { + enable = true; + + settings = { + no-comments = false; + s2k-cipher-algo = "AES128"; + throw-keyids = true; + trusted-key = [ "0xXXXXXXXXXXXXX" "0xYYYYYYYYYYYYY" ]; + }; + + homedir = "${config.home.homeDirectory}/bar/foopg"; + }; + + nmt.script = '' + assertFileExists home-files/bar/foopg/gpg.conf + assertFileContent home-files/bar/foopg/gpg.conf ${ + ./override-defaults-expected.conf + } + + assertFileNotRegex activate "^unset GNUPGHOME keyId importTrust$" + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/helix/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/helix/default.nix new file mode 100644 index 00000000000..77172c7082a --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/helix/default.nix @@ -0,0 +1 @@ +{ helix-example-settings = ./example-settings.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/helix/example-settings.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/helix/example-settings.nix new file mode 100644 index 00000000000..ed0b4713b45 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/helix/example-settings.nix @@ -0,0 +1,118 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.helix = { + enable = true; + + settings = { + theme = "base16"; + lsp.display-messages = true; + keys.normal = { + space.space = "file_picker"; + space.w = ":w"; + space.q = ":q"; + }; + }; + + languages = [{ + name = "rust"; + auto-format = false; + }]; + + themes = { + base16 = let + transparent = "none"; + gray = "#665c54"; + dark-gray = "#3c3836"; + white = "#fbf1c7"; + black = "#282828"; + red = "#fb4934"; + green = "#b8bb26"; + yellow = "#fabd2f"; + orange = "#fe8019"; + blue = "#83a598"; + magenta = "#d3869b"; + cyan = "#8ec07c"; + in { + "ui.menu" = transparent; + "ui.menu.selected" = { modifiers = [ "reversed" ]; }; + "ui.linenr" = { + fg = gray; + bg = dark-gray; + }; + "ui.popup" = { modifiers = [ "reversed" ]; }; + "ui.linenr.selected" = { + fg = white; + bg = black; + modifiers = [ "bold" ]; + }; + "ui.selection" = { + fg = black; + bg = blue; + }; + "ui.selection.primary" = { modifiers = [ "reversed" ]; }; + "comment" = { fg = gray; }; + "ui.statusline" = { + fg = white; + bg = dark-gray; + }; + "ui.statusline.inactive" = { + fg = dark-gray; + bg = white; + }; + "ui.help" = { + fg = dark-gray; + bg = white; + }; + "ui.cursor" = { modifiers = [ "reversed" ]; }; + "variable" = red; + "variable.builtin" = orange; + "constant.numeric" = orange; + "constant" = orange; + "attributes" = yellow; + "type" = yellow; + "ui.cursor.match" = { + fg = yellow; + modifiers = [ "underlined" ]; + }; + "string" = green; + "variable.other.member" = red; + "constant.character.escape" = cyan; + "function" = blue; + "constructor" = blue; + "special" = blue; + "keyword" = magenta; + "label" = magenta; + "namespace" = blue; + "diff.plus" = green; + "diff.delta" = yellow; + "diff.minus" = red; + "diagnostic" = { modifiers = [ "underlined" ]; }; + "ui.gutter" = { bg = black; }; + "info" = blue; + "hint" = dark-gray; + "debug" = dark-gray; + "warning" = yellow; + "error" = red; + }; + }; + }; + + test.stubs.helix = { }; + + nmt.script = '' + assertFileContent \ + home-files/.config/helix/config.toml \ + ${./settings-expected.toml} + assertFileContent \ + home-files/.config/helix/languages.toml \ + ${./languages-expected.toml} + assertFileContent \ + home-files/.config/helix/themes/base16.toml \ + ${./theme-base16-expected.toml} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/helix/languages-expected.toml b/infra/libkookie/home-manager-stable/tests/modules/programs/helix/languages-expected.toml new file mode 100644 index 00000000000..d3404397b3d --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/helix/languages-expected.toml @@ -0,0 +1,3 @@ +[[language]] +auto-format = false +name = "rust" diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/helix/settings-expected.toml b/infra/libkookie/home-manager-stable/tests/modules/programs/helix/settings-expected.toml new file mode 100644 index 00000000000..772bcf52534 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/helix/settings-expected.toml @@ -0,0 +1,9 @@ +theme = "base16" + +[keys.normal.space] +q = ":q" +space = "file_picker" +w = ":w" + +[lsp] +display-messages = true diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/helix/theme-base16-expected.toml b/infra/libkookie/home-manager-stable/tests/modules/programs/helix/theme-base16-expected.toml new file mode 100644 index 00000000000..25d0bef0cb1 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/helix/theme-base16-expected.toml @@ -0,0 +1,74 @@ +attributes = "#fabd2f" +constant = "#fe8019" +"constant.character.escape" = "#8ec07c" +"constant.numeric" = "#fe8019" +constructor = "#83a598" +debug = "#3c3836" +"diff.delta" = "#fabd2f" +"diff.minus" = "#fb4934" +"diff.plus" = "#b8bb26" +error = "#fb4934" +function = "#83a598" +hint = "#3c3836" +info = "#83a598" +keyword = "#d3869b" +label = "#d3869b" +namespace = "#83a598" +special = "#83a598" +string = "#b8bb26" +type = "#fabd2f" +"ui.menu" = "none" +variable = "#fb4934" +"variable.builtin" = "#fe8019" +"variable.other.member" = "#fb4934" +warning = "#fabd2f" + +[comment] +fg = "#665c54" + +[diagnostic] +modifiers = ["underlined"] + +["ui.cursor"] +modifiers = ["reversed"] + +["ui.cursor.match"] +fg = "#fabd2f" +modifiers = ["underlined"] + +["ui.gutter"] +bg = "#282828" + +["ui.help"] +bg = "#fbf1c7" +fg = "#3c3836" + +["ui.linenr"] +bg = "#3c3836" +fg = "#665c54" + +["ui.linenr.selected"] +bg = "#282828" +fg = "#fbf1c7" +modifiers = ["bold"] + +["ui.menu.selected"] +modifiers = ["reversed"] + +["ui.popup"] +modifiers = ["reversed"] + +["ui.selection"] +bg = "#83a598" +fg = "#282828" + +["ui.selection.primary"] +modifiers = ["reversed"] + +["ui.statusline"] +bg = "#3c3836" +fg = "#fbf1c7" + +["ui.statusline.inactive"] +bg = "#fbf1c7" +fg = "#3c3836" diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/hexchat/basic-configuration-expected-main-config b/infra/libkookie/home-manager-stable/tests/modules/programs/hexchat/basic-configuration-expected-main-config new file mode 100644 index 00000000000..e3617ca8217 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/hexchat/basic-configuration-expected-main-config @@ -0,0 +1,10 @@ +dcc_dir = /home/user/Downloads +gui_quit_dialog = 0 +gui_slist_skip = 1 +irc_nick1 = user +irc_nick2 = user_ +irc_nick3 = user__ +irc_real_name = real user +irc_user_name = user +text_font = Monospace 14 +text_font_main = Monospace 14 \ No newline at end of file diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/hexchat/basic-configuration-expected-serverlist-config b/infra/libkookie/home-manager-stable/tests/modules/programs/hexchat/basic-configuration-expected-serverlist-config new file mode 100644 index 00000000000..29d232842b7 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/hexchat/basic-configuration-expected-serverlist-config @@ -0,0 +1,24 @@ + +N=efnet +L= +F=4 +S=irc.choopa.net +S=irc.colosolutions.net +S=irc.mzima.net +S=irc.prison.net +J=#computers + +N=freenode +L=6 +E=UTF-8 (Unicode) +F=12 +I=user +i=user_ +R=real_user +U=user +P=password +S=chat.freenode.net +S=irc.freenode.net +J=#home-manager +J=#nixos + diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/hexchat/basic-configuration.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/hexchat/basic-configuration.nix new file mode 100644 index 00000000000..1aa39bd49ac --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/hexchat/basic-configuration.nix @@ -0,0 +1,61 @@ +{ config, lib, pkgs, ... }: + +{ + config = { + programs.hexchat = { + enable = true; + overwriteConfigFiles = true; + channels = { + freenode = { + charset = "UTF-8 (Unicode)"; + userName = "user"; + password = "password"; + loginMethod = "sasl"; + nickname = "user"; + nickname2 = "user_"; + realName = "real_user"; + options = { + autoconnect = true; + forceSSL = true; + }; + servers = [ "chat.freenode.net" "irc.freenode.net" ]; + autojoin = [ "#home-manager" "#nixos" ]; + }; + efnet = { + options = { forceSSL = true; }; + servers = [ + "irc.choopa.net" + "irc.colosolutions.net" + "irc.mzima.net" + "irc.prison.net" + ]; + autojoin = [ "#computers" ]; + }; + }; + settings = { + dcc_dir = "/home/user/Downloads"; + irc_nick1 = "user"; + irc_nick2 = "user_"; + irc_nick3 = "user__"; + irc_user_name = "user"; + irc_real_name = "real user"; + text_font = "Monospace 14"; + text_font_main = "Monospace 14"; + gui_slist_skip = "1"; # Skip network list on start-up + gui_quit_dialog = "0"; + }; + }; + + test.stubs.hexchat = { }; + + nmt.script = '' + assertFileContent \ + home-files/.config/hexchat/hexchat.conf \ + ${./basic-configuration-expected-main-config} + assertFileContent \ + home-files/.config/hexchat/servlist.conf \ + ${./basic-configuration-expected-serverlist-config} + ''; + }; + +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/hexchat/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/hexchat/default.nix new file mode 100644 index 00000000000..e70c4610c6f --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/hexchat/default.nix @@ -0,0 +1 @@ +{ hexchat-basic-configuration = ./basic-configuration.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/himalaya/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/himalaya/default.nix new file mode 100644 index 00000000000..54c3978d8a4 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/himalaya/default.nix @@ -0,0 +1 @@ +{ himalaya = ./himalaya.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/himalaya/himalaya-expected.toml b/infra/libkookie/home-manager-stable/tests/modules/programs/himalaya/himalaya-expected.toml new file mode 100644 index 00000000000..6c2dfb84c38 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/himalaya/himalaya-expected.toml @@ -0,0 +1,23 @@ +downloads-dir = "/data/download" +name = "" + +["hm@example.com"] +default = true +default-page-size = 50 +email = "hm@example.com" +imap-host = "imap.example.com" +imap-login = "home.manager" +imap-passwd-cmd = "'password-command'" +imap-port = 995 +imap-starttls = false +name = "H. M. Test" +smtp-host = "smtp.example.com" +smtp-login = "home.manager" +smtp-passwd-cmd = "'password-command'" +smtp-port = 465 +smtp-starttls = false + +["hm@example.com".mailboxes] +draft = "Drafts" +inbox = "In" +sent = "Out" diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/himalaya/himalaya.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/himalaya/himalaya.nix new file mode 100644 index 00000000000..13872d158fb --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/himalaya/himalaya.nix @@ -0,0 +1,41 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + imports = [ ../../accounts/email-test-accounts.nix ]; + + accounts.email.accounts = { + "hm@example.com" = { + himalaya = { + enable = true; + + settings = { default-page-size = 50; }; + }; + + folders = { + inbox = "In"; + sent = "Out"; + drafts = "Drafts"; + }; + + imap.port = 995; + smtp.port = 465; + }; + }; + + programs.himalaya = { + enable = true; + settings = { downloads-dir = "/data/download"; }; + }; + + test.stubs.himalaya = { }; + + nmt.script = '' + assertFileExists home-files/.config/himalaya/config.toml + assertFileContent home-files/.config/himalaya/config.toml ${ + ./himalaya-expected.toml + } + ''; +} + diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/htop/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/htop/default.nix new file mode 100644 index 00000000000..e63d74fd39b --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/htop/default.nix @@ -0,0 +1,6 @@ +{ + htop-empty-settings = ./empty-settings.nix; + htop-example-settings = ./example-settings.nix; + htop-header_layout = ./header_layout.nix; + htop-settings-without-fields = ./settings-without-fields.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/htop/empty-settings.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/htop/empty-settings.nix new file mode 100644 index 00000000000..b8e43600f7c --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/htop/empty-settings.nix @@ -0,0 +1,15 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.htop.enable = true; + + test.stubs.htop = { }; + + nmt.script = '' + assertPathNotExists home-files/.config/htop + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/htop/example-htoprc.txt b/infra/libkookie/home-manager-stable/tests/modules/programs/htop/example-htoprc.txt new file mode 100644 index 00000000000..ff06ed5ea8f --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/htop/example-htoprc.txt @@ -0,0 +1,11 @@ +color_scheme=6 +cpu_count_from_one=0 +delay=15 +fields=0 48 17 18 38 39 40 2 46 47 49 1 +highlight_base_name=1 +highlight_megabytes=1 +highlight_threads=1 +left_meter_modes=1 1 1 2 +left_meters=AllCPUs2 Memory Swap Zram +right_meter_modes=2 2 2 2 +right_meters=Tasks LoadAverage Uptime Systemd diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/htop/example-settings.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/htop/example-settings.nix new file mode 100644 index 00000000000..71685434adc --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/htop/example-settings.nix @@ -0,0 +1,47 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.htop.enable = true; + programs.htop.settings = { + color_scheme = 6; + cpu_count_from_one = 0; + delay = 15; + fields = with config.lib.htop.fields; [ + PID + USER + PRIORITY + NICE + M_SIZE + M_RESIDENT + M_SHARE + STATE + PERCENT_CPU + PERCENT_MEM + TIME + COMM + ]; + highlight_base_name = 1; + highlight_megabytes = 1; + highlight_threads = 1; + } // (with config.lib.htop; + leftMeters [ (bar "AllCPUs2") (bar "Memory") (bar "Swap") (text "Zram") ]) + // (with config.lib.htop; + rightMeters [ + (text "Tasks") + (text "LoadAverage") + (text "Uptime") + (text "Systemd") + ]); + + test.stubs.htop = { }; + + nmt.script = '' + htoprc=home-files/.config/htop/htoprc + assertFileExists $htoprc + assertFileContent $htoprc ${./example-htoprc.txt} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/htop/header_layout.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/htop/header_layout.nix new file mode 100644 index 00000000000..aaf62852237 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/htop/header_layout.nix @@ -0,0 +1,42 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = with config.lib.htop; { + programs.htop.enable = true; + programs.htop.settings = { + header_layout = "two_50_50"; + column_meters_0 = [ "AllCPUs2" "Memory" "Swap" "Zram" ]; + column_meters_modes_0 = [ modes.Bar modes.Bar modes.Bar modes.Text ]; + column_meters_1 = [ "Tasks" "LoadAverage" "Uptime" "Systemd" ]; + column_meters_modes_1 = [ modes.Text modes.Text modes.Text modes.Text ]; + }; + + test.stubs.htop = { }; + + # Test that the 'fields' key is written in addition to the customized + # settings or htop won't read the options. + nmt.script = let + fields = if pkgs.stdenv.hostPlatform.isDarwin then + "0 48 17 18 38 39 2 46 47 49 1" + else + "0 48 17 18 38 39 40 2 46 47 49 1"; + in '' + htoprc=home-files/.config/htop/htoprc + assertFileExists $htoprc + assertFileContent $htoprc \ + ${ + builtins.toFile "htoprc-expected" '' + header_layout=two_50_50 + column_meters_0=AllCPUs2 Memory Swap Zram + column_meters_1=Tasks LoadAverage Uptime Systemd + column_meters_modes_0=1 1 1 2 + column_meters_modes_1=2 2 2 2 + fields=${fields} + '' + } + ''; + }; + +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/htop/settings-without-fields.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/htop/settings-without-fields.nix new file mode 100644 index 00000000000..f1efac2d435 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/htop/settings-without-fields.nix @@ -0,0 +1,32 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.htop.enable = true; + programs.htop.settings = { color_scheme = 6; }; + + test.stubs.htop = { }; + + # Test that the 'fields' key is written in addition to the customized + # settings or htop won't read the options. + nmt.script = let + fields = if pkgs.stdenv.hostPlatform.isDarwin then + "0 48 17 18 38 39 2 46 47 49 1" + else + "0 48 17 18 38 39 40 2 46 47 49 1"; + in '' + htoprc=home-files/.config/htop/htoprc + assertFileExists $htoprc + assertFileContent $htoprc \ + ${ + builtins.toFile "htoprc-expected" '' + color_scheme=6 + fields=${fields} + '' + } + ''; + }; + +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/i3status-rust/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/i3status-rust/default.nix new file mode 100644 index 00000000000..50d8c7b853c --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/i3status-rust/default.nix @@ -0,0 +1,6 @@ +{ + i3status-rust-with-default = ./with-default.nix; + i3status-rust-with-custom = ./with-custom.nix; + i3status-rust-with-extra-settings = ./with-extra-settings.nix; + i3status-rust-with-multiple-bars = ./with-multiple-bars.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/i3status-rust/with-custom.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/i3status-rust/with-custom.nix new file mode 100644 index 00000000000..d89e2ddcb82 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/i3status-rust/with-custom.nix @@ -0,0 +1,182 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.i3status-rust = { + enable = true; + bars = { + custom = { + blocks = [ + { + block = "disk_space"; + path = "/"; + alias = "/"; + info_type = "available"; + unit = "GB"; + interval = 60; + warning = 20.0; + alert = 10.0; + } + { + block = "memory"; + display_type = "memory"; + format_mem = "{Mug}GB ({Mup}%)"; + format_swap = "{SUp}%"; + } + { + block = "cpu"; + interval = 1; + format = "{barchart}"; + } + { + block = "load"; + interval = 1; + format = "{1m} {5m}"; + } + { + block = "temperature"; + collapsed = true; + interval = 10; + format = "{min}° min, {max}° max, {average}° avg"; + chip = "*-isa-*"; + } + { + block = "networkmanager"; + ap_format = "{ssid} @ {strength}%"; + on_click = "kcmshell5 kcm_networkmanagement"; + } + { + block = "net"; + device = "enp9s0u2u1u2c2"; + speed_up = true; + interval = 5; + } + { + block = "speedtest"; + bytes = true; + } + { + block = "xrandr"; + interval = + 6000; # Because running the commands causes screen lag, see https://github.com/greshake/i3status-rust/issues/668 + } + { + block = "sound"; + format = "{output_name} {volume}%"; + on_click = "pavucontrol --tab=3"; + mappings = { + "alsa_output.pci-0000_00_1f.3.analog-stereo" = ""; + "bluez_sink.70_26_05_DA_27_A4.a2dp_sink" = ""; + }; + } + { + block = "music"; + player = "spotify"; + buttons = [ "play" "prev" "next" ]; + on_collapsed_click = "i3-msg '[class=Spotify] focus'"; + } + { + block = "time"; + interval = 60; + format = "%a %d.%m %R"; + } + { block = "battery"; } + ]; + + icons = "awesome5"; + + theme = "gruvbox-dark"; + }; + }; + }; + + test.stubs.i3status-rust = { }; + + nmt.script = '' + assertFileExists home-files/.config/i3status-rust/config-custom.toml + assertFileContent home-files/.config/i3status-rust/config-custom.toml \ + ${ + pkgs.writeText "i3status-rust-expected-config" '' + icons = "awesome5" + theme = "gruvbox-dark" + [[block]] + alert = 10 + alias = "/" + block = "disk_space" + info_type = "available" + interval = 60 + path = "/" + unit = "GB" + warning = 20 + + [[block]] + block = "memory" + display_type = "memory" + format_mem = "{Mug}GB ({Mup}%)" + format_swap = "{SUp}%" + + [[block]] + block = "cpu" + format = "{barchart}" + interval = 1 + + [[block]] + block = "load" + format = "{1m} {5m}" + interval = 1 + + [[block]] + block = "temperature" + chip = "*-isa-*" + collapsed = true + format = "{min}° min, {max}° max, {average}° avg" + interval = 10 + + [[block]] + ap_format = "{ssid} @ {strength}%" + block = "networkmanager" + on_click = "kcmshell5 kcm_networkmanagement" + + [[block]] + block = "net" + device = "enp9s0u2u1u2c2" + interval = 5 + speed_up = true + + [[block]] + block = "speedtest" + bytes = true + + [[block]] + block = "xrandr" + interval = 6000 + + [[block]] + block = "sound" + format = "{output_name} {volume}%" + on_click = "pavucontrol --tab=3" + + [block.mappings] + "alsa_output.pci-0000_00_1f.3.analog-stereo" = "" + "bluez_sink.70_26_05_DA_27_A4.a2dp_sink" = "" + + [[block]] + block = "music" + buttons = ["play", "prev", "next"] + on_collapsed_click = "i3-msg '[class=Spotify] focus'" + player = "spotify" + + [[block]] + block = "time" + format = "%a %d.%m %R" + interval = 60 + + [[block]] + block = "battery" + '' + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/i3status-rust/with-default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/i3status-rust/with-default.nix new file mode 100644 index 00000000000..3da74ac02c3 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/i3status-rust/with-default.nix @@ -0,0 +1,54 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.i3status-rust = { enable = true; }; + + test.stubs.i3status-rust = { }; + + nmt.script = '' + assertFileExists home-files/.config/i3status-rust/config-default.toml + assertFileContent home-files/.config/i3status-rust/config-default.toml \ + ${ + pkgs.writeText "i3status-rust-expected-config" '' + icons = "none" + theme = "plain" + [[block]] + alert = 10 + alias = "/" + block = "disk_space" + info_type = "available" + interval = 60 + path = "/" + unit = "GB" + warning = 20 + + [[block]] + block = "memory" + display_type = "memory" + format_mem = "{mem_used_percents}" + format_swap = "{swap_used_percents}" + + [[block]] + block = "cpu" + interval = 1 + + [[block]] + block = "load" + format = "{1m}" + interval = 1 + + [[block]] + block = "sound" + + [[block]] + block = "time" + format = "%a %d/%m %R" + interval = 60 + '' + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/i3status-rust/with-extra-settings.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/i3status-rust/with-extra-settings.nix new file mode 100644 index 00000000000..114edb99309 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/i3status-rust/with-extra-settings.nix @@ -0,0 +1,198 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.i3status-rust = { + enable = true; + bars = { + extra-settings = { + blocks = [ + { + block = "disk_space"; + path = "/"; + alias = "/"; + info_type = "available"; + unit = "GB"; + interval = 60; + warning = 20.0; + alert = 10.0; + } + { + block = "memory"; + display_type = "memory"; + format_mem = "{Mug}GB ({Mup}%)"; + format_swap = "{SUp}%"; + } + { + block = "cpu"; + interval = 1; + format = "{barchart}"; + } + { + block = "load"; + interval = 1; + format = "{1m} {5m}"; + } + { + block = "temperature"; + collapsed = true; + interval = 10; + format = "{min}° min, {max}° max, {average}° avg"; + chip = "*-isa-*"; + } + { + block = "networkmanager"; + ap_format = "{ssid} @ {strength}%"; + on_click = "kcmshell5 kcm_networkmanagement"; + } + { + block = "net"; + device = "enp9s0u2u1u2c2"; + speed_up = true; + interval = 5; + } + { + block = "speedtest"; + bytes = true; + } + { + block = "xrandr"; + interval = + 6000; # Because running the commands causes screen lag, see https://github.com/greshake/i3status-rust/issues/668 + } + { + block = "sound"; + format = "{output_name} {volume}%"; + on_click = "pavucontrol --tab=3"; + mappings = { + "alsa_output.pci-0000_00_1f.3.analog-stereo" = ""; + "bluez_sink.70_26_05_DA_27_A4.a2dp_sink" = ""; + }; + } + { + block = "music"; + player = "spotify"; + buttons = [ "play" "prev" "next" ]; + on_collapsed_click = "i3-msg '[class=Spotify] focus'"; + } + { + block = "time"; + interval = 60; + format = "%a %d.%m %R"; + } + { block = "battery"; } + ]; + + icons = "awesome5"; + + settings = { + theme = { + name = "solarized-dark"; + overrides = { + idle_bg = "#123456"; + idle_fg = "#abcdef"; + }; + }; + }; + + theme = "gruvbox-dark"; + }; + }; + }; + + test.stubs.i3status-rust = { }; + + nmt.script = '' + assertFileExists home-files/.config/i3status-rust/config-extra-settings.toml + assertFileContent home-files/.config/i3status-rust/config-extra-settings.toml \ + ${ + pkgs.writeText "i3status-rust-expected-config" '' + icons = "awesome5" + [[block]] + alert = 10 + alias = "/" + block = "disk_space" + info_type = "available" + interval = 60 + path = "/" + unit = "GB" + warning = 20 + + [[block]] + block = "memory" + display_type = "memory" + format_mem = "{Mug}GB ({Mup}%)" + format_swap = "{SUp}%" + + [[block]] + block = "cpu" + format = "{barchart}" + interval = 1 + + [[block]] + block = "load" + format = "{1m} {5m}" + interval = 1 + + [[block]] + block = "temperature" + chip = "*-isa-*" + collapsed = true + format = "{min}° min, {max}° max, {average}° avg" + interval = 10 + + [[block]] + ap_format = "{ssid} @ {strength}%" + block = "networkmanager" + on_click = "kcmshell5 kcm_networkmanagement" + + [[block]] + block = "net" + device = "enp9s0u2u1u2c2" + interval = 5 + speed_up = true + + [[block]] + block = "speedtest" + bytes = true + + [[block]] + block = "xrandr" + interval = 6000 + + [[block]] + block = "sound" + format = "{output_name} {volume}%" + on_click = "pavucontrol --tab=3" + + [block.mappings] + "alsa_output.pci-0000_00_1f.3.analog-stereo" = "" + "bluez_sink.70_26_05_DA_27_A4.a2dp_sink" = "" + + [[block]] + block = "music" + buttons = ["play", "prev", "next"] + on_collapsed_click = "i3-msg '[class=Spotify] focus'" + player = "spotify" + + [[block]] + block = "time" + format = "%a %d.%m %R" + interval = 60 + + [[block]] + block = "battery" + + [theme] + name = "solarized-dark" + + [theme.overrides] + idle_bg = "#123456" + idle_fg = "#abcdef" + '' + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/i3status-rust/with-multiple-bars.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/i3status-rust/with-multiple-bars.nix new file mode 100644 index 00000000000..eab7f42d47b --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/i3status-rust/with-multiple-bars.nix @@ -0,0 +1,102 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.i3status-rust = { + enable = true; + + bars = { + + top = { + blocks = [ + { + block = "disk_space"; + path = "/"; + alias = "/"; + info_type = "available"; + unit = "GB"; + interval = 60; + warning = 20.0; + alert = 10.0; + } + { + block = "memory"; + display_type = "memory"; + format_mem = "{Mug}GB ({Mup}%)"; + format_swap = "{SUp}%"; + } + ]; + }; + + bottom = { + blocks = [ + { + block = "cpu"; + interval = 1; + format = "{barchart}"; + } + { + block = "load"; + interval = 1; + format = "{1m} {5m}"; + } + ]; + icons = "awesome5"; + + theme = "gruvbox-dark"; + }; + + }; + + }; + + test.stubs.i3status-rust = { }; + + nmt.script = '' + assertFileExists home-files/.config/i3status-rust/config-top.toml + assertFileContent home-files/.config/i3status-rust/config-top.toml \ + ${ + pkgs.writeText "i3status-rust-expected-config" '' + icons = "none" + theme = "plain" + [[block]] + alert = 10 + alias = "/" + block = "disk_space" + info_type = "available" + interval = 60 + path = "/" + unit = "GB" + warning = 20 + + [[block]] + block = "memory" + display_type = "memory" + format_mem = "{Mug}GB ({Mup}%)" + format_swap = "{SUp}%" + '' + } + + assertFileExists home-files/.config/i3status-rust/config-bottom.toml + assertFileContent \ + home-files/.config/i3status-rust/config-bottom.toml \ + ${ + pkgs.writeText "i3status-rust-expected-config" '' + icons = "awesome5" + theme = "gruvbox-dark" + [[block]] + block = "cpu" + format = "{barchart}" + interval = 1 + + [[block]] + block = "load" + format = "{1m} {5m}" + interval = 1 + '' + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/i3status/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/i3status/default.nix new file mode 100644 index 00000000000..c8d55755861 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/i3status/default.nix @@ -0,0 +1,4 @@ +{ + i3status-with-custom = ./with-custom.nix; + i3status-with-default = ./with-default.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/i3status/with-custom.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/i3status/with-custom.nix new file mode 100644 index 00000000000..830bc6c98db --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/i3status/with-custom.nix @@ -0,0 +1,65 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.i3status = { + enable = true; + enableDefault = false; + + general = { + colors = true; + color_good = "#e0e0e0"; + color_degraded = "#d7ae00"; + color_bad = "#f69d6a"; + interval = 1; + }; + + modules = { + "volume master" = { + position = 1; + settings = { + format = "♪ %volume"; + format_muted = "♪ muted (%volume)"; + device = "pulse:1"; + }; + }; + "disk /" = { + position = 2; + settings = { format = "/ %avail"; }; + }; + }; + }; + + test.stubs.i3status = { }; + + nmt.script = '' + assertFileContent \ + home-files/.config/i3status/config \ + ${ + pkgs.writeText "i3status-expected-config" '' + general { + color_bad = "#f69d6a" + color_degraded = "#d7ae00" + color_good = "#e0e0e0" + colors = true + interval = 1 + } + + order += "volume master" + order += "disk /" + disk / { + format = "/ %avail" + } + + volume master { + device = "pulse:1" + format = "♪ %volume" + format_muted = "♪ muted (%volume)" + } + '' + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/i3status/with-default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/i3status/with-default.nix new file mode 100644 index 00000000000..d56ecc20544 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/i3status/with-default.nix @@ -0,0 +1,71 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.i3status = { + enable = true; + enableDefault = true; + }; + + test.stubs.i3status = { }; + + nmt.script = '' + assertFileContent \ + home-files/.config/i3status/config \ + ${ + pkgs.writeText "i3status-expected-config" '' + general { + colors = true + interval = 5 + } + + order += "ipv6" + order += "wireless _first_" + order += "ethernet _first_" + order += "battery all" + order += "disk /" + order += "load" + order += "memory" + order += "tztime local" + battery all { + format = "%status %percentage %remaining" + } + + disk / { + format = "%avail" + } + + ethernet _first_ { + format_down = "E: down" + format_up = "E: %ip (%speed)" + } + + ipv6 { + + } + + load { + format = "%1min" + } + + memory { + format = "%used | %available" + format_degraded = "MEMORY < %available" + threshold_degraded = "1G" + } + + tztime local { + format = "%Y-%m-%d %H:%M:%S" + } + + wireless _first_ { + format_down = "W: down" + format_up = "W: (%quality at %essid) %ip" + } + '' + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/irssi/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/irssi/default.nix new file mode 100644 index 00000000000..fc5e7ed9042 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/irssi/default.nix @@ -0,0 +1 @@ +{ irssi-example-settings = ./example-settings.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/irssi/example-settings-expected.config b/infra/libkookie/home-manager-stable/tests/modules/programs/irssi/example-settings-expected.config new file mode 100644 index 00000000000..8c54243bc38 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/irssi/example-settings-expected.config @@ -0,0 +1,43 @@ +settings = { + core = { + settings_autosave = "no"; + }; +}; + +aliases = { + +}; + +chatnets = { +oftc = { + type = "IRC"; + nick = "nick"; + autosendcmd = ""; +}; + +}; + +servers = ( +{ + chatnet = "oftc"; + address = "irc.oftc.net"; + port = "6697"; + use_ssl = "yes"; + ssl_verify = "yes"; + autoconnect = "yes"; + ssl_cert = "/home/hm-user/.irssi/certs/nick.pem"; + +} + +); + +channels = ( +{ + chatnet = "oftc"; + name = "home-manager"; + autojoin = "yes"; +} + +); + + diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/irssi/example-settings.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/irssi/example-settings.nix new file mode 100644 index 00000000000..93cf9f2d7cc --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/irssi/example-settings.nix @@ -0,0 +1,30 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.irssi = { + enable = true; + networks.oftc = { + nick = "nick"; + server = { + address = "irc.oftc.net"; + port = 6697; + autoConnect = true; + ssl.certificateFile = + "${config.home.homeDirectory}/.irssi/certs/nick.pem"; + }; + channels.home-manager.autoJoin = true; + }; + }; + + test.stubs.irssi = { }; + + nmt.script = '' + assertFileContent \ + home-files/.irssi/config \ + ${./example-settings-expected.config} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/kakoune/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/kakoune/default.nix new file mode 100644 index 00000000000..1e6e077df1f --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/kakoune/default.nix @@ -0,0 +1,7 @@ +{ + kakoune-no-plugins = ./no-plugins.nix; + kakoune-use-plugins = ./use-plugins.nix; + kakoune-whitespace-highlighter = ./whitespace-highlighter.nix; + kakoune-whitespace-highlighter-corner-cases = + ./whitespace-highlighter-corner-cases.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/kakoune/no-plugins.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/kakoune/no-plugins.nix new file mode 100644 index 00000000000..d1505751bbb --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/kakoune/no-plugins.nix @@ -0,0 +1,13 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + imports = [ ./stubs.nix ]; + + programs.kakoune = { enable = true; }; + + nmt.script = '' + assertPathNotExists home-path/share/kak/autoload/plugins + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/kakoune/stubs.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/kakoune/stubs.nix new file mode 100644 index 00000000000..28a8164185d --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/kakoune/stubs.nix @@ -0,0 +1,12 @@ +{ + test.stubs.kakoune-unwrapped = { + name = "dummy-kakoune"; + version = "1"; + outPath = null; + buildScript = '' + mkdir -p $out/bin $out/share/kak/doc + touch $out/bin/kak + chmod +x $out/bin/kak + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/kakoune/use-plugins.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/kakoune/use-plugins.nix new file mode 100644 index 00000000000..de7b3a12310 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/kakoune/use-plugins.nix @@ -0,0 +1,16 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + imports = [ ./stubs.nix ]; + + programs.kakoune = { + enable = true; + plugins = [ pkgs.kakounePlugins.prelude-kak ]; + }; + + nmt.script = '' + assertDirectoryNotEmpty home-path/share/kak/autoload/plugins + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/kakoune/whitespace-highlighter-corner-cases.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/kakoune/whitespace-highlighter-corner-cases.nix new file mode 100644 index 00000000000..4beb4b9e57a --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/kakoune/whitespace-highlighter-corner-cases.nix @@ -0,0 +1,25 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + imports = [ ./stubs.nix ]; + + programs.kakoune = { + enable = true; + config.showWhitespace = { + enable = true; + lineFeed = ''"''; + space = " "; + nonBreakingSpace = "' '"; # backwards compat + tab = "'"; + # tabStop = + }; + }; + + nmt.script = '' + assertFileExists home-files/.config/kak/kakrc + assertFileContains home-files/.config/kak/kakrc \ + "add-highlighter global/ show-whitespaces -tab \"'\" -spc ' ' -nbsp ' ' -lf '\"'" + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/kakoune/whitespace-highlighter.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/kakoune/whitespace-highlighter.nix new file mode 100644 index 00000000000..1c80fe5f2d7 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/kakoune/whitespace-highlighter.nix @@ -0,0 +1,25 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + imports = [ ./stubs.nix ]; + + programs.kakoune = { + enable = true; + config.showWhitespace = { + enable = true; + lineFeed = "1"; + space = "2"; + nonBreakingSpace = "3"; + tab = "4"; + tabStop = "5"; + }; + }; + + nmt.script = '' + assertFileExists home-files/.config/kak/kakrc + assertFileContains home-files/.config/kak/kakrc \ + "add-highlighter global/ show-whitespaces -tab '4' -tabpad '5' -spc '2' -nbsp '3' -lf '1'" + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/kitty/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/kitty/default.nix new file mode 100644 index 00000000000..694c43cd87a --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/kitty/default.nix @@ -0,0 +1 @@ +{ kitty-example-settings = ./example-settings.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/kitty/example-macos-launch-services-cmdline b/infra/libkookie/home-manager-stable/tests/modules/programs/kitty/example-macos-launch-services-cmdline new file mode 100644 index 00000000000..e104109ee59 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/kitty/example-macos-launch-services-cmdline @@ -0,0 +1 @@ +--single-instance --directory=/tmp/my-dir --listen-on=unix:/tmp/my-socket \ No newline at end of file diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/kitty/example-settings-expected.conf b/infra/libkookie/home-manager-stable/tests/modules/programs/kitty/example-settings-expected.conf new file mode 100644 index 00000000000..8d0fbd14a64 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/kitty/example-settings-expected.conf @@ -0,0 +1,22 @@ +# Generated by Home Manager. +# See https://sw.kovidgoyal.net/kitty/conf.html + +font_family DejaVu Sans +font_size 8 + + + + +enable_audio_bell no +scrollback_lines 10000 +update_check_interval 0 + + +map ctrl+c copy_or_interrupt +map ctrl+f>2 set_font_size 20 + + +env LS_COLORS=1 + + + diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/kitty/example-settings.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/kitty/example-settings.nix new file mode 100644 index 00000000000..8d609a5abb6 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/kitty/example-settings.nix @@ -0,0 +1,46 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.kitty = { + enable = true; + + darwinLaunchOptions = lib.mkIf pkgs.stdenv.hostPlatform.isDarwin [ + "--single-instance" + "--directory=/tmp/my-dir" + "--listen-on=unix:/tmp/my-socket" + ]; + + settings = { + scrollback_lines = 10000; + enable_audio_bell = false; + update_check_interval = 0; + }; + + font.name = "DejaVu Sans"; + font.size = 8; + + keybindings = { + "ctrl+c" = "copy_or_interrupt"; + "ctrl+f>2" = "set_font_size 20"; + }; + + environment = { LS_COLORS = "1"; }; + }; + + test.stubs.kitty = { }; + + nmt.script = '' + assertFileExists home-files/.config/kitty/kitty.conf + assertFileContent \ + home-files/.config/kitty/kitty.conf \ + ${./example-settings-expected.conf} + '' + lib.optionalString pkgs.stdenv.hostPlatform.isDarwin '' + assertFileContent \ + home-files/.config/kitty/macos-launch-services-cmdline \ + ${./example-macos-launch-services-cmdline} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/kodi/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/kodi/default.nix new file mode 100644 index 00000000000..1902645c481 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/kodi/default.nix @@ -0,0 +1,5 @@ +{ + kodi-example-addon-settings = ./example-addon-settings.nix; + kodi-example-settings = ./example-settings.nix; + kodi-example-sources = ./example-sources.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/kodi/example-addon-settings-expected.xml b/infra/libkookie/home-manager-stable/tests/modules/programs/kodi/example-addon-settings-expected.xml new file mode 100644 index 00000000000..21259b24472 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/kodi/example-addon-settings-expected.xml @@ -0,0 +1,4 @@ + + + false + diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/kodi/example-addon-settings.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/kodi/example-addon-settings.nix new file mode 100644 index 00000000000..c591d1ae39a --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/kodi/example-addon-settings.nix @@ -0,0 +1,18 @@ +{ config, ... }: + +{ + programs.kodi = { + enable = true; + package = config.lib.test.mkStubPackage { }; + + addonSettings = { + "service.xbmc.versioncheck".versioncheck_enable = "false"; + }; + }; + + nmt.script = '' + assertFileContent \ + home-files/.kodi/userdata/addon_data/service.xbmc.versioncheck/settings.xml \ + ${./example-addon-settings-expected.xml} + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/kodi/example-settings-expected.xml b/infra/libkookie/home-manager-stable/tests/modules/programs/kodi/example-settings-expected.xml new file mode 100644 index 00000000000..2aca9763773 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/kodi/example-settings-expected.xml @@ -0,0 +1,6 @@ + + + + true + + diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/kodi/example-settings.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/kodi/example-settings.nix new file mode 100644 index 00000000000..bdb48268af9 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/kodi/example-settings.nix @@ -0,0 +1,16 @@ +{ config, ... }: + +{ + programs.kodi = { + enable = true; + package = config.lib.test.mkStubPackage { }; + + settings = { videolibrary.showemptytvshows = "true"; }; + }; + + nmt.script = '' + assertFileContent \ + home-files/.kodi/userdata/advancedsettings.xml \ + ${./example-settings-expected.xml} + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/kodi/example-sources-expected.xml b/infra/libkookie/home-manager-stable/tests/modules/programs/kodi/example-sources-expected.xml new file mode 100644 index 00000000000..736f8963a13 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/kodi/example-sources-expected.xml @@ -0,0 +1,16 @@ + + + + diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/kodi/example-sources.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/kodi/example-sources.nix new file mode 100644 index 00000000000..f49b500011d --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/kodi/example-sources.nix @@ -0,0 +1,33 @@ +{ config, ... }: + +{ + programs.kodi = { + enable = true; + package = config.lib.test.mkStubPackage { }; + + sources = { + video = { + default = "movies"; + source = [ + { + name = "videos"; + path = "/path/to/videos"; + allowsharing = "true"; + } + { + name = "movies"; + path = "/path/to/movies"; + allowsharing = "true"; + } + ]; + }; + }; + + }; + + nmt.script = '' + assertFileContent \ + home-files/.kodi/userdata/sources.xml \ + ${./example-sources-expected.xml} + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/less/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/less/default.nix new file mode 100644 index 00000000000..f5fd77feb32 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/less/default.nix @@ -0,0 +1 @@ +{ less-with-custom-keys = ./less-with-custom-keys.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/less/less-with-custom-keys.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/less/less-with-custom-keys.nix new file mode 100644 index 00000000000..23d44718921 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/less/less-with-custom-keys.nix @@ -0,0 +1,26 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + programs.less = { + enable = true; + + keys = '' + s back-line + t forw-line + ''; + }; + + test.stubs.less = { }; + + nmt.script = '' + assertFileExists home-files/.config/lesskey + assertFileContent home-files/.config/lesskey ${ + builtins.toFile "less.expected" '' + s back-line + t forw-line + '' + } + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/lf/all-options.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/lf/all-options.nix new file mode 100644 index 00000000000..35d7901d6c1 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/lf/all-options.nix @@ -0,0 +1,85 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + pvScript = builtins.toFile "pv.sh" "cat $1"; + expected = builtins.toFile "settings-expected" '' + set icons + set noignorecase + set ratios "2:2:3" + set tabstop 4 + + cmd added :echo "foo" + cmd multiline :{{ + push gg + echo "bar" + push i + }} + cmd removed + + map aa should-be-added + map ab + + cmap should-be-added + cmap + + set previewer ${pvScript} + map i ${"$"}${pvScript} "$f" | less -R + + + + # More config... + + ''; +in { + config = { + programs.lf = { + enable = true; + + cmdKeybindings = { + "" = "should-be-added"; + "" = null; + }; + + commands = { + added = '':echo "foo"''; + removed = null; + multiline = '' + :{{ + push gg + echo "bar" + push i + }}''; + }; + + extraConfig = '' + # More config... + ''; + + keybindings = { + aa = "should-be-added"; + ab = null; + }; + + previewer = { + keybinding = "i"; + source = pvScript; + }; + + settings = { + ignorecase = false; + icons = true; + tabstop = 4; + ratios = "2:2:3"; + }; + }; + + test.stubs.lf = { }; + + nmt.script = '' + assertFileExists home-files/.config/lf/lfrc + assertFileContent home-files/.config/lf/lfrc ${expected} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/lf/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/lf/default.nix new file mode 100644 index 00000000000..65cf24fcf60 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/lf/default.nix @@ -0,0 +1,5 @@ +{ + lf-all-options = ./all-options.nix; + lf-minimal-options = ./minimal-options.nix; + lf-no-pv-keybind = ./no-pv-keybind.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/lf/minimal-options.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/lf/minimal-options.nix new file mode 100644 index 00000000000..078c776e786 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/lf/minimal-options.nix @@ -0,0 +1,17 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let expected = builtins.toFile "settings-expected" "\n\n\n\n\n\n\n\n\n\n\n"; +in { + config = { + programs.lf = { enable = true; }; + + test.stubs.lf = { }; + + nmt.script = '' + assertFileExists home-files/.config/lf/lfrc + assertFileContent home-files/.config/lf/lfrc ${expected} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/lf/no-pv-keybind.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/lf/no-pv-keybind.nix new file mode 100644 index 00000000000..c948cf0b5f6 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/lf/no-pv-keybind.nix @@ -0,0 +1,42 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + pvScript = builtins.toFile "pv.sh" "cat $1"; + expected = builtins.toFile "settings-expected" '' + + + + + + + + + set previewer ${pvScript} + + + + # More config... + + ''; +in { + config = { + programs.lf = { + enable = true; + + extraConfig = '' + # More config... + ''; + + previewer = { source = pvScript; }; + }; + + test.stubs.lf = { }; + + nmt.script = '' + assertFileExists home-files/.config/lf/lfrc + assertFileContent home-files/.config/lf/lfrc ${expected} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/lieer/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/lieer/default.nix new file mode 100644 index 00000000000..16f8627cf0d --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/lieer/default.nix @@ -0,0 +1 @@ +{ lieer = ./lieer.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/lieer/lieer-expected.json b/infra/libkookie/home-manager-stable/tests/modules/programs/lieer/lieer-expected.json new file mode 100644 index 00000000000..332e2d598af --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/lieer/lieer-expected.json @@ -0,0 +1,18 @@ +{ + "account": "hm@example.com", + "drop_non_existing_label": false, + "file_extension": "", + "ignore_empty_history": false, + "ignore_remote_labels": [ + "CATEGORY_FORUMS", + "CATEGORY_PROMOTIONS", + "CATEGORY_UPDATES", + "CATEGORY_SOCIAL", + "CATEGORY_PERSONAL" + ], + "ignore_tags": [], + "local_trash_tag": "trash", + "remove_local_messages": true, + "replace_slash_with_dot": false, + "timeout": 600 +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/lieer/lieer.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/lieer/lieer.nix new file mode 100644 index 00000000000..5e784746477 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/lieer/lieer.nix @@ -0,0 +1,25 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + imports = [ ../../accounts/email-test-accounts.nix ]; + + config = { + programs.lieer.enable = true; + programs.lieer.package = config.lib.test.mkStubPackage { }; + + accounts.email.accounts."hm@example.com" = { + flavor = "gmail.com"; + lieer.enable = true; + notmuch.enable = true; + }; + + nmt.script = '' + assertFileExists home-files/Mail/hm@example.com/.gmailieer.json + assertFileContent home-files/Mail/hm@example.com/.gmailieer.json ${ + ./lieer-expected.json + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/man/apropos.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/man/apropos.nix new file mode 100644 index 00000000000..a8ec35ead92 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/man/apropos.nix @@ -0,0 +1,22 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.man = { + enable = true; + generateCaches = true; + }; + + nmt.script = '' + assertFileExists home-files/.manpath + + CACHE_DIR=$(cat $TESTED/home-files/.manpath | cut --delimiter=' ' --fields=3) + + if [[ ! -f "$CACHE_DIR/index.bt" ]]; then + fail "Expected man cache files to exist (in $CACHE_DIR) but they were not found." + fi + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/man/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/man/default.nix new file mode 100644 index 00000000000..2e9d340f98d --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/man/default.nix @@ -0,0 +1,4 @@ +{ + man-apropos = ./apropos.nix; + man-no-manpath = ./no-manpath.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/man/no-manpath.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/man/no-manpath.nix new file mode 100644 index 00000000000..1b8cfb40c6e --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/man/no-manpath.nix @@ -0,0 +1,13 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.man = { enable = true; }; + + nmt.script = '' + assertPathNotExists home-files/.manpath + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/mangohud/basic-configuration-mpv.conf b/infra/libkookie/home-manager-stable/tests/modules/programs/mangohud/basic-configuration-mpv.conf new file mode 100644 index 00000000000..9cf2f34ef82 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/mangohud/basic-configuration-mpv.conf @@ -0,0 +1,2 @@ +no_display +output_folder=/home/user/Documents/mpv-mangohud diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/mangohud/basic-configuration.conf b/infra/libkookie/home-manager-stable/tests/modules/programs/mangohud/basic-configuration.conf new file mode 100644 index 00000000000..8ded2dbc01f --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/mangohud/basic-configuration.conf @@ -0,0 +1,13 @@ +cpu_load_change +cpu_load_value +cpu_mhz +cpu_power +cpu_stats +cpu_temp +cpu_text=CPU +fps_limit=30,60 +legacy_layout=false +media_player_name=spotify +media_player_order=title,artist,album +output_folder=/home/user/Documents/mangohud +vsync=0 diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/mangohud/basic-configuration.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/mangohud/basic-configuration.nix new file mode 100644 index 00000000000..6af57d281a6 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/mangohud/basic-configuration.nix @@ -0,0 +1,40 @@ +{ config, pkgs, ... }: + +{ + config = { + programs.mangohud = { + enable = true; + package = config.lib.test.mkStubPackage { }; + settings = { + output_folder = /home/user/Documents/mangohud; + fps_limit = [ 30 60 ]; + vsync = 0; + legacy_layout = false; + cpu_stats = true; + cpu_temp = true; + cpu_power = true; + cpu_text = "CPU"; + cpu_mhz = true; + cpu_load_change = true; + cpu_load_value = true; + media_player_name = "spotify"; + media_player_order = [ "title" "artist" "album" ]; + }; + settingsPerApplication = { + mpv = { + output_folder = /home/user/Documents/mpv-mangohud; + no_display = true; + }; + }; + }; + + nmt.script = '' + assertFileExists home-files/.config/MangoHud/MangoHud.conf + assertFileContent home-files/.config/MangoHud/MangoHud.conf \ + ${./basic-configuration.conf} + assertFileExists home-files/.config/MangoHud/mpv.conf + assertFileContent home-files/.config/MangoHud/mpv.conf \ + ${./basic-configuration-mpv.conf} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/mangohud/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/mangohud/default.nix new file mode 100644 index 00000000000..87db32ed7bd --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/mangohud/default.nix @@ -0,0 +1 @@ +{ mangohud-basic-configuration = ./basic-configuration.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/mbsync/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/mbsync/default.nix new file mode 100644 index 00000000000..9c369fa5018 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/mbsync/default.nix @@ -0,0 +1 @@ +{ mbsync = ./mbsync.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/mbsync/mbsync-expected.conf b/infra/libkookie/home-manager-stable/tests/modules/programs/mbsync/mbsync-expected.conf new file mode 100644 index 00000000000..c1ca921ac1a --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/mbsync/mbsync-expected.conf @@ -0,0 +1,80 @@ +# Generated by Home Manager. + +IMAPAccount hm-account +CertificateFile /etc/ssl/certs/ca-certificates.crt +Host imap.example.org +PassCmd "password-command 2" +SSLType IMAPS +User home.manager.jr + +IMAPStore hm-account-remote +Account hm-account + +MaildirStore hm-account-local +Inbox /home/hm-user/Mail/hm-account/Inbox +Path /home/hm-user/Mail/hm-account/ +SubFolders Verbatim + +Channel emptyChannels-empty1 +Far :hm-account-remote: +Near :hm-account-local: + +Channel emptyChannels-empty2 +Far :hm-account-remote: +Near :hm-account-local: + +Channel hm-account-earlierPatternMatch +Far :hm-account-remote:Label +Near :hm-account-local:SomethingUnderLabel +Pattern ThingUnderLabel !NotThisMaildirThough "[Weird] Label?" + +Channel hm-account-inbox +Far :hm-account-remote:Inbox +Near :hm-account-local:Inbox + +Channel hm-account-patternMatch +Far :hm-account-remote:Label +Near :hm-account-local:SomethingUnderLabel +Pattern ThingUnderLabel !NotThisMaildirThough "[Weird] Label?" + +Channel hm-account-strangeHostBoxName +Far ":hm-account-remote:[Weird]/Label Mess" +Near :hm-account-local:[AnotherWeird]/Label + +Group emptyChannels +Channel emptyChannels-empty1 +Channel emptyChannels-empty2 + +Group hm-account +Channel hm-account-earlierPatternMatch +Channel hm-account-inbox +Channel hm-account-patternMatch +Channel hm-account-strangeHostBoxName + + +IMAPAccount hm@example.com +CertificateFile /etc/ssl/certs/ca-certificates.crt +Host imap.example.com +PassCmd password-command +SSLType IMAPS +User home.manager + +IMAPStore hm@example.com-remote +Account hm@example.com + +MaildirStore hm@example.com-local +Inbox /home/hm-user/Mail/hm@example.com/Inbox +Path /home/hm-user/Mail/hm@example.com/ +SubFolders Verbatim + +Channel inboxes-inbox1 +Far :hm@example.com-remote:Inbox1 +Near :hm@example.com-local:Inboxes + +Channel inboxes-inbox2 +Far :hm@example.com-remote:Inbox2 +Near :hm@example.com-local:Inboxes + +Group inboxes +Channel inboxes-inbox1 +Channel inboxes-inbox2 diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/mbsync/mbsync-master-slave-change.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/mbsync/mbsync-master-slave-change.nix new file mode 100644 index 00000000000..2e877320879 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/mbsync/mbsync-master-slave-change.nix @@ -0,0 +1,95 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + imports = [ ../../accounts/email-test-accounts.nix ]; + + test.asserts.warnings.expected = [ + "mbsync channels no longer use masterPattern. Use farPattern in its place." + "mbsync channels no longer use slavePattern. Use nearPattern in its place." + ]; + + config = { + programs.mbsync = { + enable = true; + # programs.mbsync.groups and + # accounts.email.accounts..mbsync.groups should NOT be used at the + # same time. + # If they are, then the new version will take precendence. + groups.inboxes = { + "hm@example.com" = [ "Inbox1" "Inbox2" ]; + hm-account = [ "Inbox" ]; + }; + }; + + accounts.email.accounts = { + "hm@example.com".mbsync = { + enable = true; + groups.inboxes = { + channels = { + inbox1 = { + farPattern = "Inbox1"; + nearPattern = "Inboxes"; + }; + inbox2 = { + farPattern = "Inbox2"; + nearPattern = "Inboxes"; + }; + }; + }; + }; + + hm-account.mbsync = { + enable = true; + groups.hm-account = { + channels.earlierPatternMatch = { + farPattern = "Label"; + nearPattern = "SomethingUnderLabel"; + patterns = [ + "ThingUnderLabel" + "!NotThisMaildirThough" + ''"[Weird] Label?"'' + ]; + }; + channels.inbox = { + farPattern = "Inbox"; + nearPattern = "Inbox"; + }; + channels.strangeHostBoxName = { + farPattern = "[Weird]/Label Mess"; + nearPattern = "[AnotherWeird]/Label"; + }; + channels.patternMatch = { + farPattern = "Label"; + nearPattern = "SomethingUnderLabel"; + patterns = [ + "ThingUnderLabel" + "!NotThisMaildirThough" + ''"[Weird] Label?"'' + ]; + }; + }; + # No group should be printed. + groups.emptyGroup = { }; + # Group should be printed, but left with default channels. + groups.emptyChannels = { + channels.empty1 = { }; + channels.empty2 = { }; + }; + }; + }; + + test.asserts.warnings.expected = [ + "mbsync channels no longer use masterPattern. use farPattern in its place." + "mbsync channels no longer use slavePattern. Use nearPattern in its place." + ]; + + test.stubs.isync = { }; + + nmt.script = '' + assertFileExists home-files/.mbsyncrc + assertFileContent home-files/.mbsyncrc ${./mbsync-expected.conf} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/mbsync/mbsync.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/mbsync/mbsync.nix new file mode 100644 index 00000000000..7042760a5b9 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/mbsync/mbsync.nix @@ -0,0 +1,85 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + imports = [ ../../accounts/email-test-accounts.nix ]; + + config = { + programs.mbsync = { + enable = true; + # programs.mbsync.groups and + # accounts.email.accounts..mbsync.groups should NOT be used at the + # same time. + # If they are, then the new version will take precendence. + groups.inboxes = { + "hm@example.com" = [ "Inbox1" "Inbox2" ]; + hm-account = [ "Inbox" ]; + }; + }; + + accounts.email.accounts = { + "hm@example.com".mbsync = { + enable = true; + groups.inboxes = { + channels = { + inbox1 = { + farPattern = "Inbox1"; + nearPattern = "Inboxes"; + }; + inbox2 = { + farPattern = "Inbox2"; + nearPattern = "Inboxes"; + }; + }; + }; + }; + + hm-account.mbsync = { + enable = true; + groups.hm-account = { + channels.earlierPatternMatch = { + farPattern = "Label"; + nearPattern = "SomethingUnderLabel"; + patterns = [ + "ThingUnderLabel" + "!NotThisMaildirThough" + ''"[Weird] Label?"'' + ]; + }; + channels.inbox = { + farPattern = "Inbox"; + nearPattern = "Inbox"; + }; + channels.strangeHostBoxName = { + farPattern = "[Weird]/Label Mess"; + nearPattern = "[AnotherWeird]/Label"; + }; + channels.patternMatch = { + farPattern = "Label"; + nearPattern = "SomethingUnderLabel"; + patterns = [ + "ThingUnderLabel" + "!NotThisMaildirThough" + ''"[Weird] Label?"'' + ]; + }; + }; + # No group should be printed. + groups.emptyGroup = { }; + # Group should be printed, but left with default channels. + groups.emptyChannels = { + channels.empty1 = { }; + channels.empty2 = { }; + }; + }; + }; + + test.stubs.isync = { }; + + nmt.script = '' + assertFileExists home-files/.mbsyncrc + assertFileContent home-files/.mbsyncrc ${./mbsync-expected.conf} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/mpv/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/mpv/default.nix new file mode 100644 index 00000000000..6e071610f21 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/mpv/default.nix @@ -0,0 +1,5 @@ +{ + # Temporarily commented until fixed for recent changes in Nixpkgs. + # mpv-example-settings = ./mpv-example-settings.nix; + # mpv-invalid-settings = ./mpv-invalid-settings.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/mpv/mpv-example-settings-expected-bindings b/infra/libkookie/home-manager-stable/tests/modules/programs/mpv/mpv-example-settings-expected-bindings new file mode 100644 index 00000000000..7a2ee13b033 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/mpv/mpv-example-settings-expected-bindings @@ -0,0 +1,3 @@ +Alt+0 set window-scale 0.5 +WHEEL_DOWN seek -10 +WHEEL_UP seek 10 \ No newline at end of file diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/mpv/mpv-example-settings-expected-config b/infra/libkookie/home-manager-stable/tests/modules/programs/mpv/mpv-example-settings-expected-config new file mode 100644 index 00000000000..e44239096ad --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/mpv/mpv-example-settings-expected-config @@ -0,0 +1,13 @@ +profile=%6%gpu-hq + +cache-default=%7%4000000 +force-window=%3%yes +ytdl-format=%19%bestvideo+bestaudio + +[fast] +vo=%5%vdpau + +[protocol.dvd] +alang=%2%en +profile-desc=%26%profile for dvd:// streams + diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/mpv/mpv-example-settings.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/mpv/mpv-example-settings.nix new file mode 100644 index 00000000000..9bb53e57d40 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/mpv/mpv-example-settings.nix @@ -0,0 +1,44 @@ +{ config, lib, pkgs, ... }: + +{ + config = { + programs.mpv = { + enable = true; + package = pkgs.mpvDummy; + + bindings = { + WHEEL_UP = "seek 10"; + WHEEL_DOWN = "seek -10"; + "Alt+0" = "set window-scale 0.5"; + }; + + config = { + force-window = true; + ytdl-format = "bestvideo+bestaudio"; + cache-default = 4000000; + }; + + profiles = { + fast = { vo = "vdpau"; }; + "protocol.dvd" = { + profile-desc = "profile for dvd:// streams"; + alang = "en"; + }; + }; + + defaultProfiles = [ "gpu-hq" ]; + }; + + test.stubs.mpvDummy = { }; + + nmt.script = '' + assertFileContent \ + home-files/.config/mpv/mpv.conf \ + ${./mpv-example-settings-expected-config} + assertFileContent \ + home-files/.config/mpv/input.conf \ + ${./mpv-example-settings-expected-bindings} + ''; + }; + +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/mpv/mpv-invalid-settings.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/mpv/mpv-invalid-settings.nix new file mode 100644 index 00000000000..1c4a80c1124 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/mpv/mpv-invalid-settings.nix @@ -0,0 +1,37 @@ +{ config, lib, pkgs, ... }: + +{ + config = { + programs.mpv = { + enable = true; + package = pkgs.mpvDummy; + scripts = [ pkgs.mpvScript ]; + }; + + nixpkgs.overlays = [ + (self: super: { + mpv-unwrapped = pkgs.runCommandLocal "mpv" { + version = "0"; + passthru = { + lua.luaversion = "0"; + luaEnv = "/dummy"; + vapoursynthSupport = false; + }; + } '' + mkdir -p $out/bin $out/Applications/mpv.app/Contents/MacOS + touch $out/bin/{,u}mpv $out/Applications/mpv.app/Contents/MacOS/mpv + chmod 755 $out/bin/{,u}mpv $out/Applications/mpv.app/Contents/MacOS/mpv + ''; + mpvDummy = config.lib.test.mkStubPackage { }; + mpvScript = + pkgs.runCommandLocal "mpvScript" { scriptName = "something"; } + "mkdir $out"; + }) + ]; + + test.asserts.assertions.expected = [ + '' + The programs.mpv "package" option is mutually exclusive with "scripts" option.'' + ]; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/mu/basic-configuration.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/mu/basic-configuration.nix new file mode 100644 index 00000000000..1e1deeead35 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/mu/basic-configuration.nix @@ -0,0 +1,24 @@ +{ ... }: + +{ + imports = [ ../../accounts/email-test-accounts.nix ]; + + accounts.email.accounts = { + "hm@example.com" = { + mu.enable = true; + aliases = [ "foo@example.com" ]; + }; + }; + + programs.mu.enable = true; + + test.stubs.mu = { }; + + nmt.script = '' + assertFileContains activate \ + 'if [[ ! -d "/home/hm-user/.cache/mu" ]]; then' + + assertFileContains activate \ + '$DRY_RUN_CMD mu init --maildir=/home/hm-user/Mail --my-address=hm@example.com --my-address=foo@example.com $VERBOSE_ARG;' + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/mu/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/mu/default.nix new file mode 100644 index 00000000000..bdd8b15605b --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/mu/default.nix @@ -0,0 +1 @@ +{ mu-basic-configuration = ./basic-configuration.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/ncmpcpp-linux/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/ncmpcpp-linux/default.nix new file mode 100644 index 00000000000..b1185c85249 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/ncmpcpp-linux/default.nix @@ -0,0 +1 @@ +{ ncmpcpp-use-mpd-config = ./ncmpcpp-use-mpd-config.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/ncmpcpp-linux/ncmpcpp-use-mpd-config-expected-config b/infra/libkookie/home-manager-stable/tests/modules/programs/ncmpcpp-linux/ncmpcpp-use-mpd-config-expected-config new file mode 100644 index 00000000000..8aa57d08f16 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/ncmpcpp-linux/ncmpcpp-use-mpd-config-expected-config @@ -0,0 +1 @@ +mpd_music_dir=/home/user/music diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/ncmpcpp-linux/ncmpcpp-use-mpd-config.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/ncmpcpp-linux/ncmpcpp-use-mpd-config.nix new file mode 100644 index 00000000000..f977bddecea --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/ncmpcpp-linux/ncmpcpp-use-mpd-config.nix @@ -0,0 +1,23 @@ +{ pkgs, ... }: + +{ + config = { + programs.ncmpcpp.enable = true; + + services.mpd.enable = true; + services.mpd.musicDirectory = "/home/user/music"; + + test.stubs = { + ncmpcpp = { }; + mpd = { }; + }; + + nmt.script = '' + assertFileContent \ + home-files/.config/ncmpcpp/config \ + ${./ncmpcpp-use-mpd-config-expected-config} + + assertPathNotExists home-files/.config/ncmpcpp/bindings + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/ncmpcpp/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/ncmpcpp/default.nix new file mode 100644 index 00000000000..c150b0d8248 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/ncmpcpp/default.nix @@ -0,0 +1,4 @@ +{ + ncmpcpp-empty-settings = ./ncmpcpp-empty-settings.nix; + ncmpcpp-example-settings = ./ncmpcpp-example-settings.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/ncmpcpp/ncmpcpp-empty-settings.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/ncmpcpp/ncmpcpp-empty-settings.nix new file mode 100644 index 00000000000..55436650977 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/ncmpcpp/ncmpcpp-empty-settings.nix @@ -0,0 +1,15 @@ +{ pkgs, ... }: + +{ + config = { + programs.ncmpcpp.enable = true; + + test.stubs.ncmpcpp = { }; + + nmt.script = '' + assertPathNotExists home-files/.config/ncmpcpp/config + + assertPathNotExists home-files/.config/ncmpcpp/bindings + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/ncmpcpp/ncmpcpp-example-settings-expected-bindings b/infra/libkookie/home-manager-stable/tests/modules/programs/ncmpcpp/ncmpcpp-example-settings-expected-bindings new file mode 100644 index 00000000000..a73bd129ffd --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/ncmpcpp/ncmpcpp-example-settings-expected-bindings @@ -0,0 +1,16 @@ +def_key "j" + scroll_down +def_key "k" + scroll_up +def_key "J" + select_item + scroll_down +def_key "K" + select_item + scroll_up +def_key "x" + delete_playlist_items +def_key "x" + delete_browser_items +def_key "x" + delete_stored_playlist diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/ncmpcpp/ncmpcpp-example-settings-expected-config b/infra/libkookie/home-manager-stable/tests/modules/programs/ncmpcpp/ncmpcpp-example-settings-expected-config new file mode 100644 index 00000000000..6aedb6110e4 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/ncmpcpp/ncmpcpp-example-settings-expected-config @@ -0,0 +1,4 @@ +display_volume_level=no +mpd_music_dir=/home/user/music +playlist_disable_highlight_delay=0 +user_interface=alternative diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/ncmpcpp/ncmpcpp-example-settings.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/ncmpcpp/ncmpcpp-example-settings.nix new file mode 100644 index 00000000000..a85ea552ca8 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/ncmpcpp/ncmpcpp-example-settings.nix @@ -0,0 +1,59 @@ +{ pkgs, ... }: + +{ + config = { + programs.ncmpcpp = { + enable = true; + mpdMusicDir = "/home/user/music"; + + settings = { + user_interface = "alternative"; + display_volume_level = false; + playlist_disable_highlight_delay = 0; + }; + + bindings = [ + { + key = "j"; + command = "scroll_down"; + } + { + key = "k"; + command = "scroll_up"; + } + { + key = "J"; + command = [ "select_item" "scroll_down" ]; + } + { + key = "K"; + command = [ "select_item" "scroll_up" ]; + } + { + key = "x"; + command = "delete_playlist_items"; + } + { + key = "x"; + command = "delete_browser_items"; + } + { + key = "x"; + command = "delete_stored_playlist"; + } + ]; + }; + + test.stubs.ncmpcpp = { }; + + nmt.script = '' + assertFileContent \ + home-files/.config/ncmpcpp/config \ + ${./ncmpcpp-example-settings-expected-config} + + assertFileContent \ + home-files/.config/ncmpcpp/bindings \ + ${./ncmpcpp-example-settings-expected-bindings} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/ne/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/ne/default.nix new file mode 100644 index 00000000000..7a1c843d432 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/ne/default.nix @@ -0,0 +1,4 @@ +{ + ne-defprefs = ./defprefs.nix; + ne-passthroughs = ./passthroughs.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/ne/defprefs.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/ne/defprefs.nix new file mode 100644 index 00000000000..64d78d276d7 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/ne/defprefs.nix @@ -0,0 +1,35 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + defpref = '' + defined through defaultPreferences + ''; + + autopref = '' + defined through automaticPreferences + ''; + +in { + config = { + programs.ne = { + enable = true; + defaultPreferences = defpref; + automaticPreferences.".default" = autopref; + }; + + test.stubs.ne = { }; + + nmt = { + description = + "Check that it gracefully handles the case of both defaultPreferences and automaticPreferences.'.default' being set, defaulting to the former."; + script = '' + assertFileExists home-files/.ne/.default#ap + assertFileContent home-files/.ne/.default#ap ${ + builtins.toFile "defpref" defpref + } + ''; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/ne/passthroughs.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/ne/passthroughs.nix new file mode 100644 index 00000000000..f753826f3d0 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/ne/passthroughs.nix @@ -0,0 +1,72 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + # Samples taken from the ne manual. + keybindings = '' + SEQ "\x1b[1;5D" 14A + KEY 14A HELP + ''; + + menus = '' + MENU "File" + ITEM "Open... ^O" Open + ITEM "Close " Close + ITEM "DoIt " Macro DoIt + ''; + + virtualExtensions = '' + sh 1 ^#!\s*/.*\b(bash|sh|ksh|zsh)\s* + csh 1 ^#!\s*/.*\b(csh|tcsh)\s* + pl 1 ^#!\s*/.*\bperl\b + py 1 ^#!\s*/.*\bpython[0-9]*\s* + rb 1 ^#!\s*/.*\bruby\s* + xml 1 ^<\?xml + ''; + + automaticPreferences = { + nix = '' + TAB 0 + TS 2 + ''; + js = '' + TS 4 + ''; + }; + + checkFile = filename: contents: '' + assertFileExists home-files/.ne/${filename} + assertFileContent home-files/.ne/${filename} ${ + builtins.toFile "checkFile" contents + } + ''; + +in { + config = { + programs.ne = { + enable = true; + inherit keybindings; + inherit menus; + inherit virtualExtensions; + inherit automaticPreferences; + }; + + test.stubs.ne = { }; + + nmt = { + description = "Check that configuration files are correctly written"; + script = concatStringsSep "\n" [ + (checkFile ".keys" keybindings) + (checkFile ".extensions" virtualExtensions) + (checkFile ".menus" menus) + + # Generates a check command for each entry in automaticPreferences. + (concatStringsSep "\n" (mapAttrsToList + (extension: contents: checkFile "${extension}#ap" contents) + automaticPreferences)) + ]; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/default.nix new file mode 100644 index 00000000000..8216017c1cc --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/default.nix @@ -0,0 +1,14 @@ +{ + neomutt-simple = ./neomutt.nix; + neomutt-with-msmtp = ./neomutt-with-msmtp.nix; + neomutt-not-primary = ./neomutt-not-primary.nix; + neomutt-with-binds = ./neomutt-with-binds.nix; + neomutt-with-binds-with-warning = ./neomutt-with-binds-with-warning.nix; + neomutt-with-binds-invalid-settings = + ./neomutt-with-binds-invalid-settings.nix; + neomutt-with-gpg = ./neomutt-with-gpg.nix; + neomutt-no-folder-change = ./neomutt-no-folder-change.nix; + neomutt-with-named-mailboxes = ./neomutt-with-named-mailboxes.nix; + neomutt-with-signature = ./neomutt-with-signature.nix; + neomutt-with-signature-command = ./neomutt-with-signature-command.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/hm-example.com-expected b/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/hm-example.com-expected new file mode 100644 index 00000000000..78b756364ac --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/hm-example.com-expected @@ -0,0 +1,38 @@ +# Generated by Home Manager. +set ssl_force_tls = yes +set certificate_file=/etc/ssl/certs/ca-certificates.crt + +# GPG section +set crypt_use_gpgme = yes +set crypt_autosign = no +set crypt_opportunistic_encrypt = no +set pgp_use_gpg_agent = yes +set mbox_type = Maildir +set sort = "threads" + +# MTA section +set smtp_pass="`password-command`" +set smtp_url='smtps://home.manager@smtp.example.com' + + + + + +# MRA section +set folder='/home/hm-user/Mail/hm@example.com' +set from='hm@example.com' +set postponed='+Drafts' +set realname='H. M. Test' +set record='+Sent' +set spoolfile='+Inbox' +set trash='+Trash' + + +# Extra configuration +color status cyan default + + +unset signature +# notmuch section +set nm_default_uri = "notmuch:///home/hm-user/Mail" +virtual-mailboxes "My INBOX" "notmuch://?query=tag:inbox" diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/hm-example.com-gpg-expected.conf b/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/hm-example.com-gpg-expected.conf new file mode 100644 index 00000000000..576064243dc --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/hm-example.com-gpg-expected.conf @@ -0,0 +1,34 @@ +# Generated by Home Manager. +set ssl_force_tls = yes +set certificate_file=/etc/ssl/certs/ca-certificates.crt + +# GPG section +set crypt_use_gpgme = yes +set crypt_autosign = yes +set crypt_opportunistic_encrypt = yes +set pgp_use_gpg_agent = yes +set mbox_type = Maildir +set sort = "threads" + +# MTA section +set smtp_pass="`password-command`" +set smtp_url='smtps://home.manager@smtp.example.com' + + + + + +# MRA section +set folder='/home/hm-user/Mail/hm@example.com' +set from='hm@example.com' +set postponed='+Drafts' +set realname='H. M. Test' +set record='+Sent' +set spoolfile='+Inbox' +set trash='+Trash' + + +# Extra configuration + + +unset signature diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/hm-example.com-msmtp-expected.conf b/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/hm-example.com-msmtp-expected.conf new file mode 100644 index 00000000000..354cc43ee69 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/hm-example.com-msmtp-expected.conf @@ -0,0 +1,34 @@ +# Generated by Home Manager. +set ssl_force_tls = yes +set certificate_file=/etc/ssl/certs/ca-certificates.crt + +# GPG section +set crypt_use_gpgme = yes +set crypt_autosign = no +set crypt_opportunistic_encrypt = no +set pgp_use_gpg_agent = yes +set mbox_type = Maildir +set sort = "threads" + +# MTA section +set sendmail='msmtpq --read-envelope-from --read-recipients' + + + + + +# MRA section +set folder='/home/hm-user/Mail/hm@example.com' +set from='hm@example.com' +set postponed='+Drafts' +set realname='H. M. Test' +set record='+Sent' +set spoolfile='+Inbox' +set trash='+Trash' + + +# Extra configuration +color status cyan default + + +unset signature diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/hm-example.com-no-folder-change-expected.conf b/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/hm-example.com-no-folder-change-expected.conf new file mode 100644 index 00000000000..e5dee06168b --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/hm-example.com-no-folder-change-expected.conf @@ -0,0 +1,32 @@ +# Generated by Home Manager. +set ssl_force_tls = yes +set certificate_file=/etc/ssl/certs/ca-certificates.crt + +# GPG section +set crypt_use_gpgme = yes +set crypt_autosign = no +set crypt_opportunistic_encrypt = no +set pgp_use_gpg_agent = yes +set mbox_type = Maildir +set sort = "threads" + +# MTA section +set sendmail='msmtpq --read-envelope-from --read-recipients' + + + + + +# MRA section +set from='hm@example.com' +set postponed='+Drafts' +set realname='H. M. Test' +set record='+Sent' +set spoolfile='+Inbox' +set trash='+Trash' + + +# Extra configuration + + +unset signature diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/hm-example.com-signature-command-expected b/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/hm-example.com-signature-command-expected new file mode 100644 index 00000000000..dfc8bc39ad8 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/hm-example.com-signature-command-expected @@ -0,0 +1,38 @@ +# Generated by Home Manager. +set ssl_force_tls = yes +set certificate_file=/etc/ssl/certs/ca-certificates.crt + +# GPG section +set crypt_use_gpgme = yes +set crypt_autosign = no +set crypt_opportunistic_encrypt = no +set pgp_use_gpg_agent = yes +set mbox_type = Maildir +set sort = "threads" + +# MTA section +set smtp_pass="`password-command`" +set smtp_url='smtps://home.manager@smtp.example.com' + + + + + +# MRA section +set folder='/home/hm-user/Mail/hm@example.com' +set from='hm@example.com' +set postponed='+Drafts' +set realname='H. M. Test' +set record='+Sent' +set spoolfile='+Inbox' +set trash='+Trash' + + +# Extra configuration +color status cyan default + + +set signature = "/nix/store/00000000000000000000000000000000-signature|" +# notmuch section +set nm_default_uri = "notmuch:///home/hm-user/Mail" +virtual-mailboxes "My INBOX" "notmuch://?query=tag:inbox" diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/hm-example.com-signature-expected b/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/hm-example.com-signature-expected new file mode 100644 index 00000000000..441374a9b8f --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/hm-example.com-signature-expected @@ -0,0 +1,38 @@ +# Generated by Home Manager. +set ssl_force_tls = yes +set certificate_file=/etc/ssl/certs/ca-certificates.crt + +# GPG section +set crypt_use_gpgme = yes +set crypt_autosign = no +set crypt_opportunistic_encrypt = no +set pgp_use_gpg_agent = yes +set mbox_type = Maildir +set sort = "threads" + +# MTA section +set smtp_pass="`password-command`" +set smtp_url='smtps://home.manager@smtp.example.com' + + + + + +# MRA section +set folder='/home/hm-user/Mail/hm@example.com' +set from='hm@example.com' +set postponed='+Drafts' +set realname='H. M. Test' +set record='+Sent' +set spoolfile='+Inbox' +set trash='+Trash' + + +# Extra configuration +color status cyan default + + +set signature = /nix/store/00000000000000000000000000000000-signature.txt +# notmuch section +set nm_default_uri = "notmuch:///home/hm-user/Mail" +virtual-mailboxes "My INBOX" "notmuch://?query=tag:inbox" diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/neomutt-expected.conf b/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/neomutt-expected.conf new file mode 100644 index 00000000000..7c0e5d28a81 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/neomutt-expected.conf @@ -0,0 +1,33 @@ +# Generated by Home Manager. +set header_cache = "/home/hm-user/.cache/neomutt/headers/" +set message_cachedir = "/home/hm-user/.cache/neomutt/messages/" +set editor = "$EDITOR" +set implicit_autoview = yes + +alternative_order text/enriched text/plain text + +set delete = yes + +# Binds + + +# Macros + + + + +# Register accounts +# register account hm@example.com +mailboxes "/home/hm-user/Mail/hm@example.com/Inbox" + +folder-hook /home/hm-user/Mail/hm@example.com/ " \ + source /home/hm-user/.config/neomutt/hm@example.com " + + +# Source primary account +source /home/hm-user/.config/neomutt/hm@example.com + +# Extra configuration + + + diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/neomutt-no-folder-change.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/neomutt-no-folder-change.nix new file mode 100644 index 00000000000..0e874c22861 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/neomutt-no-folder-change.nix @@ -0,0 +1,29 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + imports = [ ../../accounts/email-test-accounts.nix ]; + + config = { + accounts.email.accounts = { + "hm@example.com" = { + msmtp.enable = true; + neomutt.enable = true; + imap.port = 993; + }; + }; + + programs.neomutt.enable = true; + programs.neomutt.changeFolderWhenSourcingAccount = false; + + test.stubs.neomutt = { }; + + nmt.script = '' + assertFileExists home-files/.config/neomutt/hm@example.com + assertFileContent home-files/.config/neomutt/hm@example.com ${ + ./hm-example.com-no-folder-change-expected.conf + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/neomutt-not-primary-expected.conf b/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/neomutt-not-primary-expected.conf new file mode 100644 index 00000000000..4a583a02d66 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/neomutt-not-primary-expected.conf @@ -0,0 +1,33 @@ +# Generated by Home Manager. +set header_cache = "/home/hm-user/.cache/neomutt/headers/" +set message_cachedir = "/home/hm-user/.cache/neomutt/messages/" +set editor = "$EDITOR" +set implicit_autoview = yes + +alternative_order text/enriched text/plain text + +set delete = yes + +# Binds + + +# Macros + + + + +# Register accounts +# register account hm-account +mailboxes "/home/hm-user/Mail/hm-account/Inbox" + +folder-hook /home/hm-user/Mail/hm-account/ " \ + source /home/hm-user/.config/neomutt/hm-account " + + +# Source primary account +source /home/hm-user/.config/neomutt/hm-account + +# Extra configuration + + + diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/neomutt-not-primary.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/neomutt-not-primary.nix new file mode 100644 index 00000000000..ccf5444a99c --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/neomutt-not-primary.nix @@ -0,0 +1,25 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + imports = [ ../../accounts/email-test-accounts.nix ]; + + config = { + accounts.email.accounts = { + "hm@example.com".maildir = null; + hm-account.neomutt.enable = true; + }; + + programs.neomutt.enable = true; + + test.stubs.neomutt = { }; + + nmt.script = '' + assertFileExists home-files/.config/neomutt/neomuttrc + assertFileContent home-files/.config/neomutt/neomuttrc ${ + ./neomutt-not-primary-expected.conf + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/neomutt-with-binds-expected.conf b/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/neomutt-with-binds-expected.conf new file mode 100644 index 00000000000..8b4bb7bce29 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/neomutt-with-binds-expected.conf @@ -0,0 +1,35 @@ +# Generated by Home Manager. +set header_cache = "/home/hm-user/.cache/neomutt/headers/" +set message_cachedir = "/home/hm-user/.cache/neomutt/messages/" +set editor = "$EDITOR" +set implicit_autoview = yes + +alternative_order text/enriched text/plain text + +set delete = yes + +# Binds +bind editor "complete-query" +bind index,pager \Cp "sidebar-prev" + +# Macros +macro index s "?" +macro index,pager c "?^K=" + + + +# Register accounts +# register account hm@example.com +mailboxes "/home/hm-user/Mail/hm@example.com/Inbox" + +folder-hook /home/hm-user/Mail/hm@example.com/ " \ + source /home/hm-user/.config/neomutt/hm@example.com " + + +# Source primary account +source /home/hm-user/.config/neomutt/hm@example.com + +# Extra configuration + + + diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/neomutt-with-binds-invalid-settings.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/neomutt-with-binds-invalid-settings.nix new file mode 100644 index 00000000000..deaf021f7bc --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/neomutt-with-binds-invalid-settings.nix @@ -0,0 +1,27 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.neomutt = { + enable = true; + + binds = [{ + action = "complete-query"; + key = ""; + map = [ ]; + }]; + + macros = [{ + action = "?^K="; + key = "c"; + map = [ ]; + }]; + }; + + test.asserts.assertions.expected = [ + "The 'programs.neomutt.(binds|macros).map' list must contain at least one element." + ]; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/neomutt-with-binds-with-warning.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/neomutt-with-binds-with-warning.nix new file mode 100644 index 00000000000..54012e9dd26 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/neomutt-with-binds-with-warning.nix @@ -0,0 +1,70 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + imports = [ ../../accounts/email-test-accounts.nix ]; + + config = { + accounts.email.accounts = { + "hm@example.com" = { + notmuch.enable = true; + neomutt = { + enable = true; + extraConfig = '' + color status cyan default + ''; + }; + imap.port = 993; + }; + }; + + programs.neomutt = { + enable = true; + vimKeys = false; + + binds = [ + { + action = "complete-query"; + key = ""; + map = "editor"; + } + { + action = "sidebar-prev"; + key = "\\Cp"; + map = [ "index" "pager" ]; + } + ]; + + macros = [ + { + action = "?"; + key = "s"; + map = "index"; + } + { + action = "?^K="; + key = "c"; + map = [ "index" "pager" ]; + } + ]; + }; + + test.stubs.neomutt = { }; + + test.asserts.warnings.expected = [ + "Specifying 'programs.neomutt.(binds|macros).map' as a string is deprecated, use a list of strings instead. See https://github.com/nix-community/home-manager/pull/1885." + ]; + + nmt.script = '' + assertFileExists home-files/.config/neomutt/neomuttrc + assertFileExists home-files/.config/neomutt/hm@example.com + assertFileContent home-files/.config/neomutt/neomuttrc ${ + ./neomutt-with-binds-expected.conf + } + assertFileContent home-files/.config/neomutt/hm@example.com ${ + ./hm-example.com-expected + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/neomutt-with-binds.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/neomutt-with-binds.nix new file mode 100644 index 00000000000..64ebf80f879 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/neomutt-with-binds.nix @@ -0,0 +1,66 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + imports = [ ../../accounts/email-test-accounts.nix ]; + + config = { + accounts.email.accounts = { + "hm@example.com" = { + notmuch.enable = true; + neomutt = { + enable = true; + extraConfig = '' + color status cyan default + ''; + }; + imap.port = 993; + }; + }; + + programs.neomutt = { + enable = true; + vimKeys = false; + + binds = [ + { + action = "complete-query"; + key = ""; + map = [ "editor" ]; + } + { + action = "sidebar-prev"; + key = "\\Cp"; + map = [ "index" "pager" ]; + } + ]; + + macros = [ + { + action = "?"; + key = "s"; + map = [ "index" ]; + } + { + action = "?^K="; + key = "c"; + map = [ "index" "pager" ]; + } + ]; + }; + + test.stubs.neomutt = { }; + + nmt.script = '' + assertFileExists home-files/.config/neomutt/neomuttrc + assertFileExists home-files/.config/neomutt/hm@example.com + assertFileContent home-files/.config/neomutt/neomuttrc ${ + ./neomutt-with-binds-expected.conf + } + assertFileContent home-files/.config/neomutt/hm@example.com ${ + ./hm-example.com-expected + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/neomutt-with-gpg.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/neomutt-with-gpg.nix new file mode 100644 index 00000000000..2eed5358302 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/neomutt-with-gpg.nix @@ -0,0 +1,32 @@ +{ config, lib, pkgs, ... }: +with lib; { + imports = [ ../../accounts/email-test-accounts.nix ]; + + config = { + accounts.email.accounts = { + "hm@example.com" = { + gpg = { + encryptByDefault = true; + signByDefault = true; + }; + neomutt.enable = true; + imap.port = 993; + }; + }; + + programs.neomutt.enable = true; + + test.stubs.neomutt = { }; + + nmt.script = '' + assertFileExists home-files/.config/neomutt/neomuttrc + assertFileExists home-files/.config/neomutt/hm@example.com + assertFileContent home-files/.config/neomutt/neomuttrc ${ + ./neomutt-expected.conf + } + assertFileContent home-files/.config/neomutt/hm@example.com ${ + ./hm-example.com-gpg-expected.conf + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/neomutt-with-msmtp.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/neomutt-with-msmtp.nix new file mode 100644 index 00000000000..48b2197d045 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/neomutt-with-msmtp.nix @@ -0,0 +1,37 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + imports = [ ../../accounts/email-test-accounts.nix ]; + + config = { + accounts.email.accounts = { + "hm@example.com" = { + msmtp.enable = true; + neomutt = { + enable = true; + extraConfig = '' + color status cyan default + ''; + }; + imap.port = 993; + }; + }; + + programs.neomutt.enable = true; + + test.stubs.neomutt = { }; + + nmt.script = '' + assertFileExists home-files/.config/neomutt/neomuttrc + assertFileExists home-files/.config/neomutt/hm@example.com + assertFileContent home-files/.config/neomutt/neomuttrc ${ + ./neomutt-expected.conf + } + assertFileContent home-files/.config/neomutt/hm@example.com ${ + ./hm-example.com-msmtp-expected.conf + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/neomutt-with-named-mailboxes-expected.conf b/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/neomutt-with-named-mailboxes-expected.conf new file mode 100644 index 00000000000..e58660fc765 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/neomutt-with-named-mailboxes-expected.conf @@ -0,0 +1,35 @@ +# Generated by Home Manager. +set header_cache = "/home/hm-user/.cache/neomutt/headers/" +set message_cachedir = "/home/hm-user/.cache/neomutt/messages/" +set editor = "$EDITOR" +set implicit_autoview = yes + +alternative_order text/enriched text/plain text + +set delete = yes + +# Binds + + +# Macros + + + + +# Register accounts +# register account hm@example.com +named-mailboxes "someCustomName" "/home/hm-user/Mail/hm@example.com/Inbox" +mailboxes "/home/hm-user/Mail/hm@example.com/Sent" +named-mailboxes "Spam" "/home/hm-user/Mail/hm@example.com/Junk Email" +mailboxes "/home/hm-user/Mail/hm@example.com/Trash" +folder-hook /home/hm-user/Mail/hm@example.com/ " \ + source /home/hm-user/.config/neomutt/hm@example.com " + + +# Source primary account +source /home/hm-user/.config/neomutt/hm@example.com + +# Extra configuration + + + diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/neomutt-with-named-mailboxes.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/neomutt-with-named-mailboxes.nix new file mode 100644 index 00000000000..fd4fedf013a --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/neomutt-with-named-mailboxes.nix @@ -0,0 +1,49 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + imports = [ ../../accounts/email-test-accounts.nix ]; + + config = { + accounts.email.accounts = { + "hm@example.com" = { + notmuch.enable = true; + neomutt = { + enable = true; + extraConfig = '' + color status cyan default + ''; + mailboxName = "someCustomName"; + extraMailboxes = [ + "Sent" + { + mailbox = "Junk Email"; + name = "Spam"; + } + { mailbox = "Trash"; } + ]; + }; + imap.port = 993; + }; + }; + + programs.neomutt = { + enable = true; + vimKeys = false; + }; + + test.stubs.neomutt = { }; + + nmt.script = '' + assertFileExists home-files/.config/neomutt/neomuttrc + assertFileExists home-files/.config/neomutt/hm@example.com + assertFileContent home-files/.config/neomutt/neomuttrc ${ + ./neomutt-with-named-mailboxes-expected.conf + } + assertFileContent home-files/.config/neomutt/hm@example.com ${ + ./hm-example.com-expected + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/neomutt-with-signature-command.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/neomutt-with-signature-command.nix new file mode 100644 index 00000000000..97c2001f964 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/neomutt-with-signature-command.nix @@ -0,0 +1,45 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + imports = [ ../../accounts/email-test-accounts.nix ]; + + config = { + accounts.email.accounts = { + "hm@example.com" = { + notmuch.enable = true; + neomutt = { + enable = true; + extraConfig = '' + color status cyan default + ''; + }; + imap.port = 993; + signature = { + showSignature = "append"; + command = pkgs.writeScript "signature" "echo This is my signature"; + }; + }; + }; + + programs.neomutt = { + enable = true; + vimKeys = false; + }; + + test.stubs.neomutt = { }; + + nmt.script = '' + assertFileExists home-files/.config/neomutt/neomuttrc + assertFileExists home-files/.config/neomutt/hm@example.com + assertFileContent home-files/.config/neomutt/neomuttrc ${ + ./neomutt-expected.conf + } + expectedSignature=$(normalizeStorePaths "home-files/.config/neomutt/hm@example.com") + assertFileContent "$expectedSignature" ${ + ./hm-example.com-signature-command-expected + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/neomutt-with-signature.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/neomutt-with-signature.nix new file mode 100644 index 00000000000..9461976d3ef --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/neomutt-with-signature.nix @@ -0,0 +1,48 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + imports = [ ../../accounts/email-test-accounts.nix ]; + + config = { + accounts.email.accounts = { + "hm@example.com" = { + notmuch.enable = true; + neomutt = { + enable = true; + extraConfig = '' + color status cyan default + ''; + }; + imap.port = 993; + signature = { + showSignature = "append"; + text = '' + -- + Test Signature + ''; + }; + }; + }; + + programs.neomutt = { + enable = true; + vimKeys = false; + }; + + test.stubs.neomutt = { }; + + nmt.script = '' + assertFileExists home-files/.config/neomutt/neomuttrc + assertFileExists home-files/.config/neomutt/hm@example.com + assertFileContent home-files/.config/neomutt/neomuttrc ${ + ./neomutt-expected.conf + } + expectedSignature=$(normalizeStorePaths "home-files/.config/neomutt/hm@example.com") + assertFileContent "$expectedSignature" ${ + ./hm-example.com-signature-expected + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/neomutt.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/neomutt.nix new file mode 100644 index 00000000000..08c8f5bf3ff --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/neomutt/neomutt.nix @@ -0,0 +1,40 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + imports = [ ../../accounts/email-test-accounts.nix ]; + + config = { + accounts.email.accounts = { + "hm@example.com" = { + notmuch.enable = true; + neomutt = { + enable = true; + extraConfig = '' + color status cyan default + ''; + }; + imap.port = 993; + }; + }; + + programs.neomutt = { + enable = true; + vimKeys = false; + }; + + test.stubs.neomutt = { }; + + nmt.script = '' + assertFileExists home-files/.config/neomutt/neomuttrc + assertFileExists home-files/.config/neomutt/hm@example.com + assertFileContent home-files/.config/neomutt/neomuttrc ${ + ./neomutt-expected.conf + } + assertFileContent home-files/.config/neomutt/hm@example.com ${ + ./hm-example.com-expected + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/neovim/coc-config.expected b/infra/libkookie/home-manager-stable/tests/modules/programs/neovim/coc-config.expected new file mode 100644 index 00000000000..c8c4105eb57 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/neovim/coc-config.expected @@ -0,0 +1,3 @@ +{ + "foo": "bar" +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/neovim/coc-config.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/neovim/coc-config.nix new file mode 100644 index 00000000000..c16514134df --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/neovim/coc-config.nix @@ -0,0 +1,27 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.neovim = { + enable = true; + coc = { + enable = true; + settings = { + # my variable + foo = "bar"; + }; + }; + }; + + nmt.script = '' + cocSettings="$TESTED/home-files/.config/nvim/coc-settings.json" + cocSettingsNormalized="$(normalizeStorePaths "$cocSettings")" + + assertFileExists "$cocSettings" + assertFileContent "$cocSettingsNormalized" "${./coc-config.expected}" + ''; + }; +} + diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/neovim/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/neovim/default.nix new file mode 100644 index 00000000000..8a6c316ea5f --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/neovim/default.nix @@ -0,0 +1,6 @@ +{ + neovim-plugin-config = ./plugin-config.nix; + neovim-coc-config = ./coc-config.nix; + # waiting for a nixpkgs patch + # neovim-no-init = ./no-init.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/neovim/no-init.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/neovim/no-init.nix new file mode 100644 index 00000000000..1156529d3e2 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/neovim/no-init.nix @@ -0,0 +1,22 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.neovim = { + enable = true; + package = pkgs.neovim-unwrapped; + vimAlias = true; + withNodeJs = false; + withPython3 = true; + withRuby = false; + + extraPython3Packages = (ps: with ps; [ jedi pynvim ]); + }; + nmt.script = '' + vimrc="home-files/.config/nvim/init.vim" + assertPathNotExists "$vimrc" + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/neovim/plugin-config.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/neovim/plugin-config.nix new file mode 100644 index 00000000000..5c26abe883d --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/neovim/plugin-config.nix @@ -0,0 +1,35 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.neovim = { + enable = true; + extraConfig = '' + " This should be present in vimrc + ''; + plugins = with pkgs.vimPlugins; [ + vim-nix + { + plugin = vim-commentary; + config = '' + " This should be present too + autocmd FileType c setlocal commentstring=//\ %s + autocmd FileType c setlocal comments=:// + ''; + } + ]; + extraLuaPackages = [ pkgs.lua51Packages.luautf8 ]; + }; + + nmt.script = '' + vimrc="$TESTED/home-files/.config/nvim/init.vim" + vimrcNormalized="$(normalizeStorePaths "$vimrc")" + + assertFileExists "$vimrc" + assertFileContent "$vimrcNormalized" "${./plugin-config.vim}" + ''; + }; +} + diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/neovim/plugin-config.vim b/infra/libkookie/home-manager-stable/tests/modules/programs/neovim/plugin-config.vim new file mode 100644 index 00000000000..89278a0a94c --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/neovim/plugin-config.vim @@ -0,0 +1,10 @@ +set packpath^=/nix/store/00000000000000000000000000000000-vim-pack-dir +set runtimepath^=/nix/store/00000000000000000000000000000000-vim-pack-dir + +" vim-commentary {{{ +" This should be present too +autocmd FileType c setlocal commentstring=//\ %s +autocmd FileType c setlocal comments=:// + +" }}} +" This should be present in vimrc diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/newsboat/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/newsboat/default.nix new file mode 100644 index 00000000000..b40751c0ebd --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/newsboat/default.nix @@ -0,0 +1,5 @@ +{ + newsboat-basics = ./newsboat-basics.nix; + newsboat-basics-2003 = ./newsboat-basics-2003.nix; + newsboat-basics-2105 = ./newsboat-basics-2105.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/newsboat/newsboat-basics-2003.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/newsboat/newsboat-basics-2003.nix new file mode 100644 index 00000000000..26d5f4b3289 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/newsboat/newsboat-basics-2003.nix @@ -0,0 +1,33 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + home.stateVersion = "20.03"; + + programs.newsboat = { + enable = true; + + urls = [ + { + url = "http://example.org/feed.xml"; + tags = [ "tag1" "tag2" ]; + title = "Cool feed"; + } + + { url = "http://example.org/feed2.xml"; } + ]; + + queries = { "foo" = ''rssurl =~ "example.com"''; }; + }; + + test.stubs.newsboat = { }; + + nmt.script = '' + assertFileContent \ + home-files/.newsboat/urls \ + ${./newsboat-basics-urls-2003.txt} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/newsboat/newsboat-basics-2105.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/newsboat/newsboat-basics-2105.nix new file mode 100644 index 00000000000..ec0f337281c --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/newsboat/newsboat-basics-2105.nix @@ -0,0 +1,34 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + home.stateVersion = "21.05"; + + programs.newsboat = { + enable = true; + + urls = [ + { + url = "http://example.org/feed.xml"; + tags = [ "tag1" "tag2" ]; + title = "Cool feed"; + } + + { url = "http://example.org/feed2.xml"; } + ]; + + queries = { "foo" = ''rssurl =~ "example.com"''; }; + }; + + test.stubs.newsboat = { }; + + # The format didn't change since 20.03, just the location. + nmt.script = '' + assertFileContent \ + home-files/.config/newsboat/urls \ + ${./newsboat-basics-urls-2003.txt} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/newsboat/newsboat-basics-urls-2003.txt b/infra/libkookie/home-manager-stable/tests/modules/programs/newsboat/newsboat-basics-urls-2003.txt new file mode 100644 index 00000000000..68f81118053 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/newsboat/newsboat-basics-urls-2003.txt @@ -0,0 +1,3 @@ +"query:foo:rssurl =~ \"example.com\"" +http://example.org/feed.xml "tag1" "tag2" "~Cool feed" +http://example.org/feed2.xml diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/newsboat/newsboat-basics-urls.txt b/infra/libkookie/home-manager-stable/tests/modules/programs/newsboat/newsboat-basics-urls.txt new file mode 100644 index 00000000000..7f084961345 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/newsboat/newsboat-basics-urls.txt @@ -0,0 +1,3 @@ +http://example.org/feed.xml "tag1" "tag2" "~Cool feed" +http://example.org/feed2.xml +"query:foo:rssurl =~ \"example.com\"" diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/newsboat/newsboat-basics.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/newsboat/newsboat-basics.nix new file mode 100644 index 00000000000..fe7f85070b1 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/newsboat/newsboat-basics.nix @@ -0,0 +1,31 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.newsboat = { + enable = true; + + urls = [ + { + url = "http://example.org/feed.xml"; + tags = [ "tag1" "tag2" ]; + title = "Cool feed"; + } + + { url = "http://example.org/feed2.xml"; } + ]; + + queries = { "foo" = ''rssurl =~ "example.com"''; }; + }; + + test.stubs.newsboat = { }; + + nmt.script = '' + assertFileContent \ + home-files/.newsboat/urls \ + ${./newsboat-basics-urls.txt} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/nix-index/assert-on-command-not-found.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/nix-index/assert-on-command-not-found.nix new file mode 100644 index 00000000000..0fa6ee7998a --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/nix-index/assert-on-command-not-found.nix @@ -0,0 +1,34 @@ +{ lib, pkgs, ... }: + +{ + config = { + programs.bash.enable = true; + programs.fish.enable = true; + programs.zsh.enable = true; + + programs.command-not-found.enable = true; + + # Needed to avoid error with dummy fish package. + xdg.dataFile."fish/home-manager_generated_completions".source = + lib.mkForce (builtins.toFile "empty" ""); + + test.stubs = { + zsh = { }; + fish = { }; + }; + + programs.nix-index.enable = true; + + # 'command-not-found' does not have a 'fish' integration + test.asserts.assertions.expected = [ + '' + The 'programs.command-not-found.enable' option is mutually exclusive + with the 'programs.nix-index.enableBashIntegration' option. + '' + '' + The 'programs.command-not-found.enable' option is mutually exclusive + with the 'programs.nix-index.enableZshIntegration' option. + '' + ]; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/nix-index/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/nix-index/default.nix new file mode 100644 index 00000000000..eaebd7311e1 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/nix-index/default.nix @@ -0,0 +1,4 @@ +{ + nix-index-integrations = ./integrations.nix; + nix-index-assert-on-command-not-found = ./assert-on-command-not-found.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/nix-index/integrations.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/nix-index/integrations.nix new file mode 100644 index 00000000000..1ae46df55e2 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/nix-index/integrations.nix @@ -0,0 +1,45 @@ +{ lib, pkgs, ... }: + +let + fishRegex = '' + function __fish_command_not_found_handler --on-event fish_command_not_found + /nix/store/.*command-not-found $argv + end + ''; +in { + config = { + programs.bash.enable = true; + programs.fish.enable = true; + programs.zsh.enable = true; + + # Needed to avoid error with dummy fish package. + xdg.dataFile."fish/home-manager_generated_completions".source = + lib.mkForce (builtins.toFile "empty" ""); + + test.stubs = { + zsh = { }; + fish = { }; + }; + + programs.nix-index.enable = true; + + nmt.script = '' + # Bash integration + assertFileExists home-files/.bashrc + assertFileRegex \ + home-files/.bashrc \ + 'source /nix/store/.*nix-index.*/etc/profile.d/command-not-found.sh' + + # Zsh integration + assertFileExists home-files/.zshrc + assertFileRegex \ + home-files/.zshrc \ + 'source /nix/store/.*nix-index.*/etc/profile.d/command-not-found.sh' + + # Fish integration + assertFileExists home-files/.config/fish/config.fish + assertFileRegex \ + home-files/.config/fish/config.fish '${fishRegex}' + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/nnn/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/nnn/default.nix new file mode 100644 index 00000000000..6ba66beb2ef --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/nnn/default.nix @@ -0,0 +1 @@ +{ nnn = ./nnn.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/nnn/nnn.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/nnn/nnn.nix new file mode 100644 index 00000000000..7a01fd8540f --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/nnn/nnn.nix @@ -0,0 +1,55 @@ +{ config, lib, pkgs, ... }: + +{ + config = { + programs.nnn = { + enable = true; + bookmarks = { + d = "~/Documents"; + D = "~/Downloads"; + p = "~/Pictures"; + v = "~/Videos"; + }; + package = pkgs.nnnDummy; + extraPackages = with pkgs; [ foo bar ]; + plugins = { + src = ./plugins; + mappings = { + c = "fzcd"; + f = "finder"; + v = "imgview"; + }; + }; + }; + + test.stubs = { + nnnDummy.buildScript = '' + runHook preInstall + + mkdir -p "$out/bin" + touch "$out/bin/nnn" + chmod +x "$out/bin/nnn" + + runHook postInstall + ''; + foo = { name = "foo"; }; + bar = { name = "bar"; }; + }; + + nmt = { + description = + "Check if the binary is correctly wrapped and if the symlinks are made"; + script = '' + assertDirectoryExists home-files/.config/nnn/plugins + + for bookmark in 'export NNN_BMS' '~/Downloads' '~/Documents' '~/Pictures' '~/Videos'; do + assertFileRegex home-path/bin/nnn "$bookmark" + done + + for plugin in 'export NNN_PLUG' 'fzcd' 'finder' 'imgview'; do + assertFileRegex home-path/bin/nnn "$plugin" + done + ''; + }; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/nnn/plugins/.keep b/infra/libkookie/home-manager-stable/tests/modules/programs/nnn/plugins/.keep new file mode 100644 index 00000000000..e69de29bb2d diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/nushell/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/nushell/default.nix new file mode 100644 index 00000000000..5b3bfa1a5bf --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/nushell/default.nix @@ -0,0 +1 @@ +{ nushell-settings = ./settings.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/nushell/settings-expected.toml b/infra/libkookie/home-manager-stable/tests/modules/programs/nushell/settings-expected.toml new file mode 100644 index 00000000000..87c5de2500d --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/nushell/settings-expected.toml @@ -0,0 +1,5 @@ +completion_mode = "circular" +edit_mode = "vi" +key_timeout = 10 +no_auto_pivot = true +startup = ["alias la [] { ls -a }", "alias e [msg] { echo $msg }"] diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/nushell/settings.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/nushell/settings.nix new file mode 100644 index 00000000000..7eef0909ca1 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/nushell/settings.nix @@ -0,0 +1,33 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.nushell = { + enable = true; + + settings = mkMerge [ + { + edit_mode = "vi"; + startup = [ "alias la [] { ls -a }" ]; + completion_mode = "circular"; + key_timeout = 10; + } + + { + startup = [ "alias e [msg] { echo $msg }" ]; + no_auto_pivot = true; + } + ]; + }; + + test.stubs.nushell = { }; + + nmt.script = '' + assertFileContent \ + home-files/.config/nu/config.toml \ + ${./settings-expected.toml} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/pandoc/csl.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/pandoc/csl.nix new file mode 100644 index 00000000000..7384ec995ea --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/pandoc/csl.nix @@ -0,0 +1,18 @@ +{ config, ... }: + +{ + programs.pandoc = { + enable = true; + + citationStyles = [ ./example.csl ]; + }; + + test.stubs.pandoc = import ./stub.nix; + + nmt.script = '' + assertFileExists home-files/.local/share/pandoc/csl/example.csl + assertFileContent home-files/.local/share/pandoc/csl/example.csl \ + ${./example.csl} + ''; +} + diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/pandoc/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/pandoc/default.nix new file mode 100644 index 00000000000..d33eff86c28 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/pandoc/default.nix @@ -0,0 +1,5 @@ +{ + pandoc-citation-styles = ./csl.nix; + pandoc-defaults = ./defaults.nix; + pandoc-templates = ./templates.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/pandoc/defaults-expected.json b/infra/libkookie/home-manager-stable/tests/modules/programs/pandoc/defaults-expected.json new file mode 100644 index 00000000000..efffefb2b3b --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/pandoc/defaults-expected.json @@ -0,0 +1,7 @@ +{ + "citeproc": true, + "metadata": { + "author": "John Doe" + }, + "pdf-engine": "xelatex" +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/pandoc/defaults.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/pandoc/defaults.nix new file mode 100644 index 00000000000..e9288657b63 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/pandoc/defaults.nix @@ -0,0 +1,30 @@ +{ config, lib, ... }: + +let cfg = config.programs.pandoc; + +in { + config = lib.mkIf config.test.enableBig { + programs.pandoc = { + enable = true; + + defaults = { + metadata = { author = "John Doe"; }; + pdf-engine = "xelatex"; + citeproc = true; + }; + }; + + nmt.script = '' + assertFileContent ${cfg.defaultsFile} ${./defaults-expected.json} + + # Test that defaults are set by looking at the metadata for an empty file + # (it should contain the author that we set in defaults). + output=$(mktemp) + ${cfg.finalPackage}/bin/pandoc --standalone \ + -f markdown /dev/null \ + -t native -o "$output" + assertFileContent "$output" ${./output-expected} + ''; + }; +} + diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/pandoc/example.csl b/infra/libkookie/home-manager-stable/tests/modules/programs/pandoc/example.csl new file mode 100644 index 00000000000..63f6267014b --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/pandoc/example.csl @@ -0,0 +1,12 @@ + + diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/pandoc/output-expected b/infra/libkookie/home-manager-stable/tests/modules/programs/pandoc/output-expected new file mode 100644 index 00000000000..390e82099c8 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/pandoc/output-expected @@ -0,0 +1,5 @@ +Pandoc + Meta + { unMeta = fromList [ ( "author" , MetaString "John Doe" ) ] + } + [] diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/pandoc/stub.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/pandoc/stub.nix new file mode 100644 index 00000000000..26af1e3ba28 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/pandoc/stub.nix @@ -0,0 +1,10 @@ +{ + name = "pandoc-stub"; + outPath = null; + buildScript = '' + mkdir -p "$out"/bin + pandoc="$out"/bin/pandoc + echo 'Stub to make the wrapper happy' > "$pandoc" + chmod a+x "$pandoc" + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/pandoc/template.latex b/infra/libkookie/home-manager-stable/tests/modules/programs/pandoc/template.latex new file mode 100644 index 00000000000..16d24ec8073 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/pandoc/template.latex @@ -0,0 +1,9 @@ +\documentclass[a4paper]{scrartcl} + +$if(title)$\title{$title$}$endif$ +$if(author)$\author{$for(author)$$author$$sep$ \and $endfor$}$endif$ + +\begin{document} +\maketitle +$body$ +\end{document} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/pandoc/templates.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/pandoc/templates.nix new file mode 100644 index 00000000000..f276381a360 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/pandoc/templates.nix @@ -0,0 +1,18 @@ +{ config, ... }: + +{ + programs.pandoc = { + enable = true; + + templates = { "default.latex" = ./template.latex; }; + }; + + test.stubs.pandoc = import ./stub.nix; + + nmt.script = '' + assertFileExists home-files/.local/share/pandoc/templates/default.latex + assertFileContent home-files/.local/share/pandoc/templates/default.latex \ + ${./template.latex} + ''; +} + diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/pet/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/pet/default.nix new file mode 100644 index 00000000000..a9d811e0b2a --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/pet/default.nix @@ -0,0 +1,5 @@ +{ + pet-snippets = ./snippets.nix; + pet-settings_21_05 = ./settings_21_05.nix; + pet-settings_21_11 = ./settings_21_11.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/pet/settings_21_05.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/pet/settings_21_05.nix new file mode 100644 index 00000000000..cf728548761 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/pet/settings_21_05.nix @@ -0,0 +1,26 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + home.stateVersion = "21.05"; + programs.pet = { + enable = true; + selectcmdPackage = config.lib.test.mkStubPackage { }; + settings.editor = "nvim"; + }; + + test.stubs.pet = { }; + + nmt.script = '' + assertFileContent home-files/.config/pet/config.toml \ + ${ + builtins.toFile "pet-settings.toml" '' + [General] + editor = "nvim" + selectcmd = "fzf" + snippetfile = "/home/hm-user/.config/pet/snippet.toml" + '' + } + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/pet/settings_21_11.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/pet/settings_21_11.nix new file mode 100644 index 00000000000..0b82d1f37d1 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/pet/settings_21_11.nix @@ -0,0 +1,42 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + home.stateVersion = "21.11"; + programs.pet = { + enable = true; + selectcmdPackage = config.lib.test.mkStubPackage { }; + settings = { + General = { + backend = "Gitlab"; + editor = "nvim"; + }; + Gitlab = { + access_token = "1234"; + file_name = "pet-snippets.toml"; + visibility = "public"; + }; + }; + }; + + test.stubs.pet = { }; + + nmt.script = '' + assertFileContent home-files/.config/pet/config.toml \ + ${ + builtins.toFile "pet-settings.toml" '' + [General] + backend = "Gitlab" + editor = "nvim" + selectcmd = "fzf" + snippetfile = "/home/hm-user/.config/pet/snippet.toml" + + [Gitlab] + access_token = "1234" + file_name = "pet-snippets.toml" + visibility = "public" + '' + } + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/pet/snippet.toml b/infra/libkookie/home-manager-stable/tests/modules/programs/pet/snippet.toml new file mode 100644 index 00000000000..a7ad0e27630 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/pet/snippet.toml @@ -0,0 +1,5 @@ +[[snippets]] +command = "git log -p -G " +description = "git: search full history for regex" +output = "" +tag = ["git", "regex"] diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/pet/snippets.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/pet/snippets.nix new file mode 100644 index 00000000000..6713b4f1630 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/pet/snippets.nix @@ -0,0 +1,29 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.pet = { + enable = true; + selectcmdPackage = pkgs.writeScriptBin "pet-cmd" "" // { + outPath = "@pet-cmd@"; + }; + snippets = [{ + description = "git: search full history for regex"; + command = "git log -p -G "; + tag = [ "git" "regex" ]; + }]; + }; + + nixpkgs.overlays = [ + (self: super: { + pet = pkgs.writeScriptBin "pet" "" // { outPath = "@pet@"; }; + }) + ]; + + nmt.script = '' + assertFileContent home-files/.config/pet/snippet.toml ${./snippet.toml} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/powerline-go/bash.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/powerline-go/bash.nix new file mode 100644 index 00000000000..a48e16fe0b0 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/powerline-go/bash.nix @@ -0,0 +1,33 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs = { + bash.enable = true; + + powerline-go = { + enable = true; + newline = true; + modules = [ "nix-shell" ]; + pathAliases = { "\\~/project/foo" = "prj-foo"; }; + settings = { + ignore-repos = [ "/home/me/project1" "/home/me/project2" ]; + }; + }; + }; + + test.stubs.powerline-go = { }; + + nmt.script = '' + assertFileExists home-files/.bashrc + assertFileContains \ + home-files/.bashrc \ + 'PS1=' + assertFileContains \ + home-files/.bashrc \ + '/bin/powerline-go -error $old_exit_status -shell bash -modules nix-shell -newline -path-aliases \~/project/foo=prj-foo -ignore-repos /home/me/project1,/home/me/project2' + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/powerline-go/bashmodulesright.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/powerline-go/bashmodulesright.nix new file mode 100644 index 00000000000..688c0fad7bb --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/powerline-go/bashmodulesright.nix @@ -0,0 +1,34 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs = { + bash.enable = true; + + powerline-go = { + enable = true; + newline = true; + modules = [ "nix-shell" ]; + modulesRight = [ "git" ]; + pathAliases = { "\\~/project/foo" = "prj-foo"; }; + settings = { + ignore-repos = [ "/home/me/project1" "/home/me/project2" ]; + }; + }; + }; + + test.stubs.powerline-go = { }; + + nmt.script = '' + assertFileExists home-files/.bashrc + assertFileContains \ + home-files/.bashrc \ + 'eval' + assertFileContains \ + home-files/.bashrc \ + '/bin/powerline-go -error $old_exit_status -shell bash -eval -modules nix-shell -modules-right git -newline -path-aliases \~/project/foo=prj-foo -ignore-repos /home/me/project1,/home/me/project2' + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/powerline-go/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/powerline-go/default.nix new file mode 100644 index 00000000000..45ab3d2d04e --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/powerline-go/default.nix @@ -0,0 +1,7 @@ +{ + powerline-go-bash = ./bash.nix; + powerline-go-zsh = ./zsh.nix; + powerline-go-fish = ./fish.nix; + powerline-go-bashmodulesright = ./bashmodulesright.nix; + powerline-go-zshmodulesright = ./zshmodulesright.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/powerline-go/fish.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/powerline-go/fish.nix new file mode 100644 index 00000000000..b7891bbfbaf --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/powerline-go/fish.nix @@ -0,0 +1,37 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs = { + fish.enable = true; + + powerline-go = { + enable = true; + newline = true; + modules = [ "nix-shell" ]; + pathAliases = { "\\~/project/foo" = "prj-foo"; }; + settings = { + ignore-repos = [ "/home/me/project1" "/home/me/project2" ]; + }; + }; + }; + + # Needed to avoid error with dummy fish package. + xdg.dataFile."fish/home-manager_generated_completions".source = + mkForce (builtins.toFile "empty" ""); + + test.stubs = { + powerline-go = { }; + fish = { }; + }; + + nmt.script = '' + assertFileExists home-files/.config/fish/config.fish + assertFileContains \ + home-files/.config/fish/config.fish \ + '/bin/powerline-go -error $status -jobs (count (jobs -p)) -modules nix-shell -newline -path-aliases \~/project/foo=prj-foo -ignore-repos /home/me/project1,/home/me/project2' + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/powerline-go/zsh.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/powerline-go/zsh.nix new file mode 100644 index 00000000000..21856e9d137 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/powerline-go/zsh.nix @@ -0,0 +1,36 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs = { + zsh.enable = true; + + powerline-go = { + enable = true; + newline = true; + modules = [ "nix-shell" ]; + pathAliases = { "\\~/project/foo" = "prj-foo"; }; + settings = { + ignore-repos = [ "/home/me/project1" "/home/me/project2" ]; + }; + }; + }; + + test.stubs = { + powerline-go = { }; + zsh = { }; + }; + + nmt.script = '' + assertFileExists home-files/.zshrc + assertFileContains \ + home-files/.zshrc \ + 'PS1=' + assertFileContains \ + home-files/.zshrc \ + '/bin/powerline-go -error $? -shell zsh -modules nix-shell -newline -path-aliases \~/project/foo=prj-foo -ignore-repos /home/me/project1,/home/me/project2' + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/powerline-go/zshmodulesright.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/powerline-go/zshmodulesright.nix new file mode 100644 index 00000000000..ffe2e1d28c2 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/powerline-go/zshmodulesright.nix @@ -0,0 +1,37 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs = { + zsh.enable = true; + + powerline-go = { + enable = true; + newline = true; + modules = [ "nix-shell" ]; + modulesRight = [ "git" ]; + pathAliases = { "\\~/project/foo" = "prj-foo"; }; + settings = { + ignore-repos = [ "/home/me/project1" "/home/me/project2" ]; + }; + }; + }; + + test.stubs = { + powerline-go = { }; + zsh = { }; + }; + + nmt.script = '' + assertFileExists home-files/.zshrc + assertFileContains \ + home-files/.zshrc \ + 'eval' + assertFileContains \ + home-files/.zshrc \ + '/bin/powerline-go -error $? -shell zsh -eval -modules nix-shell -modules-right git -newline -path-aliases \~/project/foo=prj-foo -ignore-repos /home/me/project1,/home/me/project2' + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/pubs/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/pubs/default.nix new file mode 100644 index 00000000000..db68bb1180d --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/pubs/default.nix @@ -0,0 +1 @@ +{ pubs-example-settings = ./pubs-example-settings.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/pubs/pubs-example-settings-expected-pubsrc b/infra/libkookie/home-manager-stable/tests/modules/programs/pubs/pubs-example-settings-expected-pubsrc new file mode 100644 index 00000000000..ba1fa88ff7f --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/pubs/pubs-example-settings-expected-pubsrc @@ -0,0 +1,19 @@ +[main] +pubsdir = ~/.pubs +docsdir = ~/.pubs/doc +doc_add = link +open_cmd = xdg-open + +[plugins] +active = git,alias + +[[alias]] + +[[[la]]] +command = list -a +description = lists papers in lexicographic order + +[[git]] +quiet = True +manual = False +force_color = False diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/pubs/pubs-example-settings.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/pubs/pubs-example-settings.nix new file mode 100644 index 00000000000..59f2280093f --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/pubs/pubs-example-settings.nix @@ -0,0 +1,36 @@ +{ config, lib, pkgs, ... }: + +{ + programs.pubs = { + enable = true; + + extraConfig = '' + [main] + pubsdir = ~/.pubs + docsdir = ~/.pubs/doc + doc_add = link + open_cmd = xdg-open + + [plugins] + active = git,alias + + [[alias]] + + [[[la]]] + command = list -a + description = lists papers in lexicographic order + + [[git]] + quiet = True + manual = False + force_color = False + ''; + }; + + test.stubs.pubs = { }; + + nmt.script = '' + assertFileContent \ + home-files/.pubsrc ${./pubs-example-settings-expected-pubsrc} + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/qutebrowser/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/qutebrowser/default.nix new file mode 100644 index 00000000000..8c23515c0b7 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/qutebrowser/default.nix @@ -0,0 +1,5 @@ +{ + qutebrowser-settings = ./settings.nix; + qutebrowser-keybindings = ./keybindings.nix; + qutebrowser-quickmarks = ./quickmarks.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/qutebrowser/keybindings.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/qutebrowser/keybindings.nix new file mode 100644 index 00000000000..a719d9f7636 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/qutebrowser/keybindings.nix @@ -0,0 +1,41 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.qutebrowser = { + enable = true; + + enableDefaultBindings = false; + + keyBindings = { + normal = { + "" = "spawn mpv {url}"; + ",l" = ''config-cycle spellcheck.languages ["en-GB"] ["en-US"]''; + }; + prompt = { "" = "prompt-yes"; }; + }; + }; + + test.stubs.qutebrowser = { }; + + nmt.script = let + qutebrowserConfig = if pkgs.stdenv.hostPlatform.isDarwin then + ".qutebrowser/config.py" + else + ".config/qutebrowser/config.py"; + in '' + assertFileContent \ + home-files/${qutebrowserConfig} \ + ${ + pkgs.writeText "qutebrowser-expected-config.py" '' + config.load_autoconfig(False) + c.bindings.default = {} + config.bind(",l", "config-cycle spellcheck.languages [\"en-GB\"] [\"en-US\"]", mode="normal") + config.bind("", "spawn mpv {url}", mode="normal") + config.bind("", "prompt-yes", mode="prompt")'' + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/qutebrowser/quickmarks.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/qutebrowser/quickmarks.nix new file mode 100644 index 00000000000..1491a1e67f5 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/qutebrowser/quickmarks.nix @@ -0,0 +1,33 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.qutebrowser = { + enable = true; + + quickmarks = { + nixpkgs = "https://github.com/NixOS/nixpkgs"; + home-manager = "https://github.com/nix-community/home-manager"; + }; + }; + + test.stubs.qutebrowser = { }; + + nmt.script = let + quickmarksFile = if pkgs.stdenv.hostPlatform.isDarwin then + ".qutebrowser/quickmarks" + else + ".config/qutebrowser/quickmarks"; + in '' + assertFileContent \ + home-files/${quickmarksFile} \ + ${ + pkgs.writeText "qutebrowser-expected-quickmarks" '' + home-manager https://github.com/nix-community/home-manager + nixpkgs https://github.com/NixOS/nixpkgs'' + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/qutebrowser/settings.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/qutebrowser/settings.nix new file mode 100644 index 00000000000..dca6ae6f531 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/qutebrowser/settings.nix @@ -0,0 +1,50 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.qutebrowser = { + enable = true; + + settings = { + colors = { + hints = { + bg = "#000000"; + fg = "#ffffff"; + }; + tabs.bar.bg = "#000000"; + }; + spellcheck.languages = [ "en-US" "sv-SE" ]; + tabs.tabs_are_windows = true; + }; + + extraConfig = '' + # Extra qutebrowser configuration. + ''; + }; + + test.stubs.qutebrowser = { }; + + nmt.script = let + qutebrowserConfig = if pkgs.stdenv.hostPlatform.isDarwin then + ".qutebrowser/config.py" + else + ".config/qutebrowser/config.py"; + in '' + assertFileContent \ + home-files/${qutebrowserConfig} \ + ${ + pkgs.writeText "qutebrowser-expected-config.py" '' + config.load_autoconfig(False) + c.colors.hints.bg = "#000000" + c.colors.hints.fg = "#ffffff" + c.colors.tabs.bar.bg = "#000000" + c.spellcheck.languages = ["en-US", "sv-SE"] + c.tabs.tabs_are_windows = True + # Extra qutebrowser configuration. + '' + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/rbw/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/rbw/default.nix new file mode 100644 index 00000000000..99f36f314be --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/rbw/default.nix @@ -0,0 +1,5 @@ +{ + rbw-empty-settings = ./empty-settings.nix; + rbw-simple-settings = ./simple-settings.nix; + rbw-settings = ./settings.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/rbw/empty-settings.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/rbw/empty-settings.nix new file mode 100644 index 00000000000..aa25c876c0a --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/rbw/empty-settings.nix @@ -0,0 +1,18 @@ +{ pkgs, ... }: + +let + inherit (pkgs.stdenv.hostPlatform) isDarwin; + + path = if isDarwin then + "Library/Application Support/rbw/config.json" + else + ".config/rbw/config.json"; +in { + imports = [ ./rbw-stubs.nix ]; + + programs.rbw.enable = true; + + nmt.script = '' + assertPathNotExists home-files/${path} + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/rbw/rbw-stubs.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/rbw/rbw-stubs.nix new file mode 100644 index 00000000000..c48d88be610 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/rbw/rbw-stubs.nix @@ -0,0 +1,16 @@ +{ config, ... }: + +{ + test.stubs.rbw = { }; + + nixpkgs.overlays = [ + (self: super: { + pinentry = { + gnome3 = + config.lib.test.mkStubPackage { outPath = "@pinentry-gnome3@"; }; + gtk2 = config.lib.test.mkStubPackage { outPath = "@pinentry-gtk2@"; }; + flavors = [ "gnome3" "gtk2" ]; + }; + }) + ]; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/rbw/settings.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/rbw/settings.nix new file mode 100644 index 00000000000..8cf9572bb55 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/rbw/settings.nix @@ -0,0 +1,38 @@ +{ pkgs, ... }: + +let + inherit (pkgs.stdenv.hostPlatform) isDarwin; + + path = if isDarwin then + "Library/Application Support/rbw/config.json" + else + ".config/rbw/config.json"; + + expected = pkgs.writeText "rbw-expected.json" '' + { + "base_url": "bitwarden.example.com", + "email": "name@example.com", + "identity_url": "identity.example.com", + "lock_timeout": 300, + "pinentry": "@pinentry-gnome3@/bin/pinentry" + } + ''; +in { + imports = [ ./rbw-stubs.nix ]; + + programs.rbw = { + enable = true; + settings = { + email = "name@example.com"; + base_url = "bitwarden.example.com"; + identity_url = "identity.example.com"; + lock_timeout = 300; + pinentry = "gnome3"; + }; + }; + + nmt.script = '' + assertFileExists home-files/${path} + assertFileContent home-files/${path} '${expected}' + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/rbw/simple-settings.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/rbw/simple-settings.nix new file mode 100644 index 00000000000..becf9fad197 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/rbw/simple-settings.nix @@ -0,0 +1,32 @@ +{ pkgs, ... }: + +let + inherit (pkgs.stdenv.hostPlatform) isDarwin; + + path = if isDarwin then + "Library/Application Support/rbw/config.json" + else + ".config/rbw/config.json"; + + expected = pkgs.writeText "rbw-expected.json" '' + { + "base_url": null, + "email": "name@example.com", + "identity_url": null, + "lock_timeout": 3600, + "pinentry": "@pinentry-gtk2@/bin/pinentry" + } + ''; +in { + imports = [ ./rbw-stubs.nix ]; + + programs.rbw = { + enable = true; + settings = { email = "name@example.com"; }; + }; + + nmt.script = '' + assertFileExists home-files/${path} + assertFileContent home-files/${path} '${expected}' + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/readline/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/readline/default.nix new file mode 100644 index 00000000000..c95745d19cd --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/readline/default.nix @@ -0,0 +1 @@ +{ readline-using-all-options = ./using-all-options.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/readline/using-all-options.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/readline/using-all-options.nix new file mode 100644 index 00000000000..ab851020c2e --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/readline/using-all-options.nix @@ -0,0 +1,31 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.readline = { + enable = true; + + bindings = { "\\C-h" = "backward-kill-word"; }; + + variables = { + bell-style = "audible"; + completion-map-case = true; + completion-prefix-display-length = 2; + }; + + extraConfig = '' + $if mode=emacs + "\e[1~": beginning-of-line + $endif + ''; + }; + + nmt.script = '' + assertFileContent \ + home-files/.inputrc \ + ${./using-all-options.txt} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/readline/using-all-options.txt b/infra/libkookie/home-manager-stable/tests/modules/programs/readline/using-all-options.txt new file mode 100644 index 00000000000..6b4aef51e69 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/readline/using-all-options.txt @@ -0,0 +1,11 @@ +# Generated by Home Manager. + +$include /etc/inputrc +set bell-style audible +set completion-map-case on +set completion-prefix-display-length 2 +"\C-h": backward-kill-word +$if mode=emacs +"\e[1~": beginning-of-line +$endif + diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/rofi-pass/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/rofi-pass/default.nix new file mode 100644 index 00000000000..181aef4e129 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/rofi-pass/default.nix @@ -0,0 +1,4 @@ +{ + rofi-pass-root = ./rofi-pass-root.nix; + rofi-pass-config = ./rofi-pass-config.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/rofi-pass/rofi-pass-config.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/rofi-pass/rofi-pass-config.nix new file mode 100644 index 00000000000..2028e840e82 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/rofi-pass/rofi-pass-config.nix @@ -0,0 +1,36 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.rofi = { + enable = true; + + pass = { + enable = true; + extraConfig = '' + # Extra config for rofi-pass + xdotool_delay=12 + ''; + }; + }; + + test.stubs = { + rofi = { }; + rofi-pass = { }; + }; + + nmt.script = '' + assertFileContent \ + home-files/.config/rofi-pass/config \ + ${ + pkgs.writeText "rofi-pass-expected-config" '' + # Extra config for rofi-pass + xdotool_delay=12 + + '' + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/rofi-pass/rofi-pass-root.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/rofi-pass/rofi-pass-root.nix new file mode 100644 index 00000000000..300e89db909 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/rofi-pass/rofi-pass-root.nix @@ -0,0 +1,31 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.rofi = { + enable = true; + + pass = { + enable = true; + stores = [ "~/.local/share/password-store" ]; + }; + }; + + test.stubs = { + rofi = { }; + rofi-pass = { }; + }; + + nmt.script = '' + assertFileContent \ + home-files/.config/rofi-pass/config \ + ${ + pkgs.writeText "rofi-pass-expected-config" '' + root=~/.local/share/password-store + '' + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/rofi/config-with-deprecated-options.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/rofi/config-with-deprecated-options.nix new file mode 100644 index 00000000000..b77c5ac9cff --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/rofi/config-with-deprecated-options.nix @@ -0,0 +1,17 @@ +{ ... }: + +{ + programs.rofi = { + enable = true; + colors = { }; + }; + + test.stubs.rofi = { }; + test.asserts.assertions.expected = [ + (let offendingFile = toString ./config-with-deprecated-options.nix; + in '' + The option definition `programs.rofi.colors' in `${offendingFile}' no longer has any effect; please remove it. + Please use a Rofi theme instead. + '') + ]; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/rofi/custom-theme-config.rasi b/infra/libkookie/home-manager-stable/tests/modules/programs/rofi/custom-theme-config.rasi new file mode 100644 index 00000000000..6b4d5b8a047 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/rofi/custom-theme-config.rasi @@ -0,0 +1,6 @@ +configuration { +location: 0; +xoffset: 0; +yoffset: 0; +} +@theme "custom" diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/rofi/custom-theme.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/rofi/custom-theme.nix new file mode 100644 index 00000000000..99c9a9896cf --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/rofi/custom-theme.nix @@ -0,0 +1,43 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.rofi = { + enable = true; + + theme = let inherit (config.lib.formats.rasi) mkLiteral; + in { + "@import" = "~/.cache/wal/colors-rofi-dark"; + + "*" = { + background-color = mkLiteral "#000000"; + foreground-color = mkLiteral "rgba ( 250, 251, 252, 100 % )"; + border-color = mkLiteral "#FFFFFF"; + width = 512; + }; + + "#inputbar" = { children = map mkLiteral [ "prompt" "entry" ]; }; + + "#textbox-prompt-colon" = { + expand = false; + str = ":"; + margin = mkLiteral "0px 0.3em 0em 0em"; + text-color = mkLiteral "@foreground-color"; + }; + }; + }; + + test.stubs.rofi = { }; + + nmt.script = '' + assertFileContent \ + home-files/.config/rofi/config.rasi \ + ${./custom-theme-config.rasi} + assertFileContent \ + home-files/.local/share/rofi/themes/custom.rasi \ + ${./custom-theme.rasi} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/rofi/custom-theme.rasi b/infra/libkookie/home-manager-stable/tests/modules/programs/rofi/custom-theme.rasi new file mode 100644 index 00000000000..b479e7b76c2 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/rofi/custom-theme.rasi @@ -0,0 +1,19 @@ +@import "~/.cache/wal/colors-rofi-dark" + +#inputbar { +children: [ prompt,entry ]; +} + +#textbox-prompt-colon { +expand: false; +margin: 0px 0.3em 0em 0em; +str: ":"; +text-color: @foreground-color; +} + +* { +background-color: #000000; +border-color: #FFFFFF; +foreground-color: rgba ( 250, 251, 252, 100 % ); +width: 512; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/rofi/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/rofi/default.nix new file mode 100644 index 00000000000..2f8c0a95f63 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/rofi/default.nix @@ -0,0 +1,5 @@ +{ + rofi-valid-config = ./valid-config.nix; + rofi-custom-theme = ./custom-theme.nix; + rofi-config-with-deprecated-options = ./config-with-deprecated-options.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/rofi/valid-config-expected.rasi b/infra/libkookie/home-manager-stable/tests/modules/programs/rofi/valid-config-expected.rasi new file mode 100644 index 00000000000..d9d4aa0beb0 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/rofi/valid-config-expected.rasi @@ -0,0 +1,11 @@ +configuration { +cycle: false; +font: "Droid Sans Mono 14"; +kb-primary-paste: "Control+V,Shift+Insert"; +kb-secondary-paste: "Control+v,Insert"; +location: 0; +modi: "drun,emoji,ssh"; +terminal: "/some/path"; +xoffset: 0; +yoffset: 0; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/rofi/valid-config.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/rofi/valid-config.nix new file mode 100644 index 00000000000..c581c0efd85 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/rofi/valid-config.nix @@ -0,0 +1,32 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.rofi = { + enable = true; + font = "Droid Sans Mono 14"; + terminal = "/some/path"; + cycle = false; + window = { + background = "background"; + border = "border"; + separator = "separator"; + }; + extraConfig = { + modi = "drun,emoji,ssh"; + kb-primary-paste = "Control+V,Shift+Insert"; + kb-secondary-paste = "Control+v,Insert"; + }; + }; + + test.stubs.rofi = { }; + + nmt.script = '' + assertFileContent \ + home-files/.config/rofi/config.rasi \ + ${./valid-config-expected.rasi} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/sagemath/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/sagemath/default.nix new file mode 100644 index 00000000000..678ba0399fe --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/sagemath/default.nix @@ -0,0 +1 @@ +{ sagemath = ./sagemath.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/sagemath/init-expected.sage b/infra/libkookie/home-manager-stable/tests/modules/programs/sagemath/init-expected.sage new file mode 100644 index 00000000000..0510341776f --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/sagemath/init-expected.sage @@ -0,0 +1 @@ +%colors linux diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/sagemath/sagemath.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/sagemath/sagemath.nix new file mode 100644 index 00000000000..2f30ac502fd --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/sagemath/sagemath.nix @@ -0,0 +1,20 @@ +{ config, ... }: + +{ + programs.sagemath = { + enable = true; + configDir = "${config.xdg.configHome}/sage"; + dataDir = "${config.xdg.dataHome}/sage"; + initScript = '' + %colors linux + ''; + }; + + test.stubs.sage = { }; + + nmt.script = '' + assertFileExists home-files/.config/sage/init.sage + assertFileContent home-files/.config/sage/init.sage \ + ${./init-expected.sage} + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/sbt/credentials.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/sbt/credentials.nix new file mode 100644 index 00000000000..55c3936a168 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/sbt/credentials.nix @@ -0,0 +1,39 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + credentials = [ + { + realm = "Sonatype Nexus Repository Manager"; + host = "example.com"; + user = "user"; + passwordCommand = "echo password"; + } + { + realm = "Sonatype Nexus Repository Manager X"; + host = "v2.example.com"; + user = "user1"; + passwordCommand = "echo password1"; + } + ]; + expectedCredentialsSbt = pkgs.writeText "credentials.sbt" '' + import scala.sys.process._ + credentials += Credentials("Sonatype Nexus Repository Manager", "example.com", "user", "echo password".!!.trim) + credentials += Credentials("Sonatype Nexus Repository Manager X", "v2.example.com", "user1", "echo password1".!!.trim) + ''; + credentialsSbtPath = ".sbt/1.0/credentials.sbt"; +in { + config = { + programs.sbt = { + enable = true; + credentials = credentials; + package = pkgs.writeScriptBin "sbt" ""; + }; + + nmt.script = '' + assertFileExists "home-files/${credentialsSbtPath}" + assertFileContent "home-files/${credentialsSbtPath}" "${expectedCredentialsSbt}" + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/sbt/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/sbt/default.nix new file mode 100644 index 00000000000..59ad89dae73 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/sbt/default.nix @@ -0,0 +1,4 @@ +{ + sbt-plugins = ./plugins.nix; + sbt-credentials = ./credentials.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/sbt/plugins.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/sbt/plugins.nix new file mode 100644 index 00000000000..b413de80e74 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/sbt/plugins.nix @@ -0,0 +1,39 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + dependencyGraph = { + org = "net.virtual-void"; + artifact = "sbt-dependency-graph"; + version = "0.10.0-RC1"; + }; + projectGraph = { + org = "com.dwijnand"; + artifact = "sbt-project-graph"; + version = "0.4.0"; + }; + + plugins = [ dependencyGraph projectGraph ]; + + pluginsSbtPath = ".sbt/1.0/plugins/plugins.sbt"; + + expectedPluginsSbt = pkgs.writeText "plugins.sbt" '' + addSbtPlugin("net.virtual-void" % "sbt-dependency-graph" % "0.10.0-RC1") + addSbtPlugin("com.dwijnand" % "sbt-project-graph" % "0.4.0") + ''; + +in { + config = { + programs.sbt = { + enable = true; + plugins = plugins; + package = pkgs.writeScriptBin "sbt" ""; + }; + + nmt.script = '' + assertFileExists "home-files/${pluginsSbtPath}" + assertFileContent "home-files/${pluginsSbtPath}" "${expectedPluginsSbt}" + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/scmpuff/bash.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/scmpuff/bash.nix new file mode 100644 index 00000000000..ea34373b9c8 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/scmpuff/bash.nix @@ -0,0 +1,15 @@ +{ pkgs, ... }: { + config = { + programs = { + scmpuff.enable = true; + bash.enable = true; + }; + + nmt.script = '' + assertFileExists home-files/.bashrc + assertFileContains \ + home-files/.bashrc \ + 'eval "$(${pkgs.scmpuff}/bin/scmpuff init -s)"' + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/scmpuff/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/scmpuff/default.nix new file mode 100644 index 00000000000..5852c5b69fd --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/scmpuff/default.nix @@ -0,0 +1,7 @@ +{ + scmpuff-bash = ./bash.nix; + scmpuff-no-bash = ./no-bash.nix; + scmpuff-no-shell = ./no-shell.nix; + scmpuff-no-zsh = ./no-zsh.nix; + scmpuff-zsh = ./zsh.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/scmpuff/no-bash.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/scmpuff/no-bash.nix new file mode 100644 index 00000000000..e3852b84a0a --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/scmpuff/no-bash.nix @@ -0,0 +1,15 @@ +{ pkgs, ... }: { + config = { + programs = { + scmpuff = { + enable = true; + enableBashIntegration = false; + }; + bash.enable = true; + }; + + nmt.script = '' + assertFileNotRegex home-files/.bashrc '${pkgs.scmpuff}/bin/scmpuff' + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/scmpuff/no-shell.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/scmpuff/no-shell.nix new file mode 100644 index 00000000000..ddc40773e45 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/scmpuff/no-shell.nix @@ -0,0 +1,20 @@ +{ pkgs, ... }: { + config = { + programs = { + scmpuff = { + enable = true; + enableBashIntegration = false; + enableZshIntegration = false; + }; + bash.enable = true; + zsh.enable = true; + }; + + test.stubs.zsh = { }; + + nmt.script = '' + assertFileNotRegex home-files/.zshrc '${pkgs.scmpuff} init -s' + assertFileNotRegex home-files/.bashrc '${pkgs.scmpuff} init -s' + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/scmpuff/no-zsh.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/scmpuff/no-zsh.nix new file mode 100644 index 00000000000..5854fdd6f64 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/scmpuff/no-zsh.nix @@ -0,0 +1,17 @@ +{ pkgs, ... }: { + config = { + programs = { + scmpuff = { + enable = true; + enableZshIntegration = false; + }; + zsh.enable = true; + }; + + test.stubs.zsh = { }; + + nmt.script = '' + assertFileNotRegex home-files/.zshrc '${pkgs.scmpuff} init -s' + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/scmpuff/zsh.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/scmpuff/zsh.nix new file mode 100644 index 00000000000..d132945f603 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/scmpuff/zsh.nix @@ -0,0 +1,17 @@ +{ pkgs, ... }: { + config = { + programs = { + scmpuff.enable = true; + zsh.enable = true; + }; + + test.stubs.zsh = { }; + + nmt.script = '' + assertFileExists home-files/.zshrc + assertFileContains \ + home-files/.zshrc \ + 'eval "$(${pkgs.scmpuff}/bin/scmpuff init -s)"' + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/sm64ex/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/sm64ex/default.nix new file mode 100644 index 00000000000..699c23f578b --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/sm64ex/default.nix @@ -0,0 +1 @@ +{ sm64ex = import ./settings.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/sm64ex/settings.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/sm64ex/settings.nix new file mode 100644 index 00000000000..04499f1583f --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/sm64ex/settings.nix @@ -0,0 +1,80 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.sm64ex = { + enable = true; + + settings = { + fullscreen = true; + window_x = 0; + window_y = 0; + window_w = 1920; + window_h = 1080; + vsync = 1; + texture_filtering = 1; + master_volume = 127; + music_volume = 127; + sfx_volume = 127; + env_volume = 127; + key_a = [ "0026" "1000" "1103" ]; + key_b = [ "0033" "1002" "1101" ]; + key_start = [ "0039" "1006" "ffff" ]; + key_l = [ "0034" "1007" "1104" ]; + key_r = [ "0036" "100a" "1105" ]; + key_z = [ "0025" "1009" "1102" ]; + key_cup = [ "100b" "ffff" "ffff" ]; + key_cdown = [ "100c" "ffff" "ffff" ]; + key_cleft = [ "100d" "ffff" "ffff" ]; + key_cright = [ "100e" "ffff" "ffff" ]; + key_stickup = [ "0011" "ffff" "ffff" ]; + key_stickdown = [ "001f" "ffff" "ffff" ]; + key_stickleft = [ "001e" "ffff" "ffff" ]; + key_stickright = [ "0020" "ffff" "ffff" ]; + stick_deadzone = 16; + rumble_strength = 10; + skip_intro = 1; + }; + }; + + test.stubs.sm64ex = { }; + + nmt.script = '' + assertFileContent \ + home-files/.local/share/sm64pc/sm64config.txt \ + ${ + pkgs.writeText "sm64ex-expected-settings" '' + env_volume 127 + fullscreen true + key_a 0026 1000 1103 + key_b 0033 1002 1101 + key_cdown 100c ffff ffff + key_cleft 100d ffff ffff + key_cright 100e ffff ffff + key_cup 100b ffff ffff + key_l 0034 1007 1104 + key_r 0036 100a 1105 + key_start 0039 1006 ffff + key_stickdown 001f ffff ffff + key_stickleft 001e ffff ffff + key_stickright 0020 ffff ffff + key_stickup 0011 ffff ffff + key_z 0025 1009 1102 + master_volume 127 + music_volume 127 + rumble_strength 10 + sfx_volume 127 + skip_intro 1 + stick_deadzone 16 + texture_filtering 1 + vsync 1 + window_h 1080 + window_w 1920 + window_x 0 + window_y 0'' + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/ssh/default-config-expected.conf b/infra/libkookie/home-manager-stable/tests/modules/programs/ssh/default-config-expected.conf new file mode 100644 index 00000000000..d205cab1e6e --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/ssh/default-config-expected.conf @@ -0,0 +1,14 @@ + + +Host * + ForwardAgent no + Compression no + ServerAliveInterval 0 + ServerAliveCountMax 3 + HashKnownHosts no + UserKnownHostsFile ~/.ssh/known_hosts + ControlMaster no + ControlPath ~/.ssh/master-%r@%n:%p + ControlPersist no + + diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/ssh/default-config.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/ssh/default-config.nix new file mode 100644 index 00000000000..6d7e5508a2f --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/ssh/default-config.nix @@ -0,0 +1,18 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.ssh = { enable = true; }; + + home.file.assertions.text = builtins.toJSON + (map (a: a.message) (filter (a: !a.assertion) config.assertions)); + + nmt.script = '' + assertFileExists home-files/.ssh/config + assertFileContent home-files/.ssh/config ${./default-config-expected.conf} + assertFileContent home-files/assertions ${./no-assertions.json} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/ssh/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/ssh/default.nix new file mode 100644 index 00000000000..b2f832c91a2 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/ssh/default.nix @@ -0,0 +1,18 @@ +{ + ssh-defaults = ./default-config.nix; + ssh-includes = ./includes.nix; + ssh-match-blocks = ./match-blocks-attrs.nix; + + ssh-forwards-dynamic-valid-bind-no-asserts = + ./forwards-dynamic-valid-bind-no-asserts.nix; + ssh-forwards-dynamic-bind-path-with-port-asserts = + ./forwards-dynamic-bind-path-with-port-asserts.nix; + ssh-forwards-local-bind-path-with-port-asserts = + ./forwards-local-bind-path-with-port-asserts.nix; + ssh-forwards-local-host-path-with-port-asserts = + ./forwards-local-host-path-with-port-asserts.nix; + ssh-forwards-remote-bind-path-with-port-asserts = + ./forwards-remote-bind-path-with-port-asserts.nix; + ssh-forwards-remote-host-path-with-port-asserts = + ./forwards-remote-host-path-with-port-asserts.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/ssh/forwards-dynamic-bind-path-with-port-asserts.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/ssh/forwards-dynamic-bind-path-with-port-asserts.nix new file mode 100644 index 00000000000..e841b5bcdef --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/ssh/forwards-dynamic-bind-path-with-port-asserts.nix @@ -0,0 +1,22 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.ssh = { + enable = true; + matchBlocks = { + dynamicBindPathWithPort = { + dynamicForwards = [{ + # Error: + address = "/run/user/1000/gnupg/S.gpg-agent.extra"; + port = 3000; + }]; + }; + }; + }; + + test.asserts.assertions.expected = [ "Forwarded paths cannot have ports." ]; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/ssh/forwards-dynamic-valid-bind-no-asserts-expected.conf b/infra/libkookie/home-manager-stable/tests/modules/programs/ssh/forwards-dynamic-valid-bind-no-asserts-expected.conf new file mode 100644 index 00000000000..a67a96ca406 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/ssh/forwards-dynamic-valid-bind-no-asserts-expected.conf @@ -0,0 +1,17 @@ +Host dynamicBindAddressWithPort + DynamicForward [127.0.0.1]:3000 +Host dynamicBindPathNoPort + DynamicForward /run/user/1000/gnupg/S.gpg-agent.extra + +Host * + ForwardAgent no + Compression no + ServerAliveInterval 0 + ServerAliveCountMax 3 + HashKnownHosts no + UserKnownHostsFile ~/.ssh/known_hosts + ControlMaster no + ControlPath ~/.ssh/master-%r@%n:%p + ControlPersist no + + diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/ssh/forwards-dynamic-valid-bind-no-asserts.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/ssh/forwards-dynamic-valid-bind-no-asserts.nix new file mode 100644 index 00000000000..d0c3a732256 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/ssh/forwards-dynamic-valid-bind-no-asserts.nix @@ -0,0 +1,38 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.ssh = { + enable = true; + matchBlocks = { + dynamicBindPathNoPort = { + dynamicForwards = [{ + # OK: + address = "/run/user/1000/gnupg/S.gpg-agent.extra"; + }]; + }; + + dynamicBindAddressWithPort = { + dynamicForwards = [{ + # OK: + address = "127.0.0.1"; + port = 3000; + }]; + }; + }; + }; + + home.file.result.text = builtins.toJSON + (map (a: a.message) (filter (a: !a.assertion) config.assertions)); + + nmt.script = '' + assertFileExists home-files/.ssh/config + assertFileContent \ + home-files/.ssh/config \ + ${./forwards-dynamic-valid-bind-no-asserts-expected.conf} + assertFileContent home-files/result ${./no-assertions.json} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/ssh/forwards-local-bind-path-with-port-asserts.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/ssh/forwards-local-bind-path-with-port-asserts.nix new file mode 100644 index 00000000000..e7ac454e882 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/ssh/forwards-local-bind-path-with-port-asserts.nix @@ -0,0 +1,26 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.ssh = { + enable = true; + matchBlocks = { + localBindPathWithPort = { + localForwards = [{ + # OK: + host.address = "127.0.0.1"; + host.port = 3000; + + # Error: + bind.address = "/run/user/1000/gnupg/S.gpg-agent.extra"; + bind.port = 3000; + }]; + }; + }; + }; + + test.asserts.assertions.expected = [ "Forwarded paths cannot have ports." ]; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/ssh/forwards-local-host-path-with-port-asserts.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/ssh/forwards-local-host-path-with-port-asserts.nix new file mode 100644 index 00000000000..890459c8ab9 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/ssh/forwards-local-host-path-with-port-asserts.nix @@ -0,0 +1,26 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.ssh = { + enable = true; + matchBlocks = { + localHostPathWithPort = { + localForwards = [{ + # OK: + bind.address = "127.0.0.1"; + bind.port = 3000; + + # Error: + host.address = "/run/user/1000/gnupg/S.gpg-agent.extra"; + host.port = 3000; + }]; + }; + }; + }; + + test.asserts.assertions.expected = [ "Forwarded paths cannot have ports." ]; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/ssh/forwards-remote-bind-path-with-port-asserts.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/ssh/forwards-remote-bind-path-with-port-asserts.nix new file mode 100644 index 00000000000..ece7d7953a5 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/ssh/forwards-remote-bind-path-with-port-asserts.nix @@ -0,0 +1,26 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.ssh = { + enable = true; + matchBlocks = { + remoteBindPathWithPort = { + remoteForwards = [{ + # OK: + host.address = "127.0.0.1"; + host.port = 3000; + + # Error: + bind.address = "/run/user/1000/gnupg/S.gpg-agent.extra"; + bind.port = 3000; + }]; + }; + }; + }; + + test.asserts.assertions.expected = [ "Forwarded paths cannot have ports." ]; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/ssh/forwards-remote-host-path-with-port-asserts.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/ssh/forwards-remote-host-path-with-port-asserts.nix new file mode 100644 index 00000000000..b1228f4efe4 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/ssh/forwards-remote-host-path-with-port-asserts.nix @@ -0,0 +1,26 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.ssh = { + enable = true; + matchBlocks = { + remoteHostPathWithPort = { + remoteForwards = [{ + # OK: + bind.address = "127.0.0.1"; + bind.port = 3000; + + # Error: + host.address = "/run/user/1000/gnupg/S.gpg-agent.extra"; + host.port = 3000; + }]; + }; + }; + }; + + test.asserts.assertions.expected = [ "Forwarded paths cannot have ports." ]; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/ssh/includes.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/ssh/includes.nix new file mode 100644 index 00000000000..12e2c6df843 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/ssh/includes.nix @@ -0,0 +1,15 @@ +{ config, lib, pkgs, ... }: + +{ + config = { + programs.ssh = { + enable = true; + includes = [ "config.d/*" "other/dir" ]; + }; + + nmt.script = '' + assertFileExists home-files/.ssh/config + assertFileContains home-files/.ssh/config "Include config.d/* other/dir" + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/ssh/match-blocks-attrs-expected.conf b/infra/libkookie/home-manager-stable/tests/modules/programs/ssh/match-blocks-attrs-expected.conf new file mode 100644 index 00000000000..1a197b26f72 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/ssh/match-blocks-attrs-expected.conf @@ -0,0 +1,29 @@ +Host * !github.com + Port 516 + IdentityFile file1 + IdentityFile file2 +Host abc + ProxyJump jump-host +Host xyz + ServerAliveInterval 60 + ServerAliveCountMax 10 + IdentityFile file + LocalForward [localhost]:8080 [10.0.0.1]:80 + RemoteForward [localhost]:8081 [10.0.0.2]:80 + RemoteForward /run/user/1000/gnupg/S.gpg-agent.extra /run/user/1000/gnupg/S.gpg-agent + DynamicForward [localhost]:2839 +Host ordered + Port 1 + +Host * + ForwardAgent no + Compression no + ServerAliveInterval 0 + ServerAliveCountMax 3 + HashKnownHosts no + UserKnownHostsFile ~/.ssh/known_hosts + ControlMaster no + ControlPath ~/.ssh/master-%r@%n:%p + ControlPersist no + + diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/ssh/match-blocks-attrs.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/ssh/match-blocks-attrs.nix new file mode 100644 index 00000000000..eaa20c6e32d --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/ssh/match-blocks-attrs.nix @@ -0,0 +1,58 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.ssh = { + enable = true; + matchBlocks = { + abc = { + identityFile = null; + proxyJump = "jump-host"; + }; + + ordered = hm.dag.entryAfter [ "xyz" ] { port = 1; }; + + xyz = { + identityFile = "file"; + serverAliveInterval = 60; + serverAliveCountMax = 10; + localForwards = [{ + bind.port = 8080; + host.address = "10.0.0.1"; + host.port = 80; + }]; + remoteForwards = [ + { + bind.port = 8081; + host.address = "10.0.0.2"; + host.port = 80; + } + { + bind.address = "/run/user/1000/gnupg/S.gpg-agent.extra"; + host.address = "/run/user/1000/gnupg/S.gpg-agent"; + } + ]; + dynamicForwards = [{ port = 2839; }]; + }; + + "* !github.com" = { + identityFile = [ "file1" "file2" ]; + port = 516; + }; + }; + }; + + home.file.assertions.text = builtins.toJSON + (map (a: a.message) (filter (a: !a.assertion) config.assertions)); + + nmt.script = '' + assertFileExists home-files/.ssh/config + assertFileContent \ + home-files/.ssh/config \ + ${./match-blocks-attrs-expected.conf} + assertFileContent home-files/assertions ${./no-assertions.json} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/ssh/no-assertions.json b/infra/libkookie/home-manager-stable/tests/modules/programs/ssh/no-assertions.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/ssh/no-assertions.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/starship/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/starship/default.nix new file mode 100644 index 00000000000..814aed65874 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/starship/default.nix @@ -0,0 +1 @@ +{ starship-settings = ./settings.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/starship/settings-expected.toml b/infra/libkookie/home-manager-stable/tests/modules/programs/starship/settings-expected.toml new file mode 100644 index 00000000000..ee07a02e6db --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/starship/settings-expected.toml @@ -0,0 +1,28 @@ +add_newline = false +format = "$line_break$package$line_break$character" +scan_timeout = 10 + +[aws] +disabled = true +style = "bold blue" + +[battery] +charging_symbol = "⚡️" + +[[battery.display]] +style = "bold red" +threshold = 10 + +[[battery.display]] +style = "bold yellow" +threshold = 30 + +[character] +error_symbol = "➜" +success_symbol = "➜" + +[memory_usage] +threshold = -1 + +[package] +disabled = true diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/starship/settings.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/starship/settings.nix new file mode 100644 index 00000000000..c3517cae7b2 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/starship/settings.nix @@ -0,0 +1,55 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.starship = { + enable = true; + + settings = mkMerge [ + { + add_newline = false; + format = concatStrings [ + "$line_break" + "$package" + "$line_break" + "$character" + ]; + scan_timeout = 10; + character = { + success_symbol = "➜"; + error_symbol = "➜"; + }; + package.disabled = true; + memory_usage.threshold = -1; + aws.style = "bold blue"; + battery = { + charging_symbol = "⚡️"; + display = [{ + threshold = 10; + style = "bold red"; + }]; + }; + } + + { + aws.disabled = true; + + battery.display = [{ + threshold = 30; + style = "bold yellow"; + }]; + } + ]; + }; + + test.stubs.starship = { }; + + nmt.script = '' + assertFileContent \ + home-files/.config/starship.toml \ + ${./settings-expected.toml} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/taskwarrior/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/taskwarrior/default.nix new file mode 100644 index 00000000000..52377b75a71 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/taskwarrior/default.nix @@ -0,0 +1 @@ +{ taskwarrior = ./taskwarrior.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/taskwarrior/taskwarrior.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/taskwarrior/taskwarrior.nix new file mode 100644 index 00000000000..f21198f5732 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/taskwarrior/taskwarrior.nix @@ -0,0 +1,40 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.taskwarrior = { + enable = true; + colorTheme = "dark-violets-256"; + dataLocation = "/some/data/location"; + config = { + urgency.user.tag.next.coefficient = 42.42; + urgency.blocked.coefficient = -42; + }; + extraConfig = '' + include /my/stuff + urgency.user.tag.test.coefficient=-42.42 + ''; + }; + + test.stubs.taskwarrior = { }; + + nmt.script = '' + assertFileExists home-files/.config/task/home-manager-taskrc + assertFileContent home-files/.config/task/home-manager-taskrc ${ + pkgs.writeText "taskwarrior.home-conf.expected" '' + data.location=/some/data/location + include dark-violets-256.theme + + urgency.blocked.coefficient=-42 + urgency.user.tag.next.coefficient=42.420000 + + include /my/stuff + urgency.user.tag.test.coefficient=-42.42 + + '' + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/terminator/config-file.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/terminator/config-file.nix new file mode 100644 index 00000000000..50b9c42e791 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/terminator/config-file.nix @@ -0,0 +1,24 @@ +{ config, lib, pkgs, ... }: { + config = { + programs.terminator = { + enable = true; + config = { + global_config.borderless = true; + profiles.default.background_color = "#002b36"; + }; + }; + + test.stubs.terminator = { }; + + nmt.script = '' + assertFileContent home-files/.config/terminator/config ${ + pkgs.writeText "expected" '' + [global_config] + borderless = True + [profiles] + [[default]] + background_color = "#002b36"'' + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/terminator/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/terminator/default.nix new file mode 100644 index 00000000000..4d53e534c6e --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/terminator/default.nix @@ -0,0 +1 @@ +{ terminator-config-file = ./config-file.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/texlive/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/texlive/default.nix new file mode 100644 index 00000000000..23bfe2daf0a --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/texlive/default.nix @@ -0,0 +1 @@ +{ texlive-minimal = ./texlive-minimal.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/texlive/texlive-minimal.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/texlive/texlive-minimal.nix new file mode 100644 index 00000000000..1b13936beac --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/texlive/texlive-minimal.nix @@ -0,0 +1,27 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.texlive.enable = true; + + # Set up a minimal mocked texlive package set. + nixpkgs.overlays = [ + (self: super: { + texlive = { + collection-basic = pkgs.writeTextDir "collection-basic" ""; + combine = tpkgs: + pkgs.symlinkJoin { + name = "dummy-texlive-combine"; + paths = attrValues tpkgs; + }; + }; + }) + ]; + + nmt.script = '' + assertFileExists home-path/collection-basic + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/tmux/default-shell.conf b/infra/libkookie/home-manager-stable/tests/modules/programs/tmux/default-shell.conf new file mode 100644 index 00000000000..a3362363075 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/tmux/default-shell.conf @@ -0,0 +1,30 @@ +# ============================================= # +# Start with defaults from the Sensible plugin # +# --------------------------------------------- # +run-shell @sensible_rtp@ +# ============================================= # + +set -g default-terminal "screen" +set -g base-index 0 +setw -g pane-base-index 0 +# We need to set default-shell before calling new-session +set -g default-shell "/usr/bin/myshell" + + + + + +set -g status-keys emacs +set -g mode-keys emacs + + + + + + + +setw -g aggressive-resize off +setw -g clock-mode-style 12 +set -s escape-time 500 +set -g history-limit 2000 + diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/tmux/default-shell.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/tmux/default-shell.nix new file mode 100644 index 00000000000..af05eb0e707 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/tmux/default-shell.nix @@ -0,0 +1,27 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + substituteExpected = path: + pkgs.substituteAll { + src = path; + + sensible_rtp = pkgs.tmuxPlugins.sensible.rtp; + }; + +in { + config = { + programs.tmux = { + enable = true; + shell = "/usr/bin/myshell"; + }; + + nmt.script = '' + assertFileExists home-files/.config/tmux/tmux.conf + assertFileContent home-files/.config/tmux/tmux.conf \ + ${substituteExpected ./default-shell.conf} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/tmux/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/tmux/default.nix new file mode 100644 index 00000000000..be78c2620a4 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/tmux/default.nix @@ -0,0 +1,10 @@ +{ + tmux-emacs-with-plugins = ./emacs-with-plugins.nix; + tmux-not-enabled = ./not-enabled.nix; + tmux-vi-all-true = ./vi-all-true.nix; + tmux-secure-socket-enabled = ./secure-socket-enabled.nix; + tmux-disable-confirmation-prompt = ./disable-confirmation-prompt.nix; + tmux-default-shell = ./default-shell.nix; + tmux-shortcut-without-prefix = ./shortcut-without-prefix.nix; + tmux-prefix = ./prefix.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/tmux/disable-confirmation-prompt.conf b/infra/libkookie/home-manager-stable/tests/modules/programs/tmux/disable-confirmation-prompt.conf new file mode 100644 index 00000000000..e97a94d192a --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/tmux/disable-confirmation-prompt.conf @@ -0,0 +1,30 @@ +# ============================================= # +# Start with defaults from the Sensible plugin # +# --------------------------------------------- # +run-shell @sensible_rtp@ +# ============================================= # + +set -g default-terminal "screen" +set -g base-index 0 +setw -g pane-base-index 0 + + + + + +set -g status-keys emacs +set -g mode-keys emacs + + + + + +bind-key -N "Kill the current window" & kill-window +bind-key -N "Kill the current pane" x kill-pane + + +setw -g aggressive-resize off +setw -g clock-mode-style 12 +set -s escape-time 500 +set -g history-limit 2000 + diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/tmux/disable-confirmation-prompt.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/tmux/disable-confirmation-prompt.nix new file mode 100644 index 00000000000..aec1f66cf50 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/tmux/disable-confirmation-prompt.nix @@ -0,0 +1,26 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.tmux = { + enable = true; + disableConfirmationPrompt = true; + }; + + nixpkgs.overlays = [ + (self: super: { + tmuxPlugins = super.tmuxPlugins // { + sensible = super.tmuxPlugins.sensible // { rtp = "@sensible_rtp@"; }; + }; + }) + ]; + + nmt.script = '' + assertFileExists home-files/.config/tmux/tmux.conf + assertFileContent home-files/.config/tmux/tmux.conf \ + ${./disable-confirmation-prompt.conf} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/tmux/emacs-with-plugins.conf b/infra/libkookie/home-manager-stable/tests/modules/programs/tmux/emacs-with-plugins.conf new file mode 100644 index 00000000000..d0150192524 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/tmux/emacs-with-plugins.conf @@ -0,0 +1,53 @@ +# ============================================= # +# Start with defaults from the Sensible plugin # +# --------------------------------------------- # +run-shell @tmuxplugin_sensible_rtp@ +# ============================================= # + +set -g default-terminal "screen" +set -g base-index 0 +setw -g pane-base-index 0 + +new-session + +bind -N "Split the pane into two, left and right" v split-window -h +bind -N "Split the pane into two, top and bottom" s split-window -v + + +set -g status-keys emacs +set -g mode-keys emacs + + + + + + + +setw -g aggressive-resize on +setw -g clock-mode-style 24 +set -s escape-time 500 +set -g history-limit 2000 + +# ============================================= # +# Load plugins with Home Manager # +# --------------------------------------------- # + +# tmuxplugin-logging +# --------------------- + +run-shell @tmuxplugin_logging_rtp@ + + +# tmuxplugin-prefix-highlight +# --------------------- + +run-shell @tmuxplugin_prefix_highlight_rtp@ + + +# tmuxplugin-fzf-tmux-url +# --------------------- + +run-shell @tmuxplugin_fzf_tmux_url_rtp@ + +# ============================================= # + diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/tmux/emacs-with-plugins.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/tmux/emacs-with-plugins.nix new file mode 100644 index 00000000000..4a0382d8df4 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/tmux/emacs-with-plugins.nix @@ -0,0 +1,51 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.tmux = { + aggressiveResize = true; + clock24 = true; + enable = true; + keyMode = "emacs"; + newSession = true; + reverseSplit = true; + + plugins = with pkgs.tmuxPlugins; [ + logging + prefix-highlight + fzf-tmux-url + ]; + }; + + nixpkgs.overlays = [ + (self: super: { + tmuxPlugins = super.tmuxPlugins // { + fzf-tmux-url = super.tmuxPlugins.fzf-tmux-url // { + rtp = "@tmuxplugin_fzf_tmux_url_rtp@"; + }; + + logging = super.tmuxPlugins.logging // { + rtp = "@tmuxplugin_logging_rtp@"; + }; + + prefix-highlight = super.tmuxPlugins.prefix-highlight // { + rtp = "@tmuxplugin_prefix_highlight_rtp@"; + }; + + sensible = super.tmuxPlugins.sensible // { + rtp = "@tmuxplugin_sensible_rtp@"; + }; + }; + }) + ]; + + nmt.script = '' + assertFileExists home-files/.config/tmux/tmux.conf + assertFileContent home-files/.config/tmux/tmux.conf ${ + ./emacs-with-plugins.conf + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/tmux/not-enabled.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/tmux/not-enabled.nix new file mode 100644 index 00000000000..d5f08b36f77 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/tmux/not-enabled.nix @@ -0,0 +1,13 @@ +{ config, lib, ... }: + +with lib; + +{ + config = { + programs.tmux = { enable = false; }; + + nmt.script = '' + assertPathNotExists home-files/.config/tmux/tmux.conf + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/tmux/prefix.conf b/infra/libkookie/home-manager-stable/tests/modules/programs/tmux/prefix.conf new file mode 100644 index 00000000000..831ec3b0ecd --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/tmux/prefix.conf @@ -0,0 +1,33 @@ +# ============================================= # +# Start with defaults from the Sensible plugin # +# --------------------------------------------- # +run-shell @sensible_rtp@ +# ============================================= # + +set -g default-terminal "screen" +set -g base-index 0 +setw -g pane-base-index 0 + + + + + +set -g status-keys emacs +set -g mode-keys emacs + + + +# rebind main key: C-a +unbind C-b +set -g prefix C-a +bind -N "Send the prefix key through to the application" \ + C-a send-prefix + + + + +setw -g aggressive-resize off +setw -g clock-mode-style 12 +set -s escape-time 500 +set -g history-limit 2000 + diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/tmux/prefix.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/tmux/prefix.nix new file mode 100644 index 00000000000..9f97940e7b9 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/tmux/prefix.nix @@ -0,0 +1,26 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.tmux = { + enable = true; + prefix = "C-a"; + }; + + nixpkgs.overlays = [ + (self: super: { + tmuxPlugins = super.tmuxPlugins // { + sensible = super.tmuxPlugins.sensible // { rtp = "@sensible_rtp@"; }; + }; + }) + ]; + + nmt.script = '' + assertFileExists home-files/.config/tmux/tmux.conf + assertFileContent home-files/.config/tmux/tmux.conf \ + ${./prefix.conf} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/tmux/secure-socket-enabled.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/tmux/secure-socket-enabled.nix new file mode 100644 index 00000000000..ca2de66310d --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/tmux/secure-socket-enabled.nix @@ -0,0 +1,18 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.tmux = { + enable = true; + secureSocket = true; + }; + + nmt.script = '' + assertFileExists home-path/etc/profile.d/hm-session-vars.sh + assertFileContains home-path/etc/profile.d/hm-session-vars.sh \ + 'export TMUX_TMPDIR="''${XDG_RUNTIME_DIR:-"/run/user/\$(id -u)"}"' + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/tmux/shortcut-without-prefix.conf b/infra/libkookie/home-manager-stable/tests/modules/programs/tmux/shortcut-without-prefix.conf new file mode 100644 index 00000000000..4fd89ad242a --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/tmux/shortcut-without-prefix.conf @@ -0,0 +1,34 @@ +# ============================================= # +# Start with defaults from the Sensible plugin # +# --------------------------------------------- # +run-shell @sensible_rtp@ +# ============================================= # + +set -g default-terminal "screen" +set -g base-index 0 +setw -g pane-base-index 0 + + + + + +set -g status-keys emacs +set -g mode-keys emacs + + + +# rebind main key: C-a +unbind C-b +set -g prefix C-a +bind -N "Send the prefix key through to the application" \ + a send-prefix +bind C-a last-window + + + + +setw -g aggressive-resize off +setw -g clock-mode-style 12 +set -s escape-time 500 +set -g history-limit 2000 + diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/tmux/shortcut-without-prefix.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/tmux/shortcut-without-prefix.nix new file mode 100644 index 00000000000..5c294ef97b1 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/tmux/shortcut-without-prefix.nix @@ -0,0 +1,27 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.tmux = { + enable = true; + shortcut = "a"; + prefix = null; + }; + + nixpkgs.overlays = [ + (self: super: { + tmuxPlugins = super.tmuxPlugins // { + sensible = super.tmuxPlugins.sensible // { rtp = "@sensible_rtp@"; }; + }; + }) + ]; + + nmt.script = '' + assertFileExists home-files/.config/tmux/tmux.conf + assertFileContent home-files/.config/tmux/tmux.conf \ + ${./shortcut-without-prefix.conf} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/tmux/vi-all-true.conf b/infra/libkookie/home-manager-stable/tests/modules/programs/tmux/vi-all-true.conf new file mode 100644 index 00000000000..6a6fd611475 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/tmux/vi-all-true.conf @@ -0,0 +1,30 @@ +# ============================================= # +# Start with defaults from the Sensible plugin # +# --------------------------------------------- # +run-shell @sensible_rtp@ +# ============================================= # + +set -g default-terminal "screen" +set -g base-index 0 +setw -g pane-base-index 0 + +new-session + +bind -N "Split the pane into two, left and right" v split-window -h +bind -N "Split the pane into two, top and bottom" s split-window -v + + +set -g status-keys vi +set -g mode-keys vi + + + + + + + +setw -g aggressive-resize on +setw -g clock-mode-style 24 +set -s escape-time 500 +set -g history-limit 2000 + diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/tmux/vi-all-true.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/tmux/vi-all-true.nix new file mode 100644 index 00000000000..8b9cf1a3687 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/tmux/vi-all-true.nix @@ -0,0 +1,29 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.tmux = { + aggressiveResize = true; + clock24 = true; + enable = true; + keyMode = "vi"; + newSession = true; + reverseSplit = true; + }; + + nixpkgs.overlays = [ + (self: super: { + tmuxPlugins = super.tmuxPlugins // { + sensible = super.tmuxPlugins.sensible // { rtp = "@sensible_rtp@"; }; + }; + }) + ]; + + nmt.script = '' + assertFileExists home-files/.config/tmux/tmux.conf + assertFileContent home-files/.config/tmux/tmux.conf ${./vi-all-true.conf} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/topgrade/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/topgrade/default.nix new file mode 100644 index 00000000000..46b0384a079 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/topgrade/default.nix @@ -0,0 +1 @@ +{ topgrade-settings = ./settings.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/topgrade/settings-expected.toml b/infra/libkookie/home-manager-stable/tests/modules/programs/topgrade/settings-expected.toml new file mode 100644 index 00000000000..aeed3d14b0d --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/topgrade/settings-expected.toml @@ -0,0 +1,8 @@ +cleanup = true +disable = ["sdkman", "flutter", "node", "nix", "home_manager"] +remote_topgrade_path = "bin/topgrade" +remote_topgrades = ["backup", "ci"] +set_title = false + +[commands] +"Purge unused APT packages" = "sudo apt autoremove" diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/topgrade/settings.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/topgrade/settings.nix new file mode 100644 index 00000000000..a8f5c6d1059 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/topgrade/settings.nix @@ -0,0 +1,36 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.topgrade = { + enable = true; + + settings = mkMerge [ + { + disable = [ "sdkman" "flutter" "node" "nix" "home_manager" ]; + + remote_topgrades = [ "backup" "ci" ]; + + remote_topgrade_path = "bin/topgrade"; + } + + { + set_title = false; + cleanup = true; + + commands = { "Purge unused APT packages" = "sudo apt autoremove"; }; + } + ]; + }; + + test.stubs.topgrade = { }; + + nmt.script = '' + assertFileContent \ + home-files/.config/topgrade.toml \ + ${./settings-expected.toml} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/vscode/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/vscode/default.nix new file mode 100644 index 00000000000..70f6d2e7060 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/vscode/default.nix @@ -0,0 +1 @@ +{ vscode-keybindings = ./keybindings.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/vscode/keybindings.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/vscode/keybindings.nix new file mode 100644 index 00000000000..57931c43f49 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/vscode/keybindings.nix @@ -0,0 +1,74 @@ +# Test that keybindings.json is created correctly. +{ config, lib, pkgs, ... }: + +with lib; + +let + bindings = [ + { + key = "ctrl+c"; + command = "editor.action.clipboardCopyAction"; + when = "textInputFocus && false"; + } + { + key = "ctrl+c"; + command = "deleteFile"; + when = ""; + } + { + key = "d"; + command = "deleteFile"; + when = "explorerViewletVisible"; + } + { + key = "ctrl+r"; + command = "run"; + args = { command = "echo file"; }; + } + ]; + + targetPath = if pkgs.stdenv.hostPlatform.isDarwin then + "Library/Application Support/Code/User/keybindings.json" + else + ".config/Code/User/keybindings.json"; + + expectedJson = pkgs.writeText "expected.json" '' + [ + { + "command": "editor.action.clipboardCopyAction", + "key": "ctrl+c", + "when": "textInputFocus && false" + }, + { + "command": "deleteFile", + "key": "ctrl+c", + "when": "" + }, + { + "command": "deleteFile", + "key": "d", + "when": "explorerViewletVisible" + }, + { + "args": { + "command": "echo file" + }, + "command": "run", + "key": "ctrl+r" + } + ] + ''; +in { + config = { + programs.vscode = { + enable = true; + keybindings = bindings; + package = pkgs.writeScriptBin "vscode" "" // { pname = "vscode"; }; + }; + + nmt.script = '' + assertFileExists "home-files/${targetPath}" + assertFileContent "home-files/${targetPath}" "${expectedJson}" + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/watson/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/watson/default.nix new file mode 100644 index 00000000000..32df633d44c --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/watson/default.nix @@ -0,0 +1,4 @@ +{ + watson-empty-settings = ./empty-settings.nix; + watson-example-settings = ./example-settings.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/watson/empty-settings.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/watson/empty-settings.nix new file mode 100644 index 00000000000..8e04746655b --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/watson/empty-settings.nix @@ -0,0 +1,19 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + programs.watson = { + enable = true; + package = config.lib.test.mkStubPackage { }; + }; + + nmt.script = let + configDir = if pkgs.stdenv.hostPlatform.isDarwin then + "home-files/Library/Application Support" + else + "home-files/.config"; + in '' + assertPathNotExists ${configDir}/watson/config + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/watson/example-settings-expected.ini b/infra/libkookie/home-manager-stable/tests/modules/programs/watson/example-settings-expected.ini new file mode 100644 index 00000000000..e148b12e4eb --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/watson/example-settings-expected.ini @@ -0,0 +1,14 @@ +[backend] +token=yourapitoken +url=https://api.crick.fr + +[options] +date_format=%Y.%m.%d +log_current=false +pager=true +report_current=false +reverse_log=true +stop_on_restart=false +stop_on_start=true +time_format=%H:%M:%S%z +week_start=monday diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/watson/example-settings.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/watson/example-settings.nix new file mode 100644 index 00000000000..f81f1ac857a --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/watson/example-settings.nix @@ -0,0 +1,40 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + programs.watson = { + enable = true; + package = config.lib.test.mkStubPackage { }; + + settings = { + backend = { + url = "https://api.crick.fr"; + token = "yourapitoken"; + }; + + options = { + stop_on_start = true; + stop_on_restart = false; + date_format = "%Y.%m.%d"; + time_format = "%H:%M:%S%z"; + week_start = "monday"; + log_current = false; + pager = true; + report_current = false; + reverse_log = true; + }; + }; + }; + + nmt.script = let + configDir = if pkgs.stdenv.hostPlatform.isDarwin then + "home-files/Library/Application Support" + else + "home-files/.config"; + in '' + assertFileContent \ + "${configDir}/watson/config" \ + ${./example-settings-expected.ini} + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/waybar/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/waybar/default.nix new file mode 100644 index 00000000000..bcff35bc4a2 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/waybar/default.nix @@ -0,0 +1,8 @@ +{ + waybar-systemd-with-graphical-session-target = + ./systemd-with-graphical-session-target.nix; + waybar-styling = ./styling.nix; + waybar-settings-complex = ./settings-complex.nix; + waybar-settings-with-attrs = ./settings-with-attrs.nix; + waybar-deprecated-modules-option = ./deprecated-modules-option.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/waybar/deprecated-modules-option.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/waybar/deprecated-modules-option.nix new file mode 100644 index 00000000000..b4d730afcf1 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/waybar/deprecated-modules-option.nix @@ -0,0 +1,43 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + home.stateVersion = "22.05"; + + programs.waybar = { + package = config.lib.test.mkStubPackage { outPath = "@waybar@"; }; + enable = true; + settings = [{ + modules-center = [ "test" ]; + modules = { "test" = { }; }; + }]; + }; + + test.asserts.assertions.expected = ['' + The `programs.waybar.settings.[].modules` option has been removed. + It is now possible to declare modules in the configuration without nesting them under the `modules` option. + '']; + + nmt.script = '' + assertPathNotExists home-files/.config/waybar/style.css + assertFileContent \ + home-files/.config/waybar/config \ + ${ + builtins.toFile "waybar-deprecated-modules-option.json" '' + [ + { + "modules-center": [ + "test" + ], + "modules-left": [], + "modules-right": [], + "test": {} + } + ] + '' + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/waybar/settings-complex-expected.json b/infra/libkookie/home-manager-stable/tests/modules/programs/waybar/settings-complex-expected.json new file mode 100644 index 00000000000..87e4f690d05 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/waybar/settings-complex-expected.json @@ -0,0 +1,63 @@ +[ + { + "custom/my-module": { + "exec": "@dummy@/bin/dummy", + "format": "hello from {}" + }, + "height": 30, + "idle_inhibitor": { + "format": "{icon}" + }, + "layer": "top", + "modules-center": [ + "sway/window" + ], + "modules-left": [ + "sway/workspaces", + "sway/mode", + "custom/my-module" + ], + "modules-right": [ + "idle_inhibitor", + "pulseaudio", + "network", + "cpu", + "memory", + "backlight", + "tray", + "battery#bat1", + "battery#bat2", + "clock" + ], + "output": [ + "DP-1" + ], + "position": "top", + "sway/mode": { + "tooltip": false + }, + "sway/window": { + "max-length": 120 + }, + "sway/workspaces": { + "all-outputs": true, + "disable-scroll": true + } + }, + { + "modules-center": [ + "clock" + ], + "modules-left": [ + "sway/mode" + ], + "modules-right": [], + "output": [ + "!DP-1" + ], + "position": "bottom", + "sway/mode": { + "tooltip": true + } + } +] diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/waybar/settings-complex.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/waybar/settings-complex.nix new file mode 100644 index 00000000000..2e205a7df0a --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/waybar/settings-complex.nix @@ -0,0 +1,67 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + home.stateVersion = "21.11"; + + programs.waybar = { + package = config.lib.test.mkStubPackage { outPath = "@waybar@"; }; + enable = true; + settings = [ + { + layer = "top"; + position = "top"; + height = 30; + output = [ "DP-1" ]; + modules-left = [ "sway/workspaces" "sway/mode" "custom/my-module" ]; + modules-center = [ "sway/window" ]; + modules-right = [ + "idle_inhibitor" + "pulseaudio" + "network" + "cpu" + "memory" + "backlight" + "tray" + "battery#bat1" + "battery#bat2" + "clock" + ]; + + modules = { + "sway/workspaces" = { + disable-scroll = true; + all-outputs = true; + }; + "sway/mode" = { tooltip = false; }; + "sway/window" = { max-length = 120; }; + "idle_inhibitor" = { format = "{icon}"; }; + "custom/my-module" = { + format = "hello from {}"; + exec = let + dummyScript = + config.lib.test.mkStubPackage { outPath = "@dummy@"; }; + in "${dummyScript}/bin/dummy"; + }; + }; + } + { + position = "bottom"; + output = [ "!DP-1" ]; + modules-left = [ "sway/mode" ]; + modules-center = [ "clock" ]; + modules = { "sway/mode" = { tooltip = true; }; }; + } + ]; + }; + + nmt.script = '' + assertPathNotExists home-files/.config/waybar/style.css + assertFileContent \ + home-files/.config/waybar/config \ + ${./settings-complex-expected.json} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/waybar/settings-with-attrs.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/waybar/settings-with-attrs.nix new file mode 100644 index 00000000000..ac7e20fac4a --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/waybar/settings-with-attrs.nix @@ -0,0 +1,29 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + home.stateVersion = "21.11"; + + programs.waybar = { + package = config.lib.test.mkStubPackage { outPath = "@waybar@"; }; + enable = true; + settings = let + settingsComplex = (import ./settings-complex.nix { + inherit config lib pkgs; + }).config.programs.waybar.settings; + in { + mainBar = builtins.head settingsComplex; + secondaryBar = builtins.elemAt settingsComplex 1; + }; + }; + + nmt.script = '' + assertPathNotExists home-files/.config/waybar/style.css + assertFileContent \ + home-files/.config/waybar/config \ + ${./settings-complex-expected.json} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/waybar/styling-expected.css b/infra/libkookie/home-manager-stable/tests/modules/programs/waybar/styling-expected.css new file mode 100644 index 00000000000..dc779e58770 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/waybar/styling-expected.css @@ -0,0 +1,23 @@ +* { + border: none; + border-radius: 0; + font-family: Source Code Pro; + font-weight: bold; + color: #abb2bf; + font-size: 18px; + min-height: 0px; +} +window#waybar { + background: #16191C; + color: #aab2bf; +} +#window { + padding: 0 0px; +} +#workspaces button:hover { + box-shadow: inherit; + text-shadow: inherit; + background: #16191C; + border: #16191C; + padding: 0 3px; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/waybar/styling.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/waybar/styling.nix new file mode 100644 index 00000000000..1952c4fbbb6 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/waybar/styling.nix @@ -0,0 +1,46 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + home.stateVersion = "21.11"; + + programs.waybar = { + package = config.lib.test.mkStubPackage { outPath = "@waybar@"; }; + enable = true; + style = '' + * { + border: none; + border-radius: 0; + font-family: Source Code Pro; + font-weight: bold; + color: #abb2bf; + font-size: 18px; + min-height: 0px; + } + window#waybar { + background: #16191C; + color: #aab2bf; + } + #window { + padding: 0 0px; + } + #workspaces button:hover { + box-shadow: inherit; + text-shadow: inherit; + background: #16191C; + border: #16191C; + padding: 0 3px; + } + ''; + }; + + nmt.script = '' + assertPathNotExists home-files/.config/waybar/config + assertFileContent \ + home-files/.config/waybar/style.css \ + ${./styling-expected.css} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/waybar/systemd-with-graphical-session-target.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/waybar/systemd-with-graphical-session-target.nix new file mode 100644 index 00000000000..dc7a620fab3 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/waybar/systemd-with-graphical-session-target.nix @@ -0,0 +1,26 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + home.stateVersion = "21.11"; + + programs.waybar = { + package = config.lib.test.mkStubPackage { outPath = "@waybar@"; }; + enable = true; + systemd.enable = true; + systemd.target = "sway-session.target"; + }; + + nmt.script = '' + assertPathNotExists home-files/.config/waybar/config + assertPathNotExists home-files/.config/waybar/style.css + + serviceFile=$(normalizeStorePaths home-files/.config/systemd/user/waybar.service) + assertFileContent "$serviceFile" ${ + ./systemd-with-graphical-session-target.service + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/waybar/systemd-with-graphical-session-target.service b/infra/libkookie/home-manager-stable/tests/modules/programs/waybar/systemd-with-graphical-session-target.service new file mode 100644 index 00000000000..e1343da8a81 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/waybar/systemd-with-graphical-session-target.service @@ -0,0 +1,14 @@ +[Install] +WantedBy=sway-session.target + +[Service] +ExecReload=/nix/store/00000000000000000000000000000000-coreutils/bin/kill -SIGUSR2 $MAINPID +ExecStart=@waybar@/bin/waybar +KillMode=mixed +Restart=on-failure + +[Unit] +After=graphical-session.target +Description=Highly customizable Wayland bar for Sway and Wlroots based compositors. +Documentation=https://github.com/Alexays/Waybar/wiki +PartOf=graphical-session.target diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/xmobar/basic-configuration.expected b/infra/libkookie/home-manager-stable/tests/modules/programs/xmobar/basic-configuration.expected new file mode 100644 index 00000000000..51b06a7efc4 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/xmobar/basic-configuration.expected @@ -0,0 +1,19 @@ +Config + { font = "Fira Code" + , borderColor = "#d0d0d0" + , border = FullB + , borderWidth = 3 + , bgColor = "#222" + , fgColor = "grey" + , position = TopSize C 99 30 + , commands = + [ Run Cpu ["-t", "cpu: %"] 10 + , Run Network "enp3s0" ["-S", "True", "-t", "eth: /"] 10 + , Run Memory ["-t","mem: %"] 10 + , Run Date "date: %a %d %b %Y %H:%M:%S " "date" 10 + , Run StdinReader + ] + , sepChar = "%" + , alignSep = "}{" + , template = " %StdinReader% | %cpu% | %memory% | %enp3s0% }{%date% " + } diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/xmobar/basic-configuration.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/xmobar/basic-configuration.nix new file mode 100644 index 00000000000..bbd9420eaaa --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/xmobar/basic-configuration.nix @@ -0,0 +1,40 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.xmobar = { + enable = true; + package = config.lib.test.mkStubPackage { }; + extraConfig = '' + Config + { font = "Fira Code" + , borderColor = "#d0d0d0" + , border = FullB + , borderWidth = 3 + , bgColor = "#222" + , fgColor = "grey" + , position = TopSize C 99 30 + , commands = + [ Run Cpu ["-t", "cpu: %"] 10 + , Run Network "enp3s0" ["-S", "True", "-t", "eth: /"] 10 + , Run Memory ["-t","mem: %"] 10 + , Run Date "date: %a %d %b %Y %H:%M:%S " "date" 10 + , Run StdinReader + ] + , sepChar = "%" + , alignSep = "}{" + , template = " %StdinReader% | %cpu% | %memory% | %enp3s0% }{%date% " + } + ''; + }; + + nmt.script = '' + assertFileExists home-files/.config/xmobar/.xmobarrc + assertFileContent \ + home-files/.config/xmobar/.xmobarrc \ + ${./basic-configuration.expected} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/xmobar/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/xmobar/default.nix new file mode 100644 index 00000000000..f1a31489080 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/xmobar/default.nix @@ -0,0 +1 @@ +{ xmobar-basic-configuration = ./basic-configuration.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/zplug/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/zplug/default.nix new file mode 100644 index 00000000000..172f7cd5981 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/zplug/default.nix @@ -0,0 +1 @@ +{ zplug-modules = ./modules.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/zplug/modules.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/zplug/modules.nix new file mode 100644 index 00000000000..7c4abbc425b --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/zplug/modules.nix @@ -0,0 +1,52 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.zsh = { + enable = true; + zplug = { + enable = true; + zplugHome = ~/.customZplugHome; + plugins = [ + { + name = "plugins/git"; + tags = [ "from:oh-my-zsh" ]; + } + { + name = "lib/clipboard"; + tags = [ "from:oh-my-zsh" ''if:"[[ $OSTYPE == *darwin* ]]"'' ]; + } + ]; + }; + }; + + test.stubs = { + zplug = { }; + zsh = { }; + }; + + nmt.script = '' + assertFileContains home-files/.zshrc \ + 'source @zplug@/init.zsh' + + assertFileContains home-files/.zshrc \ + 'zplug "plugins/git", from:oh-my-zsh' + + assertFileContains home-files/.zshrc \ + 'zplug "lib/clipboard", from:oh-my-zsh, if:"[[ $OSTYPE == *darwin* ]]"' + + assertFileContains home-files/.zshrc \ + 'if ! zplug check; then + zplug install + fi' + + assertFileRegex home-files/.zshrc \ + '^zplug load$' + + assertFileContains home-files/.zshrc \ + 'export ZPLUG_HOME=${config.programs.zsh.zplug.zplugHome}' + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/zsh/default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/zsh/default.nix new file mode 100644 index 00000000000..81e0d2d4152 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/zsh/default.nix @@ -0,0 +1,9 @@ +{ + zsh-session-variables = ./session-variables.nix; + zsh-history-path-new-default = ./history-path-new-default.nix; + zsh-history-path-new-custom = ./history-path-new-custom.nix; + zsh-history-path-old-default = ./history-path-old-default.nix; + zsh-history-path-old-custom = ./history-path-old-custom.nix; + zsh-history-ignore-pattern = ./history-ignore-pattern.nix; + zsh-prezto = ./prezto.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/zsh/history-ignore-pattern.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/zsh/history-ignore-pattern.nix new file mode 100644 index 00000000000..68be58fe865 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/zsh/history-ignore-pattern.nix @@ -0,0 +1,20 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + imports = [ + ({ ... }: { config.programs.zsh.history.ignorePatterns = [ "echo *" ]; }) + ({ ... }: { config.programs.zsh.history.ignorePatterns = [ "rm *" ]; }) + ]; + + config = { + programs.zsh.enable = true; + + test.stubs.zsh = { }; + + nmt.script = '' + assertFileContains home-files/.zshrc "HISTORY_IGNORE='(echo *|rm *)'" + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/zsh/history-path-new-custom.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/zsh/history-path-new-custom.nix new file mode 100644 index 00000000000..1a691f1ca6c --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/zsh/history-path-new-custom.nix @@ -0,0 +1,19 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + home.stateVersion = "20.03"; + programs.zsh = { + enable = true; + history.path = "$HOME/some/directory/zsh_history"; + }; + + test.stubs.zsh = { }; + + nmt.script = '' + assertFileRegex home-files/.zshrc '^HISTFILE="$HOME/some/directory/zsh_history"$' + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/zsh/history-path-new-default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/zsh/history-path-new-default.nix new file mode 100644 index 00000000000..06fe88d06ca --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/zsh/history-path-new-default.nix @@ -0,0 +1,16 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + home.stateVersion = "20.03"; + programs.zsh.enable = true; + + test.stubs.zsh = { }; + + nmt.script = '' + assertFileRegex home-files/.zshrc '^HISTFILE="$HOME/.zsh_history"$' + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/zsh/history-path-old-custom.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/zsh/history-path-old-custom.nix new file mode 100644 index 00000000000..42a85d00472 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/zsh/history-path-old-custom.nix @@ -0,0 +1,19 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + home.stateVersion = "19.09"; + programs.zsh = { + enable = true; + history.path = "some/directory/zsh_history"; + }; + + test.stubs.zsh = { }; + + nmt.script = '' + assertFileRegex home-files/.zshrc '^HISTFILE="$HOME/some/directory/zsh_history"$' + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/zsh/history-path-old-default.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/zsh/history-path-old-default.nix new file mode 100644 index 00000000000..490a2715d8f --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/zsh/history-path-old-default.nix @@ -0,0 +1,16 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + home.stateVersion = "19.03"; + programs.zsh.enable = true; + + test.stubs.zsh = { }; + + nmt.script = '' + assertFileRegex home-files/.zshrc '^HISTFILE="$HOME/.zsh_history"$' + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/zsh/prezto.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/zsh/prezto.nix new file mode 100644 index 00000000000..922112ef9e9 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/zsh/prezto.nix @@ -0,0 +1,22 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + programs.zsh.prezto.enable = true; + + test.stubs.zsh-prezto = { + outPath = null; + buildScript = '' + mkdir -p $out/share/zsh-prezto/runcoms + echo '# zprofile' > $out/share/zsh-prezto/runcoms/zprofile + echo '# zlogin' > $out/share/zsh-prezto/runcoms/zlogin + echo '# zlogout' > $out/share/zsh-prezto/runcoms/zlogout + echo '# zshenv' > $out/share/zsh-prezto/runcoms/zshenv + ''; + }; + + nmt.script = '' + assertFileExists home-files/.zpreztorc + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/programs/zsh/session-variables.nix b/infra/libkookie/home-manager-stable/tests/modules/programs/zsh/session-variables.nix new file mode 100644 index 00000000000..f6f795f79c8 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/programs/zsh/session-variables.nix @@ -0,0 +1,24 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + programs.zsh = { + enable = true; + + sessionVariables = { + V1 = "v1"; + V2 = "v2-${config.programs.zsh.sessionVariables.V1}"; + }; + }; + + test.stubs.zsh = { }; + + nmt.script = '' + assertFileExists home-files/.zshenv + assertFileRegex home-files/.zshenv 'export V1="v1"' + assertFileRegex home-files/.zshenv 'export V2="v2-v1"' + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/barrier/basic-configuration.nix b/infra/libkookie/home-manager-stable/tests/modules/services/barrier/basic-configuration.nix new file mode 100644 index 00000000000..03b1beae774 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/barrier/basic-configuration.nix @@ -0,0 +1,19 @@ +{ config, pkgs, ... }: + +{ + config = { + services.barrier.client = { + enable = true; + server = "testServer"; + }; + + test.stubs.barrier = { }; + + nmt.script = '' + clientServiceFile=home-files/.config/systemd/user/barrierc.service + + assertFileExists $clientServiceFile + assertFileRegex $clientServiceFile 'ExecStart=.*/bin/barrierc --enable-crypto -f testServer' + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/barrier/default.nix b/infra/libkookie/home-manager-stable/tests/modules/services/barrier/default.nix new file mode 100644 index 00000000000..d36f79532a6 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/barrier/default.nix @@ -0,0 +1 @@ +{ barrier-basic-configuration = ./basic-configuration.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/devilspie2/config.lua b/infra/libkookie/home-manager-stable/tests/modules/services/devilspie2/config.lua new file mode 100644 index 00000000000..3024d3c316b --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/devilspie2/config.lua @@ -0,0 +1,11 @@ +if (get_window_class() == "Gnome-terminal") then + make_always_on_top(); +end + +if string.match(get_window_name(), "LibreOffice Writer") then + maximize(); +end + +if (get_window_class()=="Org.gnome.Nautilus") then + set_window_geometry(1600,300,900,700); +end diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/devilspie2/configuration.nix b/infra/libkookie/home-manager-stable/tests/modules/services/devilspie2/configuration.nix new file mode 100644 index 00000000000..2072d4d8441 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/devilspie2/configuration.nix @@ -0,0 +1,37 @@ +{ config, pkgs, ... }: { + config = { + services.devilspie2 = { + enable = true; + + config = '' + if (get_window_class() == "Gnome-terminal") then + make_always_on_top(); + end + + if string.match(get_window_name(), "LibreOffice Writer") then + maximize(); + end + + if (get_window_class()=="Org.gnome.Nautilus") then + set_window_geometry(1600,300,900,700); + end + ''; + }; + + test.stubs.devilspie2 = { }; + + nmt.script = '' + configlua=home-files/.config/devilspie2/config.lua + + assertFileExists $configlua + + assertFileContent $configlua ${./config.lua} + + serviceFile=home-files/.config/systemd/user/devilspie2.service + + assertFileExists $serviceFile + + assertFileRegex $serviceFile 'ExecStart=.*/bin/devilspie2' + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/devilspie2/default.nix b/infra/libkookie/home-manager-stable/tests/modules/services/devilspie2/default.nix new file mode 100644 index 00000000000..b62380ee63e --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/devilspie2/default.nix @@ -0,0 +1 @@ +{ devilspie2-configuration = ./configuration.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/dropbox/basic-configuration.nix b/infra/libkookie/home-manager-stable/tests/modules/services/dropbox/basic-configuration.nix new file mode 100644 index 00000000000..9b8a6d651c0 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/dropbox/basic-configuration.nix @@ -0,0 +1,19 @@ +{ config, pkgs, ... }: + +{ + config = { + services.dropbox = { + enable = true; + path = "${config.home.homeDirectory}/dropbox"; + }; + + test.stubs.dropbox-cli = { }; + + nmt.script = '' + serviceFile=home-files/.config/systemd/user/dropbox.service + + assertFileExists $serviceFile + ''; + + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/dropbox/default.nix b/infra/libkookie/home-manager-stable/tests/modules/services/dropbox/default.nix new file mode 100644 index 00000000000..ad519790355 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/dropbox/default.nix @@ -0,0 +1 @@ +{ dropbox-basic-configuration = ./basic-configuration.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/emacs/default.nix b/infra/libkookie/home-manager-stable/tests/modules/services/emacs/default.nix new file mode 100644 index 00000000000..47493207fb2 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/emacs/default.nix @@ -0,0 +1,7 @@ +{ + emacs-service-27 = ./emacs-service-27.nix; + emacs-service-28 = ./emacs-service-28.nix; + emacs-socket-27 = ./emacs-socket-27.nix; + emacs-socket-28 = ./emacs-socket-28.nix; + emacs-default-editor = ./emacs-default-editor.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/emacs/emacs-27-emacsclient.desktop b/infra/libkookie/home-manager-stable/tests/modules/services/emacs/emacs-27-emacsclient.desktop new file mode 100644 index 00000000000..89503c79029 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/emacs/emacs-27-emacsclient.desktop @@ -0,0 +1,12 @@ +[Desktop Entry] +Categories=Development;TextEditor; +Comment=Edit text +Exec=@emacs@/bin/emacsclient -c %F +GenericName=Text Editor +Icon=emacs +Keywords=Text;Editor; +MimeType=text/english;text/plain;text/x-makefile;text/x-c++hdr;text/x-c++src;text/x-chdr;text/x-csrc;text/x-java;text/x-moc;text/x-pascal;text/x-tcl;text/x-tex;application/x-shellscript;text/x-c;text/x-c++; +Name=Emacs Client +StartupWMClass=Emacs +Terminal=false +Type=Application diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/emacs/emacs-28-emacsclient.desktop b/infra/libkookie/home-manager-stable/tests/modules/services/emacs/emacs-28-emacsclient.desktop new file mode 100644 index 00000000000..96b72752550 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/emacs/emacs-28-emacsclient.desktop @@ -0,0 +1,12 @@ +[Desktop Entry] +Categories=Development;TextEditor; +Comment=Edit text +Exec=@emacs@/bin/emacsclient -c %F +GenericName=Text Editor +Icon=emacs +Keywords=Text;Editor; +MimeType=text/english;text/plain;text/x-makefile;text/x-c++hdr;text/x-c++src;text/x-chdr;text/x-csrc;text/x-java;text/x-moc;text/x-pascal;text/x-tcl;text/x-tex;application/x-shellscript;text/x-c;text/x-c++; +Name=Emacs Client +StartupWMClass=Emacsd +Terminal=false +Type=Application diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/emacs/emacs-default-editor.nix b/infra/libkookie/home-manager-stable/tests/modules/services/emacs/emacs-default-editor.nix new file mode 100644 index 00000000000..77897a5b12f --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/emacs/emacs-default-editor.nix @@ -0,0 +1,24 @@ +{ config, lib, pkgs, ... }: + +{ + nixpkgs.overlays = [ + (self: super: { + # Use `cat` instead of `echo` to prevent arguments from being + # interpreted as an option. + emacs = pkgs.writeShellScriptBin "emacsclient" + ''${pkgs.coreutils}/bin/cat <<< "$*"''; + }) + ]; + + services.emacs = { + defaultEditor = true; + enable = true; + }; + + nmt.script = "source ${ + pkgs.substituteAll { + inherit (pkgs) coreutils; + src = ./emacs-default-editor.sh; + } + }"; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/emacs/emacs-default-editor.sh b/infra/libkookie/home-manager-stable/tests/modules/services/emacs/emacs-default-editor.sh new file mode 100644 index 00000000000..b1aafaac198 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/emacs/emacs-default-editor.sh @@ -0,0 +1,18 @@ +set +u +source $TESTED/home-path/etc/profile.d/hm-session-vars.sh +set -u + +check_arguments () { + if [ "$1" != "$2" ]; then + @coreutils@/bin/cat <<- EOF + Expected arguments: + $1 + but got: + $2 + EOF + exit 1 + fi +} + +check_arguments "--create-frame" "$($EDITOR)" +check_arguments "foo bar baz" "$($EDITOR foo bar baz)" diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/emacs/emacs-service-27.nix b/infra/libkookie/home-manager-stable/tests/modules/services/emacs/emacs-service-27.nix new file mode 100644 index 00000000000..6bc99ced46f --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/emacs/emacs-service-27.nix @@ -0,0 +1,38 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + nixpkgs.overlays = [ + (self: super: rec { + emacs = pkgs.writeShellScriptBin "dummy-emacs-27.2" "" // { + outPath = "@emacs@"; + }; + emacsPackagesFor = _: + makeScope super.newScope (_: { emacsWithPackages = _: emacs; }); + }) + ]; + + programs.emacs.enable = true; + services.emacs.enable = true; + services.emacs.client.enable = true; + services.emacs.extraOptions = [ "-f" "exwm-enable" ]; + + nmt.script = '' + assertPathNotExists home-files/.config/systemd/user/emacs.socket + assertFileExists home-files/.config/systemd/user/emacs.service + assertFileExists home-path/share/applications/emacsclient.desktop + + assertFileContent home-files/.config/systemd/user/emacs.service \ + ${ + pkgs.substituteAll { + inherit (pkgs) runtimeShell; + src = ./emacs-service-emacs.service; + } + } + assertFileContent home-path/share/applications/emacsclient.desktop \ + ${./emacs-27-emacsclient.desktop} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/emacs/emacs-service-28.nix b/infra/libkookie/home-manager-stable/tests/modules/services/emacs/emacs-service-28.nix new file mode 100644 index 00000000000..febfe8288f2 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/emacs/emacs-service-28.nix @@ -0,0 +1,38 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + nixpkgs.overlays = [ + (self: super: rec { + emacs = pkgs.writeShellScriptBin "dummy-emacs-28.0.5" "" // { + outPath = "@emacs@"; + }; + emacsPackagesFor = _: + makeScope super.newScope (_: { emacsWithPackages = _: emacs; }); + }) + ]; + + programs.emacs.enable = true; + services.emacs.enable = true; + services.emacs.client.enable = true; + services.emacs.extraOptions = [ "-f" "exwm-enable" ]; + + nmt.script = '' + assertPathNotExists home-files/.config/systemd/user/emacs.socket + assertFileExists home-files/.config/systemd/user/emacs.service + assertFileExists home-path/share/applications/emacsclient.desktop + + assertFileContent home-files/.config/systemd/user/emacs.service \ + ${ + pkgs.substituteAll { + inherit (pkgs) runtimeShell; + src = ./emacs-service-emacs.service; + } + } + assertFileContent home-path/share/applications/emacsclient.desktop \ + ${./emacs-28-emacsclient.desktop} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/emacs/emacs-service-emacs.service b/infra/libkookie/home-manager-stable/tests/modules/services/emacs/emacs-service-emacs.service new file mode 100644 index 00000000000..64120f4c05c --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/emacs/emacs-service-emacs.service @@ -0,0 +1,13 @@ +[Install] +WantedBy=default.target + +[Service] +ExecStart=@runtimeShell@ -l -c "@emacs@/bin/emacs --fg-daemon '-f' 'exwm-enable'" +Restart=on-failure +SuccessExitStatus=15 +Type=notify + +[Unit] +Description=Emacs text editor +Documentation=info:emacs man:emacs(1) https://gnu.org/software/emacs/ +X-RestartIfChanged=false diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/emacs/emacs-socket-27.nix b/infra/libkookie/home-manager-stable/tests/modules/services/emacs/emacs-socket-27.nix new file mode 100644 index 00000000000..b3b71e02731 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/emacs/emacs-socket-27.nix @@ -0,0 +1,43 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + +in { + config = { + nixpkgs.overlays = [ + (self: super: rec { + emacs = pkgs.writeShellScriptBin "dummy-emacs-27.2" "" // { + outPath = "@emacs@"; + }; + emacsPackagesFor = _: + makeScope super.newScope (_: { emacsWithPackages = _: emacs; }); + }) + ]; + + programs.emacs.enable = true; + services.emacs.enable = true; + services.emacs.client.enable = true; + services.emacs.extraOptions = [ "-f" "exwm-enable" ]; + services.emacs.socketActivation.enable = true; + + nmt.script = '' + assertFileExists home-files/.config/systemd/user/emacs.socket + assertFileExists home-files/.config/systemd/user/emacs.service + assertFileExists home-path/share/applications/emacsclient.desktop + + assertFileContent home-files/.config/systemd/user/emacs.socket \ + ${./emacs-socket-emacs.socket} + assertFileContent home-files/.config/systemd/user/emacs.service \ + ${ + pkgs.substituteAll { + inherit (pkgs) runtimeShell coreutils; + src = ./emacs-socket-emacs.service; + } + } + assertFileContent home-path/share/applications/emacsclient.desktop \ + ${./emacs-27-emacsclient.desktop} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/emacs/emacs-socket-28.nix b/infra/libkookie/home-manager-stable/tests/modules/services/emacs/emacs-socket-28.nix new file mode 100644 index 00000000000..9110666568e --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/emacs/emacs-socket-28.nix @@ -0,0 +1,43 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + +in { + config = { + nixpkgs.overlays = [ + (self: super: rec { + emacs = pkgs.writeShellScriptBin "dummy-emacs-28.0.5" "" // { + outPath = "@emacs@"; + }; + emacsPackagesFor = _: + makeScope super.newScope (_: { emacsWithPackages = _: emacs; }); + }) + ]; + + programs.emacs.enable = true; + services.emacs.enable = true; + services.emacs.client.enable = true; + services.emacs.extraOptions = [ "-f" "exwm-enable" ]; + services.emacs.socketActivation.enable = true; + + nmt.script = '' + assertFileExists home-files/.config/systemd/user/emacs.socket + assertFileExists home-files/.config/systemd/user/emacs.service + assertFileExists home-path/share/applications/emacsclient.desktop + + assertFileContent home-files/.config/systemd/user/emacs.socket \ + ${./emacs-socket-emacs.socket} + assertFileContent home-files/.config/systemd/user/emacs.service \ + ${ + pkgs.substituteAll { + inherit (pkgs) runtimeShell coreutils; + src = ./emacs-socket-emacs.service; + } + } + assertFileContent home-path/share/applications/emacsclient.desktop \ + ${./emacs-28-emacsclient.desktop} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/emacs/emacs-socket-emacs.service b/infra/libkookie/home-manager-stable/tests/modules/services/emacs/emacs-socket-emacs.service new file mode 100644 index 00000000000..b44694d39a7 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/emacs/emacs-socket-emacs.service @@ -0,0 +1,13 @@ +[Service] +ExecStart=@runtimeShell@ -l -c "@emacs@/bin/emacs --fg-daemon='%t/emacs/server' '-f' 'exwm-enable'" +ExecStartPost=@coreutils@/bin/chmod --changes -w %t/emacs +ExecStopPost=@coreutils@/bin/chmod --changes +w %t/emacs +Restart=on-failure +SuccessExitStatus=15 +Type=notify + +[Unit] +Description=Emacs text editor +Documentation=info:emacs man:emacs(1) https://gnu.org/software/emacs/ +RefuseManualStart=true +X-RestartIfChanged=false diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/emacs/emacs-socket-emacs.socket b/infra/libkookie/home-manager-stable/tests/modules/services/emacs/emacs-socket-emacs.socket new file mode 100644 index 00000000000..7fffcb0d004 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/emacs/emacs-socket-emacs.socket @@ -0,0 +1,12 @@ +[Install] +WantedBy=sockets.target + +[Socket] +DirectoryMode=0700 +FileDescriptorName=server +ListenStream=%t/emacs/server +SocketMode=0600 + +[Unit] +Description=Emacs text editor +Documentation=info:emacs man:emacs(1) https://gnu.org/software/emacs/ diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/espanso/basic-configuration.nix b/infra/libkookie/home-manager-stable/tests/modules/services/espanso/basic-configuration.nix new file mode 100644 index 00000000000..34c6d533b8c --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/espanso/basic-configuration.nix @@ -0,0 +1,45 @@ +{ ... }: + +{ + services.espanso = { + enable = true; + settings = { + matches = [ + { # Simple text replacement + trigger = ":espanso"; + replace = "Hi there!"; + } + { # Dates + trigger = ":date"; + replace = "{{mydate}}"; + vars = [{ + name = "mydate"; + type = "date"; + params = { format = "%m/%d/%Y"; }; + }]; + } + { # Shell commands + trigger = ":shell"; + replace = "{{output}}"; + vars = [{ + name = "output"; + type = "shell"; + params = { cmd = "echo Hello from your shell"; }; + }]; + } + ]; + }; + }; + + test.stubs.espanso = { }; + + nmt.script = '' + serviceFile=home-files/.config/systemd/user/espanso.service + assertFileExists "$serviceFile" + assertFileContent "$serviceFile" ${./basic-configuration.service} + + configFile=home-files/.config/espanso/default.yml + assertFileExists "$configFile" + assertFileContent "$configFile" ${./basic-configuration.yaml} + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/espanso/basic-configuration.service b/infra/libkookie/home-manager-stable/tests/modules/services/espanso/basic-configuration.service new file mode 100644 index 00000000000..593196e5952 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/espanso/basic-configuration.service @@ -0,0 +1,10 @@ +[Install] +WantedBy=default.target + +[Service] +ExecStart=@espanso@/bin/espanso daemon +Restart=on-failure +Type=exec + +[Unit] +Description=Espanso: cross platform text expander in Rust diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/espanso/basic-configuration.yaml b/infra/libkookie/home-manager-stable/tests/modules/services/espanso/basic-configuration.yaml new file mode 100644 index 00000000000..3789df04b0a --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/espanso/basic-configuration.yaml @@ -0,0 +1,17 @@ +matches: +- replace: Hi there! + trigger: :espanso +- replace: '{{mydate}}' + trigger: :date + vars: + - name: mydate + params: + format: '%m/%d/%Y' + type: date +- replace: '{{output}}' + trigger: :shell + vars: + - name: output + params: + cmd: echo Hello from your shell + type: shell diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/espanso/default.nix b/infra/libkookie/home-manager-stable/tests/modules/services/espanso/default.nix new file mode 100644 index 00000000000..5df5fa3f1bd --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/espanso/default.nix @@ -0,0 +1 @@ +{ espanso-basic-configuration = ./basic-configuration.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/flameshot/default.nix b/infra/libkookie/home-manager-stable/tests/modules/services/flameshot/default.nix new file mode 100644 index 00000000000..826051f3062 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/flameshot/default.nix @@ -0,0 +1,4 @@ +{ + flameshot-empty-settings = ./empty-settings.nix; + flameshot-example-settings = ./example-settings.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/flameshot/empty-settings.nix b/infra/libkookie/home-manager-stable/tests/modules/services/flameshot/empty-settings.nix new file mode 100644 index 00000000000..a5205660b35 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/flameshot/empty-settings.nix @@ -0,0 +1,13 @@ +{ ... }: + +{ + config = { + services.flameshot = { enable = true; }; + + test.stubs.flameshot = { }; + + nmt.script = '' + assertPathNotExists home-files/.config/flameshot/flameshot.ini + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/flameshot/example-settings.nix b/infra/libkookie/home-manager-stable/tests/modules/services/flameshot/example-settings.nix new file mode 100644 index 00000000000..213e86b3417 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/flameshot/example-settings.nix @@ -0,0 +1,30 @@ +{ ... }: + +{ + config = { + services.flameshot = { + enable = true; + + settings = { + General = { + disabledTrayIcon = true; + showStartupLaunchMessage = false; + }; + }; + }; + + test.stubs.flameshot = { }; + + nmt.script = '' + assertFileContent \ + home-files/.config/flameshot/flameshot.ini \ + ${ + builtins.toFile "expected.ini" '' + [General] + disabledTrayIcon=true + showStartupLaunchMessage=false + '' + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/fluidsynth/default.nix b/infra/libkookie/home-manager-stable/tests/modules/services/fluidsynth/default.nix new file mode 100644 index 00000000000..58e9c5dcc33 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/fluidsynth/default.nix @@ -0,0 +1 @@ +{ fluidsynth = import ./service.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/fluidsynth/service.nix b/infra/libkookie/home-manager-stable/tests/modules/services/fluidsynth/service.nix new file mode 100644 index 00000000000..7fbfa79ce94 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/fluidsynth/service.nix @@ -0,0 +1,25 @@ +{ config, pkgs, ... }: { + config = { + services.fluidsynth.enable = true; + services.fluidsynth.soundService = "pipewire-pulse"; + services.fluidsynth.soundFont = "/path/to/soundFont"; + services.fluidsynth.extraOptions = [ "--sample-rate 96000" ]; + + test.stubs.fluidsynth = { }; + + nmt.script = '' + serviceFile=home-files/.config/systemd/user/fluidsynth.service + + assertFileExists $serviceFile + + assertFileContains $serviceFile \ + 'ExecStart=@fluidsynth@/bin/fluidsynth -a pulseaudio -si --sample-rate 96000 /path/to/soundFont' + + assertFileContains $serviceFile \ + 'After=pipewire-pulse.service' + + assertFileContains $serviceFile \ + 'BindsTo=pipewire-pulse.service' + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/fnott/default.nix b/infra/libkookie/home-manager-stable/tests/modules/services/fnott/default.nix new file mode 100644 index 00000000000..e28250a4841 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/fnott/default.nix @@ -0,0 +1,4 @@ +{ + fnott-example-settings = ./example-settings.nix; + fnott-systemd-user-service = ./systemd-user-service.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/fnott/example-settings-expected.ini b/infra/libkookie/home-manager-stable/tests/modules/services/fnott/example-settings-expected.ini new file mode 100644 index 00000000000..6293f63d28d --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/fnott/example-settings-expected.ini @@ -0,0 +1,7 @@ +[low] +timeout=5 +title-color=ffffff +title-font=Dina:weight=bold:slant=italic + +[main] +notification-margin=5 diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/fnott/example-settings.nix b/infra/libkookie/home-manager-stable/tests/modules/services/fnott/example-settings.nix new file mode 100644 index 00000000000..16b591ff7f8 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/fnott/example-settings.nix @@ -0,0 +1,26 @@ +{ config, lib, pkgs, ... }: + +{ + config = { + services.fnott = { + enable = true; + package = config.lib.test.mkStubPackage { }; + + settings = { + main = { notification-margin = 5; }; + + low = { + timeout = 5; + title-font = "Dina:weight=bold:slant=italic"; + title-color = "ffffff"; + }; + }; + }; + + nmt.script = '' + assertFileContent \ + home-files/.config/fnott/fnott.ini \ + ${./example-settings-expected.ini} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/fnott/systemd-user-service-expected.service b/infra/libkookie/home-manager-stable/tests/modules/services/fnott/systemd-user-service-expected.service new file mode 100644 index 00000000000..1d09bfad551 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/fnott/systemd-user-service-expected.service @@ -0,0 +1,10 @@ +[Service] +BusName=org.freedesktop.Notifications +ExecStart=@fnott@/bin/fnott -c '/home/hm-user/.config/fnott/fnott.ini' +Type=dbus + +[Unit] +After=graphical-session-pre.target +Description=Fnott notification daemon +Documentation=man:fnott(1) +PartOf=graphical-session.target diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/fnott/systemd-user-service.nix b/infra/libkookie/home-manager-stable/tests/modules/services/fnott/systemd-user-service.nix new file mode 100644 index 00000000000..7efa06435a8 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/fnott/systemd-user-service.nix @@ -0,0 +1,16 @@ +{ config, lib, pkgs, ... }: + +{ + config = { + services.fnott = { + enable = true; + package = config.lib.test.mkStubPackage { outPath = "@fnott@"; }; + }; + + nmt.script = '' + assertFileContent \ + home-files/.config/systemd/user/fnott.service \ + ${./systemd-user-service-expected.service} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/fusuma/default.nix b/infra/libkookie/home-manager-stable/tests/modules/services/fusuma/default.nix new file mode 100644 index 00000000000..74024b8b914 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/fusuma/default.nix @@ -0,0 +1,4 @@ +{ + fusuma-example-settings = ./settings.nix; + fusuma-systemd-user-service = ./service.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/fusuma/expected-service.service b/infra/libkookie/home-manager-stable/tests/modules/services/fusuma/expected-service.service new file mode 100644 index 00000000000..a86627f4c59 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/fusuma/expected-service.service @@ -0,0 +1,11 @@ +[Install] +WantedBy=graphical-session.target + +[Service] +Environment=PATH=@coreutils@/bin:@xdotool@/bin +ExecStart=@fusuma@/bin/fusuma -c /home/hm-user/.config/fusuma/config.yaml + +[Unit] +After=graphical-session-pre.target +Description=Fusuma services +PartOf=graphical-session.target diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/fusuma/expected-settings.yaml b/infra/libkookie/home-manager-stable/tests/modules/services/fusuma/expected-settings.yaml new file mode 100644 index 00000000000..b02be48adf9 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/fusuma/expected-settings.yaml @@ -0,0 +1,12 @@ +interval: + swipe: 7 +swipe: + 3: + left: + command: xdotool key ctrl+alt+Right + 4: + left: + command: xdotool key ctrl+shift+alt+Right +threshold: + swipe: 1 + diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/fusuma/service.nix b/infra/libkookie/home-manager-stable/tests/modules/services/fusuma/service.nix new file mode 100644 index 00000000000..d02a75f52ee --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/fusuma/service.nix @@ -0,0 +1,19 @@ +{ config, ... }: + +{ + services.fusuma = { + enable = true; + package = config.lib.test.mkStubPackage { outPath = "@fusuma@"; }; + extraPackages = [ + (config.lib.test.mkStubPackage { outPath = "@coreutils@"; }) + (config.lib.test.mkStubPackage { outPath = "@xdotool@"; }) + ]; + settings = { }; + }; + + nmt.script = '' + assertFileContent \ + home-files/.config/systemd/user/fusuma.service \ + ${./expected-service.service} + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/fusuma/settings.nix b/infra/libkookie/home-manager-stable/tests/modules/services/fusuma/settings.nix new file mode 100644 index 00000000000..303a132725e --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/fusuma/settings.nix @@ -0,0 +1,24 @@ +{ config, ... }: + +{ + services.fusuma = { + enable = true; + package = config.lib.test.mkStubPackage { outPath = "@fusuma@"; }; + extraPackages = [ (config.lib.test.mkStubPackage { }) ]; + + settings = { + threshold = { swipe = 1; }; + interval = { swipe = 7; }; + swipe = { + "3" = { left = { command = "xdotool key ctrl+alt+Right"; }; }; + "4" = { left = { command = "xdotool key ctrl+shift+alt+Right"; }; }; + }; + }; + }; + + nmt.script = '' + assertFileContent \ + home-files/.config/fusuma/config.yaml \ + ${./expected-settings.yaml} + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/git-sync/basic.nix b/infra/libkookie/home-manager-stable/tests/modules/services/git-sync/basic.nix new file mode 100644 index 00000000000..0e9c7ad65b5 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/git-sync/basic.nix @@ -0,0 +1,37 @@ +{ config, pkgs, ... }: + +{ + config = { + services.git-sync = { + enable = true; + package = config.lib.test.mkStubPackage { outPath = "@git-sync@"; }; + repositories.test = { + path = "/a/path"; + uri = "git+ssh://user@example.com:/~user/path/to/repo.git"; + }; + }; + + nmt.script = '' + serviceFile=home-files/.config/systemd/user/git-sync-test.service + + assertFileExists $serviceFile + assertFileContent $serviceFile ${ + builtins.toFile "expected" '' + [Install] + WantedBy=default.target + + [Service] + Environment=GIT_SYNC_DIRECTORY=/a/path + Environment=GIT_SYNC_COMMAND=@git-sync@/bin/git-sync + Environment=GIT_SYNC_REPOSITORY=git+ssh://user@example.com:/~user/path/to/repo.git + Environment=GIT_SYNC_INTERVAL=500 + ExecStart=@git-sync@/bin/git-sync-on-inotify + Restart=on-abort + + [Unit] + Description=Git Sync test + '' + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/git-sync/default.nix b/infra/libkookie/home-manager-stable/tests/modules/services/git-sync/default.nix new file mode 100644 index 00000000000..0e9db79d0a6 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/git-sync/default.nix @@ -0,0 +1 @@ +{ git-sync = ./basic.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/gpg-agent/default-homedir.nix b/infra/libkookie/home-manager-stable/tests/modules/services/gpg-agent/default-homedir.nix new file mode 100644 index 00000000000..faf15374935 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/gpg-agent/default-homedir.nix @@ -0,0 +1,22 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + services.gpg-agent.enable = true; + services.gpg-agent.pinentryFlavor = null; # Don't build pinentry package. + programs.gpg.enable = true; + + test.stubs.gnupg = { }; + + nmt.script = '' + in="${config.systemd.user.sockets.gpg-agent.Socket.ListenStream}" + if [[ $in != "%t/gnupg/S.gpg-agent" ]] + then + echo $in + fail "gpg-agent socket directory not set to default value" + fi + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/gpg-agent/default.nix b/infra/libkookie/home-manager-stable/tests/modules/services/gpg-agent/default.nix new file mode 100644 index 00000000000..cf34517b28a --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/gpg-agent/default.nix @@ -0,0 +1,4 @@ +{ + gpg-agent-default-homedir = ./default-homedir.nix; + gpg-agent-override-homedir = ./override-homedir.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/gpg-agent/override-homedir.nix b/infra/libkookie/home-manager-stable/tests/modules/services/gpg-agent/override-homedir.nix new file mode 100644 index 00000000000..23d9f876548 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/gpg-agent/override-homedir.nix @@ -0,0 +1,25 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + services.gpg-agent.enable = true; + services.gpg-agent.pinentryFlavor = null; # Don't build pinentry package. + programs.gpg = { + enable = true; + homedir = "/path/to/hash"; + }; + + test.stubs.gnupg = { }; + + nmt.script = '' + in="${config.systemd.user.sockets.gpg-agent.Socket.ListenStream}" + if [[ $in != "%t/gnupg/d.wp4h7ks5zxy4dodqadgpbbpz/S.gpg-agent" ]] + then + echo $in + fail "gpg-agent socket directory is malformed" + fi + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/gromit-mpx/basic-configuration.cfg b/infra/libkookie/home-manager-stable/tests/modules/services/gromit-mpx/basic-configuration.cfg new file mode 100644 index 00000000000..d96e9b5ab4c --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/gromit-mpx/basic-configuration.cfg @@ -0,0 +1,5 @@ +"tool-1" = PEN (size=5 color="red"); +"default" = "tool-1"; + +"tool-2" = ERASER (size=75); +"default"[3] = "tool-2"; diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/gromit-mpx/basic-configuration.nix b/infra/libkookie/home-manager-stable/tests/modules/services/gromit-mpx/basic-configuration.nix new file mode 100644 index 00000000000..380bcb5c368 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/gromit-mpx/basic-configuration.nix @@ -0,0 +1,23 @@ +{ config, pkgs, ... }: + +{ + services.gromit-mpx = { + enable = true; + package = config.lib.test.mkStubPackage { }; + tools = [ + { + device = "default"; + type = "pen"; + size = 5; + } + { + device = "default"; + type = "eraser"; + size = 75; + modifiers = [ "3" ]; + } + ]; + }; + + nmt.script = import ./nmt-script.nix ./basic-configuration.cfg; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/gromit-mpx/default-configuration.cfg b/infra/libkookie/home-manager-stable/tests/modules/services/gromit-mpx/default-configuration.cfg new file mode 100644 index 00000000000..904c0c6a470 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/gromit-mpx/default-configuration.cfg @@ -0,0 +1,14 @@ +"tool-1" = PEN (size=5 color="red"); +"default" = "tool-1"; + +"tool-2" = PEN (size=5 color="blue"); +"default"[SHIFT] = "tool-2"; + +"tool-3" = PEN (size=5 color="yellow"); +"default"[CONTROL] = "tool-3"; + +"tool-4" = PEN (size=6 color="green" arrowsize=1); +"default"[2] = "tool-4"; + +"tool-5" = ERASER (size=75); +"default"[3] = "tool-5"; diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/gromit-mpx/default-configuration.nix b/infra/libkookie/home-manager-stable/tests/modules/services/gromit-mpx/default-configuration.nix new file mode 100644 index 00000000000..b2ca50569c7 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/gromit-mpx/default-configuration.nix @@ -0,0 +1,10 @@ +{ config, pkgs, ... }: + +{ + services.gromit-mpx = { + enable = true; + package = config.lib.test.mkStubPackage { }; + }; + + nmt.script = import ./nmt-script.nix ./default-configuration.cfg; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/gromit-mpx/default.nix b/infra/libkookie/home-manager-stable/tests/modules/services/gromit-mpx/default.nix new file mode 100644 index 00000000000..d2a43841f14 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/gromit-mpx/default.nix @@ -0,0 +1,4 @@ +{ + gromit-mpx-default-configuration = ./default-configuration.nix; + gromit-mpx-basic-configuration = ./basic-configuration.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/gromit-mpx/nmt-script.nix b/infra/libkookie/home-manager-stable/tests/modules/services/gromit-mpx/nmt-script.nix new file mode 100644 index 00000000000..84dcb66f368 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/gromit-mpx/nmt-script.nix @@ -0,0 +1,14 @@ +golden_file: + +'' + serviceFile=home-files/.config/systemd/user/gromit-mpx.service + + assertFileExists $serviceFile + assertFileRegex $serviceFile 'X-Restart-Triggers=.*gromitmpx\.cfg' + assertFileRegex $serviceFile 'X-Restart-Triggers=.*gromitmpx\.ini' + assertFileRegex $serviceFile 'ExecStart=.*/bin/gromit-mpx' + + assertFileExists home-files/.config/gromit-mpx.ini + assertFileExists home-files/.config/gromit-mpx.cfg + assertFileContent home-files/.config/gromit-mpx.cfg ${golden_file} +'' diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/home-manager-auto-upgrade/basic-configuration.nix b/infra/libkookie/home-manager-stable/tests/modules/services/home-manager-auto-upgrade/basic-configuration.nix new file mode 100644 index 00000000000..444c88624fa --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/home-manager-auto-upgrade/basic-configuration.nix @@ -0,0 +1,18 @@ +{ config, ... }: + +{ + config = { + services.home-manager.autoUpgrade = { + enable = true; + frequency = "00:00"; + }; + + nmt.script = '' + serviceFile=home-files/.config/systemd/user/home-manager-auto-upgrade.service + assertFileExists $serviceFile + + timerFile=home-files/.config/systemd/user/home-manager-auto-upgrade.timer + assertFileExists $timerFile + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/home-manager-auto-upgrade/default.nix b/infra/libkookie/home-manager-stable/tests/modules/services/home-manager-auto-upgrade/default.nix new file mode 100644 index 00000000000..fb09ebc3890 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/home-manager-auto-upgrade/default.nix @@ -0,0 +1 @@ +{ home-manager-auto-upgrade-basic-configuration = ./basic-configuration.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/kanshi/basic-configuration.conf b/infra/libkookie/home-manager-stable/tests/modules/services/kanshi/basic-configuration.conf new file mode 100644 index 00000000000..a305f28f2b9 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/kanshi/basic-configuration.conf @@ -0,0 +1,21 @@ +profile backwardsCompat { + output "LVDS-1" enable + exec echo "7 eight 9" +} + +profile desktop { + output "eDP-1" disable + output "Iiyama North America PLE2483H-DP" enable position 0,0 + output "Iiyama North America PLE2483H-DP 1158765348486" enable mode 1920x1080 position 1920,0 scale 2.100000 transform flipped-270 + exec echo "1 two 3" + exec echo "4 five 6" +} + +profile nomad { + output "eDP-1" enable +} + +profile test { + output "*" enable +} + diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/kanshi/basic-configuration.nix b/infra/libkookie/home-manager-stable/tests/modules/services/kanshi/basic-configuration.nix new file mode 100644 index 00000000000..c5706e635ae --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/kanshi/basic-configuration.nix @@ -0,0 +1,59 @@ +{ config, pkgs, ... }: { + config = { + services.kanshi = { + enable = true; + package = config.lib.test.mkStubPackage { }; + profiles = { + nomad = { + outputs = [{ + criteria = "eDP-1"; + status = "enable"; + }]; + }; + desktop = { + exec = [ ''echo "1 two 3"'' ''echo "4 five 6"'' ]; + outputs = [ + { + criteria = "eDP-1"; + status = "disable"; + } + { + criteria = "Iiyama North America PLE2483H-DP"; + status = "enable"; + position = "0,0"; + } + { + criteria = "Iiyama North America PLE2483H-DP 1158765348486"; + status = "enable"; + position = "1920,0"; + scale = 2.1; + mode = "1920x1080"; + transform = "flipped-270"; + } + ]; + }; + backwardsCompat = { + outputs = [{ + criteria = "LVDS-1"; + status = "enable"; + }]; + exec = ''echo "7 eight 9"''; + }; + }; + extraConfig = '' + profile test { + output "*" enable + } + ''; + }; + + nmt.script = '' + serviceFile=home-files/.config/systemd/user/kanshi.service + assertFileExists $serviceFile + + assertFileExists home-files/.config/kanshi/config + assertFileContent home-files/.config/kanshi/config \ + ${./basic-configuration.conf} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/kanshi/default.nix b/infra/libkookie/home-manager-stable/tests/modules/services/kanshi/default.nix new file mode 100644 index 00000000000..cb6b2a6b79f --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/kanshi/default.nix @@ -0,0 +1 @@ +{ kanshi-basic-configuration = ./basic-configuration.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/lieer/default.nix b/infra/libkookie/home-manager-stable/tests/modules/services/lieer/default.nix new file mode 100644 index 00000000000..1d6b435a1ca --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/lieer/default.nix @@ -0,0 +1 @@ +{ lieer-service = ./lieer-service.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/lieer/lieer-service-expected.service b/infra/libkookie/home-manager-stable/tests/modules/services/lieer/lieer-service-expected.service new file mode 100644 index 00000000000..89859f824ca --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/lieer/lieer-service-expected.service @@ -0,0 +1,9 @@ +[Service] +Environment=NOTMUCH_CONFIG=/home/hm-user/.config/notmuch/default/config +ExecStart=@gmailieer@/bin/gmi sync +Type=oneshot +WorkingDirectory=/home/hm-user/Mail/hm@example.com + +[Unit] +ConditionPathExists=/home/hm-user/Mail/hm@example.com/.gmailieer.json +Description=lieer Gmail synchronization for hm@example.com diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/lieer/lieer-service-expected.timer b/infra/libkookie/home-manager-stable/tests/modules/services/lieer/lieer-service-expected.timer new file mode 100644 index 00000000000..cb059ea47c4 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/lieer/lieer-service-expected.timer @@ -0,0 +1,9 @@ +[Install] +WantedBy=timers.target + +[Timer] +OnCalendar=*:0/5 +RandomizedDelaySec=30 + +[Unit] +Description=lieer Gmail synchronization for hm@example.com diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/lieer/lieer-service.nix b/infra/libkookie/home-manager-stable/tests/modules/services/lieer/lieer-service.nix new file mode 100644 index 00000000000..f624ae82683 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/lieer/lieer-service.nix @@ -0,0 +1,34 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + imports = [ ../../accounts/email-test-accounts.nix ]; + + config = { + services.lieer.enable = true; + + accounts.email.accounts = { + "hm@example.com" = { + flavor = "gmail.com"; + lieer = { + enable = true; + sync.enable = true; + }; + notmuch.enable = true; + }; + }; + + test.stubs.gmailieer = { }; + + nmt.script = '' + assertFileExists home-files/.config/systemd/user/lieer-hm-example-com.service + assertFileExists home-files/.config/systemd/user/lieer-hm-example-com.timer + + assertFileContent home-files/.config/systemd/user/lieer-hm-example-com.service \ + ${./lieer-service-expected.service} + assertFileContent home-files/.config/systemd/user/lieer-hm-example-com.timer \ + ${./lieer-service-expected.timer} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/mopidy/basic-configuration.conf b/infra/libkookie/home-manager-stable/tests/modules/services/mopidy/basic-configuration.conf new file mode 100644 index 00000000000..3654b961054 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/mopidy/basic-configuration.conf @@ -0,0 +1,10 @@ +[file] +enabled = true +media_dirs = + $XDG_MUSIC_DIR|Music + ~/Downloads|Downloads + +[spotify] +client_id = TOTALLY_NOT_A_FAKE_CLIENT_ID +client_secret = YOU_CAN_USE_ME_FOR_YOUR_SPOTIFY_PREMIUM_SUBSCRIPTION +enabled = true diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/mopidy/basic-configuration.nix b/infra/libkookie/home-manager-stable/tests/modules/services/mopidy/basic-configuration.nix new file mode 100644 index 00000000000..418bfde1f6c --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/mopidy/basic-configuration.nix @@ -0,0 +1,38 @@ +{ config, pkgs, ... }: + +{ + services.mopidy = { + enable = true; + settings = { + file = { + enabled = true; + media_dirs = [ "$XDG_MUSIC_DIR|Music" "~/Downloads|Downloads" ]; + }; + + spotify = { + enabled = true; + client_id = "TOTALLY_NOT_A_FAKE_CLIENT_ID"; + client_secret = "YOU_CAN_USE_ME_FOR_YOUR_SPOTIFY_PREMIUM_SUBSCRIPTION"; + }; + }; + }; + + test.stubs.mopidy = { + version = "0"; + outPath = null; + buildScript = '' + mkdir -p $out/bin + touch $out/bin/mopidy + chmod +x $out/bin/mopidy + ''; + }; + + nmt.script = '' + assertFileExists home-files/.config/systemd/user/mopidy.service + assertFileExists home-files/.config/systemd/user/mopidy-scan.service + + assertFileExists home-files/.config/mopidy/mopidy.conf + assertFileContent home-files/.config/mopidy/mopidy.conf \ + ${./basic-configuration.conf} + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/mopidy/default.nix b/infra/libkookie/home-manager-stable/tests/modules/services/mopidy/default.nix new file mode 100644 index 00000000000..2f2c33d2351 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/mopidy/default.nix @@ -0,0 +1 @@ +{ mopidy-basic-configuration = ./basic-configuration.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/mpd/basic-configuration.conf b/infra/libkookie/home-manager-stable/tests/modules/services/mpd/basic-configuration.conf new file mode 100644 index 00000000000..54d6059fa80 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/mpd/basic-configuration.conf @@ -0,0 +1,11 @@ +music_directory "/home/hm-user/music" +playlist_directory "/home/hm-user/.local/share/mpd/playlists" +db_file "/home/hm-user/.local/share/mpd/tag_cache" + +state_file "/home/hm-user/.local/share/mpd/state" +sticker_file "/home/hm-user/.local/share/mpd/sticker.sql" + +bind_to_address "127.0.0.1" + + + diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/mpd/basic-configuration.nix b/infra/libkookie/home-manager-stable/tests/modules/services/mpd/basic-configuration.nix new file mode 100644 index 00000000000..c1f288980f0 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/mpd/basic-configuration.nix @@ -0,0 +1,19 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + services.mpd.enable = true; + + test.stubs.mpd = { }; + + nmt.script = '' + serviceFile=$(normalizeStorePaths home-files/.config/systemd/user/mpd.service) + assertFileContent "$serviceFile" ${./basic-configuration.service} + + confFile=$(grep -o \ + '/nix/store/.*-mpd.conf' \ + $TESTED/home-files/.config/systemd/user/mpd.service) + assertFileContent "$confFile" ${./basic-configuration.conf} + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/mpd/basic-configuration.service b/infra/libkookie/home-manager-stable/tests/modules/services/mpd/basic-configuration.service new file mode 100644 index 00000000000..fd44042a9b9 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/mpd/basic-configuration.service @@ -0,0 +1,13 @@ +[Install] +WantedBy=default.target + +[Service] +Environment=PATH=/home/hm-user/.nix-profile/bin +ExecStart=@mpd@/bin/mpd --no-daemon /nix/store/00000000000000000000000000000000-mpd.conf +ExecStartPre=/nix/store/00000000000000000000000000000000-bash/bin/bash -c "/nix/store/00000000000000000000000000000000-coreutils/bin/mkdir -p '/home/hm-user/.local/share/mpd' '/home/hm-user/.local/share/mpd/playlists'" +Type=notify + +[Unit] +After=network.target +After=sound.target +Description=Music Player Daemon diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/mpd/default.nix b/infra/libkookie/home-manager-stable/tests/modules/services/mpd/default.nix new file mode 100644 index 00000000000..22d1638e537 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/mpd/default.nix @@ -0,0 +1 @@ +{ mpd-basic-configuration = ./basic-configuration.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/mpdris2/basic-configuration.config b/infra/libkookie/home-manager-stable/tests/modules/services/mpdris2/basic-configuration.config new file mode 100644 index 00000000000..e68277562a8 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/mpdris2/basic-configuration.config @@ -0,0 +1,8 @@ +[Bling] +mmkeys = True +notify = True + +[Connection] +host = 127.0.0.1 +music_dir = /home/hm-user/music +port = 6600 diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/mpdris2/basic-configuration.nix b/infra/libkookie/home-manager-stable/tests/modules/services/mpdris2/basic-configuration.nix new file mode 100644 index 00000000000..5e809df394c --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/mpdris2/basic-configuration.nix @@ -0,0 +1,19 @@ +{ ... }: + +{ + services.mpdris2 = { + enable = true; + notifications = true; + multimediaKeys = true; + }; + + test.stubs.mpdris2 = { }; + + nmt.script = '' + serviceFile=home-files/.config/systemd/user/mpdris2.service + assertFileContent "$serviceFile" ${./basic-configuration.service} + + configFile=home-files/.config/mpDris2/mpDris2.conf + assertFileContent "$configFile" ${./basic-configuration.config} + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/mpdris2/basic-configuration.service b/infra/libkookie/home-manager-stable/tests/modules/services/mpdris2/basic-configuration.service new file mode 100644 index 00000000000..2ea4656c752 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/mpdris2/basic-configuration.service @@ -0,0 +1,13 @@ +[Install] +WantedBy=default.target + +[Service] +BusName=org.mpris.MediaPlayer2.mpd +ExecStart=@mpdris2@/bin/mpDris2 +Restart=on-failure +RestartSec=5s +Type=simple + +[Unit] +After=mpd.service +Description=MPRIS 2 support for MPD diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/mpdris2/default.nix b/infra/libkookie/home-manager-stable/tests/modules/services/mpdris2/default.nix new file mode 100644 index 00000000000..eaf6be337ff --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/mpdris2/default.nix @@ -0,0 +1,4 @@ +{ + mpdris2-basic-configuration = ./basic-configuration.nix; + mpdris2-with-password = ./with-password.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/mpdris2/with-password.config b/infra/libkookie/home-manager-stable/tests/modules/services/mpdris2/with-password.config new file mode 100644 index 00000000000..939a4058999 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/mpdris2/with-password.config @@ -0,0 +1,9 @@ +[Bling] +mmkeys = False +notify = False + +[Connection] +host = somehost +music_dir = /home/hm-user/music +password = foo +port = 42 diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/mpdris2/with-password.nix b/infra/libkookie/home-manager-stable/tests/modules/services/mpdris2/with-password.nix new file mode 100644 index 00000000000..fcfe153151e --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/mpdris2/with-password.nix @@ -0,0 +1,22 @@ +{ ... }: + +{ + services.mpdris2 = { + enable = true; + mpd = { + host = "somehost"; + port = 42; + password = "foo"; + }; + }; + + test.stubs.mpdris2 = { }; + + nmt.script = '' + serviceFile=home-files/.config/systemd/user/mpdris2.service + assertFileContent "$serviceFile" ${./basic-configuration.service} + + configFile=home-files/.config/mpDris2/mpDris2.conf + assertFileContent "$configFile" ${./with-password.config} + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/pantalaimon/basic-configuration.nix b/infra/libkookie/home-manager-stable/tests/modules/services/pantalaimon/basic-configuration.nix new file mode 100644 index 00000000000..ac36c0b87cb --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/pantalaimon/basic-configuration.nix @@ -0,0 +1,27 @@ +{ config, pkgs, ... }: + +{ + config = { + services.pantalaimon = { + enable = true; + package = config.lib.test.mkStubPackage { outPath = "@pantalaimon@"; }; + settings = { + Default = { + LogLevel = "Debug"; + SSL = true; + }; + local-matrix = { + Homeserver = "https://matrix.org"; + ListenAddress = "127.0.0.1"; + ListenPort = 8008; + }; + }; + }; + + nmt.script = '' + serviceFile=home-files/.config/systemd/user/pantalaimon.service + assertFileExists $serviceFile + assertFileRegex $serviceFile 'ExecStart=@pantalaimon@/bin/pantalaimon -c /nix/store/.*-pantalaimon.conf' + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/pantalaimon/default.nix b/infra/libkookie/home-manager-stable/tests/modules/services/pantalaimon/default.nix new file mode 100644 index 00000000000..8c29efb4060 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/pantalaimon/default.nix @@ -0,0 +1 @@ +{ pantalaimon-basic-configuration = ./basic-configuration.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/pbgopy/default.nix b/infra/libkookie/home-manager-stable/tests/modules/services/pbgopy/default.nix new file mode 100644 index 00000000000..c2c9d485ddb --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/pbgopy/default.nix @@ -0,0 +1 @@ +{ pbgopy = import ./service.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/pbgopy/service.nix b/infra/libkookie/home-manager-stable/tests/modules/services/pbgopy/service.nix new file mode 100644 index 00000000000..465024537ac --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/pbgopy/service.nix @@ -0,0 +1,16 @@ +{ config, pkgs, ... }: { + config = { + services.pbgopy.enable = true; + + test.stubs.pbgopy = { }; + + nmt.script = '' + serviceFile=home-files/.config/systemd/user/pbgopy.service + + assertFileExists $serviceFile + + assertFileContains $serviceFile \ + 'ExecStart=@pbgopy@/bin/pbgopy serve --port 9090 --ttl 24h' + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/picom/default.nix b/infra/libkookie/home-manager-stable/tests/modules/services/picom/default.nix new file mode 100644 index 00000000000..6437013148e --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/picom/default.nix @@ -0,0 +1 @@ +{ picom-basic-configuration = ./picom-basic-configuration.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/picom/picom-basic-configuration-expected.conf b/infra/libkookie/home-manager-stable/tests/modules/services/picom/picom-basic-configuration-expected.conf new file mode 100644 index 00000000000..6a7ac09aa14 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/picom/picom-basic-configuration-expected.conf @@ -0,0 +1,33 @@ +# fading +fading = true; +fade-delta = 5; +fade-in-step = 0.04; +fade-out-step = 0.04; +fade-exclude = ["window_type *= 'menu'","name ~= 'Firefox$'","focused = 1"]; + +# shadows +shadow = true; +shadow-offset-x = -10; +shadow-offset-y = -15; +shadow-opacity = 0.8; +shadow-exclude = ["window_type *= 'menu'","name ~= 'Firefox$'","focused = 1"]; + +# opacity +active-opacity = 1.0; +inactive-opacity = 1.0; +inactive-dim = 0.0; +opacity-rule = []; + +wintypes: +{ + dock = { shadow = false; }; + dnd = { shadow = false; }; + popup_menu = { opacity = 1.0; }; + dropdown_menu = { opacity = 1.0; }; +}; + +# other options +backend = "xrender"; +vsync = true; +unredir-if-possible = true; +dbe = true; diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/picom/picom-basic-configuration-expected.service b/infra/libkookie/home-manager-stable/tests/modules/services/picom/picom-basic-configuration-expected.service new file mode 100644 index 00000000000..62620502cf2 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/picom/picom-basic-configuration-expected.service @@ -0,0 +1,12 @@ +[Install] +WantedBy=graphical-session.target + +[Service] +ExecStart=@picom@/bin/picom --config /nix/store/00000000000000000000000000000000-hm_picompicom.conf --experimental-backends +Restart=always +RestartSec=3 + +[Unit] +After=graphical-session-pre.target +Description=Picom X11 compositor +PartOf=graphical-session.target diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/picom/picom-basic-configuration.nix b/infra/libkookie/home-manager-stable/tests/modules/services/picom/picom-basic-configuration.nix new file mode 100644 index 00000000000..41f1ba01f47 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/picom/picom-basic-configuration.nix @@ -0,0 +1,37 @@ +{ config, pkgs, ... }: + +{ + services.picom = { + enable = true; + fade = true; + fadeDelta = 5; + fadeSteps = [ "0.04" "0.04" ]; + fadeExclude = + [ "window_type *= 'menu'" "name ~= 'Firefox$'" "focused = 1" ]; + shadow = true; + shadowOffsets = [ (-10) (-15) ]; + shadowOpacity = "0.8"; + shadowExclude = + [ "window_type *= 'menu'" "name ~= 'Firefox$'" "focused = 1" ]; + backend = "xrender"; + vSync = true; + extraOptions = '' + unredir-if-possible = true; + dbe = true; + ''; + experimentalBackends = true; + }; + + test.stubs.picom = { }; + + nmt.script = '' + assertFileContent \ + home-files/.config/picom/picom.conf \ + ${./picom-basic-configuration-expected.conf} + + serviceFile=$(normalizeStorePaths home-files/.config/systemd/user/picom.service) + assertFileContent \ + "$serviceFile" \ + ${./picom-basic-configuration-expected.service} + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/playerctld/basic.nix b/infra/libkookie/home-manager-stable/tests/modules/services/playerctld/basic.nix new file mode 100644 index 00000000000..3c10a99f1b4 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/playerctld/basic.nix @@ -0,0 +1,31 @@ +{ config, pkgs, ... }: + +{ + config = { + services.playerctld.enable = true; + services.playerctld.package = pkgs.writeScriptBin "playerctld" "" // { + outPath = "@playerctld@"; + }; + + nmt.script = '' + serviceFile=home-files/.config/systemd/user/playerctld.service + + assertFileExists "$serviceFile" + + assertFileContent "$serviceFile" "${ + pkgs.writeText "playerctld-test" '' + [Install] + WantedBy=default.target + + [Service] + BusName=org.mpris.MediaPlayer2.playerctld + ExecStart=@playerctld@/bin/playerctld + Type=dbus + + [Unit] + Description=MPRIS media player daemon + '' + }" + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/playerctld/default.nix b/infra/libkookie/home-manager-stable/tests/modules/services/playerctld/default.nix new file mode 100644 index 00000000000..93ed10aaf4a --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/playerctld/default.nix @@ -0,0 +1 @@ +{ playerctld-basic = ./basic.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/polybar/basic-configuration.conf b/infra/libkookie/home-manager-stable/tests/modules/services/polybar/basic-configuration.conf new file mode 100644 index 00000000000..10ea0f076ea --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/polybar/basic-configuration.conf @@ -0,0 +1,32 @@ +[bar/top] +height=3% +modules-center=date +monitor=${env:MONITOR:eDP1} +radius=0 +width=100% + +[module/date] +date=%d.%m.%y +internal=5 +label=%time% %date% +time=%H:%M +type=internal/date + +[module/volume] +click-right=pavucontrol & +format-volume= +label-muted=🔇 +label-muted-foreground=#666 +ramp-volume-0=🔈 +ramp-volume-1=🔉 +ramp-volume-2=🔊 +type=internal/pulseaudio + +[module/date] +type = internal/date +interval = 5 +date = "%d.%m.%y" +time = %H:%M +format-prefix-foreground = ${colors.foreground-alt} +label = %time% %date% + diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/polybar/basic-configuration.nix b/infra/libkookie/home-manager-stable/tests/modules/services/polybar/basic-configuration.nix new file mode 100644 index 00000000000..b6374acd893 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/polybar/basic-configuration.nix @@ -0,0 +1,58 @@ +{ config, pkgs, ... }: + +{ + config = { + services.polybar = { + enable = true; + package = config.lib.test.mkStubPackage { }; + script = "polybar bar &"; + config = { + "bar/top" = { + monitor = "\${env:MONITOR:eDP1}"; + width = "100%"; + height = "3%"; + radius = 0; + modules-center = "date"; + }; + "module/date" = { + type = "internal/date"; + internal = 5; + date = "%d.%m.%y"; + time = "%H:%M"; + label = "%time% %date%"; + }; + }; + settings = { + "module/volume" = { + type = "internal/pulseaudio"; + format.volume = " "; + label.muted.text = "🔇"; + label.muted.foreground = "#666"; + ramp.volume = [ "🔈" "🔉" "🔊" ]; + click.right = "pavucontrol &"; + }; + }; + extraConfig = '' + [module/date] + type = internal/date + interval = 5 + date = "%d.%m.%y" + time = %H:%M + format-prefix-foreground = ''${colors.foreground-alt} + label = %time% %date% + ''; + }; + + nmt.script = '' + serviceFile=home-files/.config/systemd/user/polybar.service + + assertFileExists $serviceFile + assertFileRegex $serviceFile 'X-Restart-Triggers=.*polybar\.conf' + assertFileRegex $serviceFile 'ExecStart=.*/bin/polybar-start' + + assertFileExists home-files/.config/polybar/config + assertFileContent home-files/.config/polybar/config \ + ${./basic-configuration.conf} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/polybar/default.nix b/infra/libkookie/home-manager-stable/tests/modules/services/polybar/default.nix new file mode 100644 index 00000000000..94d5d3cde20 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/polybar/default.nix @@ -0,0 +1 @@ +{ polybar-basic-configuration = ./basic-configuration.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/redshift-gammastep/default.nix b/infra/libkookie/home-manager-stable/tests/modules/services/redshift-gammastep/default.nix new file mode 100644 index 00000000000..78251059ac7 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/redshift-gammastep/default.nix @@ -0,0 +1,4 @@ +{ + gammastep-basic-configuration = ./gammastep-basic-configuration.nix; + redshift-basic-configuration = ./redshift-basic-configuration.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/redshift-gammastep/gammastep-basic-configuration-expected.service b/infra/libkookie/home-manager-stable/tests/modules/services/redshift-gammastep/gammastep-basic-configuration-expected.service new file mode 100644 index 00000000000..8d0e7a5fbc3 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/redshift-gammastep/gammastep-basic-configuration-expected.service @@ -0,0 +1,13 @@ +[Install] +WantedBy=graphical-session.target + +[Service] +ExecStart=@gammastep@/bin/gammastep -v -c /home/hm-user/.config/gammastep/config.ini +Restart=on-failure +RestartSec=3 + +[Unit] +After=graphical-session-pre.target +Description=Gammastep colour temperature adjuster +Documentation=https://gitlab.com/chinstrap/gammastep/ +PartOf=graphical-session.target diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/redshift-gammastep/gammastep-basic-configuration-file-expected.conf b/infra/libkookie/home-manager-stable/tests/modules/services/redshift-gammastep/gammastep-basic-configuration-file-expected.conf new file mode 100644 index 00000000000..a33230a681e --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/redshift-gammastep/gammastep-basic-configuration-file-expected.conf @@ -0,0 +1,13 @@ +[general] +adjustment-method=randr +dawn-time=6:00-7:45 +dusk-time=18:35-20:15 +gamma=0.800000 +location-provider=manual +temp-day=5500 +temp-night=3700 + +[manual] + +[randr] +screen=0 diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/redshift-gammastep/gammastep-basic-configuration.nix b/infra/libkookie/home-manager-stable/tests/modules/services/redshift-gammastep/gammastep-basic-configuration.nix new file mode 100644 index 00000000000..6f0454bf35c --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/redshift-gammastep/gammastep-basic-configuration.nix @@ -0,0 +1,30 @@ +{ config, pkgs, ... }: + +{ + config = { + services.gammastep = { + enable = true; + provider = "manual"; + dawnTime = "6:00-7:45"; + duskTime = "18:35-20:15"; + settings = { + general = { + adjustment-method = "randr"; + gamma = 0.8; + }; + randr = { screen = 0; }; + }; + }; + + test.stubs.gammastep = { }; + + nmt.script = '' + assertFileContent \ + home-files/.config/gammastep/config.ini \ + ${./gammastep-basic-configuration-file-expected.conf} + assertFileContent \ + home-files/.config/systemd/user/gammastep.service \ + ${./gammastep-basic-configuration-expected.service} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/redshift-gammastep/redshift-basic-configuration-expected.service b/infra/libkookie/home-manager-stable/tests/modules/services/redshift-gammastep/redshift-basic-configuration-expected.service new file mode 100644 index 00000000000..07ffbf06d8f --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/redshift-gammastep/redshift-basic-configuration-expected.service @@ -0,0 +1,13 @@ +[Install] +WantedBy=graphical-session.target + +[Service] +ExecStart=@redshift@/bin/redshift -v -c /home/hm-user/.config/redshift/redshift.conf +Restart=on-failure +RestartSec=3 + +[Unit] +After=graphical-session-pre.target +Description=Redshift colour temperature adjuster +Documentation=http://jonls.dk/redshift/ +PartOf=graphical-session.target diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/redshift-gammastep/redshift-basic-configuration-file-expected.conf b/infra/libkookie/home-manager-stable/tests/modules/services/redshift-gammastep/redshift-basic-configuration-file-expected.conf new file mode 100644 index 00000000000..f2aab6a530f --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/redshift-gammastep/redshift-basic-configuration-file-expected.conf @@ -0,0 +1,13 @@ +[manual] +lat=0.000000 +lon=0.0 + +[randr] +screen=0 + +[redshift] +adjustment-method=randr +gamma=0.800000 +location-provider=manual +temp-day=5500 +temp-night=3700 diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/redshift-gammastep/redshift-basic-configuration.nix b/infra/libkookie/home-manager-stable/tests/modules/services/redshift-gammastep/redshift-basic-configuration.nix new file mode 100644 index 00000000000..691d01e257f --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/redshift-gammastep/redshift-basic-configuration.nix @@ -0,0 +1,30 @@ +{ config, pkgs, ... }: + +{ + config = { + services.redshift = { + enable = true; + provider = "manual"; + latitude = 0.0; + longitude = "0.0"; + settings = { + redshift = { + adjustment-method = "randr"; + gamma = 0.8; + }; + randr = { screen = 0; }; + }; + }; + + test.stubs.redshift = { }; + + nmt.script = '' + assertFileContent \ + home-files/.config/redshift/redshift.conf \ + ${./redshift-basic-configuration-file-expected.conf} + assertFileContent \ + home-files/.config/systemd/user/redshift.service \ + ${./redshift-basic-configuration-expected.service} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/screen-locker/basic-configuration.nix b/infra/libkookie/home-manager-stable/tests/modules/services/screen-locker/basic-configuration.nix new file mode 100644 index 00000000000..9eee2a8e2ac --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/screen-locker/basic-configuration.nix @@ -0,0 +1,30 @@ +{ config, pkgs, ... }: + +{ + config = { + services.screen-locker = { + enable = true; + inactiveInterval = 5; + lockCmd = "${pkgs.i3lock}/bin/i3lock -n -c AA0000"; + xss-lock = { extraOptions = [ "-test" ]; }; + xautolock = { + enable = true; + detectSleep = true; + extraOptions = [ "-test" ]; + }; + }; + + test.stubs.i3lock = { }; + test.stubs.xss-lock = { }; + + nmt.script = '' + xssService=home-files/.config/systemd/user/xss-lock.service + xautolockService=home-files/.config/systemd/user/xautolock-session.service + + assertFileExists $xssService + assertFileRegex $xssService 'ExecStart=.*/bin/xss-lock.*-test.*i3lock -n -c AA0000' + assertFileExists $xautolockService + assertFileRegex $xautolockService 'ExecStart=.*/bin/xautolock.*-time 5.*-detectsleep.*-test.*' + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/screen-locker/default.nix b/infra/libkookie/home-manager-stable/tests/modules/services/screen-locker/default.nix new file mode 100644 index 00000000000..667defc5178 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/screen-locker/default.nix @@ -0,0 +1,5 @@ +{ + screen-locker-basic-configuration = ./basic-configuration.nix; + screen-locker-no-xautolock = ./no-xautolock.nix; + screen-locker-moved-options = ./moved-options.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/screen-locker/moved-options.nix b/infra/libkookie/home-manager-stable/tests/modules/services/screen-locker/moved-options.nix new file mode 100644 index 00000000000..4c9cad19ee0 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/screen-locker/moved-options.nix @@ -0,0 +1,36 @@ +{ config, pkgs, options, lib, ... }: + +{ + config = { + services.screen-locker = { + enable = true; + inactiveInterval = 5; + lockCmd = "${pkgs.i3lock}/bin/i3lock -n -c AA0000"; + xssLockExtraOptions = [ "-test" ]; + xautolockExtraOptions = [ "-test" ]; + enableDetectSleep = true; + }; + + test.stubs.i3lock = { }; + test.stubs.xss-lock = { }; + + # Use the same verification script as the basic configuration. The result + # with the old options should be identical. + nmt.script = (import ./basic-configuration.nix { + inherit config pkgs; + }).config.nmt.script; + + test.asserts.warnings.expected = with lib; + let + renamed = { + xssLockExtraOptions = "xss-lock.extraOptions"; + xautolockExtraOptions = "xautolock.extraOptions"; + enableDetectSleep = "xautolock.detectSleep"; + }; + in mapAttrsToList (old: new: + builtins.replaceStrings [ "\n" ] [ " " ] '' + The option `services.screen-locker.${old}' defined in + ${showFiles options.services.screen-locker.${old}.files} + has been renamed to `services.screen-locker.${new}'.'') renamed; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/screen-locker/no-xautolock.nix b/infra/libkookie/home-manager-stable/tests/modules/services/screen-locker/no-xautolock.nix new file mode 100644 index 00000000000..7ec5152b0f9 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/screen-locker/no-xautolock.nix @@ -0,0 +1,27 @@ +{ config, pkgs, ... }: + +{ + config = { + services.screen-locker = { + enable = true; + inactiveInterval = 5; + lockCmd = "${pkgs.i3lock}/bin/i3lock -n -c AA0000"; + xss-lock = { + extraOptions = [ "-test" ]; + screensaverCycle = 5; + }; + xautolock = { enable = false; }; + }; + + test.stubs.i3lock = { }; + test.stubs.xss-lock = { }; + + nmt.script = '' + xssService=home-files/.config/systemd/user/xss-lock.service + + assertFileExists $xssService + assertFileRegex $xssService 'ExecStart=.*/bin/xss-lock.*-test.*i3lock -n -c AA0000' + assertFileRegex $xssService 'ExecStartPre=.*/xset s 300 5' + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/swayidle/basic-configuration.nix b/infra/libkookie/home-manager-stable/tests/modules/services/swayidle/basic-configuration.nix new file mode 100644 index 00000000000..d3c6bef73a0 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/swayidle/basic-configuration.nix @@ -0,0 +1,52 @@ +{ config, pkgs, lib, ... }: + +{ + config = { + services.swayidle = { + enable = true; + package = config.lib.test.mkStubPackage { }; + timeouts = [ + { + timeout = 50; + command = ''notify-send -t 10000 -- "Screen lock in 10 seconds"''; + } + { + timeout = 60; + command = "swaylock -fF"; + } + { + timeout = 300; + command = ''swaymsg "output * dpms off"''; + resumeCommand = ''swaymsg "output * dpms on"''; + } + ]; + events = [ + { + event = "before-sleep"; + command = "swaylock -fF"; + } + { + event = "lock"; + command = "swaylock -fF"; + } + ]; + }; + + nmt.script = let + escapeForRegex = builtins.replaceStrings [ "'" "*" ] [ "'\\''" "\\*" ]; + expectedArgs = escapeForRegex (lib.concatStringsSep " " [ + "-w" + "timeout 50 'notify-send -t 10000 -- \"Screen lock in 10 seconds\"'" + "timeout 60 'swaylock -fF'" + "timeout 300 'swaymsg \"output * dpms off\"' resume 'swaymsg \"output * dpms on\"'" + "before-sleep 'swaylock -fF'" + "lock 'swaylock -fF'" + ]); + in '' + serviceFile=home-files/.config/systemd/user/swayidle.service + + assertFileExists $serviceFile + assertFileRegex $serviceFile 'ExecStart=.*/bin/swayidle ${expectedArgs}' + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/swayidle/default.nix b/infra/libkookie/home-manager-stable/tests/modules/services/swayidle/default.nix new file mode 100644 index 00000000000..124fe1d7d8a --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/swayidle/default.nix @@ -0,0 +1 @@ +{ swayidle-basic-configuration = ./basic-configuration.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/sxhkd/configuration.nix b/infra/libkookie/home-manager-stable/tests/modules/services/sxhkd/configuration.nix new file mode 100644 index 00000000000..9e99650519f --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/sxhkd/configuration.nix @@ -0,0 +1,32 @@ +{ config, pkgs, ... }: + +{ + services.sxhkd = { + enable = true; + + package = config.lib.test.mkStubPackage { outPath = "@sxhkd@"; }; + + keybindings = { + "super + a" = "run command a"; + "super + b" = null; + "super + Shift + b" = "run command b"; + }; + + extraConfig = '' + super + c + call command c + + # comment + super + d + call command d + ''; + }; + + nmt.script = '' + sxhkdrc=home-files/.config/sxhkd/sxhkdrc + + assertFileExists $sxhkdrc + + assertFileContent $sxhkdrc ${./sxhkdrc} + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/sxhkd/default.nix b/infra/libkookie/home-manager-stable/tests/modules/services/sxhkd/default.nix new file mode 100644 index 00000000000..ec25252cee0 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/sxhkd/default.nix @@ -0,0 +1,4 @@ +{ + sxhkd-configuration = ./configuration.nix; + sxhkd-service = ./service.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/sxhkd/service.nix b/infra/libkookie/home-manager-stable/tests/modules/services/sxhkd/service.nix new file mode 100644 index 00000000000..84f3086a8b5 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/sxhkd/service.nix @@ -0,0 +1,26 @@ +{ config, pkgs, ... }: + +{ + xsession = { + enable = true; + windowManager.command = ""; + }; + + services.sxhkd = { + enable = true; + package = config.lib.test.mkStubPackage { outPath = "@sxhkd@"; }; + extraOptions = [ "-m 1" ]; + }; + + nmt.script = '' + xsessionFile=home-files/.xsession + + assertFileExists $xsessionFile + + assertFileContains $xsessionFile \ + 'systemctl --user stop sxhkd.scope 2> /dev/null || true' + + assertFileContains $xsessionFile \ + 'systemd-cat -t sxhkd systemd-run --user --scope -u sxhkd @sxhkd@/bin/sxhkd -m 1 &' + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/sxhkd/sxhkdrc b/infra/libkookie/home-manager-stable/tests/modules/services/sxhkd/sxhkdrc new file mode 100644 index 00000000000..c8883464b29 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/sxhkd/sxhkdrc @@ -0,0 +1,13 @@ +super + Shift + b + run command b + +super + a + run command a + + +super + c + call command c + +# comment +super + d + call command d diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/syncthing/default.nix b/infra/libkookie/home-manager-stable/tests/modules/services/syncthing/default.nix new file mode 100644 index 00000000000..86f72b571f9 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/syncthing/default.nix @@ -0,0 +1,5 @@ +{ + syncthing-extra-options = ./extra-options.nix; + syncthing-tray = ./tray.nix; + syncthing-tray-as-bool-triggers-warning = ./tray-as-bool-triggers-warning.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/syncthing/extra-options.nix b/infra/libkookie/home-manager-stable/tests/modules/services/syncthing/extra-options.nix new file mode 100644 index 00000000000..c78b00f9c1e --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/syncthing/extra-options.nix @@ -0,0 +1,16 @@ +{ config, ... }: + +{ + services.syncthing = { + enable = true; + extraOptions = [ "-foo" ''-bar "baz"'' ]; + }; + + test.stubs.syncthing = { }; + + nmt.script = '' + assertFileExists home-files/.config/systemd/user/syncthing.service + assertFileContains home-files/.config/systemd/user/syncthing.service \ + "ExecStart=@syncthing@/bin/syncthing -no-browser -no-restart -logflags=0 '-foo' '-bar \"baz\"'" + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/syncthing/tray-as-bool-triggers-warning.nix b/infra/libkookie/home-manager-stable/tests/modules/services/syncthing/tray-as-bool-triggers-warning.nix new file mode 100644 index 00000000000..ca018c2d8a0 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/syncthing/tray-as-bool-triggers-warning.nix @@ -0,0 +1,19 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + services.syncthing.tray = true; + + test.asserts.warnings.expected = [ + "Specifying 'services.syncthing.tray' as a boolean is deprecated, set 'services.syncthing.tray.enable' instead. See https://github.com/nix-community/home-manager/pull/1257." + ]; + + test.stubs.syncthingtray-minimal = { }; + + nmt.script = '' + assertFileExists home-files/.config/systemd/user/syncthingtray.service + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/syncthing/tray.nix b/infra/libkookie/home-manager-stable/tests/modules/services/syncthing/tray.nix new file mode 100644 index 00000000000..5ff3c2841fb --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/syncthing/tray.nix @@ -0,0 +1,21 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + services.syncthing.tray.enable = true; + + nixpkgs.overlays = [ + (self: super: { + syncthingtray-minimal = + pkgs.runCommandLocal "syncthingtray" { pname = "syncthingtray"; } + "mkdir $out"; + }) + ]; + + nmt.script = '' + assertFileExists home-files/.config/systemd/user/syncthingtray.service + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/trayer/basic-configuration.nix b/infra/libkookie/home-manager-stable/tests/modules/services/trayer/basic-configuration.nix new file mode 100644 index 00000000000..3020e6310fa --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/trayer/basic-configuration.nix @@ -0,0 +1,27 @@ +{ config, pkgs, ... }: + +{ + config = { + services.trayer = { + enable = true; + package = config.lib.test.mkStubPackage { outPath = "@trayer@"; }; + settings = { + edge = "top"; + padding = 6; + SetDockType = true; + tint = "0x282c34"; + SetPartialStrut = true; + expand = true; + monitor = 1; + }; + }; + + nmt.script = '' + serviceFile=home-files/.config/systemd/user/trayer.service + + assertFileExists $serviceFile + assertFileContains $serviceFile \ + 'ExecStart=@trayer@/bin/trayer --SetDockType true --SetPartialStrut true --edge top --expand true --monitor 1 --padding 6 --tint 0x282c34' + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/trayer/default.nix b/infra/libkookie/home-manager-stable/tests/modules/services/trayer/default.nix new file mode 100644 index 00000000000..f8672b59e52 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/trayer/default.nix @@ -0,0 +1 @@ +{ trayer-basic-configuration = ./basic-configuration.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/twmn/basic-configuration.conf b/infra/libkookie/home-manager-stable/tests/modules/services/twmn/basic-configuration.conf new file mode 100644 index 00000000000..a6ddb5c7312 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/twmn/basic-configuration.conf @@ -0,0 +1,32 @@ +[gui] +always_on_top=true +background_color=black +bounce=true +bounce_duration=271 +font=Noto Sans +font_size=16 +font_variant=italic +foreground_color=#FF00FF +height=20 +in_animation=27 +in_animation_duration=314 +max_length=80 +offset_x=+20 +offset_y=-60 +opacity=80 +out_animation=13 +out_animation_duration=168 +position=center +screen=0 + +[icons] +critical=/path/icon/critical +info=/path/icon/info +warning=/path/icon/warning + +[main] +duration=4242 +host=example.com +port=9006 +sound_command=/path/sound/command + diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/twmn/basic-configuration.nix b/infra/libkookie/home-manager-stable/tests/modules/services/twmn/basic-configuration.nix new file mode 100644 index 00000000000..5da926e489e --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/twmn/basic-configuration.nix @@ -0,0 +1,51 @@ +{ + config = { + services.twmn = { + enable = true; + duration = 4242; + host = "example.com"; + port = 9006; + screen = 0; + soundCommand = "/path/sound/command"; + icons.critical = "/path/icon/critical"; + icons.info = "/path/icon/info"; + icons.warning = "/path/icon/warning"; + text = { + color = "#FF00FF"; + font.family = "Noto Sans"; + font.size = 16; + font.variant = "italic"; + maxLength = 80; + }; + window = { + alwaysOnTop = true; + color = "black"; + height = 20; + offset.x = 20; + offset.y = -60; + opacity = 80; + position = "center"; + animation = { + easeIn.curve = 27; + easeIn.duration = 314; + easeOut.curve = 13; + easeOut.duration = 168; + bounce.enable = true; + bounce.duration = 271; + }; + }; + }; + + test.stubs.twmn = { }; + + nmt.script = '' + serviceFile="home-files/.config/systemd/user/twmnd.service" + assertFileExists "$serviceFile" + assertFileRegex "$serviceFile" 'X-Restart-Triggers=.*twmn\.conf' + assertFileRegex "$serviceFile" 'ExecStart=@twmn@/bin/twmnd' + assertFileExists "home-files/.config/twmn/twmn.conf" + assertFileContent "home-files/.config/twmn/twmn.conf" \ + ${./basic-configuration.conf} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/twmn/default.nix b/infra/libkookie/home-manager-stable/tests/modules/services/twmn/default.nix new file mode 100644 index 00000000000..8a021ba38cc --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/twmn/default.nix @@ -0,0 +1 @@ +{ twmn-basic-configuration = ./basic-configuration.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/bspwm/bspwmrc b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/bspwm/bspwmrc new file mode 100755 index 00000000000..ba0da830a0b --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/bspwm/bspwmrc @@ -0,0 +1,21 @@ +if [[ $(bspc query --desktops --names --monitor 'focused') == Desktop ]]; then + bspc monitor 'focused' -d 'desktop 1' 'd'\''esk top' +fi + +bspc config 'border_width' '2' +bspc config 'external_rules_command' '/path/to/external rules command' +bspc config 'gapless_monocle' 'on' +bspc config 'ignore_ewmh_fullscreen' 'enter,exit' +bspc config 'split_ratio' '0.520000' + +bspc rule -r '*' +bspc rule -a '*' 'center=off' 'desktop=d'\''esk top#next' 'split_dir=north' 'sticky=on' + +# java gui fixes +export _JAVA_AWT_WM_NONREPARENTING=1 +bspc rule -a sun-awt-X11-XDialogPeer state=floating + +extra config + +foo & +bar || qux & diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/bspwm/configuration.nix b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/bspwm/configuration.nix new file mode 100644 index 00000000000..e4aec0f6cb5 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/bspwm/configuration.nix @@ -0,0 +1,43 @@ +{ lib, pkgs, ... }: + +with lib; + +{ + config = { + xsession.windowManager.bspwm = { + enable = true; + monitors.focused = + [ "desktop 1" "d'esk top" ]; # pathological desktop names + alwaysResetDesktops = false; + settings = { + border_width = 2; + split_ratio = 0.52; + gapless_monocle = true; + external_rules_command = "/path/to/external rules command"; + ignore_ewmh_fullscreen = [ "enter" "exit" ]; + }; + rules."*" = { + sticky = true; + center = false; + desktop = "d'esk top#next"; + splitDir = "north"; + border = null; + }; + extraConfig = '' + extra config + ''; + startupPrograms = [ "foo" "bar || qux" ]; + }; + + test.stubs.bspwm = { }; + + nmt.script = '' + bspwmrc=home-files/.config/bspwm/bspwmrc + assertFileExists "$bspwmrc" + assertFileIsExecutable "$bspwmrc" + assertFileContent "$bspwmrc" ${ + pkgs.writeShellScript "bspwmrc-expected" (readFile ./bspwmrc) + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/bspwm/default.nix b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/bspwm/default.nix new file mode 100644 index 00000000000..45b5e2ae8a1 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/bspwm/default.nix @@ -0,0 +1 @@ +{ bspwm-configuration = ./configuration.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/herbstluftwm/autostart b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/herbstluftwm/autostart new file mode 100755 index 00000000000..d59da4baec9 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/herbstluftwm/autostart @@ -0,0 +1,48 @@ +#!/nix/store/00000000000000000000000000000000-bash/bin/bash +shopt -s expand_aliases + +# shellcheck disable=SC2142 +alias herbstclient='set -- "$@" ";"' +set -- + +herbstclient emit_hook reload + +# Reset everything. +herbstclient attr theme.tiling.reset 1 +herbstclient attr theme.floating.reset 1 +herbstclient keyunbind --all +herbstclient unrule --all + +herbstclient set always_show_frame true +herbstclient set default_frame_layout 'max' +herbstclient set frame_bg_active_color '#000000' +herbstclient set frame_gap '12' +herbstclient set frame_padding '-12' + +if @herbstluftwm@/bin/herbstclient object_tree tags.by-name | /nix/store/00000000000000000000000000000000-gnugrep/bin/grep default; then + herbstclient rename default '1' +fi + +for tag in '1' 'with space' 'wə1rd#ch@rs'\'''; do + herbstclient add "$tag" +done + +herbstclient keybind Mod4-1 use 1 +herbstclient keybind Mod4-2 use 2 +herbstclient keybind Mod4-Alt-Tab cycle -1 +herbstclient keybind Mod4-Tab cycle 1 + +herbstclient mousebind Mod4-B1 move +herbstclient mousebind Mod4-B3 resize + +herbstclient rule focus=on +herbstclient rule windowtype~'_NET_WM_WINDOW_TYPE_(DIALOG|UTILITY|SPLASH)' focus=on pseudotile=on +herbstclient rule class~'[Pp]inentry' instance=pinentry focus=on floating=on floatplacement=center keys_inactive='.*' + +herbstclient use 1 + + +herbstclient unlock + +@herbstluftwm@/bin/herbstclient chain ";" "$@" + diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/herbstluftwm/default.nix b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/herbstluftwm/default.nix new file mode 100644 index 00000000000..04b9f89c7df --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/herbstluftwm/default.nix @@ -0,0 +1 @@ +{ herbstluftwm-simple-config = ./herbstluftwm-simple-config.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/herbstluftwm/herbstluftwm-simple-config.nix b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/herbstluftwm/herbstluftwm-simple-config.nix new file mode 100644 index 00000000000..27e871505d6 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/herbstluftwm/herbstluftwm-simple-config.nix @@ -0,0 +1,44 @@ +{ lib, pkgs, ... }: + +{ + xsession.windowManager.herbstluftwm = { + enable = true; + settings = { + always_show_frame = true; + default_frame_layout = "max"; + frame_bg_active_color = "#000000"; + frame_gap = 12; + frame_padding = -12; + }; + keybinds = { + "Mod4-1" = "use 1"; + "Mod4-2" = "use 2"; + "Mod4-Tab" = "cycle 1"; + "Mod4-Alt-Tab" = "cycle -1"; + }; + mousebinds = { + "Mod4-B1" = "move"; + "Mod4-B3" = "resize"; + }; + rules = [ + "focus=on" + "windowtype~'_NET_WM_WINDOW_TYPE_(DIALOG|UTILITY|SPLASH)' focus=on pseudotile=on" + "class~'[Pp]inentry' instance=pinentry focus=on floating=on floatplacement=center keys_inactive='.*'" + ]; + tags = [ "1" "with space" "wə1rd#ch@rs'" ]; + extraConfig = '' + herbstclient use 1 + ''; + }; + + test.stubs.herbstluftwm = { }; + + nmt.script = '' + autostart=home-files/.config/herbstluftwm/autostart + assertFileExists "$autostart" + assertFileIsExecutable "$autostart" + + normalizedAutostart=$(normalizeStorePaths "$autostart") + assertFileContent "$normalizedAutostart" ${./autostart} + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/default.nix b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/default.nix new file mode 100644 index 00000000000..28631a1a5a2 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/default.nix @@ -0,0 +1,10 @@ +{ + i3-bar-focused-colors = ./i3-bar-focused-colors.nix; + i3-followmouse = ./i3-followmouse.nix; + i3-fonts = ./i3-fonts.nix; + i3-fonts-deprecated = ./i3-fonts-deprecated.nix; + i3-keybindings = ./i3-keybindings.nix; + i3-null-config = ./i3-null-config.nix; + i3-workspace-default = ./i3-workspace-default.nix; + i3-workspace-output = ./i3-workspace-output.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/i3-bar-focused-colors-expected.conf b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/i3-bar-focused-colors-expected.conf new file mode 100644 index 00000000000..92f23a921de --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/i3-bar-focused-colors-expected.conf @@ -0,0 +1,99 @@ +font pango:monospace 8.000000 +floating_modifier Mod1 +default_border normal 2 +default_floating_border normal 2 +hide_edge_borders none +force_focus_wrapping no +focus_follows_mouse yes +focus_on_window_activation smart +mouse_warping output +workspace_layout default +workspace_auto_back_and_forth no +client.focused #4c7899 #285577 #ffffff #2e9ef4 #285577 +client.focused_inactive #333333 #5f676a #ffffff #484e50 #5f676a +client.unfocused #333333 #222222 #888888 #292d2e #222222 +client.urgent #2f343a #900000 #ffffff #900000 #900000 +client.placeholder #000000 #0c0c0c #ffffff #000000 #0c0c0c +client.background #ffffff + +bindsym Mod1+0 workspace number 10 +bindsym Mod1+1 workspace number 1 +bindsym Mod1+2 workspace number 2 +bindsym Mod1+3 workspace number 3 +bindsym Mod1+4 workspace number 4 +bindsym Mod1+5 workspace number 5 +bindsym Mod1+6 workspace number 6 +bindsym Mod1+7 workspace number 7 +bindsym Mod1+8 workspace number 8 +bindsym Mod1+9 workspace number 9 +bindsym Mod1+Down focus down +bindsym Mod1+Left focus left +bindsym Mod1+Return exec i3-sensible-terminal +bindsym Mod1+Right focus right +bindsym Mod1+Shift+0 move container to workspace number 10 +bindsym Mod1+Shift+1 move container to workspace number 1 +bindsym Mod1+Shift+2 move container to workspace number 2 +bindsym Mod1+Shift+3 move container to workspace number 3 +bindsym Mod1+Shift+4 move container to workspace number 4 +bindsym Mod1+Shift+5 move container to workspace number 5 +bindsym Mod1+Shift+6 move container to workspace number 6 +bindsym Mod1+Shift+7 move container to workspace number 7 +bindsym Mod1+Shift+8 move container to workspace number 8 +bindsym Mod1+Shift+9 move container to workspace number 9 +bindsym Mod1+Shift+Down move down +bindsym Mod1+Shift+Left move left +bindsym Mod1+Shift+Right move right +bindsym Mod1+Shift+Up move up +bindsym Mod1+Shift+c reload +bindsym Mod1+Shift+e exec i3-nagbar -t warning -m 'Do you want to exit i3?' -b 'Yes' 'i3-msg exit' +bindsym Mod1+Shift+minus move scratchpad +bindsym Mod1+Shift+q kill +bindsym Mod1+Shift+r restart +bindsym Mod1+Shift+space floating toggle +bindsym Mod1+Up focus up +bindsym Mod1+a focus parent +bindsym Mod1+d exec @dmenu@/bin/dmenu_run +bindsym Mod1+e layout toggle split +bindsym Mod1+f fullscreen toggle +bindsym Mod1+h split h +bindsym Mod1+minus scratchpad show +bindsym Mod1+r mode resize +bindsym Mod1+s layout stacking +bindsym Mod1+space focus mode_toggle +bindsym Mod1+v split v +bindsym Mod1+w layout tabbed + +mode "resize" { + bindsym Down resize grow height 10 px or 10 ppt + bindsym Escape mode default + bindsym Left resize shrink width 10 px or 10 ppt + bindsym Return mode default + bindsym Right resize grow width 10 px or 10 ppt + bindsym Up resize shrink height 10 px or 10 ppt +} + +bar { + font pango:monospace 8.000000 + mode dock + hidden_state hide + position bottom + status_command @i3status@/bin/i3status + i3bar_command @i3@/bin/i3bar + workspace_buttons yes + strip_workspace_numbers no + tray_output primary + colors { + background #000000 + statusline #ffffff + separator #666666 + focused_background #ffffff + focused_statusline #000000 + focused_separator #999999 + focused_workspace #4c7899 #285577 #ffffff + active_workspace #333333 #5f676a #ffffff + inactive_workspace #333333 #222222 #888888 + urgent_workspace #2f343a #900000 #ffffff + binding_mode #2f343a #900000 #ffffff +} +} + diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/i3-bar-focused-colors.nix b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/i3-bar-focused-colors.nix new file mode 100644 index 00000000000..66b4ca87a4c --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/i3-bar-focused-colors.nix @@ -0,0 +1,21 @@ +{ config, lib, ... }: + +{ + imports = [ ./i3-stubs.nix ]; + + xsession.windowManager.i3 = { + enable = true; + + config.bars = [{ + colors.focusedBackground = "#ffffff"; + colors.focusedStatusline = "#000000"; + colors.focusedSeparator = "#999999"; + }]; + }; + + nmt.script = '' + assertFileExists home-files/.config/i3/config + assertFileContent home-files/.config/i3/config \ + ${./i3-bar-focused-colors-expected.conf} + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/i3-followmouse-expected.conf b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/i3-followmouse-expected.conf new file mode 100644 index 00000000000..27234b96db7 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/i3-followmouse-expected.conf @@ -0,0 +1,96 @@ +font pango:monospace 8.000000 +floating_modifier Mod1 +default_border normal 2 +default_floating_border normal 2 +hide_edge_borders none +force_focus_wrapping no +focus_follows_mouse no +focus_on_window_activation smart +mouse_warping output +workspace_layout default +workspace_auto_back_and_forth no +client.focused #4c7899 #285577 #ffffff #2e9ef4 #285577 +client.focused_inactive #333333 #5f676a #ffffff #484e50 #5f676a +client.unfocused #333333 #222222 #888888 #292d2e #222222 +client.urgent #2f343a #900000 #ffffff #900000 #900000 +client.placeholder #000000 #0c0c0c #ffffff #000000 #0c0c0c +client.background #ffffff + +bindsym Mod1+0 workspace number 10 +bindsym Mod1+1 workspace number 1 +bindsym Mod1+2 workspace number 2 +bindsym Mod1+3 workspace number 3 +bindsym Mod1+4 workspace number 4 +bindsym Mod1+5 workspace number 5 +bindsym Mod1+6 workspace number 6 +bindsym Mod1+7 workspace number 7 +bindsym Mod1+8 workspace number 8 +bindsym Mod1+9 workspace number 9 +bindsym Mod1+Down focus down +bindsym Mod1+Left focus left +bindsym Mod1+Return exec i3-sensible-terminal +bindsym Mod1+Right focus right +bindsym Mod1+Shift+0 move container to workspace number 10 +bindsym Mod1+Shift+1 move container to workspace number 1 +bindsym Mod1+Shift+2 move container to workspace number 2 +bindsym Mod1+Shift+3 move container to workspace number 3 +bindsym Mod1+Shift+4 move container to workspace number 4 +bindsym Mod1+Shift+5 move container to workspace number 5 +bindsym Mod1+Shift+6 move container to workspace number 6 +bindsym Mod1+Shift+7 move container to workspace number 7 +bindsym Mod1+Shift+8 move container to workspace number 8 +bindsym Mod1+Shift+9 move container to workspace number 9 +bindsym Mod1+Shift+Down move down +bindsym Mod1+Shift+Left move left +bindsym Mod1+Shift+Right move right +bindsym Mod1+Shift+Up move up +bindsym Mod1+Shift+c reload +bindsym Mod1+Shift+e exec i3-nagbar -t warning -m 'Do you want to exit i3?' -b 'Yes' 'i3-msg exit' +bindsym Mod1+Shift+minus move scratchpad +bindsym Mod1+Shift+q kill +bindsym Mod1+Shift+r restart +bindsym Mod1+Shift+space floating toggle +bindsym Mod1+Up focus up +bindsym Mod1+a focus parent +bindsym Mod1+d exec @dmenu@/bin/dmenu_run +bindsym Mod1+e layout toggle split +bindsym Mod1+f fullscreen toggle +bindsym Mod1+h split h +bindsym Mod1+minus scratchpad show +bindsym Mod1+r mode resize +bindsym Mod1+s layout stacking +bindsym Mod1+space focus mode_toggle +bindsym Mod1+v split v +bindsym Mod1+w layout tabbed + +mode "resize" { + bindsym Down resize grow height 10 px or 10 ppt + bindsym Escape mode default + bindsym Left resize shrink width 10 px or 10 ppt + bindsym Return mode default + bindsym Right resize grow width 10 px or 10 ppt + bindsym Up resize shrink height 10 px or 10 ppt +} + +bar { + font pango:monospace 8.000000 + mode dock + hidden_state hide + position bottom + status_command @i3status@/bin/i3status + i3bar_command @i3@/bin/i3bar + workspace_buttons yes + strip_workspace_numbers no + tray_output primary + colors { + background #000000 + statusline #ffffff + separator #666666 + focused_workspace #4c7899 #285577 #ffffff + active_workspace #333333 #5f676a #ffffff + inactive_workspace #333333 #222222 #888888 + urgent_workspace #2f343a #900000 #ffffff + binding_mode #2f343a #900000 #ffffff +} +} + diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/i3-followmouse.nix b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/i3-followmouse.nix new file mode 100644 index 00000000000..43e15cda396 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/i3-followmouse.nix @@ -0,0 +1,31 @@ +{ config, lib, ... }: + +with lib; + +{ + config = { + xsession.windowManager.i3 = { + enable = true; + + config.focus.followMouse = false; + }; + + nixpkgs.overlays = [ + (self: super: { + dmenu = super.dmenu // { outPath = "@dmenu@"; }; + + i3 = super.writeScriptBin "i3" "" // { outPath = "@i3@"; }; + + i3-gaps = super.writeScriptBin "i3" "" // { outPath = "@i3-gaps@"; }; + + i3status = super.i3status // { outPath = "@i3status@"; }; + }) + ]; + + nmt.script = '' + assertFileExists home-files/.config/i3/config + assertFileContent home-files/.config/i3/config \ + ${./i3-followmouse-expected.conf} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/i3-fonts-deprecated.nix b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/i3-fonts-deprecated.nix new file mode 100644 index 00000000000..7e4532e5717 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/i3-fonts-deprecated.nix @@ -0,0 +1,25 @@ +{ config, lib, ... }: + +{ + imports = [ ./i3-stubs.nix ]; + + xsession.windowManager.i3 = { + enable = true; + + config = { + bars = [{ fonts = [ "FontAwesome" "Iosevka 11.500000" ]; }]; + fonts = [ "DejaVuSansMono" "Terminus Bold Semi-Condensed 13.500000" ]; + }; + }; + + nmt.script = '' + assertFileExists home-files/.config/i3/config + assertFileContent home-files/.config/i3/config \ + ${./i3-fonts-expected.conf} + ''; + + test.asserts.warnings.expected = [ + "Specifying i3.config.fonts as a list is deprecated. Use the attrset version instead." + "Specifying i3.config.bars[].fonts as a list is deprecated. Use the attrset version instead." + ]; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/i3-fonts-expected.conf b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/i3-fonts-expected.conf new file mode 100644 index 00000000000..d85d978e07d --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/i3-fonts-expected.conf @@ -0,0 +1,96 @@ +font pango:DejaVuSansMono, Terminus Bold Semi-Condensed 13.500000 +floating_modifier Mod1 +default_border normal 2 +default_floating_border normal 2 +hide_edge_borders none +force_focus_wrapping no +focus_follows_mouse yes +focus_on_window_activation smart +mouse_warping output +workspace_layout default +workspace_auto_back_and_forth no +client.focused #4c7899 #285577 #ffffff #2e9ef4 #285577 +client.focused_inactive #333333 #5f676a #ffffff #484e50 #5f676a +client.unfocused #333333 #222222 #888888 #292d2e #222222 +client.urgent #2f343a #900000 #ffffff #900000 #900000 +client.placeholder #000000 #0c0c0c #ffffff #000000 #0c0c0c +client.background #ffffff + +bindsym Mod1+0 workspace number 10 +bindsym Mod1+1 workspace number 1 +bindsym Mod1+2 workspace number 2 +bindsym Mod1+3 workspace number 3 +bindsym Mod1+4 workspace number 4 +bindsym Mod1+5 workspace number 5 +bindsym Mod1+6 workspace number 6 +bindsym Mod1+7 workspace number 7 +bindsym Mod1+8 workspace number 8 +bindsym Mod1+9 workspace number 9 +bindsym Mod1+Down focus down +bindsym Mod1+Left focus left +bindsym Mod1+Return exec i3-sensible-terminal +bindsym Mod1+Right focus right +bindsym Mod1+Shift+0 move container to workspace number 10 +bindsym Mod1+Shift+1 move container to workspace number 1 +bindsym Mod1+Shift+2 move container to workspace number 2 +bindsym Mod1+Shift+3 move container to workspace number 3 +bindsym Mod1+Shift+4 move container to workspace number 4 +bindsym Mod1+Shift+5 move container to workspace number 5 +bindsym Mod1+Shift+6 move container to workspace number 6 +bindsym Mod1+Shift+7 move container to workspace number 7 +bindsym Mod1+Shift+8 move container to workspace number 8 +bindsym Mod1+Shift+9 move container to workspace number 9 +bindsym Mod1+Shift+Down move down +bindsym Mod1+Shift+Left move left +bindsym Mod1+Shift+Right move right +bindsym Mod1+Shift+Up move up +bindsym Mod1+Shift+c reload +bindsym Mod1+Shift+e exec i3-nagbar -t warning -m 'Do you want to exit i3?' -b 'Yes' 'i3-msg exit' +bindsym Mod1+Shift+minus move scratchpad +bindsym Mod1+Shift+q kill +bindsym Mod1+Shift+r restart +bindsym Mod1+Shift+space floating toggle +bindsym Mod1+Up focus up +bindsym Mod1+a focus parent +bindsym Mod1+d exec @dmenu@/bin/dmenu_run +bindsym Mod1+e layout toggle split +bindsym Mod1+f fullscreen toggle +bindsym Mod1+h split h +bindsym Mod1+minus scratchpad show +bindsym Mod1+r mode resize +bindsym Mod1+s layout stacking +bindsym Mod1+space focus mode_toggle +bindsym Mod1+v split v +bindsym Mod1+w layout tabbed + +mode "resize" { + bindsym Down resize grow height 10 px or 10 ppt + bindsym Escape mode default + bindsym Left resize shrink width 10 px or 10 ppt + bindsym Return mode default + bindsym Right resize grow width 10 px or 10 ppt + bindsym Up resize shrink height 10 px or 10 ppt +} + +bar { + font pango:FontAwesome, Iosevka 11.500000 + mode dock + hidden_state hide + position bottom + status_command @i3status@/bin/i3status + i3bar_command @i3@/bin/i3bar + workspace_buttons yes + strip_workspace_numbers no + tray_output primary + colors { + background #000000 + statusline #ffffff + separator #666666 + focused_workspace #4c7899 #285577 #ffffff + active_workspace #333333 #5f676a #ffffff + inactive_workspace #333333 #222222 #888888 + urgent_workspace #2f343a #900000 #ffffff + binding_mode #2f343a #900000 #ffffff +} +} + diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/i3-fonts.nix b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/i3-fonts.nix new file mode 100644 index 00000000000..3618451f84c --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/i3-fonts.nix @@ -0,0 +1,29 @@ +{ config, lib, ... }: + +{ + imports = [ ./i3-stubs.nix ]; + + xsession.windowManager.i3 = { + enable = true; + + config = { + bars = [{ + fonts = { + names = [ "FontAwesome" "Iosevka" ]; + size = 11.5; + }; + }]; + fonts = { + names = [ "DejaVuSansMono" "Terminus" ]; + style = "Bold Semi-Condensed"; + size = 13.5; + }; + }; + }; + + nmt.script = '' + assertFileExists home-files/.config/i3/config + assertFileContent home-files/.config/i3/config \ + ${./i3-fonts-expected.conf} + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/i3-keybindings-expected.conf b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/i3-keybindings-expected.conf new file mode 100644 index 00000000000..b3b4c33dea8 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/i3-keybindings-expected.conf @@ -0,0 +1,97 @@ +font pango:monospace 8.000000 +floating_modifier Mod1 +default_border normal 2 +default_floating_border normal 2 +hide_edge_borders none +force_focus_wrapping no +focus_follows_mouse yes +focus_on_window_activation smart +mouse_warping output +workspace_layout default +workspace_auto_back_and_forth no +client.focused #4c7899 #285577 #ffffff #2e9ef4 #285577 +client.focused_inactive #333333 #5f676a #ffffff #484e50 #5f676a +client.unfocused #333333 #222222 #888888 #292d2e #222222 +client.urgent #2f343a #900000 #ffffff #900000 #900000 +client.placeholder #000000 #0c0c0c #ffffff #000000 #0c0c0c +client.background #ffffff + +bindsym Mod1+0 workspace number 10 +bindsym Mod1+1 workspace number 1 +bindsym Mod1+2 workspace number 2 +bindsym Mod1+3 workspace number 3 +bindsym Mod1+4 workspace number 4 +bindsym Mod1+5 workspace number 5 +bindsym Mod1+6 workspace number 6 +bindsym Mod1+7 workspace number 7 +bindsym Mod1+8 workspace number 8 +bindsym Mod1+9 workspace number 9 +bindsym Mod1+Down focus down +bindsym Mod1+Invented invented-key-command +bindsym Mod1+Left overridden-command +bindsym Mod1+Return exec i3-sensible-terminal + +bindsym Mod1+Shift+0 move container to workspace number 10 +bindsym Mod1+Shift+1 move container to workspace number 1 +bindsym Mod1+Shift+2 move container to workspace number 2 +bindsym Mod1+Shift+3 move container to workspace number 3 +bindsym Mod1+Shift+4 move container to workspace number 4 +bindsym Mod1+Shift+5 move container to workspace number 5 +bindsym Mod1+Shift+6 move container to workspace number 6 +bindsym Mod1+Shift+7 move container to workspace number 7 +bindsym Mod1+Shift+8 move container to workspace number 8 +bindsym Mod1+Shift+9 move container to workspace number 9 +bindsym Mod1+Shift+Down move down +bindsym Mod1+Shift+Left move left +bindsym Mod1+Shift+Right move right +bindsym Mod1+Shift+Up move up +bindsym Mod1+Shift+c reload +bindsym Mod1+Shift+e exec i3-nagbar -t warning -m 'Do you want to exit i3?' -b 'Yes' 'i3-msg exit' +bindsym Mod1+Shift+minus move scratchpad +bindsym Mod1+Shift+q kill +bindsym Mod1+Shift+r restart +bindsym Mod1+Shift+space floating toggle +bindsym Mod1+Up focus up +bindsym Mod1+a focus parent +bindsym Mod1+d exec @dmenu@/bin/dmenu_run +bindsym Mod1+e layout toggle split +bindsym Mod1+f fullscreen toggle +bindsym Mod1+h split h +bindsym Mod1+minus scratchpad show +bindsym Mod1+r mode resize +bindsym Mod1+s layout stacking +bindsym Mod1+space focus mode_toggle +bindsym Mod1+v split v +bindsym Mod1+w layout tabbed + +mode "resize" { + bindsym Down resize grow height 10 px or 10 ppt + bindsym Escape mode default + bindsym Left resize shrink width 10 px or 10 ppt + bindsym Return mode default + bindsym Right resize grow width 10 px or 10 ppt + bindsym Up resize shrink height 10 px or 10 ppt +} + +bar { + font pango:monospace 8.000000 + mode dock + hidden_state hide + position bottom + status_command @i3status@/bin/i3status + i3bar_command @i3@/bin/i3bar + workspace_buttons yes + strip_workspace_numbers no + tray_output primary + colors { + background #000000 + statusline #ffffff + separator #666666 + focused_workspace #4c7899 #285577 #ffffff + active_workspace #333333 #5f676a #ffffff + inactive_workspace #333333 #222222 #888888 + urgent_workspace #2f343a #900000 #ffffff + binding_mode #2f343a #900000 #ffffff +} +} + diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/i3-keybindings.nix b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/i3-keybindings.nix new file mode 100644 index 00000000000..2137c53edb1 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/i3-keybindings.nix @@ -0,0 +1,23 @@ +{ config, lib, ... }: + +{ + imports = [ ./i3-stubs.nix ]; + + xsession.windowManager.i3 = { + enable = true; + + config.keybindings = + let modifier = config.xsession.windowManager.i3.config.modifier; + in lib.mkOptionDefault { + "${modifier}+Left" = "overridden-command"; + "${modifier}+Right" = null; + "${modifier}+Invented" = "invented-key-command"; + }; + }; + + nmt.script = '' + assertFileExists home-files/.config/i3/config + assertFileContent home-files/.config/i3/config \ + ${./i3-keybindings-expected.conf} + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/i3-null-config.nix b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/i3-null-config.nix new file mode 100644 index 00000000000..f321ad49a59 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/i3-null-config.nix @@ -0,0 +1,16 @@ +{ config, lib, pkgs, ... }: + +{ + imports = [ ./i3-stubs.nix ]; + + xsession.windowManager.i3 = { + enable = true; + config = null; + }; + + nmt.script = '' + assertFileExists home-files/.config/i3/config + assertFileContent home-files/.config/i3/config \ + ${pkgs.writeText "expected" ""} + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/i3-stubs.nix b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/i3-stubs.nix new file mode 100644 index 00000000000..cfb892ace8b --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/i3-stubs.nix @@ -0,0 +1,19 @@ +{ + # Avoid unnecessary downloads in CI jobs and/or make out paths constant, i.e., + # not containing hashes, version numbers etc. + test.stubs = { + dmenu = { }; + + i3 = { + buildScript = '' + mkdir -p $out/bin + echo '#!/bin/sh' > $out/bin/i3 + chmod 755 $out/bin/i3 + ''; + }; + + i3-gaps = { }; + + i3status = { }; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/i3-workspace-default-expected.conf b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/i3-workspace-default-expected.conf new file mode 100644 index 00000000000..d7fe4b61043 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/i3-workspace-default-expected.conf @@ -0,0 +1,95 @@ +font pango:monospace 8.000000 +floating_modifier Mod1 +default_border normal 2 +default_floating_border normal 2 +hide_edge_borders none +force_focus_wrapping no +focus_follows_mouse yes +focus_on_window_activation smart +mouse_warping output +workspace_layout default +workspace_auto_back_and_forth no +client.focused #4c7899 #285577 #ffffff #2e9ef4 #285577 +client.focused_inactive #333333 #5f676a #ffffff #484e50 #5f676a +client.unfocused #333333 #222222 #888888 #292d2e #222222 +client.urgent #2f343a #900000 #ffffff #900000 #900000 +client.placeholder #000000 #0c0c0c #ffffff #000000 #0c0c0c +client.background #ffffff +bindsym Mod1+1 workspace number 1 +bindsym Mod1+0 workspace number 10 +bindsym Mod1+2 workspace number 2 +bindsym Mod1+3 workspace number 3 +bindsym Mod1+4 workspace number 4 +bindsym Mod1+5 workspace number 5 +bindsym Mod1+6 workspace number 6 +bindsym Mod1+7 workspace number 7 +bindsym Mod1+8 workspace number 8 +bindsym Mod1+9 workspace number 9 +bindsym Mod1+Down focus down +bindsym Mod1+Left focus left +bindsym Mod1+Return exec i3-sensible-terminal +bindsym Mod1+Right focus right +bindsym Mod1+Shift+0 move container to workspace number 10 +bindsym Mod1+Shift+1 move container to workspace number 1 +bindsym Mod1+Shift+2 move container to workspace number 2 +bindsym Mod1+Shift+3 move container to workspace number 3 +bindsym Mod1+Shift+4 move container to workspace number 4 +bindsym Mod1+Shift+5 move container to workspace number 5 +bindsym Mod1+Shift+6 move container to workspace number 6 +bindsym Mod1+Shift+7 move container to workspace number 7 +bindsym Mod1+Shift+8 move container to workspace number 8 +bindsym Mod1+Shift+9 move container to workspace number 9 +bindsym Mod1+Shift+Down move down +bindsym Mod1+Shift+Left move left +bindsym Mod1+Shift+Right move right +bindsym Mod1+Shift+Up move up +bindsym Mod1+Shift+c reload +bindsym Mod1+Shift+e exec i3-nagbar -t warning -m 'Do you want to exit i3?' -b 'Yes' 'i3-msg exit' +bindsym Mod1+Shift+minus move scratchpad +bindsym Mod1+Shift+q kill +bindsym Mod1+Shift+r restart +bindsym Mod1+Shift+space floating toggle +bindsym Mod1+Up focus up +bindsym Mod1+a focus parent +bindsym Mod1+d exec @dmenu@/bin/dmenu_run +bindsym Mod1+e layout toggle split +bindsym Mod1+f fullscreen toggle +bindsym Mod1+h split h +bindsym Mod1+minus scratchpad show +bindsym Mod1+r mode resize +bindsym Mod1+s layout stacking +bindsym Mod1+space focus mode_toggle +bindsym Mod1+v split v +bindsym Mod1+w layout tabbed + +mode "resize" { + bindsym Down resize grow height 10 px or 10 ppt + bindsym Escape mode default + bindsym Left resize shrink width 10 px or 10 ppt + bindsym Return mode default + bindsym Right resize grow width 10 px or 10 ppt + bindsym Up resize shrink height 10 px or 10 ppt +} + +bar { + font pango:monospace 8.000000 + mode dock + hidden_state hide + position bottom + status_command @i3status@/bin/i3status + i3bar_command @i3@/bin/i3bar + workspace_buttons yes + strip_workspace_numbers no + tray_output primary + colors { + background #000000 + statusline #ffffff + separator #666666 + focused_workspace #4c7899 #285577 #ffffff + active_workspace #333333 #5f676a #ffffff + inactive_workspace #333333 #222222 #888888 + urgent_workspace #2f343a #900000 #ffffff + binding_mode #2f343a #900000 #ffffff +} +} + diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/i3-workspace-default.nix b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/i3-workspace-default.nix new file mode 100644 index 00000000000..521b5f5d75b --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/i3-workspace-default.nix @@ -0,0 +1,17 @@ +{ config, lib, ... }: + +{ + imports = [ ./i3-stubs.nix ]; + + xsession.windowManager.i3 = { + enable = true; + + config.defaultWorkspace = "workspace number 1"; + }; + + nmt.script = '' + assertFileExists home-files/.config/i3/config + assertFileContent home-files/.config/i3/config \ + ${./i3-workspace-default-expected.conf} + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/i3-workspace-output-expected.conf b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/i3-workspace-output-expected.conf new file mode 100644 index 00000000000..dedad29e0b1 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/i3-workspace-output-expected.conf @@ -0,0 +1,100 @@ +font pango:monospace 8.000000 +floating_modifier Mod1 +default_border normal 2 +default_floating_border normal 2 +hide_edge_borders none +force_focus_wrapping no +focus_follows_mouse yes +focus_on_window_activation smart +mouse_warping output +workspace_layout default +workspace_auto_back_and_forth no +client.focused #4c7899 #285577 #ffffff #2e9ef4 #285577 +client.focused_inactive #333333 #5f676a #ffffff #484e50 #5f676a +client.unfocused #333333 #222222 #888888 #292d2e #222222 +client.urgent #2f343a #900000 #ffffff #900000 #900000 +client.placeholder #000000 #0c0c0c #ffffff #000000 #0c0c0c +client.background #ffffff + +bindsym Mod1+0 workspace number 10 +bindsym Mod1+1 workspace number 1 +bindsym Mod1+2 workspace number 2 +bindsym Mod1+3 workspace number 3 +bindsym Mod1+4 workspace number 4 +bindsym Mod1+5 workspace number 5 +bindsym Mod1+6 workspace number 6 +bindsym Mod1+7 workspace number 7 +bindsym Mod1+8 workspace number 8 +bindsym Mod1+9 workspace number 9 +bindsym Mod1+Down focus down +bindsym Mod1+Left focus left +bindsym Mod1+Return exec i3-sensible-terminal +bindsym Mod1+Right focus right +bindsym Mod1+Shift+0 move container to workspace number 10 +bindsym Mod1+Shift+1 move container to workspace number 1 +bindsym Mod1+Shift+2 move container to workspace number 2 +bindsym Mod1+Shift+3 move container to workspace number 3 +bindsym Mod1+Shift+4 move container to workspace number 4 +bindsym Mod1+Shift+5 move container to workspace number 5 +bindsym Mod1+Shift+6 move container to workspace number 6 +bindsym Mod1+Shift+7 move container to workspace number 7 +bindsym Mod1+Shift+8 move container to workspace number 8 +bindsym Mod1+Shift+9 move container to workspace number 9 +bindsym Mod1+Shift+Down move down +bindsym Mod1+Shift+Left move left +bindsym Mod1+Shift+Right move right +bindsym Mod1+Shift+Up move up +bindsym Mod1+Shift+c reload +bindsym Mod1+Shift+e exec i3-nagbar -t warning -m 'Do you want to exit i3?' -b 'Yes' 'i3-msg exit' +bindsym Mod1+Shift+minus move scratchpad +bindsym Mod1+Shift+q kill +bindsym Mod1+Shift+r restart +bindsym Mod1+Shift+space floating toggle +bindsym Mod1+Up focus up +bindsym Mod1+a focus parent +bindsym Mod1+d exec @dmenu@/bin/dmenu_run +bindsym Mod1+e layout toggle split +bindsym Mod1+f fullscreen toggle +bindsym Mod1+h split h +bindsym Mod1+minus scratchpad show +bindsym Mod1+r mode resize +bindsym Mod1+s layout stacking +bindsym Mod1+space focus mode_toggle +bindsym Mod1+v split v +bindsym Mod1+w layout tabbed + +mode "resize" { + bindsym Down resize grow height 10 px or 10 ppt + bindsym Escape mode default + bindsym Left resize shrink width 10 px or 10 ppt + bindsym Return mode default + bindsym Right resize grow width 10 px or 10 ppt + bindsym Up resize shrink height 10 px or 10 ppt +} + +bar { + font pango:monospace 8.000000 + mode dock + hidden_state hide + position bottom + status_command @i3status@/bin/i3status + i3bar_command @i3@/bin/i3bar + workspace_buttons yes + strip_workspace_numbers no + tray_output primary + colors { + background #000000 + statusline #ffffff + separator #666666 + focused_workspace #4c7899 #285577 #ffffff + active_workspace #333333 #5f676a #ffffff + inactive_workspace #333333 #222222 #888888 + urgent_workspace #2f343a #900000 #ffffff + binding_mode #2f343a #900000 #ffffff +} +} + +workspace "1" output eDP +workspace "ABC" output DP +workspace "3: Test" output HDMI +workspace "!"§$%&/(){}[]=?\*#<>-_.:,;²³" output DVI diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/i3-workspace-output.nix b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/i3-workspace-output.nix new file mode 100644 index 00000000000..df4a2c78903 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/i3/i3-workspace-output.nix @@ -0,0 +1,42 @@ +{ config, lib, ... }: + +let + i3 = { + ws1 = "1"; + ws2 = "ABC"; + ws3 = "3: Test"; + ws4 = ''!"§$%&/(){}[]=?\*#<>-_.:,;²³''; + }; + +in { + imports = [ ./i3-stubs.nix ]; + + xsession.windowManager.i3 = { + enable = true; + + config.workspaceOutputAssign = [ + { + workspace = "${i3.ws1}"; + output = "eDP"; + } + { + workspace = "${i3.ws2}"; + output = "DP"; + } + { + workspace = "${i3.ws3}"; + output = "HDMI"; + } + { + workspace = "${i3.ws4}"; + output = "DVI"; + } + ]; + }; + + nmt.script = '' + assertFileExists home-files/.config/i3/config + assertFileContent home-files/.config/i3/config \ + ${./i3-workspace-output-expected.conf} + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/default.nix b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/default.nix new file mode 100644 index 00000000000..7cc948ca4cc --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/default.nix @@ -0,0 +1,16 @@ +{ + sway-bar-focused-colors = ./sway-bar-focused-colors.nix; + sway-bindkeys-to-code = ./sway-bindkeys-to-code.nix; + sway-default = ./sway-default.nix; + sway-followmouse = ./sway-followmouse.nix; + sway-followmouse-legacy = ./sway-followmouse-legacy.nix; + sway-modules = ./sway-modules.nix; + sway-no-xwayland = ./sway-no-xwayland.nix; + sway-null-config = ./sway-null-config.nix; + sway-null-package = ./sway-null-package.nix; + sway-post-2003 = ./sway-post-2003.nix; + sway-workspace-default = ./sway-workspace-default.nix; + sway-workspace-output = ./sway-workspace-output.nix; + swaynag-example-settings = ./swaynag-example-settings.nix; + swaynag-empty-settings = ./swaynag-empty-settings.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-bar-focused-colors.conf b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-bar-focused-colors.conf new file mode 100644 index 00000000000..f8e109aab64 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-bar-focused-colors.conf @@ -0,0 +1,109 @@ +font pango:monospace 8.000000 +floating_modifier Mod1 +default_border pixel 2 +default_floating_border pixel 2 +hide_edge_borders none +focus_wrapping no +focus_follows_mouse yes +focus_on_window_activation smart +mouse_warping output +workspace_layout default +workspace_auto_back_and_forth no +client.focused #4c7899 #285577 #ffffff #2e9ef4 #285577 +client.focused_inactive #333333 #5f676a #ffffff #484e50 #5f676a +client.unfocused #333333 #222222 #888888 #292d2e #222222 +client.urgent #2f343a #900000 #ffffff #900000 #900000 +client.placeholder #000000 #0c0c0c #ffffff #000000 #0c0c0c +client.background #ffffff + +bindsym Mod1+1 workspace number 1 +bindsym Mod1+2 workspace number 2 +bindsym Mod1+3 workspace number 3 +bindsym Mod1+4 workspace number 4 +bindsym Mod1+5 workspace number 5 +bindsym Mod1+6 workspace number 6 +bindsym Mod1+7 workspace number 7 +bindsym Mod1+8 workspace number 8 +bindsym Mod1+9 workspace number 9 +bindsym Mod1+Down focus down +bindsym Mod1+Left focus left +bindsym Mod1+Return exec @rxvt-unicode-unwrapped@/bin/urxvt +bindsym Mod1+Right focus right +bindsym Mod1+Shift+1 move container to workspace number 1 +bindsym Mod1+Shift+2 move container to workspace number 2 +bindsym Mod1+Shift+3 move container to workspace number 3 +bindsym Mod1+Shift+4 move container to workspace number 4 +bindsym Mod1+Shift+5 move container to workspace number 5 +bindsym Mod1+Shift+6 move container to workspace number 6 +bindsym Mod1+Shift+7 move container to workspace number 7 +bindsym Mod1+Shift+8 move container to workspace number 8 +bindsym Mod1+Shift+9 move container to workspace number 9 +bindsym Mod1+Shift+Down move down +bindsym Mod1+Shift+Left move left +bindsym Mod1+Shift+Right move right +bindsym Mod1+Shift+Up move up +bindsym Mod1+Shift+c reload +bindsym Mod1+Shift+e exec swaynag -t warning -m 'You pressed the exit shortcut. Do you really want to exit sway? This will end your Wayland session.' -b 'Yes, exit sway' 'swaymsg exit' +bindsym Mod1+Shift+h move left +bindsym Mod1+Shift+j move down +bindsym Mod1+Shift+k move up +bindsym Mod1+Shift+l move right +bindsym Mod1+Shift+minus move scratchpad +bindsym Mod1+Shift+q kill +bindsym Mod1+Shift+space floating toggle +bindsym Mod1+Up focus up +bindsym Mod1+a focus parent +bindsym Mod1+b splith +bindsym Mod1+d exec @dmenu@/bin/dmenu_run +bindsym Mod1+e layout toggle split +bindsym Mod1+f fullscreen toggle +bindsym Mod1+h focus left +bindsym Mod1+j focus down +bindsym Mod1+k focus up +bindsym Mod1+l focus right +bindsym Mod1+minus scratchpad show +bindsym Mod1+r mode resize +bindsym Mod1+s layout stacking +bindsym Mod1+space focus mode_toggle +bindsym Mod1+v splitv +bindsym Mod1+w layout tabbed + +mode "resize" { + bindsym Down resize grow height 10 px + bindsym Escape mode default + bindsym Left resize shrink width 10 px + bindsym Return mode default + bindsym Right resize grow width 10 px + bindsym Up resize shrink height 10 px + bindsym h resize shrink width 10 px + bindsym j resize grow height 10 px + bindsym k resize shrink height 10 px + bindsym l resize grow width 10 px +} + +bar { + font pango:monospace 8.000000 + mode dock + hidden_state hide + position bottom + status_command @i3status@/bin/i3status + swaybar_command @sway@/bin/swaybar + workspace_buttons yes + strip_workspace_numbers no + tray_output primary + colors { + background #000000 + statusline #ffffff + separator #666666 + focused_background #ffffff + focused_statusline #000000 + focused_separator #999999 + focused_workspace #4c7899 #285577 #ffffff + active_workspace #333333 #5f676a #ffffff + inactive_workspace #333333 #222222 #888888 + urgent_workspace #2f343a #900000 #ffffff + binding_mode #2f343a #900000 #ffffff +} +} + +exec "systemctl --user import-environment; systemctl --user start sway-session.target" diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-bar-focused-colors.nix b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-bar-focused-colors.nix new file mode 100644 index 00000000000..9746d05038d --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-bar-focused-colors.nix @@ -0,0 +1,24 @@ +{ config, lib, pkgs, ... }: + +{ + imports = [ ./sway-stubs.nix ]; + + wayland.windowManager.sway = { + enable = true; + package = config.lib.test.mkStubPackage { outPath = "@sway@"; }; + # overriding findutils causes issues + config.menu = "${pkgs.dmenu}/bin/dmenu_run"; + + config.bars = [{ + colors.focusedBackground = "#ffffff"; + colors.focusedStatusline = "#000000"; + colors.focusedSeparator = "#999999"; + }]; + }; + + nmt.script = '' + assertFileExists home-files/.config/sway/config + assertFileContent home-files/.config/sway/config \ + ${./sway-bar-focused-colors.conf} + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-bindkeys-to-code.conf b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-bindkeys-to-code.conf new file mode 100644 index 00000000000..ce9fac65d1d --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-bindkeys-to-code.conf @@ -0,0 +1,106 @@ +font pango:monospace 8.000000 +floating_modifier Mod1 +default_border pixel 2 +default_floating_border pixel 2 +hide_edge_borders none +focus_wrapping no +focus_follows_mouse yes +focus_on_window_activation smart +mouse_warping output +workspace_layout default +workspace_auto_back_and_forth no +client.focused #4c7899 #285577 #ffffff #2e9ef4 #285577 +client.focused_inactive #333333 #5f676a #ffffff #484e50 #5f676a +client.unfocused #333333 #222222 #888888 #292d2e #222222 +client.urgent #2f343a #900000 #ffffff #900000 #900000 +client.placeholder #000000 #0c0c0c #ffffff #000000 #0c0c0c +client.background #ffffff + +bindsym --to-code Mod1+1 workspace number 1 +bindsym --to-code Mod1+2 workspace number 2 +bindsym --to-code Mod1+3 workspace number 3 +bindsym --to-code Mod1+4 workspace number 4 +bindsym --to-code Mod1+5 workspace number 5 +bindsym --to-code Mod1+6 workspace number 6 +bindsym --to-code Mod1+7 workspace number 7 +bindsym --to-code Mod1+8 workspace number 8 +bindsym --to-code Mod1+9 workspace number 9 +bindsym --to-code Mod1+Down focus down +bindsym --to-code Mod1+Left focus left +bindsym --to-code Mod1+Return exec @rxvt-unicode-unwrapped@/bin/urxvt +bindsym --to-code Mod1+Right focus right +bindsym --to-code Mod1+Shift+1 move container to workspace number 1 +bindsym --to-code Mod1+Shift+2 move container to workspace number 2 +bindsym --to-code Mod1+Shift+3 move container to workspace number 3 +bindsym --to-code Mod1+Shift+4 move container to workspace number 4 +bindsym --to-code Mod1+Shift+5 move container to workspace number 5 +bindsym --to-code Mod1+Shift+6 move container to workspace number 6 +bindsym --to-code Mod1+Shift+7 move container to workspace number 7 +bindsym --to-code Mod1+Shift+8 move container to workspace number 8 +bindsym --to-code Mod1+Shift+9 move container to workspace number 9 +bindsym --to-code Mod1+Shift+Down move down +bindsym --to-code Mod1+Shift+Left move left +bindsym --to-code Mod1+Shift+Right move right +bindsym --to-code Mod1+Shift+Up move up +bindsym --to-code Mod1+Shift+c reload +bindsym --to-code Mod1+Shift+e exec swaynag -t warning -m 'You pressed the exit shortcut. Do you really want to exit sway? This will end your Wayland session.' -b 'Yes, exit sway' 'swaymsg exit' +bindsym --to-code Mod1+Shift+h move left +bindsym --to-code Mod1+Shift+j move down +bindsym --to-code Mod1+Shift+k move up +bindsym --to-code Mod1+Shift+l move right +bindsym --to-code Mod1+Shift+minus move scratchpad +bindsym --to-code Mod1+Shift+q kill +bindsym --to-code Mod1+Shift+space floating toggle +bindsym --to-code Mod1+Up focus up +bindsym --to-code Mod1+a focus parent +bindsym --to-code Mod1+b splith +bindsym --to-code Mod1+d exec @dmenu@/bin/dmenu_run +bindsym --to-code Mod1+e layout toggle split +bindsym --to-code Mod1+f fullscreen toggle +bindsym --to-code Mod1+h focus left +bindsym --to-code Mod1+j focus down +bindsym --to-code Mod1+k focus up +bindsym --to-code Mod1+l focus right +bindsym --to-code Mod1+minus scratchpad show +bindsym --to-code Mod1+r mode resize +bindsym --to-code Mod1+s layout stacking +bindsym --to-code Mod1+space focus mode_toggle +bindsym --to-code Mod1+v splitv +bindsym --to-code Mod1+w layout tabbed + +mode "resize" { + bindsym --to-code Down resize grow height 10 px + bindsym --to-code Escape mode default + bindsym --to-code Left resize shrink width 10 px + bindsym --to-code Return mode default + bindsym --to-code Right resize grow width 10 px + bindsym --to-code Up resize shrink height 10 px + bindsym --to-code h resize shrink width 10 px + bindsym --to-code j resize grow height 10 px + bindsym --to-code k resize shrink height 10 px + bindsym --to-code l resize grow width 10 px +} + +bar { + font pango:monospace 8.000000 + mode dock + hidden_state hide + position bottom + status_command @i3status@/bin/i3status + swaybar_command @sway@/bin/swaybar + workspace_buttons yes + strip_workspace_numbers no + tray_output primary + colors { + background #000000 + statusline #ffffff + separator #666666 + focused_workspace #4c7899 #285577 #ffffff + active_workspace #333333 #5f676a #ffffff + inactive_workspace #333333 #222222 #888888 + urgent_workspace #2f343a #900000 #ffffff + binding_mode #2f343a #900000 #ffffff +} +} + +exec "systemctl --user import-environment; systemctl --user start sway-session.target" diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-bindkeys-to-code.nix b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-bindkeys-to-code.nix new file mode 100644 index 00000000000..5e62748cb9e --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-bindkeys-to-code.nix @@ -0,0 +1,19 @@ +{ config, lib, pkgs, ... }: + +{ + imports = [ ./sway-stubs.nix ]; + + wayland.windowManager.sway = { + enable = true; + package = config.lib.test.mkStubPackage { outPath = "@sway@"; }; + # overriding findutils causes issues + config.menu = "${pkgs.dmenu}/bin/dmenu_run"; + config.bindkeysToCode = true; + }; + + nmt.script = '' + assertFileExists home-files/.config/sway/config + assertFileContent home-files/.config/sway/config \ + ${./sway-bindkeys-to-code.conf} + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-default.conf b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-default.conf new file mode 100644 index 00000000000..82cf254e5e6 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-default.conf @@ -0,0 +1,106 @@ +font pango:monospace 8.000000 +floating_modifier Mod1 +default_border pixel 2 +default_floating_border pixel 2 +hide_edge_borders none +focus_wrapping no +focus_follows_mouse yes +focus_on_window_activation smart +mouse_warping output +workspace_layout default +workspace_auto_back_and_forth no +client.focused #4c7899 #285577 #ffffff #2e9ef4 #285577 +client.focused_inactive #333333 #5f676a #ffffff #484e50 #5f676a +client.unfocused #333333 #222222 #888888 #292d2e #222222 +client.urgent #2f343a #900000 #ffffff #900000 #900000 +client.placeholder #000000 #0c0c0c #ffffff #000000 #0c0c0c +client.background #ffffff + +bindsym Mod1+1 workspace number 1 +bindsym Mod1+2 workspace number 2 +bindsym Mod1+3 workspace number 3 +bindsym Mod1+4 workspace number 4 +bindsym Mod1+5 workspace number 5 +bindsym Mod1+6 workspace number 6 +bindsym Mod1+7 workspace number 7 +bindsym Mod1+8 workspace number 8 +bindsym Mod1+9 workspace number 9 +bindsym Mod1+Down focus down +bindsym Mod1+Left focus left +bindsym Mod1+Return exec @rxvt-unicode-unwrapped@/bin/urxvt +bindsym Mod1+Right focus right +bindsym Mod1+Shift+1 move container to workspace number 1 +bindsym Mod1+Shift+2 move container to workspace number 2 +bindsym Mod1+Shift+3 move container to workspace number 3 +bindsym Mod1+Shift+4 move container to workspace number 4 +bindsym Mod1+Shift+5 move container to workspace number 5 +bindsym Mod1+Shift+6 move container to workspace number 6 +bindsym Mod1+Shift+7 move container to workspace number 7 +bindsym Mod1+Shift+8 move container to workspace number 8 +bindsym Mod1+Shift+9 move container to workspace number 9 +bindsym Mod1+Shift+Down move down +bindsym Mod1+Shift+Left move left +bindsym Mod1+Shift+Right move right +bindsym Mod1+Shift+Up move up +bindsym Mod1+Shift+c reload +bindsym Mod1+Shift+e exec swaynag -t warning -m 'You pressed the exit shortcut. Do you really want to exit sway? This will end your Wayland session.' -b 'Yes, exit sway' 'swaymsg exit' +bindsym Mod1+Shift+h move left +bindsym Mod1+Shift+j move down +bindsym Mod1+Shift+k move up +bindsym Mod1+Shift+l move right +bindsym Mod1+Shift+minus move scratchpad +bindsym Mod1+Shift+q kill +bindsym Mod1+Shift+space floating toggle +bindsym Mod1+Up focus up +bindsym Mod1+a focus parent +bindsym Mod1+b splith +bindsym Mod1+d exec @dmenu@/bin/dmenu_run +bindsym Mod1+e layout toggle split +bindsym Mod1+f fullscreen toggle +bindsym Mod1+h focus left +bindsym Mod1+j focus down +bindsym Mod1+k focus up +bindsym Mod1+l focus right +bindsym Mod1+minus scratchpad show +bindsym Mod1+r mode resize +bindsym Mod1+s layout stacking +bindsym Mod1+space focus mode_toggle +bindsym Mod1+v splitv +bindsym Mod1+w layout tabbed + +mode "resize" { + bindsym Down resize grow height 10 px + bindsym Escape mode default + bindsym Left resize shrink width 10 px + bindsym Return mode default + bindsym Right resize grow width 10 px + bindsym Up resize shrink height 10 px + bindsym h resize shrink width 10 px + bindsym j resize grow height 10 px + bindsym k resize shrink height 10 px + bindsym l resize grow width 10 px +} + +bar { + font pango:monospace 8.000000 + mode dock + hidden_state hide + position bottom + status_command @i3status@/bin/i3status + swaybar_command @sway@/bin/swaybar + workspace_buttons yes + strip_workspace_numbers no + tray_output primary + colors { + background #000000 + statusline #ffffff + separator #666666 + focused_workspace #4c7899 #285577 #ffffff + active_workspace #333333 #5f676a #ffffff + inactive_workspace #333333 #222222 #888888 + urgent_workspace #2f343a #900000 #ffffff + binding_mode #2f343a #900000 #ffffff +} +} + +exec "systemctl --user import-environment; systemctl --user start sway-session.target" diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-default.nix b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-default.nix new file mode 100644 index 00000000000..7bd4373174a --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-default.nix @@ -0,0 +1,18 @@ +{ config, lib, pkgs, ... }: + +{ + imports = [ ./sway-stubs.nix ]; + + wayland.windowManager.sway = { + enable = true; + package = config.lib.test.mkStubPackage { outPath = "@sway@"; }; + # overriding findutils causes issues + config.menu = "${pkgs.dmenu}/bin/dmenu_run"; + }; + + nmt.script = '' + assertFileExists home-files/.config/sway/config + assertFileContent home-files/.config/sway/config \ + ${./sway-default.conf} + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-followmouse-expected.conf b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-followmouse-expected.conf new file mode 100644 index 00000000000..287e0322580 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-followmouse-expected.conf @@ -0,0 +1,84 @@ +font pango:monospace 8.000000 +floating_modifier Mod1 +default_border pixel 2 +default_floating_border pixel 2 +hide_edge_borders none +focus_wrapping no +focus_follows_mouse always +focus_on_window_activation smart +mouse_warping output +workspace_layout default +workspace_auto_back_and_forth no +client.focused #4c7899 #285577 #ffffff #2e9ef4 #285577 +client.focused_inactive #333333 #5f676a #ffffff #484e50 #5f676a +client.unfocused #333333 #222222 #888888 #292d2e #222222 +client.urgent #2f343a #900000 #ffffff #900000 #900000 +client.placeholder #000000 #0c0c0c #ffffff #000000 #0c0c0c +client.background #ffffff + +bindsym Mod1+1 workspace number 1 +bindsym Mod1+2 workspace number 2 +bindsym Mod1+3 workspace number 3 +bindsym Mod1+4 workspace number 4 +bindsym Mod1+5 workspace number 5 +bindsym Mod1+6 workspace number 6 +bindsym Mod1+7 workspace number 7 +bindsym Mod1+8 workspace number 8 +bindsym Mod1+9 workspace number 9 +bindsym Mod1+Down focus down +bindsym Mod1+Left focus left +bindsym Mod1+Return exec @rxvt-unicode-unwrapped@/bin/urxvt +bindsym Mod1+Right focus right +bindsym Mod1+Shift+1 move container to workspace number 1 +bindsym Mod1+Shift+2 move container to workspace number 2 +bindsym Mod1+Shift+3 move container to workspace number 3 +bindsym Mod1+Shift+4 move container to workspace number 4 +bindsym Mod1+Shift+5 move container to workspace number 5 +bindsym Mod1+Shift+6 move container to workspace number 6 +bindsym Mod1+Shift+7 move container to workspace number 7 +bindsym Mod1+Shift+8 move container to workspace number 8 +bindsym Mod1+Shift+9 move container to workspace number 9 +bindsym Mod1+Shift+Down move down +bindsym Mod1+Shift+Left move left +bindsym Mod1+Shift+Right move right +bindsym Mod1+Shift+Up move up +bindsym Mod1+Shift+c reload +bindsym Mod1+Shift+e exec swaynag -t warning -m 'You pressed the exit shortcut. Do you really want to exit sway? This will end your Wayland session.' -b 'Yes, exit sway' 'swaymsg exit' +bindsym Mod1+Shift+h move left +bindsym Mod1+Shift+j move down +bindsym Mod1+Shift+k move up +bindsym Mod1+Shift+l move right +bindsym Mod1+Shift+minus move scratchpad +bindsym Mod1+Shift+q kill +bindsym Mod1+Shift+space floating toggle +bindsym Mod1+Up focus up +bindsym Mod1+a focus parent +bindsym Mod1+b splith +bindsym Mod1+d exec @dmenu@/bin/dmenu_run +bindsym Mod1+e layout toggle split +bindsym Mod1+f fullscreen toggle +bindsym Mod1+h focus left +bindsym Mod1+j focus down +bindsym Mod1+k focus up +bindsym Mod1+l focus right +bindsym Mod1+minus scratchpad show +bindsym Mod1+r mode resize +bindsym Mod1+s layout stacking +bindsym Mod1+space focus mode_toggle +bindsym Mod1+v splitv +bindsym Mod1+w layout tabbed + +mode "resize" { + bindsym Down resize grow height 10 px + bindsym Escape mode default + bindsym Left resize shrink width 10 px + bindsym Return mode default + bindsym Right resize grow width 10 px + bindsym Up resize shrink height 10 px + bindsym h resize shrink width 10 px + bindsym j resize grow height 10 px + bindsym k resize shrink height 10 px + bindsym l resize grow width 10 px +} + +exec "systemctl --user import-environment; systemctl --user start sway-session.target" diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-followmouse-legacy-expected.conf b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-followmouse-legacy-expected.conf new file mode 100644 index 00000000000..e6f308c3d0d --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-followmouse-legacy-expected.conf @@ -0,0 +1,84 @@ +font pango:monospace 8.000000 +floating_modifier Mod1 +default_border pixel 2 +default_floating_border pixel 2 +hide_edge_borders none +focus_wrapping no +focus_follows_mouse no +focus_on_window_activation smart +mouse_warping output +workspace_layout default +workspace_auto_back_and_forth no +client.focused #4c7899 #285577 #ffffff #2e9ef4 #285577 +client.focused_inactive #333333 #5f676a #ffffff #484e50 #5f676a +client.unfocused #333333 #222222 #888888 #292d2e #222222 +client.urgent #2f343a #900000 #ffffff #900000 #900000 +client.placeholder #000000 #0c0c0c #ffffff #000000 #0c0c0c +client.background #ffffff + +bindsym Mod1+1 workspace number 1 +bindsym Mod1+2 workspace number 2 +bindsym Mod1+3 workspace number 3 +bindsym Mod1+4 workspace number 4 +bindsym Mod1+5 workspace number 5 +bindsym Mod1+6 workspace number 6 +bindsym Mod1+7 workspace number 7 +bindsym Mod1+8 workspace number 8 +bindsym Mod1+9 workspace number 9 +bindsym Mod1+Down focus down +bindsym Mod1+Left focus left +bindsym Mod1+Return exec @rxvt-unicode-unwrapped@/bin/urxvt +bindsym Mod1+Right focus right +bindsym Mod1+Shift+1 move container to workspace number 1 +bindsym Mod1+Shift+2 move container to workspace number 2 +bindsym Mod1+Shift+3 move container to workspace number 3 +bindsym Mod1+Shift+4 move container to workspace number 4 +bindsym Mod1+Shift+5 move container to workspace number 5 +bindsym Mod1+Shift+6 move container to workspace number 6 +bindsym Mod1+Shift+7 move container to workspace number 7 +bindsym Mod1+Shift+8 move container to workspace number 8 +bindsym Mod1+Shift+9 move container to workspace number 9 +bindsym Mod1+Shift+Down move down +bindsym Mod1+Shift+Left move left +bindsym Mod1+Shift+Right move right +bindsym Mod1+Shift+Up move up +bindsym Mod1+Shift+c reload +bindsym Mod1+Shift+e exec swaynag -t warning -m 'You pressed the exit shortcut. Do you really want to exit sway? This will end your Wayland session.' -b 'Yes, exit sway' 'swaymsg exit' +bindsym Mod1+Shift+h move left +bindsym Mod1+Shift+j move down +bindsym Mod1+Shift+k move up +bindsym Mod1+Shift+l move right +bindsym Mod1+Shift+minus move scratchpad +bindsym Mod1+Shift+q kill +bindsym Mod1+Shift+space floating toggle +bindsym Mod1+Up focus up +bindsym Mod1+a focus parent +bindsym Mod1+b splith +bindsym Mod1+d exec @dmenu@/bin/dmenu_run +bindsym Mod1+e layout toggle split +bindsym Mod1+f fullscreen toggle +bindsym Mod1+h focus left +bindsym Mod1+j focus down +bindsym Mod1+k focus up +bindsym Mod1+l focus right +bindsym Mod1+minus scratchpad show +bindsym Mod1+r mode resize +bindsym Mod1+s layout stacking +bindsym Mod1+space focus mode_toggle +bindsym Mod1+v splitv +bindsym Mod1+w layout tabbed + +mode "resize" { + bindsym Down resize grow height 10 px + bindsym Escape mode default + bindsym Left resize shrink width 10 px + bindsym Return mode default + bindsym Right resize grow width 10 px + bindsym Up resize shrink height 10 px + bindsym h resize shrink width 10 px + bindsym j resize grow height 10 px + bindsym k resize shrink height 10 px + bindsym l resize grow width 10 px +} + +exec "systemctl --user import-environment; systemctl --user start sway-session.target" diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-followmouse-legacy.nix b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-followmouse-legacy.nix new file mode 100644 index 00000000000..ce69d9f7fbb --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-followmouse-legacy.nix @@ -0,0 +1,24 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + imports = [ ./sway-stubs.nix ]; + + wayland.windowManager.sway = { + enable = true; + package = config.lib.test.mkStubPackage { outPath = "@sway@"; }; + + config = { + focus.followMouse = false; + menu = "${pkgs.dmenu}/bin/dmenu_run"; + bars = [ ]; + }; + }; + + nmt.script = '' + assertFileExists home-files/.config/sway/config + assertFileContent home-files/.config/sway/config \ + ${./sway-followmouse-legacy-expected.conf} + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-followmouse.nix b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-followmouse.nix new file mode 100644 index 00000000000..7065dd1ca51 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-followmouse.nix @@ -0,0 +1,22 @@ +{ config, lib, pkgs, ... }: + +{ + imports = [ ./sway-stubs.nix ]; + + wayland.windowManager.sway = { + enable = true; + package = config.lib.test.mkStubPackage { outPath = "@sway@"; }; + + config = { + focus.followMouse = "always"; + menu = "${pkgs.dmenu}/bin/dmenu_run"; + bars = [ ]; + }; + }; + + nmt.script = '' + assertFileExists home-files/.config/sway/config + assertFileContent home-files/.config/sway/config \ + ${./sway-followmouse-expected.conf} + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-modules.conf b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-modules.conf new file mode 100644 index 00000000000..99e54c841c2 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-modules.conf @@ -0,0 +1,118 @@ +font pango:monospace 8.000000 +floating_modifier Mod1 +default_border pixel 2 +default_floating_border pixel 2 +hide_edge_borders none +focus_wrapping no +focus_follows_mouse yes +focus_on_window_activation smart +mouse_warping output +workspace_layout default +workspace_auto_back_and_forth no +client.focused #4c7899 #285577 #ffffff #2e9ef4 #285577 +client.focused_inactive #333333 #5f676a #ffffff #484e50 #5f676a +client.unfocused #333333 #222222 #888888 #292d2e #222222 +client.urgent #2f343a #900000 #ffffff #900000 #900000 +client.placeholder #000000 #0c0c0c #ffffff #000000 #0c0c0c +client.background #ffffff + +bindsym Mod1+1 workspace number 1 +bindsym Mod1+2 workspace number 2 +bindsym Mod1+3 workspace number 3 +bindsym Mod1+4 workspace number 4 +bindsym Mod1+5 workspace number 5 +bindsym Mod1+6 workspace number 6 +bindsym Mod1+7 workspace number 7 +bindsym Mod1+8 workspace number 8 +bindsym Mod1+9 workspace number 9 +bindsym Mod1+Down focus down +bindsym Mod1+Left focus left +bindsym Mod1+Return exec @rxvt-unicode-unwrapped@/bin/urxvt +bindsym Mod1+Right focus right +bindsym Mod1+Shift+1 move container to workspace number 1 +bindsym Mod1+Shift+2 move container to workspace number 2 +bindsym Mod1+Shift+3 move container to workspace number 3 +bindsym Mod1+Shift+4 move container to workspace number 4 +bindsym Mod1+Shift+5 move container to workspace number 5 +bindsym Mod1+Shift+6 move container to workspace number 6 +bindsym Mod1+Shift+7 move container to workspace number 7 +bindsym Mod1+Shift+8 move container to workspace number 8 +bindsym Mod1+Shift+9 move container to workspace number 9 +bindsym Mod1+Shift+Down move down +bindsym Mod1+Shift+Left move left +bindsym Mod1+Shift+Right move right +bindsym Mod1+Shift+Up move up +bindsym Mod1+Shift+c reload +bindsym Mod1+Shift+e exec swaynag -t warning -m 'You pressed the exit shortcut. Do you really want to exit sway? This will end your Wayland session.' -b 'Yes, exit sway' 'swaymsg exit' +bindsym Mod1+Shift+h move left +bindsym Mod1+Shift+j move down +bindsym Mod1+Shift+k move up +bindsym Mod1+Shift+l move right +bindsym Mod1+Shift+minus move scratchpad +bindsym Mod1+Shift+q kill +bindsym Mod1+Shift+space floating toggle +bindsym Mod1+Up focus up +bindsym Mod1+a focus parent +bindsym Mod1+b splith +bindsym Mod1+d exec @dmenu@/bin/dmenu_run +bindsym Mod1+e layout toggle split +bindsym Mod1+f fullscreen toggle +bindsym Mod1+h focus left +bindsym Mod1+j focus down +bindsym Mod1+k focus up +bindsym Mod1+l focus right +bindsym Mod1+minus scratchpad show +bindsym Mod1+r mode resize +bindsym Mod1+s layout stacking +bindsym Mod1+space focus mode_toggle +bindsym Mod1+v splitv +bindsym Mod1+w layout tabbed + +input "*" { +xkb_variant dvorak +} + +output "HDMI-A-2" { +bg ~/path/to/background.png fill +} + +seat "*" { +hide_cursor when-typing enable +} + +mode "resize" { + bindsym Down resize grow height 10 px + bindsym Escape mode default + bindsym Left resize shrink width 10 px + bindsym Return mode default + bindsym Right resize grow width 10 px + bindsym Up resize shrink height 10 px + bindsym h resize shrink width 10 px + bindsym j resize grow height 10 px + bindsym k resize shrink height 10 px + bindsym l resize grow width 10 px +} + +bar { + font pango:monospace 8.000000 + mode dock + hidden_state hide + position bottom + status_command @i3status@/bin/i3status + swaybar_command @sway@/bin/swaybar + workspace_buttons yes + strip_workspace_numbers no + tray_output primary + colors { + background #000000 + statusline #ffffff + separator #666666 + focused_workspace #4c7899 #285577 #ffffff + active_workspace #333333 #5f676a #ffffff + inactive_workspace #333333 #222222 #888888 + urgent_workspace #2f343a #900000 #ffffff + binding_mode #2f343a #900000 #ffffff +} +} + +exec "systemctl --user import-environment; systemctl --user start sway-session.target" diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-modules.nix b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-modules.nix new file mode 100644 index 00000000000..96366ab0a2f --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-modules.nix @@ -0,0 +1,24 @@ +{ config, lib, pkgs, ... }: + +{ + imports = [ ./sway-stubs.nix ]; + + wayland.windowManager.sway = { + enable = true; + package = config.lib.test.mkStubPackage { outPath = "@sway@"; }; + # overriding findutils causes issues + config = { + menu = "${pkgs.dmenu}/bin/dmenu_run"; + + input = { "*" = { xkb_variant = "dvorak"; }; }; + output = { "HDMI-A-2" = { bg = "~/path/to/background.png fill"; }; }; + seat = { "*" = { hide_cursor = "when-typing enable"; }; }; + }; + }; + + nmt.script = '' + assertFileExists home-files/.config/sway/config + assertFileContent home-files/.config/sway/config \ + ${./sway-modules.conf} + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-no-xwayland.nix b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-no-xwayland.nix new file mode 100644 index 00000000000..f19b88eb9c1 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-no-xwayland.nix @@ -0,0 +1,23 @@ +{ config, lib, pkgs, ... }: + +{ + imports = [ ./sway-stubs.nix ]; + + wayland.windowManager.sway = { + enable = true; + package = config.lib.test.mkStubPackage { outPath = "@sway@"; }; + config = null; + systemdIntegration = false; + xwayland = false; + }; + + nmt.script = '' + assertFileExists home-files/.config/sway/config + assertFileContent home-files/.config/sway/config \ + ${ + pkgs.writeText "expected" '' + xwayland disable + '' + } + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-null-config.nix b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-null-config.nix new file mode 100644 index 00000000000..00128c8f31b --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-null-config.nix @@ -0,0 +1,18 @@ +{ config, lib, pkgs, ... }: + +{ + imports = [ ./sway-stubs.nix ]; + + wayland.windowManager.sway = { + enable = true; + package = config.lib.test.mkStubPackage { outPath = "@sway@"; }; + config = null; + systemdIntegration = false; + }; + + nmt.script = '' + assertFileExists home-files/.config/sway/config + assertFileContent home-files/.config/sway/config \ + ${pkgs.writeText "expected" ""} + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-null-package.conf b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-null-package.conf new file mode 100644 index 00000000000..82cf254e5e6 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-null-package.conf @@ -0,0 +1,106 @@ +font pango:monospace 8.000000 +floating_modifier Mod1 +default_border pixel 2 +default_floating_border pixel 2 +hide_edge_borders none +focus_wrapping no +focus_follows_mouse yes +focus_on_window_activation smart +mouse_warping output +workspace_layout default +workspace_auto_back_and_forth no +client.focused #4c7899 #285577 #ffffff #2e9ef4 #285577 +client.focused_inactive #333333 #5f676a #ffffff #484e50 #5f676a +client.unfocused #333333 #222222 #888888 #292d2e #222222 +client.urgent #2f343a #900000 #ffffff #900000 #900000 +client.placeholder #000000 #0c0c0c #ffffff #000000 #0c0c0c +client.background #ffffff + +bindsym Mod1+1 workspace number 1 +bindsym Mod1+2 workspace number 2 +bindsym Mod1+3 workspace number 3 +bindsym Mod1+4 workspace number 4 +bindsym Mod1+5 workspace number 5 +bindsym Mod1+6 workspace number 6 +bindsym Mod1+7 workspace number 7 +bindsym Mod1+8 workspace number 8 +bindsym Mod1+9 workspace number 9 +bindsym Mod1+Down focus down +bindsym Mod1+Left focus left +bindsym Mod1+Return exec @rxvt-unicode-unwrapped@/bin/urxvt +bindsym Mod1+Right focus right +bindsym Mod1+Shift+1 move container to workspace number 1 +bindsym Mod1+Shift+2 move container to workspace number 2 +bindsym Mod1+Shift+3 move container to workspace number 3 +bindsym Mod1+Shift+4 move container to workspace number 4 +bindsym Mod1+Shift+5 move container to workspace number 5 +bindsym Mod1+Shift+6 move container to workspace number 6 +bindsym Mod1+Shift+7 move container to workspace number 7 +bindsym Mod1+Shift+8 move container to workspace number 8 +bindsym Mod1+Shift+9 move container to workspace number 9 +bindsym Mod1+Shift+Down move down +bindsym Mod1+Shift+Left move left +bindsym Mod1+Shift+Right move right +bindsym Mod1+Shift+Up move up +bindsym Mod1+Shift+c reload +bindsym Mod1+Shift+e exec swaynag -t warning -m 'You pressed the exit shortcut. Do you really want to exit sway? This will end your Wayland session.' -b 'Yes, exit sway' 'swaymsg exit' +bindsym Mod1+Shift+h move left +bindsym Mod1+Shift+j move down +bindsym Mod1+Shift+k move up +bindsym Mod1+Shift+l move right +bindsym Mod1+Shift+minus move scratchpad +bindsym Mod1+Shift+q kill +bindsym Mod1+Shift+space floating toggle +bindsym Mod1+Up focus up +bindsym Mod1+a focus parent +bindsym Mod1+b splith +bindsym Mod1+d exec @dmenu@/bin/dmenu_run +bindsym Mod1+e layout toggle split +bindsym Mod1+f fullscreen toggle +bindsym Mod1+h focus left +bindsym Mod1+j focus down +bindsym Mod1+k focus up +bindsym Mod1+l focus right +bindsym Mod1+minus scratchpad show +bindsym Mod1+r mode resize +bindsym Mod1+s layout stacking +bindsym Mod1+space focus mode_toggle +bindsym Mod1+v splitv +bindsym Mod1+w layout tabbed + +mode "resize" { + bindsym Down resize grow height 10 px + bindsym Escape mode default + bindsym Left resize shrink width 10 px + bindsym Return mode default + bindsym Right resize grow width 10 px + bindsym Up resize shrink height 10 px + bindsym h resize shrink width 10 px + bindsym j resize grow height 10 px + bindsym k resize shrink height 10 px + bindsym l resize grow width 10 px +} + +bar { + font pango:monospace 8.000000 + mode dock + hidden_state hide + position bottom + status_command @i3status@/bin/i3status + swaybar_command @sway@/bin/swaybar + workspace_buttons yes + strip_workspace_numbers no + tray_output primary + colors { + background #000000 + statusline #ffffff + separator #666666 + focused_workspace #4c7899 #285577 #ffffff + active_workspace #333333 #5f676a #ffffff + inactive_workspace #333333 #222222 #888888 + urgent_workspace #2f343a #900000 #ffffff + binding_mode #2f343a #900000 #ffffff +} +} + +exec "systemctl --user import-environment; systemctl --user start sway-session.target" diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-null-package.nix b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-null-package.nix new file mode 100644 index 00000000000..fe2a4519612 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-null-package.nix @@ -0,0 +1,27 @@ +{ config, lib, pkgs, ... }: + +{ + imports = [ ./sway-stubs.nix ]; + + # Enables the default bar configuration + home.stateVersion = "20.09"; + + wayland.windowManager.sway = { + enable = true; + package = null; + config.menu = "${pkgs.dmenu}/bin/dmenu_run"; + }; + + assertions = [{ + assertion = + !lib.elem config.wayland.windowManager.sway.config.bars [ [ { } ] [ ] ]; + message = + "The default Sway bars configuration should be set for this test (sway-null-package) to work."; + }]; + + nmt.script = '' + assertFileExists home-files/.config/sway/config + assertFileContent home-files/.config/sway/config \ + ${./sway-null-package.conf} + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-post-2003.nix b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-post-2003.nix new file mode 100644 index 00000000000..7596250ec3d --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-post-2003.nix @@ -0,0 +1,20 @@ +{ config, lib, pkgs, ... }: + +{ + imports = [ ./sway-stubs.nix ]; + + home.stateVersion = "20.09"; + + wayland.windowManager.sway = { + enable = true; + package = config.lib.test.mkStubPackage { outPath = "@sway@"; }; + # overriding findutils causes issues + config.menu = "${pkgs.dmenu}/bin/dmenu_run"; + }; + + nmt.script = '' + assertFileExists home-files/.config/sway/config + assertFileContent home-files/.config/sway/config \ + ${./sway-default.conf} + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-stubs.nix b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-stubs.nix new file mode 100644 index 00000000000..55a74e1c477 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-stubs.nix @@ -0,0 +1,13 @@ +{ + # Avoid unnecessary downloads in CI jobs and/or make out paths constant, i.e., + # not containing hashes, version numbers etc. + test.stubs = { + dmenu = { }; + rxvt-unicode-unwrapped = { }; + i3status = { }; + sway = { }; + sway-unwrapped = { version = "1"; }; + swaybg = { }; + xwayland = { }; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-workspace-default-expected.conf b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-workspace-default-expected.conf new file mode 100644 index 00000000000..233e567d9f5 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-workspace-default-expected.conf @@ -0,0 +1,105 @@ +font pango:monospace 8.000000 +floating_modifier Mod1 +default_border pixel 2 +default_floating_border pixel 2 +hide_edge_borders none +focus_wrapping no +focus_follows_mouse yes +focus_on_window_activation smart +mouse_warping output +workspace_layout default +workspace_auto_back_and_forth no +client.focused #4c7899 #285577 #ffffff #2e9ef4 #285577 +client.focused_inactive #333333 #5f676a #ffffff #484e50 #5f676a +client.unfocused #333333 #222222 #888888 #292d2e #222222 +client.urgent #2f343a #900000 #ffffff #900000 #900000 +client.placeholder #000000 #0c0c0c #ffffff #000000 #0c0c0c +client.background #ffffff +bindsym Mod1+9 workspace number 9 +bindsym Mod1+1 workspace number 1 +bindsym Mod1+2 workspace number 2 +bindsym Mod1+3 workspace number 3 +bindsym Mod1+4 workspace number 4 +bindsym Mod1+5 workspace number 5 +bindsym Mod1+6 workspace number 6 +bindsym Mod1+7 workspace number 7 +bindsym Mod1+8 workspace number 8 +bindsym Mod1+Down focus down +bindsym Mod1+Left focus left +bindsym Mod1+Return exec @rxvt-unicode-unwrapped@/bin/urxvt +bindsym Mod1+Right focus right +bindsym Mod1+Shift+1 move container to workspace number 1 +bindsym Mod1+Shift+2 move container to workspace number 2 +bindsym Mod1+Shift+3 move container to workspace number 3 +bindsym Mod1+Shift+4 move container to workspace number 4 +bindsym Mod1+Shift+5 move container to workspace number 5 +bindsym Mod1+Shift+6 move container to workspace number 6 +bindsym Mod1+Shift+7 move container to workspace number 7 +bindsym Mod1+Shift+8 move container to workspace number 8 +bindsym Mod1+Shift+9 move container to workspace number 9 +bindsym Mod1+Shift+Down move down +bindsym Mod1+Shift+Left move left +bindsym Mod1+Shift+Right move right +bindsym Mod1+Shift+Up move up +bindsym Mod1+Shift+c reload +bindsym Mod1+Shift+e exec swaynag -t warning -m 'You pressed the exit shortcut. Do you really want to exit sway? This will end your Wayland session.' -b 'Yes, exit sway' 'swaymsg exit' +bindsym Mod1+Shift+h move left +bindsym Mod1+Shift+j move down +bindsym Mod1+Shift+k move up +bindsym Mod1+Shift+l move right +bindsym Mod1+Shift+minus move scratchpad +bindsym Mod1+Shift+q kill +bindsym Mod1+Shift+space floating toggle +bindsym Mod1+Up focus up +bindsym Mod1+a focus parent +bindsym Mod1+b splith +bindsym Mod1+d exec @dmenu@/bin/dmenu_run +bindsym Mod1+e layout toggle split +bindsym Mod1+f fullscreen toggle +bindsym Mod1+h focus left +bindsym Mod1+j focus down +bindsym Mod1+k focus up +bindsym Mod1+l focus right +bindsym Mod1+minus scratchpad show +bindsym Mod1+r mode resize +bindsym Mod1+s layout stacking +bindsym Mod1+space focus mode_toggle +bindsym Mod1+v splitv +bindsym Mod1+w layout tabbed + +mode "resize" { + bindsym Down resize grow height 10 px + bindsym Escape mode default + bindsym Left resize shrink width 10 px + bindsym Return mode default + bindsym Right resize grow width 10 px + bindsym Up resize shrink height 10 px + bindsym h resize shrink width 10 px + bindsym j resize grow height 10 px + bindsym k resize shrink height 10 px + bindsym l resize grow width 10 px +} + +bar { + font pango:monospace 8.000000 + mode dock + hidden_state hide + position bottom + status_command @i3status@/bin/i3status + swaybar_command @sway@/bin/swaybar + workspace_buttons yes + strip_workspace_numbers no + tray_output primary + colors { + background #000000 + statusline #ffffff + separator #666666 + focused_workspace #4c7899 #285577 #ffffff + active_workspace #333333 #5f676a #ffffff + inactive_workspace #333333 #222222 #888888 + urgent_workspace #2f343a #900000 #ffffff + binding_mode #2f343a #900000 #ffffff +} +} + +exec "systemctl --user import-environment; systemctl --user start sway-session.target" diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-workspace-default.nix b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-workspace-default.nix new file mode 100644 index 00000000000..d941109805b --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-workspace-default.nix @@ -0,0 +1,19 @@ +{ config, lib, pkgs, ... }: + +{ + imports = [ ./sway-stubs.nix ]; + + wayland.windowManager.sway = { + enable = true; + package = config.lib.test.mkStubPackage { outPath = "@sway@"; }; + # overriding findutils causes issues + config.menu = "${pkgs.dmenu}/bin/dmenu_run"; + config.defaultWorkspace = "workspace number 9"; + }; + + nmt.script = '' + assertFileExists home-files/.config/sway/config + assertFileContent home-files/.config/sway/config \ + ${./sway-workspace-default-expected.conf} + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-workspace-output-expected.conf b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-workspace-output-expected.conf new file mode 100644 index 00000000000..683298b6d8f --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-workspace-output-expected.conf @@ -0,0 +1,110 @@ +font pango:monospace 8.000000 +floating_modifier Mod1 +default_border pixel 2 +default_floating_border pixel 2 +hide_edge_borders none +focus_wrapping no +focus_follows_mouse yes +focus_on_window_activation smart +mouse_warping output +workspace_layout default +workspace_auto_back_and_forth no +client.focused #4c7899 #285577 #ffffff #2e9ef4 #285577 +client.focused_inactive #333333 #5f676a #ffffff #484e50 #5f676a +client.unfocused #333333 #222222 #888888 #292d2e #222222 +client.urgent #2f343a #900000 #ffffff #900000 #900000 +client.placeholder #000000 #0c0c0c #ffffff #000000 #0c0c0c +client.background #ffffff + +bindsym Mod1+1 workspace number 1 +bindsym Mod1+2 workspace number 2 +bindsym Mod1+3 workspace number 3 +bindsym Mod1+4 workspace number 4 +bindsym Mod1+5 workspace number 5 +bindsym Mod1+6 workspace number 6 +bindsym Mod1+7 workspace number 7 +bindsym Mod1+8 workspace number 8 +bindsym Mod1+9 workspace number 9 +bindsym Mod1+Down focus down +bindsym Mod1+Left focus left +bindsym Mod1+Return exec @rxvt-unicode-unwrapped@/bin/urxvt +bindsym Mod1+Right focus right +bindsym Mod1+Shift+1 move container to workspace number 1 +bindsym Mod1+Shift+2 move container to workspace number 2 +bindsym Mod1+Shift+3 move container to workspace number 3 +bindsym Mod1+Shift+4 move container to workspace number 4 +bindsym Mod1+Shift+5 move container to workspace number 5 +bindsym Mod1+Shift+6 move container to workspace number 6 +bindsym Mod1+Shift+7 move container to workspace number 7 +bindsym Mod1+Shift+8 move container to workspace number 8 +bindsym Mod1+Shift+9 move container to workspace number 9 +bindsym Mod1+Shift+Down move down +bindsym Mod1+Shift+Left move left +bindsym Mod1+Shift+Right move right +bindsym Mod1+Shift+Up move up +bindsym Mod1+Shift+c reload +bindsym Mod1+Shift+e exec swaynag -t warning -m 'You pressed the exit shortcut. Do you really want to exit sway? This will end your Wayland session.' -b 'Yes, exit sway' 'swaymsg exit' +bindsym Mod1+Shift+h move left +bindsym Mod1+Shift+j move down +bindsym Mod1+Shift+k move up +bindsym Mod1+Shift+l move right +bindsym Mod1+Shift+minus move scratchpad +bindsym Mod1+Shift+q kill +bindsym Mod1+Shift+space floating toggle +bindsym Mod1+Up focus up +bindsym Mod1+a focus parent +bindsym Mod1+b splith +bindsym Mod1+d exec @dmenu@/bin/dmenu_run +bindsym Mod1+e layout toggle split +bindsym Mod1+f fullscreen toggle +bindsym Mod1+h focus left +bindsym Mod1+j focus down +bindsym Mod1+k focus up +bindsym Mod1+l focus right +bindsym Mod1+minus scratchpad show +bindsym Mod1+r mode resize +bindsym Mod1+s layout stacking +bindsym Mod1+space focus mode_toggle +bindsym Mod1+v splitv +bindsym Mod1+w layout tabbed + +mode "resize" { + bindsym Down resize grow height 10 px + bindsym Escape mode default + bindsym Left resize shrink width 10 px + bindsym Return mode default + bindsym Right resize grow width 10 px + bindsym Up resize shrink height 10 px + bindsym h resize shrink width 10 px + bindsym j resize grow height 10 px + bindsym k resize shrink height 10 px + bindsym l resize grow width 10 px +} + +bar { + font pango:monospace 8.000000 + mode dock + hidden_state hide + position bottom + status_command @i3status@/bin/i3status + swaybar_command @sway@/bin/swaybar + workspace_buttons yes + strip_workspace_numbers no + tray_output primary + colors { + background #000000 + statusline #ffffff + separator #666666 + focused_workspace #4c7899 #285577 #ffffff + active_workspace #333333 #5f676a #ffffff + inactive_workspace #333333 #222222 #888888 + urgent_workspace #2f343a #900000 #ffffff + binding_mode #2f343a #900000 #ffffff +} +} + +workspace "1" output eDP +workspace "ABC" output DP +workspace "3: Test" output HDMI +workspace "!"§$%&/(){}[]=?\*#<>-_.:,;²³" output DVI +exec "systemctl --user import-environment; systemctl --user start sway-session.target" diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-workspace-output.nix b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-workspace-output.nix new file mode 100644 index 00000000000..ce51c1f5190 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/sway-workspace-output.nix @@ -0,0 +1,45 @@ +{ config, lib, pkgs, ... }: + +let + i3 = { + ws1 = "1"; + ws2 = "ABC"; + ws3 = "3: Test"; + ws4 = ''!"§$%&/(){}[]=?\*#<>-_.:,;²³''; + }; + +in { + imports = [ ./sway-stubs.nix ]; + + wayland.windowManager.sway = { + enable = true; + package = config.lib.test.mkStubPackage { outPath = "@sway@"; }; + # overriding findutils causes issues + config.menu = "${pkgs.dmenu}/bin/dmenu_run"; + + config.workspaceOutputAssign = [ + { + workspace = "${i3.ws1}"; + output = "eDP"; + } + { + workspace = "${i3.ws2}"; + output = "DP"; + } + { + workspace = "${i3.ws3}"; + output = "HDMI"; + } + { + workspace = "${i3.ws4}"; + output = "DVI"; + } + ]; + }; + + nmt.script = '' + assertFileExists home-files/.config/sway/config + assertFileContent home-files/.config/sway/config \ + ${./sway-workspace-output-expected.conf} + ''; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/swaynag-empty-settings.nix b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/swaynag-empty-settings.nix new file mode 100644 index 00000000000..0180852a388 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/swaynag-empty-settings.nix @@ -0,0 +1,15 @@ +{ config, lib, pkgs, ... }: + +{ + config = { + wayland.windowManager.sway.swaynag = { + enable = true; + + settings = { }; + }; + + nmt.script = '' + assertPathNotExists home-files/.config/swaynag + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/swaynag-example-settings-expected.conf b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/swaynag-example-settings-expected.conf new file mode 100644 index 00000000000..4e0f5d5e908 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/swaynag-example-settings-expected.conf @@ -0,0 +1,10 @@ +[] +edge=bottom +font=Dina 12 + +[green] +background=00AA00 +button-background=00CC00 +edge=top +message-padding=10 +text=FFFFFF diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/swaynag-example-settings.nix b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/swaynag-example-settings.nix new file mode 100644 index 00000000000..513d185daba --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/window-managers/sway/swaynag-example-settings.nix @@ -0,0 +1,30 @@ +{ config, lib, pkgs, ... }: + +{ + config = { + wayland.windowManager.sway.swaynag = { + enable = true; + + settings = { + "" = { + edge = "bottom"; + font = "Dina 12"; + }; + + green = { + edge = "top"; + background = "00AA00"; + text = "FFFFFF"; + button-background = "00CC00"; + message-padding = 10; + }; + }; + }; + + nmt.script = '' + assertFileContent \ + home-files/.config/swaynag/config \ + ${./swaynag-example-settings-expected.conf} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/wlsunset/default.nix b/infra/libkookie/home-manager-stable/tests/modules/services/wlsunset/default.nix new file mode 100644 index 00000000000..d59af701535 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/wlsunset/default.nix @@ -0,0 +1 @@ +{ wlsunset-service = ./wlsunset-service.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/wlsunset/wlsunset-service-expected.service b/infra/libkookie/home-manager-stable/tests/modules/services/wlsunset/wlsunset-service-expected.service new file mode 100644 index 00000000000..f0cf96f3ad0 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/wlsunset/wlsunset-service-expected.service @@ -0,0 +1,9 @@ +[Install] +WantedBy=test.target + +[Service] +ExecStart=@wlsunset@/bin/wlsunset -l 12.3 -L 128.8 -t 3500 -T 6000 -g 0.6 + +[Unit] +Description=Day/night gamma adjustments for Wayland compositors. +PartOf=graphical-session.target diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/wlsunset/wlsunset-service.nix b/infra/libkookie/home-manager-stable/tests/modules/services/wlsunset/wlsunset-service.nix new file mode 100644 index 00000000000..e3f816505e6 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/wlsunset/wlsunset-service.nix @@ -0,0 +1,23 @@ +{ config, pkgs, ... }: + +{ + config = { + services.wlsunset = { + enable = true; + package = config.lib.test.mkStubPackage { outPath = "@wlsunset@"; }; + latitude = "12.3"; + longitude = "128.8"; + temperature.day = 6000; + temperature.night = 3500; + gamma = "0.6"; + systemdTarget = "test.target"; + }; + + nmt.script = '' + serviceFile=home-files/.config/systemd/user/wlsunset.service + + assertFileExists $serviceFile + assertFileContent $serviceFile ${./wlsunset-service-expected.service} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/xsettingsd/basic-configuration.conf b/infra/libkookie/home-manager-stable/tests/modules/services/xsettingsd/basic-configuration.conf new file mode 100644 index 00000000000..4e502c98f8d --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/xsettingsd/basic-configuration.conf @@ -0,0 +1,4 @@ +Net/ThemeName "Numix" +Xft/Antialias 1 +Xft/Hinting 1 +Xft/RGBA "rgb" diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/xsettingsd/basic-configuration.nix b/infra/libkookie/home-manager-stable/tests/modules/services/xsettingsd/basic-configuration.nix new file mode 100644 index 00000000000..8ea2ec7821c --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/xsettingsd/basic-configuration.nix @@ -0,0 +1,26 @@ +{ config, pkgs, ... }: + +{ + config = { + services.xsettingsd = { + enable = true; + package = config.lib.test.mkStubPackage { }; + settings = { + "Net/ThemeName" = "Numix"; + "Xft/Antialias" = true; + "Xft/Hinting" = true; + "Xft/RGBA" = "rgb"; + }; + }; + nmt.script = '' + serviceFile=home-files/.config/systemd/user/xsettingsd.service + + assertFileExists $serviceFile + assertFileRegex $serviceFile 'ExecStart=.*/bin/xsettingsd.*' + + assertFileExists ${config.services.xsettingsd.configFile} + assertFileContent ${config.services.xsettingsd.configFile} \ + ${./basic-configuration.conf} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/services/xsettingsd/default.nix b/infra/libkookie/home-manager-stable/tests/modules/services/xsettingsd/default.nix new file mode 100644 index 00000000000..98c99f4c8e0 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/services/xsettingsd/default.nix @@ -0,0 +1 @@ +{ xsettingsd-basic-configuration = ./basic-configuration.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/systemd/default.nix b/infra/libkookie/home-manager-stable/tests/modules/systemd/default.nix new file mode 100644 index 00000000000..c949edd95cf --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/systemd/default.nix @@ -0,0 +1,6 @@ +{ + systemd-services = ./services.nix; + systemd-services-disabled-for-root = ./services-disabled-for-root.nix; + systemd-session-variables = ./session-variables.nix; + systemd-timers = ./timers.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/systemd/services-disabled-for-root.nix b/infra/libkookie/home-manager-stable/tests/modules/systemd/services-disabled-for-root.nix new file mode 100644 index 00000000000..f54ebd08be2 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/systemd/services-disabled-for-root.nix @@ -0,0 +1,23 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + home.username = mkForce "root"; + + systemd.user.services."test-service@" = { + Unit = { Description = "A basic test service"; }; + + Service = { + Environment = [ "VAR1=1" "VAR2=2" ]; + ExecStart = ''/some/exec/start/command --with-arguments "%i"''; + }; + }; + + nmt.script = '' + serviceFile=home-files/.config/systemd/user/test-service@.service + assertPathNotExists $serviceFile + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/systemd/services.nix b/infra/libkookie/home-manager-stable/tests/modules/systemd/services.nix new file mode 100644 index 00000000000..fbef7b9c2ec --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/systemd/services.nix @@ -0,0 +1,33 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + systemd.user.services."test-service@" = { + Unit = { Description = "A basic test service"; }; + + Service = { + Environment = [ "VAR1=1" "VAR2=2" ]; + ExecStart = ''/some/exec/start/command --with-arguments "%i"''; + }; + }; + + nmt.script = '' + serviceFile=home-files/.config/systemd/user/test-service@.service + assertFileExists $serviceFile + assertFileContent $serviceFile \ + ${ + builtins.toFile "services-expected.conf" '' + [Service] + Environment=VAR1=1 + Environment=VAR2=2 + ExecStart=/some/exec/start/command --with-arguments "%i" + + [Unit] + Description=A basic test service + '' + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/systemd/session-variables.nix b/infra/libkookie/home-manager-stable/tests/modules/systemd/session-variables.nix new file mode 100644 index 00000000000..cbc348c444e --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/systemd/session-variables.nix @@ -0,0 +1,26 @@ +{ config, lib, pkgs, ... }: + +{ + config = { + systemd.user.sessionVariables = { + V_int = 1; + V_str = "2"; + }; + + nmt.script = '' + envFile=home-files/.config/environment.d/10-home-manager.conf + assertFileExists $envFile + assertFileContent $envFile ${ + pkgs.writeText "expected" '' + LOCALE_ARCHIVE_2_27=${pkgs.glibcLocales}/lib/locale/locale-archive + V_int=1 + V_str=2 + XDG_CACHE_HOME=/home/hm-user/.cache + XDG_CONFIG_HOME=/home/hm-user/.config + XDG_DATA_HOME=/home/hm-user/.local/share + XDG_STATE_HOME=/home/hm-user/.local/state + '' + } + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/systemd/timers-expected.conf b/infra/libkookie/home-manager-stable/tests/modules/systemd/timers-expected.conf new file mode 100644 index 00000000000..b19f044cc0b --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/systemd/timers-expected.conf @@ -0,0 +1,8 @@ +[Install] +WantedBy=timers.target + +[Timer] +OnUnitActiveSec=1h 30m + +[Unit] +Description=A basic test timer diff --git a/infra/libkookie/home-manager-stable/tests/modules/systemd/timers.nix b/infra/libkookie/home-manager-stable/tests/modules/systemd/timers.nix new file mode 100644 index 00000000000..1c0e2722299 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/systemd/timers.nix @@ -0,0 +1,25 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + systemd.user.timers.test-timer = { + Unit = { Description = "A basic test timer"; }; + + Timer = { OnUnitActiveSec = "1h 30m"; }; + + Install = { WantedBy = [ "timers.target" ]; }; + }; + + nmt.script = '' + unitDir=home-files/.config/systemd/user + timerFile=$unitDir/test-timer.timer + + assertFileExists $timerFile + assertFileContent $timerFile ${./timers-expected.conf} + + assertFileExists $unitDir/timers.target.wants/test-timer.timer + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/targets-darwin/darwin.nix b/infra/libkookie/home-manager-stable/tests/modules/targets-darwin/darwin.nix new file mode 100644 index 00000000000..511ae87fd98 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/targets-darwin/darwin.nix @@ -0,0 +1,20 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + darwinTestApp = pkgs.runCommandLocal "target-darwin-example-app" { } '' + mkdir -p $out/Applications + touch $out/Applications/example-app + ''; + +in { + config = { + home.packages = [ darwinTestApp ]; + + nmt.script = '' + assertFileExists 'home-files/Applications/Home Manager Apps/example-app' + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/targets-darwin/default.nix b/infra/libkookie/home-manager-stable/tests/modules/targets-darwin/default.nix new file mode 100644 index 00000000000..10e4111f779 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/targets-darwin/default.nix @@ -0,0 +1,5 @@ +{ + # Disabled for now due to conflicting behavior with nix-darwin. See + # https://github.com/nix-community/home-manager/issues/1341#issuecomment-687286866 + #targets-darwin = ./darwin.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/targets-linux/default.nix b/infra/libkookie/home-manager-stable/tests/modules/targets-linux/default.nix new file mode 100644 index 00000000000..e13617ccb74 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/targets-linux/default.nix @@ -0,0 +1 @@ +{ targets-generic-linux = ./generic-linux.nix; } diff --git a/infra/libkookie/home-manager-stable/tests/modules/targets-linux/generic-linux.nix b/infra/libkookie/home-manager-stable/tests/modules/targets-linux/generic-linux.nix new file mode 100644 index 00000000000..88cec8a0052 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/targets-linux/generic-linux.nix @@ -0,0 +1,40 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + expectedXdgDataDirs = concatStringsSep ":" [ + "\${NIX_STATE_DIR:-/nix/var/nix}/profiles/default/share" + "/home/hm-user/.nix-profile/share" + "/usr/share/ubuntu" + "/usr/local/share" + "/usr/share" + "/var/lib/snapd/desktop" + "/foo" + ]; + +in { + config = { + targets.genericLinux.enable = true; + + xdg.systemDirs.data = [ "/foo" ]; + + nmt.script = '' + envFile=home-files/.config/environment.d/10-home-manager.conf + assertFileExists $envFile + assertFileContains $envFile \ + 'XDG_DATA_DIRS=${expectedXdgDataDirs}''${XDG_DATA_DIRS:+:$XDG_DATA_DIRS}' + assertFileContains $envFile \ + 'TERMINFO_DIRS=/home/hm-user/.nix-profile/share/terminfo:$TERMINFO_DIRS''${TERMINFO_DIRS:+:}/etc/terminfo:/lib/terminfo:/usr/share/terminfo' + + sessionVarsFile=home-path/etc/profile.d/hm-session-vars.sh + assertFileExists $sessionVarsFile + assertFileContains $sessionVarsFile \ + '. "${pkgs.nix}/etc/profile.d/nix.sh"' + + assertFileContains \ + home-path/etc/profile.d/hm-session-vars.sh \ + 'export TERM="$TERM"' + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/xresources/default.nix b/infra/libkookie/home-manager-stable/tests/modules/xresources/default.nix new file mode 100644 index 00000000000..70b3e6b4a9c --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/xresources/default.nix @@ -0,0 +1,4 @@ +{ + xresources = ./xresources.nix; + xresources-empty-properties = ./empty.nix; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/xresources/empty.nix b/infra/libkookie/home-manager-stable/tests/modules/xresources/empty.nix new file mode 100644 index 00000000000..9dd80176ff3 --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/xresources/empty.nix @@ -0,0 +1,13 @@ +{ config, lib, ... }: + +with lib; + +{ + config = { + xresources.properties = { }; + + nmt.script = '' + assertPathNotExists home-files/.Xresources + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/modules/xresources/xresources-expected.conf b/infra/libkookie/home-manager-stable/tests/modules/xresources/xresources-expected.conf new file mode 100644 index 00000000000..20b47e5080b --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/xresources/xresources-expected.conf @@ -0,0 +1,5 @@ +Test*boolean1: true +Test*boolean2: false +Test*int: 10 +Test*list: list-str, true, false, 10 +Test*string: test-string diff --git a/infra/libkookie/home-manager-stable/tests/modules/xresources/xresources.nix b/infra/libkookie/home-manager-stable/tests/modules/xresources/xresources.nix new file mode 100644 index 00000000000..f73e326f31e --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/modules/xresources/xresources.nix @@ -0,0 +1,22 @@ +{ config, lib, ... }: + +with lib; + +{ + config = { + xresources = { + properties = { + "Test*string" = "test-string"; + "Test*boolean1" = true; + "Test*boolean2" = false; + "Test*int" = 10; + "Test*list" = [ "list-str" true false 10 ]; + }; + }; + + nmt.script = '' + assertFileExists home-files/.Xresources + assertFileContent home-files/.Xresources ${./xresources-expected.conf} + ''; + }; +} diff --git a/infra/libkookie/home-manager-stable/tests/stubs.nix b/infra/libkookie/home-manager-stable/tests/stubs.nix new file mode 100644 index 00000000000..01f4606547e --- /dev/null +++ b/infra/libkookie/home-manager-stable/tests/stubs.nix @@ -0,0 +1,61 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + stubType = types.submodule ({ name, ... }: { + options = { + name = mkOption { + type = types.str; + default = "dummy"; + description = "The stub package name."; + }; + + outPath = mkOption { + type = types.nullOr types.str; + default = "@${name}@"; + defaultText = "@\${name}@"; + }; + + version = mkOption { + type = types.nullOr types.str; + default = null; + }; + + buildScript = mkOption { + type = types.str; + default = defaultBuildScript; + }; + }; + }); + + defaultBuildScript = "mkdir $out"; + + dummyPackage = pkgs.runCommandLocal "dummy" { } defaultBuildScript; + + mkStubPackage = { name ? "dummy", outPath ? null, version ? null + , buildScript ? defaultBuildScript }: + let + pkg = if name == "dummy" && buildScript == defaultBuildScript then + dummyPackage + else + pkgs.runCommandLocal name { } buildScript; + in pkg // optionalAttrs (outPath != null) { inherit outPath; } + // optionalAttrs (version != null) { inherit version; }; + +in { + options.test.stubs = mkOption { + type = types.attrsOf stubType; + default = { }; + description = + "Package attributes that should be replaced by a stub package."; + }; + + config = { + lib.test.mkStubPackage = mkStubPackage; + + nixpkgs.overlays = mkIf (config.test.stubs != { }) + [ (self: super: mapAttrs (n: mkStubPackage) config.test.stubs) ]; + }; +} diff --git a/infra/libkookie/home-manager-stable/xgettext b/infra/libkookie/home-manager-stable/xgettext new file mode 100755 index 00000000000..8580a324f96 --- /dev/null +++ b/infra/libkookie/home-manager-stable/xgettext @@ -0,0 +1,37 @@ +#! /usr/bin/env nix-shell +#! nix-shell -I https://github.com/NixOS/nixpkgs/archive/05f0934825c2a0750d4888c4735f9420c906b388.tar.gz -i bash -p gettext + +set -euo pipefail +shopt -s globstar + +function run() { + packageName="$1" + output="$2" + domain="$3" + shift 3 + + xgettext -v --package-name="$packageName" \ + --copyright-holder='Home Manager contributors' \ + --msgid-bugs-address=https://github.com/nix-community/home-manager/issues \ + -L Shell -k \ + -k_i:1 --flag=_i:1:c-format \ + -k_iError:1 --flag=_i:1:c-format \ + -k_iWarn:1 --flag=_i:1:c-format \ + -k_iNote:1 --flag=_i:1:c-format \ + -k_ip:1,2 --flag=_ip:1:c-format --flag=_ip:2:c-format \ + -k_ipError:1,2 --flag=_ip:1:c-format --flag=_ip:2:c-format \ + -k_ipWarn:1,2 --flag=_ip:1:c-format --flag=_ip:2:c-format \ + -k_ipNote:1,2 --flag=_ip:1:c-format --flag=_ip:2:c-format \ + --add-comments=translators: \ + -o "$output" -d "$domain" "$@" +} + +run 'Home Manager' \ + home-manager/po/home-manager.pot \ + home-manager \ + home-manager/home-manager home-manager/**/*.nix + +run 'Home Manager Modules' \ + modules/po/hm-modules.pot \ + hm-modules \ + modules/**/*.{nix,sh}