mirror of
https://github.com/nix-community/home-manager.git
synced 2024-12-14 11:57:55 +00:00
treewide: remove formatting excludes
This removes the last three formatting excludes so that the entire project is formatted by nixfmt. This is the first step towards moving to the RFC style format.
This commit is contained in:
parent
3066cc58f5
commit
a17d730ab5
4 changed files with 540 additions and 574 deletions
14
format
14
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[@]}"
|
||||
|
|
|
@ -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));
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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);
|
||||
})
|
||||
]);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue