diff --git a/format b/format index 4f46c7b9e..51ee63b88 100755 --- a/format +++ b/format @@ -23,23 +23,9 @@ for arg do esac done -# The excludes are for files touched by open pull requests and we want -# to avoid merge conflicts. -excludes=( - modules/files.nix - modules/home-environment.nix - modules/programs/zsh.nix -) - -exclude_args=() -for e in "${excludes[@]}"; do - exclude_args+=(-e "$e") -done - git_root=$(git rev-parse --show-toplevel) git ls-files -z --cached --others --full-name -- "${files[@]}" | grep -z '\.nix$' | - grep -z -v "${exclude_args[@]}" | sed -z "s|^|$git_root/|" | xargs -0 nixfmt "${nixfmt_args[@]}" diff --git a/modules/files.nix b/modules/files.nix index 59e9c2578..d5109c163 100644 --- a/modules/files.nix +++ b/modules/files.nix @@ -8,26 +8,26 @@ let homeDirectory = config.home.homeDirectory; - fileType = (import lib/file-type.nix { - inherit homeDirectory lib pkgs; - }).fileType; + fileType = + (import lib/file-type.nix { inherit homeDirectory lib pkgs; }).fileType; sourceStorePath = file: let sourcePath = toString file.source; sourceName = config.lib.strings.storeFileName (baseNameOf sourcePath); - in - if builtins.hasContext sourcePath - then file.source - else builtins.path { path = file.source; name = sourceName; }; + in if builtins.hasContext sourcePath then + file.source + else + builtins.path { + path = file.source; + name = sourceName; + }; -in - -{ +in { options = { home.file = mkOption { description = "Attribute set of files to link into the user home."; - default = {}; + default = { }; type = fileType "home.file" "{env}`HOME`" homeDirectory; }; @@ -39,16 +39,14 @@ in }; config = { - assertions = [( - let - dups = - attrNames - (filterAttrs (n: v: v > 1) - (foldAttrs (acc: v: acc + v) 0 + assertions = [ + (let + dups = attrNames (filterAttrs (n: v: v > 1) + (foldAttrs (acc: v: acc + v) 0 (mapAttrsToList (n: v: { ${v.target} = 1; }) cfg))); dupsStr = concatStringsSep ", " dups; in { - assertion = dups == []; + assertion = dups == [ ]; message = '' Conflicting managed target files: ${dupsStr} @@ -65,19 +63,17 @@ in let pathStr = toString path; name = hm.strings.storeFileName (baseNameOf pathStr); - in - pkgs.runCommandLocal name {} ''ln -s ${escapeShellArg pathStr} $out''; + in pkgs.runCommandLocal name { } "ln -s ${escapeShellArg pathStr} $out"; # This verifies that the links we are about to create will not # overwrite an existing file. - home.activation.checkLinkTargets = hm.dag.entryBefore ["writeBoundary"] ( - let + home.activation.checkLinkTargets = hm.dag.entryBefore [ "writeBoundary" ] + (let # Paths that should be forcibly overwritten by Home Manager. # Caveat emptor! forcedPaths = concatMapStringsSep " " (p: ''"$HOME"/${escapeShellArg p}'') - (mapAttrsToList (n: v: v.target) - (filterAttrs (n: v: v.force) cfg)); + (mapAttrsToList (n: v: v.target) (filterAttrs (n: v: v.force) cfg)); storeDir = escapeShellArg builtins.storeDir; @@ -87,8 +83,7 @@ in inherit (config.lib.bash) initHomeManagerLib; inherit forcedPaths storeDir; }; - in - '' + in '' function checkNewGenCollision() { local newGenFiles newGenFiles="$(readlink -e "$newGenPath/home-files")" @@ -97,8 +92,7 @@ in } checkNewGenCollision || exit 1 - '' - ); + ''); # This activation script will # @@ -121,129 +115,127 @@ in # and a failure during the intermediate state FA ∩ FB will not # result in lost links because this set of links are in both the # source and target generation. - home.activation.linkGeneration = hm.dag.entryAfter ["writeBoundary"] ( - let - link = pkgs.writeShellScript "link" '' - ${config.lib.bash.initHomeManagerLib} + home.activation.linkGeneration = hm.dag.entryAfter [ "writeBoundary" ] (let + link = pkgs.writeShellScript "link" '' + ${config.lib.bash.initHomeManagerLib} - newGenFiles="$1" - shift - for sourcePath in "$@" ; do - relativePath="''${sourcePath#$newGenFiles/}" - targetPath="$HOME/$relativePath" - if [[ -e "$targetPath" && ! -L "$targetPath" && -n "$HOME_MANAGER_BACKUP_EXT" ]] ; then - # The target exists, back it up - backup="$targetPath.$HOME_MANAGER_BACKUP_EXT" - run mv $VERBOSE_ARG "$targetPath" "$backup" || errorEcho "Moving '$targetPath' failed!" - fi - - if [[ -e "$targetPath" && ! -L "$targetPath" ]] && cmp -s "$sourcePath" "$targetPath" ; then - # The target exists but is identical – don't do anything. - verboseEcho "Skipping '$targetPath' as it is identical to '$sourcePath'" - else - # Place that symlink, --force - # This can still fail if the target is a directory, in which case we bail out. - run mkdir -p $VERBOSE_ARG "$(dirname "$targetPath")" - run ln -Tsf $VERBOSE_ARG "$sourcePath" "$targetPath" || exit 1 - fi - done - ''; - - cleanup = pkgs.writeShellScript "cleanup" '' - ${config.lib.bash.initHomeManagerLib} - - # A symbolic link whose target path matches this pattern will be - # considered part of a Home Manager generation. - homeFilePattern="$(readlink -e ${escapeShellArg builtins.storeDir})/*-home-manager-files/*" - - newGenFiles="$1" - shift 1 - for relativePath in "$@" ; do - targetPath="$HOME/$relativePath" - if [[ -e "$newGenFiles/$relativePath" ]] ; then - verboseEcho "Checking $targetPath: exists" - elif [[ ! "$(readlink "$targetPath")" == $homeFilePattern ]] ; then - warnEcho "Path '$targetPath' does not link into a Home Manager generation. Skipping delete." - else - verboseEcho "Checking $targetPath: gone (deleting)" - run rm $VERBOSE_ARG "$targetPath" - - # Recursively delete empty parent directories. - targetDir="$(dirname "$relativePath")" - if [[ "$targetDir" != "." ]] ; then - pushd "$HOME" > /dev/null - - # Call rmdir with a relative path excluding $HOME. - # Otherwise, it might try to delete $HOME and exit - # with a permission error. - run rmdir $VERBOSE_ARG \ - -p --ignore-fail-on-non-empty \ - "$targetDir" - - popd > /dev/null - fi - fi - done - ''; - in - '' - function linkNewGen() { - _i "Creating home file links in %s" "$HOME" - - local newGenFiles - newGenFiles="$(readlink -e "$newGenPath/home-files")" - find "$newGenFiles" \( -type f -or -type l \) \ - -exec bash ${link} "$newGenFiles" {} + - } - - function cleanOldGen() { - if [[ ! -v oldGenPath || ! -e "$oldGenPath/home-files" ]] ; then - return - fi - - _i "Cleaning up orphan links from %s" "$HOME" - - local newGenFiles oldGenFiles - newGenFiles="$(readlink -e "$newGenPath/home-files")" - oldGenFiles="$(readlink -e "$oldGenPath/home-files")" - - # Apply the cleanup script on each leaf in the old - # generation. The find command below will print the - # relative path of the entry. - find "$oldGenFiles" '(' -type f -or -type l ')' -printf '%P\0' \ - | xargs -0 bash ${cleanup} "$newGenFiles" - } - - cleanOldGen - - if [[ ! -v oldGenPath || "$oldGenPath" != "$newGenPath" ]] ; then - _i "Creating profile generation %s" $newGenNum - if [[ -e "$genProfilePath"/manifest.json ]] ; then - # Remove all packages from "$genProfilePath" - # `nix profile remove '.*' --profile "$genProfilePath"` was not working, so here is a workaround: - nix profile list --profile "$genProfilePath" \ - | cut -d ' ' -f 4 \ - | xargs -rt $DRY_RUN_CMD nix profile remove $VERBOSE_ARG --profile "$genProfilePath" - run nix profile install $VERBOSE_ARG --profile "$genProfilePath" "$newGenPath" - else - run nix-env $VERBOSE_ARG --profile "$genProfilePath" --set "$newGenPath" - fi - - run --quiet nix-store --realise "$newGenPath" --add-root "$newGenGcPath" --indirect - if [[ -e "$legacyGenGcPath" ]]; then - run rm $VERBOSE_ARG "$legacyGenGcPath" - fi - else - _i "No change so reusing latest profile generation %s" "$oldGenNum" + newGenFiles="$1" + shift + for sourcePath in "$@" ; do + relativePath="''${sourcePath#$newGenFiles/}" + targetPath="$HOME/$relativePath" + if [[ -e "$targetPath" && ! -L "$targetPath" && -n "$HOME_MANAGER_BACKUP_EXT" ]] ; then + # The target exists, back it up + backup="$targetPath.$HOME_MANAGER_BACKUP_EXT" + run mv $VERBOSE_ARG "$targetPath" "$backup" || errorEcho "Moving '$targetPath' failed!" fi - linkNewGen - '' - ); + if [[ -e "$targetPath" && ! -L "$targetPath" ]] && cmp -s "$sourcePath" "$targetPath" ; then + # The target exists but is identical – don't do anything. + verboseEcho "Skipping '$targetPath' as it is identical to '$sourcePath'" + else + # Place that symlink, --force + # This can still fail if the target is a directory, in which case we bail out. + run mkdir -p $VERBOSE_ARG "$(dirname "$targetPath")" + run ln -Tsf $VERBOSE_ARG "$sourcePath" "$targetPath" || exit 1 + fi + done + ''; - home.activation.checkFilesChanged = hm.dag.entryBefore ["linkGeneration"] ( - let - homeDirArg = escapeShellArg homeDirectory; + cleanup = pkgs.writeShellScript "cleanup" '' + ${config.lib.bash.initHomeManagerLib} + + # A symbolic link whose target path matches this pattern will be + # considered part of a Home Manager generation. + homeFilePattern="$(readlink -e ${ + escapeShellArg builtins.storeDir + })/*-home-manager-files/*" + + newGenFiles="$1" + shift 1 + for relativePath in "$@" ; do + targetPath="$HOME/$relativePath" + if [[ -e "$newGenFiles/$relativePath" ]] ; then + verboseEcho "Checking $targetPath: exists" + elif [[ ! "$(readlink "$targetPath")" == $homeFilePattern ]] ; then + warnEcho "Path '$targetPath' does not link into a Home Manager generation. Skipping delete." + else + verboseEcho "Checking $targetPath: gone (deleting)" + run rm $VERBOSE_ARG "$targetPath" + + # Recursively delete empty parent directories. + targetDir="$(dirname "$relativePath")" + if [[ "$targetDir" != "." ]] ; then + pushd "$HOME" > /dev/null + + # Call rmdir with a relative path excluding $HOME. + # Otherwise, it might try to delete $HOME and exit + # with a permission error. + run rmdir $VERBOSE_ARG \ + -p --ignore-fail-on-non-empty \ + "$targetDir" + + popd > /dev/null + fi + fi + done + ''; + in '' + function linkNewGen() { + _i "Creating home file links in %s" "$HOME" + + local newGenFiles + newGenFiles="$(readlink -e "$newGenPath/home-files")" + find "$newGenFiles" \( -type f -or -type l \) \ + -exec bash ${link} "$newGenFiles" {} + + } + + function cleanOldGen() { + if [[ ! -v oldGenPath || ! -e "$oldGenPath/home-files" ]] ; then + return + fi + + _i "Cleaning up orphan links from %s" "$HOME" + + local newGenFiles oldGenFiles + newGenFiles="$(readlink -e "$newGenPath/home-files")" + oldGenFiles="$(readlink -e "$oldGenPath/home-files")" + + # Apply the cleanup script on each leaf in the old + # generation. The find command below will print the + # relative path of the entry. + find "$oldGenFiles" '(' -type f -or -type l ')' -printf '%P\0' \ + | xargs -0 bash ${cleanup} "$newGenFiles" + } + + cleanOldGen + + if [[ ! -v oldGenPath || "$oldGenPath" != "$newGenPath" ]] ; then + _i "Creating profile generation %s" $newGenNum + if [[ -e "$genProfilePath"/manifest.json ]] ; then + # Remove all packages from "$genProfilePath" + # `nix profile remove '.*' --profile "$genProfilePath"` was not working, so here is a workaround: + nix profile list --profile "$genProfilePath" \ + | cut -d ' ' -f 4 \ + | xargs -rt $DRY_RUN_CMD nix profile remove $VERBOSE_ARG --profile "$genProfilePath" + run nix profile install $VERBOSE_ARG --profile "$genProfilePath" "$newGenPath" + else + run nix-env $VERBOSE_ARG --profile "$genProfilePath" --set "$newGenPath" + fi + + run --quiet nix-store --realise "$newGenPath" --add-root "$newGenGcPath" --indirect + if [[ -e "$legacyGenGcPath" ]]; then + run rm $VERBOSE_ARG "$legacyGenGcPath" + fi + else + _i "No change so reusing latest profile generation %s" "$oldGenNum" + fi + + linkNewGen + ''); + + home.activation.checkFilesChanged = hm.dag.entryBefore [ "linkGeneration" ] + (let homeDirArg = escapeShellArg homeDirectory; in '' function _cmp() { if [[ -d $1 && -d $2 ]]; then @@ -261,14 +253,12 @@ in _cmp ${sourceArg} ${homeDirArg}/${targetArg} \ && changedFiles[${targetArg}]=0 \ || changedFiles[${targetArg}]=1 - '') (filter (v: v.onChange != "") (attrValues cfg)) - + '' - unset -f _cmp - '' - ); + '') (filter (v: v.onChange != "") (attrValues cfg)) + '' + unset -f _cmp + ''); - home.activation.onFilesChange = hm.dag.entryAfter ["linkGeneration"] ( - concatMapStrings (v: '' + home.activation.onFilesChange = hm.dag.entryAfter [ "linkGeneration" ] + (concatMapStrings (v: '' if (( ''${changedFiles[${escapeShellArg v.target}]} == 1 )); then if [[ -v DRY_RUN || -v VERBOSE ]]; then echo "Running onChange hook for" ${escapeShellArg v.target} @@ -277,90 +267,83 @@ in ${v.onChange} fi fi - '') (filter (v: v.onChange != "") (attrValues cfg)) - ); + '') (filter (v: v.onChange != "") (attrValues cfg))); # Symlink directories and files that have the right execute bit. # Copy files that need their execute bit changed. - home-files = pkgs.runCommandLocal - "home-manager-files" - { - nativeBuildInputs = [ pkgs.xorg.lndir ]; - } - ('' - mkdir -p $out + home-files = pkgs.runCommandLocal "home-manager-files" { + nativeBuildInputs = [ pkgs.xorg.lndir ]; + } ('' + mkdir -p $out - # Needed in case /nix is a symbolic link. - realOut="$(realpath -m "$out")" + # Needed in case /nix is a symbolic link. + realOut="$(realpath -m "$out")" - function insertFile() { - local source="$1" - local relTarget="$2" - local executable="$3" - local recursive="$4" + function insertFile() { + local source="$1" + local relTarget="$2" + local executable="$3" + local recursive="$4" - # If the target already exists then we have a collision. Note, this - # should not happen due to the assertion found in the 'files' module. - # We therefore simply log the conflict and otherwise ignore it, mainly - # to make the `files-target-config` test work as expected. - if [[ -e "$realOut/$relTarget" ]]; then - echo "File conflict for file '$relTarget'" >&2 - return - fi + # If the target already exists then we have a collision. Note, this + # should not happen due to the assertion found in the 'files' module. + # We therefore simply log the conflict and otherwise ignore it, mainly + # to make the `files-target-config` test work as expected. + if [[ -e "$realOut/$relTarget" ]]; then + echo "File conflict for file '$relTarget'" >&2 + return + fi - # Figure out the real absolute path to the target. - local target - target="$(realpath -m "$realOut/$relTarget")" + # Figure out the real absolute path to the target. + local target + target="$(realpath -m "$realOut/$relTarget")" - # Target path must be within $HOME. - if [[ ! $target == $realOut* ]] ; then - echo "Error installing file '$relTarget' outside \$HOME" >&2 - exit 1 - fi + # Target path must be within $HOME. + if [[ ! $target == $realOut* ]] ; then + echo "Error installing file '$relTarget' outside \$HOME" >&2 + exit 1 + fi - mkdir -p "$(dirname "$target")" - if [[ -d $source ]]; then - if [[ $recursive ]]; then - mkdir -p "$target" - lndir -silent "$source" "$target" - else - ln -s "$source" "$target" - fi + mkdir -p "$(dirname "$target")" + if [[ -d $source ]]; then + if [[ $recursive ]]; then + mkdir -p "$target" + lndir -silent "$source" "$target" else - [[ -x $source ]] && isExecutable=1 || isExecutable="" + ln -s "$source" "$target" + fi + else + [[ -x $source ]] && isExecutable=1 || isExecutable="" - # Link the file into the home file directory if possible, - # i.e., if the executable bit of the source is the same we - # expect for the target. Otherwise, we copy the file and - # set the executable bit to the expected value. - if [[ $executable == inherit || $isExecutable == $executable ]]; then - ln -s "$source" "$target" + # Link the file into the home file directory if possible, + # i.e., if the executable bit of the source is the same we + # expect for the target. Otherwise, we copy the file and + # set the executable bit to the expected value. + if [[ $executable == inherit || $isExecutable == $executable ]]; then + ln -s "$source" "$target" + else + cp "$source" "$target" + + if [[ $executable == inherit ]]; then + # Don't change file mode if it should match the source. + : + elif [[ $executable ]]; then + chmod +x "$target" else - cp "$source" "$target" - - if [[ $executable == inherit ]]; then - # Don't change file mode if it should match the source. - : - elif [[ $executable ]]; then - chmod +x "$target" - else - chmod -x "$target" - fi + chmod -x "$target" fi fi - } - '' + concatStrings ( - mapAttrsToList (n: v: '' - insertFile ${ - escapeShellArgs [ - (sourceStorePath v) - v.target - (if v.executable == null - then "inherit" - else toString v.executable) - (toString v.recursive) - ]} - '') cfg - )); + fi + } + '' + concatStrings (mapAttrsToList (n: v: '' + insertFile ${ + escapeShellArgs [ + (sourceStorePath v) + v.target + (if v.executable == null then "inherit" else toString v.executable) + (toString v.recursive) + ] + } + '') cfg)); }; } diff --git a/modules/home-environment.nix b/modules/home-environment.nix index 2673d1711..4c1914ee0 100644 --- a/modules/home-environment.nix +++ b/modules/home-environment.nix @@ -113,10 +113,10 @@ let options = { layout = mkOption { type = with types; nullOr str; - default = - if versionAtLeast config.home.stateVersion "19.09" - then null - else "us"; + default = if versionAtLeast config.home.stateVersion "19.09" then + null + else + "us"; defaultText = literalExpression "null"; description = '' Keyboard layout. If `null`, then the system @@ -138,8 +138,8 @@ let options = mkOption { type = types.listOf types.str; - default = []; - example = ["grp:caps_toggle" "grp_led:scroll"]; + default = [ ]; + example = [ "grp:caps_toggle" "grp_led:scroll" ]; description = '' X keyboard options; layout switching goes here. ''; @@ -148,9 +148,7 @@ let variant = mkOption { type = with types; nullOr str; default = - if versionAtLeast config.home.stateVersion "19.09" - then null - else ""; + if versionAtLeast config.home.stateVersion "19.09" then null else ""; defaultText = literalExpression "null"; example = "colemak"; description = '' @@ -164,9 +162,7 @@ let }; }; -in - -{ +in { meta.maintainers = [ maintainers.rycee ]; imports = [ @@ -217,7 +213,7 @@ in home.language = mkOption { type = languageSubModule; - default = {}; + default = { }; description = "Language configuration."; }; @@ -255,9 +251,12 @@ in }; home.sessionVariables = mkOption { - default = {}; + default = { }; type = with types; lazyAttrsOf (oneOf [ str path int float ]); - example = { EDITOR = "emacs"; GS_OPTIONS = "-sPAPERSIZE=a4"; }; + example = { + EDITOR = "emacs"; + GS_OPTIONS = "-sPAPERSIZE=a4"; + }; description = '' Environment variables to always set at login. @@ -332,13 +331,13 @@ in home.packages = mkOption { type = types.listOf types.package; - default = []; + default = [ ]; description = "The set of packages to appear in the user environment."; }; home.extraOutputsToInstall = mkOption { type = types.listOf types.str; - default = []; + default = [ ]; example = [ "doc" "info" "devdoc" ]; description = '' List of additional package outputs of the packages @@ -371,7 +370,7 @@ in home.activation = mkOption { type = hm.types.dagOf types.str; - default = {}; + default = { }; example = literalExpression '' { myActivationAction = lib.hm.dag.entryAfter ["writeBoundary"] ''' @@ -494,77 +493,60 @@ in } ]; - warnings = - let - hmRelease = config.home.version.release; - nixpkgsRelease = lib.trivial.release; - releaseMismatch = - config.home.enableNixpkgsReleaseCheck - && hmRelease != nixpkgsRelease; - in - optional releaseMismatch '' - You are using + warnings = let + hmRelease = config.home.version.release; + nixpkgsRelease = lib.trivial.release; + releaseMismatch = config.home.enableNixpkgsReleaseCheck && hmRelease + != nixpkgsRelease; + in optional releaseMismatch '' + You are using - Home Manager version ${hmRelease} and - Nixpkgs version ${nixpkgsRelease}. + Home Manager version ${hmRelease} and + Nixpkgs version ${nixpkgsRelease}. - Using mismatched versions is likely to cause errors and unexpected - behavior. It is therefore highly recommended to use a release of Home - Manager that corresponds with your chosen release of Nixpkgs. + Using mismatched versions is likely to cause errors and unexpected + behavior. It is therefore highly recommended to use a release of Home + Manager that corresponds with your chosen release of Nixpkgs. - If you insist then you can disable this warning by adding + If you insist then you can disable this warning by adding - home.enableNixpkgsReleaseCheck = false; + home.enableNixpkgsReleaseCheck = false; - to your configuration. - ''; + to your configuration. + ''; - home.username = - mkIf (versionOlder config.home.stateVersion "20.09") - (mkDefault (builtins.getEnv "USER")); - home.homeDirectory = - mkIf (versionOlder config.home.stateVersion "20.09") - (mkDefault (builtins.getEnv "HOME")); + home.username = mkIf (versionOlder config.home.stateVersion "20.09") + (mkDefault (builtins.getEnv "USER")); + home.homeDirectory = mkIf (versionOlder config.home.stateVersion "20.09") + (mkDefault (builtins.getEnv "HOME")); - home.profileDirectory = - if config.submoduleSupport.enable - && config.submoduleSupport.externalPackageInstall - then "/etc/profiles/per-user/${cfg.username}" - else if config.nix.enable && (config.nix.settings.use-xdg-base-directories or false) - then "${config.xdg.stateHome}/nix/profile" - else cfg.homeDirectory + "/.nix-profile"; + home.profileDirectory = if config.submoduleSupport.enable + && config.submoduleSupport.externalPackageInstall then + "/etc/profiles/per-user/${cfg.username}" + else if config.nix.enable + && (config.nix.settings.use-xdg-base-directories or false) then + "${config.xdg.stateHome}/nix/profile" + else + cfg.homeDirectory + "/.nix-profile"; programs.bash.shellAliases = cfg.shellAliases; programs.zsh.shellAliases = cfg.shellAliases; programs.fish.shellAliases = cfg.shellAliases; home.sessionVariables = - let - maybeSet = n: v: optionalAttrs (v != null) { ${n} = v; }; - in - (maybeSet "LANG" cfg.language.base) - // - (maybeSet "LC_CTYPE" cfg.language.ctype) - // - (maybeSet "LC_NUMERIC" cfg.language.numeric) - // - (maybeSet "LC_TIME" cfg.language.time) - // - (maybeSet "LC_COLLATE" cfg.language.collate) - // - (maybeSet "LC_MONETARY" cfg.language.monetary) - // - (maybeSet "LC_MESSAGES" cfg.language.messages) - // - (maybeSet "LC_PAPER" cfg.language.paper) - // - (maybeSet "LC_NAME" cfg.language.name) - // - (maybeSet "LC_ADDRESS" cfg.language.address) - // - (maybeSet "LC_TELEPHONE" cfg.language.telephone) - // - (maybeSet "LC_MEASUREMENT" cfg.language.measurement); + let maybeSet = n: v: optionalAttrs (v != null) { ${n} = v; }; + in (maybeSet "LANG" cfg.language.base) + // (maybeSet "LC_CTYPE" cfg.language.ctype) + // (maybeSet "LC_NUMERIC" cfg.language.numeric) + // (maybeSet "LC_TIME" cfg.language.time) + // (maybeSet "LC_COLLATE" cfg.language.collate) + // (maybeSet "LC_MONETARY" cfg.language.monetary) + // (maybeSet "LC_MESSAGES" cfg.language.messages) + // (maybeSet "LC_PAPER" cfg.language.paper) + // (maybeSet "LC_NAME" cfg.language.name) + // (maybeSet "LC_ADDRESS" cfg.language.address) + // (maybeSet "LC_TELEPHONE" cfg.language.telephone) + // (maybeSet "LC_MEASUREMENT" cfg.language.measurement); # Provide a file holding all session variables. home.sessionVariablesPackage = pkgs.writeTextFile { @@ -602,148 +584,129 @@ in # In case the user has moved from a user-install of Home Manager # to a submodule managed one we attempt to uninstall the # `home-manager-path` package if it is installed. - home.activation.installPackages = hm.dag.entryAfter ["writeBoundary"] ( - if config.submoduleSupport.externalPackageInstall - then - '' - nixProfileRemove home-manager-path - '' - else - '' - function nixReplaceProfile() { - local oldNix="$(command -v nix)" + home.activation.installPackages = hm.dag.entryAfter [ "writeBoundary" ] + (if config.submoduleSupport.externalPackageInstall then '' + nixProfileRemove home-manager-path + '' else '' + function nixReplaceProfile() { + local oldNix="$(command -v nix)" - nixProfileRemove 'home-manager-path' + nixProfileRemove 'home-manager-path' - run $oldNix profile install $1 - } + run $oldNix profile install $1 + } - if [[ -e ${cfg.profileDirectory}/manifest.json ]] ; then - INSTALL_CMD="nix profile install" - INSTALL_CMD_ACTUAL="nixReplaceProfile" - LIST_CMD="nix profile list" - REMOVE_CMD_SYNTAX='nix profile remove {number | store path}' - else - INSTALL_CMD="nix-env -i" - INSTALL_CMD_ACTUAL="run nix-env -i" - LIST_CMD="nix-env -q" - REMOVE_CMD_SYNTAX='nix-env -e {package name}' - fi + if [[ -e ${cfg.profileDirectory}/manifest.json ]] ; then + INSTALL_CMD="nix profile install" + INSTALL_CMD_ACTUAL="nixReplaceProfile" + LIST_CMD="nix profile list" + REMOVE_CMD_SYNTAX='nix profile remove {number | store path}' + else + INSTALL_CMD="nix-env -i" + INSTALL_CMD_ACTUAL="run nix-env -i" + LIST_CMD="nix-env -q" + REMOVE_CMD_SYNTAX='nix-env -e {package name}' + fi - if ! $INSTALL_CMD_ACTUAL ${cfg.path} ; then - echo - _iError $'Oops, Nix failed to install your new Home Manager profile!\n\nPerhaps there is a conflict with a package that was installed using\n"%s"? Try running\n\n %s\n\nand if there is a conflicting package you can remove it with\n\n %s\n\nThen try activating your Home Manager configuration again.' "$INSTALL_CMD" "$LIST_CMD" "$REMOVE_CMD_SYNTAX" - exit 1 - fi - unset -f nixReplaceProfile - unset INSTALL_CMD INSTALL_CMD_ACTUAL LIST_CMD REMOVE_CMD_SYNTAX - '' - ); + if ! $INSTALL_CMD_ACTUAL ${cfg.path} ; then + echo + _iError $'Oops, Nix failed to install your new Home Manager profile!\n\nPerhaps there is a conflict with a package that was installed using\n"%s"? Try running\n\n %s\n\nand if there is a conflicting package you can remove it with\n\n %s\n\nThen try activating your Home Manager configuration again.' "$INSTALL_CMD" "$LIST_CMD" "$REMOVE_CMD_SYNTAX" + exit 1 + fi + unset -f nixReplaceProfile + unset INSTALL_CMD INSTALL_CMD_ACTUAL LIST_CMD REMOVE_CMD_SYNTAX + ''); # Text containing Bash commands that will initialize the Home Manager Bash # library. Most importantly, this will prepare for using translated strings # in the `hm-modules` text domain. - lib.bash.initHomeManagerLib = - let - domainDir = pkgs.runCommand "hm-modules-messages" { - nativeBuildInputs = [ pkgs.buildPackages.gettext ]; - } '' - for path in ${./po}/*.po; do - lang="''${path##*/}" - lang="''${lang%%.*}" - mkdir -p "$out/$lang/LC_MESSAGES" - msgfmt -o "$out/$lang/LC_MESSAGES/hm-modules.mo" "$path" - done - ''; - in - '' - export TEXTDOMAIN=hm-modules - export TEXTDOMAINDIR=${domainDir} - source ${../lib/bash/home-manager.sh} - ''; + lib.bash.initHomeManagerLib = let + domainDir = pkgs.runCommand "hm-modules-messages" { + nativeBuildInputs = [ pkgs.buildPackages.gettext ]; + } '' + for path in ${./po}/*.po; do + lang="''${path##*/}" + lang="''${lang%%.*}" + mkdir -p "$out/$lang/LC_MESSAGES" + msgfmt -o "$out/$lang/LC_MESSAGES/hm-modules.mo" "$path" + done + ''; + in '' + export TEXTDOMAIN=hm-modules + export TEXTDOMAINDIR=${domainDir} + source ${../lib/bash/home-manager.sh} + ''; - home.activationPackage = - let - mkCmd = res: '' - _iNote "Activating %s" "${res.name}" - ${res.data} - ''; - sortedCommands = hm.dag.topoSort cfg.activation; - activationCmds = - if sortedCommands ? result then - concatStringsSep "\n" (map mkCmd sortedCommands.result) - else - abort ("Dependency cycle in activation script: " - + builtins.toJSON sortedCommands); + home.activationPackage = let + mkCmd = res: '' + _iNote "Activating %s" "${res.name}" + ${res.data} + ''; + sortedCommands = hm.dag.topoSort cfg.activation; + activationCmds = if sortedCommands ? result then + concatStringsSep "\n" (map mkCmd sortedCommands.result) + else + abort ("Dependency cycle in activation script: " + + builtins.toJSON sortedCommands); - # Programs that always should be available on the activation - # script's PATH. - activationBinPaths = lib.makeBinPath ( - with pkgs; [ - bash - coreutils - diffutils # For `cmp` and `diff`. - findutils - gettext - gnugrep - gnused - jq - ncurses # For `tput`. - ] - ++ config.home.extraActivationPath - ) - + ( + # Programs that always should be available on the activation + # script's PATH. + activationBinPaths = lib.makeBinPath (with pkgs; + [ + bash + coreutils + diffutils # For `cmp` and `diff`. + findutils + gettext + gnugrep + gnused + jq + ncurses # For `tput`. + ] ++ config.home.extraActivationPath) + ( # Add path of the Nix binaries, if a Nix package is configured, then # use that one, otherwise grab the path of the nix-env tool. if config.nix.enable && config.nix.package != null then ":${config.nix.package}/bin" else - ":$(${pkgs.coreutils}/bin/dirname $(${pkgs.coreutils}/bin/readlink -m $(type -p nix-env)))" - ) + ":$(${pkgs.coreutils}/bin/dirname $(${pkgs.coreutils}/bin/readlink -m $(type -p nix-env)))") + optionalString (!cfg.emptyActivationPath) "\${PATH:+:}$PATH"; - activationScript = pkgs.writeShellScript "activation-script" '' - set -eu - set -o pipefail + activationScript = pkgs.writeShellScript "activation-script" '' + set -eu + set -o pipefail - cd $HOME + cd $HOME - export PATH="${activationBinPaths}" - ${config.lib.bash.initHomeManagerLib} + export PATH="${activationBinPaths}" + ${config.lib.bash.initHomeManagerLib} - ${builtins.readFile ./lib-bash/activation-init.sh} + ${builtins.readFile ./lib-bash/activation-init.sh} - if [[ ! -v SKIP_SANITY_CHECKS ]]; then - checkUsername ${escapeShellArg config.home.username} - checkHomeDirectory ${escapeShellArg config.home.homeDirectory} - fi + if [[ ! -v SKIP_SANITY_CHECKS ]]; then + checkUsername ${escapeShellArg config.home.username} + checkHomeDirectory ${escapeShellArg config.home.homeDirectory} + fi - ${activationCmds} - ''; - in - pkgs.runCommand - "home-manager-generation" - { - preferLocalBuild = true; - } - '' - mkdir -p $out + ${activationCmds} + ''; + in pkgs.runCommand "home-manager-generation" { preferLocalBuild = true; } '' + mkdir -p $out - echo "${config.home.version.full}" > $out/hm-version + echo "${config.home.version.full}" > $out/hm-version - cp ${activationScript} $out/activate + cp ${activationScript} $out/activate - mkdir $out/bin - ln -s $out/activate $out/bin/home-manager-generation + mkdir $out/bin + ln -s $out/activate $out/bin/home-manager-generation - substituteInPlace $out/activate \ - --subst-var-by GENERATION_DIR $out + substituteInPlace $out/activate \ + --subst-var-by GENERATION_DIR $out - ln -s ${config.home-files} $out/home-files - ln -s ${cfg.path} $out/home-path + ln -s ${config.home-files} $out/home-files + ln -s ${cfg.path} $out/home-path - ${cfg.extraBuilderCommands} - ''; + ${cfg.extraBuilderCommands} + ''; home.path = pkgs.buildEnv { name = "home-manager-path"; diff --git a/modules/programs/zsh.nix b/modules/programs/zsh.nix index 50f8055c0..0c080f3d4 100644 --- a/modules/programs/zsh.nix +++ b/modules/programs/zsh.nix @@ -6,21 +6,21 @@ let cfg = config.programs.zsh; - relToDotDir = file: (optionalString (cfg.dotDir != null) (cfg.dotDir + "/")) + file; + relToDotDir = file: + (optionalString (cfg.dotDir != null) (cfg.dotDir + "/")) + file; - pluginsDir = if cfg.dotDir != null then - relToDotDir "plugins" else ".zsh/plugins"; + pluginsDir = + if cfg.dotDir != null then relToDotDir "plugins" else ".zsh/plugins"; envVarsStr = config.lib.zsh.exportAll cfg.sessionVariables; localVarsStr = config.lib.zsh.defineAll cfg.localVariables; - aliasesStr = concatStringsSep "\n" ( - mapAttrsToList (k: v: "alias -- ${lib.escapeShellArg k}=${lib.escapeShellArg v}") cfg.shellAliases - ); + aliasesStr = concatStringsSep "\n" (mapAttrsToList + (k: v: "alias -- ${lib.escapeShellArg k}=${lib.escapeShellArg v}") + cfg.shellAliases); - dirHashesStr = concatStringsSep "\n" ( - mapAttrsToList (k: v: ''hash -d ${k}="${v}"'') cfg.dirHashes - ); + dirHashesStr = concatStringsSep "\n" + (mapAttrsToList (k: v: ''hash -d ${k}="${v}"'') cfg.dirHashes); zdotdir = "$HOME/" + lib.escapeShellArg cfg.dotDir; @@ -64,20 +64,22 @@ let path = mkOption { type = types.str; - default = if versionAtLeast stateVersion "20.03" - then "$HOME/.zsh_history" - else relToDotDir ".zsh_history"; + default = if versionAtLeast stateVersion "20.03" then + "$HOME/.zsh_history" + else + relToDotDir ".zsh_history"; defaultText = literalExpression '' "$HOME/.zsh_history" if state version ≥ 20.03, "$ZDOTDIR/.zsh_history" otherwise ''; - example = literalExpression ''"''${config.xdg.dataHome}/zsh/zsh_history"''; + example = + literalExpression ''"''${config.xdg.dataHome}/zsh/zsh_history"''; description = "History file location"; }; ignorePatterns = mkOption { type = types.listOf types.str; - default = []; + default = [ ]; example = literalExpression ''[ "rm *" "pkill *" ]''; description = '' Do not enter command lines into the history list @@ -170,7 +172,7 @@ let package = mkPackageOption pkgs "oh-my-zsh" { }; plugins = mkOption { - default = []; + default = [ ]; example = [ "git" "sudo" ]; type = types.listOf types.str; description = '' @@ -215,7 +217,7 @@ let options = { enable = mkEnableOption "history substring search"; searchUpKey = mkOption { - type = with types; either (listOf str) str ; + type = with types; either (listOf str) str; default = [ "^[[A" ]; description = '' The key codes to be used when searching up. @@ -224,7 +226,7 @@ let ''; }; searchDownKey = mkOption { - type = with types; either (listOf str) str ; + type = with types; either (listOf str) str; default = [ "^[[B" ]; description = '' The key codes to be used when searching down. @@ -253,7 +255,7 @@ let patterns = mkOption { type = types.attrsOf types.str; - default = {}; + default = { }; example = { "rm -rf *" = "fg=white,bold,bg=red"; }; description = '' Custom syntax highlighting for user-defined patterns. @@ -263,7 +265,7 @@ let styles = mkOption { type = types.attrsOf types.str; - default = {}; + default = { }; example = { comment = "fg=black,bold"; }; description = '' Custom styles for syntax highlighting. @@ -273,13 +275,25 @@ let }; }; -in - -{ +in { imports = [ - (mkRenamedOptionModule [ "programs" "zsh" "enableAutosuggestions" ] [ "programs" "zsh" "autosuggestion" "enable" ]) - (mkRenamedOptionModule [ "programs" "zsh" "enableSyntaxHighlighting" ] [ "programs" "zsh" "syntaxHighlighting" "enable" ]) - (mkRenamedOptionModule [ "programs" "zsh" "zproof" ] [ "programs" "zsh" "zprof" ]) + (mkRenamedOptionModule [ "programs" "zsh" "enableAutosuggestions" ] [ + "programs" + "zsh" + "autosuggestion" + "enable" + ]) + (mkRenamedOptionModule [ "programs" "zsh" "enableSyntaxHighlighting" ] [ + "programs" + "zsh" + "syntaxHighlighting" + "enable" + ]) + (mkRenamedOptionModule [ "programs" "zsh" "zproof" ] [ + "programs" + "zsh" + "zprof" + ]) ]; options = { @@ -297,7 +311,7 @@ in }; cdpath = mkOption { - default = []; + default = [ ]; description = '' List of paths to autocomplete calls to {command}`cd`. ''; @@ -316,7 +330,7 @@ in }; shellAliases = mkOption { - default = {}; + default = { }; example = literalExpression '' { ll = "ls -l"; @@ -331,7 +345,7 @@ in }; shellGlobalAliases = mkOption { - default = {}; + default = { }; example = literalExpression '' { UUID = "$(uuidgen | tr -d \\n)"; @@ -346,7 +360,7 @@ in }; dirHashes = mkOption { - default = {}; + default = { }; example = literalExpression '' { docs = "$HOME/Documents"; @@ -374,7 +388,8 @@ in completionInit = mkOption { default = "autoload -U compinit && compinit"; - description = "Initialization commands to run when completion is enabled."; + description = + "Initialization commands to run when completion is enabled."; type = types.lines; }; @@ -387,13 +402,13 @@ in syntaxHighlighting = mkOption { type = syntaxHighlightingModule; - default = {}; + default = { }; description = "Options related to zsh-syntax-highlighting."; }; historySubstringSearch = mkOption { type = historySubstringSearchModule; - default = {}; + default = { }; description = "Options related to zsh-history-substring-search."; }; @@ -415,7 +430,8 @@ in }; strategy = mkOption { - type = types.listOf (types.enum [ "history" "completion" "match_prev_cmd" ]); + 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. @@ -436,7 +452,7 @@ in history = mkOption { type = historyModule; - default = {}; + default = { }; description = "Options related to commands history configuration."; }; @@ -448,7 +464,7 @@ in }; sessionVariables = mkOption { - default = {}; + default = { }; type = types.attrs; example = { MAILCHECK = 30; }; description = "Environment variables that will be set for zsh session."; @@ -457,7 +473,8 @@ in initExtraBeforeCompInit = mkOption { default = ""; type = types.lines; - description = "Extra commands that should be added to {file}`.zshrc` before compinit."; + description = + "Extra commands that should be added to {file}`.zshrc` before compinit."; }; initExtra = mkOption { @@ -481,7 +498,8 @@ in profileExtra = mkOption { default = ""; type = types.lines; - description = "Extra commands that should be added to {file}`.zprofile`."; + description = + "Extra commands that should be added to {file}`.zprofile`."; }; loginExtra = mkOption { @@ -493,12 +511,13 @@ in logoutExtra = mkOption { default = ""; type = types.lines; - description = "Extra commands that should be added to {file}`.zlogout`."; + description = + "Extra commands that should be added to {file}`.zlogout`."; }; plugins = mkOption { type = types.listOf pluginModule; - default = []; + default = [ ]; example = literalExpression '' [ { @@ -528,14 +547,14 @@ in oh-my-zsh = mkOption { type = ohMyZshModule; - default = {}; + default = { }; description = "Options to configure oh-my-zsh."; }; localVariables = mkOption { type = types.attrs; - default = {}; - example = { POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=["dir" "vcs"]; }; + default = { }; + example = { POWERLEVEL9K_LEFT_PROMPT_ELEMENTS = [ "dir" "vcs" ]; }; description = '' Extra local variables defined at the top of {file}`.zshrc`. ''; @@ -609,16 +628,16 @@ in cfg.initExtraFirst "typeset -U path cdpath fpath manpath" - (optionalString (cfg.cdpath != []) '' + (optionalString (cfg.cdpath != [ ]) '' cdpath+=(${concatStringsSep " " cfg.cdpath}) '') '' - for profile in ''${(z)NIX_PROFILES}; do - fpath+=($profile/share/zsh/site-functions $profile/share/zsh/$ZSH_VERSION/functions $profile/share/zsh/vendor-completions) - done + for profile in ''${(z)NIX_PROFILES}; do + fpath+=($profile/share/zsh/site-functions $profile/share/zsh/$ZSH_VERSION/functions $profile/share/zsh/vendor-completions) + done - HELPDIR="${cfg.package}/share/zsh/$ZSH_VERSION/help" + HELPDIR="${cfg.package}/share/zsh/$ZSH_VERSION/help" '' (optionalString (cfg.defaultKeymap != null) '' @@ -635,120 +654,136 @@ in '') cfg.plugins)) '' - # Oh-My-Zsh/Prezto calls compinit during initialization, - # calling it twice causes slight start up slowdown - # as all $fpath entries will be traversed again. - ${optionalString (cfg.enableCompletion && !cfg.oh-my-zsh.enable && !cfg.prezto.enable) - cfg.completionInit - }'' + # Oh-My-Zsh/Prezto calls compinit during initialization, + # calling it twice causes slight start up slowdown + # as all $fpath entries will be traversed again. + ${optionalString + (cfg.enableCompletion && !cfg.oh-my-zsh.enable && !cfg.prezto.enable) + cfg.completionInit}'' (optionalString cfg.autosuggestion.enable '' source ${pkgs.zsh-autosuggestions}/share/zsh-autosuggestions/zsh-autosuggestions.zsh - ${optionalString (cfg.autosuggestion.strategy != []) '' - ZSH_AUTOSUGGEST_STRATEGY=(${concatStringsSep " " cfg.autosuggestion.strategy}) - '' - } - '') - (optionalString (cfg.autosuggestion.enable && cfg.autosuggestion.highlight != null) '' - ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE="${cfg.autosuggestion.highlight}" + ${optionalString (cfg.autosuggestion.strategy != [ ]) '' + ZSH_AUTOSUGGEST_STRATEGY=(${ + concatStringsSep " " cfg.autosuggestion.strategy + }) + ''} '') + (optionalString + (cfg.autosuggestion.enable && cfg.autosuggestion.highlight != null) '' + ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE="${cfg.autosuggestion.highlight}" + '') (optionalString cfg.oh-my-zsh.enable '' - # oh-my-zsh extra settings for plugins - ${cfg.oh-my-zsh.extraConfig} - # oh-my-zsh configuration generated by NixOS - ${optionalString (cfg.oh-my-zsh.plugins != []) - "plugins=(${concatStringsSep " " cfg.oh-my-zsh.plugins})" - } - ${optionalString (cfg.oh-my-zsh.custom != "") - "ZSH_CUSTOM=\"${cfg.oh-my-zsh.custom}\"" - } - ${optionalString (cfg.oh-my-zsh.theme != "") - "ZSH_THEME=\"${cfg.oh-my-zsh.theme}\"" - } - source $ZSH/oh-my-zsh.sh + # oh-my-zsh extra settings for plugins + ${cfg.oh-my-zsh.extraConfig} + # oh-my-zsh configuration generated by NixOS + ${optionalString (cfg.oh-my-zsh.plugins != [ ]) + "plugins=(${concatStringsSep " " cfg.oh-my-zsh.plugins})"} + ${optionalString (cfg.oh-my-zsh.custom != "") + ''ZSH_CUSTOM="${cfg.oh-my-zsh.custom}"''} + ${optionalString (cfg.oh-my-zsh.theme != "") + ''ZSH_THEME="${cfg.oh-my-zsh.theme}"''} + source $ZSH/oh-my-zsh.sh '') '' - ${optionalString cfg.prezto.enable - (builtins.readFile "${pkgs.zsh-prezto}/share/zsh-prezto/runcoms/zshrc")} + ${optionalString cfg.prezto.enable (builtins.readFile + "${pkgs.zsh-prezto}/share/zsh-prezto/runcoms/zshrc")} - ${concatStrings (map (plugin: '' - if [[ -f "$HOME/${pluginsDir}/${plugin.name}/${plugin.file}" ]]; then - source "$HOME/${pluginsDir}/${plugin.name}/${plugin.file}" - fi - '') cfg.plugins)} + ${concatStrings (map (plugin: '' + if [[ -f "$HOME/${pluginsDir}/${plugin.name}/${plugin.file}" ]]; then + source "$HOME/${pluginsDir}/${plugin.name}/${plugin.file}" + fi + '') cfg.plugins)} - # History options should be set in .zshrc and after oh-my-zsh sourcing. - # See https://github.com/nix-community/home-manager/issues/177. - HISTSIZE="${toString cfg.history.size}" - SAVEHIST="${toString cfg.history.save}" - ${optionalString (cfg.history.ignorePatterns != []) "HISTORY_IGNORE=${lib.escapeShellArg "(${lib.concatStringsSep "|" cfg.history.ignorePatterns})"}"} - ${if versionAtLeast config.home.stateVersion "20.03" - then ''HISTFILE="${cfg.history.path}"'' - else ''HISTFILE="$HOME/${cfg.history.path}"''} - mkdir -p "$(dirname "$HISTFILE")" + # History options should be set in .zshrc and after oh-my-zsh sourcing. + # See https://github.com/nix-community/home-manager/issues/177. + HISTSIZE="${toString cfg.history.size}" + SAVEHIST="${toString cfg.history.save}" + ${optionalString (cfg.history.ignorePatterns != [ ]) + "HISTORY_IGNORE=${ + lib.escapeShellArg + "(${lib.concatStringsSep "|" cfg.history.ignorePatterns})" + }"} + ${if versionAtLeast config.home.stateVersion "20.03" then + ''HISTFILE="${cfg.history.path}"'' + else + ''HISTFILE="$HOME/${cfg.history.path}"''} + mkdir -p "$(dirname "$HISTFILE")" - setopt HIST_FCNTL_LOCK - ${if cfg.history.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 - ${if cfg.history.expireDuplicatesFirst then "setopt" else "unsetopt"} HIST_EXPIRE_DUPS_FIRST - ${if cfg.history.share then "setopt" else "unsetopt"} SHARE_HISTORY - ${if cfg.history.extended then "setopt" else "unsetopt"} EXTENDED_HISTORY - ${if cfg.autocd != null then "${if cfg.autocd then "setopt" else "unsetopt"} autocd" else ""} + 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 + ${ + if cfg.history.expireDuplicatesFirst then "setopt" else "unsetopt" + } HIST_EXPIRE_DUPS_FIRST + ${if cfg.history.share then "setopt" else "unsetopt"} SHARE_HISTORY + ${ + if cfg.history.extended then "setopt" else "unsetopt" + } EXTENDED_HISTORY + ${if cfg.autocd != null then + "${if cfg.autocd then "setopt" else "unsetopt"} autocd" + else + ""} - ${cfg.initExtra} + ${cfg.initExtra} - # Aliases - ${aliasesStr} + # Aliases + ${aliasesStr} '' - ] - ++ (mapAttrsToList (k: v: "alias -g -- ${lib.escapeShellArg k}=${lib.escapeShellArg v}") cfg.shellGlobalAliases) - ++ [ ('' - # Named Directory Hashes - ${dirHashesStr} - '') + ] ++ (mapAttrsToList + (k: v: "alias -g -- ${lib.escapeShellArg k}=${lib.escapeShellArg v}") + cfg.shellGlobalAliases) ++ [ + ('' + # Named Directory Hashes + ${dirHashesStr} + '') - (optionalString cfg.syntaxHighlighting.enable - # Load zsh-syntax-highlighting after all custom widgets have been created - # https://github.com/zsh-users/zsh-syntax-highlighting#faq - '' - source ${cfg.syntaxHighlighting.package}/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh - ZSH_HIGHLIGHT_HIGHLIGHTERS+=(${lib.concatStringsSep " " (map lib.escapeShellArg cfg.syntaxHighlighting.highlighters)}) - ${lib.concatStringsSep "\n" ( - lib.mapAttrsToList - (name: value: "ZSH_HIGHLIGHT_STYLES+=(${lib.escapeShellArg name} ${lib.escapeShellArg value})") - cfg.syntaxHighlighting.styles - )} - ${lib.concatStringsSep "\n" ( - lib.mapAttrsToList - (name: value: "ZSH_HIGHLIGHT_PATTERNS+=(${lib.escapeShellArg name} ${lib.escapeShellArg value})") - cfg.syntaxHighlighting.patterns - )} - '') + (optionalString cfg.syntaxHighlighting.enable + # Load zsh-syntax-highlighting after all custom widgets have been created + # https://github.com/zsh-users/zsh-syntax-highlighting#faq + '' + source ${cfg.syntaxHighlighting.package}/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh + ZSH_HIGHLIGHT_HIGHLIGHTERS+=(${ + lib.concatStringsSep " " + (map lib.escapeShellArg cfg.syntaxHighlighting.highlighters) + }) + ${lib.concatStringsSep "\n" (lib.mapAttrsToList (name: value: + "ZSH_HIGHLIGHT_STYLES+=(${lib.escapeShellArg name} ${ + lib.escapeShellArg value + })") cfg.syntaxHighlighting.styles)} + ${lib.concatStringsSep "\n" (lib.mapAttrsToList (name: value: + "ZSH_HIGHLIGHT_PATTERNS+=(${lib.escapeShellArg name} ${ + lib.escapeShellArg value + })") cfg.syntaxHighlighting.patterns)} + '') - (optionalString (cfg.historySubstringSearch.enable or false) + (optionalString (cfg.historySubstringSearch.enable or false) # Load zsh-history-substring-search after zsh-syntax-highlighting # https://github.com/zsh-users/zsh-history-substring-search#usage - '' - source ${pkgs.zsh-history-substring-search}/share/zsh-history-substring-search/zsh-history-substring-search.zsh - ${lib.concatMapStringsSep "\n" - (upKey: "bindkey \"${upKey}\" history-substring-search-up") - (lib.toList cfg.historySubstringSearch.searchUpKey) - } - ${lib.concatMapStringsSep "\n" - (downKey: "bindkey \"${downKey}\" history-substring-search-down") - (lib.toList cfg.historySubstringSearch.searchDownKey) - } - '') + '' + source ${pkgs.zsh-history-substring-search}/share/zsh-history-substring-search/zsh-history-substring-search.zsh + ${lib.concatMapStringsSep "\n" + (upKey: ''bindkey "${upKey}" history-substring-search-up'') + (lib.toList cfg.historySubstringSearch.searchUpKey)} + ${lib.concatMapStringsSep "\n" + (downKey: ''bindkey "${downKey}" history-substring-search-down'') + (lib.toList cfg.historySubstringSearch.searchDownKey)} + '') - (optionalString cfg.zprof.enable - '' - zprof - '') - ]); + (optionalString cfg.zprof.enable '' + zprof + '') + ]); } (mkIf cfg.oh-my-zsh.enable { @@ -757,15 +792,14 @@ in home.file."${config.xdg.cacheHome}/oh-my-zsh/.keep".text = ""; }) - (mkIf (cfg.plugins != []) { + (mkIf (cfg.plugins != [ ]) { # Many plugins require compinit to be called # but allow the user to opt out. programs.zsh.enableCompletion = mkDefault true; - home.file = - foldl' (a: b: a // b) {} + home.file = foldl' (a: b: a // b) { } (map (plugin: { "${pluginsDir}/${plugin.name}".source = plugin.src; }) - cfg.plugins); + cfg.plugins); }) ]); }