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