aboutsummaryrefslogtreecommitdiff
path: root/home-manager
diff options
context:
space:
mode:
authorRobert Helgesson <robert@rycee.net>2017-08-26 22:24:40 +0200
committerRobert Helgesson <robert@rycee.net>2017-09-05 11:37:07 +0200
commit9c1b3735b402346533449efc741f191d6ef578dd (patch)
tree29de685e46c1e93843b99a0b999ec9735a9b8c7a /home-manager
parentab0338f6ae372ff6891a6df143fd753bcbb24f71 (diff)
home-manager: add news sub-command
This command allows the user to examine the news items generated by the news module. See #52. Many thanks to @nonsequitur and @uvNikita for suggestions and improvements.
Diffstat (limited to 'home-manager')
-rw-r--r--home-manager/default.nix1
-rw-r--r--home-manager/home-manager121
-rw-r--r--home-manager/home-manager.nix76
3 files changed, 185 insertions, 13 deletions
diff --git a/home-manager/default.nix b/home-manager/default.nix
index a5853961792..bb09886913a 100644
--- a/home-manager/default.nix
+++ b/home-manager/default.nix
@@ -23,6 +23,7 @@ pkgs.stdenv.mkDerivation {
substituteInPlace $out/bin/home-manager \
--subst-var-by bash "${pkgs.bash}" \
--subst-var-by coreutils "${pkgs.coreutils}" \
+ --subst-var-by less "${pkgs.less}" \
--subst-var-by MODULES_PATH '${modulesPathStr}' \
--subst-var-by HOME_MANAGER_EXPR_PATH "${./home-manager.nix}"
'';
diff --git a/home-manager/home-manager b/home-manager/home-manager
index 8e0bd40c2d5..4722d41a2f8 100644
--- a/home-manager/home-manager
+++ b/home-manager/home-manager
@@ -3,12 +3,12 @@
# This code explicitly requires GNU Core Utilities and we therefore
# need to ensure they are prioritized over any other similarly named
# tools on the system.
-PATH=@coreutils@/bin:$PATH
+PATH=@coreutils@/bin:@less@/bin${PATH:+:}$PATH
set -euo pipefail
function errorEcho() {
- >&2 echo "$*"
+ echo $* >&2
}
# Attempts to set the HOME_MANAGER_CONFIG global variable.
@@ -52,12 +52,11 @@ function setHomeManagerModulesPath() {
done
}
-function doBuild() {
+function doBuildAttr() {
setConfigFile
setHomeManagerModulesPath
- local extraArgs
- extraArgs="$1"
+ local extraArgs="$*"
for p in "${EXTRA_NIX_PATH[@]}"; do
extraArgs="$extraArgs -I $p"
@@ -67,11 +66,53 @@ function doBuild() {
extraArgs="$extraArgs --show-trace"
fi
- nix-build $extraArgs \
- "@HOME_MANAGER_EXPR_PATH@" \
- --argstr confPath "$HOME_MANAGER_CONFIG" \
- --argstr confAttr "$HOME_MANAGER_CONFIG_ATTRIBUTE" \
- -A activationPackage
+ nix-build \
+ "@HOME_MANAGER_EXPR_PATH@" \
+ $extraArgs \
+ --argstr confPath "$HOME_MANAGER_CONFIG" \
+ --argstr confAttr "$HOME_MANAGER_CONFIG_ATTRIBUTE"
+}
+
+function presentNews() {
+ local infoFile
+ infoFile=$(doBuildNews -A newsInfo) || return 1
+
+ # shellcheck source=/dev/null
+ . "$infoFile"
+
+ if [[ $newsNumUnread -eq 0 ]]; then
+ return
+ elif [[ "$newsDisplay" == "silent" ]]; then
+ return
+ elif [[ "$newsDisplay" == "notify" ]]; then
+ local msg
+ if [[ $newsNumUnread -eq 1 ]]; then
+ msg="There is an unread and relevant news item.\n"
+ msg+="Read it by running the command '$(basename "$0") news'."
+ else
+ msg="There are $newsNumUnread unread and relevant news items.\n"
+ msg+="Read them by running the command '$(basename "$0") news'."
+ fi
+
+ # Not actually an error but here stdout is reserved for
+ # nix-build output.
+ errorEcho
+ errorEcho -e "$msg"
+ errorEcho
+
+ if [[ -v DISPLAY ]] && type -P notify-send > /dev/null; then
+ notify-send "Home Manager" "$msg"
+ fi
+ elif [[ "$newsDisplay" == "show" ]]; then
+ doShowNews --unread
+ else
+ errorEcho "Unknown 'news.display' setting '$newsDisplay'."
+ fi
+}
+
+function doBuild() {
+ doBuildAttr -A activationPackage
+ presentNews
}
function doSwitch() {
@@ -84,12 +125,17 @@ function doSwitch() {
# prevents an unfortunately timed GC from removing the generation
# before activation completes.
wrkdir="$(mktemp -d)"
- generation=$(doBuild "-o $wrkdir/result") && $generation/activate || exitCode=1
+ generation=$(doBuildAttr -o "$wrkdir/result" -A activationPackage) \
+ && $generation/activate || exitCode=1
# Because the previous command never fails, the script keeps
# running and $wrkdir is always removed.
rm -r "$wrkdir"
+ if [[ $exitCode -eq 0 ]]; then
+ presentNews
+ fi
+
return $exitCode
}
@@ -110,6 +156,53 @@ function doListPackages() {
fi
}
+function newsReadIdsFile() {
+ local dataDir="${XDG_DATA_HOME:-$HOME/.local/share}/home-manager"
+ local path="$dataDir/news-read-ids"
+
+ # If the path doesn't exist then we should create it, otherwise
+ # Nix will error out when we attempt to use builtins.readFile.
+ if [[ ! -f "$path" ]]; then
+ mkdir -p "$dataDir"
+ touch "$path"
+ fi
+
+ echo "$path"
+}
+
+function doBuildNews() {
+ doBuildAttr "$*" \
+ --no-out-link \
+ --arg check false \
+ --argstr newsReadIdsFile "$(newsReadIdsFile)"
+}
+
+function doShowNews() {
+ local infoFile
+ infoFile=$(doBuildNews -A newsInfo) || return 1
+
+ # shellcheck source=/dev/null
+ . "$infoFile"
+
+ case $1 in
+ --all)
+ ${PAGER:-less} "$newsFileAll"
+ ;;
+ --unread)
+ ${PAGER:-less} "$newsFileUnread"
+ ;;
+ *)
+ errorEcho "Unknown argument $1"
+ return 1
+ esac
+
+ if [[ -s "$newsUnreadIdsFile" ]]; then
+ local newsReadIdsFile
+ newsReadIdsFile="$(newsReadIdsFile)"
+ cat "$newsUnreadIdsFile" >> "$newsReadIdsFile"
+ fi
+}
+
function doHelp() {
echo "Usage: $0 [OPTION] COMMAND"
echo
@@ -130,6 +223,7 @@ function doHelp() {
echo " switch Build and activate configuration"
echo " generations List all home environment generations"
echo " packages List all packages installed in home-manager-path"
+ echo " news Show news entries in a pager"
}
EXTRA_NIX_PATH=()
@@ -171,7 +265,7 @@ cmd="$*"
case "$cmd" in
build)
- doBuild ""
+ doBuild
;;
switch)
doSwitch
@@ -182,6 +276,9 @@ case "$cmd" in
packages)
doListPackages
;;
+ news)
+ doShowNews --all
+ ;;
help|--help)
doHelp
;;
diff --git a/home-manager/home-manager.nix b/home-manager/home-manager.nix
index f356b5a0c02..a6c9259f874 100644
--- a/home-manager/home-manager.nix
+++ b/home-manager/home-manager.nix
@@ -1,6 +1,14 @@
-{ pkgs ? import <nixpkgs> {}, confPath, confAttr }:
+{ pkgs ? import <nixpkgs> {}
+, confPath
+, confAttr
+, check ? true
+, newsReadIdsFile ? null
+}:
+
+with pkgs.lib;
let
+
env = import <home-manager> {
configuration =
let
@@ -8,8 +16,74 @@ let
in
if confAttr == "" then conf else conf.${confAttr};
pkgs = pkgs;
+ check = check;
};
+
+ newsReadIds =
+ if newsReadIdsFile == null
+ then {}
+ else
+ let
+ ids = splitString "\n" (fileContents newsReadIdsFile);
+ in
+ builtins.listToAttrs (map (id: { name = id; value = null; }) ids);
+
+ newsIsRead = entry: builtins.hasAttr entry.id newsReadIds;
+
+ newsFiltered =
+ let
+ pred = entry: entry.condition && ! newsIsRead entry;
+ in
+ filter pred env.newsEntries;
+
+ newsNumUnread = length newsFiltered;
+
+ newsFileUnread = pkgs.writeText "news-unread.txt" (
+ concatMapStringsSep "\n\n" (entry:
+ let
+ time = replaceStrings ["T"] [" "] (removeSuffix "+00:00" entry.time);
+ in
+ ''
+ * ${time}
+
+ ${replaceStrings ["\n"] ["\n "] entry.message}
+ ''
+ ) newsFiltered
+ );
+
+ newsFileAll = pkgs.writeText "news-all.txt" (
+ concatMapStringsSep "\n\n" (entry:
+ let
+ flag = if newsIsRead entry then "read" else "unread";
+ time = replaceStrings ["T"] [" "] (removeSuffix "+00:00" entry.time);
+ in
+ ''
+ * ${time} [${flag}]
+
+ ${replaceStrings ["\n"] ["\n "] entry.message}
+ ''
+ ) env.newsEntries
+ );
+
+ # File where each line corresponds to an unread news entry
+ # identifier. If non-empty then the file ends in "\n".
+ newsUnreadIdsFile = pkgs.writeText "news-unread-ids" (
+ let
+ text = concatMapStringsSep "\n" (entry: entry.id) newsFiltered;
+ in
+ text + optionalString (text != "") "\n"
+ );
+
+ newsInfo = pkgs.writeText "news-info.sh" ''
+ local newsNumUnread=${toString newsNumUnread}
+ local newsDisplay="${env.newsDisplay}"
+ local newsFileAll="${newsFileAll}"
+ local newsFileUnread="${newsFileUnread}"
+ local newsUnreadIdsFile="${newsUnreadIdsFile}"
+ '';
+
in
{
inherit (env) activationPackage;
+ inherit newsInfo;
}