Compare commits
201
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
237a56fb6c | ||
|
|
86d19db1e9 | ||
|
|
068dd8fe25 | ||
|
|
1b9b98c424 | ||
|
|
fe27e8178e | ||
|
|
3cbe6b31b2 | ||
|
|
bd8cb97548 | ||
|
|
a53f854095 | ||
|
|
889e51f10d | ||
|
|
55a5d7ab01 | ||
|
|
99634aadc1 | ||
|
|
792e2a1940 | ||
|
|
dc03a79f70 | ||
|
|
b360904421 | ||
|
|
621bc28f7a | ||
|
|
5fef8dcf90 | ||
|
|
6b833bd222 | ||
|
|
075f4b2ba4 | ||
|
|
46f57624e6 | ||
|
|
df3399b0d3 | ||
|
|
7267e1ca77 | ||
|
|
7249da8fc3 | ||
|
|
0c3c3aacad | ||
|
|
0b7857eb3f | ||
|
|
832aaef3d8 | ||
|
|
d7858d9579 | ||
|
|
0f3e2c8362 | ||
|
|
a86fefc663 | ||
|
|
5294e72a32 | ||
|
|
07926638d4 | ||
|
|
04c1b1e1f4 | ||
|
|
b4d22b97c0 | ||
|
|
4551dc5a59 | ||
|
|
ca76b46750 | ||
|
|
373655963a | ||
|
|
fae504043e | ||
|
|
bdb8c8b149 | ||
|
|
d76d2f4b3a | ||
|
|
08a2ae52f1 | ||
|
|
718f6b7600 | ||
|
|
18e111b00c | ||
|
|
a2be0e5678 | ||
|
|
b5e18a1b29 | ||
|
|
e0ce0e79fc | ||
|
|
bcc0d4ab14 | ||
|
|
37e77a4c30 | ||
|
|
93b93b30b8 | ||
|
|
49c638cda8 | ||
|
|
efd1ddebd9 | ||
|
|
ea5a2b77d4 | ||
|
|
bd4d579a90 | ||
|
|
0ba29f8d89 | ||
|
|
25dcfc6802 | ||
|
|
a56e04a0aa | ||
|
|
1ec5e0258d | ||
|
|
1caa1be1d2 | ||
|
|
aa71eebf0b | ||
|
|
9987dcacd8 | ||
|
|
58a3512c28 | ||
|
|
7b61fde6e9 | ||
|
|
db267226a8 | ||
|
|
521c1b1c4d | ||
|
|
a94e283e98 | ||
|
|
b26e564672 | ||
|
|
1deb25008f | ||
|
|
9ffe754410 | ||
|
|
d0a4cb0db7 | ||
|
|
46ca53e0c0 | ||
|
|
ddd7f6bf2c | ||
|
|
06e60bda8c | ||
|
|
567d0a1718 | ||
|
|
eec71b5f82 | ||
|
|
4e8c3c6269 | ||
|
|
8badfdb9b8 | ||
|
|
1eb4ee50d8 | ||
|
|
5bf98d5b1d | ||
|
|
90d67c5a4a | ||
|
|
ad9a5072d3 | ||
|
|
c6c51c81ef | ||
|
|
f318cd953f | ||
|
|
f75adf42ae | ||
|
|
192b457c61 | ||
|
|
0d3260dab1 | ||
|
|
e8f6eeb8fb | ||
|
|
3f420bf740 | ||
|
|
30effbb474 | ||
|
|
cbda5efd3c | ||
|
|
baf24a5198 | ||
|
|
69a3dfed30 | ||
|
|
b650051b81 | ||
|
|
a0b6b93831 | ||
|
|
e4a76e28e9 | ||
|
|
a6a9b44784 | ||
|
|
535b6dc8f9 | ||
|
|
99b90050ae | ||
|
|
3e40b07e76 | ||
|
|
f849865294 | ||
|
|
b4ee1e28ef | ||
|
|
2e3f837cbb | ||
|
|
54fee7544b | ||
|
|
1e121a3ece | ||
|
|
d1bbe70964 | ||
|
|
4bc636f494 | ||
|
|
340d9b725a | ||
|
|
80ced6b8f0 | ||
|
|
54494ca8ac | ||
|
|
40b2710bad | ||
|
|
cc7c6227d0 | ||
|
|
93a8c07a5a | ||
|
|
dfa080ebb4 | ||
|
|
94fdec8f41 | ||
|
|
ddf6a180cd | ||
|
|
e638cd74ae | ||
|
|
72022f3940 | ||
|
|
ff607b428e | ||
|
|
0e8cfb9670 | ||
|
|
4d2082994c | ||
|
|
2ad1035ddd | ||
|
|
2a4453ac35 | ||
|
|
ac59b7b305 | ||
|
|
f58a2ac4d3 | ||
|
|
9927dc903e | ||
|
|
5409a9140f | ||
|
|
6f929ee958 | ||
|
|
4fe6c591f2 | ||
|
|
39fd88d207 | ||
|
|
9cedb773a6 | ||
|
|
a2a5666d75 | ||
|
|
b47a893e4b | ||
|
|
fb1eea31ae | ||
|
|
372ebf45a1 | ||
|
|
7134b55487 | ||
|
|
cb5e2ced19 | ||
|
|
7cc0ece887 | ||
|
|
874db62c5f | ||
|
|
b6c656ce94 | ||
|
|
3381b9e54d | ||
|
|
481bf28d44 | ||
|
|
ca2f0e18b4 | ||
|
|
d7c60e2f7b | ||
|
|
8f2cbb62aa | ||
|
|
eb6633fc7e | ||
|
|
1ea4bcc0e4 | ||
|
|
bf7621b151 | ||
|
|
46d487fe32 | ||
|
|
7d31673399 | ||
|
|
13d19cb8fc | ||
|
|
ff49aba967 | ||
|
|
ec7c0acadc | ||
|
|
0ec2d1f6ce | ||
|
|
54db5b59be | ||
|
|
388ec2ef7f | ||
|
|
e6444f9f86 | ||
|
|
91318a32ad | ||
|
|
2df4cc4c30 | ||
|
|
095da7e302 | ||
|
|
2dda647ba6 | ||
|
|
d82f92d52c | ||
|
|
6b91a5053b | ||
|
|
f9890fb2bd | ||
|
|
d2c73a5b48 | ||
|
|
5f8d9c1047 | ||
|
|
a6d895dedf | ||
|
|
cde4f66571 | ||
|
|
233378d20c | ||
|
|
7217ce8a41 | ||
|
|
6d8f3594d7 | ||
|
|
48111eecbd | ||
|
|
cced83f09b | ||
|
|
c20eeab2cc | ||
|
|
bb1c607a29 | ||
|
|
6dc3dc7b2d | ||
|
|
ca009bc794 | ||
|
|
72d1fbcd16 | ||
|
|
0a75d65f01 | ||
|
|
8fc175077c | ||
|
|
dd60653474 | ||
|
|
8382c423f0 | ||
|
|
a26151086d | ||
|
|
cd8aaae817 | ||
|
|
b434313676 | ||
|
|
8b79f58be4 | ||
|
|
caa3d4a286 | ||
|
|
6d43be3029 | ||
|
|
ba6d9aeefd | ||
|
|
fdcb5de550 | ||
|
|
e4421bb2f0 | ||
|
|
27296ea69f | ||
|
|
0d854ac137 | ||
|
|
a7101ebab8 | ||
|
|
c9f242178b | ||
|
|
7c765d0cf0 | ||
|
|
0d9eafcaab | ||
|
|
2a8051c68b | ||
|
|
60b126a4d1 | ||
|
|
85c649acab | ||
|
|
a7d521917a | ||
|
|
506a85843d | ||
|
|
a31646fcd5 | ||
|
|
f5679802d5 | ||
|
|
950231154b |
@@ -1,7 +1,16 @@
|
||||
existing
|
||||
minimal
|
||||
install_local.sh
|
||||
bin/dotfiles-install
|
||||
config/dejima
|
||||
config/i3/config.de
|
||||
config/i3/config.local
|
||||
config/gtk-3.0/bookmarks
|
||||
config/xfce4/xfconf/xfce-perchannel-xml
|
||||
config/xfce4/terminal
|
||||
config/themes
|
||||
config/icons
|
||||
config/VSCodium
|
||||
dependencies/dotfiles-local
|
||||
packages/*.local
|
||||
.claude
|
||||
|
||||
@@ -16,3 +16,12 @@
|
||||
[submodule "dependencies/gruvbox"]
|
||||
path = dependencies/gruvbox
|
||||
url = https://github.com/morhetz/gruvbox
|
||||
[submodule "config/tmux/plugins/tpm"]
|
||||
path = config/tmux/plugins/tpm
|
||||
url = https://github.com/tmux-plugins/tpm
|
||||
[submodule "dependencies/fzf"]
|
||||
path = dependencies/fzf
|
||||
url = https://github.com/junegunn/fzf.git
|
||||
[submodule "config/tmux/plugins/tmux-fzf"]
|
||||
path = config/tmux/plugins/tmux-fzf
|
||||
url = https://github.com/sainnhe/tmux-fzf
|
||||
|
||||
Executable
+64
@@ -0,0 +1,64 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# Update all locally existing PGP keys in pacman's gnupg keyring, that are
|
||||
# relevant for Arch Linux packaging using the distribution's Web Key Directory
|
||||
# (WKD).
|
||||
# This ensures, that new signatures on already existing keys are fetched before
|
||||
# a new version of archlinux-keyring is installed. Fetching signatures early
|
||||
# prevents marginal trust issues with packages that are signed by keys which
|
||||
# only gain full trust when updating to a new version of archlinux-keyring in
|
||||
# that same system upgrade action.
|
||||
|
||||
set -eu
|
||||
|
||||
readonly main_key_domain_match="@master-key.archlinux.org$"
|
||||
readonly packager_domain_match="@archlinux.org$"
|
||||
readonly homedir="$(pacman-conf GPGDir)"
|
||||
|
||||
domain_match=""
|
||||
uid=""
|
||||
gpg_locate_external=(
|
||||
# force update a key using WKD
|
||||
gpg
|
||||
--homedir
|
||||
"$homedir"
|
||||
--quiet
|
||||
--no-permission-warning
|
||||
--auto-key-locate
|
||||
"clear,nodefault,wkd"
|
||||
--locate-external-keys
|
||||
)
|
||||
# a list of <fingerprint> <mbox> tuples of all keys in the keyring
|
||||
# e.g.:
|
||||
# C7E7849466FE2358343588377258734B41C31549 dvzrv@archlinux.org
|
||||
# 8FC15A064950A99DD1BD14DD39E4B877E62EB915 svenstaro@gmail.com
|
||||
fingerprint_mboxes="$(
|
||||
gpg --homedir "$homedir" --no-permission-warning --list-keys --list-options show-only-fpr-mbox
|
||||
)"
|
||||
|
||||
# a list of <fingerprints> of all revoked keys and keys that have no valid main
|
||||
# key signatures
|
||||
old_fingerprints="$(
|
||||
gpg --homedir "$homedir" --no-permission-warning --list-keys --with-colons |
|
||||
awk -F: '$1 == "pub" && $2 ~ /-|q|r/ { getline; print $10 }'
|
||||
)"
|
||||
|
||||
if (( EUID != 0 )); then
|
||||
printf "This script must be run as root.\n" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# first update the main signing keys, then the packager keys
|
||||
for domain_match in "$main_key_domain_match" "$packager_domain_match"; do
|
||||
while read -ra fpr_email; do
|
||||
if [[ ${fpr_email[1]} =~ $domain_match && ! "$old_fingerprints" =~ ${fpr_email[0]} ]]; then
|
||||
printf "Refreshing key %s with UID %s...\n" "${fpr_email[0]}" "${fpr_email[1]}"
|
||||
"${gpg_locate_external[@]}" "${fpr_email[1]}"
|
||||
else
|
||||
printf "Skipping key %s with UID %s...\n" "${fpr_email[0]}" "${fpr_email[1]}"
|
||||
fi
|
||||
done <<< "$fingerprint_mboxes"
|
||||
done
|
||||
|
||||
Executable
+45
@@ -0,0 +1,45 @@
|
||||
#!/bin/sh
|
||||
# Copy stdin to the system clipboard, regardless of platform or how deep in
|
||||
# ssh/tmux this shell is: prefer a local clipboard tool for the current
|
||||
# display server, and fall back to a single plain OSC 52 write when no local
|
||||
# tool is available (e.g. a headless remote host). Any tmux hops in between
|
||||
# here and the real terminal relay that onward themselves, recursively, via
|
||||
# the pane-set-clipboard hook in tmux.conf -- this doesn't need to know or
|
||||
# guess how many hops there are.
|
||||
if command -v pbcopy >/dev/null 2>&1; then
|
||||
exec pbcopy
|
||||
elif [ -n "$WAYLAND_DISPLAY" ] && command -v wl-copy >/dev/null 2>&1; then
|
||||
# wl-copy/xclip both hold the selection by staying alive as a background
|
||||
# process (X11/Wayland selections have no central store -- the owner has
|
||||
# to serve paste requests live). setsid -f detaches that process from
|
||||
# our session so tmux's copy-pipe job cleanup can't kill it right after.
|
||||
setsid -f wl-copy
|
||||
elif [ -n "$DISPLAY" ] && command -v xclip >/dev/null 2>&1; then
|
||||
setsid -f xclip -selection clipboard
|
||||
else
|
||||
data=$(base64 | tr -d '\n')
|
||||
# /dev/tty needs this process's own session to have a controlling
|
||||
# terminal, but a job spawned by nvim's clipboard provider doesn't get
|
||||
# one (nvim's job-spawning doesn't establish a ctty for children). Nvim
|
||||
# itself also isn't a single process: the one actually spawning jobs is
|
||||
# a `nvim --embed` core process with no tty of its own (shown as `?` in
|
||||
# ps) -- the real terminal belongs to a separate parent UI process. Walk
|
||||
# up the process tree past any tty-less ancestors to find it.
|
||||
real_tty=""
|
||||
pid="$PPID"
|
||||
i=0
|
||||
while [ "$i" -lt 10 ] && [ -n "$pid" ] && [ "$pid" != "0" ]; do
|
||||
t=$(ps -o tty= -p "$pid" 2>/dev/null | tr -d ' ')
|
||||
if [ -n "$t" ] && [ "$t" != "?" ]; then
|
||||
real_tty="/dev/$t"
|
||||
break
|
||||
fi
|
||||
pid=$(ps -o ppid= -p "$pid" 2>/dev/null | tr -d ' ')
|
||||
i=$((i + 1))
|
||||
done
|
||||
if [ -n "$real_tty" ] && [ -w "$real_tty" ]; then
|
||||
printf '\033]52;c;%s\a' "$data" > "$real_tty"
|
||||
else
|
||||
printf '\033]52;c;%s\a' "$data" > /dev/tty
|
||||
fi
|
||||
fi
|
||||
Executable
+5
@@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
docker compose pull
|
||||
docker compose down
|
||||
docker compose up -d
|
||||
Executable
+4
@@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
|
||||
docker compose down
|
||||
docker compose up -d
|
||||
Executable
+13
@@ -0,0 +1,13 @@
|
||||
#!/bin/bash
|
||||
|
||||
find . -type f -name "docker-compose.y*ml" -exec dirname {} \; | while read dir
|
||||
do
|
||||
if [[ "$dir" != *"DEPRECATED"* ]] && [[ "$dir" != *"MIGRATED"* ]] ; then
|
||||
pushd "$dir"
|
||||
docker compose down
|
||||
docker compose pull
|
||||
docker compose up -d
|
||||
popd
|
||||
fi
|
||||
done
|
||||
|
||||
Executable
+255
@@ -0,0 +1,255 @@
|
||||
#!/bin/bash
|
||||
# Read and write Gitea issues from a shell - the issue-side counterpart to
|
||||
# gitea-pr, and deliberately its twin rather than its sibling: both are
|
||||
# copied into the sandbox image as single self-contained files, and gitea-pr
|
||||
# also lives in a dotfiles checkout, so a shared library would be a third
|
||||
# thing to keep in step across three places. The duplicated config/token/curl
|
||||
# preamble is pinned in both files by test/static.bats instead.
|
||||
set -euo pipefail
|
||||
|
||||
GITEA_TOKEN_FILE="${GITEA_TOKEN_FILE:-$HOME/.config/gitea/token}"
|
||||
|
||||
function usage() {
|
||||
echo "Usage: gitea-issue list [--state open|closed|all] [--limit N]"
|
||||
echo " gitea-issue view NUMBER"
|
||||
echo " gitea-issue create --title TITLE [--body BODY | --body-file FILE]"
|
||||
echo " gitea-issue comment NUMBER (--body BODY | --body-file FILE)"
|
||||
echo " gitea-issue close NUMBER"
|
||||
echo " gitea-issue reopen NUMBER"
|
||||
echo ""
|
||||
echo "--body-file reads the body from FILE, or from stdin when FILE is '-'."
|
||||
echo "Prefer it over --body for anything with quotes, backticks or newlines."
|
||||
echo ""
|
||||
echo "Requires GITEA_SSH_HOST and GITEA_API set in the environment (e.g. in" \
|
||||
"your shell profile), and a token at $GITEA_TOKEN_FILE (or GITEA_TOKEN" \
|
||||
"set for this invocation only)."
|
||||
}
|
||||
|
||||
function require_config() {
|
||||
if [ -z "${GITEA_SSH_HOST:-}" ]; then
|
||||
echo "GITEA_SSH_HOST is not set. Add 'export GITEA_SSH_HOST=<gitea ssh hostname>'" \
|
||||
"(e.g. gitea.example.com) to ~/.profile.local" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ -z "${GITEA_API:-}" ]; then
|
||||
echo "GITEA_API is not set. Add 'export GITEA_API=https://<gitea host>/api/v1'" \
|
||||
"(e.g. https://gitea.example.com/api/v1) to ~/.profile.local" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
function require_token() {
|
||||
if [ -z "${GITEA_TOKEN:-}" ] && [ -f "$GITEA_TOKEN_FILE" ]; then
|
||||
GITEA_TOKEN=$(<"$GITEA_TOKEN_FILE")
|
||||
fi
|
||||
if [ -z "${GITEA_TOKEN:-}" ]; then
|
||||
echo "No Gitea token found. Generate one in the Gitea web UI" \
|
||||
"(Settings > Applications, scopes write:repository + write:issue)" \
|
||||
"and save it to $GITEA_TOKEN_FILE (chmod 600), or set GITEA_TOKEN" \
|
||||
"in the environment for this invocation only." >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Feeds the auth header to curl as a config on stdin rather than as an
|
||||
# argument. Command lines are world-readable through /proc, so `-H
|
||||
# "Authorization: token $GITEA_TOKEN"` exposes the token to every other
|
||||
# process on the host for as long as the request runs - and to anything that
|
||||
# scrapes `ps` output, including the agents this repo exists to sandbox.
|
||||
# printf is a bash builtin, so the token never lands in another argv.
|
||||
function gitea_api() {
|
||||
printf 'header = "Authorization: token %s"\n' "$GITEA_TOKEN" |
|
||||
curl -sS -w '\n%{http_code}' -K - "$@"
|
||||
}
|
||||
|
||||
# Splits gitea_api's combined output into the globals `json` and `http_code`
|
||||
# and fails with the body on any non-2xx. Every call site did this by hand in
|
||||
# gitea-pr; there are six of them here, and six hand-rolled copies is where
|
||||
# one of them quietly stops checking.
|
||||
function api_or_die() {
|
||||
local what="$1"; shift
|
||||
local response
|
||||
response=$(gitea_api "$@")
|
||||
http_code=$(echo "$response" | tail -1)
|
||||
json=$(echo "$response" | sed '$d')
|
||||
if [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then
|
||||
echo "Failed to $what (HTTP $http_code):" >&2
|
||||
echo "$json" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Reads a body from a file, or from stdin for '-'. The point is to keep prose
|
||||
# out of argv: a body composed on a command line has to survive shell quoting,
|
||||
# and the things that break it - an apostrophe, a backtick, a $ - are exactly
|
||||
# what English and code fences are made of. A file (or a heredoc into '-') has
|
||||
# no such layer.
|
||||
function read_body_file() {
|
||||
local file="$1"
|
||||
if [ "$file" = "-" ]; then
|
||||
cat
|
||||
return
|
||||
fi
|
||||
if [ ! -f "$file" ]; then
|
||||
echo "No such body file: $file" >&2
|
||||
exit 1
|
||||
fi
|
||||
cat "$file"
|
||||
}
|
||||
|
||||
function gitea_owner_repo() {
|
||||
local remote_url host owner_repo
|
||||
remote_url=$(git remote get-url origin 2>/dev/null) || {
|
||||
echo "No 'origin' remote found in this repository" >&2
|
||||
exit 1
|
||||
}
|
||||
host=$(echo "$remote_url" | sed -E 's#^[^@]+@([^:]+):.*#\1#')
|
||||
if [ "$host" != "$GITEA_SSH_HOST" ]; then
|
||||
echo "origin remote ($remote_url) is not on $GITEA_SSH_HOST; gitea-issue only supports this host" >&2
|
||||
exit 1
|
||||
fi
|
||||
owner_repo=$(echo "$remote_url" | sed -E 's#^[^@]+@[^:]+:##; s#\.git$##')
|
||||
echo "$owner_repo"
|
||||
}
|
||||
|
||||
function require_number() {
|
||||
if ! [[ "${1:-}" =~ ^[0-9]+$ ]]; then
|
||||
echo "Expected an issue number, got '${1:-}'" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Sets `body` from --body/--body-file, rejecting both. Shared by create and
|
||||
# comment so the two cannot drift into disagreeing about which one wins.
|
||||
function parse_body_args() {
|
||||
body=""
|
||||
local body_file=""
|
||||
parsed_title=""
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "$1" in
|
||||
--title) parsed_title="$2"; shift 2 ;;
|
||||
--body) body="$2"; shift 2 ;;
|
||||
--body-file) body_file="$2"; shift 2 ;;
|
||||
*) echo "Unknown option: $1" >&2; usage; exit 1 ;;
|
||||
esac
|
||||
done
|
||||
# Rejected rather than ranked: silently preferring one would make a caller
|
||||
# that passed both ship a body it didn't mean to.
|
||||
if [ -n "$body" ] && [ -n "$body_file" ]; then
|
||||
echo "Pass --body or --body-file, not both" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ -n "$body_file" ]; then
|
||||
body="$(read_body_file "$body_file")"
|
||||
fi
|
||||
}
|
||||
|
||||
if [ "$#" -lt 1 ]; then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
subcommand="$1"
|
||||
shift
|
||||
|
||||
case "$subcommand" in
|
||||
list|view|create|comment|close|reopen)
|
||||
require_config
|
||||
require_token
|
||||
owner_repo=$(gitea_owner_repo)
|
||||
owner="${owner_repo%%/*}"
|
||||
repo="${owner_repo##*/}"
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
issues_api="${GITEA_API}/repos/${owner}/${repo}/issues"
|
||||
|
||||
case "$subcommand" in
|
||||
list)
|
||||
state="open"
|
||||
limit="30"
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "$1" in
|
||||
--state) state="$2"; shift 2 ;;
|
||||
--limit) limit="$2"; shift 2 ;;
|
||||
*) echo "Unknown option: $1" >&2; usage; exit 1 ;;
|
||||
esac
|
||||
done
|
||||
case "$state" in
|
||||
open|closed|all) ;;
|
||||
*) echo "--state must be open, closed or all" >&2; exit 1 ;;
|
||||
esac
|
||||
if ! [[ "$limit" =~ ^[0-9]+$ ]]; then
|
||||
echo "--limit must be a number" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# type=issues is load-bearing: Gitea's issues endpoint returns pull
|
||||
# requests too, since a PR *is* an issue with a branch attached.
|
||||
# Without it every open PR shows up here as an issue, which reads as
|
||||
# a work list that is quietly twice as long as the real one.
|
||||
api_or_die "list issues" \
|
||||
"${issues_api}?state=${state}&type=issues&limit=${limit}"
|
||||
echo "$json" | jq -r '.[] | "#\(.number)\t[\(.state)]\t\(.title)\t(\(.comments) comments)"'
|
||||
;;
|
||||
view)
|
||||
require_number "${1:-}"
|
||||
number="$1"
|
||||
|
||||
api_or_die "fetch issue #${number}" "${issues_api}/${number}"
|
||||
echo "$json" | jq -r '"#\(.number) [\(.state)] \(.title)\n[\(.user.login) @ \(.created_at)]\n\(.body // "(no description)")\n"'
|
||||
|
||||
echo "=== Comments ==="
|
||||
api_or_die "fetch comments for issue #${number}" "${issues_api}/${number}/comments"
|
||||
echo "$json" | jq -r '.[] | "[\(.user.login) @ \(.created_at)]\n\(.body)\n"'
|
||||
;;
|
||||
create)
|
||||
parse_body_args "$@"
|
||||
if [ -z "$parsed_title" ]; then
|
||||
echo "gitea-issue create requires --title" >&2
|
||||
exit 1
|
||||
fi
|
||||
body="**Filed by LLM agent**
|
||||
|
||||
${body}"
|
||||
|
||||
api_or_die "create issue" -X POST "$issues_api" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$(jq -n --arg title "$parsed_title" --arg body "$body" \
|
||||
'{title: $title, body: $body}')"
|
||||
echo "$json" | jq -r '.html_url'
|
||||
;;
|
||||
comment)
|
||||
require_number "${1:-}"
|
||||
number="$1"
|
||||
shift
|
||||
parse_body_args "$@"
|
||||
if [ -z "$body" ]; then
|
||||
echo "gitea-issue comment requires --body or --body-file" >&2
|
||||
exit 1
|
||||
fi
|
||||
body="**Comment by LLM agent**
|
||||
|
||||
${body}"
|
||||
|
||||
api_or_die "comment on issue #${number}" -X POST "${issues_api}/${number}/comments" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$(jq -n --arg body "$body" '{body: $body}')"
|
||||
echo "$json" | jq -r '.html_url'
|
||||
;;
|
||||
close|reopen)
|
||||
require_number "${1:-}"
|
||||
number="$1"
|
||||
new_state="closed"
|
||||
[ "$subcommand" = "reopen" ] && new_state="open"
|
||||
|
||||
api_or_die "${subcommand} issue #${number}" -X PATCH "${issues_api}/${number}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$(jq -n --arg state "$new_state" '{state: $state}')"
|
||||
echo "$json" | jq -r '"#\(.number) is now \(.state): \(.html_url)"'
|
||||
;;
|
||||
esac
|
||||
Executable
+246
@@ -0,0 +1,246 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
GITEA_TOKEN_FILE="${GITEA_TOKEN_FILE:-$HOME/.config/gitea/token}"
|
||||
|
||||
function usage() {
|
||||
echo "Usage: gitea-pr create [--title TITLE] [--body BODY | --body-file FILE] [--base BRANCH]"
|
||||
echo " gitea-pr comments PR_NUMBER"
|
||||
echo " gitea-pr merge PR_NUMBER"
|
||||
echo ""
|
||||
echo "--body-file reads the body from FILE, or from stdin when FILE is '-'."
|
||||
echo "Prefer it over --body for anything with quotes, backticks or newlines."
|
||||
echo ""
|
||||
echo "Requires GITEA_SSH_HOST and GITEA_API set in the environment (e.g. in" \
|
||||
"your shell profile), and a token at $GITEA_TOKEN_FILE (or GITEA_TOKEN" \
|
||||
"set for this invocation only)."
|
||||
}
|
||||
|
||||
function require_config() {
|
||||
if [ -z "${GITEA_SSH_HOST:-}" ]; then
|
||||
echo "GITEA_SSH_HOST is not set. Add 'export GITEA_SSH_HOST=<gitea ssh hostname>'" \
|
||||
"(e.g. gitea.example.com) to ~/.profile.local" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ -z "${GITEA_API:-}" ]; then
|
||||
echo "GITEA_API is not set. Add 'export GITEA_API=https://<gitea host>/api/v1'" \
|
||||
"(e.g. https://gitea.example.com/api/v1) to ~/.profile.local" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
function require_token() {
|
||||
if [ -z "${GITEA_TOKEN:-}" ] && [ -f "$GITEA_TOKEN_FILE" ]; then
|
||||
GITEA_TOKEN=$(<"$GITEA_TOKEN_FILE")
|
||||
fi
|
||||
if [ -z "${GITEA_TOKEN:-}" ]; then
|
||||
echo "No Gitea token found. Generate one in the Gitea web UI" \
|
||||
"(Settings > Applications, scopes write:repository + write:issue)" \
|
||||
"and save it to $GITEA_TOKEN_FILE (chmod 600), or set GITEA_TOKEN" \
|
||||
"in the environment for this invocation only." >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Feeds the auth header to curl as a config on stdin rather than as an
|
||||
# argument. Command lines are world-readable through /proc, so `-H
|
||||
# "Authorization: token $GITEA_TOKEN"` exposes the token to every other
|
||||
# process on the host for as long as the request runs - and to anything that
|
||||
# scrapes `ps` output, including the agents this repo exists to sandbox.
|
||||
# printf is a bash builtin, so the token never lands in another argv.
|
||||
function gitea_api() {
|
||||
printf 'header = "Authorization: token %s"\n' "$GITEA_TOKEN" |
|
||||
curl -sS -w '\n%{http_code}' -K - "$@"
|
||||
}
|
||||
|
||||
# Reads a body from a file, or from stdin for '-'. The point is to keep prose
|
||||
# out of argv: a body composed on a command line has to survive shell quoting,
|
||||
# and the things that break it - an apostrophe, a backtick, a $ - are exactly
|
||||
# what English and code fences are made of. A file (or a heredoc into '-') has
|
||||
# no such layer.
|
||||
function read_body_file() {
|
||||
local file="$1"
|
||||
if [ "$file" = "-" ]; then
|
||||
cat
|
||||
return
|
||||
fi
|
||||
if [ ! -f "$file" ]; then
|
||||
echo "No such body file: $file" >&2
|
||||
exit 1
|
||||
fi
|
||||
cat "$file"
|
||||
}
|
||||
|
||||
function gitea_owner_repo() {
|
||||
local remote_url host owner_repo
|
||||
remote_url=$(git remote get-url origin 2>/dev/null) || {
|
||||
echo "No 'origin' remote found in this repository" >&2
|
||||
exit 1
|
||||
}
|
||||
host=$(echo "$remote_url" | sed -E 's#^[^@]+@([^:]+):.*#\1#')
|
||||
if [ "$host" != "$GITEA_SSH_HOST" ]; then
|
||||
echo "origin remote ($remote_url) is not on $GITEA_SSH_HOST; gitea-pr only supports this host" >&2
|
||||
exit 1
|
||||
fi
|
||||
owner_repo=$(echo "$remote_url" | sed -E 's#^[^@]+@[^:]+:##; s#\.git$##')
|
||||
echo "$owner_repo"
|
||||
}
|
||||
|
||||
if [ "$#" -lt 1 ]; then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
subcommand="$1"
|
||||
shift
|
||||
|
||||
case "$subcommand" in
|
||||
create|comments|merge)
|
||||
require_config
|
||||
require_token
|
||||
owner_repo=$(gitea_owner_repo)
|
||||
owner="${owner_repo%%/*}"
|
||||
repo="${owner_repo##*/}"
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$subcommand" in
|
||||
create)
|
||||
title=""
|
||||
body=""
|
||||
body_file=""
|
||||
base=""
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "$1" in
|
||||
--title) title="$2"; shift 2 ;;
|
||||
--body) body="$2"; shift 2 ;;
|
||||
--body-file) body_file="$2"; shift 2 ;;
|
||||
--base) base="$2"; shift 2 ;;
|
||||
*) echo "Unknown option: $1" >&2; usage; exit 1 ;;
|
||||
esac
|
||||
done
|
||||
# Rejected rather than ranked: silently preferring one would make a
|
||||
# caller that passed both ship a body it didn't mean to.
|
||||
if [ -n "$body" ] && [ -n "$body_file" ]; then
|
||||
echo "Pass --body or --body-file, not both" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ -n "$body_file" ]; then
|
||||
body="$(read_body_file "$body_file")"
|
||||
fi
|
||||
body="**Summary generated by LLM agent**
|
||||
|
||||
${body}"
|
||||
|
||||
current_branch=$(git rev-parse --abbrev-ref HEAD)
|
||||
if [ "$current_branch" = "HEAD" ]; then
|
||||
echo "Detached HEAD: check out the feature branch before creating a PR" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$base" ]; then
|
||||
base=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's#refs/remotes/origin/##' || true)
|
||||
base="${base:-main}"
|
||||
fi
|
||||
|
||||
response=$(gitea_api "${GITEA_API}/repos/${owner}/${repo}/pulls?state=open")
|
||||
http_code=$(echo "$response" | tail -1)
|
||||
json=$(echo "$response" | sed '$d')
|
||||
if [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then
|
||||
echo "Failed to check for an existing PR (HTTP $http_code):" >&2
|
||||
echo "$json" >&2
|
||||
exit 1
|
||||
fi
|
||||
existing_url=$(echo "$json" | jq -r --arg head "$current_branch" --arg base "$base" \
|
||||
'.[] | select(.head.ref == $head and .base.ref == $base) | .html_url' | head -1)
|
||||
if [ -n "$existing_url" ]; then
|
||||
echo "$existing_url"
|
||||
exit 0
|
||||
fi
|
||||
if [ -z "$title" ]; then
|
||||
title="$current_branch"
|
||||
fi
|
||||
|
||||
response=$(gitea_api -X POST "${GITEA_API}/repos/${owner}/${repo}/pulls" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$(jq -n --arg head "$current_branch" --arg base "$base" --arg title "$title" --arg body "$body" \
|
||||
'{head: $head, base: $base, title: $title, body: $body}')")
|
||||
http_code=$(echo "$response" | tail -1)
|
||||
json=$(echo "$response" | sed '$d')
|
||||
|
||||
if [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then
|
||||
echo "Failed to create PR (HTTP $http_code):" >&2
|
||||
echo "$json" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "$json" | jq -r '.html_url'
|
||||
;;
|
||||
comments)
|
||||
pr_number="${1:-}"
|
||||
if [ -z "$pr_number" ]; then
|
||||
echo "Usage: gitea-pr comments PR_NUMBER" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "=== Issue comments ==="
|
||||
response=$(gitea_api "${GITEA_API}/repos/${owner}/${repo}/issues/${pr_number}/comments")
|
||||
http_code=$(echo "$response" | tail -1)
|
||||
json=$(echo "$response" | sed '$d')
|
||||
if [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then
|
||||
echo "Failed to fetch issue comments (HTTP $http_code):" >&2
|
||||
echo "$json" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "$json" | jq -r '.[] | "[\(.user.login) @ \(.created_at)]\n\(.body)\n"'
|
||||
|
||||
echo "=== Reviews ==="
|
||||
response=$(gitea_api "${GITEA_API}/repos/${owner}/${repo}/pulls/${pr_number}/reviews")
|
||||
http_code=$(echo "$response" | tail -1)
|
||||
reviews_json=$(echo "$response" | sed '$d')
|
||||
if [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then
|
||||
echo "Failed to fetch reviews (HTTP $http_code):" >&2
|
||||
echo "$reviews_json" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "$reviews_json" | jq -r '.[] | select(.body != "") | "[\(.user.login) @ \(.submitted_at) — \(.state)]\n\(.body)\n"'
|
||||
|
||||
echo "=== Inline review comments ==="
|
||||
review_ids=$(echo "$reviews_json" | jq -r '.[] | select(.comments_count > 0) | .id')
|
||||
for review_id in $review_ids; do
|
||||
response=$(gitea_api \
|
||||
"${GITEA_API}/repos/${owner}/${repo}/pulls/${pr_number}/reviews/${review_id}/comments")
|
||||
http_code=$(echo "$response" | tail -1)
|
||||
json=$(echo "$response" | sed '$d')
|
||||
if [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then
|
||||
echo "Failed to fetch comments for review ${review_id} (HTTP $http_code):" >&2
|
||||
echo "$json" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "$json" | jq -r '.[] | "[\(.user.login) @ \(.path):\(.line // "?")]\n\(.body)\n"'
|
||||
done
|
||||
;;
|
||||
merge)
|
||||
pr_number="${1:-}"
|
||||
if [ -z "$pr_number" ]; then
|
||||
echo "Usage: gitea-pr merge PR_NUMBER" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
response=$(gitea_api -X POST "${GITEA_API}/repos/${owner}/${repo}/pulls/${pr_number}/merge" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"Do": "merge"}')
|
||||
http_code=$(echo "$response" | tail -1)
|
||||
json=$(echo "$response" | sed '$d')
|
||||
|
||||
if [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then
|
||||
echo "Failed to merge PR #${pr_number} (HTTP $http_code):" >&2
|
||||
echo "$json" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "Merged PR #${pr_number}"
|
||||
;;
|
||||
esac
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/bin/bash
|
||||
function usage() {
|
||||
echo "Usage: postgres-docker-backup container_name db_user dump_file"
|
||||
}
|
||||
|
||||
if [[ ! "$#" == 3 ]]; then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
container_name="$1"
|
||||
db_user="$2"
|
||||
dump_file="$3"
|
||||
if [ -z "$container_name" ] || [ -z "$db_user" ] || [ -z "$dump_file" ]; then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
docker exec "$container_name" '/bin/sh' -c "pg_dumpall -U $db_user" > $dump_file
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/bin/bash
|
||||
|
||||
function usage() {
|
||||
echo "Usage: postgres-docker-restore container_name db_user"
|
||||
}
|
||||
|
||||
if [[ ! "$#" == 2 ]]; then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
container_name="$1"
|
||||
db_user="$2"
|
||||
if [ -z "$container_name" ] || [ -z "$db_user" ]; then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
docker exec -it "$container_name" '/bin/sh' -c "psql -U $db_user"
|
||||
Executable
+20
@@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
|
||||
function usage() {
|
||||
echo "Usage: postgres-docker-restore container_name db_user dump_file"
|
||||
echo " Note that dump_file is relative to docker filesystem and must be mounted"
|
||||
}
|
||||
|
||||
if [[ ! "$#" == 3 ]]; then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
container_name="$1"
|
||||
db_user="$2"
|
||||
dump_file="$3"
|
||||
if [ -z "$container_name" ] || [ -z "$db_user" ] || [ -z "$dump_file" ]; then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
docker exec -it "$container_name" '/bin/sh' -c "psql -U $db_user < $dump_file"
|
||||
Executable
+8
@@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
# Read clipboard content on stdin (e.g. from `tmux save-buffer -`) and write
|
||||
# it as a raw OSC 52 escape sequence directly to the given tty device path.
|
||||
# Intended to be called from tmux's pane-set-clipboard hook as:
|
||||
# tmux save-buffer - | tmux-clipboard-relay "#{client_tty}"
|
||||
tty_path="$1"
|
||||
data=$(base64 | tr -d '\n')
|
||||
printf '\033]52;c;%s\a' "$data" > "$tty_path"
|
||||
Executable
+77
@@ -0,0 +1,77 @@
|
||||
#!/bin/bash
|
||||
# TODO: Dotfiles may be in a different place
|
||||
if [ ! -f "$HOME/.dotfiles-config" ]; then
|
||||
echo "$HOME/.dotfiles-config not found, please run dotfiles/install.sh to create it"
|
||||
exit 1
|
||||
fi
|
||||
source "$HOME/.dotfiles-config"
|
||||
source "$DOTFILES_DIR/functions.sh"
|
||||
|
||||
# XAUTHORITY file may be in /tmp or it may be ~/.XAUTHORITY
|
||||
if [ -f "$HOME/.Xauthority" ]; then
|
||||
export XAUTHORITY="$HOME/.Xauthority"
|
||||
else
|
||||
auth_path="$(find /tmp -maxdepth 1 -name "xauth_*")"
|
||||
if [ ! -z "$auth_path" ]; then
|
||||
export XAUTHORITY="$auth_path"
|
||||
else
|
||||
echo "No Xauthority file found. Exiting"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
wallpapers_path="$HOME/wallpapers"
|
||||
wallpapers_vertical_path="$HOME/wallpapers-vertical"
|
||||
|
||||
if [ ! -d "$wallpapers_path" ]; then
|
||||
echo "ERROR: Wallpaper directory not found!"
|
||||
echo "Please create wallpapers directory in $wallpapers_path"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if program_installed xrandr; then
|
||||
display_count="$(xrandr | grep ' connected ' | wc -l)"
|
||||
display_order="$(xrandr --listmonitors | tail -n +2 | sed 's/[\+\*]//g' | awk '{ print $2}')"
|
||||
# Build feh command
|
||||
feh_args=("--bg-fill")
|
||||
for i in $(seq 1 "$display_count"); do
|
||||
display_name="$(echo "$display_order" | sed "${i}q;d")"
|
||||
# Get information about the current display, need verbose to always return rotation
|
||||
# and remove 'primary' for consistent column placement
|
||||
display_info="$(xrandr --query --verbose | grep "$display_name" | sed 's/primary //')"
|
||||
# Get the selected resolution for the display
|
||||
resolution="$(echo "$display_info" | awk '{ print $3 }' | sed 's/\+.*//')"
|
||||
# Get the rotation for each display
|
||||
rotation="$(echo "$display_info" | awk '{ print $5 }')"
|
||||
path="$wallpapers_path"
|
||||
resolution_segment=""
|
||||
if [ "$rotation" != "normal" ] && [ "$rotation" != "inverted" ]; then
|
||||
if [ ! -d "$wallpapers_vertical_path" ]; then
|
||||
echo "$rotation"
|
||||
echo "ERROR: Vertical display detected, but vertical wallpapers directory not found!"
|
||||
echo "Please create vertical wallpapers directory in $wallpapers_vertical_path"
|
||||
exit 1
|
||||
fi
|
||||
path="$wallpapers_vertical_path"
|
||||
fi
|
||||
# If we have a resolution-specific path for the display, use it
|
||||
if [ -d "$path/1080p" ]; then
|
||||
resolution_segment="/1080p"
|
||||
fi
|
||||
if [ -d "$path/4k" ]; then
|
||||
if [ "$resolution" = "3840x2160" ] || [ "$resolution" = "2160x3840" ]; then
|
||||
resolution_segment="/4k"
|
||||
fi
|
||||
fi
|
||||
display_wallpaper="$(shuf -en1 "$path$resolution_segment"/*)"
|
||||
feh_args+=("$display_wallpaper")
|
||||
done
|
||||
echo "feh ${feh_args[@]}"
|
||||
feh "${feh_args[@]}"
|
||||
else
|
||||
# Default to ~/wallpapers/1080p or ~/wallpapers for first display if no xrandr
|
||||
if [ -d "$path/1080p" ]; then
|
||||
feh --bg-fill "$(shuf -en1 $wallpapers_path/1080p/*)"
|
||||
else
|
||||
feh --bg-fill "$(shuf -en1 $wallpapers_path/*)"
|
||||
fi
|
||||
fi
|
||||
@@ -0,0 +1,59 @@
|
||||
{
|
||||
"workbench.colorTheme": "Gruvbox Dark Medium",
|
||||
"vim.camelCaseMotion.enable": true,
|
||||
"vim.easymotion": true,
|
||||
"vim.enableNeovim": true,
|
||||
"vim.handleKeys": {
|
||||
"<C-a>": false,
|
||||
"<C-d>": true,
|
||||
"<C-f>": false,
|
||||
"<C-s>": false,
|
||||
"<C-z>": false
|
||||
},
|
||||
"vim.insertModeKeyBindingsNonRecursive": [
|
||||
{
|
||||
"before": [",", ","],
|
||||
"after": ["<Esc>"]
|
||||
}
|
||||
],
|
||||
"vim.normalModeKeyBindingsNonRecursive": [
|
||||
{
|
||||
"before": ["<leader>", "d"],
|
||||
"after": ["d", "d"]
|
||||
},
|
||||
{
|
||||
"before": ["<leader>", "d"],
|
||||
"after": ["d", "d"]
|
||||
},
|
||||
{
|
||||
"before": [",", ",", "<Esc>"],
|
||||
"commands": [":nohl"]
|
||||
},
|
||||
{
|
||||
"before": ["<leader>", "q"],
|
||||
"commands": [":bp"]
|
||||
},
|
||||
{
|
||||
"before": ["<leader>", "w"],
|
||||
"commands": [":bn"]
|
||||
},
|
||||
{
|
||||
"before": ["<leader>", "r", "r"],
|
||||
"commands": [":action "]
|
||||
},
|
||||
{
|
||||
"before": ["<leader>", "<leader>", "c"],
|
||||
"commands": [":Blose"],
|
||||
"silent": true
|
||||
}
|
||||
],
|
||||
"vim.leader": ",",
|
||||
// To improve performance
|
||||
"extensions.experimental.affinity": {
|
||||
"vscodevim.vim": 1
|
||||
},
|
||||
"vim.neovimUseConfigFile": true,
|
||||
"editor.fontFamily": "'Source Code Pro', regular",
|
||||
"vim.normalModeKeyBindings": [],
|
||||
"python.venvPath": "~/.pyenv"
|
||||
}
|
||||
@@ -1,6 +1,3 @@
|
||||
import = [
|
||||
"~/.config/alacritty/themes/themes/gruvbox_dark.toml"
|
||||
]
|
||||
|
||||
[font]
|
||||
size = 9.0
|
||||
@@ -20,3 +17,30 @@ style = "Italic"
|
||||
[font.normal]
|
||||
family = "Source Code Pro for Powerline"
|
||||
style = "Regular"
|
||||
|
||||
[general]
|
||||
import = [
|
||||
"~/.config/alacritty/themes/themes/gruvbox_dark.toml"
|
||||
]
|
||||
|
||||
[selection]
|
||||
# X11 always sets PRIMARY (middle-click paste) on text selection; that part
|
||||
# needs no config. CLIPBOARD (Ctrl+V / Ctrl+Shift+V) is a separate buffer
|
||||
# that nothing populates without this, so mirror every selection into it
|
||||
# too. This is handled by Alacritty itself, so it covers anything visible
|
||||
# on screen -- local shell, nested tmux, SSH'd remote shells -- regardless
|
||||
# of whether the app underneath knows how to talk to the clipboard.
|
||||
save_to_clipboard = true
|
||||
|
||||
[keyboard]
|
||||
# Alacritty doesn't implement the CSI-u/Kitty keyboard protocol that lets a
|
||||
# terminal report Shift+Enter as distinct from plain Enter, so it needs an
|
||||
# explicit binding. Sending a raw line feed makes Shift+Enter equivalent to
|
||||
# Ctrl+J, which Claude Code (and most other terminal apps) already treats
|
||||
# as "insert newline" with zero further configuration -- this works
|
||||
# unchanged through any depth of nested tmux, since it's just a literal
|
||||
# byte rather than an escape sequence that needs to be interpreted along
|
||||
# the way.
|
||||
bindings = [
|
||||
{ key = "Return", mods = "Shift", chars = "\n" },
|
||||
]
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
[Desktop Entry]
|
||||
Name=USDB Syncer
|
||||
Comment=Download karaoke songs
|
||||
Exec=usdb_syncer
|
||||
Terminal=false
|
||||
Type=Application
|
||||
Categories=Software;
|
||||
@@ -21,6 +21,13 @@ exec --no-startup-id dex --autostart --environment i3
|
||||
# applications #
|
||||
################
|
||||
|
||||
# set wallpaper
|
||||
exec --no-startup-id sleep 1 && ~/dotfiles/bin/update-wallpaper
|
||||
# exec --no-startup-id sleep 1 && systemctl start update-wallpaper.service
|
||||
|
||||
# start keyring
|
||||
exec --no-startup-id dbus-update-activation-environment --all
|
||||
|
||||
#exec_always --no-startup-id conky -c ~/.config/conky/conkyrc-stats
|
||||
|
||||
#exec --no-startup-id sleep 7 && firefox https://todo.bradina.haus/
|
||||
|
||||
+31
-18
@@ -10,6 +10,8 @@ bar {
|
||||
font pango: Source Code Pro for Powerline 10
|
||||
status_command i3blocks -c ~/.config/i3/i3blocks.conf
|
||||
position bottom
|
||||
output DP-0
|
||||
output DP-2
|
||||
#tray_padding 0
|
||||
|
||||
# When strip_workspace_numbers is set to yes,
|
||||
@@ -37,21 +39,32 @@ bar {
|
||||
# https://gist.github.com/lopspower/03fb1cc0ac9f32ef38f4
|
||||
# #08052be6 --> e6=90%
|
||||
|
||||
# bar {
|
||||
# font pango: Noto Sans Regular 10
|
||||
# status_command i3blocks -c ~/.config/i3/i3blocks-2.conf
|
||||
# i3bar_command i3bar --transparency
|
||||
# output HDMI-0
|
||||
# position bottom
|
||||
#
|
||||
# colors {
|
||||
# separator $purple
|
||||
# background $darkbluetrans
|
||||
# statusline $white
|
||||
# border bg txt indicator
|
||||
# focused_workspace $lighterblue $lighterblue $darkblue $purple
|
||||
# active_workspace $lightdblue $lightdblue $darkblue $purple
|
||||
# inactive_workspace $darkblue $darkblue $lightdblue $purple
|
||||
# urgent_workspace $urgentred $urgentred $white $purple
|
||||
# }
|
||||
#}
|
||||
bar {
|
||||
font pango: Noto Sans Regular 10
|
||||
status_command i3blocks -c ~/.config/i3/i3blocks-2.conf
|
||||
i3bar_command i3bar --transparency
|
||||
output HDMI-0
|
||||
position bottom
|
||||
|
||||
colors {
|
||||
# gruvbox colors
|
||||
background $bg
|
||||
statusline $yellow
|
||||
# workspaces section
|
||||
# border bg txt
|
||||
focused_workspace $aqua $aqua $darkgray
|
||||
inactive_workspace $darkgray $darkgray $yellow
|
||||
active_workspace $darkgray $darkgray $yellow
|
||||
urgent_workspace $red $red $bg
|
||||
}
|
||||
# colors {
|
||||
# separator $purple
|
||||
# background $darkbluetrans
|
||||
# statusline $white
|
||||
# border bg txt indicator
|
||||
# focused_workspace $lighterblue $lighterblue $darkblue $purple
|
||||
# active_workspace $lightdblue $lightdblue $darkblue $purple
|
||||
# inactive_workspace $darkblue $darkblue $lightdblue $purple
|
||||
# urgent_workspace $urgentred $urgentred $white $purple
|
||||
# }
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
alias vim=nvim
|
||||
@@ -0,0 +1,142 @@
|
||||
function program_installed {
|
||||
local return_=0
|
||||
|
||||
type $1 >/dev/null 2>&1 || { local return_=1; }
|
||||
|
||||
return "$return_"
|
||||
}
|
||||
|
||||
function list_processes() {
|
||||
# List all processes matching the given process name string
|
||||
ps aux | grep $(whoami) | grep -i "$1" | grep -v grep
|
||||
}
|
||||
|
||||
function kill_all() {
|
||||
# Kill all processes matching the given process name string
|
||||
if [ ! "$1" ]; then
|
||||
echo "kill_all requires a process name to kill all instances of"
|
||||
return 1
|
||||
fi
|
||||
kill_flag=15
|
||||
if [ "$15" ]; then
|
||||
kill_flag="$15"
|
||||
fi
|
||||
|
||||
count=$(list_processes "$1" | wc -l)
|
||||
|
||||
echo "Killing $count running processes matching $1"
|
||||
kill -"$kill_flag" $(list_processes "$1" | awk '{print $2}')
|
||||
|
||||
count=$(list_processes "$1" | wc -l)
|
||||
if [ $count -gt 0 ]; then
|
||||
echo "$count processes could not be killed"
|
||||
fi
|
||||
}
|
||||
|
||||
function ranger-cd() {
|
||||
# Make shell cd to ranger directory
|
||||
tempfile=$(mktemp)
|
||||
ranger --choosedir="$tempfile" "${@:-$(pwd)}" < $TTY
|
||||
test -f "$tempfile" &&
|
||||
if [ "$(cat -- "$tempfile")" != "$(echo -n `pwd`)" ]; then
|
||||
cd $(cat $tempfile)
|
||||
fi
|
||||
zle reset-prompt
|
||||
printf '\n'
|
||||
rm -f -- "$tempfile"
|
||||
}
|
||||
|
||||
function terminal-clock() {
|
||||
tty-clock -tcb < $TTY
|
||||
zle reset-prompt
|
||||
printf '\n'
|
||||
}
|
||||
|
||||
function check_dotfiles_version {
|
||||
# Check if the version of the dotfiles directory is the latest version
|
||||
# Return 0 if repo is present and the latest version
|
||||
# Return 1 if the repo is not present
|
||||
# Return 2 if the repo is behind the remote
|
||||
# Return 3 if the repo is ahead of the remote
|
||||
# Return 4 if the repo has diverged from the remote
|
||||
# Return 5 if DOTFILES_DIR is not set
|
||||
if [ -z $DOTFILES_DIR ]; then
|
||||
return 5
|
||||
fi
|
||||
|
||||
if [ ! -d $DOTFILES_DIR ]; then
|
||||
return 2
|
||||
fi
|
||||
|
||||
pushd $DOTFILES_DIR > /dev/null
|
||||
|
||||
# TODO: This may be gitbox
|
||||
git fetch origin > /dev/null
|
||||
UPSTREAM=${1:-'@{u}'}
|
||||
LOCAL=$(git rev-parse @)
|
||||
REMOTE=$(git rev-parse "$UPSTREAM")
|
||||
BASE=$(git merge-base @ "$UPSTREAM")
|
||||
|
||||
popd > /dev/null
|
||||
|
||||
if [[ $LOCAL = $REMOTE ]]; then
|
||||
return 0
|
||||
elif [[ $LOCAL = $BASE ]]; then
|
||||
return 2
|
||||
elif [[ $REMOTE = $BASE ]]; then
|
||||
return 3
|
||||
else
|
||||
return 4
|
||||
fi
|
||||
}
|
||||
|
||||
function python_roots {
|
||||
if [ -d $HOME/.local/lib/ ]; then
|
||||
for directory in $(echo $HOME/.local/lib/python*); do
|
||||
echo "$directory"
|
||||
done
|
||||
fi
|
||||
if [ -d $HOME/.local/share/pipx/venvs/powerline-status/lib/ ]; then
|
||||
for directory in $(echo $HOME/.local/share/pipx/venvs/powerline-status/lib/python*); do
|
||||
echo "$directory"
|
||||
done
|
||||
fi
|
||||
if [ -d $HOME/.local/pipx/venvs/powerline-status/lib/ ]; then
|
||||
for directory in $(echo $HOME/.local/pipx/venvs/powerline-status/lib/python*); do
|
||||
echo "$directory"
|
||||
done
|
||||
fi
|
||||
if [ -d /usr/lib/ ]; then
|
||||
for directory in $(echo /usr/lib/python*); do
|
||||
echo "$directory"
|
||||
done
|
||||
fi
|
||||
if [ -d /usr/local/lib/ ]; then
|
||||
# TODO: Make this not print warnings when the directory doesn't exit
|
||||
for directory in $(echo /usr/local/lib/python*); do
|
||||
echo "$directory"
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
function powerline_bash_sources {
|
||||
# To support bash 3.2 on macOS, can't use declare -ag so workaround with capturing output
|
||||
PYTHON_ROOTS=( $(python_roots) )
|
||||
# Powerline plugin from distribution agnostic install directory
|
||||
## Assemble list of possible sources
|
||||
if [[ -a $POWERLINE_ROOT/bindings/bash/powerline.sh ]]; then
|
||||
# Prefer user-set powerline directory
|
||||
echo "$POWERLINE_ROOT/bindings/bash/powerline.sh"
|
||||
fi
|
||||
if [ -d /usr/share/powerline ]; then
|
||||
# Apt installs here
|
||||
echo "/usr/share/powerline/bindings/bash/powerline.sh"
|
||||
fi
|
||||
# If $POWERLINE_ROOT not set or set incorrectly, try default locations
|
||||
for directory in "${PYTHON_ROOTS[@]}"; do
|
||||
if [ -d "$directory" ]; then
|
||||
echo "$directory"/site-packages/powerline/bindings/bash/powerline.sh
|
||||
echo "$directory"/dist-packages/powerline/bindings/bash/powerline.sh
|
||||
fi
|
||||
done
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
if [ -n "$BASH_VERSION" ]; then
|
||||
# include .bashrc if it exists
|
||||
if [ -f "$HOME/.bashrc" ]; then
|
||||
. "$HOME/.bashrc"
|
||||
fi
|
||||
fi
|
||||
@@ -0,0 +1,84 @@
|
||||
#PATHs
|
||||
if [ -d "$HOME/.local/bin" ]; then
|
||||
export PATH="$HOME/.local/bin:$PATH"
|
||||
fi
|
||||
|
||||
if [ -f "$HOME/.bash_functions" ]; then
|
||||
source "$HOME/.bash_functions"
|
||||
fi
|
||||
|
||||
# User profiles
|
||||
source $HOME/.profile
|
||||
# Define $POWERLINE_ROOT
|
||||
if [ -f $HOME/.profile.local ]; then
|
||||
set -a
|
||||
source $HOME/.profile.local
|
||||
set +a
|
||||
fi
|
||||
|
||||
if [ -n "$DOTFILES_DIR" ] && [ -d "$DOTFILES_DIR" ]; then
|
||||
# Gruvbox colors
|
||||
[[ -f "$DOTFILES_DIR/dependencies/gruvbox/gruvbox_256palette.sh" ]] && source "$DOTFILES_DIR/dependencies/gruvbox/gruvbox_256palette.sh"
|
||||
fi
|
||||
|
||||
# Italic support
|
||||
if [ -f $HOME/.xterm-256color-italic.terminfo ]; then
|
||||
tic $HOME/.xterm-256color-italic.terminfo
|
||||
fi
|
||||
if [ -f $HOME/.screen-256color-italic.terminfo ]; then
|
||||
tic $HOME/.screen-256color-italic.terminfo
|
||||
fi
|
||||
|
||||
# Use neovim where available
|
||||
if program_installed neovim; then
|
||||
alias vim='nvim'
|
||||
fi
|
||||
|
||||
# fzf fuzzy finder
|
||||
if program_installed fzf; then
|
||||
# TODO: This is broken when fzf is old, should include a local copy
|
||||
eval "$(fzf --bash)"
|
||||
fi
|
||||
|
||||
# thefuck command correction
|
||||
if program_installed fuck; then
|
||||
eval "$(thefuck --alias)"
|
||||
fi
|
||||
|
||||
# aactivator
|
||||
if program_installed aactivator; then
|
||||
eval "$(aactivator init)"
|
||||
fi
|
||||
|
||||
# Preferred editor for local and remote sessions
|
||||
export EDITOR='vim'
|
||||
|
||||
# Powerline
|
||||
if program_installed powerline; then
|
||||
if [ -n "$POWERLINE_ROOT" ] && \
|
||||
[ -f "$POWERLINE_ROOT" ] && \
|
||||
[ -f "$POWERLINE_ROOT/bindings/bash/powerline.sh" ]; then
|
||||
# Skip lookup if location is known
|
||||
source "$POWERLINE_ROOT/bindings/bash/powerline.sh"
|
||||
else
|
||||
POWERLINE_BASH_SOURCES=( $(powerline_bash_sources) )
|
||||
found=0
|
||||
for file in "${POWERLINE_BASH_SOURCES[@]}"; do
|
||||
if [[ -a $file ]]; then
|
||||
# TODO: Store the POWERLINE_ROOT in .profile.local if found
|
||||
source $file
|
||||
found=1
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [ $found -eq 0 ]; then
|
||||
echo "Powerline binding not found."
|
||||
echo "Please set \$POWERLINE_ROOT in .profile.local"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Local overrides
|
||||
if [ -f $HOME/.bashrc_local ]; then
|
||||
source $HOME/.bashrc_local
|
||||
fi
|
||||
@@ -0,0 +1,39 @@
|
||||
# Global preferences
|
||||
|
||||
## Development Guidelines
|
||||
|
||||
- ALWAYS implement minimal changes to accomplish your task, nothing unecessary
|
||||
- NEVER introduce unecessary complexity or side-effects on other code
|
||||
- NEVER write unecessary comments, only minimal comments to describe functionality which isn't obvious from reading the code
|
||||
- ALWAYS respect the existing style of the repository
|
||||
- ALWAYS implement the best possible solution to a problem you can find
|
||||
- NEVER reinvent the wheel. if there's an established, accepted way to do something which doesn't introduce unecessary complexity, use it
|
||||
- NEVER include co-authorship lines in a git commit
|
||||
- NEVER commit to a git repository except when bootstrapping your own fresh repositories
|
||||
|
||||
|
||||
## Spec documents
|
||||
|
||||
When a skill or workflow (e.g. brainstorming) would write a design spec/plan document
|
||||
to a project-local path like `docs/superpowers/specs/`, write it to `~/specs/` instead,
|
||||
using the same `YYYY-MM-DD-<topic>-design.md` naming convention. Do not commit spec
|
||||
documents into project git repositories unless explicitly asked to.
|
||||
|
||||
## Gitea PR review workflow
|
||||
|
||||
For repos whose `origin` remote is on `gitbox.bradina.localdomain`: when the
|
||||
finishing-a-development-branch skill's "Push and create PR" option is chosen,
|
||||
after pushing, also run `gitea-pr create` (from dotfiles `bin/`) to actually
|
||||
open the PR, and report the printed URL back. Always pass `--title`/`--body`
|
||||
with a real summary of the changes, the reasoning behind them, and what was
|
||||
tested — never placeholder or throwaway text, even for a call made mainly to
|
||||
test other behavior (e.g. testing that a duplicate-PR check short-circuits):
|
||||
if it turns out to actually create a PR, that text ships as the PR
|
||||
description.
|
||||
|
||||
When asked to check or address PR feedback, run `gitea-pr comments <PR#>`,
|
||||
make the requested changes, commit, push, and report back. Repeat for as many
|
||||
rounds as needed. Only check feedback when explicitly asked — do not poll
|
||||
proactively.
|
||||
|
||||
Never run `gitea-pr merge` unless explicitly instructed to merge in that turn.
|
||||
Executable
+30
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env bash
|
||||
# PreToolUse hook: block obviously destructive Bash commands regardless of permission mode.
|
||||
# Exit 2 blocks the tool call and returns stderr to Claude as feedback.
|
||||
|
||||
command=$(jq -r '.tool_input.command // empty')
|
||||
|
||||
deny_patterns=(
|
||||
'rm[[:space:]]+(-[a-zA-Z]*[rR][a-zA-Z]*f|-[a-zA-Z]*f[a-zA-Z]*[rR])[[:space:]]+/($|[[:space:]])'
|
||||
'rm[[:space:]]+(-[a-zA-Z]*[rR][a-zA-Z]*f|-[a-zA-Z]*f[a-zA-Z]*[rR])[[:space:]]+(--no-preserve-root|~($|/)|\*)'
|
||||
':\(\)[[:space:]]*\{[[:space:]]*:.*\|.*:.*&.*\}[[:space:]]*;[[:space:]]*:'
|
||||
'dd[[:space:]].*of=/dev/(sd|nvme|vd|hd)'
|
||||
'mkfs(\.[a-zA-Z0-9]+)?[[:space:]]'
|
||||
'>[[:space:]]*/dev/(sd|nvme|vd|hd)[a-z0-9]*($|[[:space:]])'
|
||||
'chmod[[:space:]]+-R[[:space:]]+[0-7]{3,4}[[:space:]]+/($|[[:space:]])'
|
||||
'chown[[:space:]]+-R[[:space:]].*[[:space:]]+/($|[[:space:]])'
|
||||
'(^|[[:space:]])(shutdown|reboot|poweroff|halt)([[:space:]]|$)'
|
||||
'wipefs[[:space:]]'
|
||||
'shred[[:space:]].*/dev/'
|
||||
'curl[[:space:]].*\|[[:space:]]*(sudo[[:space:]]+)?(sh|bash|zsh)($|[[:space:]])'
|
||||
'wget[[:space:]].*-O-.*\|[[:space:]]*(sudo[[:space:]]+)?(sh|bash|zsh)($|[[:space:]])'
|
||||
)
|
||||
|
||||
for pattern in "${deny_patterns[@]}"; do
|
||||
if [[ "$command" =~ $pattern ]]; then
|
||||
echo "Blocked by local denylist hook (~/.claude/hooks/deny-dangerous-bash.sh): command matches pattern '$pattern'" >&2
|
||||
exit 2
|
||||
fi
|
||||
done
|
||||
|
||||
exit 0
|
||||
Executable
+57
@@ -0,0 +1,57 @@
|
||||
#!/usr/bin/env bash
|
||||
# Claude Code statusLine command: model, dir/branch, context usage, rate limits.
|
||||
# See: https://code.claude.com/docs/en/statusline
|
||||
|
||||
input=$(cat)
|
||||
|
||||
MODEL=$(echo "$input" | jq -r '.model.display_name')
|
||||
DIR=$(echo "$input" | jq -r '.workspace.current_dir')
|
||||
PCT=$(echo "$input" | jq -r '.context_window.used_percentage // 0' | cut -d. -f1)
|
||||
FIVE_H=$(echo "$input" | jq -r '.rate_limits.five_hour.used_percentage // empty')
|
||||
WEEK=$(echo "$input" | jq -r '.rate_limits.seven_day.used_percentage // empty')
|
||||
|
||||
# Claude Code omits rate_limits when ANTHROPIC_BASE_URL isn't the literal
|
||||
# api.anthropic.com host (e.g. the dejima sandbox's credential-injecting
|
||||
# loopback proxy), even though the usage endpoint itself works fine through
|
||||
# it. Fetch it ourselves in that case, cached briefly to avoid a network
|
||||
# round-trip on every render.
|
||||
if [ -z "$FIVE_H" ] && [ -n "${ANTHROPIC_BASE_URL:-}" ] && [ -n "${ANTHROPIC_AUTH_TOKEN:-}" ]; then
|
||||
CACHE="${TMPDIR:-/tmp}/claude-statusline-usage-${UID}.json"
|
||||
if [ ! -s "$CACHE" ] || [ -n "$(find "$CACHE" -mmin +1 2>/dev/null)" ]; then
|
||||
if curl -fsS --max-time 3 "$ANTHROPIC_BASE_URL/api/oauth/usage" \
|
||||
-H "Authorization: Bearer $ANTHROPIC_AUTH_TOKEN" \
|
||||
-H "anthropic-beta: oauth-2025-04-20" \
|
||||
-o "$CACHE.tmp" 2>/dev/null; then
|
||||
mv "$CACHE.tmp" "$CACHE"
|
||||
fi
|
||||
fi
|
||||
FIVE_H=$(jq -r '.five_hour.utilization // empty' "$CACHE" 2>/dev/null)
|
||||
WEEK=$(jq -r '.seven_day.utilization // empty' "$CACHE" 2>/dev/null)
|
||||
fi
|
||||
|
||||
GREEN='\033[32m'; YELLOW='\033[33m'; RED='\033[31m'; RESET='\033[0m'
|
||||
|
||||
if [ "$PCT" -ge 90 ]; then BAR_COLOR="$RED"
|
||||
elif [ "$PCT" -ge 70 ]; then BAR_COLOR="$YELLOW"
|
||||
else BAR_COLOR="$GREEN"; fi
|
||||
|
||||
BAR_WIDTH=10
|
||||
FILLED=$((PCT * BAR_WIDTH / 100))
|
||||
EMPTY=$((BAR_WIDTH - FILLED))
|
||||
BAR=""
|
||||
[ "$FILLED" -gt 0 ] && printf -v FILL "%${FILLED}s" && BAR="${FILL// /▓}"
|
||||
[ "$EMPTY" -gt 0 ] && printf -v PAD "%${EMPTY}s" && BAR="${BAR}${PAD// /░}"
|
||||
|
||||
BRANCH=""
|
||||
git -C "$DIR" rev-parse --git-dir > /dev/null 2>&1 && BRANCH=" | 🌿 $(git -C "$DIR" branch --show-current 2>/dev/null)"
|
||||
|
||||
LIMITS=""
|
||||
[ -n "$FIVE_H" ] && LIMITS="5h: $(printf '%.0f' "$FIVE_H")%"
|
||||
[ -n "$WEEK" ] && LIMITS="${LIMITS:+$LIMITS }7d: $(printf '%.0f' "$WEEK")%"
|
||||
|
||||
echo -e "[$MODEL] 📁 ${DIR##*/}${BRANCH}"
|
||||
if [ -n "$LIMITS" ]; then
|
||||
echo -e "${BAR_COLOR}${BAR}${RESET} ${PCT}% | ${LIMITS}"
|
||||
else
|
||||
echo -e "${BAR_COLOR}${BAR}${RESET} ${PCT}%"
|
||||
fi
|
||||
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"name": "Gruvbox Dark",
|
||||
"base": "dark",
|
||||
"overrides": {
|
||||
"claude": "#d3869b",
|
||||
"text": "#ebdbb2",
|
||||
"inactive": "#665c54",
|
||||
"subtle": "#7c6f64",
|
||||
"muted": "#928374",
|
||||
"success": "#b8bb26",
|
||||
"error": "#fb4934",
|
||||
"warning": "#fabd2f",
|
||||
"link": "#83a598",
|
||||
"highlight": "#fabd2f",
|
||||
"selection": "#504945",
|
||||
"diffAdded": "#b8bb26",
|
||||
"diffRemoved": "#fb4934",
|
||||
"promptBorder": "#504945",
|
||||
"bashBorder": "#504945",
|
||||
"mcpBorder": "#504945",
|
||||
"planMode": "#83a598",
|
||||
"spinner": "#d3869b",
|
||||
"header": "#8ec07c",
|
||||
"separator": "#3c3836",
|
||||
"badge": "#fe8019",
|
||||
"permission": "#fe8019",
|
||||
"suggestion": "#8ec07c",
|
||||
"fastMode": "#fabd2f"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
@define-color borders_breeze #4c4e51;
|
||||
@define-color content_view_bg_breeze #141618;
|
||||
@define-color error_color_backdrop_breeze #da4453;
|
||||
@define-color error_color_breeze #da4453;
|
||||
@define-color error_color_insensitive_backdrop_breeze #55242b;
|
||||
@define-color error_color_insensitive_breeze #55242b;
|
||||
@define-color insensitive_base_color_breeze #131517;
|
||||
@define-color insensitive_base_fg_color_breeze #606263;
|
||||
@define-color insensitive_bg_color_breeze #1f2124;
|
||||
@define-color insensitive_borders_breeze #2d3033;
|
||||
@define-color insensitive_fg_color_breeze #686a6c;
|
||||
@define-color insensitive_selected_bg_color_breeze #1f2124;
|
||||
@define-color insensitive_selected_fg_color_breeze #686a6c;
|
||||
@define-color insensitive_unfocused_bg_color_breeze #1f2124;
|
||||
@define-color insensitive_unfocused_fg_color_breeze #686a6c;
|
||||
@define-color insensitive_unfocused_selected_bg_color_breeze #1f2124;
|
||||
@define-color insensitive_unfocused_selected_fg_color_breeze #686a6c;
|
||||
@define-color link_color_breeze #926ee4;
|
||||
@define-color link_visited_color_breeze #9b59b6;
|
||||
@define-color success_color_backdrop_breeze #27ae60;
|
||||
@define-color success_color_breeze #27ae60;
|
||||
@define-color success_color_insensitive_backdrop_breeze #19482f;
|
||||
@define-color success_color_insensitive_breeze #19482f;
|
||||
@define-color theme_base_color_breeze #141618;
|
||||
@define-color theme_bg_color_breeze #202326;
|
||||
@define-color theme_button_background_backdrop_breeze #292c30;
|
||||
@define-color theme_button_background_backdrop_insensitive_breeze #272a2e;
|
||||
@define-color theme_button_background_insensitive_breeze #272a2e;
|
||||
@define-color theme_button_background_normal_breeze #292c30;
|
||||
@define-color theme_button_decoration_focus_backdrop_breeze #926ee4;
|
||||
@define-color theme_button_decoration_focus_backdrop_insensitive_breeze #4a406a;
|
||||
@define-color theme_button_decoration_focus_breeze #926ee4;
|
||||
@define-color theme_button_decoration_focus_insensitive_breeze #4a406a;
|
||||
@define-color theme_button_decoration_hover_backdrop_breeze #926ee4;
|
||||
@define-color theme_button_decoration_hover_backdrop_insensitive_breeze #4a406a;
|
||||
@define-color theme_button_decoration_hover_breeze #926ee4;
|
||||
@define-color theme_button_decoration_hover_insensitive_breeze #4a406a;
|
||||
@define-color theme_button_foreground_active_backdrop_breeze #fcfcfc;
|
||||
@define-color theme_button_foreground_active_backdrop_insensitive_breeze #686a6c;
|
||||
@define-color theme_button_foreground_active_breeze #ffffff;
|
||||
@define-color theme_button_foreground_active_insensitive_breeze #686a6c;
|
||||
@define-color theme_button_foreground_backdrop_breeze #fcfcfc;
|
||||
@define-color theme_button_foreground_backdrop_insensitive_breeze #6d6f72;
|
||||
@define-color theme_button_foreground_insensitive_breeze #6d6f72;
|
||||
@define-color theme_button_foreground_normal_breeze #fcfcfc;
|
||||
@define-color theme_fg_color_breeze #fcfcfc;
|
||||
@define-color theme_header_background_backdrop_breeze #202326;
|
||||
@define-color theme_header_background_breeze #292c30;
|
||||
@define-color theme_header_background_light_breeze #202326;
|
||||
@define-color theme_header_foreground_backdrop_breeze #fcfcfc;
|
||||
@define-color theme_header_foreground_breeze #fcfcfc;
|
||||
@define-color theme_header_foreground_insensitive_backdrop_breeze #fcfcfc;
|
||||
@define-color theme_header_foreground_insensitive_breeze #fcfcfc;
|
||||
@define-color theme_hovering_selected_bg_color_breeze #926ee4;
|
||||
@define-color theme_selected_bg_color_breeze #6c53a6;
|
||||
@define-color theme_selected_fg_color_breeze #ffffff;
|
||||
@define-color theme_text_color_breeze #fcfcfc;
|
||||
@define-color theme_titlebar_background_backdrop_breeze #202326;
|
||||
@define-color theme_titlebar_background_breeze #292c30;
|
||||
@define-color theme_titlebar_background_light_breeze #202326;
|
||||
@define-color theme_titlebar_foreground_backdrop_breeze #fcfcfc;
|
||||
@define-color theme_titlebar_foreground_breeze #fcfcfc;
|
||||
@define-color theme_titlebar_foreground_insensitive_backdrop_breeze #fcfcfc;
|
||||
@define-color theme_titlebar_foreground_insensitive_breeze #fcfcfc;
|
||||
@define-color theme_unfocused_base_color_breeze #141618;
|
||||
@define-color theme_unfocused_bg_color_breeze #202326;
|
||||
@define-color theme_unfocused_fg_color_breeze #fcfcfc;
|
||||
@define-color theme_unfocused_selected_bg_color_alt_breeze #362c50;
|
||||
@define-color theme_unfocused_selected_bg_color_breeze #362c50;
|
||||
@define-color theme_unfocused_selected_fg_color_breeze #fcfcfc;
|
||||
@define-color theme_unfocused_text_color_breeze #fcfcfc;
|
||||
@define-color theme_unfocused_view_bg_color_breeze #131517;
|
||||
@define-color theme_unfocused_view_text_color_breeze #606263;
|
||||
@define-color theme_view_active_decoration_color_breeze #926ee4;
|
||||
@define-color theme_view_hover_decoration_color_breeze #926ee4;
|
||||
@define-color tooltip_background_breeze #292c30;
|
||||
@define-color tooltip_border_breeze #535659;
|
||||
@define-color tooltip_text_breeze #fcfcfc;
|
||||
@define-color unfocused_borders_breeze #4c4e51;
|
||||
@define-color unfocused_insensitive_borders_breeze #2d3033;
|
||||
@define-color warning_color_backdrop_breeze #f67400;
|
||||
@define-color warning_color_breeze #f67400;
|
||||
@define-color warning_color_insensitive_backdrop_breeze #5e340f;
|
||||
@define-color warning_color_insensitive_breeze #5e340f;
|
||||
@@ -1,3 +1,4 @@
|
||||
VteTerminal, vte-terminal {
|
||||
padding: 13px;
|
||||
}
|
||||
@import 'colors.css';
|
||||
@@ -1,16 +1,25 @@
|
||||
[Settings]
|
||||
gtk-font-name=Liberation Sans Regular 10
|
||||
gtk-theme-name=Gruvbox-Dark-BL
|
||||
gtk-icon-theme-name=Gruvbox_Dark
|
||||
gtk-cursor-theme-name=Gruvbox-cursors
|
||||
gtk-cursor-theme-size=16
|
||||
gtk-toolbar-style=GTK_TOOLBAR_BOTH_HORIZ
|
||||
gtk-toolbar-icon-size=GTK_ICON_SIZE_LARGE_TOOLBAR
|
||||
gtk-button-images=1
|
||||
gtk-menu-images=1
|
||||
gtk-application-prefer-dark-theme=true
|
||||
gtk-button-images=true
|
||||
gtk-cursor-blink=true
|
||||
gtk-cursor-blink-time=1000
|
||||
gtk-cursor-theme-name=breeze_cursors
|
||||
gtk-cursor-theme-size=24
|
||||
gtk-decoration-layout=icon:minimize,maximize,close
|
||||
gtk-enable-animations=true
|
||||
gtk-enable-event-sounds=0
|
||||
gtk-enable-input-feedback-sounds=0
|
||||
gtk-font-name=Noto Sans, 10
|
||||
gtk-icon-theme-name=breeze-dark
|
||||
gtk-menu-images=true
|
||||
gtk-modules=colorreload-gtk-module
|
||||
gtk-primary-button-warps-slider=true
|
||||
gtk-sound-theme-name=ocean
|
||||
gtk-theme-name=Gruvbox-Dark-BL
|
||||
gtk-toolbar-icon-size=GTK_ICON_SIZE_LARGE_TOOLBAR
|
||||
gtk-toolbar-style=3
|
||||
gtk-xft-antialias=1
|
||||
gtk-xft-dpi=122880
|
||||
gtk-xft-hinting=1
|
||||
gtk-xft-hintstyle=hintmedium
|
||||
gtk-xft-rgba=none
|
||||
|
||||
@@ -22,6 +22,15 @@ set $ws7 "7"
|
||||
set $ws8 "8"
|
||||
set $ws9 "9"
|
||||
set $ws10 "10"
|
||||
set $ws11 "11"
|
||||
set $ws12 "12"
|
||||
set $ws13 "13"
|
||||
set $ws14 "14"
|
||||
set $ws15 "15"
|
||||
set $ws16 "16"
|
||||
set $ws17 "17"
|
||||
set $ws18 "18"
|
||||
set $ws19 "19"
|
||||
|
||||
# Define colors variables:
|
||||
# gruvbox colors
|
||||
|
||||
@@ -12,20 +12,19 @@ exec --no-startup-id numlockx on
|
||||
# use arandr to setup displays and save the file as default:
|
||||
exec --no-startup-id ~/.screenlayout/default.sh
|
||||
|
||||
# set wallpaper
|
||||
exec --no-startup-id sleep 1 && feh --bg-fill --randomize ~/wallpapers
|
||||
|
||||
# set powersavings for display if not handled by DE:
|
||||
# Usage: xset dpms {standby_time} {suspend_time} {off_time}
|
||||
# exec --no-startup-id xset dpms 600 0 0
|
||||
#exec --no-startup-id xset dpms 600 0 0
|
||||
|
||||
# disable power saving (for example if using xscreensaver)
|
||||
#exec --no-startup-id xset -dpms
|
||||
exec --no-startup-id xset -dpms
|
||||
|
||||
# use xautolock to use autosuspend rules for mobile devices
|
||||
# https://wiki.archlinux.org/title/Session_lock#xautolock
|
||||
#exec --no-startup-id xautolock -time 60 -locker "systemctl suspend"
|
||||
|
||||
# set wallpaper(s) on i3 start/restart
|
||||
exec_always --no-startup-id "[ -f ~/.dotfiles-config ] && source ~/.dotfiles-config && $DOTFILES_DIR/bin/update-wallpaper"
|
||||
|
||||
# xscreensaver
|
||||
# https://www.jwz.org/xscreensaver
|
||||
@@ -45,15 +44,17 @@ exec --no-startup-id /usr/bin/dunst
|
||||
# Scratchpad with notes
|
||||
# `tmuxinator open notes` first for this to work
|
||||
exec --no-startup-id alacritty --title notebook -e zsh -c 'tmuxinator start notes'
|
||||
for_window [class="^Alacritty$" title="notebook"] move scratchpad, scratchpad hide
|
||||
for_window [class="^Alacritty$" title="notebook"] move scratchpad
|
||||
#, scratchpad hide
|
||||
|
||||
# Performance monitor
|
||||
exec --no-startup-id alacritty --title monitoring -e zsh -c 'htop'
|
||||
for_window [class="^Alacritty$" title="monitoring"] move scratchpad, scratchpad hide
|
||||
for_window [class="^Alacritty$" title="monitoring"] move scratchpad
|
||||
#, scratchpad hide
|
||||
|
||||
# Remote connections
|
||||
exec --no-startup-id alacritty --title servers -e zsh -c 'tmuxinator start servers'
|
||||
for_window [class="^Alacritty$" title="servers"] move scratchpad, scratchpad hide
|
||||
# exec --no-startup-id alacritty --title servers -e zsh -c 'tmuxinator start servers'
|
||||
# for_window [class="^Alacritty$" title="servers"] move scratchpad, scratchpad hide
|
||||
|
||||
###############
|
||||
# system tray #
|
||||
|
||||
@@ -7,10 +7,15 @@ floating_modifier $mod
|
||||
# switch/iterate between workspaces
|
||||
bindsym $mod+Tab workspace next
|
||||
bindsym $mod+Shift+Tab workspace prev
|
||||
bindsym $mod+c exec --no-startup-id ~/.config/i3/scripts/empty_workspace
|
||||
bindsym $mod+Shift+c exec --no-startup-id ~/.config/i3/scripts/move_container_empty_workspace
|
||||
|
||||
bindsym $mod+slash [class="^Alacritty$" title="notebook"] scratchpad show
|
||||
# bindsym $mod+slash scratchpad show
|
||||
bindsym $mod+m [class="^Alacritty$" title="monitoring"] scratchpad show
|
||||
bindsym $mod+Shift+colon [class="^Alacritty$" title="servers"] scratchpad show
|
||||
# bindsym $mod+Shift+colon [class="^Alacritty$" title="servers"] scratchpad show
|
||||
bindsym $mod+Shift+slash move scratchpad
|
||||
bindsym $mod+Control+slash scratchpad show
|
||||
|
||||
# switch to workspace
|
||||
bindsym $mod+1 workspace $ws1
|
||||
@@ -162,7 +167,8 @@ mode "$mode_gaps_outer" {
|
||||
######################################
|
||||
|
||||
# start a terminal
|
||||
bindsym $mod+Return exec --no-startup-id alacritty
|
||||
bindsym $mod+Return exec --no-startup-id alacritty -e sh -c "tmux new-session"
|
||||
# bindsym $mod+Return exec --no-startup-id alacritty
|
||||
|
||||
# kill focused window
|
||||
bindsym $mod+q kill
|
||||
@@ -171,7 +177,7 @@ bindsym $mod+q kill
|
||||
#bindsym --release button2 kill
|
||||
|
||||
# reload the configuration file
|
||||
bindsym $mod+Shift+c reload
|
||||
bindsym $mod+Control+r reload
|
||||
|
||||
# restart i3 inplace (preserves your layout/session, can be used to update i3)
|
||||
bindsym $mod+Shift+r restart
|
||||
@@ -206,7 +212,19 @@ bindsym $mod+Shift+Down move down
|
||||
bindsym $mod+Shift+Up move up
|
||||
bindsym $mod+Shift+Right move right
|
||||
|
||||
# splij in vertical orientation
|
||||
# move focused workspace
|
||||
bindsym $mod+Control+h move workspace to output left
|
||||
bindsym $mod+Control+j move workspace to output down
|
||||
bindsym $mod+Control+k move workspace to output up
|
||||
bindsym $mod+Control+l move workspace to output right
|
||||
|
||||
# alternatively, you can use the cursor keys:
|
||||
bindsym $mod+Control+Left move workspace to output left
|
||||
bindsym $mod+Control+Down move workspace to output down
|
||||
bindsym $mod+Control+Up move workspace to output up
|
||||
bindsym $mod+Control+Right move workspace to output right
|
||||
|
||||
# split in vertical orientation
|
||||
bindsym $mod+minus split v
|
||||
bindsym $mod+KP_Subtract split v
|
||||
|
||||
@@ -254,6 +272,7 @@ bindsym $mod+p exec --no-startup-id /usr/local/bin/switch-audio-port
|
||||
## App shortcuts
|
||||
bindsym $mod+w exec /usr/bin/firefox
|
||||
bindsym Print exec scrot ~/Pictures/Screenshots/%Y-%m-%d-%T-screenshot.png && notify-send "Screenshot saved to ~/Pictures/Screenshots/$(date +"%Y-%m-%d-%T")-screenshot.png"
|
||||
#bindsym Print exec spectactle --output ~/Pictures/Screenshots/%Y-%m-%d-%T-screenshot.png
|
||||
|
||||
# Power Profiles menu switcher (rofi)
|
||||
bindsym $mod+Shift+p exec --no-startup-id ~/.config/i3/scripts/power-profiles
|
||||
@@ -272,5 +291,12 @@ bindsym $mod+t exec --no-startup-id rofi -show window \
|
||||
|
||||
## rofi bindings to manage clipboard (install rofi-greenclip from the AUR)
|
||||
exec --no-startup-id greenclip daemon>/dev/null
|
||||
bindsym $mod+c exec --no-startup-id rofi -modi "clipboard:greenclip print" -show clipboard \
|
||||
bindsym $mod+b exec --no-startup-id rofi -modi "clipboard:greenclip print" -show clipboard \
|
||||
-config ~/.config/rofi/rofidmenu.rasi
|
||||
|
||||
## autoclicker x 100
|
||||
bindsym $mod+Shift+o exec --no-startup-id xdotool click --repeat 1000 --delay 10 1
|
||||
bindsym $mod+Shift+i exec --no-startup-id xdotool click --repeat 10000 --delay 10 1
|
||||
|
||||
# calculator
|
||||
bindsym XF86Calculator exec --no-startup-id galculator
|
||||
|
||||
@@ -9,7 +9,6 @@ default_border pixel 5
|
||||
|
||||
# thin borders
|
||||
hide_edge_borders smart
|
||||
smart_borders on
|
||||
|
||||
# Set inner/outer gaps
|
||||
gaps inner 10
|
||||
|
||||
@@ -13,18 +13,3 @@ workspace_layout default
|
||||
# Each new window will open fullscreen as a tab (left to right)
|
||||
#workspace_layout tabbed
|
||||
|
||||
##########################################
|
||||
# configuration for workspace behaviour: #
|
||||
##########################################
|
||||
|
||||
# use workspaces on different displays:
|
||||
# where you have to replace VGA-0/HDMI-0 with the names for your displays
|
||||
# you can get from xrandr command
|
||||
#workspace $ws1 output DP-2
|
||||
#workspace $ws3 output DP-2
|
||||
#workspace $ws5 output DP-2
|
||||
#workspace $ws2 output DP-4
|
||||
#workspace $ws4 output DP-4
|
||||
#workspace $ws6 output DP-4
|
||||
|
||||
exec i3-msg workspace 2
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
/home/brad/dotfiles/config/plasma-i3/i3-bar.conf
|
||||
@@ -1 +0,0 @@
|
||||
/home/brad/dotfiles/config/plasma-i3/i3-keybindings.conf
|
||||
@@ -0,0 +1,102 @@
|
||||
# i3blocks config file changed for EndeavourOS-i3 setup
|
||||
|
||||
# source is available here:
|
||||
# https://raw.githubusercontent.com/endeavouros-team/endeavouros-i3wm-setup/main/.config/i3/i3blocks.conf
|
||||
# Maintainer: joekamprad [joekamprad //a_t// endeavouros.com]
|
||||
# Former Visual Designer: Florent Valetti [@FLVAL EndeavourOS]
|
||||
# created for i3wm setup on EndeavourOS
|
||||
# https://endeavouros.com
|
||||
|
||||
# cheatsheet for icon fonts used on the block-bar:
|
||||
# https://fontawesome.com/v4.7/cheatsheet/
|
||||
|
||||
# --> to update this run the following command:
|
||||
# wget --backups=1 https://raw.githubusercontent.com/endeavouros-team/endeavouros-i3wm-setup/main/.config/i3/i3blocks.conf -P ~/.config/i3/
|
||||
|
||||
# Please see man i3blocks for a complete reference!
|
||||
# The man page is also hosted at http://vivien.github.io/i3blocks
|
||||
|
||||
|
||||
# List of valid properties:
|
||||
#
|
||||
# align
|
||||
# color
|
||||
# command
|
||||
# full_text
|
||||
# instance
|
||||
# interval
|
||||
# label
|
||||
# min_width
|
||||
# name
|
||||
# separator
|
||||
# separator_block_width
|
||||
# short_text
|
||||
# signal
|
||||
# urgent
|
||||
|
||||
# Global properties
|
||||
#
|
||||
# The top properties below are applied to every block, but can be overridden.
|
||||
separator=false
|
||||
markup=pango
|
||||
separator_block_width=15
|
||||
|
||||
#[Weather]
|
||||
#command=~/.config/i3/scripts/openweather
|
||||
# or:
|
||||
#command=~/.config/i3/scripts/openweather-city
|
||||
#interval=1800
|
||||
#color=#7275b3
|
||||
|
||||
separator_block_width=10
|
||||
[spacer]
|
||||
separator_block_width=10
|
||||
full_text=
|
||||
color=#b16286
|
||||
|
||||
[pavucontrol]
|
||||
separator_block_width=10
|
||||
full_text=
|
||||
command=pavucontrol
|
||||
color=#689d6a
|
||||
|
||||
[volume-pulseaudio]
|
||||
command=~/.config/i3/scripts/volume
|
||||
instance=Master
|
||||
color=#689d6a
|
||||
interval=1
|
||||
|
||||
separator_block_width=10
|
||||
[spacer]
|
||||
separator_block_width=10
|
||||
full_text=
|
||||
color=#b16286
|
||||
|
||||
[time]
|
||||
label=
|
||||
command=date '+%a %b %d %I:%M:%S %p'
|
||||
color=#98971a
|
||||
interval=1
|
||||
|
||||
separator_block_width=10
|
||||
[spacer]
|
||||
separator_block_width=10
|
||||
full_text=
|
||||
color=#b16286
|
||||
|
||||
[keybindings]
|
||||
full_text=
|
||||
command=~/.config/i3/scripts/keyhint
|
||||
|
||||
[sleep_screen]
|
||||
full_text=🖵
|
||||
command=~/.config/i3/scripts/blur-lock
|
||||
|
||||
[shutdown_menu]
|
||||
full_text=
|
||||
command=~/.config/i3/scripts/powermenu
|
||||
|
||||
separator_block_width=15
|
||||
[simple-2]
|
||||
full_text=
|
||||
color=#b16286
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
MAX_DESKTOPS=20
|
||||
|
||||
WORKSPACES=$(seq -s '\n' 1 1 ${MAX_DESKTOPS})
|
||||
|
||||
EMPTY_WORKSPACE=$( (i3-msg -t get_workspaces | tr ',' '\n' | grep num | awk -F: '{print int($2)}' ; \
|
||||
echo -e ${WORKSPACES} ) | sort -n | uniq -u | head -n 1)
|
||||
|
||||
i3-msg move container to workspace ${EMPTY_WORKSPACE}
|
||||
@@ -0,0 +1,63 @@
|
||||
" .ideavimrc is a configuration file for IdeaVim plugin. It uses
|
||||
" the same commands as the original .vimrc configuration.
|
||||
" You can find a list of commands here: https://jb.gg/h38q75
|
||||
" Find more examples here: https://jb.gg/share-ideavimrc
|
||||
|
||||
|
||||
"" -- Suggested options --
|
||||
" Show a few lines of context around the cursor. Note that this makes the
|
||||
" text scroll if you mouse-click near the start or end of the window.
|
||||
set scrolloff=5
|
||||
|
||||
" Do incremental searching.
|
||||
set incsearch
|
||||
|
||||
" Don't use Ex mode, use Q for formatting.
|
||||
map Q gq
|
||||
|
||||
" --- Enable IdeaVim plugins https://jb.gg/ideavim-plugins
|
||||
|
||||
" Highlight copied text
|
||||
Plug 'machakann/vim-highlightedyank'
|
||||
" Commentary plugin
|
||||
Plug 'tpope/vim-commentary'
|
||||
|
||||
|
||||
"" -- Map IDE actions to IdeaVim -- https://jb.gg/abva4t
|
||||
"" Map \r to the Reformat Code action
|
||||
"map \r <Action>(ReformatCode)
|
||||
|
||||
"" Map <leader>d to start debug
|
||||
"map <leader>d <Action>(Debug)
|
||||
|
||||
"" Map \b to toggle the breakpoint on the current line
|
||||
"map \b <Action>(ToggleLineBreakpoint)
|
||||
|
||||
inoremap ,, <ESC>
|
||||
cnoremap ,, <ESC><ESC>
|
||||
nmap j gj
|
||||
nmap k gk
|
||||
" Only set on first run or it overwrites YCM behavior
|
||||
" if has('vim_starting')
|
||||
" imap <tab> <C-X><C-O>
|
||||
" endif
|
||||
let mapleader=","
|
||||
let maplocalleader="\\"
|
||||
|
||||
" Close buffer
|
||||
map <leader><leader>c :Bclose<CR>
|
||||
" Prev/next buffer
|
||||
map <leader>q :bp<CR>
|
||||
map <leader>w :bn<CR>
|
||||
|
||||
" System clipboard cut copy paste
|
||||
map <leader>y "+y
|
||||
map <leader>Y "+Y
|
||||
map <leader>p "+p
|
||||
map <leader>P "+P
|
||||
map <leader>x "+x
|
||||
map <leader>dd "+dd
|
||||
|
||||
" Update ideavimrc
|
||||
nnoremap <leader>v :e ~/.ideavimrc<CR>;
|
||||
nnoremap <leader>rr :action IdeaVim.ReloadVimRc.reload<CR>;
|
||||
@@ -1 +1,4 @@
|
||||
POWERLINE_ROOT=/usr/share/powerline
|
||||
NO_NEOFETCH=1
|
||||
NO_GIT_CHECK=1
|
||||
NO_ZSH_COWSAY=1
|
||||
LOAD_SSH_KEYS=0
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
# nvim config map
|
||||
|
||||
Lua config managed by [lazy.nvim](https://github.com/folke/lazy.nvim). Leader is `,`, local leader is `\`.
|
||||
|
||||
## Layout
|
||||
|
||||
- `init.lua` — bootstraps lazy.nvim, loads `config/` then `plugins/`
|
||||
- `lua/config/options.lua` — `vim.opt` settings
|
||||
- `lua/config/keymaps.lua` — keymaps not tied to a specific plugin
|
||||
- `lua/config/autocmds.lua` — autocommands
|
||||
- `lua/plugins/*.lua` — one lazy.nvim spec file per topic (each file returns a plugin spec table; lazy.nvim loads every file in the directory automatically)
|
||||
- `ftplugin/*.lua` — filetype-specific settings (Python, vimwiki)
|
||||
- `lua/util.lua` — small helper functions (`ranger()`, `delete_trailing_ws()`) used from keymaps
|
||||
|
||||
## Plugins
|
||||
|
||||
### Navigation & editing (`plugins/editor.lua`)
|
||||
|
||||
- **[neo-tree.nvim](https://github.com/nvim-neo-tree/neo-tree.nvim)** — file explorer sidebar
|
||||
- `<leader>t` — toggle
|
||||
- `<leader>cd` — cd to current file's directory and open
|
||||
- **[telescope.nvim](https://github.com/nvim-telescope/telescope.nvim)** — fuzzy finder for files/buffers/grep/LSP symbols
|
||||
- `<leader>.` — jump to symbol
|
||||
- `<leader>;` — jump to buffer
|
||||
- `<leader>be` — jump to buffer, sorted by most recently used
|
||||
- `<leader>ag` — live grep
|
||||
- `<leader>?` — fuzzy-search all keybindings
|
||||
- **[flash.nvim](https://github.com/folke/flash.nvim)** — jump to any visible location via search-like labels
|
||||
- `<leader>/` — jump
|
||||
- `<leader>s` — search jump
|
||||
- `<leader><leader>s` — treesitter jump
|
||||
- `<leader>f` — forward jump
|
||||
- **[nvim-surround](https://github.com/kylechui/nvim-surround)** — add/change/delete surrounding pairs (quotes, tags, brackets)
|
||||
- `ys`, `cs`, `ds` — plugin defaults
|
||||
- **[nvim-autopairs](https://github.com/windwp/nvim-autopairs)** — auto-close brackets/quotes, automatic
|
||||
- **[nvim-treesitter-context](https://github.com/nvim-treesitter/nvim-treesitter-context)** — sticky header showing enclosing function/class while scrolling, automatic
|
||||
- **[mini.align](https://github.com/echasnovski/mini.nvim)** — align text on a character
|
||||
- `ga=`, `ga:`
|
||||
- **[mini.bufremove](https://github.com/echasnovski/mini.nvim)** — close a buffer without closing its window/split
|
||||
- `<leader><leader>c`
|
||||
- **[vim-visual-multi](https://github.com/mg979/vim-visual-multi)** — multiple cursors
|
||||
- `<C-n>` — add cursor on word
|
||||
- **[vim-tmux-navigator](https://github.com/christoomey/vim-tmux-navigator)** — move between nvim splits and tmux panes; also works from inside `:terminal` buffers (e.g. the Claude Code terminal)
|
||||
- `<C-h/j/k/l>` — move left/down/up/right
|
||||
- **[emmet-vim](https://github.com/mattn/emmet-vim)** — Emmet expansion, HTML/CSS files only
|
||||
|
||||
### UI (`plugins/ui.lua`)
|
||||
|
||||
- **[gruvbox.nvim](https://github.com/ellisonleao/gruvbox.nvim)** — colorscheme
|
||||
- **[lualine.nvim](https://github.com/nvim-lualine/lualine.nvim)** — statusline
|
||||
- **[bufferline.nvim](https://github.com/akinsho/bufferline.nvim)** — buffer tabs along the top
|
||||
- **[indent-blankline.nvim](https://github.com/lukas-reineke/indent-blankline.nvim)** — indent guides
|
||||
- **[rainbow-delimiters.nvim](https://github.com/HiPhish/rainbow-delimiters.nvim)** — rainbow-colored matching brackets
|
||||
- **[nvim-web-devicons](https://github.com/nvim-tree/nvim-web-devicons)** — filetype icons (dependency for several plugins above)
|
||||
- **[alpha-nvim](https://github.com/goolord/alpha-nvim)** — start screen shown on launch, see [Dashboard](#dashboard) below
|
||||
- `<leader><leader>o` — reopen
|
||||
|
||||
### Completion & LSP
|
||||
|
||||
- **[blink.cmp](https://github.com/Saghen/blink.cmp)** — completion engine (LSP, path, buffer sources) — `plugins/completion.lua`
|
||||
- **[mason.nvim](https://github.com/mason-org/mason.nvim)** / **[mason-lspconfig.nvim](https://github.com/mason-org/mason-lspconfig.nvim)** — installs/manages LSP servers — `plugins/lsp.lua`
|
||||
- **[nvim-lspconfig](https://github.com/neovim/nvim-lspconfig)** — LSP client config for `ts_ls`, `svelte`, `html`, `cssls`, `basedpyright`, `ruff`, `bashls` — `plugins/lsp.lua`
|
||||
- **[rustaceanvim](https://github.com/mrcjkb/rustaceanvim)** — Rust LSP setup (`rust_analyzer`), replaces the standard lspconfig flow for Rust — `plugins/rust.lua`
|
||||
- `<localleader>rr` — cargo run
|
||||
|
||||
LSP buffer keymaps (set on `LspAttach`, see `plugins/lsp.lua`):
|
||||
|
||||
- `K` — hover
|
||||
- `gd` — definition
|
||||
- `gy` — type definition
|
||||
- `gi` — implementation
|
||||
- `gr` — references
|
||||
- `rn` — rename
|
||||
- `ff` (visual) — format selection
|
||||
|
||||
### Debugging (`plugins/dap.lua`)
|
||||
|
||||
- **[nvim-dap](https://github.com/mfussenegger/nvim-dap)** — Debug Adapter Protocol client
|
||||
- `<leader>db` — toggle breakpoint
|
||||
- `<leader>dc` — continue / start debugging
|
||||
- `<leader>di` / `<leader>do` / `<leader>dO` — step into / over / out
|
||||
- `<leader>dr` — toggle REPL
|
||||
- `<leader>dq` — terminate session
|
||||
- **[nvim-dap-python](https://github.com/mfussenegger/nvim-dap-python)** — configures nvim-dap for Python using `debugpy`. Requires `:MasonInstall debugpy`; without it, debugging is skipped with a warning.
|
||||
|
||||
### Formatting & linting (`plugins/format.lua`)
|
||||
|
||||
- **[conform.nvim](https://github.com/stevearc/conform.nvim)** — format-on-save (prettier, ruff_format, rustfmt, stylua per filetype)
|
||||
- **[nvim-lint](https://github.com/mfussenegger/nvim-lint)** — async linting on save/insert-leave (eslint_d, shellcheck)
|
||||
|
||||
### Treesitter (`plugins/treesitter.lua`)
|
||||
|
||||
**[nvim-treesitter](https://github.com/nvim-treesitter/nvim-treesitter)** — syntax highlighting, folding, and indentation for the installed parser list. Uses core Neovim's built-in `vim.treesitter.start()`/foldexpr rather than the old treesitter modules.
|
||||
|
||||
### Git (`plugins/git.lua`)
|
||||
|
||||
- **[gitsigns.nvim](https://github.com/lewis6991/gitsigns.nvim)** — git change signs in the gutter, hunk stage/preview/blame
|
||||
- **[vim-fugitive](https://github.com/tpope/vim-fugitive)** — Git commands
|
||||
- `:Git`, `:Gdiffsplit`, `:Gvdiffsplit`, `:Gread`, `:Gwrite`, `:Gclog`
|
||||
|
||||
### AI (`plugins/ai.lua`)
|
||||
|
||||
- **[snacks.nvim](https://github.com/folke/snacks.nvim)** — utility library (terminal provider etc.), dependency for claudecode.nvim
|
||||
- **[claudecode.nvim](https://github.com/coder/claudecode.nvim)** — Claude Code terminal integration. Diffs render as a single unified (VS Code-style, red/green interleaved) buffer in one new split next to your active pane, and keyboard focus stays in the Claude terminal instead of jumping to the diff.
|
||||
- `<leader>ac` — toggle
|
||||
- `<leader>af` — focus
|
||||
- `<leader>ab` — add current buffer
|
||||
- `<leader>as` (visual) — send selection
|
||||
- `<leader>aa` / `<leader>ad` — accept/deny diff
|
||||
|
||||
### Wiki / notes (`plugins/vimwiki.lua`)
|
||||
|
||||
- **[vimwiki](https://github.com/vimwiki/vimwiki)** — personal wiki across 4 notebooks (bradwiki, work, private, shared under `~/synced-notebooks/`)
|
||||
- `<leader>m...` — wiki keymaps (`vim.g.vimwiki_map_prefix`)
|
||||
- **[vim-zettel](https://github.com/michal-h21/vim-zettel)** — Zettelkasten-style note linking on top of vimwiki
|
||||
- **[vim-table-mode](https://github.com/dhruvasagar/vim-table-mode)** — markdown/wiki table formatting
|
||||
- `:TableModeToggle`, or `<leader><leader>t...` prefix
|
||||
- **[markdown-preview.nvim](https://github.com/iamcco/markdown-preview.nvim)** — live browser preview for markdown/vimwiki
|
||||
- `<localleader>v` — toggle preview
|
||||
|
||||
### Misc (`plugins/misc.lua`)
|
||||
|
||||
- **[aerial.nvim](https://github.com/stevearc/aerial.nvim)** — code outline/symbol sidebar
|
||||
- `<leader>ct` — toggle
|
||||
- **[undotree](https://github.com/jiaoshijie/undotree)** — visual undo history tree
|
||||
- `<leader>u` — toggle
|
||||
- **[persistence.nvim](https://github.com/folke/persistence.nvim)** — session save/restore per project
|
||||
- restore from the dashboard's `s` button
|
||||
- **[which-key.nvim](https://github.com/folke/which-key.nvim)** — shows available keybindings as you type a prefix (e.g. pause after `<leader>`), automatic
|
||||
|
||||
## Dashboard
|
||||
|
||||
The start screen (shown on launch, reopen with `<leader><leader>o`) is [alpha-nvim](https://github.com/goolord/alpha-nvim), configured in `plugins/ui.lua`. It shows a random `fortune | cowthink` header plus buttons:
|
||||
|
||||
- `e` — new file
|
||||
- `f` — find file (Telescope)
|
||||
- `g` — live grep (Telescope)
|
||||
- `s` — restore last session (persistence.nvim)
|
||||
- `q` — quit
|
||||
|
||||
## Buffer navigation
|
||||
|
||||
`<leader>be` fuzzy-searches open buffers via Telescope, sorted by most recently used, excluding the current buffer. `<leader>;` does the same but in default Telescope order. Both are fuzzy-filterable as you type.
|
||||
@@ -0,0 +1,21 @@
|
||||
" Source config files
|
||||
source $HOME/.config/nvim/config/plugin.vimrc
|
||||
source $HOME/.config/nvim/config/bindings-vimwiki.vimrc
|
||||
source $HOME/.config/nvim/config/init.vimrc
|
||||
source $HOME/.config/nvim/config/general.vimrc
|
||||
source $HOME/.config/nvim/config/bindings.vimrc
|
||||
source $HOME/.config/nvim/config/functions.vimrc
|
||||
|
||||
" Python dependencies
|
||||
if isdirectory(expand($HOME.'/.pyenv/versions/neovim2'))
|
||||
let g:python_host_prog=expand($HOME.'/.pyenv/versions/neovim2/bin/python')
|
||||
endif
|
||||
if isdirectory(expand($HOME.'/.pyenv/versions/neovim3'))
|
||||
let g:python3_host_prog=expand($HOME.'/.pyenv/versions/neovim3/bin/python')
|
||||
endif
|
||||
|
||||
" Local overrides
|
||||
let $LOCALFILE=expand("$HOME/.nvim_local.vimrc")
|
||||
if filereadable($LOCALFILE)
|
||||
source $LOCALFILE
|
||||
endif
|
||||
@@ -1,78 +0,0 @@
|
||||
vim.cmd([[
|
||||
function! MapVimwiki()
|
||||
" grep: if exists('g:loaded_vimwiki')
|
||||
" double m
|
||||
nmap <leader>mm <Plug>VimwikiIndex
|
||||
" m wiki
|
||||
nmap <leader>mw <Plug>VimwikiUISelect
|
||||
" m help
|
||||
nmap <leader>mhelp :verbose map ,m<CR>
|
||||
" m go
|
||||
nmap <leader>mg <Plug>VimwikiGoto
|
||||
" m personal
|
||||
nmap <leader>mf <Plug>VimwikiUISelect1<CR>
|
||||
" m work
|
||||
nmap <leader>m<Space> <Plug>VimwikiUISelect2<CR>
|
||||
" m private
|
||||
nmap <leader>mp <Plug>VimwikiUISelect3<CR>
|
||||
" m shared
|
||||
nmap <leader>ms <Plug>VimwikiUISelect4<CR>
|
||||
|
||||
" <C-Enter> and <S-Enter> (the original bindings for these) don't work
|
||||
" because they send the same keycode and probably other reasons
|
||||
nmap <leader>m- <Plug>VimwikiSplitLink
|
||||
nmap <leader>m<bar> <Plug>VimwikiVSplitLink
|
||||
|
||||
nmap <leader>mnt <Plug>VimwikiNextTask
|
||||
" TODO This command doesn't exist
|
||||
" nmap <leader>mN <Plug>VimwikiPrevTask
|
||||
nmap <leader>mnl <Plug>VimwikiNextLink
|
||||
nmap <leader>mNl <Plug>VimwikiPrevLink
|
||||
" nmap <leader>m/ <Plug>VimwikiSearch /
|
||||
" nmap <leader>maq <Plug>ZettelOpen
|
||||
nmap <Tab> <Plug>VimwikiIncreaseLvlSingleItem
|
||||
nmap <S-Tab> <Plug>VimwikiDecreaseLvlSingleItem
|
||||
imap <Tab> <Plug>VimwikiIncreaseLvlSingleItem
|
||||
imap <S-Tab> <Plug>VimwikiDecreaseLvlSingleItem
|
||||
vmap <Tab> <Plug>VimwikiIncreaseLvlSingleItem
|
||||
vmap <S-Tab> <Plug>VimwikiDecreaseLvlSingleItem
|
||||
" This is how to map insert mode plug commands <Esc><Plug>{command}a
|
||||
" This always jumps to the end of the line, but with 'a' it doesn't skip
|
||||
" the [ ] when adding at the start of the line
|
||||
imap <C-Space> <Esc><Plug>VimwikiToggleListItemA
|
||||
nmap <C-d><C-Space> <Plug>VimwikiRemoveSingleCB
|
||||
imap <C-d><C-Space> <Esc><Plug>VimwikiRemoveSingleCBa
|
||||
nmap <leader>mb <Plug>VimwikiBackLinks
|
||||
" nmap <leader>m\ <Plug>VimwikiTable
|
||||
nmap <leader>mqtoc <Plug>VimwikiTOC
|
||||
nmap <leader>mqgtl <Plug>VimwikiRebuildTags<CR><Plug>VimwikiGenerateTagLinks<CR>
|
||||
|
||||
" Insert link from system clipboard
|
||||
vmap <leader>mk c[]<Esc>Pea()<Esc>"+P
|
||||
imap <leader>mk <Esc>viW<C-k>ea
|
||||
nmap <leader>mk ciw[]<Esc>Pea()<Esc>"+P
|
||||
|
||||
" TODO: None of these work
|
||||
" nmap <leader>m| :VimwikiVSplitLink 1 1<CR>
|
||||
" nmap <leader>m- :VimwikiSplitLink 1 1<CR>
|
||||
" vmap <leader>m- :VimwikiSplitLink 1 1<CR>
|
||||
|
||||
" Vim-Zettel
|
||||
" TODO The <Plug> syntax is correct but broken
|
||||
" autocmd Filetype vimwiki nmap <leader>mag <Plug>ZettelOpen
|
||||
autocmd Filetype vimwiki nmap <leader>mag :ZettelOpen<CR>
|
||||
" autocmd Filetype vimwiki nmap <leader>mp0 :ZettelOpen<CR>p0
|
||||
" autocmd Filetype vimwiki nmap <leader>mp1 :ZettelOpen<CR>p1
|
||||
" TODO This doesn't work
|
||||
autocmd Filetype vimwiki nmap <leader>mat :ZettelOpen<CR>title:
|
||||
endfunction
|
||||
|
||||
augroup Vimwiki_Mappings
|
||||
autocmd!
|
||||
" TODO: This isn't working, vimwiki bindings are not being initialized
|
||||
autocmd FileType vimwiki :call MapVimwiki()
|
||||
augroup END
|
||||
" TODO This shouldn't be necessary, why does this need to be called before vimwiki
|
||||
" and after startup?
|
||||
" :call MapVimwiki()
|
||||
]])
|
||||
@@ -1,191 +0,0 @@
|
||||
vim.cmd([[
|
||||
" --- Mappings ---
|
||||
" Explanation of mapping commands: https://stackoverflow.com/a/3776182
|
||||
" - General -
|
||||
" TODO: Remap this to easymotion but don't step on other bindings
|
||||
" noremap <space> :
|
||||
inoremap ,, <ESC>
|
||||
cnoremap ,, <ESC><ESC>
|
||||
nmap j gj
|
||||
nmap k gk
|
||||
" Only set on first run or it overwrites YCM behavior
|
||||
" if has('vim_starting')
|
||||
" imap <tab> <C-X><C-O>
|
||||
" endif
|
||||
let mapleader=","
|
||||
let maplocalleader="\\"
|
||||
" Clear highlighting on ,, in normal mode
|
||||
map <leader><leader><ESC> :nohl<CR>
|
||||
" Enable hex mode
|
||||
map <leader>\he :%!xxd<CR>
|
||||
" Disable hex mode
|
||||
map <leader>\hd :%!xxd -r<CR>
|
||||
" Show whitespace
|
||||
nmap <leader><leader>lw :set list!<CR>
|
||||
" List registers
|
||||
map <leader><leader>lr :reg<CR>
|
||||
" List marks
|
||||
map <leader><leader>lm :marks<CR>
|
||||
" Close buffer
|
||||
map <leader><leader>c :Bclose<CR>
|
||||
" Prev/next buffer
|
||||
map <leader>q :bp<CR>
|
||||
map <leader>w :bn<CR>
|
||||
" System clipboard cut copy paste
|
||||
map <leader>y "+y
|
||||
map <leader>Y "+Y
|
||||
map <leader>p "+p
|
||||
map <leader>P "+P
|
||||
map <leader>x "+x
|
||||
map <leader>dd "+dd
|
||||
" Line break above
|
||||
" TODO urxvt (and other ttys) treat C-CR, S-CR, and CR as the same input
|
||||
" imap <C-CR> <CR><ESC><ESC>Bkki
|
||||
" Move between splits
|
||||
nnoremap <C-j> <C-W><C-j>
|
||||
nnoremap <C-k> <C-W><C-k>
|
||||
nnoremap <C-h> <C-W><C-h>
|
||||
nnoremap <C-l> <C-W><C-l>
|
||||
" Make split
|
||||
nnoremap <leader>- :sp<space>
|
||||
nnoremap <leader><bar> :vsp<space>
|
||||
set splitbelow
|
||||
set splitright
|
||||
" Open vimrc
|
||||
map <leader>v :e $MYVIMRC<CR>
|
||||
" Set working directory to current file directory
|
||||
map <leader>cd :cd %:p:h<CR>:pwd<CR>:NERDTreeCWD<CR>:NERDTreeToggle<CR>
|
||||
" Update vimrc
|
||||
map <leader>rr :call ReloadVimRC()<CR>;
|
||||
" Open GVim menu
|
||||
" map <leader>m :emenu <C-Z><C-Z>
|
||||
" Low-light mode
|
||||
map <leader><leader>ll :set background=dark<CR>
|
||||
" Daylight mode
|
||||
map <leader><leader>LL :set background=light<CR>
|
||||
" Open ranger
|
||||
nmap <leader>ra :call Ranger()<CR>
|
||||
" Delete whitespace
|
||||
nmap <leader>rw :call DeleteTrailingWS()<CR>
|
||||
" Fix syntax highlighting
|
||||
noremap <F12> <Esc>:syntax sync fromstart<CR>
|
||||
|
||||
|
||||
function! MapPlugins()
|
||||
" - Plugins -
|
||||
if exists('g:loaded_startify')
|
||||
" Open Startify
|
||||
map <leader><leader>o :Startify<CR>
|
||||
endif
|
||||
|
||||
if exists('g:loaded_nerd_tree')
|
||||
" Toggle directory view
|
||||
map <leader>t :NERDTreeToggle<CR>
|
||||
endif
|
||||
|
||||
" Generative AI
|
||||
|
||||
if exists('g:loaded_tagbar')
|
||||
" Toggle tagbar
|
||||
map <leader>ct :TagbarToggle<CR>
|
||||
endif
|
||||
|
||||
if exists('g:loaded_vimwiki')
|
||||
" TODO This shouldn't be necessary!
|
||||
" NOTE: Changes must be mirrored to config/bindings-vimwiki.vimrc!
|
||||
endif
|
||||
|
||||
if exists('g:loaded_table_mode')
|
||||
endif
|
||||
|
||||
if exists('g:loaded_zettel')
|
||||
let g:zettel_default_mappings = 0
|
||||
endif
|
||||
|
||||
" Update ctags
|
||||
" nnoremap <leader>ct :! ctags -R<CR><CR>
|
||||
|
||||
if exists('g:loaded_ctrlp')
|
||||
" Jump to a tag
|
||||
nnoremap <leader>. :CtrlPTag<CR>
|
||||
" Jump to a buffer
|
||||
nnoremap <leader>; :CtrlPBuffer<CR>
|
||||
endif
|
||||
|
||||
" Make a config for YCM from Makefile
|
||||
map <leader>ygc :YcmGenerateConfig<CR>
|
||||
|
||||
" Ag
|
||||
map <leader>ag :Ag<space>
|
||||
|
||||
" Easymotion
|
||||
if exists('g:EasyMotion_loaded')
|
||||
" let g:EasyMotion_do_mapping = 0
|
||||
let g:EasyMotion_smartcase = 1
|
||||
map <leader>/ <Plug>(easymotion-sn)
|
||||
omap <leader>/ <Plug>(easymotion-tn)
|
||||
" map <leader>n <Plug>(easymotion-next)
|
||||
" map <leader>N <Plug>(easymotion-prev)
|
||||
" Bidirectional single-letter search
|
||||
map <leader>s <Plug>(easymotion-s)
|
||||
" Bidirectional 2-letter search
|
||||
map <leader><leader>s <Plug>(easymotion-s2)
|
||||
" Forward single letter search
|
||||
map <leader>f <Plug>(easymotion-f)
|
||||
" Directional jumps
|
||||
map <leader>l <Plug>(easymotion-lineforward)
|
||||
map <leader>j <Plug>(easymotion-j)
|
||||
map <leader>k <Plug>(easymotion-k)
|
||||
map <leader>h <Plug>(easymotion-linebackward)
|
||||
endif
|
||||
|
||||
" Multiple Cursors
|
||||
let g:multi_cursor_use_default_mapping=0
|
||||
let g:multi_cursor_next_key='n'
|
||||
let g:multi_cursor_prev_key='m'
|
||||
let g:multi_cursor_skip_key='.'
|
||||
let g:multi_cursor_quit_key=','
|
||||
let g:multi_cursor_start_key='<C-n>'
|
||||
|
||||
if exists('g:tabular_loaded')
|
||||
" Tabular
|
||||
map <leader>a= :Tabularize /=<CR>
|
||||
map <leader>a: :Tabularize /:\zs<CR>
|
||||
endif
|
||||
|
||||
if exists('g:loaded_nerd_comments')
|
||||
" NERD Commenter
|
||||
" Enter the NERD Commenter menu which can be tabbed through
|
||||
map <leader>nc :emenu Plugin.comment.<C-Z><C-Z>
|
||||
endif
|
||||
|
||||
if exists('g:loaded_gundo')
|
||||
" Gundo
|
||||
nnoremap <leader>u :GundoToggle<CR>
|
||||
endif
|
||||
|
||||
" --- Language Specific ---
|
||||
" - General
|
||||
" COC
|
||||
" Use K to show documentation in preview window
|
||||
nnoremap K :call ShowDocumentation()
|
||||
|
||||
nmap ff <plug>(coc-format-selected)
|
||||
nmap rn <plug>(coc-rename)
|
||||
nmap gd <plug>(coc-definition)
|
||||
nmap gy <plug>(coc-type-definition)
|
||||
nmap gi <plug>(coc-implementation)
|
||||
nmap gr <plug>(coc-references)
|
||||
|
||||
" - Rust -
|
||||
map <localleader>rr :RustRun<CR>
|
||||
|
||||
" - Markdown -
|
||||
map <localleader>v :LivedownToggle<CR>
|
||||
endfunction
|
||||
|
||||
augroup Plugin_Mappings
|
||||
autocmd!
|
||||
autocmd VimEnter * :call MapPlugins()
|
||||
augroup END
|
||||
]])
|
||||
@@ -82,8 +82,6 @@ function! MapPlugins()
|
||||
map <leader>t :NERDTreeToggle<CR>
|
||||
endif
|
||||
|
||||
" Generative AI
|
||||
|
||||
if exists('g:loaded_tagbar')
|
||||
" Toggle tagbar
|
||||
map <leader>ct :TagbarToggle<CR>
|
||||
@@ -163,6 +161,16 @@ function! MapPlugins()
|
||||
nnoremap <leader>u :GundoToggle<CR>
|
||||
endif
|
||||
|
||||
if exists('g:loaded_claudecode')
|
||||
" Claude Code
|
||||
nnoremap <leader>ac :ClaudeCode<CR>
|
||||
nnoremap <leader>af :ClaudeCodeFocus<CR>
|
||||
nnoremap <leader>ab :ClaudeCodeAdd %<CR>
|
||||
vnoremap <leader>as :ClaudeCodeSend<CR>
|
||||
nnoremap <leader>aa :ClaudeCodeDiffAccept<CR>
|
||||
nnoremap <leader>ad :ClaudeCodeDiffDeny<CR>
|
||||
endif
|
||||
|
||||
" --- Language Specific ---
|
||||
" - General
|
||||
" COC
|
||||
@@ -180,7 +188,8 @@ function! MapPlugins()
|
||||
map <localleader>rr :RustRun<CR>
|
||||
|
||||
" - Markdown -
|
||||
map <localleader>v :LivedownToggle<CR>
|
||||
" map <localleader>v :LivedownToggle<CR>
|
||||
nmap <localleader>v <Plug>MarkdownPreviewToggle
|
||||
endfunction
|
||||
|
||||
augroup Plugin_Mappings
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
vim.cmd([[
|
||||
"------ Functions ------
|
||||
if executable('ranger')
|
||||
" Open ranger from within vim
|
||||
function! Ranger()
|
||||
" Get a temp file name without creating it
|
||||
let tmpfile = substitute(system('mktemp -u'), '\n', '', '')
|
||||
" Launch ranger, passing it the temp file name
|
||||
silent exec '!RANGER_RETURN_FILE='.tmpfile.' ranger'
|
||||
" If the temp file has been written by ranger
|
||||
if filereadable(tmpfile)
|
||||
" Get the selected file name from the temp file
|
||||
let filetoedit = system('cat '.tmpfile)
|
||||
exec 'edit '.filetoedit
|
||||
call delete(tmpfile)
|
||||
endif
|
||||
redraw!
|
||||
endfunction
|
||||
endif
|
||||
|
||||
" set viminfo=%M
|
||||
|
||||
" Delete trailing white space on save, useful for Python and CoffeeScript ;)
|
||||
func! DeleteTrailingWS()
|
||||
silent! normal mz
|
||||
silent! %s/\s\+$//ge
|
||||
silent! normal `z
|
||||
endfunc
|
||||
" autocmd BufWrite *.py :call DeleteTrailingWS()
|
||||
" autocmd BufWrite *.coffee :call DeleteTrailingWS()
|
||||
|
||||
" Only define if not defined, otherwise it'll be redefined in the middle of
|
||||
" execution
|
||||
if !exists("*ReloadVimRC")
|
||||
func! ReloadVimRC()
|
||||
" IMPORTANT: After way too much messing with this trying to make everything work properly
|
||||
" after a vimrc reload, my advice is DON'T RELOAD THE VIMRC WHILE EDITING A FILE!
|
||||
" Side effects will include: Some syntax highlighting lost until next save, indentline
|
||||
" plugin will break, newly opened buffers will use buffer reloaded on's syntax file for
|
||||
" comment plugins (and possibly other things)
|
||||
" Ommision of 'syntax on' here will prevent anything from breaking inside the current buffer,
|
||||
" however new buffers will be opened without any syntax highlighting
|
||||
source $MYVIMRC
|
||||
" Need to toggle this twice, once toggles every other time, none turns
|
||||
" it off on reload. I have no idea why this is.
|
||||
RainbowToggle
|
||||
RainbowToggle
|
||||
syntax on
|
||||
" Workaround for indentline turning off on syntax enable
|
||||
IndentLinesReset
|
||||
endfunc
|
||||
endif
|
||||
|
||||
" COC Show Documentation under cursor
|
||||
function! ShowDocumentation()
|
||||
if (index(['vim','help'], &filetype) >= 0)
|
||||
execute 'h '.expand('')
|
||||
else
|
||||
call CocAction('doHover')
|
||||
endif
|
||||
endfunction
|
||||
]])
|
||||
@@ -1,164 +0,0 @@
|
||||
vim.cmd([[
|
||||
" Needed for vimwiki
|
||||
set nocompatible
|
||||
filetype plugin on
|
||||
syntax on
|
||||
|
||||
" Control-X Control-O to open autocomplete box
|
||||
set omnifunc=syntaxcomplete#Complete
|
||||
" Leave hidden buffers open
|
||||
set hidden
|
||||
set autoread " Reload files changed outside vim
|
||||
|
||||
" Turn off .swp files
|
||||
set noswapfile
|
||||
set nobackup
|
||||
|
||||
set t_Co=256 " Run in 256-color mode
|
||||
set number " Show line numbers
|
||||
|
||||
" Set the clipbaord
|
||||
" set clipboard+=unnamedplus
|
||||
" let g:clipboard = {
|
||||
" \ 'name': 'myClipboard',
|
||||
" \ 'copy': {
|
||||
" \ '+': 'tmux load-buffer -',
|
||||
" \ '*': 'tmux load-buffer -',
|
||||
" \ },
|
||||
" \ 'paste': {
|
||||
" \ '+': 'tmux save-buffer -',
|
||||
" \ '*': 'tmux save-buffer -',
|
||||
" \ },
|
||||
" \ 'cache_enabled': 1,
|
||||
" \ }
|
||||
" let g:loaded_clipboard_provider=1
|
||||
|
||||
|
||||
" Matchit plugin enhances %
|
||||
runtime macros/matchit.vim
|
||||
|
||||
" Set unix line endings
|
||||
" set fileformat=unix
|
||||
|
||||
" Set encoding for vim-devicons
|
||||
set encoding=UTF-8
|
||||
|
||||
" Don't redraw screen when not needed
|
||||
set lazyredraw
|
||||
|
||||
" Allow backspacing over everything
|
||||
set backspace=indent,eol,start
|
||||
|
||||
" Keep longer history
|
||||
set history=700
|
||||
|
||||
" Incremental search
|
||||
set incsearch
|
||||
|
||||
" Smart case insensitive search
|
||||
set ignorecase
|
||||
set smartcase
|
||||
|
||||
" Maintain context around cursor
|
||||
set scrolloff=15
|
||||
|
||||
" Wildmode configuration
|
||||
set wildmode=longest,list,full
|
||||
set wildmenu
|
||||
" Make hardcoded tab work
|
||||
:set wildcharm=<C-Z>
|
||||
|
||||
" Mouse support
|
||||
set mouse=a
|
||||
|
||||
" Configure tab behavior
|
||||
set tabstop=4
|
||||
set softtabstop=4
|
||||
set expandtab
|
||||
set shiftwidth=4
|
||||
" set autoindent
|
||||
set cindent
|
||||
set cinkeys-=0#
|
||||
set indentkeys-=0#
|
||||
" set smartindent
|
||||
|
||||
" Linewrap
|
||||
set wrap linebreak nolist
|
||||
|
||||
" Show current position
|
||||
set ruler
|
||||
|
||||
" Show matching brackets
|
||||
set showmatch
|
||||
|
||||
" Make conceals less of an issue to edit by expanding on cursor
|
||||
let g:indentLine_concealcursor=""
|
||||
let g:indentLine_conceallevel=2
|
||||
|
||||
" Code folding
|
||||
set foldmethod=syntax
|
||||
set foldcolumn=5
|
||||
set foldlevel=2
|
||||
set foldlevelstart=2
|
||||
let g:vimwiki_folding='list'
|
||||
let g:markdown_folding=1
|
||||
|
||||
" Make views automatic (they store folds)
|
||||
set viewoptions-=options
|
||||
" TODO: These caused all of my buffers to cycle on buffer operations and
|
||||
" slowed things down
|
||||
" autocmd BufWinLeave * if expand("%") != "" | silent! mkview! | endif
|
||||
" autocmd BufWinEnter * if expand("%") != "" | silent! loadview | endif
|
||||
|
||||
" Don't open empty buffer when starting existing session
|
||||
set shortmess+=I
|
||||
|
||||
" Load default menus
|
||||
source $VIMRUNTIME/menu.vim
|
||||
|
||||
" Always display airline statusline
|
||||
set laststatus=2
|
||||
" Hide default statusline text
|
||||
set noshowmode "
|
||||
|
||||
" Theme
|
||||
" colorscheme zenburn
|
||||
" colorscheme solarized
|
||||
" colorscheme base16-default
|
||||
" colorscheme hybrid_reverse
|
||||
" colorscheme hybrid_material
|
||||
try
|
||||
silent! colorscheme gruvbox
|
||||
catch /^Vim\%((\a\++)\)\=:E185/
|
||||
colorscheme desert
|
||||
endtry
|
||||
|
||||
set termguicolors
|
||||
|
||||
let g:enable_bold_font = 1
|
||||
|
||||
" Have vrm extend background color to full terminal screen
|
||||
set t_ut=
|
||||
|
||||
" --- GUI settings ---
|
||||
" set lines=50
|
||||
" set columns=150
|
||||
|
||||
" --- Language specific settings ---
|
||||
" autocmd! BufNewFile,BufReadPre,FileReadPre,BufEnter * set expandtab softtabstop=4 shiftwidth=4
|
||||
augroup Enter_Buffer
|
||||
autocmd!
|
||||
autocmd BufNewFile,BufReadPre,FileReadPre,BufEnter *.pde setlocal softtabstop=2 shiftwidth=2
|
||||
autocmd BufNewFile,BufReadPre,FileReadPre,BufEnter Makefile setlocal noexpandtab softtabstop=0 shiftwidth=8
|
||||
autocmd BufNewFile,BufReadPre,FileReadPre,BufEnter *.asm,*.S setlocal softtabstop=8 shiftwidth=8
|
||||
augroup END
|
||||
|
||||
au BufNewFile,BufRead *.py
|
||||
\ setlocal tabstop=4 |
|
||||
\ setlocal softtabstop=4 |
|
||||
\ setlocal shiftwidth=4 |
|
||||
\ setlocal textwidth=79 |
|
||||
\ setlocal expandtab |
|
||||
\ setlocal autoindent |
|
||||
\ setlocal fileformat=unix |
|
||||
]])
|
||||
@@ -1,187 +0,0 @@
|
||||
vim.cmd([[
|
||||
let g:vim_plug_install_dir = "~/.local/share/nvim/site/autoload"
|
||||
let g:plugin_install_dir = "~/.local/share/nvim/plugged"
|
||||
|
||||
" Install vim-plug if not present
|
||||
if empty(glob(g:vim_plug_install_dir . "/plug.vim"))
|
||||
execute "!curl -fLo " . g:vim_plug_install_dir . "/plug.vim "
|
||||
\ "--create-dirs https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim"
|
||||
endif
|
||||
|
||||
call plug#begin('~/.vim/plugged')
|
||||
|
||||
" --- General ---
|
||||
" - Visual -
|
||||
" Rainbow parentheses
|
||||
Plug 'luochen1990/rainbow'
|
||||
" Gruvbox
|
||||
Plug 'morhetz/gruvbox'
|
||||
" Airline
|
||||
" TODO This now depends on lua
|
||||
Plug 'bling/vim-airline'
|
||||
|
||||
" - Views -
|
||||
" Start screen
|
||||
Plug 'mhinz/vim-startify'
|
||||
" Directory view
|
||||
Plug 'scrooloose/nerdtree'
|
||||
" Visualize undo tree
|
||||
Plug 'sjl/gundo.vim'
|
||||
" Much nicer buffer management
|
||||
Plug 'jlanzarotta/bufexplorer'
|
||||
" Shows indentation level
|
||||
Plug 'yggdroot/indentLine'
|
||||
" Show marks
|
||||
" TODO Make this not conflict with ,mm for vimwiki, probably just an issue
|
||||
" with not having vimwiki installed yet
|
||||
" Plug 'kshenoy/vim-signature'
|
||||
"
|
||||
" - Sessions -
|
||||
" Better sessions
|
||||
Plug 'tpope/vim-obsession'
|
||||
|
||||
" - Generative AI -
|
||||
Plug 'David-Kunz/gen.nvim'
|
||||
|
||||
" - Ctags -
|
||||
" Ctags view
|
||||
Plug 'majutsushi/tagbar'
|
||||
" Automatically keep ctags up to date
|
||||
" Plug 'xolox/vim-easytags'
|
||||
" TODO Fix compatibility with vim-zettel
|
||||
" Plug 'c0r73x/neotags.nvim'
|
||||
|
||||
" - Syntax and completion -
|
||||
" Asynchronous linting
|
||||
Plug 'neomake/neomake'
|
||||
" Completion
|
||||
Plug 'Shougo/deoplete.nvim', { 'do': ':UpdateRemotePlugins' }
|
||||
" Awesome autocompletion for almost everything
|
||||
" Plug 'Valloric/YouCompleteMe', {
|
||||
" \ 'build' : {
|
||||
" \ 'mac' : './install.sh --clang-completer --system-libclang --omnisharp-completer --racer-completer',
|
||||
" \ 'unix' : './install.sh --clang-completer --system-libclang --omnisharp-completer --racer-completer',
|
||||
" \ 'windows' : './install.sh --clang-completer --system-libclang --omnisharp-completer --racer-completer',
|
||||
" \ 'cygwin' : './install.sh --clang-completer --system-libclang --omnisharp-completer --racer-completer'
|
||||
" \ }
|
||||
" \ }
|
||||
|
||||
" - Commenting -
|
||||
" Comment toggling with lots of options
|
||||
Plug 'scrooloose/nerdcommenter'
|
||||
" Simple, quick commenting
|
||||
Plug 'tpope/vim-commentary'
|
||||
|
||||
" - Git -
|
||||
" Shows git changes in the side gutter
|
||||
" Plug 'airblade/vim-gitgutter'
|
||||
Plug 'mhinz/vim-signify'
|
||||
" Git wrapper inside vim
|
||||
Plug 'tpope/vim-fugitive'
|
||||
|
||||
" - Automation -
|
||||
" Surround things and change surroundings
|
||||
Plug 'tpope/vim-surround'
|
||||
" Parentheses and bracket auto-close
|
||||
Plug 'Raimondi/delimitMate'
|
||||
" Much nicer navigation
|
||||
" TODO Move this to space key
|
||||
Plug 'easymotion/vim-easymotion'
|
||||
" Multiple cursors
|
||||
Plug 'terryma/vim-multiple-cursors'
|
||||
" Automatic alignment
|
||||
Plug 'godlygeek/tabular'
|
||||
" Tables
|
||||
Plug 'dhruvasagar/vim-table-mode'
|
||||
|
||||
" - Search -
|
||||
" Kickass fuzzy finder for whole filesystem
|
||||
Plug 'ctrlpvim/ctrlp.vim'
|
||||
" Can use Ag from vim
|
||||
" Plug 'rking/ag.vim'
|
||||
|
||||
" - Utility and dependencies
|
||||
" Library required for some plugins
|
||||
" Plug 'L9'
|
||||
" Close buffers
|
||||
Plug 'rbgrouleff/bclose.vim'
|
||||
" Seamless navigation between tmux panes and vim splits
|
||||
Plug 'christoomey/vim-tmux-navigator'
|
||||
" Required for easytags
|
||||
Plug 'xolox/vim-misc'
|
||||
" Make . work for plugins
|
||||
Plug 'tpope/vim-repeat'
|
||||
" Auto reload changed config
|
||||
Plug 'xolox/vim-reload'
|
||||
" Make configuration files for YCM
|
||||
" Plug 'rdnetto/YCM-Generator'
|
||||
|
||||
" - Note Taking -
|
||||
" Note taking and wiki managment
|
||||
Plug 'vimwiki/vimwiki'
|
||||
" TODO Why can't these go in Search?
|
||||
Plug 'junegunn/fzf'
|
||||
Plug 'junegunn/fzf.vim'
|
||||
Plug 'michal-h21/vim-zettel'
|
||||
" TODO Make this pull on buffer open / load
|
||||
" Plug 'michal-h21/vimwiki-sync'
|
||||
|
||||
" --- Language specific ---
|
||||
" - All -
|
||||
Plug 'sheerun/vim-polyglot'
|
||||
" Integration with language servers but manual configuration
|
||||
Plug 'neoclide/coc.nvim', {'branch': 'release'}
|
||||
" Allows vim to configure filetype by file section (for svelte)
|
||||
Plug 'Shougo/context_filetype.vim'
|
||||
" Prettier
|
||||
Plug 'prettier/vim-prettier', {
|
||||
\ 'do': 'npm install',
|
||||
\ 'for': ['javascript', 'typescript', 'css', 'less', 'scss', 'json', 'graphql', 'markdown', 'vue', 'svelte', 'yaml', 'html'] }
|
||||
|
||||
" - Web -
|
||||
Plug 'mattn/emmet-vim'
|
||||
Plug 'mattn/webapi-vim'
|
||||
Plug 'cakebaker/scss-syntax.vim'
|
||||
|
||||
" - Python -
|
||||
" Plug 'klen/python-mode'
|
||||
" Plug 'davidhalter/jedi-vim'
|
||||
" Completion
|
||||
" Plug 'zchee/deoplete-jedi'
|
||||
|
||||
" - C# -
|
||||
" Omnicompletion and syntax
|
||||
" Plug 'OmniSharp/omnisharp-vim'
|
||||
|
||||
" - Rust -
|
||||
" Syntax and autocompletion
|
||||
" Plug 'rust-lang/rust.vim'
|
||||
" Plug 'phildawes/racer'
|
||||
|
||||
" - Javascript -
|
||||
Plug 'pangloss/vim-javascript'
|
||||
|
||||
" - Typescript -
|
||||
Plug 'HerringtonDarkholme/yats.vim'
|
||||
" TODO: Needs to be installed with `:CocInstall coc-tsserver`, figure out how
|
||||
" to config this
|
||||
" Plug 'coc-extensions/coc-tsserver'
|
||||
|
||||
" - Svelte
|
||||
" Plug 'evanleck/vim-svelte', {'branch': 'main'}
|
||||
Plug 'leafOfTree/vim-svelte-plugin'
|
||||
Plug 'coc-extensions/coc-svelte'
|
||||
|
||||
" - Processing -
|
||||
Plug 'sophacles/vim-processing'
|
||||
|
||||
" - Markdown -
|
||||
" Plug 'shime/vim-livedown'
|
||||
|
||||
|
||||
" --- Icons ---
|
||||
" For some reason this needs to be loaded last
|
||||
Plug 'ryanoasis/vim-devicons'
|
||||
|
||||
call plug#end()
|
||||
]])
|
||||
@@ -1,5 +1,5 @@
|
||||
let g:vim_plug_install_dir = "~/.local/share/nvim/site/autoload"
|
||||
let g:plugin_install_dir = "~/.local/share/nvim/plugged"
|
||||
let g:plugin_install_dir = "~/.vim/plugged"
|
||||
|
||||
" Install vim-plug if not present
|
||||
if empty(glob(g:vim_plug_install_dir . "/plug.vim"))
|
||||
@@ -39,9 +39,6 @@ Plug 'yggdroot/indentLine'
|
||||
" Better sessions
|
||||
Plug 'tpope/vim-obsession'
|
||||
|
||||
" - Generative AI -
|
||||
Plug 'David-Kunz/gen.nvim'
|
||||
|
||||
" - Ctags -
|
||||
" Ctags view
|
||||
Plug 'majutsushi/tagbar'
|
||||
@@ -119,7 +116,7 @@ Plug 'xolox/vim-reload'
|
||||
" Note taking and wiki managment
|
||||
Plug 'vimwiki/vimwiki'
|
||||
" TODO Why can't these go in Search?
|
||||
Plug 'junegunn/fzf'
|
||||
Plug 'junegunn/fzf', { 'do': { -> fzf#install() } }
|
||||
Plug 'junegunn/fzf.vim'
|
||||
Plug 'michal-h21/vim-zettel'
|
||||
" TODO Make this pull on buffer open / load
|
||||
@@ -176,6 +173,14 @@ Plug 'sophacles/vim-processing'
|
||||
|
||||
" - Markdown -
|
||||
" Plug 'shime/vim-livedown'
|
||||
" Plug 'iamcco/markdown-preview.nvim', { 'do': 'cd app && npx --yes yarn install' }
|
||||
Plug 'iamcco/markdown-preview.nvim', { 'do': { -> mkdp#util#install() }, 'for': ['markdown', 'vim-plug']}
|
||||
|
||||
" --- AI ---
|
||||
" Floating/split terminal windows used by claudecode.nvim
|
||||
Plug 'folke/snacks.nvim'
|
||||
" Claude Code integration
|
||||
Plug 'coder/claudecode.nvim'
|
||||
|
||||
|
||||
" --- Icons ---
|
||||
|
||||
@@ -1,333 +0,0 @@
|
||||
require('gen').setup({
|
||||
model = "phi",
|
||||
host = "10.0.2.11",
|
||||
port = "11434"
|
||||
})
|
||||
vim.cmd([[
|
||||
" Table of Contents
|
||||
" --- General ---
|
||||
" - Visual -
|
||||
" - Views -
|
||||
" -
|
||||
" TODO
|
||||
|
||||
" --- General ---
|
||||
" - Sessions -
|
||||
" Create new session optionally with given name. These show up in Startify
|
||||
command -nargs=? SessionNew :Obsess ~/.local/share/nvim/session/<args>
|
||||
command -nargs=0 SessionEnd :Obsess!
|
||||
command -nargs=1 SessionLoad :source ~/.local/share/nvim/session/<args>
|
||||
" TODO Could use g:startify_session_persistence and just rely on that
|
||||
|
||||
" - Visual -
|
||||
set background=dark
|
||||
let base16colorspace=256
|
||||
" let g:solarized_termtrans = 3
|
||||
|
||||
" Airline
|
||||
let g:airline_powerline_fonts=1
|
||||
" PERF: Could cause bad performance
|
||||
" let g:airline_skip_empty_sections=1
|
||||
let g:airline#extensions#tabline#enabled=1
|
||||
" Modify the statusbar if a recording is in session
|
||||
" TODO: This prevents some extensions (tagbar, virtualenv) from using the
|
||||
" section
|
||||
" TODO: Only if Obsession installed!
|
||||
let g:airline_section_x='%{ObsessionStatus("Session Recording |", "")} %{&filetype}'
|
||||
|
||||
" Gruvbox
|
||||
let g:gruvbox_italic=1
|
||||
let g:gruvbox_contrast_dark="medium"
|
||||
let g:gruvbox_contrast_light="soft"
|
||||
let g:gruvbox_invert_selection=1
|
||||
let g:gruvbox_invert_signs=0
|
||||
let g:gruvbox_improved_strings=0
|
||||
let g:gruvbox_improved_warnings=1
|
||||
let g:gruvbox_italicize_strings=1
|
||||
|
||||
" Rainbow parentheses
|
||||
" if exists('g:rainbow_conf')
|
||||
" augroup Rainbow_Parentheses
|
||||
" autocmd!
|
||||
" autocmd VimEnter * if exists('g:rainbow_conf') |
|
||||
" \ RainbowToggle |
|
||||
" \ endif
|
||||
" augroup END
|
||||
" endif
|
||||
|
||||
" - Views -
|
||||
" Startify
|
||||
let g:startify_bookmarks = [
|
||||
\"~/dotfiles/config/nvim/config/init.vimrc",
|
||||
\"~/dotfiles/config/nvim/config/general.vimrc",
|
||||
\"~/dotfiles/config/nvim/config/plugin.vimrc",
|
||||
\"~/dotfiles/config/nvim/config/bindings.vimrc",
|
||||
\"~/dotfiles/config/nvim/config/functions.vimrc",
|
||||
\"~/dotfiles/zshrc",
|
||||
\"~/dotfiles/config/i3/config"
|
||||
\]
|
||||
let g:startify_custom_indices = ['f', 'd', 's', 'a', 'g']
|
||||
let g:startify_custom_header = map(split(system('fortune -a -s | fmt -80 -s | cowthink -$(shuf -n 1 -e b d g p s t w y) -f $(shuf -n 1 -e $(cowsay -l | tail -n +2)) -n'), '\n'), '" ". v:val') + [","]
|
||||
" let g:startify_lists = [
|
||||
" \ { 'type': 'files', 'header': [' MRU'] },
|
||||
" \ { 'type': 'dir', 'header': [' MRU '. getcwd()] },
|
||||
" \ { 'type': 'sessions', 'header': [' Sessions'] },
|
||||
" \ { 'type': 'bookmarks', 'header': [' Bookmarks'] },
|
||||
" \ { 'type': 'commands', 'header': [' Commands'] },
|
||||
" \ ]
|
||||
|
||||
" Automatically open tagbar when entering supported buffer
|
||||
" autocmd BufEnter * nested :call tagbar#autoopen(0)
|
||||
|
||||
" - Generative AI -
|
||||
|
||||
" - Utility -
|
||||
" DelimitMate sane bracing
|
||||
let delimitMate_expand_cr = 1
|
||||
|
||||
" Indent Guide configuration
|
||||
" set ts=2 sw=2 et
|
||||
let g:indent_guides_enable_on_vim_startup = 0
|
||||
let g:indent_guides_start_level = 2
|
||||
let g:indent_guides_auto_colors = 0
|
||||
augroup Indent_Guides
|
||||
autocmd!
|
||||
autocmd VimEnter,Colorscheme * if exists('g:indentLine_loaded') |
|
||||
\ :hi IndentGuidesOdd ctermbg=darkgreen |
|
||||
\ endif
|
||||
autocmd VimEnter,Colorscheme * if exists('g:indentLine_loaded') |
|
||||
\ :hi IndentGuidesEven ctermbg=cyan |
|
||||
\ endif
|
||||
augroup END
|
||||
|
||||
" Indent Line configuration
|
||||
let g:indentLine_faster = 1
|
||||
" let g:indentLine_leadingSpaceEnabled = 1
|
||||
" let g:indentLine_leadingSpaceChar = '.'
|
||||
|
||||
" GitGutter
|
||||
let g:gitgutter_map_keys = 0
|
||||
|
||||
" NERD Commenter
|
||||
" let g:NERDMenuMode = 1
|
||||
|
||||
" NERD Tree
|
||||
" This causes an extra buffer to open when nvim starts
|
||||
" augroup DIRCHAANGE
|
||||
" au!
|
||||
" autocmd DirChanged global :NERDTreeCWD
|
||||
" augroup END
|
||||
|
||||
" Sort by modification date
|
||||
let NERDTreeSortOrder = ['[ [-timestamp] ]']
|
||||
|
||||
" Ctrl-P configuration
|
||||
" Use nearest version control directory as cwd
|
||||
let g:ctrlp_working_path_mode = 'r'
|
||||
|
||||
" Syntastic configuration
|
||||
let g:syntastic_aggregate_errors = 1
|
||||
|
||||
let g:syntastic_always_populate_loc_list = 1
|
||||
let g:syntastic_auto_loc_list = 1
|
||||
let g:syntastic_check_on_open = 1
|
||||
let g:syntastic_check_on_wq = 0
|
||||
let g:syntastic_mode_map = {
|
||||
\ "mode": "active",
|
||||
\ "passive_filetypes": ['asm', 'scss'] }
|
||||
|
||||
" YCM configuration
|
||||
let g:ycm_global_ycm_extra_conf = '~/dotfiles/.ycm_extra_conf.py'
|
||||
let g:ycm_extra_conf_globlist = ['~/dotfiles/.ycm_extra_conf.py']
|
||||
|
||||
let g:ycm_server_keep_logfiles = 1
|
||||
let g:ycm_server_log_level = 'debug'
|
||||
" let g:loaded_youcompleteme = 1
|
||||
" let g:ycm_min_num_of_chars_for_completion = 100
|
||||
let g:neobundle#install_process_timeout = 1500
|
||||
" nnoremap <leader><leader>zy :let g:ycm_auto_trigger=0<CR>
|
||||
" nnoremap <leader><leader>zY :let g:ycm_auto_trigger=1<CR>
|
||||
|
||||
" Powerline configuration
|
||||
let g:powerline_pycmd = "py"
|
||||
" let g:powerline_pyeval = "pyeval"
|
||||
|
||||
" Neotags configuration
|
||||
" let g:neotags_enabled = 1
|
||||
|
||||
" Vimwiki configuration
|
||||
let g:vimwiki_list = [
|
||||
\{'path': '~/synced-notebooks/bradwiki/', 'syntax': 'markdown', 'ext': '.md', 'diary_rel_path': 'daily_notes/', 'diary_index': 'index', 'diary_header': 'Daily Notes', 'auto_tags': 1, 'auto_diary_index': 1, 'auto_generate_links': 1, 'auto_generate_tags': 1},
|
||||
\{'path': '~/synced-notebooks/work_notebook/', 'syntax': 'markdown', 'ext': '.md', 'diary_rel_path': 'daily_notes/', 'diary_index': 'index', 'diary_header': 'Daily Notes', 'auto_tags': 1, 'auto_diary_index': 1, 'auto_generate_links': 1, 'auto_generate_tags': 1},
|
||||
\{'path': '~/synced-notebooks/privatewiki/', 'syntax': 'markdown', 'ext': '.md'},
|
||||
\{'path': '~/synced-notebooks/sharedwiki/', 'syntax': 'markdown', 'ext': '.md'}]
|
||||
let g:vimwiki_map_prefix = '<Leader>m'
|
||||
augroup filetype_vimwiki
|
||||
autocmd!
|
||||
" Wrap lines nicely
|
||||
autocmd Filetype vimwiki set breakindent
|
||||
autocmd Filetype vimwiki set breakindentopt=shift:2
|
||||
augroup END
|
||||
|
||||
" Vim-Zettel configuration
|
||||
let g:zettel_options = [{}, {"front_matter": [["tags", ""], ["type", "note"] ], "template": "~/work_notebook/templates/daily_note.tpl"}]
|
||||
|
||||
" Table Mode configuration
|
||||
let g:table_mode_map_prefix = '<Leader><Leader>t'
|
||||
|
||||
" --- Language Specific ---
|
||||
" - All -
|
||||
" let g:polyglot_disabled = ['python']
|
||||
|
||||
" COC
|
||||
" let g:coc_node_path = '$HOME/.nvm/versions/node/v12.16.3/bin/node'
|
||||
|
||||
set updatetime=300
|
||||
set shortmess+=c " don't give |ins-completion-menu| messages.
|
||||
|
||||
" - Svelte -
|
||||
let g:svelte_preprocessor_tags = [
|
||||
\ { 'name': "ts", 'tag': "script", 'as': "typescript" }
|
||||
\ ]
|
||||
let g:svelte_preprocessors = ["scss", "sass", "typescript", "ts"]
|
||||
let g:vim_svelte_plugin_load_full_syntax = 1
|
||||
let g:vim_svelte_plugin_use_sass = 1
|
||||
let g:vim_svelte_plugin_use_typescript = 1
|
||||
let g:vim_svelte_plugin_use_foldexpr = 0
|
||||
|
||||
if !exists('g:context_filetype#same_filetypes')
|
||||
let g:context_filetype#filetypes = {}
|
||||
endif
|
||||
|
||||
let g:context_filetype#filetypes.svelte =
|
||||
\ [
|
||||
\ {'filetype' : 'typescript', 'start': '<script\%( [^>]*\)\? \%(ts\|lang="\%(ts\|typescript\)"\)\%( [^>]*\)\?>', 'end': '</script>'},
|
||||
\ {'filetype' : 'javascript', 'start' : '<script \?.*>', 'end' : '</script>'},
|
||||
\ {'filetype' : 'scss', 'start' : '<style \?.*lang=''scss''>', 'end' : '</style>'},
|
||||
\ {'filetype' : 'sass', 'start' : '<style \?.*lang="sass">', 'end' : '</style>'},
|
||||
\ {'filetype' : 'css', 'start' : '<style \?.*>', 'end' : '</style>'},
|
||||
\ ]
|
||||
|
||||
let g:ft = ''
|
||||
|
||||
" For NERDCommenter
|
||||
let g:NERDSpaceDelims = 1
|
||||
" let g:NERDCompactSexyComs = 1
|
||||
|
||||
fu! NERDCommenter_before()
|
||||
if (&ft == 'html') || (&ft == 'svelte')
|
||||
let g:ft = &ft
|
||||
let cfts = context_filetype#get_filetypes()
|
||||
if len(cfts) > 0
|
||||
if cfts[0] == 'svelte'
|
||||
let cft = 'html'
|
||||
else
|
||||
let cft = cfts[0]
|
||||
endif
|
||||
echo "Using filetype=".cft." for comment"
|
||||
exe 'setf '.cft
|
||||
if exists('b:NERDCommenterDelims')
|
||||
unlet b:NERDCommenterDelims
|
||||
endif
|
||||
call nerdcommenter#SetUp()
|
||||
endif
|
||||
endif
|
||||
endfu
|
||||
|
||||
fu! NERDCommenter_after()
|
||||
if g:ft == 'svelte'
|
||||
exec 'setf '.g:ft
|
||||
if exists('b:NERDCommenterDelims')
|
||||
unlet b:NERDCommenterDelims
|
||||
endif
|
||||
call nerdcommenter#SetUp()
|
||||
let g:ft = ''
|
||||
endif
|
||||
endfu
|
||||
|
||||
" Prettier
|
||||
let g:prettier#quickfix_enabled = 0
|
||||
let g:prettier#autoformat_require_pragma = 0
|
||||
au BufWritePre *.css,*.svelte,*.pcss,*.html,*.ts,*.js,*.json PrettierAsync
|
||||
|
||||
" - Web -
|
||||
let g:user_emmet_install_global=0
|
||||
augroup Emmet
|
||||
autocmd!
|
||||
autocmd Filetype html,css if exists('g:loaded_emmet_vim') |
|
||||
\ EmmetInstall |
|
||||
\ endif
|
||||
augroup END
|
||||
" let g:user_emmet_leader_key='<localleader>'
|
||||
|
||||
" - Javascript -
|
||||
" Javascript configuration
|
||||
let g:javascript_enable_dom_htmlcss = 1
|
||||
|
||||
" - Python -
|
||||
" Run in python using F9
|
||||
augroup Python
|
||||
autocmd!
|
||||
autocmd FileType python nnoremap <buffer> <F9> :exec '!python' shellescape(@%, 1)<cr>
|
||||
augroup END
|
||||
|
||||
" Documentation
|
||||
let g:pymode_doc = 1
|
||||
let g:pymode_doc_key = 'K'
|
||||
|
||||
" Linting
|
||||
let g:pymode_lint = 1
|
||||
let g:pymode_lint_checkers = ['pyflakes', 'pep8']
|
||||
let g:pymode_lint_message = 1
|
||||
|
||||
" Auto check on save
|
||||
let g:pymode_lint_write = 1
|
||||
|
||||
" Support virtualenv
|
||||
let g:pymode_virtualenv = 1
|
||||
|
||||
" Enable breakpoints plugin
|
||||
let g:pymode_breakpoint = 1
|
||||
let g:pymode_breakpoint_bind = '<localleader>b'
|
||||
|
||||
" Syntax highlighting
|
||||
let g:pymode_syntax = 1
|
||||
let g:pymode_syntax_all = 1
|
||||
let g:pymode_syntax_indent_errors = g:pymode_syntax_all
|
||||
let g:pymode_syntax_space_errors = g:pymode_syntax_all
|
||||
|
||||
" Enable python folding
|
||||
let g:pymode_folding = 1
|
||||
|
||||
" Enable pymode motion
|
||||
let g:pymode_motion = 1
|
||||
|
||||
" Set up default python options
|
||||
let g:pymode_options = 1
|
||||
|
||||
" Trim whitespace on save
|
||||
let g:pymode_trim_whitespaces = 1
|
||||
|
||||
" PEP8-compatible python indent
|
||||
" let g:pymode_indent = 1
|
||||
|
||||
" Rope support
|
||||
let g:pymode_rope = 0
|
||||
|
||||
" [YELP] Ignore line too long
|
||||
let g:pymode_lint_ignore = "W503,E128"
|
||||
|
||||
" - Rust -
|
||||
" Rust racer
|
||||
let g:racer_cmd = "~/dotfiles/racer/target/release/racer"
|
||||
" Must install Rust source to this location first
|
||||
let $RUST_SRC_PATH="/usr/local/src/rust/src/"
|
||||
" Rust folding
|
||||
let g:rust_fold = 2
|
||||
|
||||
" - Processing -
|
||||
let g:processing_fold = 1
|
||||
|
||||
" - Markdown -
|
||||
let g:livedown_open = 1
|
||||
]])
|
||||
@@ -73,8 +73,6 @@ let g:startify_custom_header = map(split(system('fortune -a -s | fmt -80 -s | co
|
||||
" Automatically open tagbar when entering supported buffer
|
||||
" autocmd BufEnter * nested :call tagbar#autoopen(0)
|
||||
|
||||
" - Generative AI -
|
||||
|
||||
" - Utility -
|
||||
" DelimitMate sane bracing
|
||||
let delimitMate_expand_cr = 1
|
||||
@@ -175,6 +173,7 @@ let g:table_mode_map_prefix = '<Leader><Leader>t'
|
||||
|
||||
" COC
|
||||
" let g:coc_node_path = '$HOME/.nvm/versions/node/v12.16.3/bin/node'
|
||||
let g:coc_disable_startup_warning = 1
|
||||
|
||||
set updatetime=300
|
||||
set shortmess+=c " don't give |ins-completion-menu| messages.
|
||||
@@ -323,4 +322,22 @@ let g:rust_fold = 2
|
||||
let g:processing_fold = 1
|
||||
|
||||
" - Markdown -
|
||||
" Livedown
|
||||
let g:livedown_open = 1
|
||||
" Markdown Preview
|
||||
|
||||
" --- AI ---
|
||||
" Claude Code
|
||||
" plugin/claudecode.lua auto-calls require('claudecode').setup(g:claudecode_auto_setup)
|
||||
" once the plugin loads (during plug#end() below), so this must be a plain
|
||||
" vimscript dict rather than a lua block -- see the guarded keymaps in
|
||||
" bindings.vimrc for the commands this enables.
|
||||
" Full option list: https://github.com/coder/claudecode.nvim#configuration-options
|
||||
let g:claudecode_auto_setup = {
|
||||
\ 'terminal': {
|
||||
\ 'provider': 'snacks',
|
||||
\ 'split_side': 'right',
|
||||
\ 'split_width_percentage': 0.30,
|
||||
\ },
|
||||
\ }
|
||||
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
vim.bo.textwidth = 79
|
||||
if vim.bo.modifiable then
|
||||
vim.bo.fileformat = "unix"
|
||||
end
|
||||
@@ -0,0 +1,36 @@
|
||||
local map = function(mode, lhs, rhs)
|
||||
vim.keymap.set(mode, lhs, rhs, { buffer = true })
|
||||
end
|
||||
|
||||
map("n", "<leader>mm", "<Plug>VimwikiIndex")
|
||||
map("n", "<leader>mw", "<Plug>VimwikiUISelect")
|
||||
map("n", "<leader>mhelp", ":verbose map ,m<CR>")
|
||||
map("n", "<leader>mg", "<Plug>VimwikiGoto")
|
||||
map("n", "<leader>mf", "<Plug>VimwikiUISelect1<CR>")
|
||||
map("n", "<leader>m<Space>", "<Plug>VimwikiUISelect2<CR>")
|
||||
map("n", "<leader>mp", "<Plug>VimwikiUISelect3<CR>")
|
||||
map("n", "<leader>ms", "<Plug>VimwikiUISelect4<CR>")
|
||||
|
||||
map("n", "<leader>m-", "<Plug>VimwikiSplitLink")
|
||||
map("n", "<leader>m<Bar>", "<Plug>VimwikiVSplitLink")
|
||||
|
||||
map("n", "<leader>mnt", "<Plug>VimwikiNextTask")
|
||||
map("n", "<leader>mnl", "<Plug>VimwikiNextLink")
|
||||
map("n", "<leader>mNl", "<Plug>VimwikiPrevLink")
|
||||
|
||||
map({ "n", "i", "v" }, "<Tab>", "<Plug>VimwikiIncreaseLvlSingleItem")
|
||||
map({ "n", "i", "v" }, "<S-Tab>", "<Plug>VimwikiDecreaseLvlSingleItem")
|
||||
|
||||
map("i", "<C-Space>", "<Esc><Plug>VimwikiToggleListItemA")
|
||||
map("n", "<C-d><C-Space>", "<Plug>VimwikiRemoveSingleCB")
|
||||
map("i", "<C-d><C-Space>", "<Esc><Plug>VimwikiRemoveSingleCBa")
|
||||
map("n", "<leader>mb", "<Plug>VimwikiBackLinks")
|
||||
map("n", "<leader>mqtoc", "<Plug>VimwikiTOC")
|
||||
map("n", "<leader>mqgtl", "<Plug>VimwikiRebuildTags<CR><Plug>VimwikiGenerateTagLinks<CR>")
|
||||
|
||||
map("v", "<leader>mk", 'c[]<Esc>Pea()<Esc>"+P')
|
||||
map("i", "<leader>mk", '<Esc>viW<C-k>ea')
|
||||
map("n", "<leader>mk", 'ciw[]<Esc>Pea()<Esc>"+P')
|
||||
|
||||
map("n", "<leader>mag", ":ZettelOpen<CR>")
|
||||
map("n", "<leader>mat", ":ZettelOpen<CR>title:")
|
||||
+89
-17
@@ -1,19 +1,91 @@
|
||||
vim.cmd([[
|
||||
" -- Source config files
|
||||
source $HOME/.config/nvim/config/bindings-vimwiki.vimrc
|
||||
source $HOME/.config/nvim/config/init.vimrc
|
||||
source $HOME/.config/nvim/config/plugin.vimrc
|
||||
source $HOME/.config/nvim/config/general.vimrc
|
||||
source $HOME/.config/nvim/config/bindings.vimrc
|
||||
source $HOME/.config/nvim/config/functions.vimrc
|
||||
-- Version guard: native LSP config (vim.lsp.config/vim.lsp.enable, added in
|
||||
-- 0.11) and the pinned nvim-treesitter (hard-requires 0.12 in its own health
|
||||
-- check) both need a current Neovim. Older versions -- e.g. Debian's apt
|
||||
-- package, which lags upstream by a long way even fully updated -- don't
|
||||
-- fail here; they fail later with a confusing cascade of lspconfig and
|
||||
-- mason-lspconfig errors. Check up front instead, before anything else in
|
||||
-- this file runs (some of it, like vim.uv below, doesn't exist pre-0.10).
|
||||
if vim.fn.has("nvim-0.12") == 0 then
|
||||
local ok, v = pcall(vim.version)
|
||||
local current = ok and string.format("%d.%d.%d", v.major, v.minor, v.patch) or "an older version"
|
||||
|
||||
" -- Python dependencies
|
||||
let g:python_host_prog = expand("~/.pyenv/versions/neovim2/bin/python")
|
||||
let g:python3_host_prog = expand("~/.pyenv/versions/neovim3/bin/python")
|
||||
-- vim.loop (not vim.uv -- that alias doesn't exist pre-0.10) to detect the
|
||||
-- machine's arch, since Neovim ships separate release assets per arch and
|
||||
-- the install command below needs to name the right one.
|
||||
local machine = (vim.loop.os_uname() or {}).machine or ""
|
||||
local asset_arch = ({ x86_64 = "x86_64", amd64 = "x86_64", aarch64 = "arm64", arm64 = "arm64" })[machine]
|
||||
|
||||
" -- Local overrides
|
||||
let $LOCALFILE=expand("$HOME/.nvim_local.vimrc")
|
||||
if filereadable($LOCALFILE)
|
||||
source $LOCALFILE
|
||||
endif
|
||||
]])
|
||||
if not asset_arch then
|
||||
vim.api.nvim_echo({
|
||||
{
|
||||
"This config requires Neovim 0.12.0 or newer (found "
|
||||
.. current
|
||||
.. "). No prebuilt Neovim release is published for this machine's architecture ("
|
||||
.. (machine ~= "" and machine or "unknown")
|
||||
.. "); check https://github.com/neovim/neovim/releases/latest for a build, or install from source.\n",
|
||||
"ErrorMsg",
|
||||
},
|
||||
}, true, {})
|
||||
vim.fn.getchar()
|
||||
os.exit(1)
|
||||
end
|
||||
|
||||
local sysname = ((vim.loop.os_uname() or {}).sysname or ""):lower()
|
||||
local is_mac = sysname == "darwin"
|
||||
local asset = (is_mac and "nvim-macos-" or "nvim-linux-") .. asset_arch
|
||||
|
||||
local lines = {
|
||||
{ "This config requires Neovim 0.12.0 or newer (found " .. current .. ", " .. machine .. ").\n\n", "ErrorMsg" },
|
||||
{ "Install a current build into ~/.local (no root needed):\n", "None" },
|
||||
{ " curl -LO https://github.com/neovim/neovim/releases/latest/download/" .. asset .. ".tar.gz\n", "None" },
|
||||
{ " mkdir -p ~/.local && tar xzf " .. asset .. ".tar.gz --strip-components=1 -C ~/.local\n", "None" },
|
||||
{ " rm " .. asset .. ".tar.gz\n", "None" },
|
||||
{ " # then make sure ~/.local/bin is on your PATH\n\n", "Comment" },
|
||||
}
|
||||
if not is_mac then
|
||||
vim.list_extend(lines, {
|
||||
{ "Or system-wide (needs root):\n", "None" },
|
||||
{ " curl -LO https://github.com/neovim/neovim/releases/latest/download/" .. asset .. ".tar.gz\n", "None" },
|
||||
{ " sudo mkdir -p /opt/nvim && sudo tar xzf " .. asset .. ".tar.gz --strip-components=1 -C /opt/nvim\n", "None" },
|
||||
{ " sudo ln -sf /opt/nvim/bin/nvim /usr/local/bin/nvim\n", "None" },
|
||||
{ " rm " .. asset .. ".tar.gz\n", "None" },
|
||||
})
|
||||
end
|
||||
vim.api.nvim_echo(lines, true, {})
|
||||
vim.fn.getchar()
|
||||
os.exit(1)
|
||||
end
|
||||
|
||||
-- Leader keys MUST be set before lazy.setup() so lazy-loaded `keys = {...}`
|
||||
-- specs resolve <leader> correctly when they register their keymaps.
|
||||
vim.g.mapleader = ","
|
||||
vim.g.maplocalleader = "\\"
|
||||
|
||||
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
|
||||
if not vim.uv.fs_stat(lazypath) then
|
||||
local out = vim.fn.system({
|
||||
"git",
|
||||
"clone",
|
||||
"--filter=blob:none",
|
||||
"https://github.com/folke/lazy.nvim.git",
|
||||
"--branch=stable",
|
||||
lazypath,
|
||||
})
|
||||
if vim.v.shell_error ~= 0 then
|
||||
vim.api.nvim_echo({
|
||||
{ "Failed to clone lazy.nvim:\n", "ErrorMsg" },
|
||||
{ out, "WarningMsg" },
|
||||
}, true, {})
|
||||
vim.fn.getchar()
|
||||
os.exit(1)
|
||||
end
|
||||
end
|
||||
vim.opt.rtp:prepend(lazypath)
|
||||
|
||||
require("config.options")
|
||||
require("config.keymaps")
|
||||
require("config.autocmds")
|
||||
|
||||
require("lazy").setup("plugins", {
|
||||
change_detection = { notify = false },
|
||||
})
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"aerial.nvim": { "branch": "master", "commit": "28fe6e822ae344544c379d60fcb13c9519a1f08a" },
|
||||
"alpha-nvim": { "branch": "main", "commit": "6c6a89d5b068b5251c8bdf0dd57bb921bcfeeb09" },
|
||||
"blink.cmp": { "branch": "main", "commit": "78336bc89ee5365633bcf754d93df01678b5c08f" },
|
||||
"blink.lib": { "branch": "main", "commit": "5876dd95deeb70aadbe9f1c0b7117a135061cdac" },
|
||||
"bufferline.nvim": { "branch": "main", "commit": "655133c3b4c3e5e05ec549b9f8cc2894ac6f51b3" },
|
||||
"claudecode.nvim": { "branch": "main", "commit": "2390c6e45c4789072c293ac69de051d169668b29" },
|
||||
"conform.nvim": { "branch": "master", "commit": "619363c30309d29ffa631e67c8183f2a72caa373" },
|
||||
"emmet-vim": { "branch": "master", "commit": "92ef2f74f4093edc99db5e9e4cf7e40116a85bd6" },
|
||||
"flash.nvim": { "branch": "main", "commit": "fcea7ff883235d9024dc41e638f164a450c14ca2" },
|
||||
"gitsigns.nvim": { "branch": "main", "commit": "eb60cc7b94c46005237fd34170d76f3a089a90aa" },
|
||||
"gruvbox.nvim": { "branch": "main", "commit": "154eb5ff5b96d0641307113fa385eaf0d36d9796" },
|
||||
"indent-blankline.nvim": { "branch": "master", "commit": "d28a3f70721c79e3c5f6693057ae929f3d9c0a03" },
|
||||
"lazy.nvim": { "branch": "main", "commit": "85c7ff3711b730b4030d03144f6db6375044ae82" },
|
||||
"lualine.nvim": { "branch": "master", "commit": "221ce6b2d999187044529f49da6554a92f740a96" },
|
||||
"markdown-preview.nvim": { "branch": "master", "commit": "a923f5fc5ba36a3b17e289dc35dc17f66d0548ee" },
|
||||
"mason-lspconfig.nvim": { "branch": "main", "commit": "47059d71b42d74b0a1e9f61c1d99d301039c3b5b" },
|
||||
"mason.nvim": { "branch": "main", "commit": "2a6940af80375532e5e9e7c1f2fc6319a1b7a69d" },
|
||||
"mini.align": { "branch": "main", "commit": "8cebe89d82f20e6d21b27346bcde4b4b6244a9f1" },
|
||||
"mini.bufremove": { "branch": "main", "commit": "4cfbb201b2760da79ca6e1a00e9f67cbc99cbb8f" },
|
||||
"neo-tree.nvim": { "branch": "v3.x", "commit": "ebd66767191714e008ce73b769518a763ff31bdc" },
|
||||
"nui.nvim": { "branch": "main", "commit": "de740991c12411b663994b2860f1a4fd0937c130" },
|
||||
"nvim-autopairs": { "branch": "master", "commit": "7b9923abad60b903ece7c52940e1321d39eccc79" },
|
||||
"nvim-dap": { "branch": "master", "commit": "9e848e09a697ee95302a3ef2dd43fd6eb709e570" },
|
||||
"nvim-dap-python": { "branch": "master", "commit": "1808458eba2b18f178f990e01376941a42c7f93b" },
|
||||
"nvim-lint": { "branch": "master", "commit": "a219b2c9e5b4765e5c845aba119dad55806fcaf1" },
|
||||
"nvim-lspconfig": { "branch": "master", "commit": "d224a1920728ba129880efc700d4a0180ac4ecbb" },
|
||||
"nvim-surround": { "branch": "main", "commit": "8b47db616ef658b8fc27e61db2896aa2f40134de" },
|
||||
"nvim-treesitter": { "branch": "main", "commit": "4916d6592ede8c07973490d9322f187e07dfefac" },
|
||||
"nvim-treesitter-context": { "branch": "master", "commit": "b311b30818951d01f7b4bf650521b868b3fece16" },
|
||||
"nvim-web-devicons": { "branch": "master", "commit": "dad71387de386a946b123079d0e53f23028f3abd" },
|
||||
"persistence.nvim": { "branch": "main", "commit": "b20b2a7887bd39c1a356980b45e03250f3dce49c" },
|
||||
"plenary.nvim": { "branch": "master", "commit": "74b06c6c75e4eeb3108ec01852001636d85a932b" },
|
||||
"rainbow-delimiters.nvim": { "branch": "master", "commit": "a798325b7f36acc62741d1029930a7b96d4dd4bf" },
|
||||
"rustaceanvim": { "branch": "main", "commit": "88575b98bb9937fb9983ddec5e532b67e75ce677" },
|
||||
"snacks.nvim": { "branch": "main", "commit": "882c996cf28183f4d63640de0b4c02ec886d01f2" },
|
||||
"telescope-fzf-native.nvim": { "branch": "main", "commit": "b25b749b9db64d375d782094e2b9dce53ad53a40" },
|
||||
"telescope.nvim": { "branch": "master", "commit": "427b576c16792edad01a92b89721d923c19ad60f" },
|
||||
"undotree": { "branch": "main", "commit": "02b69aed427b848c4dca483fc5e9524b6019c296" },
|
||||
"vim-fugitive": { "branch": "master", "commit": "3b753cf8c6a4dcde6edee8827d464ba9b8c4a6f0" },
|
||||
"vim-table-mode": { "branch": "master", "commit": "bb025308a45c67c7c8f0763ba37bc2ee3f534df0" },
|
||||
"vim-tmux-navigator": { "branch": "master", "commit": "e41c431a0c7b7388ae7ba341f01a0d217eb3a432" },
|
||||
"vim-visual-multi": { "branch": "master", "commit": "a6975e7c1ee157615bbc80fc25e4392f71c344d4" },
|
||||
"vim-zettel": { "branch": "master", "commit": "554d16bf65b04ae86b92db08a44b4fbcbc31023f" },
|
||||
"vimwiki": { "branch": "dev", "commit": "a54a3002e229c4b43d69ced170ff77663a5b2c40" },
|
||||
"which-key.nvim": { "branch": "main", "commit": "3aab2147e74890957785941f0c1ad87d0a44c15a" }
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
-- autoread (options.lua) only reloads a buffer once Vim checks the file's
|
||||
-- timestamp, which by default only happens on a handful of internal
|
||||
-- triggers. Force that check on focus/buffer-switch/idle so external edits
|
||||
-- (e.g. from claudecode.nvim) show up immediately instead of surfacing the
|
||||
-- stale-buffer prompt later.
|
||||
vim.api.nvim_create_autocmd({ "FocusGained", "BufEnter", "CursorHold", "CursorHoldI" }, {
|
||||
group = vim.api.nvim_create_augroup("CheckTimeOnFocus", { clear = true }),
|
||||
callback = function()
|
||||
if vim.fn.getcmdwintype() == "" then
|
||||
vim.cmd("checktime")
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
local augroup = vim.api.nvim_create_augroup("EnterBuffer", { clear = true })
|
||||
|
||||
vim.api.nvim_create_autocmd({ "BufNewFile", "BufReadPre", "FileReadPre", "BufEnter" }, {
|
||||
group = augroup,
|
||||
pattern = "Makefile",
|
||||
callback = function()
|
||||
vim.bo.expandtab = false
|
||||
vim.bo.softtabstop = 0
|
||||
vim.bo.shiftwidth = 8
|
||||
end,
|
||||
})
|
||||
|
||||
vim.api.nvim_create_autocmd({ "BufNewFile", "BufReadPre", "FileReadPre", "BufEnter" }, {
|
||||
group = augroup,
|
||||
pattern = { "*.asm", "*.S" },
|
||||
callback = function()
|
||||
vim.bo.softtabstop = 8
|
||||
vim.bo.shiftwidth = 8
|
||||
end,
|
||||
})
|
||||
|
||||
-- dejima sets DEJIMA, never present on a normal host session, so this only
|
||||
-- fires inside the sandbox: open claudecode.nvim's terminal on startup
|
||||
-- rather than requiring <leader>ac, since starting a Claude session is the
|
||||
-- entire point of being in there.
|
||||
-- :ClaudeCode is defined by the plugin itself, so it doesn't exist until
|
||||
-- claudecode.nvim has actually loaded - it's lazy-loaded on the <leader>ac
|
||||
-- keymap only (no `cmd` in its lazy.nvim spec), so force that load first.
|
||||
if vim.env.DEJIMA then
|
||||
vim.api.nvim_create_autocmd("VimEnter", {
|
||||
once = true,
|
||||
callback = function()
|
||||
vim.schedule(function()
|
||||
require("lazy").load({ plugins = { "claudecode.nvim" } })
|
||||
vim.cmd("ClaudeCode")
|
||||
-- :ClaudeCode leaves the terminal window focused, so `tab split` gives
|
||||
-- the same terminal buffer a full-screen window in its own tab while
|
||||
-- the original tab keeps the narrow split next to the editor - one tab
|
||||
-- to work in Claude, one to work side-by-side. Window-local options are
|
||||
-- inherited by the split, and snacks' auto_insert (buffer-local) puts
|
||||
-- the new window back into terminal mode on entry.
|
||||
local claude_buf = require("claudecode.terminal").get_active_terminal_bufnr()
|
||||
if claude_buf and vim.api.nvim_get_current_buf() == claude_buf then
|
||||
vim.cmd("tab split")
|
||||
end
|
||||
end)
|
||||
end,
|
||||
})
|
||||
end
|
||||
@@ -0,0 +1,59 @@
|
||||
local map = vim.keymap.set
|
||||
|
||||
-- Insert/command-mode escape via ,,
|
||||
map("i", ",,", "<Esc>", { desc = "Escape insert mode" })
|
||||
map("c", ",,", "<Esc><Esc>", { desc = "Escape command mode" })
|
||||
-- Terminal mode is a separate mode from Insert, so the above doesn't cover
|
||||
-- it (e.g. the Claude Code terminal). <C-\><C-n> is the real escape back to
|
||||
-- Normal mode there.
|
||||
map("t", ",,", "<C-\\><C-n>", { desc = "Escape terminal mode" })
|
||||
|
||||
-- Move by display line, not physical line
|
||||
map("n", "j", "gj", { desc = "Move down by display line" })
|
||||
map("n", "k", "gk", { desc = "Move up by display line" })
|
||||
|
||||
-- Clear search highlight
|
||||
map("n", "<leader><leader><Esc>", ":nohl<CR>", { desc = "Clear search highlight" })
|
||||
|
||||
-- Hex mode
|
||||
map("n", "<leader>\\he", ":%!xxd<CR>", { desc = "Hex dump buffer" })
|
||||
map("n", "<leader>\\hd", ":%!xxd -r<CR>", { desc = "Undo hex dump" })
|
||||
|
||||
-- Toggle whitespace display
|
||||
map("n", "<leader><leader>lw", ":set list!<CR>", { desc = "Toggle whitespace display" })
|
||||
-- List registers / marks
|
||||
map("n", "<leader><leader>lr", ":reg<CR>", { desc = "List registers" })
|
||||
map("n", "<leader><leader>lm", ":marks<CR>", { desc = "List marks" })
|
||||
|
||||
-- Prev/next buffer
|
||||
map("n", "<leader>q", ":bp<CR>", { desc = "Previous buffer" })
|
||||
map("n", "<leader>w", ":bn<CR>", { desc = "Next buffer" })
|
||||
|
||||
-- System clipboard
|
||||
map({ "n", "v" }, "<leader>y", '"+y', { desc = "Yank to system clipboard" })
|
||||
map({ "n", "v" }, "<leader>Y", '"+Y', { desc = "Yank line to system clipboard" })
|
||||
map({ "n", "v" }, "<leader>p", '"+p', { desc = "Paste from system clipboard" })
|
||||
map({ "n", "v" }, "<leader>P", '"+P', { desc = "Paste before from system clipboard" })
|
||||
map({ "n", "v" }, "<leader>x", '"+x', { desc = "Cut to system clipboard" })
|
||||
map("n", "<leader>dd", '"+dd', { desc = "Delete line to system clipboard" })
|
||||
|
||||
-- Make split
|
||||
map("n", "<leader>-", ":sp<Space>", { desc = "Horizontal split" })
|
||||
map("n", "<leader><Bar>", ":vsp<Space>", { desc = "Vertical split" })
|
||||
|
||||
-- Open init.lua
|
||||
map("n", "<leader>v", ":e $MYVIMRC<CR>", { desc = "Edit init.lua" })
|
||||
|
||||
-- Low-light / daylight mode
|
||||
map("n", "<leader><leader>ll", ":set background=dark<CR>", { desc = "Dark background" })
|
||||
map("n", "<leader><leader>LL", ":set background=light<CR>", { desc = "Light background" })
|
||||
|
||||
-- Ranger / trailing whitespace utilities
|
||||
map("n", "<leader>ra", function() require("util").ranger() end, { desc = "Open ranger" })
|
||||
map("n", "<leader>rw", function() require("util").delete_trailing_ws() end, { desc = "Delete trailing whitespace" })
|
||||
|
||||
-- Terminal-mode Ctrl-Z otherwise goes straight to the embedded process (e.g.
|
||||
-- suspending the claude CLI inside claudecode.nvim's terminal with no way to
|
||||
-- fg it back) instead of suspending Neovim itself, like Ctrl-Z does by
|
||||
-- default in Normal mode.
|
||||
map("t", "<C-z>", "<C-\\><C-n><C-z>", { desc = "Suspend Neovim" })
|
||||
@@ -0,0 +1,94 @@
|
||||
local opt = vim.opt
|
||||
|
||||
-- Completion / buffers
|
||||
opt.omnifunc = "syntaxcomplete#Complete"
|
||||
opt.hidden = true
|
||||
opt.autoread = true
|
||||
|
||||
-- No swap/backup files
|
||||
opt.swapfile = false
|
||||
opt.backup = false
|
||||
|
||||
opt.number = true
|
||||
|
||||
-- matchit is built into Neovim's runtime already; no `runtime macros/matchit.vim` needed
|
||||
|
||||
opt.encoding = "utf-8"
|
||||
opt.lazyredraw = true
|
||||
opt.backspace = { "indent", "eol", "start" }
|
||||
opt.history = 700
|
||||
opt.incsearch = true
|
||||
opt.ignorecase = true
|
||||
opt.smartcase = true
|
||||
opt.scrolloff = 15
|
||||
|
||||
opt.wildmode = { "longest", "list", "full" }
|
||||
opt.wildmenu = true
|
||||
opt.wildcharm = vim.api.nvim_replace_termcodes("<C-Z>", true, true, true):byte()
|
||||
|
||||
opt.mouse = "a"
|
||||
|
||||
-- Tabs
|
||||
opt.tabstop = 4
|
||||
opt.softtabstop = 4
|
||||
opt.expandtab = true
|
||||
opt.shiftwidth = 4
|
||||
|
||||
opt.wrap = true
|
||||
opt.linebreak = true
|
||||
opt.list = false
|
||||
|
||||
opt.ruler = true
|
||||
opt.showmatch = true
|
||||
|
||||
opt.viewoptions:remove("options")
|
||||
|
||||
opt.shortmess:append("I")
|
||||
|
||||
opt.laststatus = 2
|
||||
opt.showmode = false
|
||||
|
||||
opt.termguicolors = true
|
||||
vim.g.enable_bold_font = 1
|
||||
|
||||
-- Have vrm extend background color to full terminal screen
|
||||
vim.cmd("set t_ut=")
|
||||
|
||||
opt.splitbelow = true
|
||||
opt.splitright = true
|
||||
|
||||
opt.updatetime = 300
|
||||
opt.shortmess:append("c")
|
||||
|
||||
-- Clipboard: copy-only, via dotfiles/bin/clipboard-copy. This is a small
|
||||
-- script (rather than nvim's built-in raw-OSC-52-only provider) because
|
||||
-- reaching the real clipboard needs more than a raw OSC 52 write: it picks
|
||||
-- pbcopy/xclip/wl-copy when nvim is running locally, and when none of those
|
||||
-- are available (nvim on a remote host with no local display) sends a
|
||||
-- single plain OSC 52 write. Any tmux hops between here and the real
|
||||
-- terminal relay that onward themselves via the pane-set-clipboard hook in
|
||||
-- tmux.conf, so this works whether nvim is local or several ssh/tmux hops
|
||||
-- deep, on any machine sharing this dotfiles repo, without needing to know
|
||||
-- how many hops there are. Paste is intentionally left as a no-op: OSC 52
|
||||
-- read support is inconsistent across terminals and can hang waiting for a
|
||||
-- reply, so use the terminal's own native paste (e.g. Ctrl-Shift-V)
|
||||
-- instead. Guarded on executable() rather than assumed present - not every
|
||||
-- machine this config runs on has the rest of dotfiles checked out too
|
||||
-- (e.g. dejima mounts in only this nvim config directory), and
|
||||
-- without the guard vim.g.clipboard would point at a script that isn't
|
||||
-- there, erroring on every yank instead of just falling back to nvim's
|
||||
-- default clipboard handling.
|
||||
local clipboard_copy = vim.fn.expand("~/dotfiles/bin/clipboard-copy")
|
||||
if vim.fn.executable(clipboard_copy) == 1 then
|
||||
vim.g.clipboard = {
|
||||
name = "clipboard-copy (copy-only)",
|
||||
copy = {
|
||||
["+"] = { clipboard_copy },
|
||||
["*"] = { clipboard_copy },
|
||||
},
|
||||
paste = {
|
||||
["+"] = function() return {} end,
|
||||
["*"] = function() return {} end,
|
||||
},
|
||||
}
|
||||
end
|
||||
@@ -0,0 +1,104 @@
|
||||
return {
|
||||
{ "folke/snacks.nvim", lazy = false },
|
||||
|
||||
{
|
||||
"coder/claudecode.nvim",
|
||||
dependencies = { "folke/snacks.nvim" },
|
||||
opts = {
|
||||
terminal = {
|
||||
provider = "snacks",
|
||||
split_side = "right",
|
||||
split_width_percentage = 0.30,
|
||||
-- snacks.nvim's terminal style binds a double-<Esc>-within-200ms
|
||||
-- shortcut (term_normal) that silently drops the buffer out of
|
||||
-- terminal-mode into Neovim's own Normal mode -- swallowing the
|
||||
-- second Esc instead of forwarding it to the claude CLI, which uses
|
||||
-- double-Esc itself (e.g. to rewind/interrupt). Once stuck in Normal
|
||||
-- mode there (invisible, since showmode is off), the next keystroke
|
||||
-- meant for the CLI -- e.g. Ctrl-O to toggle expanded tool output --
|
||||
-- is instead consumed by Neovim's built-in Normal-mode <C-o> (jump
|
||||
-- to older jumplist position), yanking focus to a different window.
|
||||
-- Disabling this shortcut makes every Esc pass through raw to the
|
||||
-- CLI; ,, (config/keymaps.lua) remains the deliberate way to reach
|
||||
-- Normal mode in this terminal.
|
||||
snacks_win_opts = {
|
||||
keys = {
|
||||
term_normal = false,
|
||||
-- Per :help terminal-mode, when the running program hasn't enabled
|
||||
-- its own mouse reporting (the claude CLI doesn't), any mouse event
|
||||
-- over the terminal -- including the scroll wheel -- drops terminal
|
||||
-- focus to Neovim's Normal mode instead of being forwarded, leaving
|
||||
-- you stuck there (invisibly, since showmode is off) until you press
|
||||
-- 'i' again -- and clicks meant for the CLI (e.g. approval prompts)
|
||||
-- land as buffer-cursor movement in the meantime. Intercept the
|
||||
-- wheel so it scrolls the window and silently returns to terminal
|
||||
-- mode, instead of leaving that to the default behavior.
|
||||
scroll_up = {
|
||||
"<ScrollWheelUp>",
|
||||
"<C-\\><C-n><ScrollWheelUp>i",
|
||||
mode = "t",
|
||||
desc = "Scroll up without leaving terminal mode",
|
||||
},
|
||||
scroll_down = {
|
||||
"<ScrollWheelDown>",
|
||||
"<C-\\><C-n><ScrollWheelDown>i",
|
||||
mode = "t",
|
||||
desc = "Scroll down without leaving terminal mode",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
diff_opts = {
|
||||
keep_terminal_focus = true,
|
||||
-- Unified (single-buffer, VS Code-style) diff instead of side-by-side
|
||||
-- splits: it only ever opens one new window, so it can't add a second
|
||||
-- split and squish the rest of the layout the way the side-by-side
|
||||
-- diff sometimes did.
|
||||
layout = "unified",
|
||||
},
|
||||
},
|
||||
config = function(_, opts)
|
||||
require("claudecode").setup(opts)
|
||||
|
||||
-- claudecode picks a window for the diff by scanning all windows for the
|
||||
-- first non-sidebar/non-terminal one, not the one you're actually
|
||||
-- focused on, so the diff could land away from your active pane. Prefer
|
||||
-- the current window when it's a normal editing window.
|
||||
local diff = require("claudecode.diff")
|
||||
local default_find_main_editor_window = diff._find_main_editor_window
|
||||
diff._find_main_editor_window = function()
|
||||
local win = vim.api.nvim_get_current_win()
|
||||
local buf = vim.api.nvim_win_get_buf(win)
|
||||
local buftype = vim.api.nvim_buf_get_option(buf, "buftype")
|
||||
local win_config = vim.api.nvim_win_get_config(win)
|
||||
local is_floating = win_config.relative and win_config.relative ~= ""
|
||||
local is_diff_win = vim.api.nvim_win_get_option(win, "diff")
|
||||
if not is_floating and not is_diff_win and buftype ~= "terminal" and buftype ~= "prompt" then
|
||||
return win
|
||||
end
|
||||
return default_find_main_editor_window()
|
||||
end
|
||||
|
||||
-- claudecode's unified diff buffers pick up treesitter's foldexpr via
|
||||
-- the normal FileType autocmd, so they otherwise inherit the global
|
||||
-- foldlevelstart and open partially collapsed. Fully expand folds in
|
||||
-- these specifically instead of changing the default for all buffers.
|
||||
vim.api.nvim_create_autocmd("BufWinEnter", {
|
||||
group = vim.api.nvim_create_augroup("ClaudeCodeDiffUnfold", { clear = true }),
|
||||
callback = function(args)
|
||||
if vim.b[args.buf].claudecode_inline_diff then
|
||||
vim.wo.foldlevel = 99
|
||||
end
|
||||
end,
|
||||
})
|
||||
end,
|
||||
keys = {
|
||||
{ "<leader>ac", "<cmd>ClaudeCode<CR>", desc = "Toggle Claude Code" },
|
||||
{ "<leader>af", "<cmd>ClaudeCodeFocus<CR>", desc = "Focus Claude Code" },
|
||||
{ "<leader>ab", "<cmd>ClaudeCodeAdd %<CR>", desc = "Add buffer to Claude Code" },
|
||||
{ "<leader>as", "<cmd>ClaudeCodeSend<CR>", mode = "v", desc = "Send selection to Claude Code" },
|
||||
{ "<leader>aa", "<cmd>ClaudeCodeDiffAccept<CR>", desc = "Accept Claude Code diff" },
|
||||
{ "<leader>ad", "<cmd>ClaudeCodeDiffDeny<CR>", desc = "Deny Claude Code diff" },
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
return {
|
||||
"saghen/blink.cmp",
|
||||
version = "*",
|
||||
opts = {
|
||||
keymap = { preset = "default" },
|
||||
appearance = { nerd_font_variant = "mono" },
|
||||
completion = { documentation = { auto_show = true } },
|
||||
sources = { default = { "lsp", "path", "buffer" } },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
return {
|
||||
{
|
||||
"mfussenegger/nvim-dap",
|
||||
keys = {
|
||||
{ "<leader>db", function() require("dap").toggle_breakpoint() end, desc = "Toggle breakpoint" },
|
||||
{ "<leader>dc", function() require("dap").continue() end, desc = "Debug: continue" },
|
||||
{ "<leader>di", function() require("dap").step_into() end, desc = "Debug: step into" },
|
||||
{ "<leader>do", function() require("dap").step_over() end, desc = "Debug: step over" },
|
||||
{ "<leader>dO", function() require("dap").step_out() end, desc = "Debug: step out" },
|
||||
{ "<leader>dr", function() require("dap").repl.toggle() end, desc = "Debug: toggle REPL" },
|
||||
{ "<leader>dq", function() require("dap").terminate() end, desc = "Debug: terminate" },
|
||||
},
|
||||
},
|
||||
{
|
||||
-- Configures nvim-dap for Python using debugpy, installed via Mason
|
||||
-- (:MasonInstall debugpy) so it lives in an isolated venv rather than
|
||||
-- needing debugpy in every project's own environment.
|
||||
"mfussenegger/nvim-dap-python",
|
||||
dependencies = { "mfussenegger/nvim-dap" },
|
||||
ft = "python",
|
||||
config = function()
|
||||
local python = vim.fn.stdpath("data") .. "/mason/packages/debugpy/venv/bin/python"
|
||||
if vim.fn.executable(python) == 0 then
|
||||
vim.notify(
|
||||
"debugpy not installed: run :MasonInstall debugpy to enable Python debugging",
|
||||
vim.log.levels.WARN
|
||||
)
|
||||
return
|
||||
end
|
||||
require("dap-python").setup(python)
|
||||
end,
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
return {
|
||||
{
|
||||
"nvim-neo-tree/neo-tree.nvim",
|
||||
branch = "v3.x",
|
||||
dependencies = {
|
||||
"nvim-lua/plenary.nvim",
|
||||
"nvim-tree/nvim-web-devicons",
|
||||
"MunifTanjim/nui.nvim",
|
||||
},
|
||||
keys = {
|
||||
{ "<leader>t", ":Neotree toggle<CR>", desc = "Toggle file explorer" },
|
||||
{
|
||||
"<leader>cd",
|
||||
function()
|
||||
vim.cmd("cd " .. vim.fn.fnameescape(vim.fn.expand("%:p:h")))
|
||||
vim.cmd("pwd")
|
||||
vim.cmd("Neotree dir=" .. vim.fn.fnameescape(vim.fn.getcwd()))
|
||||
end,
|
||||
desc = "cd to current file's directory and open explorer",
|
||||
},
|
||||
},
|
||||
opts = {},
|
||||
},
|
||||
|
||||
{
|
||||
"nvim-telescope/telescope.nvim",
|
||||
dependencies = {
|
||||
"nvim-lua/plenary.nvim",
|
||||
{ "nvim-telescope/telescope-fzf-native.nvim", build = "make" },
|
||||
},
|
||||
cmd = "Telescope",
|
||||
keys = {
|
||||
{ "<leader>.", "<cmd>Telescope lsp_document_symbols<CR>", desc = "Jump to symbol" },
|
||||
{ "<leader>;", "<cmd>Telescope buffers<CR>", desc = "Jump to buffer" },
|
||||
{
|
||||
"<leader>be",
|
||||
"<cmd>Telescope buffers sort_mru=true ignore_current_buffer=true<CR>",
|
||||
desc = "Jump to buffer (MRU)",
|
||||
},
|
||||
{ "<leader>ag", "<cmd>Telescope live_grep<CR>", desc = "Grep" },
|
||||
{ "<leader>?", "<cmd>Telescope keymaps<CR>", desc = "Search keybindings" },
|
||||
},
|
||||
config = function()
|
||||
local telescope = require("telescope")
|
||||
telescope.setup({})
|
||||
telescope.load_extension("fzf")
|
||||
end,
|
||||
},
|
||||
|
||||
{
|
||||
"folke/flash.nvim",
|
||||
event = "VeryLazy",
|
||||
opts = {},
|
||||
keys = {
|
||||
{ "<leader>/", function() require("flash").jump() end, mode = { "n", "x", "o" }, desc = "Flash jump" },
|
||||
{ "<leader>s", function() require("flash").jump({ search = { mode = "search" } }) end, mode = { "n", "x", "o" }, desc = "Flash search jump" },
|
||||
{ "<leader><leader>s", function() require("flash").treesitter() end, mode = { "n", "x", "o" }, desc = "Flash treesitter" },
|
||||
{ "<leader>f", function() require("flash").jump({ search = { forward = true, wrap = false } }) end, mode = { "n", "x", "o" }, desc = "Flash forward" },
|
||||
},
|
||||
},
|
||||
|
||||
{ "kylechui/nvim-surround", event = { "BufReadPost", "BufNewFile" }, opts = {} },
|
||||
{ "windwp/nvim-autopairs", event = "InsertEnter", opts = {} },
|
||||
|
||||
{
|
||||
"nvim-treesitter/nvim-treesitter-context",
|
||||
event = { "BufReadPost", "BufNewFile" },
|
||||
dependencies = { "nvim-treesitter/nvim-treesitter" },
|
||||
opts = {},
|
||||
},
|
||||
|
||||
{
|
||||
"echasnovski/mini.align",
|
||||
version = "*",
|
||||
keys = {
|
||||
{ "ga=", mode = { "n", "x" }, desc = "Align on =" },
|
||||
{ "ga:", mode = { "n", "x" }, desc = "Align on :" },
|
||||
},
|
||||
config = function()
|
||||
require("mini.align").setup({
|
||||
mappings = { start = "ga", start_with_preview = "" },
|
||||
})
|
||||
end,
|
||||
},
|
||||
|
||||
{ "echasnovski/mini.bufremove", version = "*", keys = {
|
||||
{ "<leader><leader>c", function() require("mini.bufremove").delete(0, false) end, desc = "Close buffer" },
|
||||
} },
|
||||
|
||||
{
|
||||
"mg979/vim-visual-multi",
|
||||
branch = "master",
|
||||
keys = { "<C-n>" },
|
||||
init = function()
|
||||
vim.g.VM_maps = {
|
||||
["Find Under"] = "<C-n>",
|
||||
["Find Subword Under"] = "<C-n>",
|
||||
}
|
||||
end,
|
||||
},
|
||||
|
||||
{
|
||||
"christoomey/vim-tmux-navigator",
|
||||
lazy = false,
|
||||
-- Plugin's own default mappings rely on a Vim-only <C-w> terminal escape
|
||||
-- that Neovim doesn't support, so :terminal buffers (e.g. claudecode.nvim)
|
||||
-- leak the raw keystrokes to the embedded process. Disable them and
|
||||
-- define our own, using Neovim's actual terminal-mode escape.
|
||||
init = function()
|
||||
vim.g.tmux_navigator_no_mappings = 1
|
||||
end,
|
||||
keys = {
|
||||
{ "<C-h>", "<cmd>TmuxNavigateLeft<CR>" },
|
||||
{ "<C-j>", "<cmd>TmuxNavigateDown<CR>" },
|
||||
{ "<C-k>", "<cmd>TmuxNavigateUp<CR>" },
|
||||
{ "<C-l>", "<cmd>TmuxNavigateRight<CR>" },
|
||||
{ "<C-h>", "<C-\\><C-n><cmd>TmuxNavigateLeft<CR>", mode = "t" },
|
||||
{ "<C-j>", "<C-\\><C-n><cmd>TmuxNavigateDown<CR>", mode = "t" },
|
||||
{ "<C-k>", "<C-\\><C-n><cmd>TmuxNavigateUp<CR>", mode = "t" },
|
||||
{ "<C-l>", "<C-\\><C-n><cmd>TmuxNavigateRight<CR>", mode = "t" },
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
"mattn/emmet-vim",
|
||||
ft = { "html", "css" },
|
||||
init = function()
|
||||
vim.g.user_emmet_install_global = 0
|
||||
end,
|
||||
config = function()
|
||||
vim.api.nvim_create_autocmd("FileType", {
|
||||
pattern = { "html", "css" },
|
||||
callback = function() vim.cmd("EmmetInstall") end,
|
||||
})
|
||||
end,
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
return {
|
||||
{
|
||||
"stevearc/conform.nvim",
|
||||
event = { "BufWritePre" },
|
||||
cmd = { "ConformInfo" },
|
||||
opts = {
|
||||
formatters_by_ft = {
|
||||
css = { "prettier" },
|
||||
svelte = { "prettier" },
|
||||
pcss = { "prettier" },
|
||||
html = { "prettier" },
|
||||
typescript = { "prettier" },
|
||||
typescriptreact = { "prettier" },
|
||||
javascript = { "prettier" },
|
||||
javascriptreact = { "prettier" },
|
||||
json = { "prettier" },
|
||||
yaml = { "prettier" },
|
||||
markdown = { "prettier" },
|
||||
python = { "ruff_format" },
|
||||
rust = { "rustfmt" },
|
||||
lua = { "stylua" },
|
||||
},
|
||||
format_on_save = {
|
||||
lsp_format = "fallback",
|
||||
timeout_ms = 2000,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
"mfussenegger/nvim-lint",
|
||||
event = { "BufWritePost", "BufReadPost", "InsertLeave" },
|
||||
config = function()
|
||||
require("lint").linters_by_ft = {
|
||||
javascript = { "eslint_d" },
|
||||
typescript = { "eslint_d" },
|
||||
javascriptreact = { "eslint_d" },
|
||||
typescriptreact = { "eslint_d" },
|
||||
svelte = { "eslint_d" },
|
||||
}
|
||||
|
||||
if vim.fn.executable("shellcheck") == 1 then
|
||||
require("lint").linters_by_ft.sh = { "shellcheck" }
|
||||
else
|
||||
vim.notify("shellcheck not found: skipping shell linting", vim.log.levels.WARN)
|
||||
end
|
||||
|
||||
vim.api.nvim_create_autocmd({ "BufWritePost", "BufReadPost", "InsertLeave" }, {
|
||||
callback = function()
|
||||
require("lint").try_lint()
|
||||
end,
|
||||
})
|
||||
end,
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
return {
|
||||
{ "lewis6991/gitsigns.nvim", event = { "BufReadPre", "BufNewFile" }, opts = {} },
|
||||
{ "tpope/vim-fugitive", cmd = { "Git", "Gdiffsplit", "Gvdiffsplit", "Gread", "Gwrite", "Gclog" } },
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
-- ruff is a prebuilt GitHub release binary, but mason installs basedpyright
|
||||
-- from PyPI into a venv. Debian ships venv's ensurepip separately
|
||||
-- (python3-venv), and without it every startup fails the install.
|
||||
local servers = { "ruff" }
|
||||
|
||||
local function has_python_venv()
|
||||
if vim.fn.executable("python3") ~= 1 then
|
||||
return false
|
||||
end
|
||||
vim.fn.system({ "python3", "-c", "import ensurepip" })
|
||||
return vim.v.shell_error == 0
|
||||
end
|
||||
|
||||
if has_python_venv() then
|
||||
table.insert(servers, "basedpyright")
|
||||
else
|
||||
vim.notify("python3 venv unavailable (install python3-venv): skipping LSP server basedpyright", vim.log.levels.WARN)
|
||||
end
|
||||
|
||||
local npm_servers = { "ts_ls", "svelte", "html", "cssls", "bashls" }
|
||||
local function has_public_npm()
|
||||
if vim.fn.executable("npm") ~= 1 then
|
||||
return false
|
||||
end
|
||||
local result = vim.fn.system("npm config get registry")
|
||||
return result:find("registry.npmjs.org") ~= nil
|
||||
end
|
||||
|
||||
if has_public_npm() then
|
||||
vim.list_extend(servers, npm_servers)
|
||||
else
|
||||
vim.notify(
|
||||
"public npm registry unavailable: skipping LSP servers " .. table.concat(npm_servers, ", "),
|
||||
vim.log.levels.WARN
|
||||
)
|
||||
end
|
||||
|
||||
return {
|
||||
{
|
||||
"mason-org/mason.nvim",
|
||||
opts = {},
|
||||
},
|
||||
{
|
||||
"mason-org/mason-lspconfig.nvim",
|
||||
dependencies = { "mason-org/mason.nvim" },
|
||||
opts = {
|
||||
ensure_installed = servers,
|
||||
},
|
||||
},
|
||||
{
|
||||
"neovim/nvim-lspconfig",
|
||||
dependencies = { "mason-org/mason-lspconfig.nvim", "saghen/blink.cmp", "saghen/blink.lib" },
|
||||
config = function()
|
||||
local capabilities = require("blink.cmp").get_lsp_capabilities()
|
||||
|
||||
vim.api.nvim_create_autocmd("LspAttach", {
|
||||
group = vim.api.nvim_create_augroup("LspKeymaps", { clear = true }),
|
||||
callback = function(args)
|
||||
local opts = { buffer = args.buf }
|
||||
vim.keymap.set("n", "K", vim.lsp.buf.hover, opts)
|
||||
vim.keymap.set("n", "gd", vim.lsp.buf.definition, opts)
|
||||
vim.keymap.set("n", "gy", vim.lsp.buf.type_definition, opts)
|
||||
vim.keymap.set("n", "gi", vim.lsp.buf.implementation, opts)
|
||||
vim.keymap.set("n", "gr", vim.lsp.buf.references, opts)
|
||||
vim.keymap.set("n", "rn", vim.lsp.buf.rename, opts)
|
||||
vim.keymap.set("v", "ff", function() vim.lsp.buf.format({ async = true }) end, opts)
|
||||
end,
|
||||
})
|
||||
|
||||
for _, server in ipairs(servers) do
|
||||
vim.lsp.config(server, { capabilities = capabilities })
|
||||
vim.lsp.enable(server)
|
||||
end
|
||||
end,
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
return {
|
||||
{
|
||||
"stevearc/aerial.nvim",
|
||||
dependencies = { "nvim-treesitter/nvim-treesitter", "nvim-tree/nvim-web-devicons" },
|
||||
keys = {
|
||||
{ "<leader>ct", "<cmd>AerialToggle<CR>", desc = "Toggle symbol outline" },
|
||||
},
|
||||
opts = {},
|
||||
},
|
||||
|
||||
{
|
||||
"jiaoshijie/undotree",
|
||||
dependencies = { "nvim-lua/plenary.nvim" },
|
||||
keys = {
|
||||
{ "<leader>u", function() require("undotree").toggle() end, desc = "Toggle undo tree" },
|
||||
},
|
||||
opts = {},
|
||||
},
|
||||
|
||||
{
|
||||
"folke/persistence.nvim",
|
||||
event = "BufReadPre",
|
||||
opts = {},
|
||||
},
|
||||
|
||||
{
|
||||
"folke/which-key.nvim",
|
||||
event = "VeryLazy",
|
||||
opts = {},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
return {
|
||||
{
|
||||
"mrcjkb/rustaceanvim",
|
||||
version = "^6",
|
||||
lazy = false,
|
||||
init = function()
|
||||
vim.g.rustaceanvim = {
|
||||
tools = {},
|
||||
server = {
|
||||
on_attach = function(_, bufnr)
|
||||
vim.keymap.set("n", "<localleader>rr", function()
|
||||
vim.cmd.RustLsp("run")
|
||||
end, { buffer = bufnr })
|
||||
end,
|
||||
},
|
||||
}
|
||||
end,
|
||||
},
|
||||
{
|
||||
"mason-org/mason-lspconfig.nvim",
|
||||
opts = {
|
||||
automatic_enable = { exclude = { "rust_analyzer" } },
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
return {
|
||||
"nvim-treesitter/nvim-treesitter",
|
||||
lazy = false,
|
||||
build = ":TSUpdate",
|
||||
config = function()
|
||||
local parsers = {
|
||||
"javascript",
|
||||
"typescript",
|
||||
"tsx",
|
||||
"svelte",
|
||||
"html",
|
||||
"css",
|
||||
"scss",
|
||||
"json",
|
||||
"yaml",
|
||||
"python",
|
||||
"rust",
|
||||
"bash",
|
||||
"lua",
|
||||
"vim",
|
||||
"vimdoc",
|
||||
"query",
|
||||
"markdown",
|
||||
"markdown_inline",
|
||||
"regex",
|
||||
}
|
||||
|
||||
-- Install parsers (skip if the tree-sitter CLI isn't available; parsers
|
||||
-- already cached from a previous run on this machine still work fine)
|
||||
if vim.fn.executable("tree-sitter") == 1 then
|
||||
require("nvim-treesitter").install(parsers)
|
||||
else
|
||||
local uname = vim.uv.os_uname()
|
||||
local sysname = (uname.sysname or ""):lower()
|
||||
local machine = uname.machine or ""
|
||||
local is_mac = sysname == "darwin"
|
||||
|
||||
local install_cmd
|
||||
if is_mac then
|
||||
local arch_part = ({ x86_64 = "x64", amd64 = "x64", aarch64 = "arm64", arm64 = "arm64" })[machine] or "x64"
|
||||
local asset = "tree-sitter-macos-" .. arch_part
|
||||
install_cmd = " curl -L https://github.com/tree-sitter/tree-sitter/releases/latest/download/"
|
||||
.. asset
|
||||
.. ".gz | gunzip > ~/.local/bin/tree-sitter && chmod +x ~/.local/bin/tree-sitter"
|
||||
else
|
||||
install_cmd = " cargo install --root ~/.local tree-sitter-cli"
|
||||
end
|
||||
|
||||
vim.notify(
|
||||
"tree-sitter CLI not found: skipping install of missing parsers.\n"
|
||||
.. "Install into ~/.local/bin:\n"
|
||||
.. install_cmd,
|
||||
vim.log.levels.WARN
|
||||
)
|
||||
end
|
||||
|
||||
-- Enable treesitter highlighting, folding, and indentation for
|
||||
-- filetypes with an installed parser. Note some filetype names differ
|
||||
-- from their parser names (e.g. "bash" parser -> "sh" filetype).
|
||||
vim.api.nvim_create_autocmd("FileType", {
|
||||
pattern = {
|
||||
"javascript",
|
||||
"typescript",
|
||||
"typescriptreact",
|
||||
"javascriptreact",
|
||||
"svelte",
|
||||
"html",
|
||||
"css",
|
||||
"scss",
|
||||
"json",
|
||||
"yaml",
|
||||
"python",
|
||||
"rust",
|
||||
"sh",
|
||||
"lua",
|
||||
"vim",
|
||||
"help",
|
||||
"query",
|
||||
"markdown",
|
||||
},
|
||||
callback = function()
|
||||
-- Highlighting, provided by Neovim. Falls back to Vim's legacy
|
||||
-- syntax/indent if no parser is installed for this filetype.
|
||||
if not pcall(vim.treesitter.start) then
|
||||
return
|
||||
end
|
||||
-- Folding, provided by Neovim
|
||||
vim.wo.foldexpr = "v:lua.vim.treesitter.foldexpr()"
|
||||
vim.wo.foldmethod = "expr"
|
||||
-- Indentation, provided by nvim-treesitter
|
||||
vim.bo.indentexpr = "v:lua.require'nvim-treesitter'.indentexpr()"
|
||||
end,
|
||||
})
|
||||
|
||||
-- General fold display settings (not treesitter-specific)
|
||||
vim.opt.foldlevel = 2
|
||||
vim.opt.foldlevelstart = 2
|
||||
vim.opt.foldcolumn = "5"
|
||||
end,
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
return {
|
||||
{
|
||||
"ellisonleao/gruvbox.nvim",
|
||||
priority = 1000,
|
||||
opts = {
|
||||
italic = { strings = true, comments = true, operators = false, folds = true },
|
||||
invert_selection = true,
|
||||
invert_signs = false,
|
||||
},
|
||||
config = function(_, opts)
|
||||
require("gruvbox").setup(opts)
|
||||
vim.o.background = "dark"
|
||||
local ok = pcall(vim.cmd.colorscheme, "gruvbox")
|
||||
if not ok then
|
||||
vim.cmd.colorscheme("desert")
|
||||
end
|
||||
end,
|
||||
},
|
||||
|
||||
{
|
||||
"nvim-lualine/lualine.nvim",
|
||||
dependencies = { "nvim-tree/nvim-web-devicons" },
|
||||
event = "VeryLazy",
|
||||
opts = {
|
||||
options = { theme = "gruvbox" },
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
"akinsho/bufferline.nvim",
|
||||
dependencies = { "nvim-tree/nvim-web-devicons" },
|
||||
event = "VeryLazy",
|
||||
opts = {},
|
||||
},
|
||||
|
||||
{
|
||||
"lukas-reineke/indent-blankline.nvim",
|
||||
main = "ibl",
|
||||
event = { "BufReadPost", "BufNewFile" },
|
||||
opts = {},
|
||||
},
|
||||
|
||||
{
|
||||
"HiPhish/rainbow-delimiters.nvim",
|
||||
event = { "BufReadPost", "BufNewFile" },
|
||||
},
|
||||
|
||||
{ "nvim-tree/nvim-web-devicons", opts = {} },
|
||||
|
||||
{
|
||||
"goolord/alpha-nvim",
|
||||
dependencies = { "nvim-tree/nvim-web-devicons" },
|
||||
event = "VimEnter",
|
||||
config = function()
|
||||
local alpha = require("alpha")
|
||||
local dashboard = require("alpha.themes.dashboard")
|
||||
|
||||
local function fortune_header()
|
||||
-- cowsay -l prints a header line, then wraps every cow name across
|
||||
-- several space-separated lines (not one name per line), so a name
|
||||
-- has to be picked from all of them split on whitespace, not by
|
||||
-- treating a whole (possibly multi-name) line as one name.
|
||||
local raw = vim.fn.systemlist("cowsay -l")
|
||||
local cow = "default"
|
||||
local names = {}
|
||||
for i = 2, #raw do
|
||||
for name in raw[i]:gmatch("%S+") do
|
||||
table.insert(names, name)
|
||||
end
|
||||
end
|
||||
if #names > 0 then
|
||||
cow = names[math.random(#names)]
|
||||
end
|
||||
local moods = { "b", "d", "g", "p", "s", "t", "w", "y" }
|
||||
local mood = moods[math.random(#moods)]
|
||||
local cmd = string.format(
|
||||
"fortune -a -s | fmt -80 -s | cowthink -%s -f %s -n",
|
||||
mood,
|
||||
cow
|
||||
)
|
||||
local ok, lines = pcall(vim.fn.systemlist, cmd)
|
||||
if not ok or #lines == 0 then
|
||||
return { "Welcome to Neovim" }
|
||||
end
|
||||
return lines
|
||||
end
|
||||
|
||||
dashboard.section.header.val = fortune_header()
|
||||
dashboard.section.buttons.val = {
|
||||
dashboard.button("e", " New file", ":enew<CR>"),
|
||||
dashboard.button("f", " Find file", ":Telescope find_files<CR>"),
|
||||
dashboard.button("g", " Live grep", ":Telescope live_grep<CR>"),
|
||||
dashboard.button("s", " Restore session", ":lua require('persistence').load()<CR>"),
|
||||
dashboard.button("q", " Quit", ":qa<CR>"),
|
||||
}
|
||||
alpha.setup(dashboard.opts)
|
||||
|
||||
vim.keymap.set("n", "<leader><leader>o", ":Alpha<CR>")
|
||||
end,
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
vim.g.vimwiki_list = {
|
||||
{
|
||||
path = "~/synced-notebooks/bradwiki/",
|
||||
syntax = "markdown",
|
||||
ext = ".md",
|
||||
diary_rel_path = "daily_notes/",
|
||||
diary_index = "index",
|
||||
diary_header = "Daily Notes",
|
||||
auto_tags = 1,
|
||||
auto_diary_index = 1,
|
||||
auto_generate_links = 1,
|
||||
auto_generate_tags = 1,
|
||||
},
|
||||
{
|
||||
path = "~/synced-notebooks/work_notebook/",
|
||||
syntax = "markdown",
|
||||
ext = ".md",
|
||||
diary_rel_path = "daily_notes/",
|
||||
diary_index = "index",
|
||||
diary_header = "Daily Notes",
|
||||
auto_tags = 1,
|
||||
auto_diary_index = 1,
|
||||
auto_generate_links = 1,
|
||||
auto_generate_tags = 1,
|
||||
},
|
||||
{ path = "~/synced-notebooks/privatewiki/", syntax = "markdown", ext = ".md" },
|
||||
{ path = "~/synced-notebooks/sharedwiki/", syntax = "markdown", ext = ".md" },
|
||||
}
|
||||
vim.g.vimwiki_map_prefix = "<Leader>m"
|
||||
vim.g.vimwiki_folding = "list"
|
||||
vim.g.markdown_folding = 1
|
||||
|
||||
vim.g.zettel_options = {
|
||||
{},
|
||||
{
|
||||
front_matter = { { "tags", "" }, { "type", "note" } },
|
||||
template = "~/work_notebook/templates/daily_note.tpl",
|
||||
},
|
||||
}
|
||||
|
||||
vim.g.table_mode_map_prefix = "<Leader><Leader>t"
|
||||
|
||||
vim.api.nvim_create_autocmd("FileType", {
|
||||
group = vim.api.nvim_create_augroup("VimwikiFiletype", { clear = true }),
|
||||
pattern = "vimwiki",
|
||||
callback = function()
|
||||
vim.opt_local.breakindent = true
|
||||
vim.opt_local.breakindentopt = "shift:2"
|
||||
end,
|
||||
})
|
||||
|
||||
return {
|
||||
{ "vimwiki/vimwiki", lazy = false },
|
||||
{ "michal-h21/vim-zettel", dependencies = { "vimwiki/vimwiki" }, lazy = false },
|
||||
{ "dhruvasagar/vim-table-mode", cmd = "TableModeToggle" },
|
||||
{
|
||||
"iamcco/markdown-preview.nvim",
|
||||
build = function() vim.fn["mkdp#util#install"]() end,
|
||||
ft = { "markdown", "vimwiki" },
|
||||
keys = {
|
||||
{ "<localleader>v", "<Plug>MarkdownPreviewToggle", ft = { "markdown", "vimwiki" }, desc = "Toggle markdown preview" },
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
local M = {}
|
||||
|
||||
-- Open ranger from within nvim; if it writes a chosen path to its return
|
||||
-- file, open that file. Mirrors the old vimscript Ranger() function.
|
||||
function M.ranger()
|
||||
if vim.fn.executable("ranger") == 0 then
|
||||
vim.notify("ranger is not installed", vim.log.levels.WARN)
|
||||
return
|
||||
end
|
||||
local tmpfile = vim.fn.system("mktemp -u"):gsub("\n", "")
|
||||
vim.cmd(("silent !RANGER_RETURN_FILE=%s ranger"):format(tmpfile))
|
||||
if vim.fn.filereadable(tmpfile) == 1 then
|
||||
local filetoedit = vim.fn.system("cat " .. tmpfile)
|
||||
vim.cmd("edit " .. filetoedit)
|
||||
vim.fn.delete(tmpfile)
|
||||
end
|
||||
vim.cmd("redraw!")
|
||||
end
|
||||
|
||||
-- Delete trailing whitespace on the current buffer, preserving cursor
|
||||
-- position. Mirrors the old vimscript DeleteTrailingWS() function.
|
||||
function M.delete_trailing_ws()
|
||||
local view = vim.fn.winsaveview()
|
||||
vim.cmd([[silent! %s/\s\+$//ge]])
|
||||
vim.fn.winrestview(view)
|
||||
end
|
||||
|
||||
return M
|
||||
+4
-3
@@ -22,7 +22,6 @@ shadow-exclude = [
|
||||
"class_g = 'lattedock'",
|
||||
"_GTK_FRAME_EXTENTS@:c"
|
||||
]
|
||||
xinerama-shadow-crop = true;
|
||||
|
||||
### Blur
|
||||
blur:{
|
||||
@@ -52,8 +51,6 @@ backend = "glx";
|
||||
#backend = "xrender";
|
||||
vsync = true;
|
||||
|
||||
glx-no-stencil = true;
|
||||
glx-no-rebind-pixmap = true;
|
||||
xrender-sync-fence = true;
|
||||
|
||||
dbus=true;
|
||||
@@ -74,3 +71,7 @@ mark-wmwin-focused = true;
|
||||
mark-ovredir-focused = true;
|
||||
use-ewmh-active-win = true;
|
||||
detect-client-leader = true;
|
||||
|
||||
## Fixes graphical issues (jitter/flickering) in Jetbrains IDEs
|
||||
## TODO: This doesn't fully fix the issue
|
||||
unredir-if-possible = false;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"groups": {
|
||||
"stack_depth": { "fg": "gb:light1", "bg": "gb:light4", "attrs": ["bold"] }
|
||||
"stack_depth": { "fg": "gray1", "bg": "gray10", "attrs": ["bold"] }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"groups": {
|
||||
"stack_depth": { "fg": "gb:light1", "bg": "gb:light4", "attrs": ["bold"] }
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@
|
||||
}
|
||||
},
|
||||
"pdb": {
|
||||
"colorscheme": "default",
|
||||
"colorscheme": "gruvbox",
|
||||
"theme": "default"
|
||||
},
|
||||
"shell": {
|
||||
|
||||
+129
-5
@@ -1,6 +1,130 @@
|
||||
export TERMINAL=alacritty
|
||||
export EDITOR=nvim
|
||||
export SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/ssh-agent.socket"
|
||||
alias vim=nvim
|
||||
XDG_DATA_DIRS="/var/lib/flatpak/exports/share:$XDG_DATA_DIRS"
|
||||
# Override in .profile.local for custom repo
|
||||
DOTFILES_LOCAL_REPOSITORY="https://gitbox.branderson.io/branderson/dotfiles-local"
|
||||
|
||||
# Programs expected to be installed by tools
|
||||
# These are the name on $PATH, not the package name
|
||||
dependencies=(
|
||||
tree
|
||||
nvim
|
||||
ag
|
||||
fzf
|
||||
node
|
||||
cowsay
|
||||
fortune
|
||||
)
|
||||
|
||||
# Load dotfiles directory into DOTFILES_DIR
|
||||
# Dotfiles directory should be in environment or ~/.dotfiles-config
|
||||
if [ -f "$HOME/.dotfiles-config" ]; then
|
||||
source "$HOME/.dotfiles-config"
|
||||
fi
|
||||
|
||||
# PATHs
|
||||
## Earlier paths in PATH checked first
|
||||
if [ -d /usr/games ]; then
|
||||
export PATH="/usr/games:$PATH"
|
||||
fi
|
||||
if [ -d /opt/homebrew/opt/coreutils/libexec/gnubin ]; then
|
||||
export PATH="/opt/homebrew/opt/coreutils/libexec/gnubin:$PATH"
|
||||
fi
|
||||
if [ -d /opt/homebrew/opt/python@3.13/libexec/bin ]; then
|
||||
export PATH="/opt/homebrew/opt/python@3.13/libexec/bin:$PATH"
|
||||
fi
|
||||
if [ -d /opt/homebrew/bin ]; then
|
||||
export PATH="/opt/homebrew/bin:$PATH"
|
||||
fi
|
||||
## Keep user bin directories first in PATH so they're preferred
|
||||
if [ -d "$DOTFILES_DIR/bin" ]; then
|
||||
export PATH="$DOTFILES_DIR/bin:$PATH"
|
||||
fi
|
||||
## OS-specific binaries
|
||||
if [[ $OSTYPE == 'darwin'* ]]; then
|
||||
if [[ -d "$DOTFILES_DIR/macbin" ]]; then
|
||||
export PATH="$DOTFILES_DIR/macbin:$PATH"
|
||||
fi
|
||||
elif [[ $OSTYPE == 'linux'* ]]; then
|
||||
if [[ -d "$DOTFILES_DIR/linbin" ]]; then
|
||||
export PATH="$DOTFILES_DIR/linbin:$PATH"
|
||||
fi
|
||||
fi
|
||||
if [ -d "$HOME/.local/bin" ]; then
|
||||
export PATH="$HOME/.local/bin:$PATH"
|
||||
fi
|
||||
if [ -d "$HOME/bin" ]; then
|
||||
export PATH="$HOME/bin:$PATH"
|
||||
fi
|
||||
|
||||
source "$HOME/.bash_functions"
|
||||
|
||||
# Set up brew if on macOS
|
||||
if [[ $OSTYPE == 'darwin'* ]]; then
|
||||
if [ -f /opt/homebrew/bin/brew ]; then
|
||||
eval "$(/opt/homebrew/bin/brew shellenv)"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Prefer alacritty terminal if installed
|
||||
if program_installed alacritty; then
|
||||
export TERMINAL=alacritty
|
||||
fi
|
||||
|
||||
# Prefer neovim, if installed
|
||||
if program_installed nvim; then
|
||||
export EDITOR=nvim
|
||||
alias vim=nvim
|
||||
fi
|
||||
|
||||
if program_installed powerline; then
|
||||
# Make powerline support Python virtualenvs
|
||||
export POWERLINE_COMMAND="$DOTFILES_DIR/scripts/powerline-wrapper.sh"
|
||||
fi
|
||||
|
||||
# alias make='nocorrect make'
|
||||
# alias git='nocorrect git'
|
||||
# Crontab
|
||||
#alias crontab-e='vim ~/.crontab && crontab ~/.crontab'
|
||||
|
||||
#alias sl="sl -laF"
|
||||
|
||||
# Put flatpak apps in XDG
|
||||
if program_installed flatpak; then
|
||||
export XDG_DATA_DIRS="/var/lib/flatpak/exports/share:$XDG_DATA_DIRS"
|
||||
fi
|
||||
|
||||
# pyenv paths
|
||||
export PYENV_ROOT="$HOME/.pyenv"
|
||||
export PATH="$PYENV_ROOT/bin:$PATH"
|
||||
|
||||
# Make sure ssh-agent is available
|
||||
if [ -n "$LOAD_SSH_KEYS" ] && [ "$LOAD_SSH_KEYS" -eq 1 ]; then
|
||||
if program_installed ssh-add && [ ! -z "$SSH_AUTH_SOCK" ] && [ -d "$SSH_AUTH_SOCK" ] > /dev/null 2>&1 ; then
|
||||
# Add SSH keys to agent if not already added
|
||||
## Find existing keys, supporting one layer of folder organization
|
||||
public_keys=($(find "$HOME/.ssh/" -maxdepth 2 -name "*.pub"))
|
||||
if [ ${#public_keys[@]} -gt 0 ]; then
|
||||
for public_key in "${public_keys[@]}"; do
|
||||
if [[ $(uname -s) == Linux* ]]; then
|
||||
# Add SSH keys only if not already present
|
||||
ssh-add -l | grep -q `ssh-keygen -lf "$public_key" | awk '{print $2}'` || ssh-add -k
|
||||
break
|
||||
elif [[ $(uname -s) == Darwin* ]]; then
|
||||
# Add SSH keys only if not already present
|
||||
ssh-add -l | grep -q `ssh-keygen -lf "$public_key" | awk '{print $2}'` || ssh-add --apple-use-keychain
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if program_installed i3; then
|
||||
# Set QT environment variables
|
||||
export QT_QPA_PLATFORMTHEME="qt5ct"
|
||||
fi
|
||||
|
||||
# Extra domains dejima's firewall should allow beyond its defaults
|
||||
export ALLOWED_DOMAINS=""
|
||||
|
||||
# Gitea host, used by bin/gitea-pr and dejima's git-push-guard hook
|
||||
export GITEA_SSH_HOST="gitbox.bradina.localdomain"
|
||||
export GITEA_API="https://gitbox.branderson.io/api/v1"
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
[Unit]
|
||||
After=network-online.target nss-lookup.target
|
||||
ConditionPathIsDirectory=/etc/pacman.d/gnupg/
|
||||
ConditionPathIsReadWrite=/etc/pacman.d/gnupg/
|
||||
ConditionFileIsExecutable=/usr/bin/archlinux-keyring-wkd-sync
|
||||
Description=Refresh existing keys of archlinux-keyring
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/bin/archlinux-keyring-wkd-sync
|
||||
|
||||
CapabilityBoundingSet=
|
||||
DeviceAllow=
|
||||
LockPersonality=true
|
||||
MemoryDenyWriteExecute=true
|
||||
NoNewPrivileges=true
|
||||
PrivateDevices=true
|
||||
PrivateTmp=true
|
||||
ProtectClock=true
|
||||
ProtectControlGroups=true
|
||||
ProtectHome=true
|
||||
ProtectHostname=true
|
||||
ProtectKernelLogs=true
|
||||
ProtectKernelModules=true
|
||||
ProtectKernelTunables=true
|
||||
ProtectProc=noaccess
|
||||
ProtectSystem=strict
|
||||
ReadWritePaths=/etc/pacman.d/gnupg
|
||||
RemoveIPC=true
|
||||
RestrictAddressFamilies=~AF_PACKET AF_NETLINK
|
||||
RestrictNamespaces=true
|
||||
RestrictRealtime=true
|
||||
RestrictSUIDSGID=true
|
||||
SystemCallArchitectures=native
|
||||
SystemCallFilter=@system-service
|
||||
SystemCallFilter=~@resources
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
[Unit]
|
||||
Description=Refresh existing PGP keys of archlinux-keyring regularly
|
||||
|
||||
[Timer]
|
||||
OnCalendar=weekly
|
||||
Persistent=true
|
||||
RandomizedDelaySec=12h
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
[Unit]
|
||||
Description=Update wallpapers when display change detected
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=brad
|
||||
Environment=DISPLAY=:0
|
||||
ExecStartPre=/bin/sleep 3
|
||||
# TODO: The file might not be here if ~/.dotfiles-config set to somewhere else
|
||||
ExecStart=/home/brad/dotfiles/bin/update-wallpaper
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
+185
-2
@@ -1,2 +1,185 @@
|
||||
# run-shell "~/.tmux/verify_tmux_version.sh"
|
||||
source-file "~/.tmux/tmux_3.1c.conf"
|
||||
# ----------------------------------------------------------------------------
|
||||
# Prefix
|
||||
# ----------------------------------------------------------------------------
|
||||
set -g prefix C-a
|
||||
unbind C-b
|
||||
bind C-a send-prefix
|
||||
bind Tab last-window
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# General behavior
|
||||
# ----------------------------------------------------------------------------
|
||||
set-option -g set-titles on
|
||||
set -g default-terminal "screen-256color"
|
||||
set -g history-limit 10000
|
||||
set -sg escape-time 1
|
||||
set-option -g base-index 1
|
||||
setw -g pane-base-index 1
|
||||
setw -g aggressive-resize on
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Windows and panes
|
||||
# ----------------------------------------------------------------------------
|
||||
bind T swap-window -t 1
|
||||
bind | split-window -h -c "#{pane_current_path}"
|
||||
bind - split-window -v -c "#{pane_current_path}"
|
||||
bind c new-window -c "#{pane_current_path}"
|
||||
|
||||
bind h select-pane -L
|
||||
bind j select-pane -D
|
||||
bind k select-pane -U
|
||||
bind l select-pane -R
|
||||
|
||||
# Smart pane switching with awareness of vim splits
|
||||
is_vim='echo "#{pane_current_command}" | grep -iqE "(^|\/)g?(view|n?vim?)(diff)?$"'
|
||||
# Claude Code also wants its own use of C-j (insert newline), same as vim
|
||||
# wants C-h/j/k/l for its own window navigation -- forward it raw instead of
|
||||
# letting tmux swallow it for pane-switching.
|
||||
is_vim_or_claude='echo "#{pane_current_command}" | grep -iqE "(^|\/)(g?(view|n?vim?)(diff)?|claude)$"'
|
||||
bind -n C-h if-shell "$is_vim" "send-keys C-h" "select-pane -L"
|
||||
bind -n C-j if-shell "$is_vim_or_claude" "send-keys C-j" "select-pane -D"
|
||||
bind -n C-k if-shell "$is_vim" "send-keys C-k" "select-pane -U"
|
||||
bind -n C-l if-shell "$is_vim" "send-keys C-l" "select-pane -R"
|
||||
bind -n 'C-\' if-shell "$is_vim" "send-keys 'C-\\'" "select-pane -l"
|
||||
|
||||
bind -r C-h select-window -t :-
|
||||
bind -r C-l select-window -t :+
|
||||
|
||||
bind a setw synchronize-panes
|
||||
|
||||
# Fuzzy pickers over every session/window/pane, each with a live preview of
|
||||
# what it's running (tmux-fzf). prefix+F opens the plugin's own top-level
|
||||
# menu; these skip straight to the panels used most -- pane.sh is where
|
||||
# break/join/swap live, i.e. moving a pane into another window without
|
||||
# hand-typing a target the way join-pane needs.
|
||||
#
|
||||
# TMUX_FZF_CLIENT pins the action to the client that opened it, exactly as
|
||||
# the plugin's own binding does: a command run via run-shell has no client
|
||||
# context of its own, so tmux otherwise falls back to the most recently
|
||||
# active client -- the wrong terminal whenever a second client (e.g. a
|
||||
# browser one over ttyd) is attached to the same session.
|
||||
bind P run-shell -b "TMUX_FZF_CLIENT='#{client_tty}' ~/.tmux/plugins/tmux-fzf/scripts/pane.sh"
|
||||
bind W run-shell -b "TMUX_FZF_CLIENT='#{client_tty}' ~/.tmux/plugins/tmux-fzf/scripts/window.sh"
|
||||
bind S run-shell -b "TMUX_FZF_CLIENT='#{client_tty}' ~/.tmux/plugins/tmux-fzf/scripts/session.sh"
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Copy mode and mouse
|
||||
# ----------------------------------------------------------------------------
|
||||
setw -g mode-keys vi
|
||||
set-option -g -q mouse on
|
||||
|
||||
bind y run 'tmux save-buffer - | $HOME/dotfiles/bin/clipboard-copy'
|
||||
bind C-y run 'tmux save-buffer - | $HOME/dotfiles/bin/clipboard-copy'
|
||||
|
||||
# Let escape sequences a pane explicitly DCS-wraps for passthrough (e.g.
|
||||
# sixel image data, see the iTerm2 terminal-features line below) reach the
|
||||
# real terminal, even when nested behind ssh/tmux layers. Not used for the
|
||||
# clipboard -- that has its own relay via the pane-set-clipboard hook above.
|
||||
# allow-passthrough was added in tmux 3.3; older tmux doesn't understand the
|
||||
# option, so only set it when the running tmux is new enough.
|
||||
if-shell "tmux -V | awk '{print $2}' | awk -F. '{if ($1*1000+$2 >= 3003) exit 0; else exit 1}'" 'set -g allow-passthrough on'
|
||||
|
||||
# Let tmux tell Shift+Enter apart from plain Enter and forward that
|
||||
# distinction inward, so Claude Code's Shift+Enter-inserts-newline shortcut
|
||||
# works. extended-keys/terminal-features need tmux >= 3.2. The terminal
|
||||
# name is matched with '*' rather than the commonly-suggested 'xterm*',
|
||||
# because a nested tmux's "terminal" is the outer tmux, which reports
|
||||
# itself using default-terminal above (screen-256color) -- 'xterm*' would
|
||||
# never match that, breaking the nested case this is meant to support.
|
||||
#
|
||||
# Investigated as a suspect for multi-line paste getting corrupted with
|
||||
# literal CSI 27;<mod>;<key>~ garbage in place of newlines (see Claude Code
|
||||
# issues #43169 and #30239) -- turning this off did not fix that paste
|
||||
# corruption, so it's an upstream Claude Code paste-tokenizer bug, not
|
||||
# something caused by this setting. Restored.
|
||||
if-shell "tmux -V | awk '{print $2}' | awk -F. '{if ($1*1000+$2 >= 3002) exit 0; else exit 1}'" 'set -s extended-keys on; set -as terminal-features "*:extkeys"'
|
||||
|
||||
# Accept pane-originated OSC 52 clipboard-set attempts into a real tmux
|
||||
# buffer. Only on-vs-off matters here -- off would refuse to even look at
|
||||
# these escapes; "on" (rather than "external") is needed so the pane-set-
|
||||
# clipboard hook below has an actual buffer to read.
|
||||
set -g set-clipboard on
|
||||
|
||||
# tmux's own mechanism for forwarding an accepted clipboard-set (or its own
|
||||
# copy-mode copies) to the real terminal is generating a fresh OSC 52 write
|
||||
# via the "Ms" terminfo capability -- confirmed unreliable here (both
|
||||
# pane-forwarded and tmux-generated OSC 52 silently failed to reach the
|
||||
# clipboard even with Ms correctly registered against Alacritty). Relay it
|
||||
# ourselves instead: whenever any pane sets the clipboard, grab what was
|
||||
# just captured above and write it straight to this client's own terminal
|
||||
# device. If that's a real terminal, this is the final hop and we're done.
|
||||
# If it's actually another tmux one layer further out (e.g. this tmux is
|
||||
# itself running inside an outer tmux over ssh), that data becomes pane
|
||||
# output there, and the *same* hook -- present there too, since it's the
|
||||
# same dotfiles -- fires again. That recurses cleanly through however many
|
||||
# tmux layers are actually in the chain, without any of them needing to
|
||||
# know the total count in advance.
|
||||
set-hook -g pane-set-clipboard 'run-shell "tmux save-buffer - | $HOME/dotfiles/bin/tmux-clipboard-relay #{client_tty}"'
|
||||
|
||||
# The default/no-argument form of copy-pipe (used by double/triple-click and
|
||||
# a couple of default bindings) pipes to this option instead of a literal
|
||||
# command -- route it through the same working script as the explicit
|
||||
# copy-pipe bindings in tmux/modern.conf.
|
||||
set -g copy-command '$HOME/dotfiles/bin/clipboard-copy'
|
||||
|
||||
# iTerm2 supports SIXEL images (since 3.3.0) but doesn't set a distinct TERM
|
||||
# to identify itself, so this matches on its usual "xterm-256color" report --
|
||||
# any other client reporting that same TERM will also be treated as
|
||||
# sixel-capable. Alacritty is deliberately left off: upstream Alacritty has
|
||||
# no sixel support, so telling tmux otherwise would replace today's clean
|
||||
# text placeholder with garbled escape data.
|
||||
set -as terminal-features ",xterm-256color:sixel"
|
||||
|
||||
# tmux renamed the copy-mode key table (vi-copy -> copy-mode-vi) and changed
|
||||
# bind-key's table flag (-t -> -T) in 2.4. Source the file matching the
|
||||
# running tmux so old tmux never parses syntax it doesn't understand.
|
||||
if-shell "tmux -V | awk '{print $2}' | awk -F. '{if ($1*1000+$2 < 2004) exit 0; else exit 1}'" 'source-file ~/.tmux/legacy.conf' 'source-file ~/.tmux/modern.conf'
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Misc bindings
|
||||
# ----------------------------------------------------------------------------
|
||||
bind-key C run-shell "cal $(date +%Y)"
|
||||
bind r source-file ~/.tmux.conf \; display "Reloaded config"
|
||||
|
||||
# A pane whose connection died mid-redraw (e.g. an SSH session killed by the
|
||||
# laptop sleeping) can get stuck with tmux thinking the cursor is hidden,
|
||||
# since that's tracked from the pane's own output and nothing ever sent the
|
||||
# matching show-cursor sequence. Re-run it in the active pane to fix it.
|
||||
bind R send-keys "printf '\\033[?25h'" Enter
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Powerline (guarded so machines without it don't error on load)
|
||||
# ----------------------------------------------------------------------------
|
||||
run-shell "command -v powerline-daemon >/dev/null 2>&1 && powerline-daemon -q; true"
|
||||
run-shell "command -v powerline-config >/dev/null 2>&1 && powerline-config tmux setup; true"
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Status bar
|
||||
# ----------------------------------------------------------------------------
|
||||
# Flash the status bar when this client's prefix key is armed, so nested
|
||||
# tmux sessions (e.g. laptop -> ssh -> devbox tmux) make it obvious which
|
||||
# layer is about to receive the next keystroke. Falls back to whatever
|
||||
# status-style powerline set above (captured here) the rest of the time.
|
||||
# Colors match gruvbox's own visual/selection convention (bg0 on orange).
|
||||
set -g @status_style_armed "bg=#fe8019,fg=#282828"
|
||||
run-shell 'tmux set-option -g @status_style_normal "$(tmux show-options -gv status-style)"'
|
||||
set -g status-style "#{?client_prefix,#{@status_style_armed},#{@status_style_normal}}"
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Plugins (TPM)
|
||||
# ----------------------------------------------------------------------------
|
||||
set -g @plugin 'tmux-plugins/tpm'
|
||||
set -g @plugin 'tmux-plugins/tmux-sensible'
|
||||
# Checked out as a submodule under config/tmux/plugins rather than left for
|
||||
# TPM to clone on first prefix+I: ~/.tmux is a symlink to that directory, so
|
||||
# a TPM-installed plugin lands inside this repo as untracked files. The
|
||||
# submodule pins a version, installs with the existing "git submodule
|
||||
# update --init" in install.sh, and keeps git status clean. TPM still sources
|
||||
# it from the @plugin line below and can still update it.
|
||||
set -g @plugin 'sainnhe/tmux-fzf'
|
||||
|
||||
# Local overrides
|
||||
if-shell "[ -f ~/.tmux_local.conf ]" 'source ~/.tmux_local.conf'
|
||||
|
||||
# Initialize TPM (must be the last line)
|
||||
run '~/.tmux/plugins/tpm/tpm'
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
# tmux < 2.4 copy-mode key table (vi-copy, old -t flag) and mouse-wheel/
|
||||
# PageUp passthrough. Sourced conditionally from tmux.conf; see
|
||||
# tmux/modern.conf for tmux >= 2.4.
|
||||
|
||||
bind-key -t vi-copy PPage page-up
|
||||
bind-key -t vi-copy NPage page-down
|
||||
bind-key -t vi-copy WheelUpPane halfpage-up
|
||||
bind-key -t vi-copy WheelDownPane halfpage-down
|
||||
bind-key -t vi-copy v begin-selection
|
||||
bind-key -t vi-copy y copy-pipe "$HOME/dotfiles/bin/clipboard-copy"
|
||||
unbind-key -t vi-copy Enter
|
||||
bind-key -t vi-copy Enter copy-pipe "$HOME/dotfiles/bin/clipboard-copy"
|
||||
|
||||
bind-key -n PPage if-shell -F "#{alternate_on}" "send-keys PPage" "copy-mode -e; send-keys PPage"
|
||||
bind-key -n WheelUpPane if-shell -F -t = "#{alternate_on}" "send-keys -M" "select-pane -t =; copy-mode -e; send-keys -M"
|
||||
bind-key -n WheelDownPane if-shell -F -t = "#{alternate_on}" "send-keys -M" "select-pane -t =; send-keys -M"
|
||||
@@ -0,0 +1,24 @@
|
||||
# tmux >= 2.4 copy-mode key table and mouse-wheel/PageUp passthrough.
|
||||
# Sourced conditionally from tmux.conf; see tmux/legacy.conf for older tmux.
|
||||
|
||||
bind-key -T copy-mode-vi PPage send-keys -X page-up
|
||||
bind-key -T copy-mode-vi NPage send-keys -X page-down
|
||||
bind-key -T copy-mode-vi WheelUpPane send-keys -X halfpage-up
|
||||
bind-key -T copy-mode-vi WheelDownPane send-keys -X halfpage-down
|
||||
bind-key -T copy-mode-vi v send-keys -X begin-selection
|
||||
bind-key -T copy-mode-vi y send-keys -X copy-pipe "$HOME/dotfiles/bin/clipboard-copy"
|
||||
unbind-key -T copy-mode-vi Enter
|
||||
bind-key -T copy-mode-vi Enter send-keys -X copy-pipe "$HOME/dotfiles/bin/clipboard-copy"
|
||||
|
||||
# The default MouseDragEnd1Pane binding (copy-selection-and-cancel) relies on
|
||||
# tmux's own OSC 52 write via the Ms terminfo capability, which doesn't
|
||||
# reliably reach every terminal (confirmed broken against Alacritty here).
|
||||
# Route mouse-drag copies through the same clipboard-copy script as keyboard
|
||||
# yanks instead, so both use the mechanism that's actually proven to work.
|
||||
bind-key -T copy-mode-vi MouseDragEnd1Pane send-keys -X copy-pipe-and-cancel "$HOME/dotfiles/bin/clipboard-copy"
|
||||
|
||||
# Let mouse wheel / PageUp pass through to apps using the alternate screen
|
||||
# (vim, less, etc.) instead of always entering copy-mode
|
||||
bind-key -T root PPage if-shell -F "#{alternate_on}" "send-keys PPage" "copy-mode -e; send-keys PPage"
|
||||
bind-key -T root WheelUpPane if-shell -F -t = "#{alternate_on}" "send-keys -M" "select-pane -t =; copy-mode -e; send-keys -M"
|
||||
bind-key -T root WheelDownPane if-shell -F -t = "#{alternate_on}" "send-keys -M" "select-pane -t =; send-keys -M"
|
||||
Submodule
+1
Submodule config/tmux/plugins/tmux-fzf added at 4cbbbbde54
Submodule
+1
Submodule config/tmux/plugins/tpm added at 99469c4a9b
@@ -1,37 +0,0 @@
|
||||
# PREFIX | splits horizontally and PREFIX - splits vertically
|
||||
bind | split-window -h
|
||||
bind - split-window -v
|
||||
|
||||
# mouse support
|
||||
set -g mode-mouse on # scrolling
|
||||
set -g mouse-select-pane on # clicking into panes
|
||||
set -g mouse-resize-pane on # resizing panes
|
||||
set -g mouse-select-window on # select windows
|
||||
|
||||
# toggle mouse support
|
||||
bind m \
|
||||
set -g mode-mouse on \;\
|
||||
set -g mouse-resize-pane on \;\
|
||||
set -g mouse-select-pane on \;\
|
||||
set -g mouse-select-window on \;\
|
||||
display 'Mouse: ON'
|
||||
|
||||
bind M \
|
||||
set -g mode-mouse off \;\
|
||||
set -g mouse-resize-pane off \;\
|
||||
set -g mouse-select-pane off \;\
|
||||
set -g mouse-select-window off \;\
|
||||
display 'Mouse: OFF'
|
||||
|
||||
# ----------------------
|
||||
# set some pretty colors
|
||||
# ----------------------
|
||||
# set pane colors - hilight the active pane
|
||||
# set-option -g pane-border-fg colour235 #base02
|
||||
# set-option -g pane-active-border-fg colour240 #base01
|
||||
|
||||
# # colorize messages in the command line
|
||||
# set-option -g message-bg black #base02
|
||||
# set-option -g message-fg brightred #orange
|
||||
|
||||
source "$HOME/.tmux/tmux_shared.conf"
|
||||
@@ -1,2 +0,0 @@
|
||||
|
||||
source "$HOME/.tmux/tmux_shared.conf"
|
||||
@@ -1,48 +0,0 @@
|
||||
# PREFIX | splits horizontally and PREFIX - splits vertically
|
||||
bind | split-window -h -c "#{pane_current_path}"
|
||||
bind - split-window -v -c "#{pane_current_path}"
|
||||
|
||||
# open new window with pwd
|
||||
bind c new-window -c "#{pane_current_path}"
|
||||
|
||||
# PREFIX T makes current window index 1
|
||||
bind T swap-window -t 1
|
||||
|
||||
# use vim movement for panes
|
||||
bind h select-pane -L
|
||||
bind j select-pane -D
|
||||
bind k select-pane -U
|
||||
bind l select-pane -R
|
||||
|
||||
# mouse support
|
||||
set-option -g -q mouse on
|
||||
|
||||
# Copy Mode
|
||||
bind-key -t root PPage if-shell -F "#{alternate_on}" "send-keys PPage" "copy-mode -e; send-keys PPage"
|
||||
bind-key -t vi-copy PPage page-up
|
||||
bind-key -t vi-copy NPage page-down
|
||||
# Mouse Wheel
|
||||
bind-key -t root WheelUpPane if-shell -F -t = "#{alternate_on}" "send-keys -M" "select-pane -t =; copy-mode -e; send-keys -M"
|
||||
bind-key -t root WheelDownPane if-shell -F -t = "#{alternate_on}" "send-keys -M" "select-pane -t =; send-keys -M"
|
||||
bind-key -t vi-copy WheelUpPane halfpage-up
|
||||
bind-key -t vi-copy WheelDownPane halfpage-down
|
||||
|
||||
# Make sure the client is always using the correct environment
|
||||
# eval $(tmux switch-client \; show-environment -s)
|
||||
|
||||
# Copy/Paste
|
||||
#
|
||||
# provide access to clipboard
|
||||
# set-option -g default-command "reattach-to-user-namespace -l zsh"
|
||||
# set-window-option -g automatic-rename on
|
||||
|
||||
# use vim keybindings in copy mode
|
||||
setw -g mode-keys vi
|
||||
|
||||
# v selection
|
||||
bind-key -t vi-copy v begin-selection
|
||||
bind-key -t vi-copy y copy-pipe "reattach-to-user-namespace pbcopy"
|
||||
|
||||
# make enter use copy pipe
|
||||
unbind -t vi-copy Enter
|
||||
bind-key -t vi-copy Enter copy-pipe "reattach-to-user-namespace pbcopy"
|
||||
@@ -1,42 +0,0 @@
|
||||
# PREFIX | splits horizontally and PREFIX - splits vertically
|
||||
bind | split-window -h -c "#{pane_current_path}"
|
||||
bind - split-window -v -c "#{pane_current_path}"
|
||||
|
||||
# open new window with pwd
|
||||
bind c new-window -c "#{pane_current_path}"
|
||||
|
||||
# use vim keybindings in copy mode
|
||||
setw -g mode-keys vi
|
||||
|
||||
# Copy Mode
|
||||
bind-key -T copy-mode-vi PPage send-keys -X page-up
|
||||
bind-key -T copy-mode-vi NPage send-keys -X page-down
|
||||
|
||||
# Mouse Wheel
|
||||
bind-key -T copy-mode-vi WheelUpPane send-keys -X halfpage-up
|
||||
bind-key -T copy-mode-vi WheelDownPane send-keys -X halfpage-down
|
||||
|
||||
# v selection
|
||||
bind-key -T copy-mode-vi v send-keys -X begin-selection
|
||||
bind-key -T copy-mode-vi y send-keys -X copy-pipe "reattach-to-user-namespace pbcopy"
|
||||
|
||||
# make enter use copy pipe
|
||||
unbind -T copy-mode-vi Enter
|
||||
bind-key -T copy-mode-vi Enter send-keys -X copy-pipe "reattach-to-user-namespace pbcopy"
|
||||
|
||||
set-option -g -q mouse on
|
||||
set-option -g -q mouse-resize-pane on
|
||||
set-option -g -q mouse-select-pane on
|
||||
set-option -g -q mouse-select-window on
|
||||
|
||||
# Enable middle click in urxvt
|
||||
set-option -ga terminal-override ',rxvt-uni*:XT:Ms=\E]52;%p1%s;%p2%s\007'
|
||||
|
||||
# Copy Mode
|
||||
bind-key -T root PPage if-shell -F "#{alternate_on}" "send-keys PPage" "copy-mode -e; send-keys PPage"
|
||||
|
||||
# Mouse Wheel
|
||||
bind-key -T root WheelUpPane if-shell -F -t = "#{alternate_on}" "send-keys -M" "select-pane -t =; copy-mode -e; send-keys -M"
|
||||
bind-key -T root WheelDownPane if-shell -F -t = "#{alternate_on}" "send-keys -M" "select-pane -t =; send-keys -M"
|
||||
|
||||
source ~/.tmux/tmux_shared.conf
|
||||
@@ -1,42 +0,0 @@
|
||||
# PREFIX | splits horizontally and PREFIX - splits vertically
|
||||
bind | split-window -h -c "#{pane_current_path}"
|
||||
bind - split-window -v -c "#{pane_current_path}"
|
||||
|
||||
# open new window with pwd
|
||||
bind c new-window -c "#{pane_current_path}"
|
||||
|
||||
# use vim keybindings in copy mode
|
||||
setw -g mode-keys vi
|
||||
|
||||
# Copy Mode
|
||||
bind-key -T copy-mode-vi PPage send-keys -X page-up
|
||||
bind-key -T copy-mode-vi NPage send-keys -X page-down
|
||||
|
||||
# Mouse Wheel
|
||||
bind-key -T copy-mode-vi WheelUpPane send-keys -X halfpage-up
|
||||
bind-key -T copy-mode-vi WheelDownPane send-keys -X halfpage-down
|
||||
|
||||
# v selection
|
||||
bind-key -T copy-mode-vi v send-keys -X begin-selection
|
||||
bind-key -T copy-mode-vi y send-keys -X copy-pipe "reattach-to-user-namespace pbcopy"
|
||||
|
||||
# make enter use copy pipe
|
||||
unbind -T copy-mode-vi Enter
|
||||
bind-key -T copy-mode-vi Enter send-keys -X copy-pipe "reattach-to-user-namespace pbcopy"
|
||||
|
||||
set-option -g -q mouse on
|
||||
set-option -g -q mouse-resize-pane on
|
||||
set-option -g -q mouse-select-pane on
|
||||
set-option -g -q mouse-select-window on
|
||||
|
||||
# Enable middle click in urxvt
|
||||
set-option -ga terminal-override ',rxvt-uni*:XT:Ms=\E]52;%p1%s;%p2%s\007'
|
||||
|
||||
# Copy Mode
|
||||
bind-key -T root PPage if-shell -F "#{alternate_on}" "send-keys PPage" "copy-mode -e; send-keys PPage"
|
||||
|
||||
# Mouse Wheel
|
||||
bind-key -T root WheelUpPane if-shell -F -t = "#{alternate_on}" "send-keys -M" "select-pane -t =; copy-mode -e; send-keys -M"
|
||||
bind-key -T root WheelDownPane if-shell -F -t = "#{alternate_on}" "send-keys -M" "select-pane -t =; send-keys -M"
|
||||
|
||||
source ~/.tmux/tmux_shared.conf
|
||||
@@ -1,106 +0,0 @@
|
||||
# use UTF8
|
||||
# set -g utf8
|
||||
# set-window-option -g utf8 on
|
||||
|
||||
# 256 color mode
|
||||
set -g default-terminal "screen-256color"
|
||||
# set-option -sa terminal-overrides ',screen*:RGB'
|
||||
# set-option -ga terminal-overrides ',screen*:Tc'
|
||||
# set-option -sa terminal-overrides ',xterm*:RGB'
|
||||
# set-option -ga terminal-overrides ',xterm*:Tc'
|
||||
# set-option -sa terminal-overrides ',tmux*:RGB'
|
||||
# set-option -ga terminal-overrides ',tmux*:Tc'
|
||||
# set-option -sa terminal-overrides ',rxvt*:RGB'
|
||||
# set-option -ga terminal-overrides ',rxvt*:Tc'
|
||||
|
||||
# Properly handle ssh agent forwarding when reconnecting to session
|
||||
# set-environment -g 'SSH_AUTH_SOCK' ~/.ssh/ssh_auth_sock
|
||||
|
||||
set-option -g set-titles on
|
||||
# Tmux attach will create a new session if one doesn't exist
|
||||
# new-session -n $HOST
|
||||
|
||||
# set scrollback history
|
||||
set -g history-limit 10000
|
||||
|
||||
# set Ctrl-a as prefix and unbind Ctrl-b
|
||||
set -g prefix C-a
|
||||
unbind C-b
|
||||
|
||||
# last active window
|
||||
# bind-key C-a last-window
|
||||
bind Tab last-window
|
||||
|
||||
# pass prefix through to application
|
||||
bind C-a send-prefix
|
||||
|
||||
# don't constrain size unless smaller client looking at window
|
||||
setw -g aggressive-resize on
|
||||
|
||||
# set command delay
|
||||
set -sg escape-time 1
|
||||
|
||||
# set base index to 1 rather than 0
|
||||
set-option -g base-index 1
|
||||
setw -g pane-base-index 1
|
||||
|
||||
# use PREFIX-r to reload config
|
||||
bind r source-file ~/.tmux/tmux_shared.conf \; display "Reloaded config"
|
||||
|
||||
# PREFIX T makes current window index 1
|
||||
bind T swap-window -t 1
|
||||
|
||||
# use vim movement for panes
|
||||
bind h select-pane -L
|
||||
bind j select-pane -D
|
||||
bind k select-pane -U
|
||||
bind l select-pane -R
|
||||
|
||||
# Smart pane switching with awareness of vim splits
|
||||
is_vim='echo "#{pane_current_command}" | grep -iqE "(^|\/)g?(view|n?vim?)(diff)?$"'
|
||||
bind -n C-h if-shell "$is_vim" "send-keys C-h" "select-pane -L"
|
||||
bind -n C-j if-shell "$is_vim" "send-keys C-j" "select-pane -D"
|
||||
bind -n C-k if-shell "$is_vim" "send-keys C-k" "select-pane -U"
|
||||
bind -n C-l if-shell "$is_vim" "send-keys C-l" "select-pane -R"
|
||||
bind -n 'C-\' if-shell "$is_vim" "send-keys 'C-\\'" "select-pane -l"
|
||||
|
||||
# bind C-h and C-l to cycle through panes
|
||||
bind -r C-h select-window -t :-
|
||||
bind -r C-l select-window -t :+
|
||||
|
||||
# Synchonize keyboard input across panes
|
||||
bind a setw synchronize-panes
|
||||
|
||||
# open calendar
|
||||
bind-key C run-shell "cal $(date +%Y)"
|
||||
|
||||
# Make sure the client is always using the correct environment
|
||||
# eval $(tmux switch-client \; show-environment -s)
|
||||
|
||||
bind y run 'tmux save-buffer - | reattach-to-user-namespace pbcopy '
|
||||
bind C-y run 'tmux save-buffer - | reattach-to-user-namespace pbcopy '1
|
||||
|
||||
# ----------------------
|
||||
# set some pretty colors
|
||||
# ----------------------
|
||||
# set pane colors - hilight the active pane
|
||||
# set-option -g pane-border-fg colour235 #base02
|
||||
# set-option -g pane-active-border-fg colour240 #base01
|
||||
|
||||
# Show active pane
|
||||
# set-window-option -g window-style 'bg=#181818'
|
||||
# set-window-option -g window-active-style 'bg=black'
|
||||
# set-window-option -g pane-active-border-style ''
|
||||
# set-window-option -g pane-active-border-style 'fg=#181818'
|
||||
|
||||
# colorize messages in the command line
|
||||
# set-option -g message-bg black #base02
|
||||
# set-option -g message-fg brightred #orange
|
||||
|
||||
# Powerline
|
||||
run-shell "powerline-daemon -q"
|
||||
run-shell "powerline-config tmux setup"
|
||||
# source-file $POWERLINE_ROOT/bindings/tmux/powerline.conf
|
||||
|
||||
# Local overrides
|
||||
if-shell "[ -f ~/.tmux_local.conf ]" 'source ~/.tmux_local.conf'
|
||||
@@ -1,27 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
verify_tmux_version() {
|
||||
tmux_home=~/.tmux
|
||||
tmux_version="$(tmux -V | cut -c 6-)"
|
||||
|
||||
# This is necessary because 3.1c gives a syntax error in bc
|
||||
# TODO Fix this it will break with the next tmux version
|
||||
if [[ $tmux_version -eq "3.1c"]] ; then
|
||||
tmux source-file $tmux_home/tmux_3.1c.conf
|
||||
exit
|
||||
if [[ $(echo "$tmux_version >= 2.5" | bc) -eq 1 ]] ; then
|
||||
tmux source-file $tmux_home/tmux_3.1c.conf
|
||||
exit
|
||||
elif [[ $(echo "$tmux_version >= 2.1" | bc) -eq 1 ]] ; then
|
||||
tmux source-file $tmux_home/tmux_2.1_to_2.5.conf
|
||||
exit
|
||||
elif [[ $(echo "$tmux_version >= 1.9" | bc) -eq 1 ]] ; then
|
||||
tmux source-file $tmux_home/tmux_1.9_to_2.1.conf
|
||||
exit
|
||||
else
|
||||
tmux source-file $tmux_home/tmux_1.9_down.conf
|
||||
exit
|
||||
fi
|
||||
}
|
||||
|
||||
verify_tmux_version
|
||||
@@ -0,0 +1 @@
|
||||
ACTION=="change", SUBSYSTEM=="drm", RUN+="/usr/bin/systemctl start --no-block update-wallpapers.service"
|
||||
+90
-3
@@ -1,3 +1,30 @@
|
||||
# Returns 0 if program is installed and 1 otherwise
|
||||
function program_installed {
|
||||
local return_=0
|
||||
|
||||
type $1 >/dev/null 2>&1 || { local return_=1; }
|
||||
|
||||
return "$return_"
|
||||
}
|
||||
|
||||
function cd {
|
||||
builtin cd "$@"
|
||||
|
||||
if [[ -z "$VIRTUAL_ENV" ]] ; then
|
||||
# If env folder is found then activate the vitualenv
|
||||
if [[ -d ./venv ]] ; then
|
||||
source ./venv/bin/activate
|
||||
fi
|
||||
else
|
||||
# If no longer within virtualenv, deactivate
|
||||
parentdir="$(dirname "$VIRTUAL_ENV")"
|
||||
if [[ "$PWD"/ != "$parentdir"/* ]] ; then
|
||||
deactivate
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
function list_processes() {
|
||||
# List all processes matching the given process name string
|
||||
ps aux | grep $(whoami) | grep -i "$1" | grep -v grep
|
||||
@@ -51,13 +78,19 @@ function check_dotfiles_version {
|
||||
# Return 2 if the repo is behind the remote
|
||||
# Return 3 if the repo is ahead of the remote
|
||||
# Return 4 if the repo has diverged from the remote
|
||||
if [ ! -d $HOME/dotfiles ]; then
|
||||
# Return 5 if DOTFILES_DIR is not set
|
||||
if [ -z $DOTFILES_DIR ]; then
|
||||
return 5
|
||||
fi
|
||||
|
||||
if [ ! -d $DOTFILES_DIR ]; then
|
||||
return 2
|
||||
fi
|
||||
|
||||
pushd $HOME/dotfiles > /dev/null
|
||||
pushd $DOTFILES_DIR > /dev/null
|
||||
|
||||
git fetch origin
|
||||
# TODO: This may be gitbox
|
||||
git fetch origin > /dev/null
|
||||
UPSTREAM=${1:-'@{u}'}
|
||||
LOCAL=$(git rev-parse @)
|
||||
REMOTE=$(git rev-parse "$UPSTREAM")
|
||||
@@ -75,3 +108,57 @@ function check_dotfiles_version {
|
||||
return 4
|
||||
fi
|
||||
}
|
||||
|
||||
function set_python_roots {
|
||||
PYTHON_ROOTS=()
|
||||
if [ -d $HOME/.local/lib/ ]; then
|
||||
for directory in $(echo $HOME/.local/lib/python*(N)); do
|
||||
PYTHON_ROOTS+=$directory
|
||||
done
|
||||
fi
|
||||
if [ -d $HOME/.local/share/pipx/venvs/powerline-status/lib/ ]; then
|
||||
for directory in $(echo $HOME/.local/share/pipx/venvs/powerline-status/lib/python*(N)); do
|
||||
PYTHON_ROOTS+=$directory
|
||||
done
|
||||
fi
|
||||
if [ -d $HOME/.local/pipx/venvs/powerline-status/lib/ ]; then
|
||||
for directory in $(echo $HOME/.local/pipx/venvs/powerline-status/lib/python*(N)); do
|
||||
PYTHON_ROOTS+=$directory
|
||||
done
|
||||
fi
|
||||
if [ -d /usr/lib/ ]; then
|
||||
for directory in $(echo /usr/lib/python*(N)); do
|
||||
PYTHON_ROOTS+=$directory
|
||||
done
|
||||
fi
|
||||
if [ -d /usr/local/lib/ ]; then
|
||||
# TODO: Make this not print warnings when the directory doesn't exit
|
||||
for directory in $(echo /usr/local/lib/python*(N)); do
|
||||
PYTHON_ROOTS+=$directory
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
function set_powerline_zsh_sources {
|
||||
set_python_roots
|
||||
# Powerline plugin from distribution agnostic install directory
|
||||
## Assemble list of possible sources
|
||||
declare -ag POWERLINE_ZSH_SOURCES=()
|
||||
if [[ -a $POWERLINE_ROOT/bindings/zsh/powerline.zsh ]]; then
|
||||
# Prefer user-set powerline directory
|
||||
POWERLINE_ZSH_SOURCES+=$POWERLINE_ROOT/bindings/zsh/powerline.zsh
|
||||
fi
|
||||
if [ -d /usr/share/powerline ]; then
|
||||
# Apt installs here
|
||||
POWERLINE_ZSH_SOURCES+="/usr/share/powerline/bindings/zsh/powerline.zsh"
|
||||
fi
|
||||
# If $POWERLINE_ROOT not set or set incorrectly, try default locations
|
||||
for directory in $PYTHON_ROOTS; do
|
||||
#for directory in $(echo $template); do
|
||||
if [ -d "$directory" ]; then
|
||||
POWERLINE_ZSH_SOURCES+="$directory"/site-packages/powerline/bindings/zsh/powerline.zsh
|
||||
POWERLINE_ZSH_SOURCES+="$directory"/dist-packages/powerline/bindings/zsh/powerline.zsh
|
||||
fi
|
||||
# done
|
||||
done
|
||||
}
|
||||
|
||||
+196
-190
@@ -1,92 +1,91 @@
|
||||
# Gruvbox colors
|
||||
# source "$HOME/.vim/bundle/gruvbox/gruvbox_256palette.sh"
|
||||
[[ -f "$HOME/dotfiles/dependencies/gruvbox/gruvbox_256palette.sh" ]] && source "$HOME/dotfiles/dependencies/gruvbox/gruvbox_256palette.sh"
|
||||
# ZSH-specific environment variables
|
||||
# Override in .profile.local
|
||||
|
||||
# Custom functions
|
||||
source "$HOME/.zsh_functions"
|
||||
|
||||
# Path to your oh-my-zsh installation.
|
||||
export ZSH=$HOME/dotfiles/dependencies/ohmyzsh
|
||||
#export RUST_SRC_PATH=/usr/local/src/rust/src
|
||||
|
||||
# Z
|
||||
# . $HOME/dotfiles/z/z.sh
|
||||
# Set name of the theme to load.
|
||||
# # Look in ~/.oh-my-zsh/themes/
|
||||
# # Optionally, if you set this to "random", it'll load a random theme each
|
||||
# # time that oh-my-zsh is loaded.
|
||||
## oh-my-zsh
|
||||
# Automatically update oh-my-zsh without asking
|
||||
DISABLE_UPDATE_PROMPT=true
|
||||
# Disable oh-my-zsh auto-update checks
|
||||
DISABLE_AUTO_UPDATE=false
|
||||
# How often to check for oh-my-zsh updates
|
||||
UPDATE_ZSH_DAYS=30
|
||||
# Disable cowsay on login by default.
|
||||
NO_ZSHRC_COWSAY=1
|
||||
# Theme to load [~/.oh-my-zsh/themes/]
|
||||
ZSH_THEME="agnoster"
|
||||
# Base16 Shell
|
||||
# BASE16_SHELL="$HOME/.config/base16-shell/base16-tomorrow.dark.sh"
|
||||
# [[ -s $BASE16_SHELL ]] && source $BASE16_SHELL
|
||||
# BASE16_SHELL="$HOME/.config/base16-shell/base16-ocean.dark.sh"
|
||||
# [[ -s $BASE16_SHELL ]] && source $BASE16_SHELL
|
||||
#
|
||||
# # Uncomment the following line to use case-sensitive completion.
|
||||
# # CASE_SENSITIVE="true"
|
||||
#
|
||||
# # Uncomment the following line to disable bi-weekly auto-update checks.
|
||||
# # DISABLE_AUTO_UPDATE="true"
|
||||
#
|
||||
# # Uncomment the following line to change how often to auto-update (in days).
|
||||
# # export UPDATE_ZSH_DAYS=13
|
||||
#
|
||||
# # Uncomment the following line to disable colors in ls.
|
||||
# # DISABLE_LS_COLORS="true"
|
||||
#
|
||||
# # Uncomment the following line to disable auto-setting terminal title.
|
||||
# # DISABLE_AUTO_TITLE="true"
|
||||
#
|
||||
# # Uncomment the following line to enable command auto-correction.
|
||||
# # ENABLE_CORRECTION="true"
|
||||
#
|
||||
# # Uncomment the following line to display red dots whilst waiting for completion.
|
||||
# # COMPLETION_WAITING_DOTS="true"
|
||||
#
|
||||
# # Uncomment the following line if you want to disable marking untracked files
|
||||
# # under VCS as dirty. This makes repository status check for large repositories
|
||||
# # much, much faster.
|
||||
# # DISABLE_UNTRACKED_FILES_DIRTY="true"
|
||||
#
|
||||
# # Uncomment the following line if you want to change the command execution time
|
||||
# # stamp shown in the history command output.
|
||||
# # The optional three formats: "mm/dd/yyyy"|"dd.mm.yyyy"|"yyyy-mm-dd"
|
||||
# # HIST_STAMPS="mm/dd/yyyy"
|
||||
#
|
||||
# # Would you like to use another custom folder than $ZSH/custom?
|
||||
# # ZSH_CUSTOM=/path/to/new-custom-folder
|
||||
# Automatic window title setting
|
||||
DISABLE_AUTO_TITLE="true"
|
||||
# Command correction support
|
||||
ENABLE_CORRECTION="false"
|
||||
# Case-sensitive completion
|
||||
CASE_SENSITIVE="false"
|
||||
# ls colors
|
||||
DISABLE_LS_COLORS="false"
|
||||
# Red ... on completion waiting
|
||||
COMPLETION_WAITING_DOTS="true"
|
||||
|
||||
# # zsh-syntax-highlighting must come last
|
||||
plugins=(archlinux colorize command-not-found cp git github bower grunt npm macos)
|
||||
# tmux
|
||||
zmodload zsh/zpty
|
||||
|
||||
# # User configuration
|
||||
|
||||
# Enable environment variables as CD directories
|
||||
setopt cdablevars
|
||||
# Enable correction for mistyped commands
|
||||
unsetopt correctall
|
||||
# alias make='nocorrect make'
|
||||
# alias git='nocorrect git'
|
||||
|
||||
#PATHs
|
||||
#export PATH=$HOME/bin:/usr/local/bin:$PATH
|
||||
#export MANPATH="/usr/local/man:$MANPATH"
|
||||
#PATH="$(ruby -e 'puts Gem.user_dir')/bin:$PATH"
|
||||
# Add user cowpath to COWPATH
|
||||
#COWPATH="$COWPATH:$HOME/dotfiles/cowfiles"
|
||||
# Make a random (cow?) with a random face say something
|
||||
# fortune -a | fmt -80 -s | cowthink -$(shuf -n 1 -e b d g p s t w y) -f $(shuf -n 1 -e $(cowsay -l | tail -n +2)) -n
|
||||
# Uncomment the following line if you want to disable marking untracked files
|
||||
# under VCS as dirty. This makes repository status check for large repositories
|
||||
# much, much faster.
|
||||
# DISABLE_UNTRACKED_FILES_DIRTY="true"
|
||||
#
|
||||
# Uncomment the following line if you want to change the command execution time
|
||||
# stamp shown in the history command output.
|
||||
# The optional three formats: "mm/dd/yyyy"|"dd.mm.yyyy"|"yyyy-mm-dd"
|
||||
# HIST_STAMPS="mm/dd/yyyy"
|
||||
|
||||
# User profiles
|
||||
source $HOME/.profile
|
||||
# Define $POWERLINE_ROOT
|
||||
if [ -f $HOME/.profile.local ]; then
|
||||
set -a
|
||||
source $HOME/.profile.local
|
||||
set +a
|
||||
fi
|
||||
|
||||
source $ZSH/oh-my-zsh.sh
|
||||
# Custom functions
|
||||
source "$HOME/.zsh_functions"
|
||||
|
||||
if [ -n "$DOTFILES_DIR" ] && [ -d "$DOTFILES_DIR" ]; then
|
||||
# Load dependencies
|
||||
## oh-my-zsh
|
||||
if [ ! -f "$DOTFILES_DIR/dependencies/ohmyzsh/oh-my-zsh.sh" ]; then
|
||||
cd "$DOTFILES_DIR"
|
||||
git submodule update --init
|
||||
cd -
|
||||
fi
|
||||
export ZSH=$DOTFILES_DIR/dependencies/ohmyzsh
|
||||
## Gruvbox colors
|
||||
[[ -f "$DOTFILES_DIR/dependencies/gruvbox/gruvbox_256palette.sh" ]] && source "$DOTFILES_DIR/dependencies/gruvbox/gruvbox_256palette.sh"
|
||||
fi
|
||||
missing_dependencies=()
|
||||
for dependency in "${dependencies[@]}"; do
|
||||
if ! program_installed $dependency; then
|
||||
missing_dependencies+="$dependency"
|
||||
fi
|
||||
done
|
||||
if [ "${#missing_dependencies[@]}" -gt 0 ]; then
|
||||
echo "Missing dependencies: ${missing_dependencies[@]}"
|
||||
fi
|
||||
|
||||
# Dircolors
|
||||
# eval $(dircolors ~/.dircolors)
|
||||
|
||||
# tmux
|
||||
zmodload zsh/zpty
|
||||
|
||||
# Enable environment variables as CD directories
|
||||
setopt cdablevars
|
||||
# Enable correction for mistyped commands
|
||||
unsetopt correctall
|
||||
setopt appendhistory autocd extendedglob
|
||||
unsetopt beep
|
||||
|
||||
alias -s txt=vim
|
||||
alias -s .c=vim
|
||||
|
||||
if [ -d $ZSH ] && [ ! -z $ZSH ]; then
|
||||
source $ZSH/oh-my-zsh.sh
|
||||
fi
|
||||
|
||||
# Italic support
|
||||
if [ -f $HOME/.xterm-256color-italic.terminfo ]; then
|
||||
@@ -96,114 +95,19 @@ if [ -f $HOME/.screen-256color-italic.terminfo ]; then
|
||||
tic $HOME/.screen-256color-italic.terminfo
|
||||
fi
|
||||
|
||||
# TODO: Remove this
|
||||
# Use neovim where available
|
||||
if type nvim > /dev/null 2>&1; then
|
||||
alias vim='nvim'
|
||||
fi
|
||||
# if type nvim > /dev/null 2>&1; then
|
||||
# alias vim='nvim'
|
||||
# fi
|
||||
|
||||
# # Preferred editor for local and remote sessions
|
||||
# # if [[ -n $SSH_CONNECTION ]]; then
|
||||
export EDITOR='vim'
|
||||
# export EDITOR='vim'
|
||||
# export TERM=xterm-256color
|
||||
# TODO ====
|
||||
|
||||
# # else
|
||||
# # export EDITOR='mvim'
|
||||
# # fi
|
||||
#
|
||||
# # Compilation flags
|
||||
# # export ARCHFLAGS="-arch x86_64"
|
||||
#
|
||||
# # ssh
|
||||
# # export SSH_KEY_PATH="~/.ssh/dsa_id"
|
||||
#
|
||||
# # Set personal aliases, overriding those provided by oh-my-zsh libs,
|
||||
# # plugins, and themes. Aliases can be placed here, though oh-my-zsh
|
||||
# # users are encouraged to define aliases within the ZSH_CUSTOM folder.
|
||||
# # For a full list of active aliases, run `alias`.
|
||||
# #
|
||||
# # Example aliases
|
||||
# # alias zshconfig="mate ~/.zshrc"
|
||||
# # alias ohmyzsh="mate ~/.oh-my-zsh"
|
||||
alias -s txt=vim
|
||||
alias -s .c=vim
|
||||
# Crontab
|
||||
#alias crontab-e='vim ~/.crontab && crontab ~/.crontab'
|
||||
|
||||
# Lines configured by zsh-newuser-install
|
||||
setopt appendhistory autocd extendedglob
|
||||
unsetopt beep
|
||||
bindkey -v
|
||||
# End of lines configured by zsh-newuser-install
|
||||
# The following lines were added by compinstall
|
||||
zstyle :compinstall filename '~/.zshrc'
|
||||
|
||||
autoload -Uz compinit
|
||||
compinit
|
||||
# End of lines added by compinstall
|
||||
|
||||
DEFAULT_USER=brad
|
||||
|
||||
# Syntax highlighting configuration
|
||||
# ZSH_HIGHLIGHT_STYLES[path]='bold'
|
||||
# ZSH_HIGHLIGHT_STYLES[path_prefix]=none
|
||||
# ZSH_HIGHLIGHT_STYLES[path_approx]='fg=yellow'
|
||||
# ZSH_HIGHLIGHT_STYLES[globbing]='fg=yellow'
|
||||
|
||||
# Source files
|
||||
#typeset -ga sources
|
||||
#sources+=$HOME/dotfiles/shortcuts.txt
|
||||
|
||||
# Powerline plugin from distribution agnostic install directory
|
||||
# pip install --user powerline-status &>/dev/null
|
||||
if [[ -a $POWERLINE_ROOT/bindings/zsh/powerline.zsh ]]; then
|
||||
# Prefer user-set powerline directory
|
||||
sources+=$POWERLINE_ROOT/bindings/zsh/powerline.zsh
|
||||
else
|
||||
echo "Attempting to source Powerline bindings from default locations.\nPlease set \$POWERLINE_ROOT in .profile.local"
|
||||
# If $POWERLINE_ROOT not set or set incorrectly, try default locations
|
||||
sources+=$HOME/.local/lib/python2.6/site-packages/powerline/bindings/zsh/powerline.zsh
|
||||
sources+=$HOME/.local/lib/python2.6/dist-packages/powerline/bindings/zsh/powerline.zsh
|
||||
sources+=$HOME/.local/lib/python2.7/site-packages/powerline/bindings/zsh/powerline.zsh
|
||||
sources+=$HOME/.local/lib/python2.7/dist-packages/powerline/bindings/zsh/powerline.zsh
|
||||
sources+=$HOME/.local/lib/python3.6/site-packages/powerline/bindings/zsh/powerline.zsh
|
||||
sources+=$HOME/.local/lib/python3.6/dist-packages/powerline/bindings/zsh/powerline.zsh
|
||||
sources+=/usr/lib/python2.6/site-packages/powerline/bindings/zsh/powerline.zsh
|
||||
sources+=/usr/lib/python2.6/dist-packages/powerline/bindings/zsh/powerline.zsh
|
||||
sources+=/usr/local/lib/python2.6/site-packages/powerline/bindings/zsh/powerline.zsh
|
||||
sources+=/usr/local/lib/python2.6/dist-packages/powerline/bindings/zsh/powerline.zsh
|
||||
sources+=/usr/lib/python2.7/site-packages/powerline/bindings/zsh/powerline.zsh
|
||||
sources+=/usr/lib/python2.7/dist-packages/powerline/bindings/zsh/powerline.zsh
|
||||
sources+=/usr/local/lib/python2.7/site-packages/powerline/bindings/zsh/powerline.zsh
|
||||
sources+=/usr/local/lib/python2.7/dist-packages/powerline/bindings/zsh/powerline.zsh
|
||||
sources+=/usr/lib/python3.6/site-packages/powerline/bindings/zsh/powerline.zsh
|
||||
sources+=/usr/lib/python3.6/dist-packages/powerline/bindings/zsh/powerline.zsh
|
||||
sources+=/usr/local/lib/python3.6/site-packages/powerline/bindings/zsh/powerline.zsh
|
||||
sources+=/usr/local/lib/python3.6/dist-packages/powerline/bindings/zsh/powerline.zsh
|
||||
fi
|
||||
foreach file (`echo $sources`)
|
||||
if [[ -a $file ]]; then
|
||||
source $file
|
||||
fi
|
||||
end
|
||||
|
||||
# Check dotfiles version
|
||||
check_dotfiles_version
|
||||
dotfiles_version=$?
|
||||
if [[ $dotfiles_version = 1 ]]; then
|
||||
echo "Dotfiles repository not present at $HOME/dotfiles"
|
||||
elif [[ $dotfiles_version = 2 ]]; then
|
||||
echo "Dotfiles repository at $HOME/dotfiles is outdated"
|
||||
elif [[ $dotfiles_version = 3 ]]; then
|
||||
echo "Dotfiles repository at $HOME/dotfiles is ahead of origin"
|
||||
elif [[ $dotfiles_version = 4 ]]; then
|
||||
echo "Dotfiles repository at $HOME/dotfiles has diverged from origin"
|
||||
fi
|
||||
|
||||
# TMuxinator Completion
|
||||
# source ~/bin/tmuxinator.zsh
|
||||
|
||||
# Dircolors
|
||||
# eval $(dircolors ~/.dircolors)
|
||||
|
||||
# Keybindings
|
||||
bindkey -M vicmd 'K' run-help
|
||||
@@ -215,26 +119,128 @@ bindkey -M viins ',,' vi-cmd-mode
|
||||
#bindkey '^o' ranger-cd
|
||||
#zle -N terminal-clock
|
||||
#bindkey '^t' terminal-clock
|
||||
# TMuxinator Completion
|
||||
# source ~/bin/tmuxinator.zsh
|
||||
|
||||
#alias sl="sl -laF"
|
||||
zstyle :compinstall filename '~/.zshrc'
|
||||
autoload -Uz compinit
|
||||
compinit
|
||||
|
||||
DEFAULT_USER="$USER"
|
||||
|
||||
# Syntax highlighting configuration
|
||||
# ZSH_HIGHLIGHT_STYLES[path]='bold'
|
||||
# ZSH_HIGHLIGHT_STYLES[path_prefix]=none
|
||||
# ZSH_HIGHLIGHT_STYLES[path_approx]='fg=yellow'
|
||||
# ZSH_HIGHLIGHT_STYLES[globbing]='fg=yellow'
|
||||
|
||||
# Source files
|
||||
#typeset -ga sources
|
||||
#sources+=$DOTFILES_DIR/shortcuts.txt
|
||||
|
||||
# Check dotfiles version
|
||||
if [ -n "$NO_GIT_CHECK" ] && [ ! "$NO_GIT_CHECK" -eq 1 ]; then
|
||||
# 5 second timeout to avoid delaying
|
||||
timeout -k 5 5s $(which zsh) -c 'source ~/.zsh_functions && check_dotfiles_version'
|
||||
dotfiles_version=$?
|
||||
if [[ $dotfiles_version = 1 ]]; then
|
||||
echo "Dotfiles repository not present at $DOTFILES_DIR"
|
||||
elif [[ $dotfiles_version = 2 ]]; then
|
||||
echo "Dotfiles repository at $DOTFILES_DIR is outdated"
|
||||
elif [[ $dotfiles_version = 3 ]]; then
|
||||
echo "Dotfiles repository at $DOTFILES_DIR is ahead of origin"
|
||||
elif [[ $dotfiles_version = 4 ]]; then
|
||||
echo "Dotfiles repository at $DOTFILES_DIR has diverged from origin"
|
||||
elif [[ $dotfiles_version = 5 ]]; then
|
||||
echo "Dotfiles repository not set in $HOME/.dotfiles-config"
|
||||
echo "Please run ./install.sh in dotfiles repository and exit to create ~/.dotfiles-config"
|
||||
echo "The following will not work until this is set:"
|
||||
echo " - oh-my-zsh will not be started"
|
||||
echo " - gruvbox color palette will not be loaded"
|
||||
echo ""
|
||||
fi
|
||||
fi
|
||||
|
||||
# Powerline
|
||||
if program_installed powerline; then
|
||||
if [ -n "$POWERLINE_ROOT" ] && \
|
||||
[ -f "$POWERLINE_ROOT" ] && \
|
||||
[ -f "$POWERLINE_ROOT/bindings/zsh/powerline.zsh" ]; then
|
||||
# Skip lookup if location is known
|
||||
source "$POWERLINE_ROOT/bindings/zsh/powerline.zsh"
|
||||
else
|
||||
found=0
|
||||
set_powerline_zsh_sources
|
||||
for file in $POWERLINE_ZSH_SOURCES; do
|
||||
if [[ -a $file ]]; then
|
||||
# TODO: Store the POWERLINE_ROOT in .profile.local if found
|
||||
source $file
|
||||
found=1
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [ $found -eq 0 ]; then
|
||||
echo "Powerline binding not found.\nPlease set \$POWERLINE_ROOT in .profile.local"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Tool options
|
||||
export SHELLCHECK_OPTS="-e SC2029 -e SC2155"
|
||||
|
||||
# Limit claude-code: cap CPU/memory/process count
|
||||
# Adjust the -p values if these limits are ever too tight.
|
||||
# if program_installed claude && program_installed systemd-run; then
|
||||
# claude() {
|
||||
# systemd-run --user --scope --quiet \
|
||||
# -p CPUQuota=50% \
|
||||
# -p MemoryMax=6G \
|
||||
# -p TasksMax=512 \
|
||||
# -- command claude "$@"
|
||||
# }
|
||||
# fi
|
||||
|
||||
# Syntax highlighting
|
||||
if [ -f /usr/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh ]; then
|
||||
source /usr/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
|
||||
fi
|
||||
|
||||
# fzf fuzzy finder
|
||||
if program_installed fzf; then
|
||||
# TODO: This is broken on debian fzf (no --zsh)
|
||||
source <(fzf --zsh)
|
||||
fi
|
||||
|
||||
# thefuck command correction
|
||||
if program_installed fuck; then
|
||||
eval "$(thefuck --alias)"
|
||||
fi
|
||||
|
||||
# pyenv-virtualenv (for managing virtualenvs for different python versions)
|
||||
if program_installed pyenv; then
|
||||
export PYENV_ROOT="$HOME/.pyenv"
|
||||
export PYENV_VIRTUALENV_DISABLE_PROMPT=1
|
||||
[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"
|
||||
eval "$(pyenv init - zsh)"
|
||||
# eval "$(pyenv virtualenv-init -)"
|
||||
fi
|
||||
|
||||
# oh-my-zsh plugins (must come after all initialization above)
|
||||
plugins=(archlinux colored-man-pages colorize command-not-found cp docker docker-compose fzf git history history-substring-search nmap npm pip poetry pyenv macos rsync snap ssh sudo systemd terraform thefuck tmux tmuxinator vi-mode virtualenv yarn zsh-interactive-cd zsh-navigation-tools)
|
||||
|
||||
# Local overrides
|
||||
if [ -f $HOME/.zshrc_local ]; then
|
||||
source $HOME/.zshrc_local
|
||||
fi
|
||||
|
||||
if [ -f ~/.fzf.zsh ]; then
|
||||
source ~/.fzf.zsh
|
||||
# Fun stupid opt-in stuff on new shell. Enable these in .profile.local
|
||||
if program_installed neofetch; then
|
||||
if [ ! -n "$NO_NEOFETCH" ] || [ "$NO_NEOFETCH" -eq 1 ]; then
|
||||
else
|
||||
neofetch
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -f /usr/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh ]; then
|
||||
source /usr/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
|
||||
if [ -n "$NO_ZSHRC_COWSAY" ] && [ ! "$NO_ZSHRC_COWSAY" -eq 1 ]; then
|
||||
# Make a random (cow?) with a random face say something
|
||||
fortune -a | fmt -80 -s | cowthink -$(shuf -n 1 -e b d g p s t w y) -f $(shuf -n 1 -e $(cowsay -l | tail -n +2)) -n
|
||||
fi
|
||||
|
||||
# pyenv-virtualenv (for managing virtualenvs for different python versions)
|
||||
#export PYENV_VIRTUALENV_DISABLE_PROMPT=1
|
||||
#eval "$(pyenv init -)"
|
||||
#eval "$(pyenv virtualenv-init -)"
|
||||
|
||||
Executable
+274
@@ -0,0 +1,274 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Source .profile.local in case it's been recently updated with repo
|
||||
source "$HOME/.profile"
|
||||
if [ -f "$HOME/.profile.local" ]; then
|
||||
set -a
|
||||
source "$HOME/.profile.local"
|
||||
set +a
|
||||
fi
|
||||
if [ -f "$HOME/.dotfiles-config" ]; then
|
||||
source "$HOME/.dotfiles-config"
|
||||
else
|
||||
echo "Dotfiles repository not set in $HOME/.dotfiles-config"
|
||||
echo "Please run ./install.sh in dotfiles repository and exit to create ~/.dotfiles-config"
|
||||
exit 1
|
||||
fi
|
||||
if [ -z "$DOTFILES_LOCAL_REPOSITORY" ]; then
|
||||
echo "Local dotfiles repository not set. Please set this in .profile"
|
||||
exit 1
|
||||
fi
|
||||
source "$DOTFILES_DIR/functions.sh"
|
||||
|
||||
# Check if running interactively
|
||||
if [ -t 0 ]; then
|
||||
# Interactive session
|
||||
interactive=1
|
||||
else
|
||||
# Non-interactive session (e.g. Coder workspace initialization)
|
||||
interactive=0
|
||||
fi
|
||||
|
||||
dir="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" # dotfiles-local repository directory
|
||||
locals_dir="$dir/dependencies/dotfiles-local"
|
||||
config_dir="$locals_dir"/config
|
||||
dotfiles_packages_root="$DOTFILES_DIR/packages"
|
||||
|
||||
package_lists="
|
||||
apt
|
||||
arch
|
||||
aur
|
||||
brew
|
||||
flatpak
|
||||
pipx
|
||||
snap
|
||||
"
|
||||
|
||||
home_files="
|
||||
bashrc_local
|
||||
zshrc_local
|
||||
profile.local
|
||||
tmux_local.conf
|
||||
nvim_local.vimrc
|
||||
"
|
||||
|
||||
configs="
|
||||
i3/config.local
|
||||
"
|
||||
|
||||
# Clone dotfiles_local if not present
|
||||
if [ ! -d "$locals_dir" ]; then
|
||||
echo "Cloning local dotfiles repository:"
|
||||
echo "$DOTFILES_LOCAL_REPOSITORY"
|
||||
git clone "$DOTFILES_LOCAL_REPOSITORY" "$locals_dir"
|
||||
fi
|
||||
|
||||
cd "$locals_dir"
|
||||
|
||||
if ! program_installed git; then
|
||||
echo "git not installed, please install and rerun"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Ask machine name and set branch
|
||||
if [ -n "$1" ]; then
|
||||
branch_name="$1"
|
||||
else
|
||||
if [ "$interactive" == 0 ]; then
|
||||
echo "Non-interactive sessions must specify a branch name. Rerun with:"
|
||||
echo "> ./dotfiles-local.sh {branch_name}"
|
||||
exit 1
|
||||
fi
|
||||
echo -n "What machine name would you like to use for this branch? [$(hostname)] "
|
||||
read response
|
||||
if [ -z "$response" ]; then
|
||||
# echo "Please enter a valid name for this machine's branch. Rerun with:"
|
||||
# echo "> ./dotfiles-local.sh {branch_name}"
|
||||
# exit 1
|
||||
branch_name="$(hostname)"
|
||||
else
|
||||
branch_name="$response"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check if already on branch
|
||||
if [ $(git rev-parse --abbrev-ref HEAD) == "$branch_name" ]; then
|
||||
echo "Already on branch $branch_name"
|
||||
else
|
||||
# Check if branch already exists
|
||||
git ls-remote --exit-code --heads origin "$branch_name" > /dev/null
|
||||
if [ $? == 0 ]; then
|
||||
echo "$branch_name branch exists, checking out existing branch"
|
||||
# TODO: This doesn't work if the local branch already exists
|
||||
# Should just check if we're already on the branch
|
||||
git checkout -b "$branch_name" "origin/$branch_name"
|
||||
else
|
||||
echo "$branch_name branch doesn't exist yet, creating and checking out new branch"
|
||||
git checkout main
|
||||
git checkout -b "$branch_name"
|
||||
fi
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Move any existing local installation script into repo and symlink out
|
||||
skip=0
|
||||
if [ -f "$DOTFILES_DIR/install_local.sh" ]; then
|
||||
echo "Discovered local installation script install_local.sh"
|
||||
# Check if file is a symlink
|
||||
if [[ -L "$DOTFILES_DIR/install_local.sh" ]]; then
|
||||
# TODO: Make sure that it's actually linked from here and not somewhere else
|
||||
echo "Skipping: install_local.sh because file already linked"
|
||||
skip=1
|
||||
elif [[ -f "$DOTFILES_DIR/install_local.sh" ]]; then
|
||||
if [[ -f "$locals_dir/install_local.sh" ]]; then
|
||||
# TODO: Do we want to overwrite what's in dotfiles-local?
|
||||
echo "Replacing copy in dotfiles-local with local copy and symlinking back"
|
||||
else
|
||||
echo "Moving into dotfiles-local and symlinking back"
|
||||
fi
|
||||
mv "$DOTFILES_DIR/install_local.sh" "$locals_dir/"
|
||||
fi
|
||||
fi
|
||||
if [[ $skip == 0 ]] && [[ -f "$locals_dir/install_local.sh" ]]; then
|
||||
ln -s "$locals_dir/install_local.sh" "$DOTFILES_DIR/install_local.sh"
|
||||
echo ""
|
||||
elif [[ skip == 0 ]]; then
|
||||
echo "No install_local.sh script found in dotfiles-local or dotfiles. Skipping"
|
||||
echo ""
|
||||
elif [[ $skip == 1 ]]; then
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Move any existing local packages into repo and symlink out
|
||||
while IFS= read -r package_manager || [[ -n $package_manager ]]; do
|
||||
if [[ "$package_manager" == '#'* || -z "${package_manager// }" ]]; then
|
||||
continue
|
||||
fi
|
||||
skip=0
|
||||
if [ -f "$dotfiles_packages_root/$package_manager.local" ]; then
|
||||
echo "Discovered local packages for $package_manager"
|
||||
|
||||
# Check if file is a symlink
|
||||
if [[ -L "$dotfiles_packages_root/$package_manager.local" ]]; then
|
||||
# TODO: Make sure that it's actually linked from here and not somewhere else
|
||||
echo "Skipping: $package_manager.local because file already linked"
|
||||
skip=1
|
||||
elif [[ -f "$dotfiles_packages_root/$package_manager.local" ]]; then
|
||||
if [[ -f "$locals_dir/packages/$package_manager.local" ]]; then
|
||||
# TODO: Do we want to overwrite what's in dotfiles-local?
|
||||
echo "Replacing copy in dotfiles-local with local copy and symlinking back"
|
||||
else
|
||||
echo "Moving into dotfiles-local and symlinking back"
|
||||
fi
|
||||
mv "$dotfiles_packages_root/$package_manager.local" "$locals_dir/packages/"
|
||||
fi
|
||||
fi
|
||||
if [[ $skip == 0 ]] && [[ -f "$locals_dir/packages/$package_manager.local" ]]; then
|
||||
ln -s "$locals_dir/packages/$package_manager.local" "$dotfiles_packages_root/$package_manager.local"
|
||||
echo ""
|
||||
elif [[ $skip == 0 ]]; then
|
||||
echo "No $package_manager.local found in dotfiles-local/packages or dotfiles/packages. Skipping"
|
||||
echo ""
|
||||
elif [[ $skip == 1 ]]; then
|
||||
echo ""
|
||||
fi
|
||||
done < <(printf '%s' "$package_lists")
|
||||
|
||||
# Move any existing local dotfiles into repo and symlink out
|
||||
# TODO: These only symlink to dotfiles, they don't symlink to the actual locations. Should probably fix that
|
||||
while IFS= read -r config || [[ -n $config ]]; do
|
||||
if [[ "$config" == '#'* || -z "${config// }" ]]; then
|
||||
continue
|
||||
fi
|
||||
skip=0
|
||||
if [ -f "$HOME/.$config" ]; then
|
||||
echo "Discovered local dotfile ~/.$config"
|
||||
|
||||
# Check if file is a symlink
|
||||
if [[ -L "$HOME/.$config" ]]; then
|
||||
# TODO: Make sure that it's actually linked from here and not somewhere else
|
||||
echo "Skipping: ~/.$config because file already linked"
|
||||
skip=1
|
||||
elif [[ -f "$HOME/.$config" ]]; then
|
||||
if [[ -f "$locals_dir/config/$config" ]]; then
|
||||
# TODO: Do we want to overwrite what's in dotfiles-local?
|
||||
echo "Replacing copy in dotfiles-local with local copy and symlinking back"
|
||||
else
|
||||
echo "Moving into dotfiles-local and symlinking back"
|
||||
fi
|
||||
mv "$HOME/.$config" "$config_dir/$config"
|
||||
fi
|
||||
elif [ -f "$locals_dir/config/$config" ]; then
|
||||
echo "No local dotfile in ~/.$config but present in dotfiles-local. Symlinking"
|
||||
fi
|
||||
if [[ $skip == 0 ]] && [[ -f "$locals_dir/config/$config" ]]; then
|
||||
ln -s "$locals_dir/config/$config" "$HOME/.$config"
|
||||
echo ""
|
||||
elif [[ $skip == 0 ]]; then
|
||||
echo "No $config file found in dotfiles-local/config or ~/. Skipping"
|
||||
echo ""
|
||||
elif [[ $skip == 1 ]]; then
|
||||
echo ""
|
||||
fi
|
||||
done < <(printf '%s' "$home_files")
|
||||
|
||||
# Move any existing files in .config into repo and symlink out
|
||||
while IFS= read -r config || [[ -n $config ]]; do
|
||||
if [[ "$config" == '#'* || -z "${config// }" ]]; then
|
||||
continue
|
||||
fi
|
||||
skip=0
|
||||
if [ -f "$HOME/.config/$config" ]; then
|
||||
echo "Discovered local dotfile ~/.config/$config"
|
||||
|
||||
# Check if file is a symlink
|
||||
if [[ -L "$HOME/.config/$config" ]]; then
|
||||
# TODO: Make sure that it's actually linked from here and not somewhere else
|
||||
echo "Skipping: ~/.config/$config because file already linked"
|
||||
skip=1
|
||||
elif [[ -f "$HOME/.config/$config" ]]; then
|
||||
if [[ -f "$locals_dir/config/$config" ]]; then
|
||||
# TODO: Do we want to overwrite what's in dotfiles-local?
|
||||
echo "Replacing copy in dotfiles-local with local copy and symlinking back"
|
||||
else
|
||||
echo "Moving into dotfiles-local and symlinking back"
|
||||
fi
|
||||
mv "$HOME/.config/$config" "$config_dir/$config"
|
||||
fi
|
||||
elif [ -f "$locals_dir/config/$config" ]; then
|
||||
echo "No local dotfile in ~/.config/$config but present in dotfiles-local. Symlinking"
|
||||
fi
|
||||
if [[ $skip == 0 ]] && [[ -f "$locals_dir/config/$config" ]]; then
|
||||
ln -s "$locals_dir/config/$config" "$HOME/.config/$config"
|
||||
echo ""
|
||||
elif [[ $skip == 0 ]]; then
|
||||
echo "No $config file found in dotfiles-local/config or ~/.config . Skipping"
|
||||
echo ""
|
||||
elif [[ $skip == 1 ]]; then
|
||||
echo ""
|
||||
fi
|
||||
done < <(printf '%s' "$configs")
|
||||
|
||||
# Check if git repo has changes
|
||||
if [[ `git status --porcelain` ]]; then
|
||||
# Changes found
|
||||
# sync dotfiles to git
|
||||
if [ "$interactive" == 0 ]; then
|
||||
echo "Syncing local dotfiles to git branch. [$branch_name]"
|
||||
else
|
||||
echo -n "Would you like to push dotfiles-local to git? [$branch_name] (y/n) "
|
||||
read response
|
||||
if [[ $response != 'y' ]] && [[ $response != 'Y' ]]; then
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
git add -A
|
||||
git commit -m "Automated sync"
|
||||
git push origin "$branch_name"
|
||||
echo "dotfiles-local synced to git. [$branch_name]"
|
||||
else
|
||||
# No changes found
|
||||
echo "No changes found, not pushing branch to git remote"
|
||||
fi
|
||||
|
||||
cd -
|
||||
+29
-13
@@ -1,28 +1,44 @@
|
||||
# TODO: Flip the return values of these, 0 should be true by POSIX convention
|
||||
|
||||
# Returns 1 if program is installed and 0 otherwise
|
||||
# Returns 0 if program is installed and 1 otherwise
|
||||
function program_installed {
|
||||
local return_=1
|
||||
local return_=0
|
||||
|
||||
type $1 >/dev/null 2>&1 || { local return_=0; }
|
||||
type $1 >/dev/null 2>&1 || { local return_=1; }
|
||||
|
||||
echo "$return_"
|
||||
return "$return_"
|
||||
}
|
||||
|
||||
# Returns 1 if service is enabled and 0 otherwise
|
||||
# Returns 0 if service is enabled and 1 otherwise
|
||||
function service_enabled {
|
||||
local return_=1
|
||||
local return_=0
|
||||
|
||||
systemctl is-enabled --quiet $1 || { local return_=0; }
|
||||
systemctl is-enabled --quiet $1 || { local return_=1; }
|
||||
|
||||
echo "$return_"
|
||||
return "$return_"
|
||||
}
|
||||
|
||||
# Returns 1 if user service is enabled and 0 otherwise
|
||||
function user_service_enabled {
|
||||
local return_=1
|
||||
local return_=0
|
||||
|
||||
systemctl --user is-enabled --quiet $1 || { local return_=0; }
|
||||
systemctl --user is-enabled --quiet $1 || { local return_=1; }
|
||||
|
||||
echo "$return_"
|
||||
return "$return_"
|
||||
}
|
||||
|
||||
function update_dotfiles_config {
|
||||
if [ "$#" != 2 ]; then
|
||||
echo "Usage: update_dotfiles_config ENV_VARIABLE VALUE"
|
||||
exit 1
|
||||
fi
|
||||
local var="$1"
|
||||
local val="$2"
|
||||
|
||||
if [ ! -f "$HOME/.dotfiles-config" ]; then
|
||||
touch "$HOME/.dotfiles-config"
|
||||
fi
|
||||
if [ $(cat "$HOME/.dotfiles-config" | grep -Eq "^export $1=.*$") ]; then
|
||||
sed -i "s/$1=.*$/$1=$2/" "$HOME/.dotfiles-config"
|
||||
else
|
||||
echo "export $1=$2" >> "$HOME/.dotfiles-config"
|
||||
fi
|
||||
}
|
||||
|
||||
+732
-153
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user