Author SHA1 Message Date
branderson 84b66dea7c Add laptop packages and beginning lua migration for nvim 2024-04-09 22:04:09 -07:00
110 changed files with 1793 additions and 4833 deletions
-9
View File
@@ -1,16 +1,7 @@
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
-9
View File
@@ -16,12 +16,3 @@
[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
-64
View File
@@ -1,64 +0,0 @@
#!/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
-45
View File
@@ -1,45 +0,0 @@
#!/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
-5
View File
@@ -1,5 +0,0 @@
#!/bin/bash
docker compose pull
docker compose down
docker compose up -d
-4
View File
@@ -1,4 +0,0 @@
#!/bin/bash
docker compose down
docker compose up -d
-13
View File
@@ -1,13 +0,0 @@
#!/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
-255
View File
@@ -1,255 +0,0 @@
#!/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
-246
View File
@@ -1,246 +0,0 @@
#!/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
-18
View File
@@ -1,18 +0,0 @@
#!/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
-18
View File
@@ -1,18 +0,0 @@
#!/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"
-20
View File
@@ -1,20 +0,0 @@
#!/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"
-8
View File
@@ -1,8 +0,0 @@
#!/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"
-77
View File
@@ -1,77 +0,0 @@
#!/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
-59
View File
@@ -1,59 +0,0 @@
{
"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"
}
+3 -27
View File
@@ -1,3 +1,6 @@
import = [
"~/.config/alacritty/themes/themes/gruvbox_dark.toml"
]
[font]
size = 9.0
@@ -17,30 +20,3 @@ 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" },
]
-7
View File
@@ -1,7 +0,0 @@
[Desktop Entry]
Name=USDB Syncer
Comment=Download karaoke songs
Exec=usdb_syncer
Terminal=false
Type=Application
Categories=Software;
-7
View File
@@ -21,13 +21,6 @@ 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/
+18 -31
View File
@@ -10,8 +10,6 @@ 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,
@@ -39,32 +37,21 @@ 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 {
# 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
# }
}
# 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
# }
#}
-1
View File
@@ -1 +0,0 @@
alias vim=nvim
-142
View File
@@ -1,142 +0,0 @@
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
}
-6
View File
@@ -1,6 +0,0 @@
if [ -n "$BASH_VERSION" ]; then
# include .bashrc if it exists
if [ -f "$HOME/.bashrc" ]; then
. "$HOME/.bashrc"
fi
fi
-84
View File
@@ -1,84 +0,0 @@
#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
-39
View File
@@ -1,39 +0,0 @@
# 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.
@@ -1,30 +0,0 @@
#!/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
-57
View File
@@ -1,57 +0,0 @@
#!/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
-30
View File
@@ -1,30 +0,0 @@
{
"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"
}
}
-84
View File
@@ -1,84 +0,0 @@
@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
View File
@@ -1,4 +1,3 @@
VteTerminal, vte-terminal {
padding: 13px;
}
@import 'colors.css';
+9 -18
View File
@@ -1,25 +1,16 @@
[Settings]
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-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-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
-9
View File
@@ -22,15 +22,6 @@ 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
+9 -10
View File
@@ -12,19 +12,20 @@ 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
@@ -44,17 +45,15 @@ 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 #
+5 -31
View File
@@ -7,15 +7,10 @@ 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+slash move scratchpad
bindsym $mod+Control+slash scratchpad show
bindsym $mod+Shift+colon [class="^Alacritty$" title="servers"] scratchpad show
# switch to workspace
bindsym $mod+1 workspace $ws1
@@ -167,8 +162,7 @@ mode "$mode_gaps_outer" {
######################################
# start a terminal
bindsym $mod+Return exec --no-startup-id alacritty -e sh -c "tmux new-session"
# bindsym $mod+Return exec --no-startup-id alacritty
bindsym $mod+Return exec --no-startup-id alacritty
# kill focused window
bindsym $mod+q kill
@@ -177,7 +171,7 @@ bindsym $mod+q kill
#bindsym --release button2 kill
# reload the configuration file
bindsym $mod+Control+r reload
bindsym $mod+Shift+c reload
# restart i3 inplace (preserves your layout/session, can be used to update i3)
bindsym $mod+Shift+r restart
@@ -212,19 +206,7 @@ bindsym $mod+Shift+Down move down
bindsym $mod+Shift+Up move up
bindsym $mod+Shift+Right move right
# 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
# splij in vertical orientation
bindsym $mod+minus split v
bindsym $mod+KP_Subtract split v
@@ -272,7 +254,6 @@ 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
@@ -291,12 +272,5 @@ 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+b exec --no-startup-id rofi -modi "clipboard:greenclip print" -show clipboard \
bindsym $mod+c 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
+1
View File
@@ -9,6 +9,7 @@ default_border pixel 5
# thin borders
hide_edge_borders smart
smart_borders on
# Set inner/outer gaps
gaps inner 10
+15
View File
@@ -13,3 +13,18 @@ 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
View File
@@ -0,0 +1 @@
/home/brad/dotfiles/config/plasma-i3/i3-bar.conf
+1
View File
@@ -0,0 +1 @@
/home/brad/dotfiles/config/plasma-i3/i3-keybindings.conf
-102
View File
@@ -1,102 +0,0 @@
# 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
@@ -1,10 +0,0 @@
#!/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}
-63
View File
@@ -1,63 +0,0 @@
" .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 -4
View File
@@ -1,4 +1 @@
NO_NEOFETCH=1
NO_GIT_CHECK=1
NO_ZSH_COWSAY=1
LOAD_SSH_KEYS=0
POWERLINE_ROOT=/usr/share/powerline
-143
View File
@@ -1,143 +0,0 @@
# 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.
-21
View File
@@ -1,21 +0,0 @@
" 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
+78
View File
@@ -0,0 +1,78 @@
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()
]])
+191
View File
@@ -0,0 +1,191 @@
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
]])
+3 -12
View File
@@ -82,6 +82,8 @@ function! MapPlugins()
map <leader>t :NERDTreeToggle<CR>
endif
" Generative AI
if exists('g:loaded_tagbar')
" Toggle tagbar
map <leader>ct :TagbarToggle<CR>
@@ -161,16 +163,6 @@ 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
@@ -188,8 +180,7 @@ function! MapPlugins()
map <localleader>rr :RustRun<CR>
" - Markdown -
" map <localleader>v :LivedownToggle<CR>
nmap <localleader>v <Plug>MarkdownPreviewToggle
map <localleader>v :LivedownToggle<CR>
endfunction
augroup Plugin_Mappings
+62
View File
@@ -0,0 +1,62 @@
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
]])
+164
View File
@@ -0,0 +1,164 @@
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 |
]])
+187
View File
@@ -0,0 +1,187 @@
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()
]])
+5 -10
View File
@@ -1,5 +1,5 @@
let g:vim_plug_install_dir = "~/.local/share/nvim/site/autoload"
let g:plugin_install_dir = "~/.vim/plugged"
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"))
@@ -39,6 +39,9 @@ Plug 'yggdroot/indentLine'
" Better sessions
Plug 'tpope/vim-obsession'
" - Generative AI -
Plug 'David-Kunz/gen.nvim'
" - Ctags -
" Ctags view
Plug 'majutsushi/tagbar'
@@ -116,7 +119,7 @@ Plug 'xolox/vim-reload'
" Note taking and wiki managment
Plug 'vimwiki/vimwiki'
" TODO Why can't these go in Search?
Plug 'junegunn/fzf', { 'do': { -> fzf#install() } }
Plug 'junegunn/fzf'
Plug 'junegunn/fzf.vim'
Plug 'michal-h21/vim-zettel'
" TODO Make this pull on buffer open / load
@@ -173,14 +176,6 @@ 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 ---
+333
View File
@@ -0,0 +1,333 @@
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
]])
+2 -19
View File
@@ -73,6 +73,8 @@ 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
@@ -173,7 +175,6 @@ 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.
@@ -322,22 +323,4 @@ 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,
\ },
\ }
-4
View File
@@ -1,4 +0,0 @@
vim.bo.textwidth = 79
if vim.bo.modifiable then
vim.bo.fileformat = "unix"
end
-36
View File
@@ -1,36 +0,0 @@
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:")
+17 -89
View File
@@ -1,91 +1,19 @@
-- 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"
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
-- 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]
" -- Python dependencies
let g:python_host_prog = expand("~/.pyenv/versions/neovim2/bin/python")
let g:python3_host_prog = expand("~/.pyenv/versions/neovim3/bin/python")
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 },
})
" -- Local overrides
let $LOCALFILE=expand("$HOME/.nvim_local.vimrc")
if filereadable($LOCALFILE)
source $LOCALFILE
endif
]])
-47
View File
@@ -1,47 +0,0 @@
{
"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" }
}
-63
View File
@@ -1,63 +0,0 @@
-- 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
-59
View File
@@ -1,59 +0,0 @@
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" })
-94
View File
@@ -1,94 +0,0 @@
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
-104
View File
@@ -1,104 +0,0 @@
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" },
},
},
}
-10
View File
@@ -1,10 +0,0 @@
return {
"saghen/blink.cmp",
version = "*",
opts = {
keymap = { preset = "default" },
appearance = { nerd_font_variant = "mono" },
completion = { documentation = { auto_show = true } },
sources = { default = { "lsp", "path", "buffer" } },
},
}
-33
View File
@@ -1,33 +0,0 @@
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,
},
}
-137
View File
@@ -1,137 +0,0 @@
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,
},
}
-55
View File
@@ -1,55 +0,0 @@
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,
},
}
-4
View File
@@ -1,4 +0,0 @@
return {
{ "lewis6991/gitsigns.nvim", event = { "BufReadPre", "BufNewFile" }, opts = {} },
{ "tpope/vim-fugitive", cmd = { "Git", "Gdiffsplit", "Gvdiffsplit", "Gread", "Gwrite", "Gclog" } },
}
-59
View File
@@ -1,59 +0,0 @@
local servers = { "basedpyright", "ruff" }
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,
},
}
-31
View File
@@ -1,31 +0,0 @@
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 = {},
},
}
-25
View File
@@ -1,25 +0,0 @@
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" } },
},
},
}
-100
View File
@@ -1,100 +0,0 @@
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,
}
-101
View File
@@ -1,101 +0,0 @@
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,
},
}
-64
View File
@@ -1,64 +0,0 @@
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" },
},
},
}
-28
View File
@@ -1,28 +0,0 @@
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
+3 -4
View File
@@ -22,6 +22,7 @@ shadow-exclude = [
"class_g = 'lattedock'",
"_GTK_FRAME_EXTENTS@:c"
]
xinerama-shadow-crop = true;
### Blur
blur:{
@@ -51,6 +52,8 @@ backend = "glx";
#backend = "xrender";
vsync = true;
glx-no-stencil = true;
glx-no-rebind-pixmap = true;
xrender-sync-fence = true;
dbus=true;
@@ -71,7 +74,3 @@ 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": "gray1", "bg": "gray10", "attrs": ["bold"] }
"stack_depth": { "fg": "gb:light1", "bg": "gb:light4", "attrs": ["bold"] }
}
}
@@ -1,5 +0,0 @@
{
"groups": {
"stack_depth": { "fg": "gb:light1", "bg": "gb:light4", "attrs": ["bold"] }
}
}
+1 -1
View File
@@ -13,7 +13,7 @@
}
},
"pdb": {
"colorscheme": "gruvbox",
"colorscheme": "default",
"theme": "default"
},
"shell": {
+5 -129
View File
@@ -1,130 +1,6 @@
# Override in .profile.local for custom repo
DOTFILES_LOCAL_REPOSITORY="https://gitbox.branderson.io/branderson/dotfiles-local"
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"
# 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"
@@ -1,37 +0,0 @@
[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
@@ -1,11 +0,0 @@
[Unit]
Description=Refresh existing PGP keys of archlinux-keyring regularly
[Timer]
OnCalendar=weekly
Persistent=true
RandomizedDelaySec=12h
[Install]
WantedBy=timers.target
-14
View File
@@ -1,14 +0,0 @@
[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
+2 -198
View File
@@ -1,198 +1,2 @@
# ----------------------------------------------------------------------------
# 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.
#
# Not the cause of multi-line paste arriving with literal CSI 27;5;106~ in
# place of each newline (that being C-j, the pasted newline, in
# modifyOtherKeys form). That is a tmux 3.5/3.5a bug: 3.5 rewrote extended-key
# handling and encodes keys inside a bracketed paste, which the layer further
# in then passes through verbatim rather than decoding. Reproduced against
# 3.2a/3.3a/3.4/3.5a/3.6b/3.7c -- only 3.5 and 3.5a corrupt, and only on a hop
# whose downstream has asked for modifyOtherKeys mode 2, which a nested tmux
# always does and a bare application under screen-256color generally doesn't.
# Hence it shows up with tmux at both ends of the ssh and not with one.
# Fixed upstream in 3.6, so upgrade the offending layer where that's possible.
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"'
# Where it isn't -- a host pinned to a distro tmux -- give the paste back on
# just those two versions. Nothing narrower helps: csi-u format only changes
# which escape lands in the text, and withholding the extkeys feature above
# stops this tmux asking its own parent for extended keys without stopping it
# encoding them for the pane. Turning them off is the whole of the workaround,
# and confining it to 3.5/3.5a keeps them everywhere else.
if-shell "tmux -V | awk '{hit = ($2 ~ /^3[.]5/)} END {exit hit ? 0 : 1}'" 'set -s extended-keys off'
# 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'
# run-shell "~/.tmux/verify_tmux_version.sh"
source-file "~/.tmux/tmux_3.1c.conf"
-16
View File
@@ -1,16 +0,0 @@
# 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"
-24
View File
@@ -1,24 +0,0 @@
# 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"
+37
View File
@@ -0,0 +1,37 @@
# 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"
+2
View File
@@ -0,0 +1,2 @@
source "$HOME/.tmux/tmux_shared.conf"
+48
View File
@@ -0,0 +1,48 @@
# 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"
+42
View File
@@ -0,0 +1,42 @@
# 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
+42
View File
@@ -0,0 +1,42 @@
# 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
+106
View File
@@ -0,0 +1,106 @@
# 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'
+27
View File
@@ -0,0 +1,27 @@
#!/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
-1
View File
@@ -1 +0,0 @@
ACTION=="change", SUBSYSTEM=="drm", RUN+="/usr/bin/systemctl start --no-block update-wallpapers.service"
+3 -90
View File
@@ -1,30 +1,3 @@
# 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
@@ -78,19 +51,13 @@ 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
# Return 5 if DOTFILES_DIR is not set
if [ -z $DOTFILES_DIR ]; then
return 5
fi
if [ ! -d $DOTFILES_DIR ]; then
if [ ! -d $HOME/dotfiles ]; then
return 2
fi
pushd $DOTFILES_DIR > /dev/null
pushd $HOME/dotfiles > /dev/null
# TODO: This may be gitbox
git fetch origin > /dev/null
git fetch origin
UPSTREAM=${1:-'@{u}'}
LOCAL=$(git rev-parse @)
REMOTE=$(git rev-parse "$UPSTREAM")
@@ -108,57 +75,3 @@ 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
}
+185 -191
View File
@@ -1,92 +1,93 @@
# ZSH-specific environment variables
# Override in .profile.local
## 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"
# 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"
# 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
# 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"
# 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
# Path to your oh-my-zsh installation.
export ZSH=$HOME/dotfiles/dependencies/ohmyzsh
#export RUST_SRC_PATH=/usr/local/src/rust/src
# Dircolors
# eval $(dircolors ~/.dircolors)
# 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.
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
# # 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
setopt appendhistory autocd extendedglob
unsetopt beep
# alias make='nocorrect make'
# alias git='nocorrect git'
alias -s txt=vim
alias -s .c=vim
#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
if [ -d $ZSH ] && [ ! -z $ZSH ]; then
source $ZSH/oh-my-zsh.sh
# User profiles
source $HOME/.profile
# Define $POWERLINE_ROOT
if [ -f $HOME/.profile.local ]; then
source $HOME/.profile.local
fi
source $ZSH/oh-my-zsh.sh
# Italic support
if [ -f $HOME/.xterm-256color-italic.terminfo ]; then
tic $HOME/.xterm-256color-italic.terminfo
@@ -95,19 +96,114 @@ 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
@@ -119,128 +215,26 @@ bindkey -M viins ',,' vi-cmd-mode
#bindkey '^o' ranger-cd
#zle -N terminal-clock
#bindkey '^t' terminal-clock
# TMuxinator Completion
# source ~/bin/tmuxinator.zsh
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
#alias sl="sl -laF"
# 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
# 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
if [ -f ~/.fzf.zsh ]; then
source ~/.fzf.zsh
fi
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
if [ -f /usr/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh ]; then
source /usr/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
fi
# pyenv-virtualenv (for managing virtualenvs for different python versions)
#export PYENV_VIRTUALENV_DISABLE_PROMPT=1
#eval "$(pyenv init -)"
#eval "$(pyenv virtualenv-init -)"
-274
View File
@@ -1,274 +0,0 @@
#!/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 -
+13 -29
View File
@@ -1,44 +1,28 @@
# Returns 0 if program is installed and 1 otherwise
# TODO: Flip the return values of these, 0 should be true by POSIX convention
# Returns 1 if program is installed and 0 otherwise
function program_installed {
local return_=0
local return_=1
type $1 >/dev/null 2>&1 || { local return_=1; }
type $1 >/dev/null 2>&1 || { local return_=0; }
return "$return_"
echo "$return_"
}
# Returns 0 if service is enabled and 1 otherwise
# Returns 1 if service is enabled and 0 otherwise
function service_enabled {
local return_=0
local return_=1
systemctl is-enabled --quiet $1 || { local return_=1; }
systemctl is-enabled --quiet $1 || { local return_=0; }
return "$return_"
echo "$return_"
}
# Returns 1 if user service is enabled and 0 otherwise
function user_service_enabled {
local return_=0
local return_=1
systemctl --user is-enabled --quiet $1 || { local return_=1; }
systemctl --user is-enabled --quiet $1 || { local return_=0; }
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
echo "$return_"
}
+152 -731
View File
File diff suppressed because it is too large Load Diff
-25
View File
@@ -1,25 +0,0 @@
vim
neovim
silversearcher-ag
fzf
powerline
thefuck
tree
nodejs
zsh
htop
jq
npm
tree-sitter-cli
ripgrep
shellcheck
bubblewrap
socat
# Agent sandboxing
bubblewrap
socat
# Useless stuff
fortune-mod
cowsay

Some files were not shown because too many files have changed in this diff Show More