diff --git a/environments/niri/niri.kdl b/environments/niri/niri.kdl index f92a955..06f28bd 100644 --- a/environments/niri/niri.kdl +++ b/environments/niri/niri.kdl @@ -34,9 +34,6 @@ clipboard { hotkey-overlay { skip-at-startup } -// animations { -// off -// } binds { XF86AudioPlay allow-when-locked=true { spawn "playerctl" "play-pause"; } diff --git a/modules/cli/nix/impermanence.nix b/modules/cli/nix/impermanence.nix index dff025e..54b2e6f 100644 --- a/modules/cli/nix/impermanence.nix +++ b/modules/cli/nix/impermanence.nix @@ -61,11 +61,12 @@ ".local/share/waydroid" ".local/share/bottles" ".var" - ".zen" + ".kube" ".cache/flatpak" ".local/share/atuin" # Cache for sessions (keep website logged in, plugin downloaded...) ".mozilla" + ".zen" ".config/google-chrome" ".config/discord" ".config/vesktop" diff --git a/modules/cli/zsh/default.nix b/modules/cli/zsh/default.nix index 852ab54..324210b 100644 --- a/modules/cli/zsh/default.nix +++ b/modules/cli/zsh/default.nix @@ -52,7 +52,9 @@ dc = "docker-compose"; dcd = "docker-compose -f (../)#docker-compose.dev.yml"; k = "kubectl"; - kctx = "kubectl config get-contexts -o name | fzf --height=10 | xargs kubectl config use-context"; + kubectl = "kubecolor"; + kctx = "kubectl config use-context $(kubectl config get-contexts -o name | fzf --height=10)"; + kns = "kubectl config set-context --current --namespace=$(kubectl get ns -o custom-columns=':metadata.name' --no-headers | fzf --height=10)"; op = "xdg-open"; py = "python3 2> /dev/null || , python3"; jctl = "sudo journalctl -n 1000 -fu"; @@ -114,10 +116,18 @@ src = pkgs.oh-my-zsh; file = "share/oh-my-zsh/plugins/copyfile/copyfile.plugin.zsh"; } + { + name = "completion-sync"; + src = ./.; + file = "./zsh-completion-sync.plugin.zsh"; + } ]; completionInit = #bash '' + # disable zsh-autocomplete plugin compatibility (from zsh-completion-sync) + zstyle ':completion-sync:compinit:compat:zsh-autocomplete' enabled true + # The globbing is a little complicated here: # - '#q' is an explicit glob qualifier that makes globbing work within zsh's [[ ]] construct. # - 'N' makes the glob pattern evaluate to nothing when it doesn't match (rather than throw a globbing error) @@ -313,6 +323,8 @@ rename # this is perl-rename gfold lsof + kubectl + kubecolor # bitwarden-cli ] ++ lib.optionals pkgs.stdenv.isLinux [ diff --git a/modules/cli/zsh/zsh-completion-sync.plugin.zsh b/modules/cli/zsh/zsh-completion-sync.plugin.zsh new file mode 100644 index 0000000..6563626 --- /dev/null +++ b/modules/cli/zsh/zsh-completion-sync.plugin.zsh @@ -0,0 +1,372 @@ +# stolen from https://github.com/BronzeDeer/zsh-completion-sync/blob/master/zsh-completion-sync.plugin.zsh + +_completion_sync:debug_log(){ + if zstyle -t "$1" debug; then + echo "completion sync: $2" + fi +} + +_completion_sync:delete_first_from_fpath(){ + # There might be multiple instances of the same path on the fpath + # We will only delete the first instance to "reset" the priority order + # but leave later occurences + local idx="$fpath[(Ie)$1]" + if (( $idx != 0 )); then + _completion_sync:debug_log ':completion-sync:fpath:delete' "deleting '$1' from FPATH at index '$idx'" + fpath[$idx]=() + fi +} + +_completion_sync:fpath_maybe_add_xdg(){ + # There are two valid paths in an XDG_DATA_DIR, one from the zsh install and one from third party + # It is unclear if would ever make sense to add the ones from the zsh install, + # since they should be always on the fpath, but for now we test for both + + local p="$1/zsh/$ZSH_VERSION/functions" + + if [[ -d $p ]]; then + _completion_sync:debug_log ':completion-sync:xdg:add' "Added '$p' to FPATH" + fpath=("$p" $fpath) + fi + + + p="$1/zsh/site-functions" + if [[ -d $p ]]; then + _completion_sync:debug_log ':completion-sync:xdg:add' "Added '$p' to FPATH" + fpath=("$p" $fpath) + fi +} + +_completion_sync:functions_from_xdg_data(){ + local a=($(echo "$XDG_DATA_DIRS" | tr ':' "\n" | xargs -I{} realpath -e "{}/zsh/site-functions" "\n" realpath -e "{}/zsh/$ZSH_VERSION/functions" "\n" realpath -e "{}/zsh/vendor-completions" 2>/dev/null | tr "\n" ' ')) + # unique the directories + echo "${(u)a[@]}" +} + +# This function directly reads into the completion_sync_fpaths_from_path variable to avoid a subshell invocation +_completion_sync:find_fpaths_from_path(){ + local rel_paths=() + if ! zstyle -g rel_paths ':completion-sync:path' rel_paths; then + rel_paths=("../share/zsh/$ZSH_VERSION/functions" '../share/zsh/site-functions') + fi + + completion_sync_fpaths_from_path=() + + for p in $path; do + for rp in $rel_paths; do + local maybe_fpath="$p/$rp" + # This is the equivalent of using readlink on the path (i.e. canonicalize it, and resolve symlinks) + _completion_sync:debug_log ':completion-sync:path:path2fpath:candidate' "fpath candidate: $maybe_fpath" + maybe_fpath=${maybe_fpath:A} + _completion_sync:debug_log ':completion-sync:path:path2fpath:candidate:canonicalize' "fpath candidate (canonicalized): $maybe_fpath" + if [[ -d "$maybe_fpath" ]]; then + _completion_sync:debug_log ':completion-sync:path:path2fpath' "found fpath on path: $maybe_fpath" + completion_sync_fpaths_from_path=("$maybe_fpath" $completion_sync_fpaths_from_path) + fi + done + done + # unique the directories + _completion_sync:debug_log ':completion-sync:path:path2fpath:unique' "fpaths on path (non-unique):\n${(F)completion_sync_fpaths_from_path}\n" + completion_sync_fpaths_from_path=(${(u)completion_sync_fpaths_from_path[@]}) + _completion_sync:debug_log ':completion-sync:path:path2fpath:unique' "fpaths on path (unique):\n${(F)completion_sync_fpaths_from_path}\n" + +} + +_completion_sync:custom_compinit_isenabled(){ + zstyle -t ':completion-sync:compinit:custom' enabled + return +} + +_completion_sync:zsh_autocomplete_compat_isenabled(){ + # set return code to !custom_isenabled && compat:zsh-autocomplete enabled + _completion_sync:custom_compinit_isenabled + if [[ $? -ne 0 ]]; then + zstyle -T ':completion-sync:compinit:compat:zsh-autocomplete' enabled + return + else + return 1 + fi +} + +_completion_sync:zsh_autocomplete_compat_disable(){ + zstyle ':completion-sync:compinit:compat:zsh-autocomplete' enabled false +} + + +_completion_sync:zsh_autocomplete_compat_reload(){ + # If zsh-autocomplete is loaded, it will either be in the fully initiliazed state, or the pre-initialized state + + # In the pre-initilaized state, a precmd hook is waiting to execute, which will setup the plugin and among other things reload compinit and define a named-directory + # Instead of waiting for the pre-cmd hook to fire, we want it to execute right now. + + # Find the autocomplete hook if present + local precmd=${(M)precmd_functions:#.autocomplete*precmd} + # If the plugin is already fully initialized, then the relevant functions have been undefined and we need to re-initialize it from the start. + if [[ -z $precmd ]]; then + # In this case the named directory "~zsh-autocomplete" will be present, which we can use to reload regardless of install location + if [[ ! -v nameddirs[zsh-autocomplete] ]]; then + _completion_sync:debug_log ':completion-sync:compinit:compat:zsh-autocomplete' "compat: zsh-autocomplete: unable to detect plugin setup functions or named directory, disabling compat" + _completion_sync:zsh_autocomplete_compat_disable + return 1 + else + # Since the named directory exists we can source the plugin again, which will put the precmd hook back in the array + _completion_sync:debug_log ':completion-sync:compinit:compat:zsh-autocomplete' "compat: zsh-autocomplete: re-initializing zsh-autocomplete via 'source ~zsh-autocomplete/zsh-autocomplete.plugin.zsh'" + source ~zsh-autocomplete/zsh-autocomplete.plugin.zsh + + precmd=${(M)precmd_functions:#.autocomplete*precmd} + if [[ -z $precmd ]]; then + echo "completion-sync: compat: zsh-autocomplete: unable to detect plugin setup functions even after reinitializing, disabling compat" + _completion_sync:zsh_autocomplete_compat_disable + return 1 + fi + fi + fi + + # Execute the precmd hook, this will re-initialize the compsys (since we are handling the zcompdump file) + _completion_sync:debug_log ':completion-sync:compinit:compat:zsh-autocomplete' "compat: zsh-autocomplete: executing precmd hook '$precmd' now" + _completion_sync:debug_log ':completion-sync:compinit:compat:zsh-autocomplete:diff' "compat: zsh-autocomplete: precmd hooks before" + _completion_sync:debug_log ':completion-sync:compinit:compat:zsh-autocomplete:diff' "$precmd_functions" + $precmd + _completion_sync:debug_log ':completion-sync:compinit:compat:zsh-autocomplete:diff' "compat: zsh-autocomplete: precmd hooks after" + _completion_sync:debug_log ':completion-sync:compinit:compat:zsh-autocomplete:diff' "$precmd_functions" + +} + +# Take a path (as first arg) to a zstyle which has two leaf keys "enabled" and "command" +# if enabled is true, eval the string inside command +_completion_sync:run_hook_if_enabled(){ + local style="$1" + + if zstyle -t "$style" enabled; then + local hook + zstyle -s "$style" command hook + eval "$hook" + fi +} + +_completion_sync:compsys_reload(){ + # Delete current cache + rm -rf "$_per_shell_compdump" + + _completion_sync:run_hook_if_enabled ':completion-sync:compinit:custom:pre-hook' + + if _completion_sync:custom_compinit_isenabled ; then + local custom + zstyle -s ':completion-sync:compinit:custom' command custom + _completion_sync:debug_log ':completion-sync:compinit:custom' "compinit: using custom command instead of compinit: ${(q)custom}" + eval $custom + elif _completion_sync:zsh_autocomplete_compat_isenabled ; then + # Reload will either reload zsh-autocomplete or disable the compat if it is not present + if ! _completion_sync:zsh_autocomplete_compat_reload; then + # zsh_autocomplete_compat could not properly reload, the plugin is likely not present, disable compat + _completion_sync:zsh_autocomplete_compat_disable + # Re-run the compsys logic with zac compat disabled + _completion_sync:compsys_reload + fi + else + + # Ensure that we call compinit provided from the fpath (default: off) + if zstyle -t ':completion-sync:compinit:builtin-compinit' enabled; then + # Allow us to restore the previous compinit, to be a good citizen + functions -c compinit compinit_orig + # Remove the current compinit to allow for reloading + unfunction compinit + # restore original compinit + autoload +X compinit + + _completion_sync:debug_log ':completion-sync:compinit:builtin-compinit' "previous compinit: $(whence -v compinit_orig)" + _completion_sync:debug_log ':completion-sync:compinit:builtin-compinit' "loaded compinit: $(whence -v compinit)" + fi + + _completion_sync:debug_log ':completion-sync:compinit' "invoking compinit as 'compinit -d \"$_per_shell_compdump\"'" + compinit -d "$_per_shell_compdump" + + if zstyle -t ':completion-sync:compinit:builtin-compinit' enabled; then + # restore original function + functions -c compinit_orig compinit + _completion_sync:debug_log ':completion-sync:compinit:builtin-compinit' "restored compinit: $(whence -v compinit)" + fi + + fi + + _completion_sync:run_hook_if_enabled ':completion-sync:compinit:custom:post-hook' + +} + +_completion_sync:path_hook(){ + if [[ ! -v COMPLETION_SYNC_OLD_PATH ]]; then + _completion_sync:debug_log ':completion-sync:path:init' "Detecting FPATHs from PATH enabled" + + _completion_sync:debug_log ':completion-sync:path:init:diff' "from path: old FPATH\n${(F)fpath}\n" + # Detect current fpaths from path and read it into the variable + _completion_sync:find_fpaths_from_path + + # Prepend in reverse order to maintain their order in the final path + for idx in {${#completion_sync_fpaths_from_path}..1} ; do + local elem=${completion_sync_fpaths_from_path[$idx]} + # First time around, only add relevant XDG_DATA_DIRs, which are not on the FPATH yet + if (( ! ${fpath[(I)"$elem"]} )); then + + _completion_sync:debug_log ':completion-sync:path:init:diff' "from path: $elem" + + fpath=($elem $fpath) + completion_sync_fpath_changed_during_init=true + fi + done + + _completion_sync:debug_log ':completion-sync:path:init:diff' "from path: new FPATH\n${(F)fpath}\n" + elif [[ "$COMPLETION_SYNC_OLD_PATH" != "$PATH" ]]; then + _completion_sync:debug_log ':completion-sync:path:onchange' "PATH CHANGED" + # Check if the fpath dirs changed + local completion_sync_old_fpaths_from_path=( "${(@f)completion_sync_fpaths_from_path}" ) + + if [[ "$completion_sync_old_fpaths_from_path" != "$completion_sync_fpaths_from_path" ]]; then + _completion_sync:debug_log ':completion-sync:path:onchange' "Need to update FPATH from PATH!" + + local diff=( "${(@)$(diff <(echo "${(F)completion_sync_fpaths_from_path}") <( echo "${(F)completion_sync_old_fpaths_from_path}") | grep -E "<|>")}" ) + _completion_sync:debug_log ':completion-sync:path:diff' "$diff" + + # TODO: Generalize without subshell + # Prepend in reverse order to maintain their order in the final path + for idx in {${#diff}..1} ; do + local p=$diff[$idx] + case "${p[1]}" in + \<) + # path got added + local p_path="${p:2}" + _completion_sync:debug_log ':completion-sync:path:onchange:add' "Adding path '$p_path'" + _completion_sync:debug_log ':completion-sync:fpath:add' "Adding '$p_path' to FPATH" + fpath=("$p_path" $fpath) + ;; + \>) + # path got removed + local p_path="${p:2}" + _completion_sync:debug_log ':completion-sync:path:onchange:delete' "Removing path '$p_path'" + _completion_sync:delete_first_from_fpath "$p_path" + ;; + *) + # This should not happen + _completion_sync:debug_log ':completion-sync:path:onchange' "Invalid diff line $p" + _completion_sync:debug_log ':completion-sync:path:onchange' "Tried to match on character ${p[1]}" + ;; + esac + done + else + _completion_sync:debug_log ':completion-sync:path:onchange' "No FPATH change needed" + fi + fi + COMPLETION_SYNC_OLD_PATH="$PATH" +} + +_completion_sync:hook(){ + if zstyle -t ':completion-sync:path' enabled; then + _completion_sync:path_hook + fi + + if zstyle -T ':completion-sync:xdg' enabled; then + if [[ ! -v COMPLETION_SYNC_OLD_XDG_DATA_DIRS ]]; then + _completion_sync:debug_log ':completion-sync:xdg:init' "Syncing XDG_DATA_DIRS into FPATH enabled" + + _completion_sync:debug_log ':completion-sync:xdg:init:diff' "old FPATH\n${(F)fpath}" + + # First time around, only add relevant XDG_DATA_DIRs, which are not on the FPATH yet + # Find XDG_DATA_DIRS which have $ZSH function dirs under them + completion_sync_old_xdg_fpaths=( $(_completion_sync:functions_from_xdg_data) ) + + _completion_sync:debug_log ':completion-sync:xdg:init:diff' "adding from XDG" + + # Prepend in reverse order to maintain their order in the final path + for idx in {${#completion_sync_old_xdg_fpaths}..1} ; do + local elem="${completion_sync_old_xdg_fpaths[$idx]}" + if (( ! ${fpath[(I)$elem]} )); then + + _completion_sync:debug_log ':completion-sync:xdg:init:diff' $elem + + fpath=($elem $fpath) + completion_sync_fpath_changed_during_init=true + fi + done + + _completion_sync:debug_log ':completion-sync:xdg:init:diff' "New FPATH\n${(F)fpath}" + + elif [[ "$COMPLETION_SYNC_OLD_XDG_DATA_DIRS" != "$XDG_DATA_DIRS" ]]; then + _completion_sync:debug_log ':completion-sync:xdg:onchange' "XDG_DATA_DIRS CHANGED" + # Check if the fpath dirs changed + local new_paths=( $(_completion_sync:functions_from_xdg_data) ) + + if [[ "$completion_sync_old_xdg_fpaths" != "$new_paths" ]]; then + _completion_sync:debug_log ':completion-sync:xdg:onchange' "Need to update FPATH from XDG_DATA_DIRS!" + + local diff=( "${(f)$(diff <(echo "${(F)new_paths}") <( echo "${(F)completion_sync_old_xdg_fpaths}") | grep -E "<|>")}" ) + _completion_sync:debug_log ':completion-sync:xdg:diff' "$diff" + + # Prepend in reverse order to maintain their order in the final path + for idx in {${#diff}..1} ; do + local p=$diff[$idx] + case "${p[1]}" in + \<) + # path got added + local p_path="${p:2}" + _completion_sync:debug_log ':completion-sync:xdg:onchange:add' "Adding path '$p_path'" + _completion_sync:debug_log ':completion-sync:fpath:add' "Adding '$p_path' to FPATH" + fpath=("$p_path" $fpath) + ;; + \>) + # path got removed + local p_path="${p:2}" + _completion_sync:debug_log ':completion-sync:xdg:onchange:delete' "Removing path '$p_path'" + _completion_sync:delete_first_from_fpath "$p_path" + ;; + *) + # This should not happen + _completion_sync:debug_log ':completion-sync:xdg:onchange' "Invalid diff line $p" + _completion_sync:debug_log ':completion-sync:xdg:onchange' "Tried to match on character ${p[1]}" + ;; + esac + done + + completion_sync_old_xdg_fpaths=( "${(@f)new_paths}" ) + else + _completion_sync:debug_log ':completion-sync:xdg:onchange' "No FPATH change needed" + fi + fi + COMPLETION_SYNC_OLD_XDG_DATA_DIRS="$XDG_DATA_DIRS" + fi + + if [[ ! -v completion_sync_old_fpath ]]; then + _completion_sync:debug_log ':completion-sync:fpath:init' "Syncing completions to fpath enabled" + # Do not re-init the first time around unless other init code extended FPATH + if [[ "$completion_sync_fpath_changed_during_init" == "true" ]]; then + _completion_sync:debug_log ':completion-sync:fpath:init' "FPATH Changed during init, reloading compsys!" + _completion_sync:compsys_reload + fi + elif [[ "$completion_sync_old_fpath" != "$fpath" ]]; then + + _completion_sync:debug_log ':completion-sync:fpath:onchange' "FPATH Changed!" + if zstyle -t ':completion-sync:fpath:onchange:diff' debug; then + diff <(echo "${(F)fpath}" | sort ) <(echo "${(F)completion_sync_old_fpath}" | sort) | grep -E "<|>" + fi + + _completion_sync:compsys_reload + fi + completion_sync_old_fpath=( "${(@f)fpath}" ) +} + +local compDumpDir="${TMPDIR:-/tmp}/per-shell-zcompdumps" +mkdir -p $compDumpDir +# Create a specific zcompdump for this pid. This allows us to use a zcompdump per shell and identify it later if desired +_per_shell_compdump="$compDumpDir/$$.zcompdump" +# Set the relevant env vars for compdump location, various plugins/mechanisms will create the compdump there +ZSH_COMPDUMP="$_per_shell_compdump" +_comp_dumpfile="$_per_shell_compdump" + +typeset -ag precmd_functions +if (( ! ${precmd_functions[(I)_completion_sync:hook]} )); then +# Add our hook last to go after _direnv_hook + precmd_functions=($precmd_functions _completion_sync:hook) +fi +typeset -ag chpwd_functions +if (( ! ${chpwd_functions[(I)_completion_sync:hook]} )); then + # Add our hook last to go after _direnv_hook + chpwd_functions=($chpwd_functions _completion_sync:hook) +fi diff --git a/modules/wm/home.nix b/modules/wm/home.nix index c41e1fe..c82df17 100644 --- a/modules/wm/home.nix +++ b/modules/wm/home.nix @@ -55,6 +55,7 @@ in { then "" else "-dark"; in "${pkgs.glib}/bin/gsettings set org.gnome.desktop.interface gtk-theme adw-gtk3${suffix}"; + kubecolor = "echo 'preset: ${theme}' > ~/.kube/color.yaml"; }; in { enable = true;