summaryrefslogtreecommitdiff
path: root/mut
diff options
context:
space:
mode:
authorMike Vink <mike1994vink@gmail.com>2023-10-06 23:10:55 +0200
committerMike Vink <mike1994vink@gmail.com>2023-10-06 23:10:55 +0200
commitcfaef26e8718916adcc68fbfb63b15f2389b2cd2 (patch)
tree3989af4514d31d0a5cb89e8b96d51210ad7bf152 /mut
parent654ec06ab6a885ea851c4cbf68d06a00b41b0e14 (diff)
move all the files
Diffstat (limited to 'mut')
-rw-r--r--mut/bin/checkout69
-rwxr-xr-xmut/bin/compile40
-rwxr-xr-xmut/bin/filter-ansi2
-rwxr-xr-xmut/bin/get-sshables7
-rwxr-xr-xmut/bin/kakup100
-rw-r--r--mut/bin/kubeconfig-merge3
-rw-r--r--mut/bin/lfub24
-rwxr-xr-xmut/bin/linkhandler26
-rw-r--r--mut/bin/mailsync112
-rw-r--r--mut/bin/maimpick18
-rwxr-xr-xmut/bin/news5
-rwxr-xr-xmut/bin/nixup94
-rw-r--r--mut/bin/notmuch-hook17
-rw-r--r--mut/bin/openfile10
-rwxr-xr-xmut/bin/pass-ansible-vault-client17
-rw-r--r--mut/bin/sb-battery37
-rw-r--r--mut/bin/sb-clock29
-rw-r--r--mut/bin/sb-internet26
-rw-r--r--mut/bin/sb-mailbox20
-rw-r--r--mut/bin/sb-nettraf29
-rw-r--r--mut/bin/sb-news17
-rw-r--r--mut/bin/set-bg15
-rw-r--r--mut/bin/spectrwmbar59
-rwxr-xr-xmut/bin/sysact21
-rwxr-xr-xmut/bin/terragrunt94
-rw-r--r--mut/bin/tmux-normal-mode28
-rw-r--r--mut/bin/transadd9
-rw-r--r--mut/emacs/init.el181
-rw-r--r--mut/neovim/README.md2
-rw-r--r--mut/neovim/compiler/ansible-lint.vim11
-rw-r--r--mut/neovim/compiler/go-test.vim14
-rw-r--r--mut/neovim/compiler/helm.vim14
-rw-r--r--mut/neovim/compiler/racket.vim26
-rw-r--r--mut/neovim/compiler/terragrunt.vim21
-rw-r--r--mut/neovim/debug8
-rw-r--r--mut/neovim/fnl/conf/diagnostic.fnl16
-rw-r--r--mut/neovim/fnl/conf/events.fnl32
-rw-r--r--mut/neovim/fnl/conf/filetype.fnl44
-rw-r--r--mut/neovim/fnl/conf/init.fnl172
-rw-r--r--mut/neovim/fnl/conf/lsp.fnl75
-rw-r--r--mut/neovim/fnl/conf/macros.fnl45
-rw-r--r--mut/neovim/fnl/conf/newtab/init.fnl36
-rw-r--r--mut/neovim/fnl/conf/nix-develop/init.fnl122
-rw-r--r--mut/neovim/fnl/conf/pkgs.fnl15
-rw-r--r--mut/neovim/fnl/conf/pkgs/cmp.fnl114
-rw-r--r--mut/neovim/fnl/conf/pkgs/conjure.fnl17
-rw-r--r--mut/neovim/fnl/conf/pkgs/dap.fnl78
-rw-r--r--mut/neovim/fnl/conf/pkgs/gitsigns.fnl2
-rw-r--r--mut/neovim/fnl/conf/pkgs/harpoon.fnl39
-rw-r--r--mut/neovim/fnl/conf/pkgs/heirline.fnl241
-rw-r--r--mut/neovim/fnl/conf/pkgs/lsp_lines.fnl2
-rw-r--r--mut/neovim/fnl/conf/pkgs/lsp_signature.fnl3
-rw-r--r--mut/neovim/fnl/conf/pkgs/lspconfig.fnl51
-rw-r--r--mut/neovim/fnl/conf/pkgs/neotest.fnl4
-rw-r--r--mut/neovim/fnl/conf/pkgs/noice.fnl34
-rw-r--r--mut/neovim/fnl/conf/pkgs/null-ls.fnl21
-rw-r--r--mut/neovim/fnl/conf/pkgs/test.fnl9
-rw-r--r--mut/neovim/fnl/conf/pkgs/tree-sitter-context.fnl2
-rw-r--r--mut/neovim/fnl/conf/pkgs/treesitter.fnl2
-rw-r--r--mut/neovim/fnl/conf/pkgs/venn.fnl18
-rw-r--r--mut/neovim/fnl/conf/settings.fnl69
-rw-r--r--mut/neovim/fnl/conf/wict-nvim/builder.fnl99
-rw-r--r--mut/neovim/fnl/conf/wict-nvim/effects.fnl81
-rw-r--r--mut/neovim/fnl/conf/wict-nvim/frames/frame.fnl61
-rw-r--r--mut/neovim/fnl/conf/wict-nvim/frames/vec.fnl28
-rw-r--r--mut/neovim/fnl/conf/wict-nvim/init.fnl31
-rw-r--r--mut/neovim/fnl/conf/wictl-nvim/init.fnl58
-rw-r--r--mut/neovim/fnl/conf/wictl-nvim/resolvers.fnl5
-rw-r--r--mut/neovim/fnl/conf/wictl-nvim/term.fnl54
-rw-r--r--mut/neovim/init.fnl36
-rw-r--r--mut/neovim/init.lua46
-rw-r--r--mut/neovim/test.py0
72 files changed, 2967 insertions, 0 deletions
diff --git a/mut/bin/checkout b/mut/bin/checkout
new file mode 100644
index 0000000..95f28c8
--- /dev/null
+++ b/mut/bin/checkout
@@ -0,0 +1,69 @@
+#!@bash@/bin/bash
+error () {
+ echo "$1"
+ exit 1
+}
+
+. <(pass show work/env)
+DEST_DIR=""
+case "${@}" in
+ az|"az "*)
+ shift
+ LIST_PROJECTS="/_apis/projects?api-version=7.1-preview.4"
+ AUTH_HEADER="Authorization: Basic $(echo -n ":$GIT_PASS" | base64)"
+ LIST_REPOSITORIES="/_apis/git/repositories?api-version=7.1-preview.1"
+ GIT_DIR="$HOME/projects/"
+ if [ ! -d $GIT_DIR ]; then
+ mkdir -p $GIT_DIR
+ fi
+ MAX_REPOS=20
+
+ echo "curl -s -H \"$AUTH_HEADER\" $WORK_AZDO_GIT_ORG_URL$LIST_PROJECTS"
+ PROJECT=$(curl -s -H "$AUTH_HEADER" $WORK_AZDO_GIT_ORG_URL$LIST_PROJECTS \
+ | jq '
+ .value[].name
+ ' \
+ | xargs -I{} bash -c "
+ curl -s -H '$AUTH_HEADER' $WORK_AZDO_GIT_ORG_URL/{}$LIST_REPOSITORIES \
+ | jq '
+ .value[].name
+ ' \
+ | awk '{ gsub(/\"/, \"\", \$1); printf \"{}/_git/%s\\n\", \$1 }'
+ " \
+ | fzf)
+
+ DEST_DIR="$GIT_DIR/$(echo $PROJECT | cut -d '/' -f3)"
+ if [ ! -d $DEST_DIR ]
+ then
+ git clone --bare $WORK_AZDO_GIT_ORG_URL/$PROJECT $DEST_DIR
+ fi
+ ;;
+ gh|"gh "*)
+ shift
+ repo=$(gh repo list --json owner,name -q '.[] | "\(.owner.login)/\(.name)"' | fzf --print-query -1)
+ GIT_DIR="$HOME/projects"
+ if [ ! -d $GIT_DIR ]; then
+ mkdir -p $GIT_DIR
+ fi
+
+ if [[ "$(echo "$repo" | wc -l)" -ne 1 ]]; then
+ echo "Fetching my repo"
+ repo="$(echo "$repo" | tail -n1)"
+ fi
+
+ DEST_DIR="$GIT_DIR/$(echo $repo | cut -d '/' -f2)"
+ if [ ! -d $DEST_DIR ]
+ then
+ gh repo clone $repo $DEST_DIR -- --bare
+ fi
+ ;;
+ *)
+ error "Don't know how to fetch this"
+ ;;
+esac
+
+if ! [[ -z "$DEST_DIR" ]]; then
+ cd $DEST_DIR
+ git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
+ $EDITOR "$DEST_DIR"
+fi
diff --git a/mut/bin/compile b/mut/bin/compile
new file mode 100755
index 0000000..04c0586
--- /dev/null
+++ b/mut/bin/compile
@@ -0,0 +1,40 @@
+#!@bash@/bin/bash
+echo " Compiliiing ${@}"
+
+error () {
+ echo "$1"
+ exit 1
+}
+
+case "${@}" in
+ racket*)
+ shift
+ echo " \-> racket -l errortrace -t ${@}"
+ racket -l errortrace -t ${@}
+ ;;
+ ansible-lint*)
+ shift
+ echo " \-> ansible-lint --profile production --write=all -qq --nocolor"
+ ansible-lint --profile production --write=all -qq --nocolor ${@}
+ ;;
+ ansible-playbook*)
+ shift
+ echo " \-> ansible-playbook -e@<(pass)"
+ ansible-playbook -b -e "{\"ansible_become_pass\":\"$PASSWORD\"}" ${@}
+ ;;
+ awx*)
+ echo " \-> awx"
+ shift
+ awx "$@" | filter-ansi
+ ;;
+ helm\ lint*)
+ shift
+ shift
+ echo " \-> helm lint --set cluster=debug-cluster --strict --quiet --with-subcharts ${@}"
+ helm lint --set cluster=debug-cluster --strict --quiet --with-subcharts ${@} | sed -u -E -e "s@$(basename ${PWD})/|error during tpl function execution for \".*\"@@g"
+ ;;
+ *)
+ echo " \-> ${@}"
+ ${@}
+ ;;
+esac
diff --git a/mut/bin/filter-ansi b/mut/bin/filter-ansi
new file mode 100755
index 0000000..369f9fd
--- /dev/null
+++ b/mut/bin/filter-ansi
@@ -0,0 +1,2 @@
+# #!@bash@/bin/bash
+cat -u - | sed -u -E -e 's/\x1b\[[0-9;]*[mGKHF]|\r//g'
diff --git a/mut/bin/get-sshables b/mut/bin/get-sshables
new file mode 100755
index 0000000..f67c23c
--- /dev/null
+++ b/mut/bin/get-sshables
@@ -0,0 +1,7 @@
+#!/bin/bash
+set -euxo pipefail
+[[ -d ~/sshables ]] || mkdir -p ~/sshables
+
+for cluster in $(kubectl config get-clusters | tail -n +2); do
+ [[ -f ~/sshables/$cluster ]] || { echo $cluster; kubectl --context $cluster get nodes -oname > ~/sshables/$cluster; }
+done
diff --git a/mut/bin/kakup b/mut/bin/kakup
new file mode 100755
index 0000000..af1a520
--- /dev/null
+++ b/mut/bin/kakup
@@ -0,0 +1,100 @@
+#!@bash@/bin/bash
+session-or-client() {
+ {
+ project="$(cat -)"
+ if [[ -z $project ]]; then
+ return
+ fi
+ pushd $project
+ name=${PWD#$HOME/}
+ name=${name//\//-}
+ name=${name#-}
+ server=kaks@$name
+ client=kakc@$name
+ TMUX_ENV="-e KAK_SERVER=$server -e KAK_CLIENT=$client"
+
+ tmux has-session -t $server || {
+ tmux new $TMUX_ENV -d -s $server -n $server bash -c '[[ -f .envrc ]] && eval "$(direnv export bash)"; { kak -s '$name' -d & }; tmux wait -S '$name'; wait'
+ tmux wait "$name"
+ }
+ if [[ -z $TMUX ]] || [ $SWITCH_TO_SESSION -eq 1 ]; then
+ tmux has-session -t $client || tmux new $TMUX_ENV -d -s $client -n $client kak -c $name
+ fi
+ popd
+ } </dev/stdin >debug 2>&1
+ echo $client
+}
+
+search() {
+ if tty -s
+ then
+ project="$(fd -d1 "." -t d $HOME $HOME/projects | fzf -1)"
+ else
+ output=$(mktemp -d /tmp/kakup.XXXXXXXX)/fifo
+ mkfifo ${output}
+ st -e bash -c "fd -d1 '.' -t d $HOME $HOME/projects | fzf -1 | tee ${output} >/dev/null 2>&1" &
+ project="$(cat ${output})"
+ rm -r $(dirname ${output})
+ fi
+
+ pushd $project >/dev/null 2>&1
+ if grep 'bare = true' config >/dev/null 2>&1 ; then
+ if tty -s
+ then
+ branch="$(git branch -a --format '%(refname)' | fzf -1)"
+ else
+ output=$(mktemp -d /tmp/kakup.XXXXXXXX)/fifo
+ mkfifo ${output}
+ st -e bash -c "git branch -a --format '%(refname)' | fzf -1 >${output}" &
+ branch="$(cat ${output})"
+ rm -r $(dirname ${output})
+ fi
+ echo "$branch" >debug 2>&1
+ if [[ "$branch" == "refs/remotes/"* ]]; then
+ git branch ${branch#refs/remotes/*/} -t $branch >debug 2>&1
+ git worktree add ${branch#refs/remotes/*/} ${branch#refs/remotes/*/} >debug 2>&1
+ branch="${branch#refs/remotes/*/}"
+ elif [[ "$branch" == "refs/heads/"* ]]; then
+ branch="${branch#refs/heads/}"
+ git worktree add $branch $branch >debug 2>&1
+ fi
+ echo "$project/$branch"
+ else
+ echo "$project"
+ fi
+ popd >/dev/null 2>&1
+}
+
+NEW_TERM=0
+SWITCH_TO_SESSION=0
+while getopts "tfF" opt; do
+ case "$opt" in
+ h|\?) exit 0 ;;
+ t) NEW_TERM=1 ;;
+ f) client="$(search | session-or-client)" ;;
+ F) SWITCH_TO_SESSION=1; client="$(search | session-or-client)" ;;
+ esac
+done
+
+shift $((OPTIND - 1))
+
+[ -z "$client" ] && {
+ case "${@}" in
+ "") client="$(pwd | session-or-client)" ;;
+ *) client="$(echo "${@}" | session-or-client)" ;;
+ esac
+}
+
+[[ ! -z "$client" ]] && {
+ if [ $NEW_TERM -eq 1 ]; then
+ st -e tmux attach -t "$client"
+ elif [[ -z $TMUX ]]; then
+ tmux attach -t "$client"
+ else
+ if [ $SWITCH_TO_SESSION -eq 0 ]; then
+ tmux new-window -n $client kak -c ${client##kakc@}
+ else
+ tmux switch -t $client
+ fi
+ fi
+}
diff --git a/mut/bin/kubeconfig-merge b/mut/bin/kubeconfig-merge
new file mode 100644
index 0000000..73d3ac1
--- /dev/null
+++ b/mut/bin/kubeconfig-merge
@@ -0,0 +1,3 @@
+#!@bash@/bin/bash
+cp $HOME/.kube/config /tmp/.kube_config
+KUBECONFIG=$1:/tmp/.kube_config kubectl config view --flatten > $HOME/.kube/config
diff --git a/mut/bin/lfub b/mut/bin/lfub
new file mode 100644
index 0000000..9012f50
--- /dev/null
+++ b/mut/bin/lfub
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+# This is a wrapper script for lb that allows it to create image previews with
+# ueberzug. This works in concert with the lf configuration file and the
+# lf-cleaner script.
+
+set -e
+
+cleanup() {
+ exec 3>&-
+ rm "$FIFO_UEBERZUG"
+}
+
+if [ -n "$SSH_CLIENT" ] || [ -n "$SSH_TTY" ]; then
+ lf "$@"
+else
+ [ ! -d "$HOME/.cache/lf" ] && mkdir -p "$HOME/.cache/lf"
+ export FIFO_UEBERZUG="$HOME/.cache/lf/ueberzug-$$"
+ mkfifo "$FIFO_UEBERZUG"
+ ueberzug layer -s <"$FIFO_UEBERZUG" -p json &
+ exec 3>"$FIFO_UEBERZUG"
+ trap cleanup HUP INT QUIT TERM PWR EXIT
+ lf "$@" 3>&-
+fi
diff --git a/mut/bin/linkhandler b/mut/bin/linkhandler
new file mode 100755
index 0000000..f62b581
--- /dev/null
+++ b/mut/bin/linkhandler
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+# Feed script a url or file location.
+# If an image, it will view in sxiv,
+# if a video or gif, it will view in mpv
+# if a music file or pdf, it will download,
+# otherwise it opens link in browser.
+
+if [ -z "$1" ]; then
+ url="$(xclip -o)"
+else
+ url="$1"
+fi
+
+case "$url" in
+ *mkv|*webm|*mp4|*youtube.com/watch*|*youtube.com/playlist*|*youtube.com/shorts*|*youtu.be*|*hooktube.com*|*bitchute.com*|*videos.lukesmith.xyz*|*odysee.com*)
+ setsid -f mpv -quiet "$url" >/dev/null 2>&1 ;;
+ *png|*jpg|*jpe|*jpeg|*gif)
+ curl -sL "$url" > "/tmp/$(echo "$url" | sed "s/.*\///;s/%20/ /g")" && sxiv -a "/tmp/$(echo "$url" | sed "s/.*\///;s/%20/ /g")" >/dev/null 2>&1 & ;;
+ *pdf|*cbz|*cbr)
+ curl -sL "$url" > "/tmp/$(echo "$url" | sed "s/.*\///;s/%20/ /g")" && zathura "/tmp/$(echo "$url" | sed "s/.*\///;s/%20/ /g")" >/dev/null 2>&1 & ;;
+ *mp3|*flac|*opus|*mp3?source*)
+ qndl "$url" 'curl -LO' >/dev/null 2>&1 ;;
+ *)
+ [ -f "$url" ] && setsid -f "$TERMINAL" -e "$EDITOR" "$url" >/dev/null 2>&1 || setsid -f "$BROWSER" "$url" >/dev/null 2>&1
+esac
diff --git a/mut/bin/mailsync b/mut/bin/mailsync
new file mode 100644
index 0000000..426e5b7
--- /dev/null
+++ b/mut/bin/mailsync
@@ -0,0 +1,112 @@
+#!/bin/sh
+
+# - Syncs mail for all accounts, or a single account given as an argument.
+# - Displays a notification showing the number of new mails.
+# - Displays a notification for each new mail with its subject displayed.
+# - Runs notmuch to index new mail.
+# - This script can be set up as a cron job for automated mail syncing.
+
+# There are many arbitrary and ugly features in this script because it is
+# inherently difficult to pass environmental variables to cronjobs and other
+# issues. It also should at least be compatible with Linux (and maybe BSD) with
+# Xorg and MacOS as well.
+
+# Run only if not already running in other instance
+pgrep mbsync >/dev/null && { echo "mbsync is already running."; exit ;}
+
+# First, we have to get the right variables for the mbsync file, the pass
+# archive, notmuch and the GPG home. This is done by searching common profile
+# files for variable assignments. This is ugly, but there are few options that
+# will work on the maximum number of machines.
+eval "$(grep -h -- \
+ "^\s*\(export \)\?\(MBSYNCRC\|MPOPRC\|PASSWORD_STORE_DIR\|PASSWORD_STORE_GPG_OPTS\|NOTMUCH_CONFIG\|GNUPGHOME\|MAILSYNC_MUTE\|XDG_CONFIG_HOME\|XDG_DATA_HOME\)=" \
+ "$HOME/.profile" "$HOME/.bash_profile" "$HOME/.zprofile" "$HOME/.config/zsh/.zprofile" "$HOME/.zshenv" \
+ "$HOME/.config/zsh/.zshenv" "$HOME/.bashrc" "$HOME/.zshrc" "$HOME/.config/zsh/.zshrc" \
+ "$HOME/.pam_environment" 2>/dev/null)"
+
+export GPG_TTY="$(tty)"
+
+[ -n "$MBSYNCRC" ] && alias mbsync="mbsync -c $MBSYNCRC" || MBSYNCRC="$HOME/.mbsyncrc"
+[ -n "$MPOPRC" ] || MPOPRC="$HOME/.config/mpop/config"
+
+lastrun="${XDG_CONFIG_HOME:-$HOME/.config}/neomutt/.mailsynclastrun"
+
+# Settings are different for MacOS (Darwin) systems.
+case "$(uname)" in
+ Darwin) notify() { osascript -e "display notification \"$2\" with title \"$1\"" ;} ;;
+ *)
+ case "$(readlink -f /sbin/init)" in
+ *systemd*|*openrc*) export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$(id -u)/bus ;;
+ esac
+ # remember if a display server is running since `ps` doesn't always contain a display
+ pgrepoutput="$(pgrep -ax X\(\|org\|wayland\))"
+ displays="$(echo "$pgrepoutput" | grep -wo "[0-9]*:[0-9]\+" | sort -u)"
+ [ -z "$displays" ] && [ -d /tmp/.X11-unix ] && displays=$(cd /tmp/.X11-unix && for x in X*; do echo ":${x#X}"; done)
+
+ notify() { [ -n "$pgrepoutput" ] && for x in ${displays:-:0}; do
+ export DISPLAY="$x"
+ notify-send --app-name="mutt-wizard" "$1" "$2"
+ done ;}
+ ;;
+esac
+
+# Check account for new mail. Notify if there is new content.
+syncandnotify() {
+ case "$1" in
+ imap) mbsync -q "$2" ;;
+ pop) mpop -q "$2" ;;
+ esac
+ new=$(find\
+ "$HOME/.local/share/mail/${2%%-*}/"[Ii][Nn][Bb][Oo][Xx]/new/ \
+ "$HOME/.local/share/mail/${2%%-*}/"[Ii][Nn][Bb][Oo][Xx]/cur/ \
+ -type f -newer "$lastrun" 2> /dev/null)
+ newcount=$(echo "$new" | sed '/^\s*$/d' | wc -l)
+ case 1 in
+ $((newcount > 5)) )
+ echo "$newcount new mail for $2."
+ [ -z "$MAILSYNC_MUTE" ] && notify "New Mail!" "📬 $newcount new mail(s) in \`$2\` account."
+ ;;
+ $((newcount > 0)) )
+ echo "$newcount new mail for $2."
+ [ -z "$MAILSYNC_MUTE" ] &&
+ for file in $new; do
+ # Extract and decode subject and sender from mail.
+ subject="$(sed -n "/^Subject:/ s|Subject: *|| p" "$file" |
+ perl -CS -MEncode -ne 'print decode("MIME-Header", $_)')"
+ from="$(sed -n "/^From:/ s|From: *|| p" "$file" |
+ perl -CS -MEncode -ne 'print decode("MIME-Header", $_)')"
+ from="${from% *}" ; from="${from%\"}" ; from="${from#\"}"
+ notify "📧$from:" "$subject"
+ done
+ ;;
+ *) echo "No new mail for $2." ;;
+esac
+}
+
+allgroups="$(grep -hs "Group" "$MBSYNCRC" "$MPOPRC" | sort -u)"
+
+# Get accounts to sync. All if no argument. Prefix with `error` if non-existent.
+IFS='
+'
+if [ -z "$1" ]; then
+ tosync="$allgroups"
+else
+ tosync="$(for arg in "$@"; do for grp in $allgroups; do
+ [ "$arg" = "${grp##* }" ] && echo "$grp" && break
+ done || echo "error $arg"; done)"
+fi
+
+for grp in $tosync; do
+ case $grp in
+ Group*) syncandnotify imap "${grp##* }" & ;;
+ account*) syncandnotify pop "${grp##* }" & ;;
+ error*) echo "ERROR: Account ${channelt##* } not found." ;;
+ esac
+done
+
+wait
+
+notmuch-hook
+
+#Create a touch file that indicates the time of the last run of mailsync
+touch "$lastrun"
diff --git a/mut/bin/maimpick b/mut/bin/maimpick
new file mode 100644
index 0000000..5de26c1
--- /dev/null
+++ b/mut/bin/maimpick
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# This is bound to Shift+PrintScreen by default, requires maim. It lets you
+# choose the kind of screenshot to take, including copying the image or even
+# highlighting an area to copy. scrotcucks on suicidewatch right now.
+
+# variables
+output="$(date '+%y%m%d-%H%M-%S').png"
+xclip_cmd="xclip -sel clip -t image/png"
+
+case "$(printf "a selected area\\ncurrent window\\nfull screen\\na selected area (copy)\\ncurrent window (copy)\\nfull screen (copy)" | dmenu -l 6 -i -p "Screenshot which area?")" in
+ "a selected area") maim -u -s pic-selected-"${output}" ;;
+ "current window") maim -q -d 0.2 -i "$(xdotool getactivewindow)" pic-window-"${output}" ;;
+ "full screen") maim -q -d 0.2 pic-full-"${output}" ;;
+ "a selected area (copy)") maim -u -s | ${xclip_cmd} ;;
+ "current window (copy)") maim -q -d 0.2 -i "$(xdotool getactivewindow)" | ${xclip_cmd} ;;
+ "full screen (copy)") maim -q -d 0.2 | ${xclip_cmd} ;;
+esac
diff --git a/mut/bin/news b/mut/bin/news
new file mode 100755
index 0000000..097582b
--- /dev/null
+++ b/mut/bin/news
@@ -0,0 +1,5 @@
+#!@bash@/bin/bash
+cat <(cat ~/.config/newsboat/urls) <(for url in $(env | grep NEWSBOAT_URL_); do
+ printf '%s\n' ${url#NEWSBOAT_URL_*=}
+done) > ~/.newsboat-urls
+newsboat -u ~/.newsboat-urls
diff --git a/mut/bin/nixup b/mut/bin/nixup
new file mode 100755
index 0000000..afbe4b1
--- /dev/null
+++ b/mut/bin/nixup
@@ -0,0 +1,94 @@
+#!@bash@/bin/bash
+case "${@}" in
+ bootstrap-store)
+ [[ -d ${HOME}/nix ]] || {
+ docker create --name nix-data-${USER} nixos/nix sh >/dev/null 2>&1
+ sudo docker cp nix-data-${USER}:/nix ~
+ docker rm nix-data-${USER}
+ }
+ docker create -v ${HOME}/nix:/nix --name nix-data-${USER} nixos/nix sh
+ ;;
+ nuke)
+ docker rm nix-data-${USER}
+ docker rm nixos-${USER}
+ ;;
+ "")
+ if ! docker image ls | grep nixos-${USER}; then
+ cat > /tmp/docker-build-${USER} <<EOF
+FROM alpine
+
+# Enable HTTPS support in wget and set nsswitch.conf to make resolution work within containers
+RUN apk add --no-cache --update openssl \
+ && echo hosts: files dns > /etc/nsswitch.conf
+
+# Download Nix and install it into the system.
+ARG NIX_VERSION=2.3.14
+RUN wget https://nixos.org/releases/nix/nix-\${NIX_VERSION}/nix-\${NIX_VERSION}-\$(uname -m)-linux.tar.xz \
+ && tar xf nix-\${NIX_VERSION}-\$(uname -m)-linux.tar.xz \
+ && addgroup -g 30000 -S nixbld \
+ && for i in \$(seq 1 30); do adduser -S -D -h /var/empty -g "Nix build user \$i" -u \$((30000 + i)) -G nixbld nixbld\$i ; done \
+ && mkdir -m 0755 /etc/nix \
+ && echo 'sandbox = false' > /etc/nix/nix.conf \
+ && mkdir -m 0755 /nix && USER=root sh nix-\${NIX_VERSION}-\$(uname -m)-linux/install \
+ && ln -s /nix/var/nix/profiles/default/etc/profile.d/nix.sh /etc/profile.d/ \
+ && rm -r /nix-\${NIX_VERSION}-\$(uname -m)-linux* \
+ && /nix/var/nix/profiles/default/bin/nix-collect-garbage --delete-old \
+ && /nix/var/nix/profiles/default/bin/nix-store --optimise \
+ && /nix/var/nix/profiles/default/bin/nix-store --verify --check-contents
+
+# Somehow this file is missing?
+RUN mkdir -p /etc/bash && touch /etc/bash/bashrc
+
+ONBUILD ENV \
+ ENV=/etc/profile \
+ USER=root \
+ PATH=/nix/var/nix/profiles/default/bin:/nix/var/nix/profiles/default/sbin:/bin:/sbin:/usr/bin:/usr/sbin \
+ GIT_SSL_CAINFO=/etc/ssl/certs/ca-certificates.crt \
+ NIX_SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt
+
+ENV \
+ ENV=/etc/profile \
+ USER=root \
+ PATH=/nix/var/nix/profiles/default/bin:/nix/var/nix/profiles/default/sbin:/bin:/sbin:/usr/bin:/usr/sbin \
+ GIT_SSL_CAINFO=/etc/ssl/certs/ca-certificates.crt \
+ NIX_SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt \
+ NIX_PATH=/nix/var/nix/profiles/per-user/root/channels
+
+# Add your user the alpine way
+RUN apk add --no-cache --update shadow \
+ && groupadd -g $(getent group docker | cut -d: -f3) docker \
+ && groupadd -g $(id -g) ${USER} \
+ && useradd -g $(id -g) --groups wheel,docker -u $(id -u) ${USER} \
+ && rm -rf /var/cache/apk/*
+EOF
+ docker build . -t nixos-${USER} -f /tmp/docker-build-${USER}
+ fi
+ docker run --volumes-from=nix-data-${USER} --rm -it \
+ -v /var/run/docker.sock:/var/run/docker.sock \
+ -v /etc/kube:/etc/kube \
+ -v /etc/ssl/certs/ca-bundle.crt:/etc/ssl/certs/ca-bundle.crt \
+ -v /etc/ssl/certs/ca-bundle.crt:/etc/ssl/certs/ca-certificates.crt \
+ -e GIT_SSL_CAINFO=/etc/ssl/certs/ca-bundle.crt \
+ -e NIX_SSL_CERT_FILE=/etc/ssl/certs/ca-bundle.crt \
+ -e SSL_CERT_FILE=/etc/ssl/certs/ca-bundle.crt \
+ -e no_proxy=$no_proxy \
+ -e http_proxy=$http_proxy \
+ -e https_proxy=$http_proxy \
+ -e SHELL=bash \
+ -e USER=${USER} \
+ -u $(id -u):$(id -g) \
+ --group-add wheel \
+ --group-add docker \
+ -v ${HOME}:${HOME} \
+ -w ${HOME} \
+ --name nixos-${USER} \
+ --network host \
+ nixos-${USER} bash --login
+ ;;
+ clear)
+ docker run --rm --volumes-from=nix-data-${USER} nixos/nix nix-collect-garbage -d
+ ;;
+ list)
+ docker run --rm --volumes-from nix-data-${USER} nixos/nix ls -la /nix
+ ;;
+esac
diff --git a/mut/bin/notmuch-hook b/mut/bin/notmuch-hook
new file mode 100644
index 0000000..da376b6
--- /dev/null
+++ b/mut/bin/notmuch-hook
@@ -0,0 +1,17 @@
+. <(pass show personal/notmuch)
+notmuch new --quiet
+notmuch tag -new +unread +jobs -- 'tag:new and (from:jobs-listings* or from:jobs-noreply*)'
+notmuch tag -new +unread +houses -- 'tag:new and (from:"'$MAKELAAR'" or thread:{'$MAKELAAR'})'
+notmuch tag -new -inbox +unread +dev -- 'tag:new and (from:/.*github.com/ or thread:{from:/.*github.com/})'
+
+notmuch tag -new +inbox +unread -- tag:new
+
+# Gmail + mbsync = a lot of duplicates due to the archive
+notmuch tag -new -inbox +archive -- 'folder:/Archive/ -folder:/Inbox/ -folder:/\[Gmail\]/ -folder:/FarDrafts/ -folder:/Important/ -folder:/Sent/'
+
+# Tag messages with files that were moved to trash in neomutt
+notmuch tag --remove-all +trash -- folder:/Trash/
+# Same but with messages with files that were moved to spam
+notmuch tag --remove-all +spam -- folder:/Spam/
+# Remove files of messages that were tagged but still have files left behind in the mailbox, should be fine since gmail already keeps a duplicate in the Archive so the message will not be deleted only one file of the message
+notmuch search --output=files -- 'folder:/Inbox/ -tag:inbox' | grep Inbox | xargs >/dev/null 2>&1 rm
diff --git a/mut/bin/openfile b/mut/bin/openfile
new file mode 100644
index 0000000..0f60b10
--- /dev/null
+++ b/mut/bin/openfile
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+# Helps open a file with xdg-open from mutt in a external program without weird side effects.
+tempdir="${XDG_CACHE_HOME:-$HOME/.cache}/mutt-wizard/files"
+file="$tempdir/${1##*/}"
+[ "$(uname)" = "Darwin" ] && opener="open" || opener="setsid -f xdg-open"
+mkdir -p "$tempdir"
+cp -f "$1" "$file"
+$opener "$file" >/dev/null 2>&1
+find "${tempdir:?}" -mtime +1 -type f -delete
diff --git a/mut/bin/pass-ansible-vault-client b/mut/bin/pass-ansible-vault-client
new file mode 100755
index 0000000..8b8d026
--- /dev/null
+++ b/mut/bin/pass-ansible-vault-client
@@ -0,0 +1,17 @@
+#!@bash@/bin/bash
+VAULT_ID=""
+while [[ $# -gt 0 ]]; do
+ case $1 in
+ --vault-id)
+ VAULT_ID=$2
+ shift
+ shift
+ ;;
+ --vault-id=*)
+ VAULT_ID="${1#*=}"
+ shift
+ ;;
+ esac
+done
+
+pass show work/ansible-vault/$VAULT_ID
diff --git a/mut/bin/sb-battery b/mut/bin/sb-battery
new file mode 100644
index 0000000..aeb7413
--- /dev/null
+++ b/mut/bin/sb-battery
@@ -0,0 +1,37 @@
+#!/bin/sh
+
+# Prints all batteries, their percentage remaining and an emoji corresponding
+# to charge status (🔌 for plugged up, 🔋 for discharging on battery, etc.).
+
+case $BUTTON in
+ 3) notify-send "🔋 Battery module" "🔋: discharging
+🛑: not charging
+♻: stagnant charge
+🔌: charging
+⚡: charged
+❗: battery very low!
+- Scroll to change adjust xbacklight." ;;
+ 4) xbacklight -inc 10 ;;
+ 5) xbacklight -dec 10 ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+# Loop through all attached batteries and format the info
+for battery in /sys/class/power_supply/BAT?*; do
+ # If non-first battery, print a space separator.
+ [ -n "${capacity+x}" ] && printf " "
+ # Sets up the status and capacity
+ case "$(cat "$battery/status" 2>&1)" in
+ "Full") status="⚡" ;;
+ "Discharging") status="🔋" ;;
+ "Charging") status="🔌" ;;
+ "Not charging") status="🛑" ;;
+ "Unknown") status="♻️" ;;
+ *) exit 1 ;;
+ esac
+ capacity="$(cat "$battery/capacity" 2>&1)"
+ # Will make a warn variable if discharging and low
+ [ "$status" = "🔋" ] && [ "$capacity" -le 25 ] && warn="❗"
+ # Prints the info
+ printf "%s%s%d%%" "$status" "$warn" "$capacity"; unset warn
+done && printf "\\n"
diff --git a/mut/bin/sb-clock b/mut/bin/sb-clock
new file mode 100644
index 0000000..ba9e43d
--- /dev/null
+++ b/mut/bin/sb-clock
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+clock=$(date '+%I')
+
+case "$clock" in
+ "00") icon="🕛" ;;
+ "01") icon="🕐" ;;
+ "02") icon="🕑" ;;
+ "03") icon="🕒" ;;
+ "04") icon="🕓" ;;
+ "05") icon="🕔" ;;
+ "06") icon="🕕" ;;
+ "07") icon="🕖" ;;
+ "08") icon="🕗" ;;
+ "09") icon="🕘" ;;
+ "10") icon="🕙" ;;
+ "11") icon="🕚" ;;
+ "12") icon="🕛" ;;
+esac
+
+case $BUTTON in
+ 1) notify-send "This Month" "$(cal --color=always | sed "s/..7m/<b><span color=\"cyan\">/;s|..0m|</span></b>|")" && notify-send "Appointments" "$(calcurse -d3)" ;;
+ 2) setsid -f "$TERMINAL" -e calcurse ;;
+ 3) notify-send "📅 Time/date module" "\- Left click to show upcoming appointments for the next three days via \`calcurse -d3\` and show the month via \`cal\`
+- Middle click opens calcurse if installed" ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+date "+%Y %b %d (%a) $icon%I:%M%p"
diff --git a/mut/bin/sb-internet b/mut/bin/sb-internet
new file mode 100644
index 0000000..225d376
--- /dev/null
+++ b/mut/bin/sb-internet
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+# Show wifi 📶 and percent strength or 📡 if none.
+# Show 🌐 if connected to ethernet or ❎ if none.
+# Show 🔒 if a vpn connection is active
+
+case $BUTTON in
+ 1) "$TERMINAL" -e nmtui; pkill -RTMIN+4 dwmblocks ;;
+ 3) notify-send "🌐 Internet module" "\- Click to connect
+❌: wifi disabled
+📡: no wifi connection
+📶: wifi connection with quality
+❎: no ethernet
+🌐: ethernet working
+🔒: vpn is active
+" ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+if grep -xq 'up' /sys/class/net/w*/operstate 2>/dev/null ; then
+ wifiicon="$(awk '/^\s*w/ { print "📶", int($3 * 100 / 70) "% " }' /proc/net/wireless)"
+elif grep -xq 'down' /sys/class/net/w*/operstate 2>/dev/null ; then
+ grep -xq '0x1003' /sys/class/net/w*/flags && wifiicon="📡 " || wifiicon="❌ "
+fi
+
+printf "%s%s%s\n" "$wifiicon" "$(sed "s/down/❎/;s/up/🌐/" /sys/class/net/e*/operstate 2>/dev/null)" "$(sed "s/.*/🔒/" /sys/class/net/tun*/operstate 2>/dev/null)"
diff --git a/mut/bin/sb-mailbox b/mut/bin/sb-mailbox
new file mode 100644
index 0000000..ab1669e
--- /dev/null
+++ b/mut/bin/sb-mailbox
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+# Displays number of unread mail and an loading icon if updating.
+# When clicked, brings up `neomutt`.
+
+case $BUTTON in
+ 1) setsid -f "$TERMINAL" -e neomutt ;;
+ 2) setsid -f mailsync >/dev/null ;;
+ 3) notify-send "📬 Mail module" "\- Shows unread mail
+- Shows 🔃 if syncing mail
+- Left click opens neomutt
+- Middle click syncs mail" ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+unread="$(find "${XDG_DATA_HOME:-$HOME/.local/share}"/mail/*/[Ii][Nn][Bb][Oo][Xx]/new/* -type f | wc -l 2>/dev/null)"
+
+pidof mbsync >/dev/null 2>&1 && icon="🔃"
+
+[ "$unread" = "0" ] && [ "$icon" = "" ] || echo "📬$unread$icon"
diff --git a/mut/bin/sb-nettraf b/mut/bin/sb-nettraf
new file mode 100644
index 0000000..06b3c49
--- /dev/null
+++ b/mut/bin/sb-nettraf
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+# Module showing network traffic. Shows how much data has been received (RX) or
+# transmitted (TX) since the previous time this script ran. So if run every
+# second, gives network traffic per second.
+
+case $BUTTON in
+ 1) setsid -f "$TERMINAL" -e bmon ;;
+ 3) notify-send "🌐 Network traffic module" "🔻: Traffic received
+🔺: Traffic transmitted" ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+update() {
+ sum=0
+ for arg; do
+ read -r i < "$arg"
+ sum=$(( sum + i ))
+ done
+ cache=/tmp/${1##*/}
+ [ -f "$cache" ] && read -r old < "$cache" || old=0
+ printf %d\\n "$sum" > "$cache"
+ printf %d\\n $(( sum - old ))
+}
+
+rx=$(update /sys/class/net/[ew]*/statistics/rx_bytes)
+tx=$(update /sys/class/net/[ew]*/statistics/tx_bytes)
+
+printf "🔻%4sB 🔺%4sB\\n" $(numfmt --to=iec $rx $tx)
diff --git a/mut/bin/sb-news b/mut/bin/sb-news
new file mode 100644
index 0000000..a155c0a
--- /dev/null
+++ b/mut/bin/sb-news
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+# Displays number of unread news items and an loading icon if updating.
+# When clicked, brings up `newsboat`.
+
+case $BUTTON in
+ 1) setsid "$TERMINAL" -e newsboat ;;
+ 2) setsid -f newsup >/dev/null exit ;;
+ 3) notify-send "📰 News module" "\- Shows unread news items
+- Shows 🔃 if updating with \`newsup\`
+- Left click opens newsboat
+- Middle click syncs RSS feeds
+<b>Note:</b> Only one instance of newsboat (including updates) may be running at a time." ;;
+ 6) "$TERMINAL" -e "$EDITOR" "$0" ;;
+esac
+
+ cat /tmp/newsupdate 2>/dev/null || echo "$(newsboat -x print-unread | awk '{ if($1>0) print "📰" $1}')$(cat "${XDG_CONFIG_HOME:-$HOME/.config}"/newsboat/.update 2>/dev/null)"
diff --git a/mut/bin/set-bg b/mut/bin/set-bg
new file mode 100644
index 0000000..bede726
--- /dev/null
+++ b/mut/bin/set-bg
@@ -0,0 +1,15 @@
+#!@bash@/bin/bash
+reload=0
+while getopts "r" opt; do
+ case "$opt" in
+ h|\?) exit 0 ;;
+ r) reload=1 ;;
+ esac
+done
+if [ $reload -eq 1 ]; then
+ # (cat ~/.cache/wal/sequences &)
+ wal -R
+else
+ sxiv -tob ~/bg | parallel wal -i
+fi
+kak -l | parallel '<<< "colorscheme wal" kak -p {}'
diff --git a/mut/bin/spectrwmbar b/mut/bin/spectrwmbar
new file mode 100644
index 0000000..a106b01
--- /dev/null
+++ b/mut/bin/spectrwmbar
@@ -0,0 +1,59 @@
+#!/usr/bin/env sh
+# script for spectrwm status bar
+
+trap 'update' 5
+
+fgcolors=("+@fg=1;" "+@fg=2;" "+@fg=3;" "+@fg=4;" "+@fg=5;" "+@fg=6;" "+@fg=7;" "+@fg=8;")
+nfgcolors=${#fgcolors[@]}
+
+SLEEP_SEC=5m
+
+repeat() {
+ i=0; while [ $i -lt $1 ]
+ do
+ echo -ne "$TOKEN"
+ i=$(( i + 1 ))
+ done
+}
+
+cpu() {
+ read cpu a b c previdle rest < /proc/stat
+ prevtotal=$((a+b+c+previdle))
+ sleep 0.5
+ read cpu a b c idle rest < /proc/stat
+ total=$((a+b+c+idle))
+ cpu=$((100*( (total-prevtotal) - (idle-previdle) ) / (total-prevtotal) ))
+ echo -e "CPU: $cpu%"
+}
+
+battery() {
+ BATTERY="$(cat /sys/class/power_supply/BAT0/capacity)"
+
+ BAR_LEFT=$BATTERY
+ BATTERY_BAR=""
+ BLOCK=$(( 100 / nfgcolors ))
+ TOKEN=$(printf '\u2588')
+
+ BAT_COL=$(( $nfgcolors -1 ))
+ #loops forever outputting a line every SLEEP_SEC secs
+ while [ $(( BAR_LEFT - BLOCK )) -gt 0 ]
+ do
+ BATTERY_BAR="${fgcolors[$BAT_COL]}$(repeat $BLOCK)${BATTERY_BAR}"
+ BAR_LEFT=$(( BAR_LEFT - BLOCK ))
+ BAT_COL=$(( BAT_COL - 1))
+ done
+
+ BATTERY_BAR="BATTERY: ${fgcolors[$BAT_COL]}$(repeat $BAR_LEFT)${BATTERY_BAR}"
+ echo $BATTERY_BAR
+}
+
+update() {
+ echo "$(cpu) $(battery)"
+ wait
+}
+
+while :; do
+ update
+ sleep $SLEEP_SEC &
+ wait
+done
diff --git a/mut/bin/sysact b/mut/bin/sysact
new file mode 100755
index 0000000..4bb92dc
--- /dev/null
+++ b/mut/bin/sysact
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+# A dmenu wrapper script for system functions.
+export WM="dwm"
+ctl='systemctl'
+
+wmpid(){ # This function is needed if there are multiple instances of the window manager.
+ echo "$(pidof dwm)"
+}
+
+case "$(printf "🔒 lock\n🚪 leave $WM\n♻️ renew $WM\n🐻 hibernate\n🔃 reboot\n🖥️shutdown\n💤 sleep\n📺 display off" | dmenu -i -p 'Action: ')" in
+ '🔒 lock') slock ;;
+ "🚪 leave $WM") kill -TERM "$(wmpid)" ;;
+ "♻️ renew $WM") kill -HUP "$(wmpid)" ;;
+ '🐻 hibernate') slock $ctl hibernate -i ;;
+ '💤 sleep') slock $ctl suspend -i ;;
+ '🔃 reboot') $ctl reboot -i ;;
+ '🖥️shutdown') $ctl poweroff -i ;;
+ '📺 display off') xset dpms force off ;;
+ *) exit 1 ;;
+esac
diff --git a/mut/bin/terragrunt b/mut/bin/terragrunt
new file mode 100755
index 0000000..38918e8
--- /dev/null
+++ b/mut/bin/terragrunt
@@ -0,0 +1,94 @@
+#!@bash@/bin/bash
+TERRAGRUNT_ARGS=()
+CONTEXT=""
+ENV=""
+MODULE=""
+FULL=0
+while [[ $# -gt 0 ]]; do
+ case $1 in
+ -full)
+ FULL=1
+ shift
+ ;;
+ -m|--module-path)
+ MODULE="$2"
+ shift
+ shift
+ ;;
+ -m=*|--module-path=*)
+ MODULE="${1#*=}"
+ shift
+ ;;
+ -e|--env)
+ ABS_ENV="$2"
+ CONTEXT=${ABS_ENV%/*}
+ ENV=${ABS_ENV#*/}
+ shift
+ shift
+ ;;
+ -e=*|--env=*)
+ ABS_ENV="${1#*=}"
+ CONTEXT=${ABS_ENV%/*}
+ ENV=${ABS_ENV#*/}
+ shift
+ ;;
+ *|-*)
+ TERRAGRUNT_ARGS+=("$1")
+ shift
+ esac
+done
+
+TTY=""
+case ${TERRAGRUNT_ARGS[0]} in
+ plan)
+ TERRAGRUNT_ARGS+=(-no-color -compact-warnings)
+ ;;
+ apply|destroy)
+ TTY="-t"
+ for arg in $TERRAGRUNT_ARGS; do
+ if [[ $arg -eq "gruntplan" ]]; then
+ TTY=""
+ fi
+ done
+ TERRAGRUNT_ARGS+=(-no-color -compact-warnings)
+ ;;
+ init)
+ TERRAGRUNT_ARGS+=(-no-color -compact-warnings)
+ ;;
+esac
+
+VARIABLES=""
+REPO="${PWD}"
+TERRAGRUNT_EXTRA_MOUNTS=""
+for var in $(pass show work/env)
+do
+ case $var in
+ TERRAGRUNT_EXTRA_MOUNTS*)
+ TERRAGRUNT_EXTRA_MOUNTS="$TERRAGRUNT_EXTRA_MOUNTS ${var#*=}"
+ ;;
+ *)
+ VARIABLES="$VARIABLES$(printf ' -e %s' "$var")"
+ ;;
+ esac
+done
+
+for var in $(printenv)
+do
+ case $var in
+ TF_*)
+ VARIABLES="$VARIABLES$(printf ' -e %s' $var)"
+ ;;
+ esac
+done
+
+ENVIRONMENTS="$REPO/environments"
+WORKDIR="$ENVIRONMENTS/$ENV/$MODULE"
+
+# TODO(mike): how to do concise mode | grep -E '(^.*[#~+-] .*|^[[:punct:]]|Plan)'
+# TODO(mike): check expiry of azure directory
+echo "docker run --rm -i $TTY $VARIABLES -v $HOME/.terragrunt-cache:/tmp -v $HOME/.azure:/root/.azure -v $HOME/.netrc:/root/.netrc $TERRAGRUNT_EXTRA_MOUNTS -v ${REPO}:${REPO} -w ${WORKDIR} $TERRAGRUNT_CONTAINER terragrunt ${TERRAGRUNT_ARGS[@]} | filter-ansi | grep --line-buffered -E '(^ .*[#~+-] .*|^[[:punct:]]|^Plan.*|^\S.*)'"
+if [[ $FULL -eq 0 ]]; then
+ docker run --rm -i $TTY $VARIABLES -v $HOME/.terragrunt-cache:/tmp -v $HOME/.azure:/root/.azure -v $HOME/.netrc:/root/.netrc $TERRAGRUNT_EXTRA_MOUNTS -v ${REPO}:${REPO} -w ${WORKDIR} $TERRAGRUNT_CONTAINER terragrunt ${TERRAGRUNT_ARGS[@]} | filter-ansi | grep --line-buffered -E '(^ .*[#~+-] .*|^[[:punct:]]|^Plan.*|^\S.*)'
+else
+ docker run --rm -i $TTY $VARIABLES -v $HOME/.terragrunt-cache:/tmp -v $HOME/.azure:/root/.azure -v $HOME/.netrc:/root/.netrc $TERRAGRUNT_EXTRA_MOUNTS -v ${REPO}:${REPO} -w ${WORKDIR} $TERRAGRUNT_CONTAINER terragrunt ${TERRAGRUNT_ARGS[@]} | filter-ansi
+fi
diff --git a/mut/bin/tmux-normal-mode b/mut/bin/tmux-normal-mode
new file mode 100644
index 0000000..5730017
--- /dev/null
+++ b/mut/bin/tmux-normal-mode
@@ -0,0 +1,28 @@
+ # Make our own copy-mode with Kakoune!
+ # cursor_y=$(tmux display-message -t "''${pane_id}" -p "#{cursor_y}") ;\
+ # cursor_x=$(tmux display-message -t "''${pane_id}" -p "#{cursor_x}") ;\
+ # pane_height=$(tmux display-message -t "''${pane_id}" -p "#{pane_height}") ;\
+ # line_count="$(wc -l "$file" |awk "{print \$1}")" ;\
+ # sel_line=$(( line_count - ( pane_height - cursor_y ) + 1 )) ;\
+ # printf "sel = %s\n" "$line_count" >>/tmp/debug.log ;\
+ # cursor="''${sel_line}.''${cursor_x},''${sel_line}.''${cursor_x}" ;\
+ # printf "cursor = %s\n" "$cursor" >>/tmp/debug.log
+
+kakoune_session="$(tmux display-message -p "#{window_name}" | sed "s/kakc@//")"
+dispatch_name="dispatch://$(tmux display-message -p "#{pane_start_command}")"
+case "${@}" in
+ '')
+ output=$(mktemp -d /tmp/kak-tmux.XXXXXXXX)/fifo
+ mkfifo ${output}
+ ( tmux capture-pane -S '-' -E '-' -J -e -p -t $TMUX_PANE | filter-ansi >${output} & )
+ tmux new-window -t kaks@$kakoune_session -n "$dispatch_name" -d "
+ kak -c '$kakoune_session' -e \"edit -fifo ${output} '${dispatch_name}';\
+ set-option buffer readonly true ;\
+ set-option window filetype dispatch ;\
+ hook -always -once buffer BufCloseFifo .* %{ nop %sh{ rm -r $(dirname ${output}) } }\""
+ tmux swap-pane -s kaks@$kakoune_session:"$dispatch_name".0 -t :
+ ;;
+ --quit)
+ tmux break-pane -t kaks@$kakoune_session -a -d -n "$dispatch_name"
+ ;;
+esac
diff --git a/mut/bin/transadd b/mut/bin/transadd
new file mode 100644
index 0000000..a598fad
--- /dev/null
+++ b/mut/bin/transadd
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+# Mimeapp script for adding torrent to transmission-daemon, but will also start the daemon first if not running.
+
+# transmission-daemon sometimes fails to take remote requests in its first moments, hence the sleep.
+
+pidof transmission-daemon >/dev/null || (transmission-daemon && notify-send "Starting transmission daemon..." && sleep 3 && pkill -RTMIN+7 "${STATUSBAR:-dwmblocks}")
+
+transmission-remote -a "$@" && notify-send "🔽 Torrent added."
diff --git a/mut/emacs/init.el b/mut/emacs/init.el
new file mode 100644
index 0000000..b31b0f0
--- /dev/null
+++ b/mut/emacs/init.el
@@ -0,0 +1,181 @@
+;; do autoload stuff here
+(package-initialize)
+(require 'package)
+(add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/") t)
+
+(defun seq-keep (function sequence)
+ "Apply FUNCTION to SEQUENCE and return the list of all the non-nil results."
+ (delq nil (seq-map function sequence)))
+
+(defvar rc/package-contents-refreshed nil)
+
+(defun rc/package-refresh-contents-once ()
+ (when (not rc/package-contents-refreshed)
+ (setq rc/package-contents-refreshed t)
+ (package-refresh-contents)))
+
+(defun rc/require-one-package (package)
+ (when (not (package-installed-p package))
+ (rc/package-refresh-contents-once)
+ (package-install package)))
+
+(defun rc/require (&rest packages)
+ (dolist (package packages)
+ (rc/require-one-package package)))
+
+(defun rc/require-theme (theme)
+ (let ((theme-package (->> theme
+ (symbol-name)
+ (funcall (-flip #'concat) "-theme")
+ (intern))))
+ (rc/require theme-package)
+ (load-theme theme t)))
+
+
+(rc/require 'dash)
+(require 'dash)
+(rc/require 'dash-functional)
+(require 'dash-functional)
+
+(defun rc/get-default-font ()
+ (cond
+ ((eq system-type 'windows-nt) "Consolas-13")
+ (t "mono-13")))
+(add-to-list 'default-frame-alist `(font . ,(rc/get-default-font)))
+(rc/require 'ansi-color)
+
+(rc/require 'ido 'ido-completing-read+ 'smex 'corfu)
+(ido-mode t)
+(ido-everywhere t)
+(ido-ubiquitous-mode t)
+(global-corfu-mode)
+
+(global-set-key (kbd "M-x") 'smex)
+(global-set-key (kbd "M-X") 'smex-major-mode-commands)
+;; This is your old M-x. p
+(global-set-key (kbd "C-c C-c M-x") 'execute-extended-command)
+
+(tool-bar-mode 0)
+(menu-bar-mode 0)
+(scroll-bar-mode 0)
+(column-number-mode 1)
+(show-paren-mode 1)
+
+(setq-default inhibit-splash-screen t
+ make-backup-files nil
+ tab-width 4
+ indent-tabs-mode nil
+ compilation-scroll-output t
+ visible-bell (equal system-type 'windows-nt))
+
+(setq-default c-basic-offset 4
+ c-default-style '((java-mode . "java")
+ (awk-mode . "awk")
+ (other . "bsd")))
+(setq split-width-threshold 9999)
+
+(defun rc/duplicate-line ()
+ "Duplicate current line"
+ (interactive)
+ (let ((column (- (point) (point-at-bol)))
+ (line (let ((s (thing-at-point 'line t)))
+ (if s (string-remove-suffix "\n" s) ""))))
+ (move-end-of-line 1)
+ (newline)
+ (insert line)
+ (move-beginning-of-line 1)
+ (forward-char column)))
+
+(global-set-key (kbd "M-J") 'text-scale-decrease)
+(global-set-key (kbd "M-K") 'text-scale-increase)
+
+(global-set-key (kbd "M-c") 'rc/duplicate-line)
+(global-set-key (kbd "C-c p") 'find-file-at-point)
+(global-display-line-numbers-mode)
+(setq next-line-add-newlines t)
+(setq display-line-numbers-type 'relative)
+
+(rc/require 'direnv 'editorconfig 'multiple-cursors)
+(editorconfig-mode 1)
+(electric-pair-mode)
+(global-set-key (kbd "C-S-c C-S-c") 'mc/edit-lines)
+(global-set-key (kbd "C->") 'mc/mark-next-like-this)
+(global-set-key (kbd "C-<") 'mc/mark-previous-like-this)
+(global-set-key (kbd "C-c C-<") 'mc/mark-all-like-this)
+(global-set-key (kbd "C-.") 'mc/mark-all-in-region)
+
+(rc/require 'cl-lib 'magit)
+(setq magit-auto-revert-mode nil)
+(global-set-key (kbd "C-c m s") 'magit-status)
+(global-set-key (kbd "C-c m l") 'magit-log)
+
+(require 'dired-x)
+(setq dired-omit-files
+ (concat dired-omit-files "\\|^\\..+$"))
+(setq-default dired-dwim-target t)
+(setq dired-listing-switches "-alh")
+
+;; stolen from: https://emacs.stackexchange.com/questions/24698/ansi-escape-sequences-in-compilation-mode
+(rc/require 'ansi-color)
+(defun endless/colorize-compilation ()
+ "Colorize from `compilation-filter-start' to `point'."
+ (let ((inhibit-read-only t))
+ (ansi-color-apply-on-region
+ compilation-filter-start (point))))
+(add-hook 'compilation-filter-hook
+ #'endless/colorize-compilation)
+
+(setq TeX-auto-save t)
+(setq TeX-parse-self t)
+(setq-default TeX-master nil)
+
+(setq completion-auto-select 'second-tab)
+(setq completions-format 'one-column)
+(setq completions-max-height 20)
+(define-key completion-in-region-mode-map (kbd "M-p") #'minibuffer-previous-completion)
+(define-key completion-in-region-mode-map (kbd "M-n") #'minibuffer-next-completion)
+;; (rc/require 'consult 'vertico 'orderless)
+;; (setq completion-in-region-function #'completion--)
+
+
+(rc/require
+ 'nix-mode
+ 'go-mode
+ 'auctex
+ 'yaml-pro
+ 'rust-mode
+ )
+
+(require 'lsp-mode)
+(add-hook 'rust-mode-hook #'lsp-deferred)
+(add-hook 'go-mode-hook #'lsp-deferred)
+(defun lsp-go-install-save-hooks ()
+ (add-hook 'before-save-hook #'lsp-format-buffer t t)
+ (add-hook 'before-save-hook #'lsp-organize-imports t t))
+(add-hook 'go-mode-hook #'lsp-go-install-save-hooks)
+(lsp-register-custom-settings
+ '(("gopls.hints.assignVariableTypes" t t)
+ ("gopls.hints.compositeLiteralFields" t t)
+ ("gopls.hints.compositeLiteralTypes" t t)
+ ("gopls.hints.constantValues" t t)
+ ("gopls.hints.functionTypeParameters" t t)
+ ("gopls.hints.parameterNames" t t)
+ ("gopls.hints.rangeVariableTypes" t t)))
+
+(rc/require-theme 'gruber-darker)
+(custom-set-variables
+ ;; custom-set-variables was added by Custom.
+ ;; If you edit it by hand, you could mess it up, so be careful.
+ ;; Your init file should contain only one such instance.
+ ;; If there is more than one, they won't work right.
+ '(custom-enabled-themes '(gruber-darker))
+ '(custom-safe-themes
+ '("ba4ab079778624e2eadbdc5d9345e6ada531dc3febeb24d257e6d31d5ed02577" "a9dc7790550dcdb88a23d9f81cc0333490529a20e160a8599a6ceaf1104192b5" "5f128efd37c6a87cd4ad8e8b7f2afaba425425524a68133ac0efd87291d05874" "5b9a45080feaedc7820894ebbfe4f8251e13b66654ac4394cb416fef9fdca789" "9013233028d9798f901e5e8efb31841c24c12444d3b6e92580080505d56fd392" "6adeb971e4d5fe32bee0d5b1302bc0dfd70d4b42bad61e1c346599a6dc9569b5" "8d3ef5ff6273f2a552152c7febc40eabca26bae05bd12bc85062e2dc224cde9a" "75b2a02e1e0313742f548d43003fcdc45106553af7283fb5fad74359e07fe0e2" "b9761a2e568bee658e0ff723dd620d844172943eb5ec4053e2b199c59e0bcc22" "9d29a302302cce971d988eb51bd17c1d2be6cd68305710446f658958c0640f68" "f053f92735d6d238461da8512b9c071a5ce3b9d972501f7a5e6682a90bf29725" "dc8285f7f4d86c0aebf1ea4b448842a6868553eded6f71d1de52f3dcbc960039" "38c0c668d8ac3841cb9608522ca116067177c92feeabc6f002a27249976d7434" "162201cf5b5899938cfaec99c8cb35a2f1bf0775fc9ccbf5e63130a1ea217213" "ff24d14f5f7d355f47d53fd016565ed128bf3af30eb7ce8cae307ee4fe7f3fd0" "da75eceab6bea9298e04ce5b4b07349f8c02da305734f7c0c8c6af7b5eaa9738" "e3daa8f18440301f3e54f2093fe15f4fe951986a8628e98dcd781efbec7a46f2" "631c52620e2953e744f2b56d102eae503017047fb43d65ce028e88ef5846ea3b" "88f7ee5594021c60a4a6a1c275614103de8c1435d6d08cc58882f920e0cec65e" "dfb1c8b5bfa040b042b4ef660d0aab48ef2e89ee719a1f24a4629a0c5ed769e8" "e13beeb34b932f309fb2c360a04a460821ca99fe58f69e65557d6c1b10ba18c7" default))
+ '(package-selected-packages
+ '(doom-themes corfu yaml-pro smex rust-mode nix-mode multiple-cursors magit lsp-ui ido-completing-read+ gruber-darker-theme go-mode editorconfig direnv dash-functional auctex)))
+(custom-set-faces
+ ;; custom-set-faces was added by Custom.
+ ;; If you edit it by hand, you could mess it up, so be careful.
+ ;; Your init file should contain only one such instance.
+ ;; If there is more than one, they won't work right.
+ )
diff --git a/mut/neovim/README.md b/mut/neovim/README.md
new file mode 100644
index 0000000..3a441bd
--- /dev/null
+++ b/mut/neovim/README.md
@@ -0,0 +1,2 @@
+# mike_neovim
+installs my neovim config on mac or linux
diff --git a/mut/neovim/compiler/ansible-lint.vim b/mut/neovim/compiler/ansible-lint.vim
new file mode 100644
index 0000000..9427092
--- /dev/null
+++ b/mut/neovim/compiler/ansible-lint.vim
@@ -0,0 +1,11 @@
+if exists('current_compiler')
+ finish
+endif
+let current_compiler = 'go-test'
+
+if exists(':CompilerSet') != 2
+ command -nargs=* CompilerSet setlocal <args>
+endif
+
+CompilerSet makeprg=compile\ ansible-lint
+CompilerSet errorformat=%Z%f:%l\ %m,%Z%f:%l,%E%\\%%(%\\S%\\)%\\@=%m,%C%\\%%(%\\S%\\)%\\@=%m,%-G
diff --git a/mut/neovim/compiler/go-test.vim b/mut/neovim/compiler/go-test.vim
new file mode 100644
index 0000000..61442e5
--- /dev/null
+++ b/mut/neovim/compiler/go-test.vim
@@ -0,0 +1,14 @@
+if exists('current_compiler')
+ finish
+endif
+let current_compiler = 'go-test'
+
+if exists(':CompilerSet') != 2
+ command -nargs=* CompilerSet setlocal <args>
+endif
+
+" %f>%l:%c:%t:%n:%m
+CompilerSet makeprg=go\ test
+CompilerSet errorformat=%.%#:\ %m\ %f:%l,%.%#:\ %m\ at\ %f:%l%.%#,
+
+" vim: sw=2 sts=2 et
diff --git a/mut/neovim/compiler/helm.vim b/mut/neovim/compiler/helm.vim
new file mode 100644
index 0000000..7e4b21d
--- /dev/null
+++ b/mut/neovim/compiler/helm.vim
@@ -0,0 +1,14 @@
+if exists('current_compiler')
+ finish
+endif
+let current_compiler = 'go-test'
+
+if exists(':CompilerSet') != 2
+ command -nargs=* CompilerSet setlocal <args>
+endif
+
+CompilerSet makeprg=compile\ helm\ lint
+CompilerSet errorformat=\[%t%.%#\]%.%#\ template:\ %f:%l:%c:\ %m,
+ \\[%t%.%#\]\ %f:\ %m,
+
+" vim: sw=2 sts=2 et
diff --git a/mut/neovim/compiler/racket.vim b/mut/neovim/compiler/racket.vim
new file mode 100644
index 0000000..1f98a41
--- /dev/null
+++ b/mut/neovim/compiler/racket.vim
@@ -0,0 +1,26 @@
+if exists('current_compiler')
+ finish
+endif
+let current_compiler = 'go-test'
+
+if exists(':CompilerSet') != 2
+ command -nargs=* CompilerSet setlocal <args>
+endif
+
+" The errorformat can also use vim's regular expression syntax (albeit in a rather awkward way) which gives us a solution to the problem. We can use a non-capturing group and a zero-width assertion to require the presence of these signaling phrases without consuming them. This then allows the %m to pick them up. As plain regular expression syntax this zero-width assertion looks like:
+"
+" \%(undefined reference\|multiple definition\)\@=
+"
+" But in order to use it in efm we need to replace \ by %\ and % by %%
+
+
+CompilerSet makeprg=compile\ racket
+CompilerSet errorformat=\%Z%*\\S%.%#,
+ \%C\ \ \ %f:%l:%c,
+ \%C\ \ \ %f:%l:%c:\ %m,
+ \%C\ \ %.%#%\\%%(module%\\spath:%\\\|at\:%\\\|in\:%\\\|expected\:%\\\|given\:%\\)%\\@=%m,
+ \%C\ %.%#,
+ \%E%\\%%(%\\w%\\)%\\@=%f:%*\\d:%*\\d:\ %m,
+ \%E%*\\f:%*\\d:%*\\d:\ %m,
+ \%E%\\%%(%\\S%\\+:%\\\|%\.%\\+--%\\)%\\@=%m,
+" vim: sw=2 sts=2 et
diff --git a/mut/neovim/compiler/terragrunt.vim b/mut/neovim/compiler/terragrunt.vim
new file mode 100644
index 0000000..54f94ef
--- /dev/null
+++ b/mut/neovim/compiler/terragrunt.vim
@@ -0,0 +1,21 @@
+if exists('current_compiler')
+ finish
+endif
+let current_compiler = 'go-test'
+
+if exists(':CompilerSet') != 2
+ command -nargs=* CompilerSet setlocal <args>
+endif
+
+" The errorformat can also use vim's regular expression syntax (albeit in a rather awkward way) which gives us a solution to the problem. We can use a non-capturing group and a zero-width assertion to require the presence of these signaling phrases without consuming them. This then allows the %m to pick them up. As plain regular expression syntax this zero-width assertion looks like:
+"
+" \%(undefined reference\|multiple definition\)\@=
+"
+" But in order to use it in efm we need to replace \ by %\ and % by %%
+
+
+CompilerSet makeprg=terragrunt
+CompilerSet errorformat=%.%#level=%t%.%#msg=%f:%l%\\,%c-%*\\d:\ %m,
+ \%Z%m,
+ \%E-\ %m\ (at\ %f:%l\\,%c-%*\\d),
+" vim: sw=2 sts=2 et
diff --git a/mut/neovim/debug b/mut/neovim/debug
new file mode 100644
index 0000000..6319340
--- /dev/null
+++ b/mut/neovim/debug
@@ -0,0 +1,8 @@
+~/projects/k8s ~/neovim
+can't find session: kaks@projects-k8s
+direnv: loading ~/projects/k8s/.envrc
+direnv: using flake
+direnv: nix-direnv: using cached dev shell
+make: *** No rule to make target 'envtest'. Stop.
+direnv: export +AR +AS +CC +CONFIG_SHELL +CXX +ENVTEST +ENVTEST_K8S_VERSION +GOTOOLDIR +HOST_PATH +IN_NIX_SHELL +KUBEBUILDER_ASSETS +LD +LOCALBIN +NIX_BINTOOLS +NIX_BINTOOLS_WRAPPER_TARGET_HOST_x86_64_unknown_linux_gnu +NIX_BUILD_CORES +NIX_CC +NIX_CC_WRAPPER_TARGET_HOST_x86_64_unknown_linux_gnu +NIX_CFLAGS_COMPILE +NIX_ENFORCE_NO_NATIVE +NIX_HARDENING_ENABLE +NIX_INDENT_MAKE +NIX_LDFLAGS +NIX_STORE +NM +OBJCOPY +OBJDUMP +RANLIB +READELF +SIZE +SOURCE_DATE_EPOCH +STRINGS +STRIP +buildInputs +buildPhase +builder +cmakeFlags +configureFlags +depsBuildBuild +depsBuildBuildPropagated +depsBuildTarget +depsBuildTargetPropagated +depsHostHost +depsHostHostPropagated +depsTargetTarget +depsTargetTargetPropagated +doCheck +doInstallCheck +dontAddDisableDepTrack +mesonFlags +nativeBuildInputs +out +outputs +patches +phases +propagatedBuildInputs +propagatedNativeBuildInputs +shell +shellHook +stdenv +strictDeps +system ~PATH ~XDG_DATA_DIRS ~name
+~/neovim
diff --git a/mut/neovim/fnl/conf/diagnostic.fnl b/mut/neovim/fnl/conf/diagnostic.fnl
new file mode 100644
index 0000000..7ef1dd3
--- /dev/null
+++ b/mut/neovim/fnl/conf/diagnostic.fnl
@@ -0,0 +1,16 @@
+(fn m [mode key cb]
+ (vim.keymap.set mode key cb {:silent true :noremap true}))
+
+(m :n :<leader>ge (fn []
+ (vim.diagnostic.open_float)))
+
+(vim.diagnostic.config {:virtual_text false})
+
+(vim.keymap.set :n :<Leader>l (let [l (require :lsp_lines)]
+ l.toggle)
+ {:desc "Toggle lsp_lines"})
+
+(vim.api.nvim_set_hl 0 :VirtualTextWarning {:link :Grey})
+(vim.api.nvim_set_hl 0 :VirtualTextError {:link :DiffDelete})
+(vim.api.nvim_set_hl 0 :VirtualTextInfo {:link :DiffChange})
+(vim.api.nvim_set_hl 0 :VirtualTextHint {:link :DiffAdd})
diff --git a/mut/neovim/fnl/conf/events.fnl b/mut/neovim/fnl/conf/events.fnl
new file mode 100644
index 0000000..00d75d4
--- /dev/null
+++ b/mut/neovim/fnl/conf/events.fnl
@@ -0,0 +1,32 @@
+(vim.api.nvim_create_augroup "conf#events" {:clear true})
+(local event vim.api.nvim_create_autocmd)
+
+(event [:BufReadPost] {:pattern ["*"]
+ :callback (fn []
+ (local pattern "'\\s\\+$'")
+ (vim.cmd (.. "syn match TrailingWhitespace "
+ pattern))
+ (vim.cmd "hi link TrailingWhitespace IncSearch"))
+ :group "conf#events"})
+
+(local vimenter-cwd (vim.fn.getcwd))
+(event [:VimLeave] {:pattern ["*"]
+ :callback (fn []
+ (vim.cmd (.. "mksession! " vimenter-cwd
+ :/.vimsession.vim)))
+ :group "conf#events"})
+
+(event [:BufWinEnter :WinEnter]
+ {:pattern ["term://*"]
+ :callback (fn []
+ (vim.cmd :startinsert))
+ :group "conf#events"})
+
+(event [:BufLeave] {:pattern ["term://*"]
+ :callback (fn []
+ (vim.cmd :stopinsert))
+ :group "conf#events"})
+
+(event [:FileType] {:pattern [:dirvish]
+ :callback #(vim.cmd "silent! unmap <buffer> <C-p>")
+ :group "conf#events"})
diff --git a/mut/neovim/fnl/conf/filetype.fnl b/mut/neovim/fnl/conf/filetype.fnl
new file mode 100644
index 0000000..29f64b0
--- /dev/null
+++ b/mut/neovim/fnl/conf/filetype.fnl
@@ -0,0 +1,44 @@
+(fn playbook? [filename]
+ (P filename)
+ (local pattern (vim.regex :^playbook.*))
+ (pattern:match_str filename))
+
+(fn group-vars? [relative-dir]
+ (local pattern (vim.regex :group_vars$))
+ (pattern:match_str relative-dir))
+
+(fn roles? [relative-dir]
+ (local pattern (vim.regex :roles$))
+ (pattern:match_str relative-dir))
+
+(fn task? [relative-file]
+ (local pattern (vim.regex :.*tasks.*))
+ (pattern:match_str relative-file))
+
+(fn ansible-files? [items]
+ (local [item & rest] items)
+ (if (not item) :yaml
+ (task? item) :yaml.ansible
+ (roles? item) :yaml.ansible
+ (group-vars? item) :yaml.ansible
+ (ansible-files? rest)))
+
+(fn yaml-filetype [path buf]
+ (local [repo?]
+ (vim.fs.find :.git
+ {:upward true
+ :path (vim.fs.dirname path)
+ :stop (vim.fs.dirname (vim.loop.cwd))}))
+ (local files (or (not repo?) (icollect [path file-or-dir (vim.fs.dir (vim.fs.dirname repo?)
+ {:skip #(not= "."
+ ($1:sub 1
+ 1))
+ :depth 2})]
+ (do
+ path))))
+ (if (and repo? (playbook? (vim.fn.fnamemodify path ":t"))) :yaml.ansible
+ (and repo? (task? (vim.fn.fnamemodify path ":."))) :yaml.ansible
+ repo? (ansible-files? files)
+ :yaml))
+
+(vim.filetype.add {:extension {:yml yaml-filetype :yaml yaml-filetype}})
diff --git a/mut/neovim/fnl/conf/init.fnl b/mut/neovim/fnl/conf/init.fnl
new file mode 100644
index 0000000..90bc20c
--- /dev/null
+++ b/mut/neovim/fnl/conf/init.fnl
@@ -0,0 +1,172 @@
+(vim.cmd "colorscheme kanagawa-wave")
+(vim.cmd "filetype plugin on")
+(vim.cmd "filetype indent on")
+(vim.cmd "highlight WinSeparator guibg=None")
+(vim.cmd "packadd cfilter")
+
+(require :conf.settings)
+;; (require :conf.pkgs)
+;; (require :conf.lsp)
+;; (require :conf.events)
+;; (require :conf.filetype)
+;; (require :conf.newtab)
+;; (require :conf.nix-develop)
+
+;; (require :conf.diagnostic)
+
+;; TODO: make a function that sets this autocommand: au BufWritePost currentfile :!curl -X POST -d "{\"previewRun\": true, \"yamlOverride\": \"$(cat % | yq -P)\", \"resources\": {\"repositories\": {\"self\": {\"refName\": \"refs/heads/branch\"}}}}" -s -H "Content-Type: application/json" -H "Authorization: Basic $WORK_AZDO_GIT_AUTH" "$WORK_AZDO_GIT_ORG_URL/Stater/_apis/pipelines/pipelineid/preview?api-version=7.1-preview.1" | jq -r '.finalYaml // .' > scratch.yaml
+
+(let [map vim.keymap.set]
+ (map :t :<c-s> "<c-\\><c-n>")
+ ;; pausing and continueing printing output is not necessary inside neovim terminal right?
+ (map :t :<c-q> "<c-\\><c-n>:q<cr>")
+ (map :n :<leader>qo ":copen<cr>")
+ (map :n :<leader>qc ":cclose<cr>")
+ (map :n :<leader>lo ":lopen<cr>")
+ (map :n :<leader>lc ":lclose<cr>")
+ (map :n "[q" ":cprevious<cr>")
+ (map :n "]q" ":cnext<cr>")
+ (map :n "[x" ":lprevious<cr>")
+ (map :n "]x" ":lnext<cr>")
+ (map :n :<c-p> ":Telescope find_files<cr>" {:noremap true})
+ (map :n "`<Backspace>" ":FocusDispatch ")
+ (map :n "`k" ":K9s ")
+ (map :n "`s" ":Ssh ")
+ (map :n :<leader>p ":NewTab<cr>")
+ (map :n :<leader>cf ":tabedit ~/flake|tc ~/flake|G<cr><c-w>o")
+ (map :n :<leader>cn ":tabedit ~/neovim|tc ~/neovim|G<cr><c-w>o"))
+
+(tset _G :P (lambda [...]
+ (let [inspected (icollect [_ v (ipairs [...])]
+ (vim.inspect v))]
+ (each [_ printer (ipairs inspected)]
+ (print printer)))))
+
+(local git-worktree (require :git-worktree))
+(git-worktree.setup {:change_directory_command :tcd
+ :update_on_change true
+ :autopush true})
+
+(fn append [tbl item]
+ (table.insert tbl item)
+ tbl)
+
+(fn by-newline [lines]
+ (fn iter [items by result]
+ (local [item & rest] items)
+ (if (= item nil) result
+ (= "" item) (iter rest [] (append result by))
+ (iter rest (append by item) result)))
+
+ (ipairs (iter lines [] [])))
+
+(vim.keymap.set [:n] :<leader>w
+ (fn []
+ (vim.fn.feedkeys ":Worktree switch ")
+ (local cmp (require :cmp))
+ (vim.schedule (fn []
+ (cmp.close)
+ (cmp.complete)))))
+
+(vim.keymap.set [:n] :<leader>W ":Worktree ")
+(fn list-worktrees []
+ (local pworktree (io.popen "git worktree list --porcelain"))
+ (icollect [_ worktree (by-newline (icollect [line (pworktree:lines)]
+ line))]
+ (match (icollect [_ line (ipairs worktree)]
+ (vim.split line " "))
+ [[:worktree path] [:HEAD commit] [:branch branch]] (branch:gsub :refs/heads/
+ ""))))
+
+(fn list-branches []
+ (local pbranch (io.popen "git branch --list -r --format \"%(refname)\""))
+ (icollect [_ ref (ipairs (icollect [line (pbranch:lines)]
+ (line:gsub :refs/remotes/.+/ "")))]
+ (if (not (= ref :HEAD))
+ ref)))
+
+(vim.api.nvim_create_user_command :Worktree
+ (fn [ctx]
+ (match ctx.fargs
+ [:create tree branch upstream] (git-worktree.create_worktree tree
+ branch
+ upstream)
+ [:create tree upstream] (git-worktree.create_worktree tree
+ tree
+ upstream)
+ [:create tree] (git-worktree.create_worktree tree
+ tree
+ :origin)
+ [:switch tree] (git-worktree.switch_worktree tree)
+ [:delete tree] (git-worktree.delete_worktree tree)
+ _ (vim.notify "not recognized")))
+ {:nargs "*"
+ :complete (fn [lead cmdline cursor]
+ (local cmdline-tokens
+ (vim.split cmdline " "))
+ (match cmdline-tokens
+ [:Worktree :create & rest] (list-branches)
+ [:Worktree :switch & rest] (list-worktrees)
+ [:Worktree :delete & rest] (list-worktrees)
+ [:Worktree & rest] [:create
+ :switch
+ :delete]))})
+
+(vim.api.nvim_create_user_command :HomeManager
+ (fn [ctx]
+ (vim.cmd (.. ":Dispatch home-manager switch --impure "
+ (os.getenv :HOME) "/flake#"
+ (. ctx.fargs 1))))
+ {:nargs 1})
+
+(vim.api.nvim_create_user_command :Gpush
+ (fn [ctx]
+ (vim.cmd ":Dispatch git push"))
+ {})
+
+(vim.api.nvim_create_user_command :Grunt
+ (fn [ctx]
+ (match (. ctx.fargs 1)
+ :plan (vim.cmd (.. ":Dispatch "
+ (if ctx.bang
+ "TF_LOG=DEBUG "
+ "")
+ "terragrunt "
+ (table.concat ctx.fargs
+ " ")
+ " " :-out=gruntplan))
+ :apply (vim.cmd (.. ":Dispatch "
+ (if ctx.bang
+ "TF_LOG=DEBUG "
+ "")
+ "terragrunt "
+ (table.concat ctx.fargs
+ " ")
+ " " :gruntplan))
+ _ (vim.cmd (.. ":Start "
+ (if ctx.bang
+ "TF_LOG=DEBUG "
+ "")
+ "terragrunt "
+ (table.concat ctx.fargs
+ " ")))))
+ {:nargs "*" :bang true})
+
+(vim.api.nvim_create_user_command :K9s
+ (fn [ctx]
+ (vim.cmd (.. ":Start k9s --context "
+ (. ctx.fargs 1))))
+ {:nargs 1})
+
+(vim.api.nvim_create_user_command :Ssh
+ (fn [ctx]
+ (vim.cmd (.. ":Start ssh " (. ctx.fargs 1))))
+ {:nargs 1
+ :complete (fn [lead cmdline cursor]
+ (local p
+ (io.popen :get-sshables))
+ (local lines
+ (icollect [line (p:lines)]
+ line))
+ (p:close)
+ lines)})
diff --git a/mut/neovim/fnl/conf/lsp.fnl b/mut/neovim/fnl/conf/lsp.fnl
new file mode 100644
index 0000000..35fa34f
--- /dev/null
+++ b/mut/neovim/fnl/conf/lsp.fnl
@@ -0,0 +1,75 @@
+(fn map-to-capabilities [{: client : buf} format]
+ (fn bo [name value]
+ (vim.api.nvim_buf_set_option buf name value))
+
+ (fn bm [mode key cb]
+ (vim.keymap.set mode key cb {:silent true :noremap true :buffer buf}))
+
+ (fn lspdo [action]
+ (. vim.lsp.buf action))
+
+ (fn use [cpb]
+ (match cpb
+ :completionProvider (bo :omnifunc "v:lua.vim.lsp.omnifunc")
+ :renameProvider (bm :n :<leader>gr (lspdo :rename))
+ :signatureHelpProvider (bm :n :<leader>gs (lspdo :signature_help))
+ :definitionProvider (bm :n :<leader>gd (lspdo :definition))
+ :declaration (bm :n :<leader>gD (lspdo :declaration))
+ :implementationProvider (bm :n :<leader>gi (lspdo :implementation))
+ :referencesProvider (bm :n :<leader>gg (lspdo :references))
+ :documentSymbolProvider (bm :n :<leader>gds (lspdo :workspace_symbol))
+ :codeActionProvider (bm :n :<leader>ga (lspdo :code_action))
+ :codeLensProvider (bm :n :<leader>gl
+ (lambda []
+ (vim.lsp.codelens.run)))
+ :hoverProvider (bo :keywordprg ":LspHover")
+ :documentFormattingProvider (if format
+ ((fn []
+ (bo :formatexpr
+ "v:lua.vim.lsp.format()")
+ (bm :n :<leader>gq
+ #(vim.lsp.buf.format {:async true})))))))
+
+ (each [cpb enabled? (pairs client.server_capabilities)]
+ (if enabled?
+ (use cpb)))
+ {: client : buf})
+
+(fn register-handlers [{: client : buf}]
+ (tset (. client :handlers) :textDocument/publishDiagnostics
+ (vim.lsp.with (fn [_ result ctx config]
+ (vim.lsp.diagnostic.on_publish_diagnostics _ result ctx
+ config)
+ (vim.diagnostic.setloclist {:open false}))
+ {:virtual_text true
+ :underline true
+ :update_in_insert false
+ :severity_sort true}))
+ {: client : buf})
+
+(var format-on-save true)
+(fn toggle-format-on-save []
+ (set format-on-save (not format-on-save)))
+
+(vim.api.nvim_create_user_command :LspToggleOnSave toggle-format-on-save
+ {:nargs 1 :complete (fn [] [:format])})
+
+(fn events [{: client : buf}]
+ (match client.server_capabilities
+ {:documentFormattingProvider true}
+ (let [format-events-group (vim.api.nvim_create_augroup :format-events
+ {:clear true})]
+ (vim.api.nvim_create_autocmd [:BufWritePre]
+ {:group format-events-group
+ :callback (lambda []
+ (if format-on-save
+ (vim.lsp.buf.format)))
+ :buffer buf}))))
+
+(fn attach [client buf format]
+ (-> {: client : buf}
+ (register-handlers)
+ (map-to-capabilities format)
+ (events)))
+
+{: attach}
diff --git a/mut/neovim/fnl/conf/macros.fnl b/mut/neovim/fnl/conf/macros.fnl
new file mode 100644
index 0000000..9ce8b26
--- /dev/null
+++ b/mut/neovim/fnl/conf/macros.fnl
@@ -0,0 +1,45 @@
+(fn by-two [l]
+ (fn iter [t i]
+ (let [k (. l (- i 1))
+ v (. l i)]
+ (when (and (not= k nil) (not= v nil))
+ (values (+ i 2) [k v]))))
+
+ (values iter l 2))
+
+(fn decode-opt-value [v]
+ (fn symbol-luatype [s]
+ (let [t (tostring s)]
+ (match t
+ :on true
+ :off false
+ _ t)))
+
+ (if (sym? v) (symbol-luatype v) v))
+
+(fn opt-template [o]
+ (fn remove/append [target value mode]
+ `(let [target# (. vim :opt ,target)
+ value# ,value]
+ ,(match mode
+ :append `(target#:append value#)
+ :remove `(target#:remove value#))))
+
+ (fn [v]
+ (match (string.sub o 1 1)
+ "-" (remove/append (string.sub o 2) v :remove)
+ "+" (remove/append (string.sub o 2) v :append)
+ _ `(tset (. vim :opt) ,o ,v))))
+
+(fn settings [...]
+ `,(icollect [_ [o v] (by-two [...])]
+ ((opt-template (tostring o)) (decode-opt-value v))))
+
+(fn globals [...]
+ (local globa (icollect [_ [k v] (by-two [...])]
+ [(tostring k) v]))
+ `(let [l# ,globa]
+ (each [a# b# (ipairs l#)]
+ (tset (. vim :g) (. b# 1) (. b# 2)))))
+
+{: settings : globals}
diff --git a/mut/neovim/fnl/conf/newtab/init.fnl b/mut/neovim/fnl/conf/newtab/init.fnl
new file mode 100644
index 0000000..fbf8e18
--- /dev/null
+++ b/mut/neovim/fnl/conf/newtab/init.fnl
@@ -0,0 +1,36 @@
+(local pickers (require :telescope.pickers))
+(local finders (require :telescope.finders))
+(local conf (. (require :telescope.config) :values))
+(local themes (require :telescope.themes))
+(local actions (require :telescope.actions))
+(local action_state (require :telescope.actions.state))
+
+(fn colors [opts]
+ (local opts (if opts opts {}))
+ (local finder
+ (pickers.new opts
+ {:prompt_title :colors
+ :finder (finders.new_oneshot_job [:fd
+ :-d1
+ "."
+ (os.getenv :HOME)
+ (.. (os.getenv :HOME)
+ :/projects)]
+ {})
+ :attach_mappings (fn [prompt_buf map]
+ (actions.select_default:replace (fn []
+ (actions.close prompt_buf)
+ (local selection
+ (action_state.get_selected_entry))
+ (vim.cmd (.. :tabnew
+ (. selection
+ 1)))
+ (vim.cmd (.. :tc
+ (. selection
+ 1))))))
+ :sorter (conf.generic_sorter opts)}))
+ (finder:find))
+
+(vim.api.nvim_create_user_command :NewTab (fn [] (colors (themes.get_ivy))) {})
+
+(vim.api.nvim_create_user_command :Colors colors {})
diff --git a/mut/neovim/fnl/conf/nix-develop/init.fnl b/mut/neovim/fnl/conf/nix-develop/init.fnl
new file mode 100644
index 0000000..0983e06
--- /dev/null
+++ b/mut/neovim/fnl/conf/nix-develop/init.fnl
@@ -0,0 +1,122 @@
+(local loop vim.loop)
+
+(var original-env {})
+(local ignored-variables {:SHELL true
+ :BASHOPTS true
+ :HOME true
+ :NIX_BUILD_TOP true
+ :NIX_ENFORCE_PURITY true
+ :NIX_LOG_FD true
+ :NIX_REMOTE true
+ :PPID true
+ :SHELL true
+ :SHELLOPTS true
+ :SSL_CERT_FILE true
+ :TEMP true
+ :TEMPDIR true
+ :TERM true
+ :TMP true
+ :TMPDIR true
+ :TZ true
+ :UID true})
+
+(local separated-dirs {:PATH ":" :XDG_DATA_DIRS ":"})
+
+(fn set-env [key value]
+ (if (not (. original-env key))
+ (tset original-env key (or (. vim.env key) :nix-develop-nil)))
+ (local sep (. separated-dirs key))
+ (if sep
+ (do
+ (local suffix (or (. vim.env key) ""))
+ (tset vim.env key (.. value sep suffix)))
+ (tset vim.env key value)))
+
+(fn unload-env []
+ (each [k v (pairs original-env)]
+ (if (= v :nix-develop-nil)
+ (tset vim.env k nil)
+ (tset vim.env k v))))
+
+(fn ignored? [key]
+ (. ignored-variables (string.upper key)))
+
+(fn exported? [Type]
+ (= Type :exported))
+
+(fn handle-shellhook [shellhook] ; (P :handle-shellhook shellhook)
+ (var shellhook-env "")
+ (local stdin (loop.new_pipe))
+ (local stdout (loop.new_pipe))
+ (local p
+ (loop.spawn :bash {:stdio [stdin stdout nil]}
+ (fn [code signal]
+ (vim.schedule #(vim.notify (.. "shellhook: exit code "
+ code " " signal))))))
+ (loop.read_start stdout
+ (fn [err data]
+ (assert (not err) err)
+ (if data
+ (set shellhook-env (.. shellhook-env data))
+ (do
+ (if (not= shellhook-env "")
+ (vim.schedule (fn []
+ (local json
+ (vim.fn.json_decode shellhook-env))
+ ; (P json)
+ (each [key value (pairs json)]
+ (set-env key value)))))))))
+ (stdin:write (.. shellhook "jq -n 'env'\n\n"))
+ (stdin:close))
+
+(fn handle-nix-print-dev-env [str]
+ (vim.schedule (fn []
+ (local json (. (vim.fn.json_decode str) :variables))
+ (-> (icollect [key {: type : value} (pairs json)]
+ (do
+ (if (and (exported? type) (not (ignored? key)))
+ (set-env key value))
+ (if (= key :shellHook)
+ value)))
+ (#(each [_ shellhook (ipairs $1)]
+ (handle-shellhook shellhook)))))))
+
+(fn nix-develop [fargs unload]
+ (if unload
+ (unload-env))
+ (local cmd :nix)
+ (local fargs (or fargs []))
+ (local args [:print-dev-env :--json (unpack fargs)])
+ (local stdout (loop.new_pipe))
+ (local stdio [nil stdout nil])
+ (var nix-print-dev-env "")
+ (local p
+ (loop.spawn cmd {: args : stdio}
+ (fn [code signal]
+ (if (not= code 0)
+ (vim.schedule #(vim.notify (.. "nix-develop: exit code "
+ code " " signal)))))))
+ (loop.read_start stdout
+ (fn [err data]
+ (assert (not err) err)
+ (if data
+ (set nix-print-dev-env (.. nix-print-dev-env data))
+ (do
+ (vim.schedule #(vim.notify "nix-develop: stdout end"))
+ (if (not= nix-print-dev-env "")
+ (handle-nix-print-dev-env nix-print-dev-env)))))))
+
+(vim.api.nvim_create_user_command :NixDevelop
+ (fn [ctx]
+ (nix-develop ctx.fargs true))
+ {:nargs "*"})
+
+(vim.api.nvim_create_augroup :nix-develop {:clear true})
+(vim.api.nvim_create_autocmd [:DirChanged :VimEnter]
+ {:pattern ["*"]
+ :callback (fn [ctx]
+ (unload-env)
+ (if (= 1
+ (vim.fn.filereadable (.. ctx.file
+ :/flake.nix)))
+ (nix-develop false)))})
diff --git a/mut/neovim/fnl/conf/pkgs.fnl b/mut/neovim/fnl/conf/pkgs.fnl
new file mode 100644
index 0000000..1445454
--- /dev/null
+++ b/mut/neovim/fnl/conf/pkgs.fnl
@@ -0,0 +1,15 @@
+;; (require :conf.pkgs.cmp)
+
+;; (require :conf.pkgs.null-ls)
+;; (require :conf.pkgs.lspconfig)
+;; (require :conf.pkgs.treesitter)
+;; (require :conf.pkgs.tree-sitter-context)
+;; (require :conf.pkgs.conjure)
+;; (require :conf.pkgs.test)
+;; (require :conf.pkgs.lsp_lines)
+;; (require :conf.pkgs.noice)
+;; (require :conf.pkgs.dap)
+;; (require :conf.pkgs.heirline)
+;; (require :conf.pkgs.gitsigns)
+;; (require :conf.pkgs.harpoon)
+;; (require :conf.pkgs.venn)
diff --git a/mut/neovim/fnl/conf/pkgs/cmp.fnl b/mut/neovim/fnl/conf/pkgs/cmp.fnl
new file mode 100644
index 0000000..76319f4
--- /dev/null
+++ b/mut/neovim/fnl/conf/pkgs/cmp.fnl
@@ -0,0 +1,114 @@
+(local cmp (require :cmp))
+(local compare (require :cmp.config.compare))
+(local always-first [:write :edit :split :quit :cfirst])
+
+(fn string-startswith? [str start]
+ (= start (string.sub str 1 (string.len start))))
+
+(fn string-startswith-anyof? [str start-list]
+ (fn iter [[item & rest]]
+ (if (not item) false
+ (string-startswith? str item) true
+ (iter rest)))
+
+ (iter start-list))
+
+(fn string-startswith-upper? [str]
+ (local first-char (string.sub str 1 1))
+ (= first-char (string.upper first-char)))
+
+(fn has-words-before? []
+ (local [line col] (vim.api.nvim_win_get_cursor 0))
+ (local [word & rest] (vim.api.nvim_buf_get_lines 0 (- line 1) line true))
+ (local before (word:sub col col))
+ (local is_string (before:match "%s"))
+ (and (not= col 0) (= is_string nil)))
+
+(fn enum [types key]
+ (. (. cmp types) key))
+
+(fn cmp-setup [cmp autocomplete]
+ (let [luasnip (require :luasnip)
+ snip (fn [args]
+ (luasnip.lsp_expand (. args :body)))]
+ (local cfg
+ {:experimental {:ghost_text true}
+ :snippet {:expand snip}
+ :preselect cmp.PreselectMode.None
+ :mapping {:<Tab> (cmp.mapping (fn [fallback]
+ (if (cmp.visible)
+ (cmp.select_next_item)
+ (luasnip.expand_or_jumpable)
+ (luasnip.expand_or_jump)
+ (has-words-before?)
+ (cmp.complete)
+ (fallback))
+ [:i :s]))
+ :<S-Tab> (cmp.mapping (fn [fallback]
+ (if (cmp.visible)
+ (cmp.select_prev_item)
+ (luasnip.jumpable -1)
+ (luasnip.jump -1)
+ (fallback))
+ [:i :s]))
+ :<C-b> (cmp.mapping.scroll_docs -4)
+ :<C-f> (cmp.mapping.scroll_docs 4)
+ :<C-j> (cmp.mapping.complete)
+ :<CR> (cmp.mapping.confirm {:behavior (enum :ConfirmBehavior
+ :Replace)
+ :select true})}
+ :sources (cmp.config.sources [{:name :nvim_lsp}
+ {:name :path}
+ {:name :luasnip}])})
+ (if (not autocomplete) (tset cfg :completion {:autocomplete false}))
+ ;; (print (vim.inspect cfg))
+ (cmp.setup cfg)
+ (cmp.setup.cmdline ["/" "?"]
+ {:sources (cmp.config.sources [{:name :buffer}])
+ :experimental {:ghost_text true}
+ :mapping (cmp.mapping.preset.cmdline)})
+ (cmp.setup.cmdline ":"
+ {:matching {:disallow_partial_fuzzy_matching true
+ :disallow_prefix_unmatching true}
+ :sources (cmp.config.sources [{:name :path}]
+ [{:name :cmdline
+ :keyword_length 1}])
+ :preselect cmp.PreselectMode.Item
+ :sorting {:priority_weight 2
+ :comparators [(fn [e1 e2]
+ (fn iter [[item & rest]]
+ (if (or (not rest)
+ (not item))
+ false
+ (= e1.completion_item.label
+ item)
+ true
+ (iter rest)))
+
+ (iter always-first))
+ compare.offset
+ compare.exact
+ compare.score
+ compare.locality
+ compare.kind
+ compare.length
+ compare.order]}
+ :mapping (cmp.mapping.preset.cmdline {:<CR> {:c (fn [fallback]
+ (if (not (cmp.confirm {:behavior (enum :ConfirmBehavior
+ :Replace)
+ :select true}))
+ (fallback)
+ (vim.schedule fallback)))}})})))
+
+; {:name :cmdline_history
+; :keyword_pattern "^[ABCDEFHIJKLMNOPQRSTUVWXYZ].*"
+; :entry_filter (fn [entry
+; ctx]
+; (if (string-startswith-upper entry.completion_item.label)
+; true
+; false))
+; :max_item_count 1)})))
+; disallow_fuzzy_matching = false,
+; disallow_partial_matching = false,
+; disallow_prefix_unmatching = false,)))
+(cmp-setup cmp true)
diff --git a/mut/neovim/fnl/conf/pkgs/conjure.fnl b/mut/neovim/fnl/conf/pkgs/conjure.fnl
new file mode 100644
index 0000000..c07a6f4
--- /dev/null
+++ b/mut/neovim/fnl/conf/pkgs/conjure.fnl
@@ -0,0 +1,17 @@
+(tset vim.g "conjure#log#wrap" true)
+
+(tset vim.g "conjure#client#python#stdio#command" "python -iq")
+
+(vim.api.nvim_create_user_command :ConjurePythonCommand
+ (fn [opts]
+ (tset vim.g
+ "conjure#client#python#stdio#command"
+ opts.args))
+ {:nargs 1})
+
+(let [group (vim.api.nvim_create_augroup "conf#pkgs#conjure" {:clear true})]
+ (vim.api.nvim_create_autocmd [:BufEnter]
+ {: group
+ :callback (fn [opts]
+ (vim.diagnostic.disable opts.buf))
+ :pattern [:conjure-log*]}))
diff --git a/mut/neovim/fnl/conf/pkgs/dap.fnl b/mut/neovim/fnl/conf/pkgs/dap.fnl
new file mode 100644
index 0000000..6476d3e
--- /dev/null
+++ b/mut/neovim/fnl/conf/pkgs/dap.fnl
@@ -0,0 +1,78 @@
+(local dap (require :dap))
+(local adapters (. dap :adapters))
+(local configurations (. dap :configurations))
+
+(local dapui (require :dapui))
+
+(tset adapters :delve
+ {:type :server
+ :port "${port}"
+ :executable {:command :dlv :args [:dap :-l "127.0.0.1:${port}"]}})
+
+(tset configurations :go
+ [{:type :delve
+ :name :Debug
+ :request :launch
+ :env {:CGO_CFLAGS :-Wno-error=cpp}
+ :program "${file}"}
+ {:type :delve
+ :name :DebugTest
+ :request :launch
+ :mode :test
+ :env {:CGO_CFLAGS :-Wno-error=cpp}
+ :program "${file}"}
+ {:type :delve
+ :name :DebugTerraform
+ :request :launch
+ :program "${file}"
+ :env {:CGO_CFLAGS :-Wno-error=cpp}
+ :args [:-debug]}
+ {:type :delve
+ :name :DebugTerraformAcc
+ :request :launch
+ :program "${file}"
+ :mode :test
+ :env {:CGO_CFLAGS :-Wno-error=cpp :TF_ACC :1}}
+ {:type :delve
+ :name :DebugTestSuite
+ :request :launch
+ :mode :test
+ :env {:CGO_CFLAGS :-Wno-error=cpp}
+ :program "${fileDirname}"}])
+
+(dapui.setup {:expand_lines false})
+
+(vim.keymap.set :n :si (lambda []
+ (dapui.toggle {:reset true})) {:silent true})
+;; "breakpoints",
+;; "repl",
+;; "scopes",
+;; "stacks",
+;; "watches",
+;; "hover",
+;; "console",)
+(vim.keymap.set :n :sfw
+ (lambda []
+ (dapui.float_element :watches
+ {:width (vim.api.nvim_win_get_width 0) :height 30 :enter true})))
+(vim.keymap.set :n :sfs
+ (lambda []
+ (dapui.float_element :scopes
+ {:width (vim.api.nvim_win_get_width 0) :height 30 :enter true})))
+
+(vim.keymap.set :n :sq dap.terminate {:silent true})
+(vim.keymap.set :n :sc dap.continue {:silent true})
+(vim.keymap.set :n :sr dap.run_to_cursor {:silent true})
+(vim.keymap.set :n :sn dap.step_over {:silent true})
+(vim.keymap.set :n :ss dap.step_into {:silent true})
+(vim.keymap.set :n :so dap.step_out {:silent true})
+(vim.keymap.set :n :sb dap.toggle_breakpoint {:silent true})
+(vim.keymap.set :n :sB dap.set_breakpoint {:silent true})
+(vim.keymap.set :n :slp
+ (fn []
+ (dap.set_breakpoint nil nil
+ (vim.fn.input "Log point message: ")))
+ {:silent true})
+
+(vim.keymap.set :n :st dap.repl.toggle {:silent true})
+(vim.keymap.set :n :sl dap.run_last {:silent true})
diff --git a/mut/neovim/fnl/conf/pkgs/gitsigns.fnl b/mut/neovim/fnl/conf/pkgs/gitsigns.fnl
new file mode 100644
index 0000000..813d410
--- /dev/null
+++ b/mut/neovim/fnl/conf/pkgs/gitsigns.fnl
@@ -0,0 +1,2 @@
+(local gitsigns (require :gitsigns))
+(gitsigns.setup)
diff --git a/mut/neovim/fnl/conf/pkgs/harpoon.fnl b/mut/neovim/fnl/conf/pkgs/harpoon.fnl
new file mode 100644
index 0000000..3f5fc48
--- /dev/null
+++ b/mut/neovim/fnl/conf/pkgs/harpoon.fnl
@@ -0,0 +1,39 @@
+(local harpoon-mark (require :harpoon.mark))
+(local harpoon-ui (require :harpoon.ui))
+(fn make-harpoon [func]
+ (fn []
+ (func)
+ (vim.cmd :redrawtabline)))
+
+(vim.keymap.set :n "[]" (make-harpoon (fn [] (harpoon-mark.add_file))))
+(vim.keymap.set :n "][" (make-harpoon (fn [] (harpoon-ui.toggle_quick_menu))))
+(vim.keymap.set :n "]]" (make-harpoon (fn [] (harpoon-ui.nav_next))))
+(vim.keymap.set :n "[[" (make-harpoon (fn [] (harpoon-ui.nav_prev))))
+
+(var use-numbers false)
+(local num [1 2 3 4 5])
+(local shortcuts ["+" "-" "<" ">" "\""])
+(fn print-use-numbers []
+ (print (vim.inspect use-numbers)))
+
+(fn toggle-harpoon-mappings []
+ (if (not use-numbers)
+ (do
+ ; (each [_ i (ipairs shortcuts)] ; (vim.keymap.del :n i))
+ (vim.keymap.set :n "[+" (make-harpoon (fn [] (harpoon-ui.nav_file 1))))
+ (vim.keymap.set :n "[-" (make-harpoon (fn [] (harpoon-ui.nav_file 2))))
+ (vim.keymap.set :n "[<" (make-harpoon (fn [] (harpoon-ui.nav_file 3))))
+ (vim.keymap.set :n "[>" (make-harpoon (fn [] (harpoon-ui.nav_file 4))))
+ (vim.keymap.set :n "[\"" (make-harpoon (fn [] (harpoon-ui.nav_file 5))))
+ (set use-numbers true))
+ (do
+ ; (each [_ s (ipairs shortcuts)] ; (vim.keymap.del :n s)
+ (vim.keymap.set :n "[1" (make-harpoon (fn [] (harpoon-ui.nav_file 1))))
+ (vim.keymap.set :n "[2" (make-harpoon (fn [] (harpoon-ui.nav_file 2))))
+ (vim.keymap.set :n "[3" (make-harpoon (fn [] (harpoon-ui.nav_file 3))))
+ (vim.keymap.set :n "[4" (make-harpoon (fn [] (harpoon-ui.nav_file 4))))
+ (vim.keymap.set :n "[5" (make-harpoon (fn [] (harpoon-ui.nav_file 5))))
+ (set use-numbers false))))
+
+(vim.api.nvim_create_user_command :H toggle-harpoon-mappings {})
+(toggle-harpoon-mappings)
diff --git a/mut/neovim/fnl/conf/pkgs/heirline.fnl b/mut/neovim/fnl/conf/pkgs/heirline.fnl
new file mode 100644
index 0000000..c8d9c52
--- /dev/null
+++ b/mut/neovim/fnl/conf/pkgs/heirline.fnl
@@ -0,0 +1,241 @@
+(local heirline (require :heirline))
+(local conditions (require :heirline.conditions))
+(local utils (require :heirline.utils))
+(local colors (let [kanagawa-colors (require :kanagawa.colors)]
+ (kanagawa-colors.setup)))
+
+(local Align {:provider "%="})
+(local Space {:provider " "})
+(fn with [tbl with-kv]
+ (local w {})
+ (each [k v (pairs tbl)]
+ (tset w k v))
+ (each [k v (pairs with-kv)]
+ (tset w k v))
+ w)
+
+(heirline.load_colors colors)
+(fn palette [name]
+ (. colors :palette name))
+
+(fn theme [theme name]
+ (. colors :theme theme name))
+
+(var FileNameBlock
+ {;; let's first set up some attributes needed by this component and it's children
+ :init (lambda [self]
+ (tset self :filename (vim.api.nvim_buf_get_name 0)))})
+
+(local FileName
+ {:provider (lambda [self]
+ ;; first, trim the pattern relative to the current directory. For other
+ ;;- options, see :h filename-modifers
+ (var filename (vim.fn.fnamemodify (. self :filename) ":."))
+ (if (= filename "")
+ (set filename "[No Name]")
+ ;;- now, if the filename would occupy more than 1/4th of the available
+ ;;-- space, we trim the file path to its initials
+ ;;-- See Flexible Components section below for dynamic truncation
+ (if (not (conditions.width_percent_below (length filename)
+ 0.25))
+ (set filename (vim.fn.pathshorten filename))))
+ filename)
+ :hl {:fg (. (utils.get_highlight :Directory) :fg)}})
+
+(local FileNameModifier {:hl (lambda []
+ (when vim.bo.modified
+ {:fg (theme :diag :warning)
+ :bold true
+ :force true}))})
+
+(local FileFlags [{:condition (lambda [] vim.bo.modified)
+ :provider "[+]"
+ :hl {:fg (theme :diag :warning)}}])
+
+(set FileNameBlock (utils.insert FileNameBlock
+ (utils.insert FileNameModifier FileName)
+ FileFlags {:provider "%<"}))
+
+(local DAPMessages {:condition (lambda []
+ (local dap (require :dap))
+ (local session (dap.session))
+ (not (= session nil)))
+ :provider (lambda []
+ (local dap (require :dap))
+ (.. " " (dap.status)))
+ :hl :Debug})
+
+(local Ruler {;; %l = current line number
+ ;; %L = number of lines in the buffer
+ ;; %c = column number
+ ;; %P = percentage through file of displayed window
+ :provider "%7(%l/%3L%):%2c %P"})
+
+(local ScrollBar
+ {:static {:sbar ["▁" "▂" "▃" "▄" "▅" "▆" "▇" "█"]}
+ ;; Another variant, because the more choice the better.
+ ;; sbar { '🭶', '🭷', '🭸', '🭹', '🭺', '🭻'}}
+ :provider (lambda [self]
+ (local curr_line (. (vim.api.nvim_win_get_cursor 0) 1))
+ (local lines (vim.api.nvim_buf_line_count 0))
+ (local i
+ (- (length self.sbar)
+ (math.floor (* (/ (- curr_line 1) lines)
+ (length (. self :sbar))))))
+ (string.rep (. self :sbar i) 2))
+ :hl {:fg (theme :syn :fun) :bg (theme :ui :bg)}})
+
+(local Nix
+ {:condition (fn [] vim.env.IN_NIX_SHELL)
+ :provider (fn [self]
+ (local purity vim.env.IN_NIX_SHELL)
+ (local name vim.env.name)
+ (.. "" purity "(" name ")"))
+ :hl {:fg (theme :syn :fun) :bold true :bg (theme :ui :bg_m3)}})
+
+(local RecordingMacro {:condition #(not= "" (vim.fn.reg_recording))
+ :provider (fn [self]
+ (.. "Recording... " (vim.fn.reg_recording)))
+ :hl {:fg (theme :syn :fun)
+ :bold true
+ :bg (theme :ui :bg_m3)}})
+
+(local harpoon (require :harpoon))
+(local harpoon-mark (require :harpoon.mark))
+(local harpoon-colors [(theme :syn :identifier)
+ (theme :syn :identifier)
+ (theme :syn :identifier)])
+
+(fn mark-component [i mark]
+ (utils.insert {} {:hl {:bg (if (= mark.filename
+ (vim.fn.fnamemodify (vim.api.nvim_buf_get_name 0)
+ ":."))
+ (theme :ui :bg_p1)
+ (theme :ui :bg_m1))
+ :bold true
+ :fg (. harpoon-colors i)}
+ :provider (fn [self]
+ (.. " M" i " "))}))
+
+;{:hl {:fg (theme :syn :fun)} :provider (vim.fn.pathshorten mark.filename)}))
+; {:hl {:bold true :fg (. harpoon-colors i)} :provider ")"} Space))
+
+(local HarpoonMarks
+ (utils.insert {:hl :TabLineSel
+ :condition #(< 0
+ (length (. (harpoon.get_mark_config)
+ :marks)))}
+ {:init (lambda [self]
+ (local mark-list
+ (. (harpoon.get_mark_config) :marks))
+ (each [i mark (ipairs mark-list)]
+ (tset self i
+ (self:new (mark-component i mark) i)))
+ (while (> (length self) (length mark-list))
+ (table.remove self (length self))))}))
+
+(local Tabpage
+ {:provider (lambda [self]
+ (fn fnamemod [name mod]
+ (vim.fn.fnamemodify name mod))
+
+ (fn format-name [name]
+ (if (= name "") "[No Name]"
+ (fnamemod name ":t")))
+
+ (.. "%" self.tabnr "T " self.tabnr " "))
+ :hl (lambda [self]
+ (if (not self.is_active) :TabLine :TabLineSel))})
+
+(fn active-tab-hrpn [self]
+ (local hl {})
+ (if (. self :is_active)
+ (do
+ (tset hl :fg (theme :syn :identifier))
+ (tset hl :bold true)))
+ hl)
+
+(fn active-hl [hl]
+ (lambda [self]
+ (if self.is_active
+ hl
+ {})))
+
+(fn tab-visible-buffers [tab]
+ (local visible (vim.fn.tabpagebuflist tab))
+ (if (= visible 0)
+ []
+ visible))
+
+(fn tab-harpoon-marks [tab]
+ (local visible (tab-visible-buffers tab))
+ (local tab-buffers (accumulate [buffers [] _ buf (ipairs visible)]
+ (do
+ (if (not (vim.tbl_contains buffers buf))
+ (table.insert buffers buf))
+ buffers)))
+ (icollect [_ buf (ipairs tab-buffers)]
+ (do
+ (local status (harpoon-mark.status buf))
+ (if (not= status "")
+ status))))
+
+(local Tabpage
+ (utils.insert Tabpage {:hl active-tab-hrpn :provider "🌊 [ "}
+ {:hl (active-hl {:fg (theme :syn :fun)})
+ :provider (lambda [self]
+ (local harpoon_marks
+ (tab-harpoon-marks self.tabnr))
+ (table.concat harpoon_marks " "))}
+ {:hl active-tab-hrpn :provider " ] %T"}))
+
+(local TabpageClose {:provider "%999X  %X" :hl :TabLine})
+
+(local TabPages
+ {;; only show this component if there's 2 or more tabpages
+ :condition (lambda []
+ (>= (length (vim.api.nvim_list_tabpages)) 1))})
+
+(local TabPages (utils.insert TabPages (utils.make_tablist Tabpage)
+ TabpageClose))
+
+(local dispatch-get-request (. vim.fn "dispatch#request"))
+(local Dispatch (utils.insert {:init (fn [self]
+ (set self.req (dispatch-get-request)))
+ :condition (fn []
+ (not (vim.tbl_isempty (dispatch-get-request))))}
+ {:provider "dispatch("
+ :hl (fn [self]
+ {:fg (if (= 1 self.req.completed)
+ (theme :syn :fun)
+ (theme :diag :warning))
+ :bold true})}
+ {:provider (fn [self]
+ self.req.command)
+ :hl {:fg (theme :syn :string) :bold false}}
+ {:provider ")"
+ :hl (fn [self]
+ {:fg (if (= 1 self.req.completed)
+ (theme :syn :fun)
+ (theme :diag :warning))
+ :bold true})}))
+
+(local StatusLine [FileNameBlock
+ Space
+ HarpoonMarks
+ Space
+ TabPages
+ DAPMessages
+ Space
+ RecordingMacro
+ Dispatch
+ Align
+ Space
+ Nix
+ Space
+ Ruler
+ Space
+ ScrollBar
+ Space])
+
+(heirline.setup {:statusline StatusLine})
diff --git a/mut/neovim/fnl/conf/pkgs/lsp_lines.fnl b/mut/neovim/fnl/conf/pkgs/lsp_lines.fnl
new file mode 100644
index 0000000..7194bd9
--- /dev/null
+++ b/mut/neovim/fnl/conf/pkgs/lsp_lines.fnl
@@ -0,0 +1,2 @@
+(let [l (require :lsp_lines)]
+ (l.setup))
diff --git a/mut/neovim/fnl/conf/pkgs/lsp_signature.fnl b/mut/neovim/fnl/conf/pkgs/lsp_signature.fnl
new file mode 100644
index 0000000..7fecc9e
--- /dev/null
+++ b/mut/neovim/fnl/conf/pkgs/lsp_signature.fnl
@@ -0,0 +1,3 @@
+(local lsp_signature (require :lsp_signature))
+
+(lsp_signature.setup)
diff --git a/mut/neovim/fnl/conf/pkgs/lspconfig.fnl b/mut/neovim/fnl/conf/pkgs/lspconfig.fnl
new file mode 100644
index 0000000..accd001
--- /dev/null
+++ b/mut/neovim/fnl/conf/pkgs/lspconfig.fnl
@@ -0,0 +1,51 @@
+(local lspconfig (require :lspconfig))
+(local configs (require :lspconfig.configs))
+(local {: attach} (require :conf.lsp))
+
+(lspconfig.pyright.setup {:root_dir (lspconfig.util.root_pattern :.git
+ (vim.fn.getcwd))
+ :on_attach attach})
+
+(lspconfig.tsserver.setup {:root_dir (lspconfig.util.root_pattern :.git
+ (vim.fn.getcwd))
+ :on_attach attach})
+
+(local pid (vim.fn.getpid))
+(lspconfig.omnisharp.setup {:cmd [:OmniSharp
+ :--languageserver
+ :--hostPID
+ (tostring pid)]
+ :handlers {[:textDocument/definition] (. (require :omnisharp_extended)
+ :handler)}
+ :root_dir (lspconfig.util.root_pattern :.git
+ (vim.fn.getcwd))
+ :on_attach attach})
+
+(lspconfig.gopls.setup {:root_dir (lspconfig.util.root_pattern :.git
+ (vim.fn.getcwd))
+ :on_attach attach
+ :settings {:gopls {:codelenses {:test true :bench true}
+ ;; Show a code lens toggling the display of gc's choices.}
+ :buildFlags [:-tags=all]}}})
+
+(lspconfig.ansiblels.setup {:ansible {:ansible {:path :ansible}
+ :executionEnvironment {:enabled false}
+ :python {:interpreterPath :python}
+ :validation {:enabled true
+ :lint {:enabled false
+ :arguments " --profile=production --write=all "
+ :path :ansible-lint}}}})
+
+;; (tset configs :fennel_language_server
+;; {:default_config {;; replace it with true path
+;; :cmd [:fennel-language-server]
+;; :filetypes [:fennel]
+;; :single_file_support true
+;; ;; source code resides in directory `fnl/`
+;; :root_dir (lspconfig.util.root_pattern :fnl)
+;; :settings {:fennel {:workspace {;; If you are using hotpot.nvim or aniseed,
+;; ;; make the server aware of neovim runtime files.
+;; :library (vim.api.nvim_list_runtime_paths)}
+;; :diagnostics {:globals [:vim]}}}}})
+;;
+;; (lspconfig.fennel_language_server.setup {:on_attach attach})
diff --git a/mut/neovim/fnl/conf/pkgs/neotest.fnl b/mut/neovim/fnl/conf/pkgs/neotest.fnl
new file mode 100644
index 0000000..251cdcb
--- /dev/null
+++ b/mut/neovim/fnl/conf/pkgs/neotest.fnl
@@ -0,0 +1,4 @@
+(let [nt (require :neotest)
+ python (require :neotest-python)]
+ (nt.setup {:adapters [(python {:dap {:justMyCode false}})]}))
+
diff --git a/mut/neovim/fnl/conf/pkgs/noice.fnl b/mut/neovim/fnl/conf/pkgs/noice.fnl
new file mode 100644
index 0000000..58ac761
--- /dev/null
+++ b/mut/neovim/fnl/conf/pkgs/noice.fnl
@@ -0,0 +1,34 @@
+(local noice (require :noice))
+(noice.setup {:views {:cmdline_popup {:border {:style :none :padding [1 3]}
+ :win_options {:winhighlight "NormalFloat:NormalFloat,FloatBorder:FloatBorder"}}}
+ :lsp {;; override markdown rendering so that **cmp** and other plugins use **Treesitter**
+ :override {[:vim.lsp.util.convert_input_to_markdown_lines] true
+ [:vim.lsp.util.stylize_markdown] true
+ [:cmp.entry.get_documentation] true}}
+ :popupmenu {:enabled false}
+ :messages {; NOTE: If you enable messages then the cmdline is enabled automatically.
+ ; This is a current Neovim limitation.
+ :enabled true
+ ; enables the Noice messages UI
+ :view :mini
+ ; default view for messages
+ :view_error :mini
+ ; view for errors
+ :view_warn :mini
+ ; view for warnings
+ :view_history :mini
+ ; view for :messages
+ :view_search :virtualtext}
+ ; view for search count messages. Set to `false` to disable}
+ ;; you can enable a preset for easier configuration
+ :presets {:bottom_search true
+ ; use a classic bottom cmdline for search
+ :command_palette true
+ ; position the cmdline and popupmenu together
+ :long_message_to_split true
+ ; long messages will be sent to a split
+ :inc_rename false
+ ; enables an input dialog for inc-rename.nvim
+ :lsp_doc_border false}})
+
+; add a border to hover docs and signature help}})
diff --git a/mut/neovim/fnl/conf/pkgs/null-ls.fnl b/mut/neovim/fnl/conf/pkgs/null-ls.fnl
new file mode 100644
index 0000000..9908823
--- /dev/null
+++ b/mut/neovim/fnl/conf/pkgs/null-ls.fnl
@@ -0,0 +1,21 @@
+(local lsp-conf (require :conf.lsp))
+(local null-ls (require :null-ls))
+
+(local fmt null-ls.builtins.formatting)
+(local diag null-ls.builtins.diagnostics)
+
+(fn executable? [program]
+ (fn []
+ (= 1 (vim.fn.executable program))))
+
+(null-ls.setup {:update_in_insert false
+ :debug true
+ :on_attach (fn [client buf]
+ (lsp-conf.attach client buf true))
+ :sources [fmt.alejandra
+ fmt.fnlfmt
+ (fmt.black.with {:condition (executable? :black)})
+ (fmt.goimports.with {:condition (executable? :goimports)})
+ (fmt.gofumpt.with {:condition (executable? :gofumpt)})
+ (fmt.raco_fmt.with {:condition (executable? :raco)})
+ (fmt.terraform_fmt.with {:condition (executable? :terraform)})]})
diff --git a/mut/neovim/fnl/conf/pkgs/test.fnl b/mut/neovim/fnl/conf/pkgs/test.fnl
new file mode 100644
index 0000000..4f0bcc4
--- /dev/null
+++ b/mut/neovim/fnl/conf/pkgs/test.fnl
@@ -0,0 +1,9 @@
+(tset vim.g "test#strategy" :neovim)
+(tset vim.g "test#neovim#term_position" :botright)
+
+(vim.keymap.set :n :<leader>t ":TestNearest<CR>" {:silent true})
+(vim.keymap.set :n :<leader>C ":TestClass<CR>" {:silent true})
+(vim.keymap.set :n :<leader>T ":TestFile<CR>" {:silent true})
+(vim.keymap.set :n :<leader>a ":TestSuite<CR>" {:silent true})
+(vim.keymap.set :n :<leader>l ":TestLast<CR>" {:silent true})
+(vim.keymap.set :n :<leader>g ":TestVisit<CR>" {:silent true})
diff --git a/mut/neovim/fnl/conf/pkgs/tree-sitter-context.fnl b/mut/neovim/fnl/conf/pkgs/tree-sitter-context.fnl
new file mode 100644
index 0000000..12fedc6
--- /dev/null
+++ b/mut/neovim/fnl/conf/pkgs/tree-sitter-context.fnl
@@ -0,0 +1,2 @@
+(local context (require :treesitter-context))
+(context.setup {:enable true})
diff --git a/mut/neovim/fnl/conf/pkgs/treesitter.fnl b/mut/neovim/fnl/conf/pkgs/treesitter.fnl
new file mode 100644
index 0000000..c613be0
--- /dev/null
+++ b/mut/neovim/fnl/conf/pkgs/treesitter.fnl
@@ -0,0 +1,2 @@
+(let [ts (require :nvim-treesitter.configs)]
+ (ts.setup {:highlight {:enable true}}))
diff --git a/mut/neovim/fnl/conf/pkgs/venn.fnl b/mut/neovim/fnl/conf/pkgs/venn.fnl
new file mode 100644
index 0000000..064e84e
--- /dev/null
+++ b/mut/neovim/fnl/conf/pkgs/venn.fnl
@@ -0,0 +1,18 @@
+;; venn.nvim: enable or disable keymappings
+(fn toggle-venn []
+ (if (not vim.b.venn_enabled)
+ (do
+ (set vim.b.venn_enabled true)
+ (vim.cmd "setlocal ve=all") ; draw a line on HJKL keystokes
+ (vim.keymap.set [:n] :J "<C-v>j:VBox<CR>" {:noremap true :buffer 0})
+ (vim.keymap.set [:n] :K "<C-v>k:VBox<CR>" {:noremap true :buffer 0})
+ (vim.keymap.set [:n] :L "<C-v>l:VBox<CR>" {:noremap true :buffer 0})
+ (vim.keymap.set [:n] :H "<C-v>h:VBox<CR>" {:noremap true :buffer 0}) ; draw a box by pres]sing "f" with visual selection)
+ (vim.keymap.set [:v] :f ":VBox<CR>" {:noremap true :buffer 0}))
+ (do
+ (vim.cmd "setlocal ve=")
+ (vim.cmd "mapclear <buffer>")
+ (set vim.b.venn_enabled nil))))
+
+; toggle keymappings for venn using <leader>v)
+(vim.keymap.set [:n] :<leader>v toggle-venn {:noremap true})
diff --git a/mut/neovim/fnl/conf/settings.fnl b/mut/neovim/fnl/conf/settings.fnl
new file mode 100644
index 0000000..ec68e6c
--- /dev/null
+++ b/mut/neovim/fnl/conf/settings.fnl
@@ -0,0 +1,69 @@
+(import-macros {: settings : globals} :conf.macros)
+
+(globals
+ codeium_enabled false
+ loaded_2html_plugin true
+ loaded_fzf false
+ loaded_man false
+ loaded_gzip false
+ loaded_health false
+ loaded_matchit false
+ loaded_matchparen false
+ loaded_netrwPlugin false
+ loaded_rplugin false
+ loaded_shada false
+ loaded_spellfile false
+ loaded_tarPlugin false
+ loaded_tohtml false
+ loaded_tutor false
+ loaded_zipPlugin false
+
+ mapleader " "
+ maplocalleader " "
+ dirvish_mode ":sort | sort ,^.*[^/]$, r")
+
+(settings
+ +shortmess "c"
+ +diffopt vertical
+ +isfname "@-@"
+ wmw 10
+ inccommand split
+ signcolumn yes
+ smd off
+ scrolloff 8
+ termguicolors on
+ incsearch on
+ undofile on
+ undodir (.. (os.getenv :HOME) :/.local/share/nvim/undo)
+ backup off
+ backupcopy yes
+ swapfile off
+ wrap off
+ splitbelow on
+ magic on
+ showbreak "+++"
+ listchars {:eol "󰁂"}
+ list on
+ autoread on
+ autoindent on
+ smartindent on
+ expandtab on
+ tabstop 4
+ softtabstop 4
+ shiftwidth 4
+ hidden on
+ number on
+ relativenumber on
+ exrc on
+ secure on
+ completeopt "menuone,noselect"
+ wildmode "lastused"
+ complete ".,w,k,kspell,b"
+ foldopen "block,hor,jump,mark,percent,quickfix,search,tag"
+ laststatus 3
+ ; winbar "%=%m %f"
+ winbar ""
+ hlsearch off
+ clipboard ""
+ showtabline 0
+ cmdheight 0)
diff --git a/mut/neovim/fnl/conf/wict-nvim/builder.fnl b/mut/neovim/fnl/conf/wict-nvim/builder.fnl
new file mode 100644
index 0000000..177b773
--- /dev/null
+++ b/mut/neovim/fnl/conf/wict-nvim/builder.fnl
@@ -0,0 +1,99 @@
+(tset package.loaded :conf.wict-nvim.frames.frame nil)
+(local vec (require :conf.wict-nvim.frames.vec))
+(local frame (require :conf.wict-nvim.frames.frame))
+(local m {})
+
+;; Creates a new painter that wraps the paint and close methods of a painter
+(local transform-painter (fn [painter ori width height]
+ (fn [frm]
+ (local coord (frame.frame->coord frm))
+ (local new-ori (coord ori))
+ (local new-frame
+ (frame new-ori
+ (vec.sub (coord width) new-ori)
+ (vec.sub (coord height) new-ori)))
+ (painter new-frame))))
+
+(local pad (fn [painter pad-size]
+ (fn [frm]
+ (local pad-width (/ pad-size (frame.width frm)))
+ (local pad-height (/ pad-size (frame.height frm)))
+ (local transformed
+ (transform-painter painter (vec.vec pad-width pad-height)
+ (vec.vec (- 1 pad-width) pad-height)
+ (vec.vec pad-width (- 1 pad-height))))
+ (transformed frm))))
+
+(local beside (fn [p1 p2 size]
+ (local size (or size 0.5))
+ (local left
+ (transform-painter p1 (vec.vec 0 0) (vec.vec size 0)
+ (vec.vec 0 1)))
+ (local right
+ (transform-painter p2 (vec.vec size 0) (vec.vec 1 0)
+ (vec.vec size 1)))
+ (fn [frm]
+ (left frm)
+ (right frm))))
+
+(local builder {})
+
+(fn builder.Padding [self size]
+ (table.insert self.partial-painters {:op :pad : size})
+ self)
+
+(fn builder.Beside [self partial-builder size]
+ (table.insert self.partial-painters {:op :beside : partial-builder : size})
+ self)
+
+(fn builder.LeftOf [self partial-builder size]
+ (table.insert self.partial-painters {:op :left : partial-builder : size})
+ self)
+
+(fn builder.RightOf [self partial-builder size]
+ (table.insert self.partial-painters {:op :right : partial-builder : size})
+ self)
+
+(fn builder.build-painter [self effects]
+ (accumulate [painter (fn [frame] (print :leaf-painter)) _ partial-painter (ipairs self.partial-painters)]
+ (do
+ (match partial-painter
+ {:op :pad : size} (do
+ (pad painter size))
+ {:op :left : partial-builder} (do
+ (beside painter
+ (partial-builder:build-painter effects)
+ partial-painter.size))
+ {:op :right : partial-builder} (do
+ (beside (partial-builder:build-painter effects)
+ painter partial-painter.size))
+ {:op :beside : partial-builder} (do
+ (beside painter
+ (partial-builder:build-painter effects)
+ partial-painter.size))
+ {: maps : buffer} (do
+ (local window (effects:new-window maps))
+ (local painter-ptr painter)
+ (fn [frm]
+ (local frame-opts
+ (frame.frame->open-win-options frm))
+ (local buf (buffer))
+ (if (not (window:open?))
+ (window:open buf frame-opts)
+ (window:repaint buf frame-opts))
+ (painter-ptr frm)))
+ _ painter))))
+
+(fn builder.Build [self effects]
+ (local painter (self:build-painter effects))
+ (fn [frm]
+ (effects:attach)
+ (painter frm)))
+
+(fn builder.For [partial-painter]
+ (local bldr {:partial-painters [partial-painter]})
+ (setmetatable bldr builder)
+ (set builder.__index builder)
+ bldr)
+
+builder
diff --git a/mut/neovim/fnl/conf/wict-nvim/effects.fnl b/mut/neovim/fnl/conf/wict-nvim/effects.fnl
new file mode 100644
index 0000000..e4321da
--- /dev/null
+++ b/mut/neovim/fnl/conf/wict-nvim/effects.fnl
@@ -0,0 +1,81 @@
+(local m {})
+(local window {})
+
+(local aug vim.api.nvim_create_augroup)
+(local del-aug (fn [] (vim.api.nvim_create_augroup :EffectsMgr {:clear true})))
+(local au vim.api.nvim_create_autocmd)
+(local winvar (fn [...] (pcall vim.api.nvim_win_get_var ...)))
+(local unmap (fn [{: mode : lhs : opts}] (pcall vim.keymap.del mode lhs opts)))
+(local map (fn [mode lhs rhs opts] (vim.keymap.set mode lhs rhs opts)))
+
+(fn window.close [self]
+ (if (self:open?)
+ (set self.handle (vim.api.nvim_win_close self.handle true))))
+
+(fn window.open [self buf frame]
+ (set frame.style :minimal)
+ (set self.handle (vim.api.nvim_open_win buf false frame))
+ (P self.handle :before-setvar)
+ (vim.api.nvim_buf_set_var buf :effect-window self)
+ (vim.api.nvim_win_set_var self.handle :effect-window self)
+ (if self.enter
+ (vim.api.nvim_set_current_win self.handle)))
+
+(fn window.id [self]
+ self.handle)
+
+(fn window.open? [self]
+ (if self.handle
+ (vim.api.nvim_win_is_valid self.handle) false))
+
+(fn window.new [self i enter maps]
+ (local w (setmetatable {: i : enter : maps} window))
+ (set self.__index self)
+ w)
+
+(fn m.new-window [self maps]
+ (local w (window:new (+ (length self.windows) 1) (= (length self.windows) 0)
+ maps))
+ (table.insert self.windows w)
+ w)
+
+(fn m.close [self]
+ (each [_ w (ipairs self.windows)]
+ (w:close))
+ (if self.augroup
+ (set self.augroup (del-aug self.augroup)))
+ (if self.unmap
+ (set self.unmap (self.unmap))))
+
+(fn m.attach [self]
+ (set self.augroup (aug :EffectsMgr {:clear true}))
+ (au [:WinEnter]
+ {:group self.augroup
+ :pattern "*"
+ :callback (fn [cb-info]
+ (P :effectEnter)
+ (local (ok? win) (winvar 0 :effect-window))
+ (P ok? win)
+ (if (not ok?)
+ (self:close)
+ (do
+ (if win.maps
+ (self:win-maps win)))))}))
+
+(fn m.win-maps [self win]
+ (P win)
+ (if self.unmap
+ (self.unmap))
+ (set self.unmap (fn []
+ (each [_ m (ipairs win.maps)]
+ (unmap m))))
+ (each [_ {: mode : lhs : rhs : opts} (ipairs win.maps)]
+ (map mode lhs (rhs self win) opts)))
+
+(fn m.new [self opts]
+ (local effects {:windows []})
+ (setmetatable effects self)
+ (set self.__index self)
+ effects)
+
+m
diff --git a/mut/neovim/fnl/conf/wict-nvim/frames/frame.fnl b/mut/neovim/fnl/conf/wict-nvim/frames/frame.fnl
new file mode 100644
index 0000000..d32c9b5
--- /dev/null
+++ b/mut/neovim/fnl/conf/wict-nvim/frames/frame.fnl
@@ -0,0 +1,61 @@
+(local vec (require :conf.wict-nvim.frames.vec))
+(local m {})
+(local frame {})
+
+;; frame is interpreted as matrix coords
+;; origin ------------------> ne-edge
+;; |
+;; |
+;; |
+;; |
+;; |
+;; |
+;;\ /
+;; .
+;; sw-edge
+(fn frame.make [self ori width height]
+ (local f {: ori : width : height})
+ (setmetatable f self)
+ (set self.__index self)
+ f)
+
+(fn frame.origin [f]
+ f.ori)
+
+(fn frame.width-edge [f]
+ f.width)
+
+(fn frame.height-edge [f]
+ f.height)
+
+(fn m.frame->coord [f]
+ (fn [v]
+ (vec.add (f:origin)
+ (vec.add (vec.scale (v:x-coord) (f:width-edge))
+ (vec.scale (v:y-coord) (f:height-edge))))))
+
+(fn m.width [f]
+ (let [width-edge (f:width-edge)]
+ (width-edge:x-coord)))
+
+(fn m.height [f]
+ (let [height-edge (f:height-edge)]
+ (height-edge:y-coord)))
+
+(fn m.frame->open-win-options [f anchor]
+ (local coord (m.frame->coord f))
+ (local ori (f:origin))
+ (local width-edge (f:width-edge))
+ (local height-edge (f:height-edge))
+ (local anchor (or anchor :NW))
+ {:width (width-edge:x-coord)
+ :height (height-edge:y-coord)
+ :col (ori:x-coord)
+ :row (ori:y-coord)
+ : anchor
+ :relative :editor})
+
+(setmetatable m {:__call (fn [self ...]
+ (frame:make ...))})
+
+m
diff --git a/mut/neovim/fnl/conf/wict-nvim/frames/vec.fnl b/mut/neovim/fnl/conf/wict-nvim/frames/vec.fnl
new file mode 100644
index 0000000..4a9515d
--- /dev/null
+++ b/mut/neovim/fnl/conf/wict-nvim/frames/vec.fnl
@@ -0,0 +1,28 @@
+(local m {})
+(local vec {})
+
+(fn vec.make [self x y]
+ (local v {: x : y})
+ (setmetatable v self)
+ (set self.__index self)
+ v)
+
+(fn vec.x-coord [v]
+ v.x)
+
+(fn vec.y-coord [v]
+ v.y)
+
+(fn m.add [v1 v2]
+ (vec:make (+ (v1:x-coord) (v2:x-coord)) (+ (v1:y-coord) (v2:y-coord))))
+
+(fn m.sub [v1 v2]
+ (vec:make (- (v1:x-coord) (v2:x-coord)) (- (v1:y-coord) (v2:y-coord))))
+
+(fn m.scale [a v]
+ (vec:make (math.floor (* a (v:x-coord))) (math.floor (* a (v:y-coord)))))
+
+(fn m.vec [...]
+ (vec:make ...))
+
+m
diff --git a/mut/neovim/fnl/conf/wict-nvim/init.fnl b/mut/neovim/fnl/conf/wict-nvim/init.fnl
new file mode 100644
index 0000000..9e40fad
--- /dev/null
+++ b/mut/neovim/fnl/conf/wict-nvim/init.fnl
@@ -0,0 +1,31 @@
+(tset package.loaded :conf.wict-nvim.frames.vec nil)
+(local vec (require :conf.wict-nvim.frames.vec))
+
+(tset package.loaded :conf.wict-nvim.frames.frame nil)
+(local frame (require :conf.wict-nvim.frames.frame))
+
+(tset package.loaded :conf.wict-nvim.builder nil)
+(local builder (require :conf.wict-nvim.builder))
+
+(tset package.loaded :conf.wict-nvim.effects nil)
+(local effects (require :conf.wict-nvim.effects))
+
+(local m {})
+
+(local root-frame (frame (vec.vec 0 0) (vec.vec vim.o.columns 0)
+ (vec.vec 0 vim.o.lines)))
+
+(local painter (-> (builder.For {:buffer (fn [] 0)
+ :maps [{:mode [:n :v :o]
+ :lhs :q
+ :rhs (fn [effects window]
+ (fn []
+ (effects:close)))}]})
+ (builder.Beside (-> (builder.For {:buffer (fn [] 0)
+ :maps []}))
+ 0.5)
+ (builder.Padding 5)
+ (builder.Build (effects:new))))
+
+; (painter root-frame)
+{: root-frame : builder : effects}
diff --git a/mut/neovim/fnl/conf/wictl-nvim/init.fnl b/mut/neovim/fnl/conf/wictl-nvim/init.fnl
new file mode 100644
index 0000000..bd04182
--- /dev/null
+++ b/mut/neovim/fnl/conf/wictl-nvim/init.fnl
@@ -0,0 +1,58 @@
+(local Path (require :plenary.path))
+(tset package.loaded :conf.wict-nvim nil)
+(local wict (require :conf.wict-nvim))
+(tset package.loaded :conf.wictl-nvim.resolvers nil)
+(local Resolver (require :conf.wictl-nvim.resolvers))
+
+(local bld wict.builder)
+(local eff wict.effects)
+
+(local config_path (vim.fn.stdpath :config))
+(local data_path (vim.fn.stdpath :data))
+(local user_config (string.format "%s/wictl.json" config_path))
+(local cache_config (string.format "%s/wictl.json" data_path))
+
+(local m {})
+
+(local WictlConfig {})
+;; {
+;; ["/path/to/project"] = {
+;; terms = [{cmd = "k9s"}]
+;; }
+
+(fn m.Edit [project])
+
+(fn m.Read [path]
+ (local p (Path:new path))
+ (vim.fn.json_decode (p:read)))
+
+(fn m.Save []
+ (local cache-path (Path:new cache_config))
+ (cache-path:write (vim.fn.json_encode WictlConfig) :w))
+
+(local ensure-complete-project (fn [config]
+ (var config (or config {:terms []}))
+ (if (not config.terms)
+ (set config.terms
+ [{:name :k9s :cmd :bash}]))
+ config))
+
+(local get-project (fn []
+ (local proj (. WictlConfig (Resolver.project_key)))
+ (ensure-complete-project (or proj
+ (do
+ (local cfg {})
+ (tset WictlConfig
+ (Resolver.project_key)
+ cfg)
+ cfg)))))
+
+(fn m.Get-Terms-Config []
+ (local proj (get-project))
+ proj.terms)
+
+(m.Save)
+(m.Read cache_config)
+(m.Get-Terms-Config)
+
+m
diff --git a/mut/neovim/fnl/conf/wictl-nvim/resolvers.fnl b/mut/neovim/fnl/conf/wictl-nvim/resolvers.fnl
new file mode 100644
index 0000000..df5f2ac
--- /dev/null
+++ b/mut/neovim/fnl/conf/wictl-nvim/resolvers.fnl
@@ -0,0 +1,5 @@
+(local m {})
+(fn m.project_key []
+ (vim.loop.cwd))
+
+m
diff --git a/mut/neovim/fnl/conf/wictl-nvim/term.fnl b/mut/neovim/fnl/conf/wictl-nvim/term.fnl
new file mode 100644
index 0000000..51e263a
--- /dev/null
+++ b/mut/neovim/fnl/conf/wictl-nvim/term.fnl
@@ -0,0 +1,54 @@
+(tset package.loaded :conf.wict-nvim nil)
+(local ui (require :conf.wict-nvim))
+(tset package.loaded :conf.wict-nvim.effects nil)
+(local ui-eff (require :conf.wict-nvim.effects))
+
+(tset package.loaded :conf.wictl-nvim nil)
+(local wictl (require :conf.wictl-nvim))
+
+(local Resolver (require :conf.wictl-nvim.resolvers))
+(local ui-bld ui.builder)
+(local M {})
+
+(local ProjectBufs {})
+(var selected nil)
+(local term-ui (-> (ui-bld.For {:buffer (fn [] selected)
+ :maps [{:mode [:n :v :o]
+ :lhs :q
+ :rhs (fn [effects window]
+ (fn []
+ (P :quitting!)
+ (effects:close)))}]})
+ (ui-bld.Padding 2)
+ (ui-bld.Build (ui-eff:new))))
+
+(fn M.open [idx]
+ (local new-term-buf (fn []
+ (local (buf_handle term_handle) (M.start idx))
+ (tset ProjectBufs (Resolver.project_key) idx
+ {: buf_handle : term_handle})
+ {: buf_handle : term_handle}))
+ (local proj (or (. ProjectBufs (Resolver.project_key))
+ (do
+ (local p [])
+ (tset ProjectBufs (Resolver.project_key) p)
+ p)))
+ (var term (or (. proj idx) (new-term-buf)))
+ (if (or (not (vim.api.nvim_buf_is_valid term.buf_handle))
+ (not (vim.api.nvim_buf_get_var term.buf_handle :terminal_job_id)))
+ (set term (new-term-buf)))
+ (set selected term.buf_handle)
+ (term-ui ui.root-frame))
+
+(fn M.start [idx]
+ (P :starting)
+ (local term (. (wictl.Get-Terms-Config) idx))
+ (local prestart-buf (vim.api.nvim_get_current_buf))
+ (vim.cmd (.. "edit term://" term.cmd))
+ (local buf_handle (vim.api.nvim_get_current_buf))
+ (local term_handle vim.b.terminal_job_id)
+ (vim.api.nvim_buf_set_option buf_handle :bufhidden :hide)
+ (vim.api.nvim_set_current_buf prestart-buf)
+ (values buf_handle term_handle))
+
+M
diff --git a/mut/neovim/init.fnl b/mut/neovim/init.fnl
new file mode 100644
index 0000000..7e82675
--- /dev/null
+++ b/mut/neovim/init.fnl
@@ -0,0 +1,36 @@
+;; fixes nixpkgs hotpot not adding package path correctly
+
+(tset _G.package :path
+ (.. (vim.fn.stdpath :cache) "/hotpot/hotpot.nvim/lua/?/init.lua;"
+ package.path))
+
+(fn build-init []
+ (let [{: build} (require :hotpot.api.make)
+ allowed-globals (icollect [n _ (pairs _G)]
+ n)
+ opts {:verbosity 0
+ :compiler {:modules {:allowedGlobals allowed-globals}}}
+ here #(values $1)
+ config-path (vim.fn.stdpath :config)]
+ (build config-path opts (.. config-path :/init.fnl) here
+ (.. config-path :/after/ftdetect/.+) here
+ (.. config-path :/ftplugin/.+) here
+ (.. config-path :/after/ftplugin/.+) here)))
+
+;; Call hotpot.setup and compile again after fs event
+
+(let [hotpot (require :hotpot)
+ setup hotpot.setup
+ build hotpot.api.make.build
+ uv vim.loop
+ config-path (vim.fn.stdpath :config)]
+ (setup {:provide_require_fennel true
+ :compiler {:modules {:correlate true}
+ :macros {:env :_COMPILER
+ :compilerEnv _G
+ :allowedGlobals false}}})
+ (let [handle (uv.new_fs_event)
+ path (vim.fn.expand (.. config-path :/init.fnl))]
+ (uv.fs_event_start handle path {} #(vim.schedule build-init))
+ (vim.api.nvim_create_autocmd :VimLeavePre {:callback #(uv.close handle)})))
+(require :conf)
diff --git a/mut/neovim/init.lua b/mut/neovim/init.lua
new file mode 100644
index 0000000..3de4446
--- /dev/null
+++ b/mut/neovim/init.lua
@@ -0,0 +1,46 @@
+_G.package["path"] = (vim.fn.stdpath("cache") .. "/hotpot/hotpot.nvim/lua/?/init.lua;" .. package.path)
+local function build_init()
+ local _let_1_ = require("hotpot.api.make")
+ local build = _let_1_["build"]
+ local allowed_globals
+ do
+ local tbl_17_auto = {}
+ local i_18_auto = #tbl_17_auto
+ for n, _ in pairs(_G) do
+ local val_19_auto = n
+ if (nil ~= val_19_auto) then
+ i_18_auto = (i_18_auto + 1)
+ do end (tbl_17_auto)[i_18_auto] = val_19_auto
+ else
+ end
+ end
+ allowed_globals = tbl_17_auto
+ end
+ local opts = {verbosity = 0, compiler = {modules = {allowedGlobals = allowed_globals}}}
+ local here
+ local function _3_(_241)
+ return _241
+ end
+ here = _3_
+ local config_path = vim.fn.stdpath("config")
+ return build(config_path, opts, (config_path .. "/init.fnl"), here, (config_path .. "/after/ftdetect/.+"), here, (config_path .. "/ftplugin/.+"), here, (config_path .. "/after/ftplugin/.+"), here)
+end
+do
+ local hotpot = require("hotpot")
+ local setup = hotpot.setup
+ local build = hotpot.api.make.build
+ local uv = vim.loop
+ local config_path = vim.fn.stdpath("config")
+ setup({provide_require_fennel = true, compiler = {modules = {correlate = true}, macros = {env = "_COMPILER", compilerEnv = _G, allowedGlobals = false}}})
+ local handle = uv.new_fs_event()
+ local path = vim.fn.expand((config_path .. "/init.fnl"))
+ local function _4_()
+ return vim.schedule(build_init)
+ end
+ uv.fs_event_start(handle, path, {}, _4_)
+ local function _5_()
+ return uv.close(handle)
+ end
+ vim.api.nvim_create_autocmd("VimLeavePre", {callback = _5_})
+end
+return require("conf") \ No newline at end of file
diff --git a/mut/neovim/test.py b/mut/neovim/test.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/mut/neovim/test.py