diff options
| author | Mike Vink <mike1994vink@gmail.com> | 2023-10-06 23:10:55 +0200 |
|---|---|---|
| committer | Mike Vink <mike1994vink@gmail.com> | 2023-10-06 23:10:55 +0200 |
| commit | cfaef26e8718916adcc68fbfb63b15f2389b2cd2 (patch) | |
| tree | 3989af4514d31d0a5cb89e8b96d51210ad7bf152 /mut | |
| parent | 654ec06ab6a885ea851c4cbf68d06a00b41b0e14 (diff) | |
move all the files
Diffstat (limited to 'mut')
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 |
