1
0
Fork 0
mirror of https://github.com/nix-community/home-manager synced 2024-11-26 21:19:45 +01:00

Merge branch 'master' into fix/hypridle

This commit is contained in:
Zoe Roux 2024-11-14 12:20:03 +01:00 committed by GitHub
commit 27510a7e32
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
307 changed files with 6706 additions and 1848 deletions

View file

@ -19,3 +19,6 @@ indent_style = tab
[*.md]
trim_trailing_whitespace = false
[*.plist]
insert_final_newline = false

View file

@ -8,14 +8,6 @@ updates:
commit-message:
prefix: "ci:"
- package-ecosystem: "github-actions"
directory: "/"
target-branch: "release-23.11"
schedule:
interval: "weekly"
commit-message:
prefix: "ci:"
- package-ecosystem: "github-actions"
directory: "/"
target-branch: "release-24.05"

View file

@ -11,7 +11,7 @@ jobs:
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: cachix/install-nix-action@v27
- uses: cachix/install-nix-action@v30
with:
nix_path: nixpkgs=channel:nixos-unstable
- uses: cachix/cachix-action@v15

View file

@ -12,7 +12,7 @@ jobs:
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: cachix/install-nix-action@v27
- uses: cachix/install-nix-action@v30
with:
nix_path: nixpkgs=channel:nixos-unstable
- run: |
@ -25,3 +25,5 @@ jobs:
- run: nix-shell --show-trace . -A install
- run: yes | home-manager -I home-manager=. uninstall
- run: nix-shell --show-trace --arg enableBig false --pure tests -A run.all
# Somebody please help us fix the macos tests.
if: matrix.os != 'macos-latest'

View file

@ -12,9 +12,9 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Nix
uses: cachix/install-nix-action@v27
uses: cachix/install-nix-action@v30
- name: Update flake.lock
uses: DeterminateSystems/update-flake-lock@v23
uses: DeterminateSystems/update-flake-lock@v24
with:
token: ${{ secrets.GH_TOKEN_FOR_UPDATES }}
pr-labels: dependencies

View file

@ -147,7 +147,7 @@ in {
substitute \
${hmOptionsDocs.optionsJSON}/nix-support/hydra-build-products \
$out/nix-support/hydra-build-products \
--replace \
--replace-fail \
'${hmOptionsDocs.optionsJSON}/share/doc/nixos' \
"$out/share/doc/home-manager"
'';

View file

@ -59,5 +59,7 @@ in stdenv.mkDerivation {
echo "doc manual $dest index.html" >> $out/nix-support/hydra-build-products
'';
passthru = { inherit home-manager-options; };
meta = { maintainers = [ lib.maintainers.considerate ]; };
}

View file

@ -59,5 +59,6 @@ usage/configuration.md
usage/rollbacks.md
usage/dotfiles.md
usage/graphical.md
usage/gpu-non-nixos.md
usage/updating.md
```

View file

@ -0,0 +1,81 @@
# GPU on non-NixOS systems {#sec-usage-gpu-non-nixos}
To access the GPU, programs need access to OpenGL and Vulkan libraries. While
this works transparently on NixOS, it does not on other Linux systems. A
solution is provided by [NixGL](https://github.com/nix-community/nixGL), which
can be integrated into Home Manager.
To enable the integration, import NixGL into your home configuration, either as
a channel, or as a flake input passed via `extraSpecialArgs`. Then, set the
`nixGL.packages` option to the package set provided by NixGL.
Once integration is enabled, it can be used in two ways: as Nix functions for
wrapping programs installed via Home Manager, and as shell commands for running
programs installed by other means (such as `nix shell`). In either case, there
are several wrappers available. They can be broadly categorized
- by vendor: as Mesa (for Free drivers of all vendors) and Nvidia (for
Nvidia-specific proprietary drivers).
- by GPU selection: as primary and secondary (offloading).
For example, the `mesa` wrapper provides support for running programs on the
primary GPU for Intel, AMD and Nouveau drivers, while the `mesaPrime` wrapper
does the same for the secondary GPU.
**Note:** when using Nvidia wrappers together with flakes, your home
configuration will not be pure and needs to be built using `home-manager switch
--impure`. Otherwise, the build will fail, complaining about missing attribute
`currentTime`.
Wrapper functions are available under `config.lib.nixGL.wrappers`. However, it
can be more convenient to use the `config.lib.nixGL.wrap` alias, which can be
configured to use any of the wrappers. It is intended to provide a customization
point when the same home configuration is used across several machines with
different hardware. There is also the `config.lib.nixGL.wrapOffload` alias for
two-GPU systems.
Another convenience is that all wrapper functions are always available. However,
when `nixGL.packages` option is unset, they are no-ops. This allows them to be
used even when the home configuration is used on NixOS machines. The exception
is the `prime-offload` script which ignores `nixGL.packages` and is installed
into the environment whenever `nixGL.prime.installScript` is set. This script,
which can be used to start a program on a secondary GPU, does not depend on
NixGL and is useful on NixOS systems as well.
Below is an abbreviated example for an Optimus laptop that makes use of both
Mesa and Nvidia wrappers, where the latter is used in dGPU offloading mode. It
demonstrates how to wrap `mpv` to run on the integrated Intel GPU, wrap FreeCAD
to run on the Nvidia dGPU, and how to install the wrapper scripts. It also wraps
Xonotic to run on the dGPU, but uses the wrapper function directly for
demonstration purposes.
```nix
{ config, lib, pkgs, nixgl, ... }:
{
nixGL.packages = nixgl.packages;
nixGL.defaultWrapper = "mesa";
nixGL.offloadWrapper = "nvidiaPrime";
nixGL.installScripts = [ "mesa" "nvidiaPrime" ];
programs.mpv = {
enable = true;
package = config.lib.nixGL.wrap pkgs.mpv;
};
home.packages = [
(config.lib.nixGL.wrapOffload pkgs.freecad)
(config.lib.nixGL.wrappers.nvidiaPrime pkgs.xonotic)
];
}
```
The above example assumes a flake-based setup where `nixgl` was passed from the
flake. When using channels, the example would instead begin with
```nix
{ config, lib, pkgs, ... }:
{
nixGL.packages = import <nixgl> { inherit pkgs; };
# The rest is the same as above
...
```

View file

@ -7,7 +7,21 @@ is therefore not final.
This release has the following notable changes:
- No changes.
- The swayidle module behavior has changed. Specifically, swayidle was
previously always called with a `-w` flag. This flag is now moved to
the default
[services.swayidle.extraArgs](#opt-services.swayidle.extraArgs)
value to make it optional.
Your configuration may break if you already set this option and also
rely on the flag being automatically added. To resolve this, please
add `-w` to your assignment of
[services.swayidle.extraArgs](#opt-services.swayidle.extraArgs).
- Support for Boolean values in the option
[programs.eza.icons](#opt-programs.eza.icons) is deprecated for
future removal. The new value for `true` is `"auto"`, and for
`false` it is `null`.
## State Version Changes {#sec-release-24.11-state-version-changes}

View file

@ -2,11 +2,11 @@
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1719848872,
"narHash": "sha256-H3+EC5cYuq+gQW8y0lSrrDZfH71LB4DAf+TDFyvwCNA=",
"lastModified": 1731139594,
"narHash": "sha256-IigrKK3vYRpUu+HEjPL/phrfh7Ox881er1UEsZvw9Q4=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "00d80d13810dbfea8ab4ed1009b09100cca86ba8",
"rev": "76612b17c0ce71689921ca12d9ffdc9c23ce40b2",
"type": "github"
},
"original": {

View file

@ -1,5 +1,5 @@
{ runCommand, lib, bash, callPackage, coreutils, findutils, gettext, gnused, jq
, less, ncurses, unixtools
, less, ncurses, inetutils
# used for pkgs.path for nixos-option
, pkgs
@ -38,7 +38,7 @@ in runCommand "home-manager" {
less
ncurses
nixos-option
unixtools.hostname
inetutils # for `hostname`
]
}" \
--subst-var-by HOME_MANAGER_LIB '${../lib/bash/home-manager.sh}' \

View file

@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: Home Manager\n"
"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n"
"POT-Creation-Date: 2024-04-17 23:19+0200\n"
"PO-Revision-Date: 2024-04-05 11:01+0000\n"
"Last-Translator: Leix b <abone9999@gmail.com>\n"
"PO-Revision-Date: 2024-08-07 17:09+0000\n"
"Last-Translator: Tomi Ockier <ockier1@gmail.com>\n"
"Language-Team: Catalan <https://hosted.weblate.org/projects/home-manager/cli/"
"ca/>\n"
"Language: ca\n"
@ -17,12 +17,12 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.5-dev\n"
"X-Generator: Weblate 5.7-dev\n"
#. translators: For example: "home-manager: missing argument for --cores"
#: home-manager/home-manager:16
msgid "%s: missing argument for %s"
msgstr ""
msgstr "%: falta un argument per %s"
#: home-manager/home-manager:64
msgid "No configuration file found at %s"

220
home-manager/po/hi.po Normal file
View file

@ -0,0 +1,220 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR Home Manager contributors
# This file is distributed under the same license as the Home Manager package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 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: 2024-04-17 23:19+0200\n"
"PO-Revision-Date: 2024-10-09 14:31+0000\n"
"Last-Translator: Utkarsh Sharma <utkasharma19@gmail.com>\n"
"Language-Team: Hindi <https://hosted.weblate.org/projects/home-manager/cli/"
"hi/>\n"
"Language: hi\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 5.8-dev\n"
#. translators: For example: "home-manager: missing argument for --cores"
#: home-manager/home-manager:16
msgid "%s: missing argument for %s"
msgstr "%s: %s के लिए कोई आर्ग्यूमेंट नहीं दिया"
#: home-manager/home-manager:64
msgid "No configuration file found at %s"
msgstr "%s में कोई कन्फि़गरेशन फाइल नहीं मिली"
#. translators: The first '%s' specifier will be replaced by either
#. 'home.nix' or 'flake.nix'.
#: home-manager/home-manager:81 home-manager/home-manager:85
#: home-manager/home-manager:184
msgid ""
"Keeping your Home Manager %s in %s is deprecated,\n"
"please move it to %s"
msgstr ""
"अपने Home Manager %s को %s में रखना अप्रचलित है,\n"
"कृपया इसे %s में स्थानांतरित करें"
#: home-manager/home-manager:92
msgid "No configuration file found. Please create one at %s"
msgstr "कोई कॉन्फ़िगरेशन फ़ाइल नहीं मिली। कृपया %s पर एक फ़ाइल बनाएं।"
#: home-manager/home-manager:107
msgid "Home Manager not found at %s."
msgstr "%s पर Home Manager नहीं मिला।"
#. translators: This message will be seen by very few users that likely are familiar with English. So feel free to leave this untranslated.
#: home-manager/home-manager:115
msgid ""
"The fallback Home Manager path %s has been deprecated and a file/directory "
"was found there."
msgstr ""
#. translators: This message will be seen by very few users that likely are familiar with English. So feel free to leave this untranslated.
#: home-manager/home-manager:118
msgid ""
"To remove this warning, do one of the following.\n"
"\n"
"1. Explicitly tell Home Manager to use the path, for example by adding\n"
"\n"
" { programs.home-manager.path = \"%s\"; }\n"
"\n"
" to your configuration.\n"
"\n"
" If you import Home Manager directly, you can use the `path` parameter\n"
"\n"
" pkgs.callPackage /path/to/home-manager-package { path = \"%s\"; }\n"
"\n"
" when calling the Home Manager package.\n"
"\n"
"2. Remove the deprecated path.\n"
"\n"
" $ rm -r \"%s\""
msgstr ""
#: home-manager/home-manager:146
msgid "Sanity checking Nix"
msgstr ""
#: home-manager/home-manager:166
msgid "Could not find suitable profile directory, tried %s and %s"
msgstr ""
#. translators: Here "flake" is a noun that refers to the Nix Flakes feature.
#: home-manager/home-manager:221
msgid "Can't inspect options of a flake configuration"
msgstr ""
#: home-manager/home-manager:296 home-manager/home-manager:319
#: home-manager/home-manager:1051
msgid "%s: unknown option '%s'"
msgstr ""
#: home-manager/home-manager:301 home-manager/home-manager:1052
msgid "Run '%s --help' for usage help"
msgstr ""
#: home-manager/home-manager:327 home-manager/home-manager:431
msgid "The file %s already exists, leaving it unchanged..."
msgstr ""
#: home-manager/home-manager:329 home-manager/home-manager:433
msgid "Creating %s..."
msgstr ""
#: home-manager/home-manager:475
msgid "Creating initial Home Manager generation..."
msgstr ""
#. translators: The "%s" specifier will be replaced by a file path.
#: home-manager/home-manager:480
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/home-manager:485
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 ""
#. translators: Here "flake" is a noun that refers to the Nix Flakes feature.
#: home-manager/home-manager:496
msgid "Can't instantiate a flake configuration"
msgstr ""
#: home-manager/home-manager:572
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:586
msgid "Unknown \"news.display\" setting \"%s\"."
msgstr ""
#: home-manager/home-manager:594
#, sh-format
msgid "Please set the $EDITOR or $VISUAL environment variable"
msgstr ""
#: home-manager/home-manager:612
msgid "Cannot run build in read-only directory"
msgstr ""
#: home-manager/home-manager:693
msgid "No generation with ID %s"
msgstr ""
#: home-manager/home-manager:695
msgid "Cannot remove the current generation %s"
msgstr ""
#: home-manager/home-manager:697
msgid "Removing generation %s"
msgstr ""
#: home-manager/home-manager:718
msgid "No generations to expire"
msgstr ""
#: home-manager/home-manager:729
msgid "No home-manager packages seem to be installed."
msgstr ""
#: home-manager/home-manager:811
msgid "Unknown argument %s"
msgstr ""
#: home-manager/home-manager:835
msgid "This will remove Home Manager from your system."
msgstr ""
#: home-manager/home-manager:838
msgid "This is a dry run, nothing will actually be uninstalled."
msgstr ""
#: home-manager/home-manager:842
msgid "Really uninstall Home Manager?"
msgstr ""
#: home-manager/home-manager:848
msgid "Switching to empty Home Manager configuration..."
msgstr ""
#: home-manager/home-manager:863
msgid "Yay!"
msgstr ""
#: home-manager/home-manager:868
msgid "Home Manager is uninstalled but your home.nix is left untouched."
msgstr ""
#: home-manager/home-manager:1091
msgid "expire-generations expects one argument, got %d."
msgstr ""
#: home-manager/home-manager:1113
msgid "Unknown command: %s"
msgstr ""
#: home-manager/install.nix:18
msgid "This derivation is not buildable, please run it using nix-shell."
msgstr ""

View file

@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: Home Manager\n"
"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n"
"POT-Creation-Date: 2024-04-17 23:19+0200\n"
"PO-Revision-Date: 2024-07-05 14:09+0000\n"
"PO-Revision-Date: 2024-09-02 17:09+0000\n"
"Last-Translator: Ferenci Ákos <synthetace@gmail.com>\n"
"Language-Team: Hungarian <https://hosted.weblate.org/projects/home-manager/"
"cli/hu/>\n"
@ -17,7 +17,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.7-dev\n"
"X-Generator: Weblate 5.8-dev\n"
#. translators: For example: "home-manager: missing argument for --cores"
#: home-manager/home-manager:16
@ -54,6 +54,8 @@ msgid ""
"The fallback Home Manager path %s has been deprecated and a file/directory "
"was found there."
msgstr ""
"A tartalék Home Manager fájlútvonal %s elavult és fájl/könyvtár található "
"itt."
#. translators: This message will be seen by very few users that likely are familiar with English. So feel free to leave this untranslated.
#: home-manager/home-manager:118
@ -76,19 +78,37 @@ msgid ""
"\n"
" $ rm -r \"%s\""
msgstr ""
"A felmerült hiba elhárítására a következőket tegye:\n"
"\n"
"1. Közvetlen adja át a Home Manager-nek a fájlútvonalat, pl.:\n"
"\n"
" { programs.home-manager.path = \"%s\"; }\n"
"\n"
" sor konfigurációhoz való hozzáadásával.\n"
"\n"
" Amennyiben a Home Manager-t közvetlen importolja, használhatja a 'path' "
"paramétert\n"
"\n"
" pkgs.callPackage/path/tohome-manager-package{path = \"%s\"; }\n"
" a Home Manager csomag meghívásakor.\n"
"\n"
" 2. Távolítsa el az elavult fájlútvonalat.\n"
"\n"
" $ rm -r \"$s\""
#: home-manager/home-manager:146
msgid "Sanity checking Nix"
msgstr ""
msgstr "Nix épségének ellenőrzése"
#: home-manager/home-manager:166
msgid "Could not find suitable profile directory, tried %s and %s"
msgstr ""
"Nem található megfelelő profil mappa, %s és %s útvonalak lettek kipróbálva."
#. translators: Here "flake" is a noun that refers to the Nix Flakes feature.
#: home-manager/home-manager:221
msgid "Can't inspect options of a flake configuration"
msgstr ""
msgstr "Nem lehet a flake konfiguráció beállításait megtekinteni."
#: home-manager/home-manager:296 home-manager/home-manager:319
#: home-manager/home-manager:1051
@ -121,6 +141,13 @@ msgid ""
"to configure Home Manager. Run 'man home-configuration.nix' to\n"
"see all available options."
msgstr ""
"Elkészült! A home-manager eszköz most már installálva van és a \n"
"\n"
" %s\n"
"\n"
"fájl szerkesztésével konfigurálhatja a Home Manager-t. \n"
"Futtassa a 'man home-configuration.nix' parancsot az összes opció "
"áttekintéséhez."
#. translators: The "%s" specifier will be replaced by a URL.
#: home-manager/home-manager:485
@ -131,6 +158,11 @@ msgid ""
"\n"
"if the error seems to be the fault of Home Manager."
msgstr ""
"Uh oh, az installáció nem sikerült! Kérem készítsen egy jelentést erről a \n"
"\n"
" %s\n"
"\n"
"helyen amennyiben a hiba a Home Manager miatt lépett fel."
#. translators: Here "flake" is a noun that refers to the Nix Flakes feature.
#: home-manager/home-manager:496
@ -145,16 +177,20 @@ msgid_plural ""
"There are %d unread and relevant news items.\n"
"Read them by running the command \"%s news\"."
msgstr[0] ""
"%d olvasatlan és releváns hírt kapott.\n"
"Olvassa el a \"%s news\" futattásával."
msgstr[1] ""
"%d olvasatlan és releváns hírt kapott.\n"
"Olvassa el őket a \"%s news\" futattásával."
#: home-manager/home-manager:586
msgid "Unknown \"news.display\" setting \"%s\"."
msgstr ""
msgstr "Ismeretlen \"news.display\" opció \"%s\"."
#: home-manager/home-manager:594
#, sh-format
msgid "Please set the $EDITOR or $VISUAL environment variable"
msgstr ""
msgstr "Kérem állítása be az $EDITOR vagy a $VISUAL környezeti változókat."
#: home-manager/home-manager:612
msgid "Cannot run build in read-only directory"
@ -162,11 +198,11 @@ msgstr "Build futtatása nem lehetséges csak-olvasható könyvtárban"
#: home-manager/home-manager:693
msgid "No generation with ID %s"
msgstr ""
msgstr "Nem található generáció a következő ID-val: %"
#: home-manager/home-manager:695
msgid "Cannot remove the current generation %s"
msgstr ""
msgstr "A jelenlegi generáció %s nem eltávolítható"
#: home-manager/home-manager:697
msgid "Removing generation %s"
@ -174,11 +210,11 @@ msgstr "%s generáció eltávolítása"
#: home-manager/home-manager:718
msgid "No generations to expire"
msgstr ""
msgstr "Nincs lejárandó generáció"
#: home-manager/home-manager:729
msgid "No home-manager packages seem to be installed."
msgstr ""
msgstr "Nem található installált Home Manager csomag"
#: home-manager/home-manager:811
msgid "Unknown argument %s"
@ -186,19 +222,19 @@ msgstr "Ismeretlen argumentum %s"
#: home-manager/home-manager:835
msgid "This will remove Home Manager from your system."
msgstr ""
msgstr "Ez a művelet eltávolítja a Home Manager-t a rendszeréről."
#: home-manager/home-manager:838
msgid "This is a dry run, nothing will actually be uninstalled."
msgstr ""
msgstr "Ez egy üres járat, semmi nem lesz valójában eltávolítva."
#: home-manager/home-manager:842
msgid "Really uninstall Home Manager?"
msgstr ""
msgstr "Biztosan eltávolítja a Home Managert-t?"
#: home-manager/home-manager:848
msgid "Switching to empty Home Manager configuration..."
msgstr ""
msgstr "Átváltás üres Home Manager konfigurációra..."
#: home-manager/home-manager:863
msgid "Yay!"
@ -206,7 +242,7 @@ msgstr "Hurrá!"
#: home-manager/home-manager:868
msgid "Home Manager is uninstalled but your home.nix is left untouched."
msgstr ""
msgstr "Home Manager eltávolítva, de a home.nix fájl érintetlenül maradt."
#: home-manager/home-manager:1091
msgid "expire-generations expects one argument, got %d."
@ -219,3 +255,4 @@ msgstr "Ismeretlen parancs: %s"
#: home-manager/install.nix:18
msgid "This derivation is not buildable, please run it using nix-shell."
msgstr ""
"Ez a származtatás nem építhető fel, kérlek futtasd nix-shell segítségével."

View file

@ -8,22 +8,22 @@ msgstr ""
"Project-Id-Version: Home Manager\n"
"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n"
"POT-Creation-Date: 2024-04-17 23:19+0200\n"
"PO-Revision-Date: 2024-02-16 22:01+0000\n"
"Last-Translator: Robert Helgesson <robert@rycee.net>\n"
"PO-Revision-Date: 2024-10-17 00:20+0000\n"
"Last-Translator: Julius Marozas <marozas.julius@gmail.com>\n"
"Language-Team: Lithuanian <https://hosted.weblate.org/projects/home-manager/"
"cli/lt/>\n"
"Language: lt\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%100<10 || n%100>=20) ? 1 : 2);\n"
"X-Generator: Weblate 5.4\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && ("
"n%100<10 || n%100>=20) ? 1 : 2);\n"
"X-Generator: Weblate 5.8-rc\n"
#. translators: For example: "home-manager: missing argument for --cores"
#: home-manager/home-manager:16
msgid "%s: missing argument for %s"
msgstr ""
msgstr "%s: trūksta argumento %s"
#: home-manager/home-manager:64
msgid "No configuration file found at %s"
@ -55,6 +55,8 @@ msgid ""
"The fallback Home Manager path %s has been deprecated and a file/directory "
"was found there."
msgstr ""
"Atsarginis kelias %s į Home Manager jau nebenaudojamas, tačiau jame buvo "
"rastas failas/katalogas."
#. translators: This message will be seen by very few users that likely are familiar with English. So feel free to leave this untranslated.
#: home-manager/home-manager:118
@ -77,6 +79,24 @@ msgid ""
"\n"
" $ rm -r \"%s\""
msgstr ""
"Norėdami pašalinti šį įspėjimą, atlikite vieną iš šių veiksmų.\n"
"\n"
"1. Aiškiai nurodykite kelią į Home Manager, pavyzdžiui, pridėdami\n"
"\n"
" { programs.home-manager.path = \"%s\"; }\n"
"\n"
" prie jūsų konfigūracijos.\n"
"\n"
" Jei importuojate Home Manager tiesiogiai, galite naudoti parametrą `path`."
"\n"
"\n"
" pkgs.callPackage /path/to/home-manager-package { path = \"%s\"; }\n"
"\n"
" kviečiant į Home Manager paketą.\n"
"\n"
"2. Pašalinkite nebenaudojamą kelią.\n"
"\n"
" $ rm -r \"%s\""
#: home-manager/home-manager:146
msgid "Sanity checking Nix"
@ -175,10 +195,9 @@ msgstr "Nežinomas \"news.display\" nustatymas \"%s\"."
#: home-manager/home-manager:594
#, sh-format
msgid "Please set the $EDITOR or $VISUAL environment variable"
msgstr ""
msgstr "Nustatykite $EDITOR arba $VISUAL aplinkos kintamuosius"
#: home-manager/home-manager:612
#, fuzzy
msgid "Cannot run build in read-only directory"
msgstr "Negalima vykdyti kompiliavimo read-only kataloge"

View file

@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: Home Manager\n"
"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n"
"POT-Creation-Date: 2024-04-17 23:19+0200\n"
"PO-Revision-Date: 2024-03-31 22:01+0000\n"
"Last-Translator: SMFloris <floris.sm@gmail.com>\n"
"PO-Revision-Date: 2024-09-09 10:09+0000\n"
"Last-Translator: Felix Puscasu <puscasu.felix1@gmail.com>\n"
"Language-Team: Romanian <https://hosted.weblate.org/projects/home-manager/"
"cli/ro/>\n"
"Language: ro\n"
@ -18,12 +18,12 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < "
"20)) ? 1 : 2;\n"
"X-Generator: Weblate 5.5-dev\n"
"X-Generator: Weblate 5.8-dev\n"
#. translators: For example: "home-manager: missing argument for --cores"
#: home-manager/home-manager:16
msgid "%s: missing argument for %s"
msgstr ""
msgstr "%s: Argument lipsă pentru %s"
#: home-manager/home-manager:64
msgid "No configuration file found at %s"

View file

@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: Home Manager\n"
"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n"
"POT-Creation-Date: 2024-04-17 23:19+0200\n"
"PO-Revision-Date: 2024-03-31 22:01+0000\n"
"Last-Translator: Petr Portnov | PROgrm_JARvis <mrJARVIScraft@gmail.com>\n"
"PO-Revision-Date: 2024-09-12 02:12+0000\n"
"Last-Translator: NikSne <commits@niksne.ru>\n"
"Language-Team: Russian <https://hosted.weblate.org/projects/home-manager/cli/"
"ru/>\n"
"Language: ru\n"
@ -18,12 +18,12 @@ msgstr ""
"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 5.5-dev\n"
"X-Generator: Weblate 5.8-dev\n"
#. translators: For example: "home-manager: missing argument for --cores"
#: home-manager/home-manager:16
msgid "%s: missing argument for %s"
msgstr ""
msgstr "%s: отсутствует параметр для %s"
#: home-manager/home-manager:64
msgid "No configuration file found at %s"

View file

@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: Home Manager\n"
"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n"
"POT-Creation-Date: 2024-04-17 23:19+0200\n"
"PO-Revision-Date: 2024-06-02 08:12+0000\n"
"PO-Revision-Date: 2024-08-01 04:09+0000\n"
"Last-Translator: goatastronaut0212 <goatastronaut0212@proton.me>\n"
"Language-Team: Vietnamese <https://hosted.weblate.org/projects/home-manager/"
"cli/vi/>\n"
@ -17,7 +17,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Weblate 5.6-dev\n"
"X-Generator: Weblate 5.7-dev\n"
#. translators: For example: "home-manager: missing argument for --cores"
#: home-manager/home-manager:16
@ -97,7 +97,7 @@ msgstr ""
#: home-manager/home-manager:146
msgid "Sanity checking Nix"
msgstr "Kiểm tra độ hợp lệ của Nix"
msgstr "Kiểm tra hợp lệ của Nix"
#: home-manager/home-manager:166
msgid "Could not find suitable profile directory, tried %s and %s"
@ -175,11 +175,12 @@ msgid_plural ""
"There are %d unread and relevant news items.\n"
"Read them by running the command \"%s news\"."
msgstr[0] ""
msgstr[1] ""
"Có %d tin tức liên quan và chưa được đọc.\n"
"Để đọc nó hãy chạy lệnh \"%s news\"."
#: home-manager/home-manager:586
msgid "Unknown \"news.display\" setting \"%s\"."
msgstr ""
msgstr "Không tồn tại \"news.display\" cấu hình \"%s\"."
#: home-manager/home-manager:594
#, sh-format
@ -192,19 +193,19 @@ msgstr "Không thể chạy lệnh xây dựng trong thư mục chỉ cho phép
#: home-manager/home-manager:693
msgid "No generation with ID %s"
msgstr ""
msgstr "Không có thế hệ với ID %s"
#: home-manager/home-manager:695
msgid "Cannot remove the current generation %s"
msgstr ""
msgstr "Không thể xóa thể hệ hiện tại %s"
#: home-manager/home-manager:697
msgid "Removing generation %s"
msgstr ""
msgstr "Đang xóa thế hệ %s"
#: home-manager/home-manager:718
msgid "No generations to expire"
msgstr ""
msgstr "Không có bất kỳ thế hệ nào hết hạn"
#: home-manager/home-manager:729
msgid "No home-manager packages seem to be installed."
@ -237,10 +238,12 @@ msgstr "Tuyệt vời!"
#: home-manager/home-manager:868
msgid "Home Manager is uninstalled but your home.nix is left untouched."
msgstr ""
"Home Manager đã được gỡ cài đặt nhưng home.nix của bạn sẽ được giữ nguyên "
"vẹn."
#: home-manager/home-manager:1091
msgid "expire-generations expects one argument, got %d."
msgstr ""
msgstr "expire-generations kỳ vọng 1 đối số, có %d."
#: home-manager/home-manager:1113
msgid "Unknown command: %s"

View file

@ -12,7 +12,8 @@ let
path = mkOption {
type = types.str;
default = "${cfg.basePath}/${name}";
defaultText = "accounts.calendar.basePath/name";
defaultText =
lib.literalExpression "accounts.calendar.basePath/name";
description = "The path of the storage.";
};

View file

@ -12,7 +12,8 @@ let
path = mkOption {
type = types.str;
default = "${cfg.basePath}/${name}";
defaultText = "accounts.contact.basePath/name";
defaultText =
lib.literalExpression "accounts.contact.basePath/name";
description = "The path of the storage.";
};

View file

@ -67,7 +67,7 @@ let
};
in {
meta.maintainers = [ maintainers.polykernel maintainers.league ];
meta.maintainers = [ maintainers.league ];
imports = [
(mkAliasOptionModule [ "xsession" "pointerCursor" "package" ] [

View file

@ -280,8 +280,9 @@ in
};
```
may not work as expected. If you need to reference another
session variable, then do so inside Nix instead. The above
example then becomes
session variable (even if it is declared by using other options
like [](#opt-xdg.configHome)), then do so inside Nix instead.
The above example then becomes
```nix
home.sessionVariables = {
FOO = "Hello";

View file

@ -14,4 +14,5 @@ rec {
shell = import ./shell.nix { inherit lib; };
zsh = import ./zsh.nix { inherit lib; };
nushell = import ./nushell.nix { inherit lib; };
}

View file

@ -7,6 +7,12 @@
# [1] https://github.com/NixOS/nixpkgs/blob/fca0d6e093c82b31103dc0dacc48da2a9b06e24b/maintainers/maintainer-list.nix#LC1
{
aabccd021 = {
name = "Muhamad Abdurahman";
email = "aabccd021@gmail.com";
github = "aabccd021";
githubId = 33031950;
};
abayomi185 = {
name = "Yomi";
email = "yomi+nix@yomitosh.com";
@ -37,6 +43,12 @@
github = "Avimitin";
githubId = 30021675;
};
bamhm182 = {
name = "bamhm182";
email = "bamhm182@gmail.com";
github = "bamhm182";
githubId = 920269;
};
blmhemu = {
name = "blmhemu";
email = "19410501+blmhemu@users.noreply.github.com";
@ -49,6 +61,12 @@
github = "bertof";
githubId = 9915675;
};
bricked = {
name = "Bricked";
email = "hello@bricked.dev";
github = "brckd";
githubId = 92804487;
};
CarlosLoboxyz = {
name = "Carlos Lobo";
email = "86011416+CarlosLoboxyz@users.noreply.github.com";
@ -270,6 +288,22 @@
github = "nilp0inter";
githubId = 1224006;
};
NitroSniper = {
name = "Nitro Sniper";
email = "nitro@ortin.dev";
github = "NitroSniper";
githubId = 44097331;
};
n-hass = {
name = "Nicholas Hassan";
email = "nick@hassan.host";
github = "n-hass";
githubId = 72363381;
keys = [{
longkeyid = "rsa4096/0xFC95AB946A781EE7";
fingerprint = "FDEE 6116 DBA7 8840 7323 4466 A371 5973 2728 A6A6";
}];
};
seylerius = {
email = "sable@seyleri.us";
name = "Sable Seyler";
@ -331,6 +365,11 @@
githubId = 12465195;
name = "Bruno BELANYI";
};
libewa = {
email = "libewa-git@icloud.com";
github = "libewa";
githubId = 67926131;
};
malvo = {
email = "malte@malvo.org";
github = "malte-v";
@ -409,12 +448,6 @@
github = "nurelin";
githubId = 5276274;
};
omernaveedxyz = {
name = "Omer Naveed";
email = "omer@omernaveed.dev";
github = "omernaveedxyz";
githubId = 112912585;
};
otavio = {
email = "otavio.salvador@ossystems.com.br";
github = "otavio";
@ -581,4 +614,18 @@
github = "zorrobert";
githubId = 118135271;
};
joygnu = {
name = "joygnu";
email = "contact@joygnu.org";
github = "joygnu";
githubId = 152063003;
};
callumio = {
name = "Callum Leslie";
email = "git+nix@cleslie.uk";
github = "callumio";
githubId = 16057677;
keys =
[{ fingerprint = "BC82 4BB5 1656 D144 285E A0EC D382 C4AF EECE AA90"; }];
};
}

65
modules/lib/nushell.nix Normal file
View file

@ -0,0 +1,65 @@
{ lib }: rec {
mkNushellInline = expr: lib.setType "nushell-inline" { inherit expr; };
toNushell = { indent ? "", multiline ? true, asBindings ? false }@args:
v:
let
innerIndent = "${indent} ";
introSpace = if multiline then ''
${innerIndent}'' else
" ";
outroSpace = if multiline then ''
${indent}'' else
" ";
innerArgs = args // {
indent = if asBindings then indent else innerIndent;
asBindings = false;
};
concatItems = lib.concatStringsSep introSpace;
isNushellInline = lib.isType "nushell-inline";
generatedBindings = assert lib.assertMsg (badVarNames == [ ])
"Bad Nushell variable names: ${
lib.generators.toPretty { } badVarNames
}";
lib.concatStrings (lib.mapAttrsToList (key: value: ''
${indent}let ${key} = ${toNushell innerArgs value}
'') v);
isBadVarName = name:
# Extracted from https://github.com/nushell/nushell/blob/ebc7b80c23f777f70c5053cca428226b3fe00d30/crates/nu-parser/src/parser.rs#L33
# Variables with numeric or even empty names are allowed. The only requisite is not containing any of the following characters
let invalidVariableCharacters = ".[({+-*^/=!<>&|";
in lib.match "^[$]?[^${lib.escapeRegex invalidVariableCharacters}]+$"
name == null;
badVarNames = lib.filter isBadVarName (builtins.attrNames v);
in if asBindings then
generatedBindings
else if v == null then
"null"
else if lib.isInt v || lib.isFloat v || lib.isString v || lib.isBool v then
lib.strings.toJSON v
else if lib.isList v then
(if v == [ ] then
"[]"
else
"[${introSpace}${
concatItems (map (value: "${toNushell innerArgs value}") v)
}${outroSpace}]")
else if lib.isAttrs v then
(if isNushellInline v then
"(${v.expr})"
else if v == { } then
"{}"
else if lib.isDerivation v then
toString v
else
"{${introSpace}${
concatItems (lib.mapAttrsToList (key: value:
"${lib.strings.toJSON key}: ${toNushell innerArgs value}") v)
}${outroSpace}}")
else
abort "nushell.toNushell: type ${lib.typeOf v} is unsupported";
}

View file

@ -107,4 +107,27 @@ in rec {
mergeDefaultOption loc defs;
};
nushellValue = let
valueType = types.nullOr (types.oneOf [
(lib.mkOptionType {
name = "nushell";
description = "Nushell inline value";
descriptionClass = "name";
check = lib.isType "nushell-inline";
})
types.bool
types.int
types.float
types.str
types.path
(types.attrsOf valueType // {
description = "attribute set of Nushell values";
descriptionClass = "name";
})
(types.listOf valueType // {
description = "list of Nushell values";
descriptionClass = "name";
})
]);
in valueType;
}

View file

@ -1,9 +1,6 @@
{ config, lib, options, pkgs, ... }:
with lib;
let
cfg = config.news;
hostPlatform = pkgs.stdenv.hostPlatform;
@ -44,7 +41,6 @@ let
config = { id = mkDefault (builtins.hashString "sha256" config.message); };
});
in {
meta.maintainers = [ maintainers.rycee ];
@ -1703,6 +1699,134 @@ in {
one place. See https://github.com/glanceapp/glance for more.
'';
}
{
time = "2024-09-13T08:58:17+00:00";
condition = hostPlatform.isLinux;
message = ''
A new module is available: 'services.trayscale'.
An unofficial GUI wrapper around the Tailscale CLI client.
'';
}
{
time = "2024-09-13T09:50:49+00:00";
message = ''
A new module is available: 'programs.neovide'.
Neovide is a simple, no-nonsense, cross-platform graphical user
interface for Neovim (an aggressively refactored and updated Vim
editor).
'';
}
{
time = "2024-09-20T07:00:11+00:00";
condition = config.programs.kitty.theme != null;
message = ''
The option 'programs.kitty.theme' has been deprecated, please use
'programs.kitty.themeFile' instead.
The 'programs.kitty.themeFile' option expects the file name of a
theme from `kitty-themes`, without the `.conf` suffix. See
<https://github.com/kovidgoyal/kitty-themes/tree/master/themes> for a
list of themes.
'';
}
{
time = "2024-09-20T07:48:08+00:00";
condition = hostPlatform.isLinux && config.services.swayidle.enable;
message = ''
The swayidle module behavior has changed. Specifically, swayidle was
previously always called with a `-w` flag. This flag is now moved to
the default `services.swayidle.extraArgs` value to make it optional.
Your configuration may break if you already set this option and also
rely on the flag being automatically added. To resolve this, please
add `-w` to your assignment of `services.swayidle.extraArgs`.
'';
}
{
time = "2024-10-09T06:16:23+00:00";
condition = hostPlatform.isLinux;
message = ''
A new module is available: 'services.snixembed'.
snixembed proxies StatusNotifierItems as XEmbedded systemtray-spec
icons. This is useful for some tools in some environments, e.g., Safe
Eyes in i3, lxde or mate.
'';
}
{
time = "2024-10-11T08:23:19+00:00";
message = ''
A new module is available: 'programs.vifm'.
Vifm is a curses based Vim-like file manager extended with some useful
ideas from mutt.
'';
}
{
time = "2024-10-17T13:07:55+00:00";
message = ''
A new module is available: 'programs.zed-editor'.
Zed is a fast text editor for macOS and Linux.
See https://zed.dev for more.
'';
}
{
time = "2024-10-18T14:01:07+00:00";
message = ''
A new module is available: 'programs.cmus'.
cmus is a small, fast and powerful console music player.
'';
}
{
time = "2024-10-20T07:53:54+00:00";
condition = hostPlatform.isLinux;
message = ''
A new module is available: 'programs.nh'.
nh is yet another Nix CLI helper. Adding functionality on top of the
existing solutions, like nixos-rebuild, home-manager cli or nix
itself.
'';
}
{
time = "2024-10-25T08:18:30+00:00";
condition = hostPlatform.isLinux;
message = ''
A new module is available: 'nixGL'.
NixGL solve the "OpenGL" problem with nix. The 'nixGL' module provides
integration of NixGL into Home Manager. See the "GPU on non-NixOS
systems" section in the Home Manager manual for more.
'';
}
{
time = "2024-11-01T19:44:59+00:00";
condition = hostPlatform.isLinux;
message = ''
A new module is available: 'services.podman'.
Podman is a daemonless container engine that lets you manage
containers, pods, and images.
This Home Manager module allows you to define containers that will run
as systemd services.
'';
}
];
};
}

View file

@ -311,5 +311,5 @@ in {
})
]);
meta.maintainers = [ maintainers.polykernel ];
meta.maintainers = [ ];
}

296
modules/misc/nixgl.nix Normal file
View file

@ -0,0 +1,296 @@
{ config, lib, pkgs, ... }:
let
cfg = config.nixGL;
wrapperListMarkdown = with builtins;
foldl' (list: name:
list + ''
- ${name}
'') "" (attrNames config.lib.nixGL.wrappers);
in {
meta.maintainers = [ lib.maintainers.smona ];
options.nixGL = {
packages = lib.mkOption {
type = with lib.types; nullOr attrs;
default = null;
example = lib.literalExpression "inputs.nixGL.packages";
description = ''
The nixGL package set containing GPU library wrappers. This can be used
to provide OpenGL and Vulkan access to applications on non-NixOS systems
by using `(config.lib.nixGL.wrap <package>)` for the default wrapper, or
`(config.lib.nixGL.wrappers.<wrapper> <package>)` for any available
wrapper.
The wrapper functions are always available. If this option is empty (the
default), they are a no-op. This is useful on NixOS where the wrappers
are unnecessary.
Note that using any Nvidia wrapper requires building the configuration
with the `--impure` option.
'';
};
defaultWrapper = lib.mkOption {
type = lib.types.enum (builtins.attrNames config.lib.nixGL.wrappers);
default = "mesa";
description = ''
The package wrapper function available for use as `(config.lib.nixGL.wrap
<package>)`. Intended to start programs on the main GPU.
Wrapper functions can be found under `config.lib.nixGL.wrappers`. They
can be used directly, however, setting this option provides a convenient
shorthand.
The following wrappers are available:
${wrapperListMarkdown}
'';
};
offloadWrapper = lib.mkOption {
type = lib.types.enum (builtins.attrNames config.lib.nixGL.wrappers);
default = "mesaPrime";
description = ''
The package wrapper function available for use as
`(config.lib.nixGL.wrapOffload <package>)`. Intended to start programs
on the secondary GPU.
Wrapper functions can be found under `config.lib.nixGL.wrappers`. They
can be used directly, however, setting this option provides a convenient
shorthand.
The following wrappers are available:
${wrapperListMarkdown}
'';
};
prime.card = lib.mkOption {
type = lib.types.str;
default = "1";
example = "pci-0000_06_00_0";
description = ''
Selects the non-default graphics card used for PRIME render offloading.
The value can be:
- a number, selecting the n-th non-default GPU;
- a PCI bus id in the form `pci-XXX_YY_ZZ_U`;
- a PCI id in the form `vendor_id:device_id`
For more information, consult the Mesa documentation on the `DRI_PRIME`
environment variable.
'';
};
prime.nvidiaProvider = lib.mkOption {
type = with lib.types; nullOr str;
default = null;
example = "NVIDIA-G0";
description = ''
If this option is set, it overrides the offload provider for Nvidia
PRIME offloading. Consult the proprietary Nvidia driver documentation
on the `__NV_PRIME_RENDER_OFFLOAD_PROVIDER` environment variable.
'';
};
prime.installScript = lib.mkOption {
type = with lib.types; nullOr (enum [ "mesa" "nvidia" ]);
default = null;
example = "mesa";
description = ''
If this option is set, the wrapper script `prime-offload` is installed
into the environment. It allows starting programs on the secondary GPU
selected by the `nixGL.prime.card` option. This makes sense when the
program is not already using one of nixGL PRIME wrappers, or for
programs not installed from Nixpkgs.
This option can be set to either "mesa" or "nvidia", making the script
use one or the other graphics library.
'';
};
installScripts = lib.mkOption {
type = with lib.types;
nullOr (listOf (enum (builtins.attrNames config.lib.nixGL.wrappers)));
default = null;
example = [ "mesa" "mesaPrime" ];
description = ''
For each wrapper `wrp` named in the provided list, a wrapper script
named `nixGLWrp` is installed into the environment. These scripts are
useful for running programs not installed via Home Manager.
The following wrappers are available:
${wrapperListMarkdown}
'';
};
vulkan.enable = lib.mkOption {
type = lib.types.bool;
default = false;
example = true;
description = ''
Whether to enable Vulkan in nixGL wrappers.
This is disabled by default bacause Vulkan brings in several libraries
that can cause symbol version conflicts in wrapped programs. Your
mileage may vary.
'';
};
};
config = let
findWrapperPackage = packageAttr:
# NixGL has wrapper packages in different places depending on how you
# access it. We want HM configuration to be the same, regardless of how
# NixGL is imported.
#
# First, let's see if we have a flake.
if builtins.hasAttr pkgs.system cfg.packages then
cfg.packages.${pkgs.system}.${packageAttr}
else
# Next, let's see if we have a channel.
if builtins.hasAttr packageAttr cfg.packages then
cfg.packages.${packageAttr}
else
# Lastly, with channels, some wrappers are grouped under "auto".
if builtins.hasAttr "auto" cfg.packages then
cfg.packages.auto.${packageAttr}
else
throw "Incompatible NixGL package layout";
getWrapperExe = vendor:
let
glPackage = findWrapperPackage "nixGL${vendor}";
glExe = lib.getExe glPackage;
vulkanPackage = findWrapperPackage "nixVulkan${vendor}";
vulkanExe = if cfg.vulkan.enable then lib.getExe vulkanPackage else "";
in "${glExe} ${vulkanExe}";
mesaOffloadEnv = { "DRI_PRIME" = "${cfg.prime.card}"; };
nvOffloadEnv = {
"DRI_PRIME" = "${cfg.prime.card}";
"__NV_PRIME_RENDER_OFFLOAD" = "1";
"__GLX_VENDOR_LIBRARY_NAME" = "nvidia";
"__VK_LAYER_NV_optimus" = "NVIDIA_only";
} // (let provider = cfg.prime.nvidiaProvider;
in if !isNull provider then {
"__NV_PRIME_RENDER_OFFLOAD_PROVIDER" = "${provider}";
} else
{ });
makePackageWrapper = vendor: environment: pkg:
if builtins.isNull cfg.packages then
pkg
else
# Wrap the package's binaries with nixGL, while preserving the rest of
# the outputs and derivation attributes.
(pkg.overrideAttrs (old: {
name = "nixGL-${pkg.name}";
# Make sure this is false for the wrapper derivation, so nix doesn't expect
# a new debug output to be produced. We won't be producing any debug info
# for the original package.
separateDebugInfo = false;
nativeBuildInputs = old.nativeBuildInputs or [ ]
++ [ pkgs.makeWrapper ];
buildCommand = let
# We need an intermediate wrapper package because makeWrapper
# requires a single executable as the wrapper.
combinedWrapperPkg =
pkgs.writeShellScriptBin "nixGLCombinedWrapper-${vendor}" ''
exec ${getWrapperExe vendor} "$@"
'';
in ''
set -eo pipefail
${ # Heavily inspired by https://stackoverflow.com/a/68523368/6259505
lib.concatStringsSep "\n" (map (outputName: ''
echo "Copying output ${outputName}"
set -x
cp -rs --no-preserve=mode "${
pkg.${outputName}
}" "''$${outputName}"
set +x
'') (old.outputs or [ "out" ]))}
rm -rf $out/bin/*
shopt -s nullglob # Prevent loop from running if no files
for file in ${pkg.out}/bin/*; do
local prog="$(basename "$file")"
makeWrapper \
"${lib.getExe combinedWrapperPkg}" \
"$out/bin/$prog" \
--argv0 "$prog" \
--add-flags "$file" \
${
lib.concatStringsSep " " (lib.attrsets.mapAttrsToList
(var: val: "--set '${var}' '${val}'") environment)
}
done
# If .desktop files refer to the old package, replace the references
for dsk in "$out/share/applications"/*.desktop ; do
if ! grep -q "${pkg.out}" "$dsk"; then
continue
fi
src="$(readlink "$dsk")"
rm "$dsk"
sed "s|${pkg.out}|$out|g" "$src" > "$dsk"
done
shopt -u nullglob # Revert nullglob back to its normal default state
'';
}));
wrappers = {
mesa = makePackageWrapper "Intel" { };
mesaPrime = makePackageWrapper "Intel" mesaOffloadEnv;
nvidia = makePackageWrapper "Nvidia" { };
nvidiaPrime = makePackageWrapper "Nvidia" nvOffloadEnv;
};
in {
lib.nixGL.wrap = wrappers.${cfg.defaultWrapper};
lib.nixGL.wrapOffload = wrappers.${cfg.offloadWrapper};
lib.nixGL.wrappers = wrappers;
home.packages = let
wantsPrimeWrapper = (!isNull cfg.prime.installScript);
wantsWrapper = wrapper:
(!isNull cfg.packages) && (!isNull cfg.installScripts)
&& (builtins.elem wrapper cfg.installScripts);
envVarsAsScript = environment:
lib.concatStringsSep "\n"
(lib.attrsets.mapAttrsToList (var: val: "export ${var}=${val}")
environment);
in [
(lib.mkIf wantsPrimeWrapper (pkgs.writeShellScriptBin "prime-offload" ''
${if cfg.prime.installScript == "mesa" then
(envVarsAsScript mesaOffloadEnv)
else
(envVarsAsScript nvOffloadEnv)}
exec "$@"
''))
(lib.mkIf (wantsWrapper "mesa") (pkgs.writeShellScriptBin "nixGLMesa" ''
exec ${getWrapperExe "Intel"} "$@"
''))
(lib.mkIf (wantsWrapper "mesaPrime")
(pkgs.writeShellScriptBin "nixGLMesaPrime" ''
${envVarsAsScript mesaOffloadEnv}
exec ${getWrapperExe "Intel"} "$@"
''))
(lib.mkIf (wantsWrapper "nvidia")
(pkgs.writeShellScriptBin "nixGLNvidia" ''
exec ${getWrapperExe "Nvidia"} "$@"
''))
(lib.mkIf (wantsWrapper "nvidia")
(pkgs.writeShellScriptBin "nixGLNvidiaPrime" ''
${envVarsAsScript nvOffloadEnv}
exec ${getWrapperExe "Nvidia"} "$@"
''))
];
};
}

View file

@ -29,4 +29,19 @@ with lib;
'';
};
};
config = {
# To make it easier for the end user to override the values in the
# configuration depending on the installation method, we set default values
# for the arguments that are defined in the NixOS/nix-darwin modules.
#
# Without these defaults, these attributes would simply not exist, and the
# module system can not inform modules about their non-existence; see
# https://github.com/NixOS/nixpkgs/issues/311709#issuecomment-2110861842
_module.args = {
osConfig = mkDefault null;
nixosConfig = mkDefault null;
darwinConfig = mkDefault null;
};
};
}

View file

@ -51,7 +51,7 @@ let
terminal = mkOption {
description = "Whether the program runs in a terminal window.";
type = types.bool;
type = types.nullOr types.bool;
default = false;
};

View file

@ -5,10 +5,12 @@ with lib;
let
cfg = config.xdg.mime;
inherit (lib) getExe getExe';
in {
options = {
xdg.mime.enable = mkOption {
xdg.mime = {
enable = mkOption {
type = types.bool;
default = pkgs.stdenv.hostPlatform.isLinux;
defaultText =
@ -23,15 +25,30 @@ in {
respectively.
'';
};
sharedMimeInfoPackage = mkOption {
type = types.package;
default = pkgs.shared-mime-info;
defaultText = literalExpression "pkgs.shared-mime-info";
description = "The package to use when running update-mime-database.";
};
config = mkIf config.xdg.mime.enable {
desktopFileUtilsPackage = mkOption {
type = types.package;
default = pkgs.desktop-file-utils;
defaultText = literalExpression "pkgs.desktop-file-utils";
description =
"The package to use when running update-desktop-database.";
};
};
};
config = mkIf cfg.enable {
assertions =
[ (hm.assertions.assertPlatform "xdg.mime" pkgs platforms.linux) ];
home.packages = [
# Explicitly install package to provide basic mime types.
pkgs.shared-mime-info
cfg.sharedMimeInfoPackage
# Make sure the target directories will be real directories.
(pkgs.runCommandLocal "dummy-xdg-mime-dirs1" { } ''
@ -46,12 +63,12 @@ in {
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 \
${getExe cfg.sharedMimeInfoPackage} \
-V $out/share/mime > /dev/null
fi
if [[ -w $out/share/applications ]]; then
${pkgs.buildPackages.desktop-file-utils}/bin/update-desktop-database \
${getExe' cfg.desktopFileUtilsPackage "update-desktop-database"} \
$out/share/applications
fi
'';

View file

@ -30,6 +30,8 @@ in {
apply = toString;
description = ''
Absolute path to directory holding application caches.
Sets `XDG_CACHE_HOME` for the user if `xdg.enable` is set `true`.
'';
};
@ -48,6 +50,8 @@ in {
apply = toString;
description = ''
Absolute path to directory holding application configurations.
Sets `XDG_CONFIG_HOME` for the user if `xdg.enable` is set `true`.
'';
};
@ -67,6 +71,18 @@ in {
apply = toString;
description = ''
Absolute path to directory holding application data.
Sets `XDG_DATA_HOME` for the user if `xdg.enable` is set `true`.
'';
};
stateFile = mkOption {
type = fileType "xdg.stateFile" "<varname>xdg.stateHome</varname>"
cfg.stateHome;
default = { };
description = ''
Attribute set of files to link into the user's XDG
state home.
'';
};
@ -76,6 +92,8 @@ in {
apply = toString;
description = ''
Absolute path to directory holding application states.
Sets `XDG_STATE_HOME` for the user if `xdg.enable` is set `true`.
'';
};
};
@ -122,6 +140,8 @@ in {
cfg.configFile)
(mapAttrs' (name: file: nameValuePair "${cfg.dataHome}/${name}" file)
cfg.dataFile)
(mapAttrs' (name: file: nameValuePair "${cfg.stateHome}/${name}" file)
cfg.stateFile)
{ "${cfg.cacheHome}/.keep".text = ""; }
];
}

View file

@ -31,6 +31,7 @@ let
./misc/gtk.nix
./misc/lib.nix
./misc/news.nix
./misc/nixgl.nix
./misc/numlock.nix
./misc/pam.nix
./misc/qt.nix
@ -77,6 +78,7 @@ let
./programs/carapace.nix
./programs/cava.nix
./programs/chromium.nix
./programs/cmus.nix
./programs/command-not-found/command-not-found.nix
./programs/comodoro.nix
./programs/darcs.nix
@ -92,6 +94,7 @@ let
./programs/feh.nix
./programs/firefox.nix
./programs/fish.nix
./programs/floorp.nix
./programs/foot.nix
./programs/freetube.nix
./programs/fuzzel.nix
@ -167,8 +170,10 @@ let
./programs/ncspot.nix
./programs/ne.nix
./programs/neomutt.nix
./programs/neovide.nix
./programs/neovim.nix
./programs/newsboat.nix
./programs/nh.nix
./programs/nheko.nix
./programs/nix-index.nix
./programs/nnn.nix
@ -240,8 +245,9 @@ let
./programs/translate-shell.nix
./programs/urxvt.nix
./programs/vdirsyncer.nix
./programs/vim.nix
./programs/vifm.nix
./programs/vim-vint.nix
./programs/vim.nix
./programs/vscode.nix
./programs/vscode/haskell.nix
./programs/pywal.nix
@ -259,6 +265,7 @@ let
./programs/yt-dlp.nix
./programs/z-lua.nix
./programs/zathura.nix
./programs/zed-editor.nix
./programs/zellij.nix
./programs/zk.nix
./programs/zoxide.nix
@ -345,6 +352,7 @@ let
./services/plan9port.nix
./services/playerctld.nix
./services/plex-mpv-shim.nix
./services/podman-linux
./services/polybar.nix
./services/poweralertd.nix
./services/psd.nix
@ -360,6 +368,7 @@ let
./services/screen-locker.nix
./services/sctd.nix
./services/signaturepdf.nix
./services/snixembed.nix
./services/spotifyd.nix
./services/ssh-agent.nix
./services/stalonetray.nix
@ -374,6 +383,7 @@ let
./services/tahoe-lafs.nix
./services/taskwarrior-sync.nix
./services/trayer.nix
./services/trayscale.nix
./services/twmn.nix
./services/udiskie.nix
./services/unclutter.nix

View file

@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: Home Manager Modules\n"
"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n"
"POT-Creation-Date: 2024-04-17 23:19+0200\n"
"PO-Revision-Date: 2023-12-29 02:09+0000\n"
"Last-Translator: Peter Pfeufer <info@ppfeufer.de>\n"
"PO-Revision-Date: 2024-10-15 21:37+0000\n"
"Last-Translator: Viktor Illmer <accounts@viktor.im>\n"
"Language-Team: German <https://hosted.weblate.org/projects/home-manager/"
"modules/de/>\n"
"Language: de\n"
@ -17,7 +17,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.4-dev\n"
"X-Generator: Weblate 5.8-rc\n"
#: modules/files.nix:191
msgid "Creating home file links in %s"
@ -120,7 +120,7 @@ msgstr "Fehler: HOME ist auf \"%s\" gesetzt, aber wir erwarten \"%s\""
#: modules/lib-bash/activation-init.sh:153
msgid "Starting Home Manager activation"
msgstr "Starte Home Manager Aktivierung"
msgstr "Starte Home-Manager-Aktivierung"
#: modules/lib-bash/activation-init.sh:157
msgid "Sanity checking Nix"

116
modules/po/hi.po Normal file
View file

@ -0,0 +1,116 @@
# 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 <EMAIL@ADDRESS>, 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: 2024-04-17 23:19+0200\n"
"PO-Revision-Date: 2024-10-09 14:31+0000\n"
"Last-Translator: Utkarsh Sharma <utkasharma19@gmail.com>\n"
"Language-Team: Hindi <https://hosted.weblate.org/projects/home-manager/"
"modules/hi/>\n"
"Language: hi\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 5.8-dev\n"
#: modules/files.nix:191
msgid "Creating home file links in %s"
msgstr ""
#: modules/files.nix:204
msgid "Cleaning up orphan links from %s"
msgstr "%s से ऑर्फे़न लिंक्स मिटाई जा रही है"
#: modules/files.nix:220
msgid "Creating profile generation %s"
msgstr ""
#: modules/files.nix:237
msgid "No change so reusing latest profile generation %s"
msgstr ""
#: modules/home-environment.nix:634
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:667
msgid "Activating %s"
msgstr ""
#: modules/lib-bash/activation-init.sh:22
msgid "Migrating profile from %s to %s"
msgstr ""
#: modules/lib-bash/activation-init.sh:54
msgid "Could not find suitable profile directory, tried %s and %s"
msgstr ""
#: modules/lib-bash/activation-init.sh:83
msgid "Sanity checking oldGenNum and oldGenPath"
msgstr ""
#: modules/lib-bash/activation-init.sh:86
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:127
msgid "Error: USER is set to \"%s\" but we expect \"%s\""
msgstr ""
#: modules/lib-bash/activation-init.sh:136
msgid "Error: HOME is set to \"%s\" but we expect \"%s\""
msgstr ""
#: modules/lib-bash/activation-init.sh:153
msgid "Starting Home Manager activation"
msgstr ""
#: modules/lib-bash/activation-init.sh:157
msgid "Sanity checking Nix"
msgstr ""
#: modules/lib-bash/activation-init.sh:170
msgid "This is a dry run"
msgstr ""
#: modules/lib-bash/activation-init.sh:174
msgid "This is a live run"
msgstr ""
#: modules/lib-bash/activation-init.sh:180
msgid "Using Nix version: %s"
msgstr ""
#: modules/lib-bash/activation-init.sh:183
msgid "Activation variables:"
msgstr ""

View file

@ -8,29 +8,32 @@ msgstr ""
"Project-Id-Version: Home Manager Modules\n"
"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n"
"POT-Creation-Date: 2024-04-17 23:19+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Automatically generated\n"
"Language-Team: none\n"
"PO-Revision-Date: 2024-09-02 17:09+0000\n"
"Last-Translator: Ferenci Ákos <synthetace@gmail.com>\n"
"Language-Team: Hungarian <https://hosted.weblate.org/projects/home-manager/"
"modules/hu/>\n"
"Language: hu\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 5.8-dev\n"
#: modules/files.nix:191
msgid "Creating home file links in %s"
msgstr ""
msgstr "Hivatkozások létrehozása itt: %s"
#: modules/files.nix:204
msgid "Cleaning up orphan links from %s"
msgstr ""
msgstr "Árva hivatkozások kitakarítása innen: %s"
#: modules/files.nix:220
msgid "Creating profile generation %s"
msgstr ""
msgstr "%s. profil generáció létrehozása"
#: modules/files.nix:237
msgid "No change so reusing latest profile generation %s"
msgstr ""
msgstr "Nincs változás, legutóbbi %s. generáció lesz használva"
#: modules/home-environment.nix:634
msgid ""
@ -59,6 +62,7 @@ msgstr ""
#: modules/lib-bash/activation-init.sh:54
msgid "Could not find suitable profile directory, tried %s and %s"
msgstr ""
"Nem található megfelelő profil mappa, %s és %s útvonalak lettek kipróbálva."
#: modules/lib-bash/activation-init.sh:83
msgid "Sanity checking oldGenNum and oldGenPath"
@ -94,7 +98,7 @@ msgstr ""
#: modules/lib-bash/activation-init.sh:157
msgid "Sanity checking Nix"
msgstr ""
msgstr "Nix épségének ellenőrzése"
#: modules/lib-bash/activation-init.sh:170
msgid "This is a dry run"

View file

@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: Home Manager Modules\n"
"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n"
"POT-Creation-Date: 2024-04-17 23:19+0200\n"
"PO-Revision-Date: 2023-08-11 19:51+0000\n"
"Last-Translator: HeartBlin913861820c094e37 <heartblin@proton.me>\n"
"PO-Revision-Date: 2024-10-13 22:15+0000\n"
"Last-Translator: AtomicDude <vasilescutoma4@gmail.com>\n"
"Language-Team: Romanian <https://hosted.weblate.org/projects/home-manager/"
"modules/ro/>\n"
"Language: ro\n"
@ -18,7 +18,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < "
"20)) ? 1 : 2;\n"
"X-Generator: Weblate 5.0-dev\n"
"X-Generator: Weblate 5.8-dev\n"
#: modules/files.nix:191
msgid "Creating home file links in %s"
@ -26,7 +26,7 @@ msgstr "Se creează legături ale fișierelor personale în %s"
#: modules/files.nix:204
msgid "Cleaning up orphan links from %s"
msgstr "Se curăță legăturiile orfane din %s"
msgstr "Se curăță legăturile orfane din %s"
#: modules/files.nix:220
msgid "Creating profile generation %s"

View file

@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: Home Manager Modules\n"
"Report-Msgid-Bugs-To: https://github.com/nix-community/home-manager/issues\n"
"POT-Creation-Date: 2024-04-17 23:19+0200\n"
"PO-Revision-Date: 2024-06-02 08:12+0000\n"
"PO-Revision-Date: 2024-08-01 04:09+0000\n"
"Last-Translator: goatastronaut0212 <goatastronaut0212@proton.me>\n"
"Language-Team: Vietnamese <https://hosted.weblate.org/projects/home-manager/"
"modules/vi/>\n"
@ -17,7 +17,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Weblate 5.6-dev\n"
"X-Generator: Weblate 5.7-dev\n"
#: modules/files.nix:191
msgid "Creating home file links in %s"
@ -53,11 +53,11 @@ msgstr ""
#: modules/home-environment.nix:667
msgid "Activating %s"
msgstr ""
msgstr "Đang khởi động %s"
#: modules/lib-bash/activation-init.sh:22
msgid "Migrating profile from %s to %s"
msgstr ""
msgstr "Chuyển đổi hồ sơ từ %s tới %s"
#: modules/lib-bash/activation-init.sh:54
msgid "Could not find suitable profile directory, tried %s and %s"
@ -85,11 +85,11 @@ msgstr ""
#: modules/lib-bash/activation-init.sh:127
msgid "Error: USER is set to \"%s\" but we expect \"%s\""
msgstr ""
msgstr "Lỗi: USER được đặt thành \"%s\" nhưng chúng tôi kỳ vọng \"%s\""
#: modules/lib-bash/activation-init.sh:136
msgid "Error: HOME is set to \"%s\" but we expect \"%s\""
msgstr ""
msgstr "Lỗi: HOME được đặt thành \"%s\" nhưng chúng tôi kỳ vọng \"%s\""
#: modules/lib-bash/activation-init.sh:153
msgid "Starting Home Manager activation"
@ -97,7 +97,7 @@ msgstr ""
#: modules/lib-bash/activation-init.sh:157
msgid "Sanity checking Nix"
msgstr "Kiểm tra độ hợp lệ của Nix"
msgstr "Kiểm tra hợp lệ của Nix"
#: modules/lib-bash/activation-init.sh:170
msgid "This is a dry run"

View file

@ -56,7 +56,7 @@ in {
buildCommand = lib.concatStringsSep "\n" [
prevAttrs.buildCommand
# TODO: why is this needed? Is there a better way to retain escape sequences?
"substituteInPlace $out --replace '\\\\' '\\'"
"substituteInPlace $out --replace-quiet '\\\\' '\\'"
];
});
};

View file

@ -110,18 +110,18 @@ in {
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 ${flagsStr})"
eval "$(${lib.getExe cfg.package} init bash ${flagsStr})"
fi
'';
programs.zsh.initExtra = mkIf cfg.enableZshIntegration ''
if [[ $options[zle] = on ]]; then
eval "$(${cfg.package}/bin/atuin init zsh ${flagsStr})"
eval "$(${lib.getExe cfg.package} init zsh ${flagsStr})"
fi
'';
programs.fish.interactiveShellInit = mkIf cfg.enableFishIntegration ''
${cfg.package}/bin/atuin init fish ${flagsStr} | source
${lib.getExe cfg.package} init fish ${flagsStr} | source
'';
programs.nushell = mkIf cfg.enableNushellIntegration {
@ -130,7 +130,9 @@ in {
if not ($atuin_cache | path exists) {
mkdir $atuin_cache
}
${cfg.package}/bin/atuin init nu ${flagsStr} | save --force ${config.xdg.cacheHome}/atuin/init.nu
${
lib.getExe cfg.package
} init nu ${flagsStr} | save --force ${config.xdg.cacheHome}/atuin/init.nu
'';
extraConfig = ''
source ${config.xdg.cacheHome}/atuin/init.nu

View file

@ -177,6 +177,18 @@ let
default = null;
example = "nearest";
};
extraConfig = mkOption {
type = types.lines;
description = "Extra lines to append to this profile's config.";
default = "";
example = literalExpression ''
'''
x-prop-non_desktop 0
some-key some-value
'''
'';
};
};
};
@ -267,7 +279,8 @@ let
+ 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}"))
+ " ${toString config.scale.x}x${toString config.scale.y}")
++ optional (config.extraConfig != "") config.extraConfig)
else ''
output ${name}
off

View file

@ -29,6 +29,8 @@ in {
programs.bash = {
enable = mkEnableOption "GNU Bourne-Again SHell";
package = mkPackageOption pkgs "bash" { default = "bashInteractive"; };
enableCompletion = mkOption {
type = types.bool;
default = true;
@ -190,7 +192,7 @@ in {
HISTIGNORE = escapeShellArg (concatStringsSep ":" cfg.historyIgnore);
}));
in mkIf cfg.enable {
home.packages = [ pkgs.bashInteractive ];
home.packages = [ cfg.package ];
home.file.".bash_profile".source = writeBashScript "bash_profile" ''
# include .profile if it exists

View file

@ -7,7 +7,7 @@ let
cfg = config.programs.bemenu;
in {
meta.maintainers = [ hm.maintainers.omernaveedxyz ];
meta.maintainers = [ ];
options.programs.bemenu = {
enable = mkEnableOption "bemenu";

View file

@ -272,10 +272,7 @@ in {
};
config = mkIf cfg.enable {
assertions = [
(lib.hm.assertions.assertPlatform "programs.borgmatic" pkgs
lib.platforms.linux)
] ++ (mapAttrsToList (backup: opts: {
assertions = (mapAttrsToList (backup: opts: {
assertion = opts.location.sourceDirectories == null
|| opts.location.patterns == null;
message = ''

View file

@ -56,5 +56,5 @@ in {
};
};
meta.maintainers = [ maintainers.polykernel ];
meta.maintainers = [ ];
}

View file

@ -15,7 +15,7 @@ let
modal = mkEnableOption "modal (vim) mode";
verbs = mkOption {
type = with types; listOf (attrsOf (either bool str));
type = with types; listOf (attrsOf (oneOf [ bool str (listOf str) ]));
default = [ ];
example = literalExpression ''
[
@ -46,6 +46,9 @@ let
`key` (optional)
: a keyboard key triggering execution
`keys` (optional)
: multiple keyboard keys each triggering execution
`shortcut` (optional)
: an alternate way to call the verb (without
the arguments part)
@ -54,7 +57,7 @@ let
: whether to quit broot on execution
(default: `true`)
`from_shell` (optional)</term>
`from_shell` (optional)
: whether the verb must be executed from the
parent shell (default: `false`)
'';

44
modules/programs/cmus.nix Normal file
View file

@ -0,0 +1,44 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.programs.cmus;
in {
meta.maintainers = [ hm.maintainers.joygnu ];
options.programs.cmus = {
enable = mkEnableOption "Enable cmus, the music player.";
theme = mkOption {
type = types.lines;
default = "";
example = "gruvbox";
description = ''
Select color theme. A list of available color themes can be found
here: <https://github.com/cmus/cmus/tree/master/data>.
'';
};
extraConfig = mkOption {
type = types.lines;
default = "";
example = ''
set audio_backend = "mpd"
set status_display = "default"
'';
description = "Extra configuration to add to cmus {file}`rc`.";
};
};
config = mkIf cfg.enable {
home.packages = [ pkgs.cmus ];
home.file.".config/cmus/rc".text = ''
${optionalString (cfg.theme != "") "colorscheme ${cfg.theme}"}
${cfg.extraConfig}
'';
};
}

View file

@ -19,7 +19,7 @@ in {
"Flake support is now always enabled.")
];
meta.maintainers = [ lib.maintainers.rycee ];
meta.maintainers = [ lib.maintainers.rycee lib.maintainers.shikanime ];
options.programs.direnv = {
enable = mkEnableOption "direnv, the environment switcher";
@ -95,6 +95,14 @@ in {
package = mkPackageOption pkgs "nix-direnv" { };
};
mise = {
enable = mkEnableOption ''
[mise](https://mise.jdx.dev/direnv.html),
integration of use_mise for direnv'';
package = mkPackageOption pkgs "mise" { };
};
silent = mkEnableOption "silent mode, that is, disabling direnv logging";
};
@ -112,6 +120,12 @@ in {
xdg.configFile."direnv/direnvrc" =
lib.mkIf (cfg.stdlib != "") { text = cfg.stdlib; };
xdg.configFile."direnv/lib/hm-mise.sh" = mkIf cfg.mise.enable {
text = ''
eval "$(${getExe cfg.mise.package} direnv activate)"
'';
};
programs.bash.initExtra = mkIf cfg.enableBashIntegration (
# Using mkAfter to make it more likely to appear after other
# manipulations of the prompt.
@ -130,36 +144,29 @@ in {
${getExe cfg.package} hook fish | source
'');
programs.nushell.extraConfig = mkIf cfg.enableNushellIntegration (
# Using mkAfter to make it more likely to appear after other
# manipulations of the prompt.
mkAfter ''
programs.nushell.extraConfig = mkIf cfg.enableNushellIntegration (mkAfter ''
$env.config = ($env.config? | default {})
$env.config.hooks = ($env.config.hooks? | default {})
$env.config.hooks.pre_prompt = (
$env.config.hooks.pre_prompt?
| default []
| append {||
let direnv = (${getExe cfg.package} export json
| from json
| default {})
if ($direnv | is-empty) {
return
}
$direnv
${getExe cfg.package} export json
| from json --strict
| default {}
| items {|key, value|
{
key: $key
value: (do (
let value = do (
$env.ENV_CONVERSIONS?
| default {}
| get -i $key
| get -i from_string
| default {|x| $x}
) $value)
) $value
return [ $key $value ]
}
}
| transpose -ird
| into record
| load-env
}
)

View file

@ -5,6 +5,7 @@ with lib;
let
cfg = config.programs.eww;
ewwCmd = "${cfg.package}/bin/eww";
in {
meta.maintainers = [ hm.maintainers.mainrs ];
@ -30,10 +31,40 @@ in {
{file}`$XDG_CONFIG_HOME/eww`.
'';
};
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 ];
xdg.configFile."eww".source = cfg.configDir;
programs.bash.initExtra = mkIf cfg.enableBashIntegration ''
if [[ $TERM != "dumb" ]]; then
eval "$(${ewwCmd} shell-completions --shell bash)"
fi
'';
programs.zsh.initExtra = mkIf cfg.enableZshIntegration ''
if [[ $TERM != "dumb" ]]; then
eval "$(${ewwCmd} shell-completions --shell zsh)"
fi
'';
programs.fish.interactiveShellInit = mkIf cfg.enableFishIntegration ''
if test "$TERM" != "dumb"
eval "$(${ewwCmd} shell-completions --shell fish)"
end
'';
};
}

View file

@ -49,10 +49,21 @@ with lib;
};
icons = mkOption {
type = types.bool;
default = false;
type = types.enum [ null true false "auto" "always" "never" ];
default = null;
description = ''
Display icons next to file names ({option}`--icons` argument).
Note, the support for Boolean values is deprecated.
Setting this option to `true` corresponds to `--icons=auto`.
'';
};
colors = mkOption {
type = types.enum [ null "auto" "always" "never" ];
default = null;
description = ''
Use terminal colors in output ({option}`--color` argument).
'';
};
@ -70,7 +81,15 @@ with lib;
config = let
cfg = config.programs.eza;
args = escapeShellArgs (optional cfg.icons "--icons"
iconsOption = let
v = if isBool cfg.icons then
(if cfg.icons then "auto" else null)
else
cfg.icons;
in optionals (v != null) [ "--icons" v ];
args = escapeShellArgs (iconsOption
++ optionals (cfg.colors != null) [ "--color" cfg.colors ]
++ optional cfg.git "--git" ++ cfg.extraOptions);
optionsAlias = optionalAttrs (args != "") { eza = "eza ${args}"; };
@ -83,6 +102,12 @@ with lib;
lla = "eza -la";
};
in mkIf cfg.enable {
warnings = optional (isBool cfg.icons) ''
Setting programs.eza.icons to a Boolean is deprecated.
Please update your configuration so that
programs.eza.icons = ${if cfg.icons then ''"auto"'' else "null"}'';
home.packages = [ cfg.package ];
programs.bash.shellAliases = optionsAlias
@ -91,8 +116,17 @@ with lib;
programs.zsh.shellAliases = optionsAlias
// optionalAttrs cfg.enableZshIntegration aliases;
programs.fish.shellAliases = optionsAlias
programs.fish = mkMerge [
(mkIf (!config.programs.fish.preferAbbrs) {
shellAliases = optionsAlias
// optionalAttrs cfg.enableFishIntegration aliases;
})
(mkIf config.programs.fish.preferAbbrs {
shellAliases = optionsAlias;
shellAbbrs = optionalAttrs cfg.enableFishIntegration aliases;
})
];
programs.ion.shellAliases = optionsAlias
// optionalAttrs cfg.enableIonIntegration aliases;

View file

@ -26,7 +26,9 @@ in {
};
};
display = {
size = {
binaryPrefix = "si";
};
color = "blue";
separator = " ";
};

View file

@ -1,945 +1,50 @@
{ config, lib, pkgs, ... }:
{ lib, ... }:
with lib;
let
inherit (pkgs.stdenv.hostPlatform) isDarwin;
modulePath = [ "programs" "firefox" ];
cfg = config.programs.firefox;
moduleName = concatStringsSep "." modulePath;
jsonFormat = pkgs.formats.json { };
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;
nativeMessagingHostsPath = if isDarwin then
"${mozillaConfigPath}/NativeMessagingHosts"
else
"${mozillaConfigPath}/native-messaging-hosts";
nativeMessagingHostsJoined = pkgs.symlinkJoin {
name = "ff_native-messaging-hosts";
paths = [
# Link a .keep file to keep the directory around
(pkgs.writeTextDir "lib/mozilla/native-messaging-hosts/.keep" "")
# Link package configured native messaging hosts (entire Firefox actually)
cfg.finalPackage
]
# Link user configured native messaging hosts
++ cfg.nativeMessagingHosts;
};
# The extensions path shared by all profiles; will not be supported
# by future Firefox versions.
extensionPath = "extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}";
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;
userPrefValue = pref:
builtins.toJSON (if isBool pref || isInt pref || isString pref then
pref
else
builtins.toJSON pref);
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}", ${userPrefValue value});
'') prefs')}
${extraPrefs}
'';
mkContainersJson = containers:
let
containerToIdentity = _: container: {
userContextId = container.id;
name = container.name;
icon = container.icon;
color = container.color;
public = true;
};
in ''
${builtins.toJSON {
version = 4;
lastUserContextId =
elemAt (mapAttrsToList (_: container: container.id) containers) 0;
identities = mapAttrsToList containerToIdentity containers ++ [
{
userContextId = 4294967294; # 2^32 - 2
name = "userContextIdInternal.thumbnail";
icon = "";
color = "";
accessKey = "";
public = false;
}
{
userContextId = 4294967295; # 2^32 - 1
name = "userContextIdInternal.webextStorageLocal";
icon = "";
color = "";
accessKey = "";
public = false;
}
];
}}
'';
firefoxBookmarksFile = bookmarks:
let
indent = level:
lib.concatStringsSep "" (map (lib.const " ") (lib.range 1 level));
bookmarkToHTML = indentLevel: bookmark:
''
${indent indentLevel}<DT><A HREF="${
escapeXML bookmark.url
}" ADD_DATE="1" LAST_MODIFIED="1"${
lib.optionalString (bookmark.keyword != null)
" SHORTCUTURL=\"${escapeXML bookmark.keyword}\""
}${
lib.optionalString (bookmark.tags != [ ])
" TAGS=\"${escapeXML (concatStringsSep "," bookmark.tags)}\""
}>${escapeXML bookmark.name}</A>'';
directoryToHTML = indentLevel: directory: ''
${indent indentLevel}<DT>${
if directory.toolbar then
''
<H3 ADD_DATE="1" LAST_MODIFIED="1" PERSONAL_TOOLBAR_FOLDER="true">Bookmarks Toolbar''
else
''<H3 ADD_DATE="1" LAST_MODIFIED="1">${escapeXML directory.name}''
}</H3>
${indent indentLevel}<DL><p>
${allItemsToHTML (indentLevel + 1) directory.bookmarks}
${indent indentLevel}</DL><p>'';
itemToHTMLOrRecurse = indentLevel: item:
if item ? "url" then
bookmarkToHTML indentLevel item
else
directoryToHTML indentLevel item;
allItemsToHTML = indentLevel: bookmarks:
lib.concatStringsSep "\n"
(map (itemToHTMLOrRecurse indentLevel) bookmarks);
bookmarkEntries = allItemsToHTML 1 bookmarks;
in pkgs.writeText "firefox-bookmarks.html" ''
<!DOCTYPE NETSCAPE-Bookmark-file-1>
<!-- This is an automatically generated file.
It will be read and overwritten.
DO NOT EDIT! -->
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">
<TITLE>Bookmarks</TITLE>
<H1>Bookmarks Menu</H1>
<DL><p>
${bookmarkEntries}
</DL>
'';
mkNoDuplicateAssertion = entities: entityKind:
(let
# Return an attribute set with entity IDs as keys and a list of
# entity names with corresponding ID as value. An ID is present in
# the result only if more than one entity has it. The argument
# entities is a list of AttrSet of one id/name pair.
findDuplicateIds = entities:
filterAttrs (_entityId: entityNames: length entityNames != 1)
(zipAttrs entities);
duplicates = findDuplicateIds (mapAttrsToList
(entityName: entity: { "${toString entity.id}" = entityName; })
entities);
mkMsg = entityId: entityNames:
" - ID ${entityId} is used by " + concatStringsSep ", " entityNames;
in {
assertion = duplicates == { };
message = ''
Must not have a Firefox ${entityKind} with an existing ID but
'' + concatStringsSep "\n" (mapAttrsToList mkMsg duplicates);
});
wrapPackage = package:
let
# The configuration expected by the Firefox wrapper.
fcfg = { enableGnomeExtensions = cfg.enableGnomeExtensions; };
# A bit of hackery to force a config into the wrapper.
browserName =
package.browserName or (builtins.parseDrvName package.name).name;
# The configuration expected by the Firefox wrapper builder.
bcfg = setAttrByPath [ browserName ] fcfg;
in if package == null then
null
else if isDarwin then
package
else if versionAtLeast config.home.stateVersion "19.09" then
package.override (old: {
cfg = old.cfg or { } // fcfg;
extraPolicies = (old.extraPolicies or { }) // cfg.policies;
})
else
(pkgs.wrapFirefox.override { config = bcfg; }) package { };
mkFirefoxModule = import ./firefox/mkFirefoxModule.nix;
in {
meta.maintainers = [ maintainers.rycee maintainers.kira-bruneau ];
meta.maintainers = [ maintainers.rycee hm.maintainers.bricked ];
imports = [
(mkRemovedOptionModule [ "programs" "firefox" "extensions" ] ''
(mkFirefoxModule {
inherit modulePath;
name = "Firefox";
wrappedPackageName = "firefox";
unwrappedPackageName = "firefox-unwrapped";
visible = true;
platforms.linux = rec {
vendorPath = ".mozilla";
configPath = "${vendorPath}/firefox";
};
platforms.darwin = {
vendorPath = "Library/Application Support/Mozilla";
configPath = "Library/Application Support/Firefox";
};
})
(mkRemovedOptionModule (modulePath ++ [ "extensions" ]) ''
Extensions are now managed per-profile. That is, change from
programs.firefox.extensions = [ foo bar ];
${moduleName}.extensions = [ foo bar ];
to
programs.firefox.profiles.myprofile.extensions = [ foo bar ];'')
(mkRemovedOptionModule [ "programs" "firefox" "enableAdobeFlash" ]
${moduleName}.profiles.myprofile.extensions = [ foo bar ];'')
(mkRemovedOptionModule (modulePath ++ [ "enableAdobeFlash" ])
"Support for this option has been removed.")
(mkRemovedOptionModule [ "programs" "firefox" "enableGoogleTalk" ]
(mkRemovedOptionModule (modulePath ++ [ "enableGoogleTalk" ])
"Support for this option has been removed.")
(mkRemovedOptionModule [ "programs" "firefox" "enableIcedTea" ]
(mkRemovedOptionModule (modulePath ++ [ "enableIcedTea" ])
"Support for this option has been removed.")
];
options = {
programs.firefox = {
enable = mkEnableOption "Firefox";
package = mkOption {
type = with types; nullOr 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
nativeMessagingHosts = [
# Gnome shell native connector
pkgs.gnome-browser-connector
# Tridactyl native connector
pkgs.tridactyl-native
];
}
'';
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.
Set to `null` to disable installing Firefox.
'';
};
nativeMessagingHosts = mkOption {
type = types.listOf types.package;
default = [ ];
description = ''
Additional packages containing native messaging hosts that should be
made available to Firefox extensions.
'';
};
finalPackage = mkOption {
type = with types; nullOr package;
readOnly = true;
description = "Resulting Firefox package.";
};
policies = mkOption {
type = types.attrsOf jsonFormat.type;
default = { };
description =
"[See list of policies](https://mozilla.github.io/policy-templates/).";
example = {
DefaultDownloadDirectory = "\${home}/Downloads";
BlockAboutConfig = true;
};
};
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 = types.attrsOf (jsonFormat.type // {
description =
"Firefox preference (int, bool, string, and also attrs, list, float as a JSON string)";
});
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;
"browser.newtabpage.pinned" = [{
title = "NixOS";
url = "https://nixos.org";
}];
}
'';
description = ''
Attribute set of Firefox preferences.
Firefox only supports int, bool, and string types for
preferences, but home-manager will automatically
convert all other JSON-compatible values into strings.
'';
};
extraConfig = mkOption {
type = types.lines;
default = "";
description = ''
Extra preferences to add to {file}`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 = let
bookmarkSubmodule = types.submodule ({ config, name, ... }: {
options = {
name = mkOption {
type = types.str;
default = name;
description = "Bookmark name.";
};
tags = mkOption {
type = types.listOf types.str;
default = [ ];
description = "Bookmark tags.";
};
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.";
};
};
}) // {
description = "bookmark submodule";
};
bookmarkType = types.addCheck bookmarkSubmodule (x: x ? "url");
directoryType = types.submodule ({ config, name, ... }: {
options = {
name = mkOption {
type = types.str;
default = name;
description = "Directory name.";
};
bookmarks = mkOption {
type = types.listOf nodeType;
default = [ ];
description = "Bookmarks within directory.";
};
toolbar = mkOption {
type = types.bool;
default = false;
description = ''
Make this the toolbar directory. Note, this does _not_
mean that this directory will be added to the toolbar,
this directory _is_ the toolbar.
'';
};
};
}) // {
description = "directory submodule";
};
nodeType = types.either bookmarkType directoryType;
in with types;
coercedTo (attrsOf nodeType) attrValues (listOf nodeType);
default = [ ];
example = literalExpression ''
[
{
name = "wikipedia";
tags = [ "wiki" ];
keyword = "wiki";
url = "https://en.wikipedia.org/wiki/Special:Search?search=%s&go=Go";
}
{
name = "kernel.org";
url = "https://www.kernel.org";
}
{
name = "Nix sites";
toolbar = true;
bookmarks = [
{
name = "homepage";
url = "https://nixos.org/";
}
{
name = "wiki";
tags = [ "wiki" "nix" ];
url = "https://wiki.nixos.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.";
};
search = {
force = mkOption {
type = with types; bool;
default = false;
description = ''
Whether to force replace the existing search
configuration. This is recommended since Firefox will
replace the symlink for the search configuration on every
launch, but note that you'll lose any existing
configuration by enabling this.
'';
};
default = mkOption {
type = with types; nullOr str;
default = null;
example = "DuckDuckGo";
description = ''
The default search engine used in the address bar and search bar.
'';
};
privateDefault = mkOption {
type = with types; nullOr str;
default = null;
example = "DuckDuckGo";
description = ''
The default search engine used in the Private Browsing.
'';
};
order = mkOption {
type = with types; uniq (listOf str);
default = [ ];
example = [ "DuckDuckGo" "Google" ];
description = ''
The order the search engines are listed in. Any engines
that aren't included in this list will be listed after
these in an unspecified order.
'';
};
engines = mkOption {
type = with types; attrsOf (attrsOf jsonFormat.type);
default = { };
example = literalExpression ''
{
"Nix Packages" = {
urls = [{
template = "https://search.nixos.org/packages";
params = [
{ name = "type"; value = "packages"; }
{ name = "query"; value = "{searchTerms}"; }
];
}];
icon = "''${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg";
definedAliases = [ "@np" ];
};
"NixOS Wiki" = {
urls = [{ template = "https://wiki.nixos.org/index.php?search={searchTerms}"; }];
iconUpdateURL = "https://wiki.nixos.org/favicon.png";
updateInterval = 24 * 60 * 60 * 1000; # every day
definedAliases = [ "@nw" ];
};
"Bing".metaData.hidden = true;
"Google".metaData.alias = "@g"; # builtin engines only support specifying one additional alias
}
'';
description = ''
Attribute set of search engine configurations. Engines
that only have {var}`metaData` specified will
be treated as builtin to Firefox.
See [SearchEngine.jsm](https://searchfox.org/mozilla-central/rev/669329e284f8e8e2bb28090617192ca9b4ef3380/toolkit/components/search/SearchEngine.jsm#1138-1177)
in Firefox's source for available options. We maintain a
mapping to let you specify all options in the referenced
link without underscores, but it may fall out of date with
future options.
Note, {var}`icon` is also a special option
added by Home Manager to make it convenient to specify
absolute icon paths.
'';
};
};
containersForce = mkOption {
type = types.bool;
default = false;
description = ''
Whether to force replace the existing containers
configuration. This is recommended since Firefox will
replace the symlink on every launch, but note that you'll
lose any existing configuration by enabling this.
'';
};
containers = mkOption {
type = types.attrsOf (types.submodule ({ name, ... }: {
options = {
name = mkOption {
type = types.str;
default = name;
description = "Container name, e.g., shopping.";
};
id = mkOption {
type = types.ints.unsigned;
default = 0;
description = ''
Container ID. This should be set to a unique number per container in this profile.
'';
};
# List of colors at
# https://searchfox.org/mozilla-central/rev/5ad226c7379b0564c76dc3b54b44985356f94c5a/toolkit/components/extensions/parent/ext-contextualIdentities.js#32
color = mkOption {
type = types.enum [
"blue"
"turquoise"
"green"
"yellow"
"orange"
"red"
"pink"
"purple"
"toolbar"
];
default = "pink";
description = "Container color.";
};
icon = mkOption {
type = types.enum [
"briefcase"
"cart"
"circle"
"dollar"
"fence"
"fingerprint"
"gift"
"vacation"
"food"
"fruit"
"pet"
"tree"
"chill"
];
default = "fruit";
description = "Container icon.";
};
};
}));
default = { };
example = {
"shopping" = {
id = 1;
color = "blue";
icon = "cart";
};
"dangerous" = {
id = 2;
color = "red";
icon = "fruit";
};
};
description = ''
Attribute set of container configurations. See
[Multi-Account
Containers](https://support.mozilla.org/en-US/kb/containers)
for more information.
'';
};
extensions = mkOption {
type = types.listOf types.package;
default = [ ];
example = literalExpression ''
with pkgs.nur.repos.rycee.firefox-addons; [
privacy-badger
]
'';
description = ''
List of Firefox add-on packages to install for this profile.
Some pre-packaged add-ons are accessible from the
[Nix User Repository](https://github.com/nix-community/NUR).
Once you have NUR installed run
```console
$ 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.
To automatically enable extensions add
`"extensions.autoDisableScopes" = 0;`
to
[{option}`programs.firefox.profiles.<profile>.settings`](#opt-programs.firefox.profiles._name_.settings)
'';
};
};
}));
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.gnome.gnome-browser-connector.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
getContainers = profiles:
flatten
(mapAttrsToList (_: value: (attrValues value.containers)) profiles);
findInvalidContainerIds = profiles:
filter (container: container.id >= 4294967294)
(getContainers profiles);
in {
assertion = cfg.profiles == { }
|| length (findInvalidContainerIds cfg.profiles) == 0;
message = "Container id must be smaller than 4294967294 (2^32 - 2)";
})
(mkNoDuplicateAssertion cfg.profiles "profile")
] ++ (mapAttrsToList
(_: profile: mkNoDuplicateAssertion profile.containers "container")
cfg.profiles);
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.
'';
programs.firefox.finalPackage = wrapPackage cfg.package;
home.packages = lib.optional (cfg.finalPackage != null) cfg.finalPackage;
home.file = mkMerge ([{
"${firefoxConfigPath}/profiles.ini" =
mkIf (cfg.profiles != { }) { text = profilesIni; };
"${nativeMessagingHostsPath}" = {
source =
"${nativeMessagingHostsJoined}/lib/mozilla/native-messaging-hosts";
recursive = true;
};
}] ++ 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}/containers.json" =
mkIf (profile.containers != { }) {
force = profile.containersForce;
text = mkContainersJson profile.containers;
};
"${profilesPath}/${profile.path}/search.json.mozlz4" = mkIf
(profile.search.default != null || profile.search.privateDefault != null
|| profile.search.order != [ ] || profile.search.engines != { }) {
force = profile.search.force;
source = let
settings = {
version = 6;
engines = let
# Map of nice field names to internal field names.
# This is intended to be exhaustive and should be
# updated at every version bump.
internalFieldNames = (genAttrs [
"name"
"isAppProvided"
"loadPath"
"hasPreferredIcon"
"updateInterval"
"updateURL"
"iconUpdateURL"
"iconURL"
"iconMapObj"
"metaData"
"orderHint"
"definedAliases"
"urls"
] (name: "_${name}")) // {
searchForm = "__searchForm";
};
processCustomEngineInput = input:
(removeAttrs input [ "icon" ])
// optionalAttrs (input ? icon) {
# Convenience to specify absolute path to icon
iconURL = "file://${input.icon}";
} // (optionalAttrs (input ? iconUpdateURL) {
# Convenience to default iconURL to iconUpdateURL so
# the icon is immediately downloaded from the URL
iconURL = input.iconURL or input.iconUpdateURL;
} // {
# Required for custom engine configurations, loadPaths
# are unique identifiers that are generally formatted
# like: [source]/path/to/engine.xml
loadPath = ''
[home-manager]/programs.firefox.profiles.${profile.name}.search.engines."${
replaceStrings [ "\\" ] [ "\\\\" ] input.name
}"'';
});
processEngineInput = name: input:
let
requiredInput = {
inherit name;
isAppProvided = input.isAppProvided or removeAttrs input
[ "metaData" ] == { };
metaData = input.metaData or { };
};
in if requiredInput.isAppProvided then
requiredInput
else
processCustomEngineInput (input // requiredInput);
buildEngineConfig = name: input:
mapAttrs' (name: value: {
name = internalFieldNames.${name} or name;
inherit value;
}) (processEngineInput name input);
sortEngineConfigs = configs:
let
buildEngineConfigWithOrder = order: name:
let
config = configs.${name} or {
_name = name;
_isAppProvided = true;
_metaData = { };
};
in config // {
_metaData = config._metaData // { inherit order; };
};
engineConfigsWithoutOrder =
attrValues (removeAttrs configs profile.search.order);
sortedEngineConfigs =
(imap buildEngineConfigWithOrder profile.search.order)
++ engineConfigsWithoutOrder;
in sortedEngineConfigs;
engineInput = profile.search.engines // {
# Infer profile.search.default as an app provided
# engine if it's not in profile.search.engines
${profile.search.default} =
profile.search.engines.${profile.search.default} or { };
} // {
${profile.search.privateDefault} =
profile.search.engines.${profile.search.privateDefault} or { };
};
in sortEngineConfigs (mapAttrs buildEngineConfig engineInput);
metaData = optionalAttrs (profile.search.default != null) {
current = profile.search.default;
hash = "@hash@";
} // optionalAttrs (profile.search.privateDefault != null) {
private = profile.search.privateDefault;
privateHash = "@privateHash@";
} // {
useSavedOrder = profile.search.order != [ ];
};
};
# Home Manager doesn't circumvent user consent and isn't acting
# maliciously. We're modifying the search outside of Firefox, but
# a claim by Mozilla to remove this would be very anti-user, and
# is unlikely to be an issue for our use case.
disclaimer = appName:
"By modifying this file, I agree that I am doing so "
+ "only within ${appName} itself, using official, user-driven search "
+ "engine selection processes, and in a way which does not circumvent "
+ "user consent. I acknowledge that any attempt to change this file "
+ "from outside of ${appName} is a malicious act, and will be responded "
+ "to accordingly.";
salt = if profile.search.default != null then
profile.path + profile.search.default + disclaimer "Firefox"
else
null;
privateSalt = if profile.search.privateDefault != null then
profile.path + profile.search.privateDefault
+ disclaimer "Firefox"
else
null;
in pkgs.runCommand "search.json.mozlz4" {
nativeBuildInputs = with pkgs; [ mozlz4a openssl ];
json = builtins.toJSON settings;
inherit salt privateSalt;
} ''
if [[ -n $salt ]]; then
export hash=$(echo -n "$salt" | openssl dgst -sha256 -binary | base64)
export privateHash=$(echo -n "$privateSalt" | openssl dgst -sha256 -binary | base64)
mozlz4a <(substituteStream json search.json.in --subst-var hash --subst-var privateHash) "$out"
else
mozlz4a <(echo "$json") "$out"
fi
'';
};
"${profilesPath}/${profile.path}/extensions" =
mkIf (profile.extensions != [ ]) {
source = let
extensionsEnvPkg = pkgs.buildEnv {
name = "hm-firefox-extensions";
paths = profile.extensions;
};
in "${extensionsEnvPkg}/share/mozilla/${extensionPath}";
recursive = true;
force = true;
};
}));
};
}

View file

@ -0,0 +1,811 @@
{ modulePath, name, description ? null, wrappedPackageName ? null
, unwrappedPackageName ? null, platforms, visible ? false }:
{ config, lib, pkgs, ... }:
with lib;
let
inherit (pkgs.stdenv.hostPlatform) isDarwin;
moduleName = concatStringsSep "." modulePath;
cfg = getAttrFromPath modulePath config;
jsonFormat = pkgs.formats.json { };
supportedPlatforms = flatten (attrVals (attrNames platforms) lib.platforms);
isWrapped = versionAtLeast config.home.stateVersion "19.09"
&& wrappedPackageName != null;
defaultPackageName =
if isWrapped then wrappedPackageName else unwrappedPackageName;
packageName = if wrappedPackageName != null then
wrappedPackageName
else
unwrappedPackageName;
profilesPath =
if isDarwin then "${cfg.configPath}/Profiles" else cfg.configPath;
nativeMessagingHostsPath = if isDarwin then
"${cfg.vendorPath}/NativeMessagingHosts"
else
"${cfg.vendorPath}/native-messaging-hosts";
nativeMessagingHostsJoined = pkgs.symlinkJoin {
name = "ff_native-messaging-hosts";
paths = [
# Link a .keep file to keep the directory around
(pkgs.writeTextDir "lib/mozilla/native-messaging-hosts/.keep" "")
# Link package configured native messaging hosts (entire browser actually)
cfg.finalPackage
]
# Link user configured native messaging hosts
++ cfg.nativeMessagingHosts;
};
# The extensions path shared by all profiles; will not be supported
# by future browser versions.
extensionPath = "extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}";
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;
} // lib.optionalAttrs (cfg.profileVersion != null) {
Version = cfg.profileVersion;
};
};
profilesIni = generators.toINI { } profiles;
userPrefValue = pref:
builtins.toJSON (if isBool pref || isInt pref || isString pref then
pref
else
builtins.toJSON pref);
mkUserJs = prefs: extraPrefs: bookmarks:
let
prefs' = lib.optionalAttrs ([ ] != bookmarks) {
"browser.bookmarks.file" = toString (browserBookmarksFile bookmarks);
"browser.places.importBookmarksHTML" = true;
} // prefs;
in ''
// Generated by Home Manager.
${concatStrings (mapAttrsToList (name: value: ''
user_pref("${name}", ${userPrefValue value});
'') prefs')}
${extraPrefs}
'';
mkContainersJson = containers:
let
containerToIdentity = _: container: {
userContextId = container.id;
name = container.name;
icon = container.icon;
color = container.color;
public = true;
};
in ''
${builtins.toJSON {
version = 5;
lastUserContextId =
foldlAttrs (acc: _: value: if value.id > acc then value.id else acc) 0
containers;
identities = mapAttrsToList containerToIdentity containers ++ [
{
userContextId = 4294967294; # 2^32 - 2
name = "userContextIdInternal.thumbnail";
icon = "";
color = "";
accessKey = "";
public = false;
}
{
userContextId = 4294967295; # 2^32 - 1
name = "userContextIdInternal.webextStorageLocal";
icon = "";
color = "";
accessKey = "";
public = false;
}
];
}}
'';
browserBookmarksFile = bookmarks:
let
indent = level:
lib.concatStringsSep "" (map (lib.const " ") (lib.range 1 level));
bookmarkToHTML = indentLevel: bookmark:
''
${indent indentLevel}<DT><A HREF="${
escapeXML bookmark.url
}" ADD_DATE="1" LAST_MODIFIED="1"${
lib.optionalString (bookmark.keyword != null)
" SHORTCUTURL=\"${escapeXML bookmark.keyword}\""
}${
lib.optionalString (bookmark.tags != [ ])
" TAGS=\"${escapeXML (concatStringsSep "," bookmark.tags)}\""
}>${escapeXML bookmark.name}</A>'';
directoryToHTML = indentLevel: directory: ''
${indent indentLevel}<DT>${
if directory.toolbar then
''
<H3 ADD_DATE="1" LAST_MODIFIED="1" PERSONAL_TOOLBAR_FOLDER="true">Bookmarks Toolbar''
else
''<H3 ADD_DATE="1" LAST_MODIFIED="1">${escapeXML directory.name}''
}</H3>
${indent indentLevel}<DL><p>
${allItemsToHTML (indentLevel + 1) directory.bookmarks}
${indent indentLevel}</DL><p>'';
itemToHTMLOrRecurse = indentLevel: item:
if item ? "url" then
bookmarkToHTML indentLevel item
else
directoryToHTML indentLevel item;
allItemsToHTML = indentLevel: bookmarks:
lib.concatStringsSep "\n"
(map (itemToHTMLOrRecurse indentLevel) bookmarks);
bookmarkEntries = allItemsToHTML 1 bookmarks;
in pkgs.writeText "${packageName}-bookmarks.html" ''
<!DOCTYPE NETSCAPE-Bookmark-file-1>
<!-- This is an automatically generated file.
It will be read and overwritten.
DO NOT EDIT! -->
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">
<TITLE>Bookmarks</TITLE>
<H1>Bookmarks Menu</H1>
<DL><p>
${bookmarkEntries}
</DL>
'';
mkNoDuplicateAssertion = entities: entityKind:
(let
# Return an attribute set with entity IDs as keys and a list of
# entity names with corresponding ID as value. An ID is present in
# the result only if more than one entity has it. The argument
# entities is a list of AttrSet of one id/name pair.
findDuplicateIds = entities:
filterAttrs (_entityId: entityNames: length entityNames != 1)
(zipAttrs entities);
duplicates = findDuplicateIds (mapAttrsToList
(entityName: entity: { "${toString entity.id}" = entityName; })
entities);
mkMsg = entityId: entityNames:
" - ID ${entityId} is used by " + concatStringsSep ", " entityNames;
in {
assertion = duplicates == { };
message = ''
Must not have a ${name} ${entityKind} with an existing ID but
'' + concatStringsSep "\n" (mapAttrsToList mkMsg duplicates);
});
wrapPackage = package:
let
# The configuration expected by the Firefox wrapper.
fcfg = { enableGnomeExtensions = cfg.enableGnomeExtensions; };
# A bit of hackery to force a config into the wrapper.
browserName =
package.browserName or (builtins.parseDrvName package.name).name;
# The configuration expected by the Firefox wrapper builder.
bcfg = setAttrByPath [ browserName ] fcfg;
in if package == null then
null
else if isDarwin then
package
else if isWrapped then
package.override (old: {
cfg = old.cfg or { } // fcfg;
extraPolicies = (old.extraPolicies or { }) // cfg.policies;
})
else
(pkgs.wrapFirefox.override { config = bcfg; }) package { };
in {
options = setAttrByPath modulePath {
enable = mkOption {
type = types.bool;
default = false;
example = true;
description = ''
Whether to enable ${name}.${
optionalString (description != null) " ${description}"
}
${optionalString (!visible)
"See `programs.firefox` for more configuration options."}
'';
};
package = mkOption {
inherit visible;
type = with types; nullOr package;
default = pkgs.${defaultPackageName};
defaultText = literalExpression "pkgs.${packageName}";
example = literalExpression ''
pkgs.${packageName}.override {
# See nixpkgs' firefox/wrapper.nix to check which options you can use
nativeMessagingHosts = [
# Gnome shell native connector
pkgs.gnome-browser-connector
# Tridactyl native connector
pkgs.tridactyl-native
];
}
'';
description = ''
The ${name} package to use. If state version 19.09 then
this should be a wrapped ${name} package. For earlier state
versions it should be an unwrapped ${name} package.
Set to `null` to disable installing ${name}.
'';
};
languagePacks = mkOption {
type = types.listOf types.str;
default = [ ];
description = ''
The language packs to install. Available language codes can be found
on the releases page:
`https://releases.mozilla.org/pub/firefox/releases/''${version}/linux-x86_64/xpi/`,
replacing `''${version}` with the version of Firefox you have.
'';
example = [ "en-GB" "de" ];
};
name = mkOption {
internal = true;
type = types.str;
default = name;
example = "Firefox";
description = "The name of the browser.";
};
wrappedPackageName = mkOption {
internal = true;
type = with types; nullOr str;
default = wrappedPackageName;
description = "Name of the wrapped browser package.";
};
vendorPath = mkOption {
internal = true;
type = with types; nullOr str;
default = with platforms;
if isDarwin then
darwin.vendorPath or null
else
linux.vendorPath or null;
example = ".mozilla";
description =
"Directory containing the native messaging hosts directory.";
};
configPath = mkOption {
internal = true;
type = types.str;
default = with platforms;
if isDarwin then darwin.configPath else linux.configPath;
example = ".mozilla/firefox";
description = "Directory containing the ${name} configuration files.";
};
nativeMessagingHosts = optionalAttrs (cfg.vendorPath != null) (mkOption {
inherit visible;
type = types.listOf types.package;
default = [ ];
description = ''
Additional packages containing native messaging hosts that should be
made available to ${name} extensions.
'';
});
finalPackage = mkOption {
inherit visible;
type = with types; nullOr package;
readOnly = true;
description = "Resulting ${cfg.name} package.";
};
policies = optionalAttrs (wrappedPackageName != null) (mkOption {
inherit visible;
type = types.attrsOf jsonFormat.type;
default = { };
description =
"[See list of policies](https://mozilla.github.io/policy-templates/).";
example = {
DefaultDownloadDirectory = "\${home}/Downloads";
BlockAboutConfig = true;
};
});
profileVersion = mkOption {
internal = true;
type = types.nullOr types.ints.unsigned;
default = if isDarwin then null else 2;
description = "profile version, set null for nix-darwin";
};
profiles = mkOption {
inherit visible;
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 = types.attrsOf (jsonFormat.type // {
description =
"${name} preference (int, bool, string, and also attrs, list, float as a JSON string)";
});
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;
"browser.newtabpage.pinned" = [{
title = "NixOS";
url = "https://nixos.org";
}];
}
'';
description = ''
Attribute set of ${name} preferences.
${name} only supports int, bool, and string types for
preferences, but home-manager will automatically
convert all other JSON-compatible values into strings.
'';
};
extraConfig = mkOption {
type = types.lines;
default = "";
description = ''
Extra preferences to add to {file}`user.js`.
'';
};
userChrome = mkOption {
type = types.lines;
default = "";
description = "Custom ${name} user chrome CSS.";
example = ''
/* Hide tab bar in FF Quantum */
@-moz-document url(chrome://browser/content/browser.xul), url(chrome://browser/content/browser.xhtml) {
#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 ${name} user content CSS.";
example = ''
/* Hide scrollbar in FF Quantum */
*{scrollbar-width:none !important}
'';
};
bookmarks = mkOption {
type = let
bookmarkSubmodule = types.submodule ({ config, name, ... }: {
options = {
name = mkOption {
type = types.str;
default = name;
description = "Bookmark name.";
};
tags = mkOption {
type = types.listOf types.str;
default = [ ];
description = "Bookmark tags.";
};
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.";
};
};
}) // {
description = "bookmark submodule";
};
bookmarkType = types.addCheck bookmarkSubmodule (x: x ? "url");
directoryType = types.submodule ({ config, name, ... }: {
options = {
name = mkOption {
type = types.str;
default = name;
description = "Directory name.";
};
bookmarks = mkOption {
type = types.listOf nodeType;
default = [ ];
description = "Bookmarks within directory.";
};
toolbar = mkOption {
type = types.bool;
default = false;
description = ''
Make this the toolbar directory. Note, this does _not_
mean that this directory will be added to the toolbar,
this directory _is_ the toolbar.
'';
};
};
}) // {
description = "directory submodule";
};
nodeType = types.either bookmarkType directoryType;
in with types;
coercedTo (attrsOf nodeType) attrValues (listOf nodeType);
default = [ ];
example = literalExpression ''
[
{
name = "wikipedia";
tags = [ "wiki" ];
keyword = "wiki";
url = "https://en.wikipedia.org/wiki/Special:Search?search=%s&go=Go";
}
{
name = "kernel.org";
url = "https://www.kernel.org";
}
{
name = "Nix sites";
toolbar = true;
bookmarks = [
{
name = "homepage";
url = "https://nixos.org/";
}
{
name = "wiki";
tags = [ "wiki" "nix" ];
url = "https://wiki.nixos.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.";
};
search = mkOption {
type = types.submodule (args:
import ./profiles/search.nix {
inherit (args) config;
inherit lib pkgs;
appName = cfg.name;
modulePath = modulePath ++ [ "profiles" name "search" ];
profilePath = config.path;
});
default = { };
description = "Declarative search engine configuration.";
};
containersForce = mkOption {
type = types.bool;
default = false;
description = ''
Whether to force replace the existing containers configuration.
This is recommended since Firefox will replace the symlink on
every launch, but note that you'll lose any existing configuration
by enabling this.
'';
};
containers = mkOption {
type = types.attrsOf (types.submodule ({ name, ... }: {
options = {
name = mkOption {
type = types.str;
default = name;
description = "Container name, e.g., shopping.";
};
id = mkOption {
type = types.ints.unsigned;
default = 0;
description = ''
Container ID. This should be set to a unique number per container in this profile.
'';
};
# List of colors at
# https://searchfox.org/mozilla-central/rev/5ad226c7379b0564c76dc3b54b44985356f94c5a/toolkit/components/extensions/parent/ext-contextualIdentities.js#32
color = mkOption {
type = types.enum [
"blue"
"turquoise"
"green"
"yellow"
"orange"
"red"
"pink"
"purple"
"toolbar"
];
default = "pink";
description = "Container color.";
};
icon = mkOption {
type = types.enum [
"briefcase"
"cart"
"circle"
"dollar"
"fence"
"fingerprint"
"gift"
"vacation"
"food"
"fruit"
"pet"
"tree"
"chill"
];
default = "fruit";
description = "Container icon.";
};
};
}));
default = { };
example = {
"shopping" = {
id = 1;
color = "blue";
icon = "cart";
};
"dangerous" = {
id = 2;
color = "red";
icon = "fruit";
};
};
description = ''
Attribute set of container configurations. See
[Multi-Account
Containers](https://support.mozilla.org/en-US/kb/containers)
for more information.
'';
};
extensions = mkOption {
type = types.listOf types.package;
default = [ ];
example = literalExpression ''
with pkgs.nur.repos.rycee.firefox-addons; [
privacy-badger
]
'';
description = ''
List of ${name} add-on packages to install for this profile.
Some pre-packaged add-ons are accessible from the
[Nix User Repository](https://github.com/nix-community/NUR).
Once you have NUR installed run
```console
$ nix-env -f '<nixpkgs>' -qaP -A nur.repos.rycee.firefox-addons
```
to list the available ${name} add-ons.
Note that it is necessary to manually enable these extensions
inside ${name} after the first installation.
To automatically enable extensions add
`"extensions.autoDisableScopes" = 0;`
to
[{option}`${moduleName}.profiles.<profile>.settings`](#opt-${moduleName}.profiles._name_.settings)
'';
};
};
}));
default = { };
description = "Attribute set of ${name} profiles.";
};
enableGnomeExtensions = mkOption {
inherit visible;
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.gnome.gnome-browser-connector.enable` to
`true`.
'';
};
};
config = mkIf cfg.enable ({
assertions = [
(hm.assertions.assertPlatform moduleName pkgs supportedPlatforms)
(let
defaults =
catAttrs "name" (filter (a: a.isDefault) (attrValues cfg.profiles));
in {
assertion = cfg.profiles == { } || length defaults == 1;
message = "Must have exactly one default ${cfg.name} profile but found "
+ toString (length defaults) + optionalString (length defaults > 1)
(", namely " + concatStringsSep ", " defaults);
})
(let
getContainers = profiles:
flatten
(mapAttrsToList (_: value: (attrValues value.containers)) profiles);
findInvalidContainerIds = profiles:
filter (container: container.id >= 4294967294)
(getContainers profiles);
in {
assertion = cfg.profiles == { }
|| length (findInvalidContainerIds cfg.profiles) == 0;
message = "Container id must be smaller than 4294967294 (2^32 - 2)";
})
{
assertion = cfg.languagePacks == [ ] || cfg.package != null;
message = ''
'programs.firefox.languagePacks' requires 'programs.firefox.package'
to be set to a non-null value.
'';
}
(mkNoDuplicateAssertion cfg.profiles "profile")
] ++ (mapAttrsToList
(_: profile: mkNoDuplicateAssertion profile.containers "container")
cfg.profiles);
warnings = optional (cfg.enableGnomeExtensions or false) ''
Using '${moduleName}.enableGnomeExtensions' has been deprecated and
will be removed in the future. Please change to overriding the package
configuration using '${moduleName}.package' instead. You can refer to
its example for how to do this.
'';
home.packages = lib.optional (cfg.finalPackage != null) cfg.finalPackage;
home.file = mkMerge ([{
"${cfg.configPath}/profiles.ini" =
mkIf (cfg.profiles != { }) { text = profilesIni; };
}] ++ optional (cfg.vendorPath != null) {
"${nativeMessagingHostsPath}" = {
source =
"${nativeMessagingHostsJoined}/lib/mozilla/native-messaging-hosts";
recursive = true;
};
} ++ 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}/containers.json" =
mkIf (profile.containers != { }) {
text = mkContainersJson profile.containers;
force = profile.containersForce;
};
"${profilesPath}/${profile.path}/search.json.mozlz4" =
mkIf (profile.search.enable) {
enable = profile.search.enable;
force = profile.search.force;
source = profile.search.file;
};
"${profilesPath}/${profile.path}/extensions" =
mkIf (profile.extensions != [ ]) {
source = let
extensionsEnvPkg = pkgs.buildEnv {
name = "hm-firefox-extensions";
paths = profile.extensions;
};
in "${extensionsEnvPkg}/share/mozilla/${extensionPath}";
recursive = true;
force = true;
};
}));
} // setAttrByPath modulePath {
finalPackage = wrapPackage cfg.package;
policies = {
ExtensionSettings = listToAttrs (map (lang:
nameValuePair "langpack-${lang}@firefox.mozilla.org" {
installation_mode = "normal_installed";
install_url =
"https://releases.mozilla.org/pub/firefox/releases/${cfg.package.version}/linux-x86_64/xpi/${lang}.xpi";
}) cfg.languagePacks);
};
});
}

View file

@ -0,0 +1,251 @@
{ config, lib, pkgs, appName, modulePath, profilePath }:
with lib;
let
jsonFormat = pkgs.formats.json { };
# Map of nice field names to internal field names.
# This is intended to be exhaustive and should be
# updated at every version bump.
internalFieldNames = (genAttrs [
"name"
"isAppProvided"
"loadPath"
"hasPreferredIcon"
"updateInterval"
"updateURL"
"iconUpdateURL"
"iconURL"
"iconMapObj"
"metaData"
"orderHint"
"definedAliases"
"urls"
] (name: "_${name}")) // {
searchForm = "__searchForm";
};
processCustomEngineInput = input:
(removeAttrs input [ "icon" ]) // optionalAttrs (input ? icon) {
# Convenience to specify absolute path to icon
iconURL = "file://${input.icon}";
} // (optionalAttrs (input ? iconUpdateURL) {
# Convenience to default iconURL to iconUpdateURL so
# the icon is immediately downloaded from the URL
iconURL = input.iconURL or input.iconUpdateURL;
} // {
# Required for custom engine configurations, loadPaths
# are unique identifiers that are generally formatted
# like: [source]/path/to/engine.xml
loadPath = "[home-manager]/${
concatStringsSep "." (map strings.escapeNixIdentifier
(modulePath ++ [ "engines" input.name ]))
}";
});
processEngineInput = name: input:
let
requiredInput = {
inherit name;
isAppProvided = input.isAppProvided or removeAttrs input [ "metaData" ]
== { };
metaData = input.metaData or { };
};
in if requiredInput.isAppProvided then
requiredInput
else
processCustomEngineInput (input // requiredInput);
buildEngineConfig = name: input:
mapAttrs' (name: value: {
name = internalFieldNames.${name} or name;
inherit value;
}) (processEngineInput name input);
sortEngineConfigs = configs:
let
buildEngineConfigWithOrder = order: name:
let
config = configs.${name} or {
_name = name;
_isAppProvided = true;
_metaData = { };
};
in config // { _metaData = config._metaData // { inherit order; }; };
engineConfigsWithoutOrder = attrValues (removeAttrs configs config.order);
sortedEngineConfigs = (imap buildEngineConfigWithOrder config.order)
++ engineConfigsWithoutOrder;
in sortedEngineConfigs;
engineInput = config.engines // {
# Infer config.default as an app provided
# engine if it's not in config.engines
${config.default} = config.engines.${config.default} or { };
} // {
${config.privateDefault} = config.engines.${config.privateDefault} or { };
};
settings = {
version = 6;
engines = sortEngineConfigs (mapAttrs buildEngineConfig engineInput);
metaData = optionalAttrs (config.default != null) {
current = config.default;
hash = "@hash@";
} // optionalAttrs (config.privateDefault != null) {
private = config.privateDefault;
privateHash = "@privateHash@";
} // {
useSavedOrder = config.order != [ ];
};
};
# Home Manager doesn't circumvent user consent and isn't acting
# maliciously. We're modifying the search outside of the browser, but
# a claim by Mozilla to remove this would be very anti-user, and
# is unlikely to be an issue for our use case.
disclaimer = "By modifying this file, I agree that I am doing so "
+ "only within ${appName} itself, using official, user-driven search "
+ "engine selection processes, and in a way which does not circumvent "
+ "user consent. I acknowledge that any attempt to change this file "
+ "from outside of ${appName} is a malicious act, and will be responded "
+ "to accordingly.";
salt = if config.default != null then
profilePath + config.default + disclaimer
else
null;
privateSalt = if config.privateDefault != null then
profilePath + config.privateDefault + disclaimer
else
null;
file = pkgs.runCommand "search.json.mozlz4" {
nativeBuildInputs = with pkgs; [ mozlz4a openssl ];
json = builtins.toJSON settings;
inherit salt privateSalt;
} ''
if [[ -n $salt ]]; then
export hash=$(echo -n "$salt" | openssl dgst -sha256 -binary | base64)
export privateHash=$(echo -n "$privateSalt" | openssl dgst -sha256 -binary | base64)
mozlz4a <(substituteStream json search.json.in --subst-var hash --subst-var privateHash) "$out"
else
mozlz4a <(echo "$json") "$out"
fi
'';
in {
imports = [ (pkgs.path + "/nixos/modules/misc/meta.nix") ];
meta.maintainers = with maintainers; [ kira-bruneau ];
options = {
enable = mkOption {
type = with types; bool;
default = config.default != null || config.privateDefault != null
|| config.order != [ ] || config.engines != { };
internal = true;
};
force = mkOption {
type = with types; bool;
default = false;
description = ''
Whether to force replace the existing search
configuration. This is recommended since ${appName} will
replace the symlink for the search configuration on every
launch, but note that you'll lose any existing configuration
by enabling this.
'';
};
default = mkOption {
type = with types; nullOr str;
default = null;
example = "DuckDuckGo";
description = ''
The default search engine used in the address bar and search
bar.
'';
};
privateDefault = mkOption {
type = with types; nullOr str;
default = null;
example = "DuckDuckGo";
description = ''
The default search engine used in the Private Browsing.
'';
};
order = mkOption {
type = with types; uniq (listOf str);
default = [ ];
example = [ "DuckDuckGo" "Google" ];
description = ''
The order the search engines are listed in. Any engines that
aren't included in this list will be listed after these in an
unspecified order.
'';
};
engines = mkOption {
type = with types; attrsOf (attrsOf jsonFormat.type);
default = { };
example = literalExpression ''
{
"Nix Packages" = {
urls = [{
template = "https://search.nixos.org/packages";
params = [
{ name = "type"; value = "packages"; }
{ name = "query"; value = "{searchTerms}"; }
];
}];
icon = "''${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg";
definedAliases = [ "@np" ];
};
"NixOS Wiki" = {
urls = [{ template = "https://wiki.nixos.org/index.php?search={searchTerms}"; }];
iconUpdateURL = "https://wiki.nixos.org/favicon.png";
updateInterval = 24 * 60 * 60 * 1000; # every day
definedAliases = [ "@nw" ];
};
"Bing".metaData.hidden = true;
"Google".metaData.alias = "@g"; # builtin engines only support specifying one additional alias
}
'';
description = ''
Attribute set of search engine configurations. Engines that
only have {var}`metaData` specified will be treated as builtin
to ${appName}.
See [SearchEngine.jsm](https://searchfox.org/mozilla-central/rev/669329e284f8e8e2bb28090617192ca9b4ef3380/toolkit/components/search/SearchEngine.jsm#1138-1177)
in ${appName}'s source for available options. We maintain a
mapping to let you specify all options in the referenced link
without underscores, but it may fall out of date with future
options.
Note, {var}`icon` is also a special option added by Home
Manager to make it convenient to specify absolute icon paths.
'';
};
file = mkOption {
type = with types; path;
default = file;
internal = true;
readOnly = true;
description = ''
Resulting search.json.mozlz4 file.
'';
};
};
}

View file

@ -253,6 +253,12 @@ in {
'';
};
generateCompletions = mkEnableOption
"the automatic generation of completions based upon installed man pages"
// {
default = true;
};
shellAliases = mkOption {
type = with types; attrsOf str;
default = { };
@ -288,6 +294,16 @@ in {
'';
};
preferAbbrs = mkOption {
type = types.bool;
default = false;
example = true;
description = ''
If enabled, abbreviations will be preferred over aliases when
other modules define aliases for fish.
'';
};
shellInit = mkOption {
type = types.lines;
default = "";
@ -380,9 +396,9 @@ in {
};
config = mkIf cfg.enable (mkMerge [
{
home.packages = [ cfg.package ];
{ home.packages = [ cfg.package ]; }
(mkIf cfg.generateCompletions {
# Support completion for `man` by building a cache for `apropos`.
programs.man.generateCaches = mkDefault true;
@ -446,7 +462,9 @@ in {
set fish_complete_path $prev "${config.xdg.dataHome}/fish/home-manager_generated_completions" $post
end
'';
})
{
xdg.configFile."fish/config.fish".source = fishIndent "config.fish" ''
# ~/.config/fish/config.fish: DO NOT EDIT -- this file has been generated
# automatically by home-manager.

View file

@ -0,0 +1,29 @@
{ lib, ... }:
with lib;
let
modulePath = [ "programs" "floorp" ];
mkFirefoxModule = import ./firefox/mkFirefoxModule.nix;
in {
meta.maintainers = [ hm.maintainers.bricked ];
imports = [
(mkFirefoxModule {
inherit modulePath;
name = "Floorp";
wrappedPackageName = "floorp";
unwrappedPackageName = "floorp-unwrapped";
visible = true;
platforms.linux = {
configPath = ".floorp";
vendorPath = ".floorp";
};
platforms.darwin = { configPath = "Library/Application Support/Floorp"; };
})
];
}

View file

@ -12,13 +12,27 @@ in {
enable = lib.mkEnableOption "Git authentication handler for OAuth";
package = lib.mkPackageOption pkgs "git-credential-oauth" { };
extraFlags = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
example = lib.literalExpression ''[ "-device" ]'';
description = ''
Extra command-line arguments passed to git-credential-oauth.
For valid arguments, see {manpage}`git-credential-oauth(1)`.
'';
};
};
};
config = lib.mkIf cfg.enable {
home.packages = [ cfg.package ];
programs.git.extraConfig.credential.helper =
[ "${cfg.package}/bin/git-credential-oauth" ];
programs.git.extraConfig.credential.helper = lib.mkAfter [
("${cfg.package}/bin/git-credential-oauth"
+ lib.optionalString (cfg.extraFlags != [ ])
" ${lib.strings.concatStringsSep " " cfg.extraFlags}")
];
};
}

View file

@ -214,6 +214,59 @@ in {
};
};
maintenance = {
enable = mkEnableOption "" // {
description = ''
Enable the automatic {command}`git maintenance`.
See <https://git-scm.com/docs/git-maintenance>.
'';
};
repositories = mkOption {
type = with types; listOf str;
default = [ ];
description = ''
Repositories on which {command}`git maintenance` should run.
Should be a list of absolute paths.
'';
};
timers = mkOption {
type = types.attrsOf types.str;
default = {
hourly = "*-*-* 1..23:53:00";
daily = "Tue..Sun *-*-* 0:53:00";
weekly = "Mon 0:53:00";
};
description = ''
Systemd timers to create for scheduled {command}`git maintenance`.
Key is passed to `--schedule` argument in {command}`git maintenance run`
and value is passed to `Timer.OnCalendar` in `systemd.user.timers`.
'';
};
};
diff-highlight = {
enable = mkEnableOption "" // {
description = ''
Enable the contrib {command}`diff-highlight` syntax highlighter.
See <https://github.com/git/git/blob/master/contrib/diff-highlight/README>,
'';
};
pagerOpts = mkOption {
type = types.listOf types.str;
default = [ ];
example = [ "--tabs=4" "-RFX" ];
description = ''
Arguments to be passed to {command}`less`.
'';
};
};
difftastic = {
enable = mkEnableOption "" // {
description = ''
@ -222,6 +275,8 @@ in {
'';
};
package = mkPackageOption pkgs "difftastic" { };
background = mkOption {
type = types.enum [ "light" "dark" ];
default = "light";
@ -358,11 +413,15 @@ in {
home.packages = [ cfg.package ];
assertions = [{
assertion = let
enabled =
[ cfg.delta.enable cfg.diff-so-fancy.enable cfg.difftastic.enable ];
enabled = [
cfg.delta.enable
cfg.diff-so-fancy.enable
cfg.difftastic.enable
cfg.diff-highlight.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.";
"Only one of 'programs.git.delta.enable' or 'programs.git.difftastic.enable' or 'programs.git.diff-so-fancy.enable' or 'programs.git.diff-highlight' can be set to true at the same time.";
}];
programs.git.iniContent.user = {
@ -477,12 +536,66 @@ in {
};
})
(mkIf cfg.maintenance.enable {
programs.git.iniContent.maintenance.repo = cfg.maintenance.repositories;
systemd.user.services."git-maintenance@" = {
Unit = {
Description = "Optimize Git repositories data";
Documentation = [ "man:git-maintenance(1)" ];
};
Service = {
Type = "oneshot";
ExecStart = let exe = lib.getExe cfg.package;
in ''
"${exe}" for-each-repo --keep-going --config=maintenance.repo maintenance run --schedule=%i
'';
LockPersonality = "yes";
MemoryDenyWriteExecute = "yes";
NoNewPrivileges = "yes";
RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6 AF_VSOCK";
RestrictNamespaces = "yes";
RestrictRealtime = "yes";
RestrictSUIDSGID = "yes";
SystemCallArchitectures = "native";
SystemCallFilter = "@system-service";
};
};
systemd.user.timers = let
toSystemdTimer = name: time:
lib.attrsets.nameValuePair "git-maintenance@${name}" {
Unit.Description = "Optimize Git repositories data";
Timer = {
OnCalendar = time;
Persistent = true;
};
Install.WantedBy = [ "timers.target" ];
};
in lib.attrsets.mapAttrs' toSystemdTimer cfg.maintenance.timers;
})
(mkIf cfg.diff-highlight.enable {
programs.git.iniContent = let
dhCommand =
"${cfg.package}/share/git/contrib/diff-highlight/diff-highlight";
in {
core.pager = "${dhCommand} | ${getExe pkgs.less} ${
escapeShellArgs cfg.diff-highlight.pagerOpts
}";
interactive.diffFilter = dhCommand;
};
})
(mkIf cfg.difftastic.enable {
home.packages = [ pkgs.difftastic ];
home.packages = [ cfg.difftastic.package ];
programs.git.iniContent = let
difftCommand = concatStringsSep " " [
"${pkgs.difftastic}/bin/difft"
"${getExe cfg.difftastic.package}"
"--color ${cfg.difftastic.color}"
"--background ${cfg.difftastic.background}"
"--display ${cfg.difftastic.display}"

View file

@ -316,7 +316,7 @@ in {
})
];
home.packages = [ pkgs.gnome.gnome-terminal ];
home.packages = [ pkgs.gnome-terminal ];
dconf.settings = let dconfPath = "org/gnome/terminal/legacy";
in {

View file

@ -28,7 +28,7 @@ in {
programs.zsh.initExtra = mkIf cfg.enableZshIntegration ''
function assume() {
export GRANTED_ALIAS_CONFIGURED="true"
source ${package}/bin/.assume-wrapped "$@"
source ${package}/bin/assume "$@"
unset GRANTED_ALIAS_CONFIGURED
}
'';

View file

@ -15,6 +15,7 @@ in {
type = types.package;
default = pkgs.helix;
defaultText = literalExpression "pkgs.helix";
example = literalExpression "pkgs.evil-helix";
description = "The package to use for helix.";
};
@ -75,7 +76,6 @@ in {
default = { };
example = literalExpression ''
{
# the language-server option currently requires helix from the master branch at https://github.com/helix-editor/helix/
language-server.typescript-language-server = with pkgs.nodePackages; {
command = "''${typescript-language-server}/bin/typescript-language-server";
args = [ "--stdio" "--tsserver-path=''${typescript}/lib/node_modules/typescript/lib" ];
@ -188,7 +188,7 @@ in {
nativeBuildInputs = [ pkgs.makeWrapper ];
postBuild = ''
wrapProgram $out/bin/hx \
--prefix PATH : ${lib.makeBinPath cfg.extraPackages}
--suffix PATH : ${lib.makeBinPath cfg.extraPackages}
'';
})
]

View file

@ -113,7 +113,8 @@ in {
enable = mkEnableOption "htop";
settings = mkOption {
type = types.attrs;
type = with types;
attrsOf (oneOf [ bool int str (listOf (oneOf [ int str ])) ]);
default = { };
example = literalExpression ''
{

View file

@ -7,6 +7,11 @@ let
cfg = config.programs.jujutsu;
tomlFormat = pkgs.formats.toml { };
configDir = if pkgs.stdenv.isDarwin then
"Library/Application Support"
else
config.xdg.configHome;
in {
meta.maintainers = [ maintainers.shikanime ];
@ -51,7 +56,7 @@ in {
config = mkIf cfg.enable {
home.packages = [ cfg.package ];
xdg.configFile."jj/config.toml" = mkIf (cfg.settings != { }) {
home.file."${configDir}/jj/config.toml" = mkIf (cfg.settings != { }) {
source = tomlFormat.generate "jujutsu-config" (cfg.settings
// optionalAttrs (cfg.ediff) (let
emacsDiffScript = pkgs.writeShellScriptBin "emacs-ediff" ''

View file

@ -9,11 +9,7 @@ let
inherit (pkgs.stdenv.hostPlatform) isDarwin;
in {
meta.maintainers = with maintainers; [
katexochen
liyangau
hm.maintainers.LucasWagler
];
meta.maintainers = with maintainers; [ liyangau hm.maintainers.LucasWagler ];
imports = [
(mkRenamedOptionModule [ "programs" "k9s" "skin" ] [
@ -46,7 +42,7 @@ in {
};
skins = mkOption {
type = types.attrsOf yamlFormat.type;
type = with types; attrsOf (either yamlFormat.type path);
default = { };
description = ''
Skin files written to {file}`$XDG_CONFIG_HOME/k9s/skins/` (linux)
@ -54,6 +50,7 @@ in {
<https://k9scli.io/topics/skins/> for supported values.
'';
example = literalExpression ''
{
my_blue_skin = {
k9s = {
body = {
@ -61,6 +58,8 @@ in {
};
};
};
my_red_skin = ./red_skin.yaml;
}
'';
};
@ -174,7 +173,10 @@ in {
"k9s/skins/${name}.yaml"
else
"Library/Application Support/k9s/skins/${name}.yaml") {
source = yamlFormat.generate "k9s-skin-${name}.yaml" value;
source = if lib.types.path.check value then
value
else
yamlFormat.generate "k9s-skin-${name}.yaml" value;
}) cfg.skins;
enableXdgConfig = !isDarwin || config.xdg.enable;

View file

@ -68,6 +68,11 @@ in {
type = with lib.types;
attrsOf (submodule {
options.khard.enable = lib.mkEnableOption "khard access";
options.khard.defaultCollection = lib.mkOption {
type = types.str;
default = "";
description = "VCARD collection to be searched by khard.";
};
});
};
};
@ -75,11 +80,17 @@ in {
config = lib.mkIf cfg.enable {
home.packages = [ pkgs.khard ];
xdg.configFile."khard/khard.conf".text = ''
xdg.configFile."khard/khard.conf".text = let
makePath = anAccount:
builtins.toString (/. + lib.concatStringsSep "/" [
anAccount.local.path
anAccount.khard.defaultCollection
]);
in ''
[addressbooks]
${lib.concatMapStringsSep "\n" (acc: ''
[[${acc.name}]]
path = ${acc.local.path}
path = ${makePath acc}
'') (lib.attrValues accounts)}
${renderSettings cfg.settings}

View file

@ -3,10 +3,9 @@
with lib;
let
cfg = config.programs.kitty;
eitherStrBoolInt = with types; either str (either bool int);
settingsValueType = with types; oneOf [ str bool int float ];
optionalPackage = opt:
optional (opt != null && opt.package != null) opt.package;
@ -57,6 +56,26 @@ let
'';
};
in {
imports = [
(mkChangedOptionModule [ "programs" "kitty" "theme" ] [
"programs"
"kitty"
"themeFile"
] (config:
let value = getAttrFromPath [ "programs" "kitty" "theme" ] config;
in if value != null then
(let
matching = filter (x: x.name == value) (builtins.fromJSON
(builtins.readFile
"${pkgs.kitty-themes}/share/kitty-themes/themes.json"));
in throwIf (length matching == 0)
"kitty-themes does not contain a theme named ${value}"
strings.removeSuffix ".conf"
(strings.removePrefix "themes/" (head matching).file))
else
null))
];
options.programs.kitty = {
enable = mkEnableOption "Kitty terminal emulator";
@ -83,7 +102,7 @@ in {
};
settings = mkOption {
type = types.attrsOf eitherStrBoolInt;
type = types.attrsOf settingsValueType;
default = { };
example = literalExpression ''
{
@ -100,16 +119,16 @@ in {
'';
};
theme = mkOption {
themeFile = 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 {command}`kitty +kitten themes`.
See <https://github.com/kovidgoyal/kitty-themes>
for more details.
Apply a Kitty color theme. This option takes the file name of a theme
in `kitty-themes`, without the `.conf` suffix. See
<https://github.com/kovidgoyal/kitty-themes/tree/master/themes> for a
list of themes.
'';
example = "Space Gray Eighties";
example = "SpaceGray_Eighties";
};
font = mkOption {
@ -146,11 +165,11 @@ in {
type = types.str;
default = "no-rc";
example = "no-cursor";
apply = (o:
apply = o:
let
modes = splitString " " o;
filtered = filter (m: m != "no-rc") modes;
in concatStringsSep " " (concatLists [ [ "no-rc" ] filtered ]));
in concatStringsSep " " (concatLists [ [ "no-rc" ] filtered ]);
description = ''
Set the mode of the shell integration. This accepts the same options
as the `shell_integration` option of Kitty. Note that
@ -184,24 +203,15 @@ in {
text = ''
# Generated by Home Manager.
# See https://sw.kovidgoyal.net/kitty/conf.html
'' + concatStringsSep "\n" ([
'' + concatStringsSep "\n" [
(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}/share/kitty-themes/${
let
matching = filter (x: x.name == cfg.theme) (builtins.fromJSON
(builtins.readFile
"${pkgs.kitty-themes}/share/kitty-themes/themes.json"));
in throwIf (length matching == 0)
"kitty-themes does not contain a theme named ${cfg.theme}"
(head matching).file
}
(optionalString (cfg.themeFile != null) ''
include ${pkgs.kitty-themes}/share/kitty-themes/themes/${cfg.themeFile}.conf
'')
''
# Shell integration is sourced and configured manually
@ -211,13 +221,23 @@ in {
(toKittyKeybindings cfg.keybindings)
(toKittyEnv cfg.environment)
cfg.extraConfig
]);
];
} // optionalAttrs pkgs.stdenv.hostPlatform.isLinux {
onChange = ''
${pkgs.procps}/bin/pkill -USR1 -u $USER kitty || true
'';
};
home.activation.checkKittyTheme = mkIf (cfg.themeFile != null) (let
themePath =
"${pkgs.kitty-themes}/share/kitty-themes/themes/${cfg.themeFile}.conf";
in hm.dag.entryBefore [ "writeBoundary" ] ''
if [[ ! -f "${themePath}" ]]; then
errorEcho "kitty-themes does not contain the theme file ${themePath}!"
exit 1
fi
'');
xdg.configFile."kitty/macos-launch-services-cmdline" = mkIf
(cfg.darwinLaunchOptions != null && pkgs.stdenv.hostPlatform.isDarwin) {
text = concatStringsSep " " cfg.darwinLaunchOptions;

View file

@ -74,7 +74,15 @@ in {
programs.zsh.shellAliases = mkIf cfg.enableAliases aliases;
programs.fish.shellAliases = mkIf cfg.enableAliases aliases;
programs.fish = mkMerge [
(mkIf (!config.programs.fish.preferAbbrs) {
shellAliases = mkIf cfg.enableAliases aliases;
})
(mkIf config.programs.fish.preferAbbrs {
shellAbbrs = mkIf cfg.enableAliases aliases;
})
];
programs.lsd =
mkIf (cfg.colors != { }) { settings.color.theme = "custom"; };

View file

@ -5,6 +5,8 @@ let
cfg = config.programs.mcfly;
tomlFormat = pkgs.formats.toml { };
bashIntegration = ''
eval "$(${getExe pkgs.mcfly} init bash)"
'' + optionalString cfg.fzf.enable ''
@ -40,6 +42,37 @@ in {
options.programs.mcfly = {
enable = mkEnableOption "mcfly";
settings = mkOption {
type = tomlFormat.type;
default = { };
example = literalExpression ''
{
colors = {
menubar = {
bg = "black";
fg = "red";
};
darkmode = {
prompt = "cyan";
timing = "yellow";
results_selection_fg = "cyan";
results_selection_bg = "black";
results_selection_hl = "red";
};
};
}
'';
description = ''
Settings written to {file}`~/.config/mcfly/config.toml`.
Note, if your McFly database is currently in {file}`~/.mcfly`,
then this option has no effect.
Move the database to {file}`$XDG_DATA_DIR/mcfly/history.db` and
remove {file}`~/.mcfly` to make the settings take effect. See
<https://github.com/cantino/mcfly#database-location>.
'';
};
keyScheme = mkOption {
type = types.enum [ "emacs" "vim" ];
default = "emacs";
@ -105,6 +138,11 @@ in {
{
home.packages = [ pkgs.mcfly ] ++ optional cfg.fzf.enable pkgs.mcfly-fzf;
# Oddly enough, McFly expects this in the data path, not in config.
xdg.dataFile."mcfly/config.toml" = mkIf (cfg.settings != { }) {
source = tomlFormat.generate "mcfly-config.toml" cfg.settings;
};
programs.bash.initExtra = mkIf cfg.enableBashIntegration bashIntegration;
programs.zsh.initExtra = mkIf cfg.enableZshIntegration zshIntegration;

View file

@ -15,6 +15,8 @@ in {
programs.micro = {
enable = mkEnableOption "micro, a terminal-based text editor";
package = mkPackageOption pkgs "micro" { };
settings = mkOption {
type = jsonFormat.type;
default = { };
@ -35,7 +37,7 @@ in {
};
config = mkIf cfg.enable {
home.packages = [ pkgs.micro ];
home.packages = [ cfg.package ];
xdg.configFile."micro/settings.json".source =
jsonFormat.generate "micro-settings" cfg.settings;

View file

@ -0,0 +1,52 @@
{ config, lib, pkgs, ... }:
let
cfg = config.programs.neovide;
settingsFormat = pkgs.formats.toml { };
in {
meta.maintainers = [ lib.hm.maintainers.NitroSniper ];
options.programs.neovide = {
enable = lib.mkEnableOption "Neovide, No Nonsense Neovim Client in Rust";
package = lib.mkPackageOption pkgs "neovide" { };
settings = lib.mkOption {
type = settingsFormat.type;
example = lib.literalExpression ''
{
fork = false;
frame = "full";
idle = true;
maximized = false;
neovim-bin = "/usr/bin/nvim";
no-multigrid = false;
srgb = false;
tabs = true;
theme = "auto";
title-hidden = true;
vsync = true;
wsl = false;
font = {
normal = [];
size = 14.0;
};
}
'';
description = ''
Neovide configuration.
For available settings see <https://neovide.dev/config-file.html>.
For any option not found will need to be done in your neovim's config instead.
'';
};
};
config = lib.mkIf cfg.enable {
home.packages = [ cfg.package ];
xdg.configFile."neovide/config.toml".source =
settingsFormat.generate "config.toml" cfg.settings;
};
}

View file

@ -398,6 +398,13 @@ in {
customRC = cfg.extraConfig;
};
wrappedNeovim' = pkgs.wrapNeovimUnstable cfg.package (neovimConfig // {
wrapperArgs =
(lib.escapeShellArgs (neovimConfig.wrapperArgs ++ cfg.extraWrapperArgs))
+ " " + extraMakeWrapperArgs + " " + extraMakeWrapperLuaCArgs + " "
+ extraMakeWrapperLuaArgs;
wrapRc = false;
});
in mkIf cfg.enable {
programs.neovim.generatedConfigViml = neovimConfig.neovimRcContent;
@ -414,17 +421,18 @@ in {
home.sessionVariables = mkIf cfg.defaultEditor { EDITOR = "nvim"; };
home.shellAliases = mkIf cfg.vimdiffAlias { vimdiff = "nvim -d"; };
xdg.configFile =
let hasLuaConfig = hasAttr "lua" config.programs.neovim.generatedConfigs;
in mkMerge (
# writes runtime
(map (x: x.runtime) pluginsNormalized) ++ [{
"nvim/init.lua" = let
luaRcContent =
lib.optionalString (neovimConfig.neovimRcContent != "")
luaRcContent = lib.optionalString (wrappedNeovim'.initRc != "")
"vim.cmd [[source ${
pkgs.writeText "nvim-init-home-manager.vim"
neovimConfig.neovimRcContent
wrappedNeovim'.initRc
}]]" + config.programs.neovim.extraLuaConfig
+ lib.optionalString hasLuaConfig
config.programs.neovim.generatedConfigs.lua;
@ -435,17 +443,6 @@ in {
};
}]);
programs.neovim.finalPackage = pkgs.wrapNeovimUnstable cfg.package
(neovimConfig // {
wrapperArgs = (lib.escapeShellArgs
(neovimConfig.wrapperArgs ++ cfg.extraWrapperArgs)) + " "
+ 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"; };
programs.neovim.finalPackage = wrappedNeovim';
};
}

94
modules/programs/nh.nix Normal file
View file

@ -0,0 +1,94 @@
{ config, osConfig, lib, pkgs, ... }:
let
cfg = config.programs.nh;
in {
meta.maintainers = with lib.maintainers; [ johnrtitor ];
options.programs.nh = {
enable = lib.mkEnableOption "nh, yet another Nix CLI helper";
package = lib.mkPackageOption pkgs "nh" { };
flake = lib.mkOption {
type = lib.types.nullOr lib.types.path;
default = null;
description = ''
The path that will be used for the {env}`FLAKE` environment variable.
{env}`FLAKE` is used by nh as the default flake for performing actions,
like {command}`nh os switch`.
'';
};
clean = {
enable = lib.mkEnableOption ''
periodic garbage collection for user profile and nix store with nh clean
user'';
dates = lib.mkOption {
type = lib.types.singleLineStr;
default = "weekly";
description = ''
How often cleanup is performed.
The format is described in {manpage}`systemd.time(7)`.
'';
};
extraArgs = lib.mkOption {
type = lib.types.singleLineStr;
default = "";
example = "--keep 5 --keep-since 3d";
description = ''
Options given to nh clean when the service is run automatically.
See `nh clean all --help` for more information.
'';
};
};
};
config = {
warnings = lib.optionals (!(cfg.clean.enable -> !osConfig.nix.gc.automatic))
[
"programs.nh.clean.enable and nix.gc.automatic (system-wide in configuration.nix) are both enabled. Please use one or the other to avoid conflict."
];
assertions = [{
assertion = (cfg.flake != null) -> !(lib.hasSuffix ".nix" cfg.flake);
message = "nh.flake must be a directory, not a nix file";
}];
home = lib.mkIf cfg.enable {
packages = [ cfg.package ];
sessionVariables = lib.mkIf (cfg.flake != null) { FLAKE = cfg.flake; };
};
systemd.user = lib.mkIf cfg.clean.enable {
services.nh-clean = {
Unit.Description = "Nh clean (user)";
Service = {
Type = "oneshot";
ExecStart =
"exec ${lib.getExe cfg.package} clean user ${cfg.clean.extraArgs}";
Environment = "PATH=$PATH:${config.nix.package}";
};
};
timers.nh-clean = {
Unit.Description = "Run nh clean";
Timer = {
OnCalendar = cfg.clean.dates;
Persistent = true;
};
Install.WantedBy = [ "timers.target" ];
};
};
};
}

View file

@ -39,7 +39,7 @@ let
};
});
in {
meta.maintainers = [ maintainers.Philipp-M ];
meta.maintainers = [ maintainers.Philipp-M maintainers.joaquintrinanes ];
imports = [
(mkRemovedOptionModule [ "programs" "nushell" "settings" ] ''
@ -145,11 +145,24 @@ in {
};
environmentVariables = mkOption {
type = types.attrsOf types.str;
type = types.attrsOf hm.types.nushellValue;
default = { };
example = { FOO = "BAR"; };
example = literalExpression ''
{
FOO = "BAR";
LIST_VALUE = [ "foo" "bar" ];
NU_LIB_DIRS = lib.concatStringsSep ":" [ ./scripts ];
PROMPT_COMMAND = lib.hm.nushell.mkNushellInline '''{|| "> "}''';
ENV_CONVERSIONS.PATH = {
from_string = lib.hm.nushell.mkNushellInline "{|s| $s | split row (char esep) }";
to_string = lib.hm.nushell.mkNushellInline "{|v| $v | str join (char esep) }";
};
}
'';
description = ''
An attribute set that maps an environment variable to a shell interpreted string.
Environment variables to be set.
Inline values can be set with `lib.hm.nushell.mkNushellInline`.
'';
};
};
@ -173,9 +186,11 @@ in {
})
(let
envVarsStr = concatStringsSep "\n"
(mapAttrsToList (k: v: "$env.${k} = ${v}") cfg.environmentVariables);
in mkIf (cfg.envFile != null || cfg.extraEnv != "" || envVarsStr != "") {
hasEnvVars = cfg.environmentVariables != { };
envVarsStr = ''
load-env ${hm.nushell.toNushell { } cfg.environmentVariables}
'';
in mkIf (cfg.envFile != null || cfg.extraEnv != "" || hasEnvVars) {
"${configDir}/env.nu".text = mkMerge [
(mkIf (cfg.envFile != null) cfg.envFile.text)
cfg.extraEnv

View file

@ -19,6 +19,8 @@ in {
options.programs.papis = {
enable = mkEnableOption "papis";
package = mkPackageOption pkgs "papis" { };
settings = mkOption {
type = with types; attrsOf (oneOf [ bool int str ]);
default = { };
@ -84,7 +86,7 @@ in {
(", namely " + concatStringsSep "," defaultLibraries);
}];
home.packages = [ pkgs.papis ];
home.packages = [ cfg.package ];
xdg.configFile."papis/config" =
mkIf (cfg.libraries != { }) { text = generators.toINI { } settingsIni; };

View file

@ -9,7 +9,7 @@ let
aliases = {
ls = "${cfg.package}/bin/pls";
ll =
"${cfg.package}/bin/pls -d perms -d user -d group -d size -d mtime -d git";
"${cfg.package}/bin/pls -d perm -d user -d group -d size -d mtime -d git";
};
in {
@ -28,7 +28,15 @@ in {
programs.bash.shellAliases = mkIf cfg.enableAliases aliases;
programs.fish.shellAliases = mkIf cfg.enableAliases aliases;
programs.fish = mkMerge [
(mkIf (!config.programs.fish.preferAbbrs) {
shellAliases = mkIf cfg.enableAliases aliases;
})
(mkIf config.programs.fish.preferAbbrs {
shellAbbrs = mkIf cfg.enableAliases aliases;
})
];
programs.zsh.shellAliases = mkIf cfg.enableAliases aliases;
};

View file

@ -23,14 +23,13 @@ in {
default = { };
description = ''
Configuration written to {file}`$XDG_CONFIG_HOME/pqivrc`. See
{manpage}`pqiv(1)` for a list of available options. To set a
boolean flag, set the value to 1.
{manpage}`pqiv(1)` for a list of available options.
'';
example = literalExpression ''
{
options = {
lazy-load = 1;
hide-info-box = 1;
lazy-load = true;
hide-info-box = true;
background-pattern = "black";
thumbnail-size = "256x256";
command-1 = "thunar";
@ -68,7 +67,15 @@ in {
xdg.configFile."pqivrc" =
mkIf (cfg.settings != { } && cfg.extraConfig != "") {
text = lib.concatLines [
(generators.toINI { } cfg.settings)
(generators.toINI {
mkKeyValue = key: value:
let
value' = if isBool value then
(if value then "1" else "0")
else
toString value;
in "${key} = ${value'}";
} cfg.settings)
cfg.extraConfig
];
};

View file

@ -1,12 +1,12 @@
{ config, lib, pkgs, ... }:
let
inherit (lib)
mkEnableOption mkPackageOption mkOption types literalExpression mkIf;
inherit (lib) mkEnableOption mkPackageOption mkOption literalExpression mkIf;
inherit (lib.types) listOf;
cfg = config.programs.spotify-player;
tomlFormat = pkgs.formats.toml { };
tomlType = tomlFormat.type;
in {
meta.maintainers = with lib.hm.maintainers; [ diniamo ];
@ -16,7 +16,7 @@ in {
package = mkPackageOption pkgs "spotify-player" { };
settings = mkOption {
type = tomlFormat.type;
type = tomlType;
default = { };
example = literalExpression ''
{
@ -43,7 +43,7 @@ in {
};
themes = mkOption {
type = types.listOf tomlFormat.type;
type = listOf tomlType;
default = [ ];
example = literalExpression ''
[
@ -94,7 +94,7 @@ in {
};
keymaps = mkOption {
type = types.listOf tomlFormat.type;
type = listOf tomlType;
default = [ ];
example = literalExpression ''
[
@ -129,6 +129,36 @@ in {
for the full list of options.
'';
};
actions = mkOption {
type = listOf tomlType;
default = [ ];
example = literalExpression ''
[
{
action = "GoToArtist";
key_sequence = "g A";
}
{
action = "GoToAlbum";
key_sequence = "g B";
target = "PlayingTrack";
}
{
action = "ToggleLiked";
key_sequence = "C-l";
}
]
'';
description = ''
Configuration written to the `actions` field of
{file}`$XDG_CONFIG_HOME/spotify-player/keymap.toml`.
See
<https://github.com/aome510/spotify-player/blob/master/docs/config.md#actions>
for the full list of options.
'';
};
};
config = mkIf cfg.enable {
@ -146,7 +176,7 @@ in {
"spotify-player/keymap.toml" = mkIf (cfg.keymaps != [ ]) {
source = tomlFormat.generate "spotify-player-keymap" {
inherit (cfg) keymaps;
inherit (cfg) keymaps actions;
};
};
};

View file

@ -85,7 +85,8 @@ in {
'';
};
package = mkPackageOption pkgs "taskwarrior" { };
package =
mkPackageOption pkgs "taskwarrior" { example = "pkgs.taskwarrior3"; };
};
};

View file

@ -7,6 +7,11 @@ let
cfg = config.programs.thunderbird;
thunderbirdJson = types.attrsOf (pkgs.formats.json { }).type // {
description =
"Thunderbird preference (int, bool, string, and also attrs, list, float as a JSON string)";
};
enabledAccounts = attrValues
(filterAttrs (_: a: a.thunderbird.enable) config.accounts.email.accounts);
@ -161,11 +166,21 @@ in {
};
settings = mkOption {
type = with types; attrsOf (oneOf [ bool int str ]);
type = thunderbirdJson;
default = { };
example = literalExpression ''
{
"mail.spellcheck.inline" = false;
"mailnews.database.global.views.global.columns" = {
selectCol = {
visible = false;
ordinal = 1;
};
threadCol = {
visible = true;
ordinal = 2;
};
};
}
'';
description = ''
@ -210,13 +225,27 @@ in {
Extra preferences to add to {file}`user.js`.
'';
};
search = mkOption {
type = types.submodule (args:
import ./firefox/profiles/search.nix {
inherit (args) config;
inherit lib pkgs;
appName = "Thunderbird";
modulePath =
[ "programs" "thunderbird" "profiles" name "search" ];
profilePath = name;
});
default = { };
description = "Declarative search engine configuration.";
};
};
}));
description = "Attribute set of Thunderbird profiles.";
};
settings = mkOption {
type = with types; attrsOf (oneOf [ bool int str ]);
type = thunderbirdJson;
default = { };
example = literalExpression ''
{
@ -378,6 +407,13 @@ in {
] ++ (map (a: toThunderbirdAccount a profile) accounts)))
profile.extraConfig;
};
"${thunderbirdProfilesPath}/${name}/search.json.mozlz4" =
mkIf (profile.search.enable) {
enable = profile.search.enable;
force = profile.search.force;
source = profile.search.file;
};
}));
};
}

33
modules/programs/vifm.nix Normal file
View file

@ -0,0 +1,33 @@
{ config, lib, pkgs, ... }:
let
inherit (lib) mkIf mkOption types;
cfg = config.programs.vifm;
in {
meta.maintainers = [ lib.hm.maintainers.aabccd021 ];
options.programs.vifm = {
enable = lib.mkEnableOption "vifm, a Vim-like file manager";
package = lib.mkPackageOption pkgs "vifm" { };
extraConfig = mkOption {
type = types.lines;
default = "";
example = "mark h ~/";
description = ''
Extra lines added to the {file}`$XDG_CONFIG_HOME/vifm/vifmrc` file.
'';
};
};
config = mkIf cfg.enable {
home.packages = [ cfg.package ];
xdg.configFile."vifm/vifmrc" =
mkIf (cfg.extraConfig != "") { text = cfg.extraConfig; };
};
}

View file

@ -14,7 +14,7 @@ let
config.xdg.configHome;
in {
meta.maintainers = [ maintainers.polykernel ];
meta.maintainers = [ ];
options.programs.watson = {
enable = mkEnableOption "watson, a wonderful CLI to track your time";

View file

@ -100,7 +100,7 @@ in {
-- Generated by Home Manager.
-- See https://wezfurlong.org/wezterm/
local wezterm = require 'wezterm';
local wezterm = require 'wezterm'
${cfg.extraConfig}
'';

View file

@ -56,13 +56,21 @@ in {
'';
};
enableBashIntegration = mkEnableOption "Bash integration";
enableBashIntegration = mkEnableOption "Bash integration" // {
default = true;
};
enableZshIntegration = mkEnableOption "Zsh integration";
enableZshIntegration = mkEnableOption "Zsh integration" // {
default = true;
};
enableFishIntegration = mkEnableOption "Fish integration";
enableFishIntegration = mkEnableOption "Fish integration" // {
default = true;
};
enableNushellIntegration = mkEnableOption "Nushell integration";
enableNushellIntegration = mkEnableOption "Nushell integration" // {
default = true;
};
keymap = mkOption {
type = tomlFormat.type;

View file

@ -77,16 +77,26 @@ in {
})"
'';
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;
programs.fish = mkMerge [
{
shellInit = mkIf cfg.enableFishIntegration ''
source (${pkgs.z-lua}/bin/z --init fish ${
concatStringsSep " " cfg.options
} | psub)
'';
}
(mkIf (!config.programs.fish.preferAbbrs) {
shellAliases = mkIf cfg.enableAliases aliases;
})
(mkIf config.programs.fish.preferAbbrs {
shellAbbrs = mkIf cfg.enableAliases aliases;
})
];
};
}

View file

@ -31,7 +31,7 @@ in {
options = mkOption {
default = { };
type = with types; attrsOf (either str (either bool int));
type = with types; attrsOf (oneOf [ str bool int float ]);
description = ''
Add {option}`:set` command options to zathura and make
them permanent. See

View file

@ -0,0 +1,89 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.programs.zed-editor;
jsonFormat = pkgs.formats.json { };
mergedSettings = cfg.userSettings // {
# this part by @cmacrae
auto_install_extensions = lib.genAttrs cfg.extensions (_: true);
};
in {
meta.maintainers = [ hm.maintainers.libewa ];
options = {
# TODO: add vscode option parity (installing extensions, configuring
# keybinds with nix etc.)
programs.zed-editor = {
enable = mkEnableOption
"Zed, the high performance, multiplayer code editor from the creators of Atom and Tree-sitter";
package = mkPackageOption pkgs "zed-editor" { };
userSettings = mkOption {
type = jsonFormat.type;
default = { };
example = literalExpression ''
{
features = {
copilot = false;
};
telemetry = {
metrics = false;
};
vim_mode = false;
ui_font_size = 16;
buffer_font_size = 16;
}
'';
description = ''
Configuration written to Zed's {file}`settings.json`.
'';
};
userKeymaps = mkOption {
type = jsonFormat.type;
default = { };
example = literalExpression ''
[
{
context = "Workspace";
bindings = {
ctrl-shift-t = "workspace::NewTerminal";
};
};
]
'';
description = ''
Configuration written to Zed's {file}`keymap.json`.
'';
};
extensions = mkOption {
type = types.listOf types.str;
default = [ ];
example = literalExpression ''
[ "swift" "nix" "xy-zed" ]
'';
description = ''
A list of the extensions Zed should install on startup.
Use the name of a repository in the [extension list](https://github.com/zed-industries/extensions/tree/main/extensions).
'';
};
};
};
config = mkIf cfg.enable {
home.packages = [ cfg.package ];
xdg.configFile."zed/settings.json" = (mkIf (mergedSettings != { }) {
source = jsonFormat.generate "zed-user-settings" mergedSettings;
});
xdg.configFile."zed/keymap.json" = (mkIf (cfg.userKeymaps != { }) {
source = jsonFormat.generate "zed-user-keymaps" cfg.userKeymaps;
});
};
}

View file

@ -26,9 +26,9 @@ in {
options = mkOption {
type = types.listOf types.str;
default = [ ];
example = [ "--no-aliases" ];
example = [ "--no-cmd" ];
description = ''
List of options to pass to zoxide.
List of options to pass to zoxide init.
'';
};
@ -68,9 +68,9 @@ in {
config = mkIf cfg.enable {
home.packages = [ cfg.package ];
programs.bash.initExtra = mkIf cfg.enableBashIntegration ''
programs.bash.initExtra = mkIf cfg.enableBashIntegration (mkOrder 150 ''
eval "$(${cfg.package}/bin/zoxide init bash ${cfgOptions})"
'';
'');
programs.zsh.initExtra = mkIf cfg.enableZshIntegration ''
eval "$(${cfg.package}/bin/zoxide init zsh ${cfgOptions})"

View file

@ -34,6 +34,21 @@ let
historyModule = types.submodule ({ config, ... }: {
options = {
append = mkOption {
type = types.bool;
default = false;
description = ''
If set, zsh sessions will append their history list to the history
file, rather than replace it. Thus, multiple parallel zsh sessions
will all have the new entries from their history lists added to the
history file, in the order that they exit.
This file will still be periodically re-written to trim it when the
number of lines grows 20% beyond the value specified by
`programs.zsh.history.save`.
'';
};
size = mkOption {
type = types.int;
default = 10000;
@ -398,6 +413,22 @@ in
{manpage}`zshzle(1)` for syntax.
'';
};
strategy = mkOption {
type = types.listOf (types.enum [ "history" "completion" "match_prev_cmd" ]);
default = [ "history" ];
description = ''
`ZSH_AUTOSUGGEST_STRATEGY` is an array that specifies how suggestions should be generated.
The strategies in the array are tried successively until a suggestion is found.
There are currently three built-in strategies to choose from:
- `history`: Chooses the most recent match from history.
- `completion`: Chooses a suggestion based on what tab-completion would suggest. (requires `zpty` module)
- `match_prev_cmd`: Like `history`, but chooses the most recent match whose preceding history item matches
the most recently executed command. Note that this strategy won't work as expected with ZSH options that
don't preserve the history order such as `HIST_IGNORE_ALL_DUPS` or `HIST_EXPIRE_DUPS_FIRST`.
'';
};
};
history = mkOption {
@ -610,6 +641,7 @@ in
(optionalString cfg.autosuggestion.enable ''
source ${pkgs.zsh-autosuggestions}/share/zsh-autosuggestions/zsh-autosuggestions.zsh
ZSH_AUTOSUGGEST_STRATEGY=(${concatStringsSep " " cfg.autosuggestion.strategy})
'')
(optionalString (cfg.autosuggestion.enable && cfg.autosuggestion.highlight != null) ''
ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE="${cfg.autosuggestion.highlight}"
@ -652,6 +684,7 @@ in
mkdir -p "$(dirname "$HISTFILE")"
setopt HIST_FCNTL_LOCK
${if cfg.history.append then "setopt" else "unsetopt"} APPEND_HISTORY
${if cfg.history.ignoreDups then "setopt" else "unsetopt"} HIST_IGNORE_DUPS
${if cfg.history.ignoreAllDups then "setopt" else "unsetopt"} HIST_IGNORE_ALL_DUPS
${if cfg.history.ignoreSpace then "setopt" else "unsetopt"} HIST_IGNORE_SPACE

View file

@ -46,7 +46,6 @@ in {
# Lower CPU and I/O priority:
Nice = 19;
CPUSchedulingPolicy = "batch";
IOSchedulingClass = "best-effort";
IOSchedulingPriority = 7;
IOWeight = 100;

View file

@ -65,9 +65,8 @@ in {
};
configFile = mkOption {
type = with types; either str path;
default = "${config.xdg.configHome}/dunst/dunstrc";
defaultText = "$XDG_CONFIG_HOME/dunst/dunstrc";
type = with types; nullOr (either str path);
default = null;
description = ''
Path to the configuration file read by dunst.
@ -170,7 +169,7 @@ in {
"stock"
];
mkPath = { basePath, theme, category }:
mkPath = { basePath, theme, category, }:
"${basePath}/share/icons/${theme.name}/${theme.size}/${category}";
in concatMapStringsSep ":" mkPath (cartesianProduct {
basePath = basePaths;
@ -188,7 +187,9 @@ in {
Service = {
Type = "dbus";
BusName = "org.freedesktop.Notifications";
ExecStart = "${cfg.package}/bin/dunst -config ${cfg.configFile}";
ExecStart = escapeShellArgs ([ "${cfg.package}/bin/dunst" ] ++
# Using `-config` breaks dunst's drop-ins, so only use it when an alternative path is set
optionals (cfg.configFile != null) [ "-config" cfg.configFile ]);
Environment = optionalString (cfg.waylandDisplay != "")
"WAYLAND_DISPLAY=${cfg.waylandDisplay}";
};

View file

@ -121,9 +121,9 @@ in {
systemd.user.services.espanso = {
Unit = { Description = "Espanso: cross platform text expander in Rust"; };
Service = {
Type = "exec";
ExecStart = "${cfg.package}/bin/espanso daemon";
ExecStart = "${cfg.package}/bin/espanso launcher";
Restart = "on-failure";
RestartSec = 3;
};
Install = { WantedBy = [ "default.target" ]; };
};

View file

@ -24,7 +24,7 @@ in {
};
settings = mkOption {
type = iniFormat.type;
inherit (iniFormat) type;
default = { };
example = {
General = {
@ -64,7 +64,7 @@ in {
Install = { WantedBy = [ "graphical-session.target" ]; };
Service = {
Environment = "PATH=${config.home.profileDirectory}/bin";
Environment = [ "PATH=${config.home.profileDirectory}/bin" ];
ExecStart = "${cfg.package}/bin/flameshot";
Restart = "on-abort";

View file

@ -9,7 +9,7 @@ let
iniFormat = pkgs.formats.ini { };
in {
meta.maintainers = with maintainers; [ polykernel ];
meta.maintainers = [ ];
options = {
services.fnott = {

View file

@ -16,9 +16,9 @@ let
"PATH=${
lib.makeBinPath (with pkgs; [ openssh git ] ++ repo.extraPackages)
}"
"GIT_SYNC_DIRECTORY=${repo.path}"
"GIT_SYNC_DIRECTORY=${strings.escapeShellArg repo.path}"
"GIT_SYNC_COMMAND=${cfg.package}/bin/git-sync"
"GIT_SYNC_REPOSITORY=${repo.uri}"
"GIT_SYNC_REPOSITORY=${strings.escapeShellArg repo.uri}"
"GIT_SYNC_INTERVAL=${toString repo.interval}"
];
ExecStart = "${cfg.package}/bin/git-sync-on-inotify";
@ -112,6 +112,15 @@ in {
description = ''
The repositories that should be synchronized.
'';
example = literalExpression ''
{
xyz = {
path = "''${config.home.homeDirectory}/foo/home-manager";
uri = "git@github.com:nix-community/home-manager.git";
interval = 1000;
};
}
'';
};
};
};

View file

@ -49,7 +49,7 @@ in {
args = concatStringsSep " " ([ "--start" "--foreground" ]
++ optional (cfg.components != [ ])
("--components=" + concatStringsSep "," cfg.components));
in "${pkgs.gnome.gnome-keyring}/bin/gnome-keyring-daemon ${args}";
in "${pkgs.gnome-keyring}/bin/gnome-keyring-daemon ${args}";
Restart = "on-abort";
};

View file

@ -18,6 +18,10 @@ let
export GPG_TTY
'' + optionalString cfg.enableSshSupport gpgSshSupportStr;
gpgZshInitStr = ''
export GPG_TTY=$TTY
'' + optionalString cfg.enableSshSupport gpgSshSupportStr;
gpgFishInitStr = ''
set -gx GPG_TTY (tty)
'' + optionalString cfg.enableSshSupport gpgSshSupportStr;
@ -30,7 +34,7 @@ let
$env.SSH_AUTH_SOCK = ($env.SSH_AUTH_SOCK? | default (${gpgPkg}/bin/gpgconf --list-dirs agent-ssh-socket))
'';
# mimic `gpgconf` output for use in `systemd` unit definitions.
# mimic `gpgconf` output for use in the service 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
@ -38,10 +42,14 @@ let
let
hash =
substring 0 24 (hexStringToBase32 (builtins.hashString "sha1" homedir));
in if homedir == options.programs.gpg.homedir.default then
"%t/gnupg/${dir}"
subdir = if homedir == options.programs.gpg.homedir.default then
"${dir}"
else
"%t/gnupg/d.${hash}/${dir}";
"d.${hash}/${dir}";
in if pkgs.stdenv.isDarwin then
"/private/var/run/org.nix-community.home.gpg-agent/${subdir}"
else
"%t/gnupg/${subdir}";
# Act like `xxd -r -p | base32` but with z-base-32 alphabet and no trailing padding.
# Written in Nix for purity.
@ -77,6 +85,32 @@ let
};
in hexString: (foldl' go initState (stringToCharacters hexString)).ret;
# Systemd socket unit generator.
mkSocket = { desc, docs, stream, fdName }: {
Unit = {
Description = desc;
Documentation = docs;
};
Socket = {
ListenStream = gpgconf "${stream}";
FileDescriptorName = "${fdName}";
Service = "gpg-agent.service";
SocketMode = "0600";
DirectoryMode = "0700";
};
Install = { WantedBy = [ "sockets.target" ]; };
};
# Launchd agent socket generator.
mkAgentSock = name: {
SockType = "stream";
SockPathName = gpgconf name;
SockPathMode =
384; # Property lists don't support octal literals (0600 = 384).
};
in {
meta.maintainers = [ maintainers.rycee ];
@ -257,7 +291,7 @@ in {
'';
programs.bash.initExtra = mkIf cfg.enableBashIntegration gpgInitStr;
programs.zsh.initExtra = mkIf cfg.enableZshIntegration gpgInitStr;
programs.zsh.initExtra = mkIf cfg.enableZshIntegration gpgZshInitStr;
programs.fish.interactiveShellInit =
mkIf cfg.enableFishIntegration gpgFishInitStr;
@ -272,17 +306,8 @@ in {
'') cfg.sshKeys;
})
# The systemd units below are direct translations of the
# descriptions in the
#
# ${gpgPkg}/share/doc/gnupg/examples/systemd-user
#
# directory.
{
assertions = [
(hm.assertions.assertPlatform "services.gpg-agent" pkgs platforms.linux)
];
(mkMerge [
(mkIf pkgs.stdenv.isLinux {
systemd.user.services.gpg-agent = {
Unit = {
Description = "GnuPG cryptographic agent and passphrase cache";
@ -301,61 +326,54 @@ in {
};
};
systemd.user.sockets.gpg-agent = {
Unit = {
Description = "GnuPG cryptographic agent and passphrase cache";
Documentation = "man:gpg-agent(1)";
systemd.user.sockets.gpg-agent = mkSocket {
desc = "GnuPG cryptographic agent and passphrase cache";
docs = "man:gpg-agent(1)";
stream = "S.gpg-agent";
fdName = "std";
};
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 =
systemd.user.sockets.gpg-agent-ssh = mkIf cfg.enableSshSupport
(mkSocket ({
desc = "GnuPG cryptographic agent (ssh-agent emulation)";
docs =
"man:gpg-agent(1) man:ssh-add(1) man:ssh-agent(1) man:ssh(1)";
};
stream = "S.gpg-agent.ssh";
fdName = "ssh";
}));
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 =
systemd.user.sockets.gpg-agent-extra = mkIf cfg.enableExtraSocket
(mkSocket {
desc =
"GnuPG cryptographic agent and passphrase cache (restricted)";
Documentation = "man:gpg-agent(1) man:ssh(1)";
};
docs = "man:gpg-agent(1) man:ssh(1)";
stream = "S.gpg-agent.extra";
fdName = "extra";
});
})
Socket = {
ListenStream = gpgconf "S.gpg-agent.extra";
FileDescriptorName = "extra";
Service = "gpg-agent.service";
SocketMode = "0600";
DirectoryMode = "0700";
(mkIf pkgs.stdenv.isDarwin {
launchd.agents.gpg-agent = {
enable = true;
config = {
ProgramArguments = [ "${gpgPkg}/bin/gpg-agent" "--supervised" ]
++ optional cfg.verbose "--verbose";
EnvironmentVariables = { GNUPGHOME = homedir; };
KeepAlive = {
Crashed = true;
SuccessfulExit = false;
};
ProcessType = "Background";
RunAtLoad = cfg.enableSshSupport;
Sockets = {
Agent = mkAgentSock "S.gpg-agent";
Ssh = mkIf cfg.enableSshSupport (mkAgentSock "S.gpg-agent.ssh");
Extra =
mkIf cfg.enableExtraSocket (mkAgentSock "S.gpg-agent.extra");
};
};
Install = { WantedBy = [ "sockets.target" ]; };
};
})
])
]);
}

View file

@ -88,7 +88,7 @@ in {
ExecStart = "${pkgs.grobi}/bin/grobi watch -v";
Restart = "always";
RestartSec = "2s";
Environment = "PATH=${pkgs.xorg.xrandr}/bin:${pkgs.bash}/bin";
Environment = [ "PATH=${pkgs.xorg.xrandr}/bin:${pkgs.bash}/bin" ];
};
Install = { WantedBy = [ "graphical-session.target" ]; };

View file

@ -72,7 +72,7 @@ in {
Install = { WantedBy = [ "default.target" ]; };
Service = {
Environment = "PATH=${makeBinPath [ pkgs.mercurial pkgs.git ]}";
Environment = [ "PATH=${makeBinPath [ pkgs.mercurial pkgs.git ]}" ];
ExecStart =
"${pkgs.hound}/bin/houndd ${concatStringsSep " " houndOptions}";
};

Some files were not shown because too many files have changed in this diff Show more