Compare commits

..

55 Commits

Author SHA1 Message Date
316eefe916 kitty:get_cwd: Use KITTY_LISTEN_ON for socket path
Also verify that the socket exists before using it.
2025-12-11 15:27:39 +01:00
3a821d832b kitty:get_cwd: Use the match flag for performance
Instead of requesting the full tree as a JSON and extracting the focused
window with `jq`, use `kitten-@-ls`'s `--match` flag. This further
improves the performance.

Also remove the commented code using recursive descent because it is not
up-to-date anymore.
2025-12-11 15:27:38 +01:00
b291163a80 kitty:get_cwd: Make faster by not using kitten
kitten-@-ls(1) is unfortunately a bit slow (100ms) which is noticeable
when launching new windows using `get_cwd`. Make `get_cwd` faster (down
to 25ms) by communicating directly with the socket instead of using
`kitten`.
2025-12-11 15:27:23 +01:00
2e2bad65a2 polybar: Change while read loop to an xargs pipe 2025-12-10 14:27:53 +01:00
c46b1c5ea1 i3: Add bindings to switch forward & backward
After unplugging an external monitor I sometimes still have old
workspaces that I can't access through their index.
2025-12-10 14:20:40 +01:00
5f40b97e9a i3: Workspace 0 should be 10 2025-12-10 14:19:48 +01:00
5599ce14d7 i3: Normal numeric workspaces on multi outputs
Use normal workspace numbers with the output name as workspace name, but
strip the name in polybar.

See https://github.com/polybar/polybar/pull/3230 for strip-wsnames.
2025-12-04 14:31:05 +01:00
4008bb543b vim:looks: Don't hardcode the colorscheme colors 2025-11-25 18:06:24 +01:00
d0abb14567 vim: Highlight trailing spaces in colorscheme red 2025-11-25 18:06:13 +01:00
9e18be760c vim:setts: Use the number column for the signcolumn 2025-11-25 17:27:48 +01:00
04d3d6e87f vim:plugs:nrrwrgn: Add padding to small windows 2025-11-25 17:19:34 +01:00
526a37301a vim:plugs:ctags: Don't index venv and __pycache__ 2025-11-25 17:11:14 +01:00
7dc9efc0e4 vim:gitcommit: Fold unstaged and untracked files 2025-11-25 17:09:24 +01:00
9bc8b4b93f vim:ftplug:man: Only trigger one timer
Stop an already running timer similar to how it is done already when
highlighting the selection.
2025-11-25 16:07:52 +01:00
ead724b75b vim:ftplug:man: Fix WinResized support check
The check if the WinResized event is supported was broken from the
beginning on since I used `has()` instead of `exists()`.

Fixes: 558bb0582e (man.vim: Check if WinResized is supported,
       2025-01-29)
2025-11-25 15:56:21 +01:00
1c5beed613 git🐮 Fix stderr redirection
I also swapped the printf and the redirection since I think I prefer it
this way.
2025-09-21 01:34:48 +02:00
2dd1a80036 git🐮 Fix parameter quoting
The parameter expansion outside of the single quotes (or inside, however
you want to see it) was not quoted.
2025-09-21 01:30:56 +02:00
4f2a74e546 less: Remap ^E to edit current screen in vim 2025-09-19 01:47:39 +02:00
cb1821ba33 less: Remap ^Y to copying the whole file 2025-09-19 01:44:23 +02:00
5128d15251 less: Strip all ANSI sequences, not just SGR
Kitty's shell integration uses OSC sequences to mark the prompt and
output in the scrollback buffer. When opening that in vim through less I
want these to be gone as well.
2025-09-19 01:36:54 +02:00
2b31632914 bin:no-ansi: Add a label to each pattern 2025-09-19 01:14:09 +02:00
27791acf50 bin:no-ansi: Correct allowed byte ranges
Correct the allowed byte ranges of the APC, DCS, OSC, PM & SOS
sequences. All but the SOS sequence allow additionally the bytes in the
range `0x8 - 0xD` and SOS may be followed by any sequence of bytes
except for SOS and ST (i.e. `\eX` & `\e\\`).

Link: https://www.ecma-international.org/wp-content/uploads/ECMA-48_5th_edition_june_1991.pdf#page=27
2025-09-19 00:51:47 +02:00
8aa76b3ee6 bin:no-ansi: Don't just match CSI sequences
Try to match all ANSI escape sequences, not just CSI (i.e. `\e[`) - also
the ones that are followed by additional bytes (e.g. CSI, OSC).
2025-09-19 00:26:36 +02:00
6b866f5474 bin:no-ansi*: Use printf for escape byte
I dislike having the raw escape byte in these scripts. Unfortunately
`sed` does not support interpreting it via an escape sequence, so use
printf for that. To remain POSIX compatible use `\033` and not `\e` or
`\x1b` since I couldn't find these in the printf(1p) manpage.
Unfortunately this brings a second layer of escaping.
2025-09-19 00:13:28 +02:00
4f6929bcce less: Keep position when editing in vim via e/E 2025-09-18 23:19:07 +02:00
2495d835b4 kitty: Slightly decrease click_interval to 0.4
Kitty's source code makes me believe that this is always 0.5s on X11.
This decreases the delay when opening links.

Link: https://github.com/kovidgoyal/kitty/blob/3482d084aef1/glfw/x11_window.c#L2360-L2363
2025-09-18 12:56:10 +02:00
dda2ff640e kitty: Increase font size by one point to 12 2025-09-18 12:26:36 +02:00
87398bf712 vim:keys: Use getreginfo() instead of getregtype()
The result from getreginfo can be passed directly to setreg making this
a bit neater. Taken from the neovim defaults (ironically not from
v_star-default).

Link: https://github.com/neovim/neovim/blob/08847a9ea15a/runtime/lua/vim/_defaults.lua#L73-L79
2025-09-18 01:08:18 +02:00
0a5b6d0767 vim:keys: Only map v_* & v_# if they don't exist
I learned just now that neovim added mappings for these by default in
v0.8.0. But instead of checking for neovim, check for the existence of
mappings in case vim adds these in the future too.
2025-09-18 01:07:34 +02:00
5b8f54b0cb vim:keys: Fix newline and tab search for v_*
Multiline search didn't work previously when searching with v_* and tabs
were ignored when searching with v_<leader>*.
2025-09-17 23:01:11 +02:00
ef5b2911bf vim:coc: Select first item before confirming
I believe I had the problem in the past that the completion wouldn't
automatically select the first entry but simply display the menu. Thus
it would simply insert a new line when pressing return to accept it.

Unfortunately I didn't commit it back then and I can't reproduce it now.
But it doesn't not hurt so I commit it to be safe.
2025-09-17 21:55:00 +02:00
768cb4ed4a vim:keys: Add mapping for git-commit-last-msg 2025-09-17 21:46:43 +02:00
f2ce78b6b3 vim:fzf: Use location list instead of the quickfix
Since the quickfix is a global list I can't keep multiple ripgrep
searches open at once. The location list is window-local thus solving
this issue.
2025-09-17 21:44:46 +02:00
a3d2bf985c i3: Use back_and_forth instead of i3-msg+jq 2025-09-17 17:35:19 +02:00
e8c5ec93f1 i3: Re-add stacking and tabbed layout bindings
I removed these in 69d0290afd (i3: Remove bindings for stacked and
tabbed layout, 2023-04-20) since I never need them and I always forgot
how to switch back when I pressed these accidentally.

Bring these back as comments, since the comment above still mentions
these and since I can imagine a rare situation where I might want one
these and simply want to comment them in.
2025-09-17 17:30:51 +02:00
ae52ba20d2 vim: Disable 'cindent' in non-code filetypes 2025-09-17 16:49:34 +02:00
ea2867fc9f dircolors: Color pdfs like images and videos 2025-09-17 16:44:48 +02:00
7f83427749 hooks:pre-commit: Broken link detection on delete
Until now the hook only checked newly added symlinks. This patch is a
first draft of also checking the worktree and index for any dangling
symlinks after staging a deletion.

The whole thing probably breaks when file-names contain newlines and
maybe also a mix of quotes. I plan on making this more robust in the
future but see no urgency for it since this repository has pretty simple
filenames.
2025-09-15 17:40:35 +02:00
8a4029121e hooks:pre-commit: Explicitly propagate pipe error
The `die` in the pipe does not exit the whole script but only the pipe.
This currently works because the pipe is the last thing being executed.
If something would come after the pipe, the hook would happily continue
executing. Properly propagate the exit to prevent this in the future.
2025-09-15 17:34:01 +02:00
7c184ed11e git🐮 Fix GIT_DIR for submodules via git alias
Git sets some environment variables when executing a shell command.
Specifically it sets GIT_DIR when called inside a submodule. This makes
git inside the subshell target the main worktree instead of the
temporary one.
2025-09-15 14:24:36 +02:00
8e8ef29b37 git🐮 Use %s to print worktree path
Don't pass the worktree path directly into the format string - just to
be safe.
2025-09-15 13:49:34 +02:00
d8859bc709 git🐮 Keep as much relative offset as possible 2025-09-15 13:49:34 +02:00
65d99c40e8 git🐮 Keep relative path offset 2025-09-15 13:49:33 +02:00
d28ef61694 git🐮 Rename temporary worktree directory
Shorten the "worktree" and place the random bytes at the end for better
sorting.
2025-09-15 13:23:01 +02:00
d5a95f9ce5 git🐮 Fix name of submodules
Previously git-checkout-worktree would use the name of the superproject
instead of the submodule for the temporary directory.
2025-09-15 13:19:28 +02:00
723899d70f git: Add empty line before include section
I want the section at the very end and this broke the alphabetic
sorting.
2025-09-12 17:06:01 +02:00
126ccb0c7a git: Fix option capitalization
Semantically this changes nothing, but the name with a capital `S` is
used by git-config(1).
2025-09-12 17:04:49 +02:00
dadf344f2b git: Explicitly set core.whitespace.tabwidth=8 2025-09-12 17:03:53 +02:00
f17cde7943 git: Show all refs as decoration in logs 2025-09-12 16:57:00 +02:00
a89ad407ba git: Make all graph colors bold
This looks a bit better in my opinion.
2025-09-12 16:56:05 +02:00
a26a899213 git: Make all bold colors bright
Make all bold colors (also) bright, since kitty does not render bold
colors in their bright version, but I've gotten used to how this looks.

For the graph I've gotten rid of the boldness and only switched to
bright versions since I think it makes no sense to have different line
weights for the branches (Although I apparently never noticed, so I
can't say that this was misleading in practice).
2025-09-12 16:51:36 +02:00
6db1a710c6 git: Rename zsh-autoload.sh -> external-script.sh
With the last commit 9c1e3f4679 (git:zsh-autoload: Use relative
scripts/ folder, 2025-09-12), `zsh-autoload.sh` could execute any type
of external script. Rename it to a more generic name.
2025-09-12 16:25:39 +02:00
9c1e3f4679 git:zsh-autoload: Use relative scripts/ folder
This makes it a bit more agnostic to the type of scripts being used.
2025-09-12 14:49:59 +02:00
bb7ef3769d git: Add branch-rename
Small script to rename a branch locally and on a given remote.
2025-09-12 14:35:44 +02:00
0534ec493e zsh:alias: Make sizes an anonymous function
This way one can easily redirect stderr for both commands (not just
`sort`) and specify a path. The path defaults to the current directory,
but listing each entry by globbing.
2025-09-07 21:09:11 +02:00
28 changed files with 423 additions and 104 deletions

View File

@@ -185,3 +185,6 @@ EXEC 01;92
*.opus 00;36
*.spx 00;36
*.xspf 00;36
## Others
*.pdf 01;95

View File

@@ -4,21 +4,22 @@
addIgnoredFile = off
detachedHead = off
[alias]
# NOTE: git-zsh-autoload (./zsh-autoload.sh) is a small wrapper that
# launches autoloadable zsh functions (.config/zsh/autoload/git/*) in
# the right directory, as shell commands in git aliases are executed
# from the top-level directory of the repository.
# NOTE: git-external-script (./external-script.sh) is a small wrapper
# that launches external scripts from the ./scripts/ collection in the
# right directory, as shell commands in git aliases are executed from
# the top-level directory of the repository.
abort = "!git-zsh-autoload abort"
abort = "!git-external-script abort"
autosquash = -c sequence.editor=/bin/true rebase -i --autosquash
autofixup= autosquash
branch-rename = "!git-external-script branch-rename"
c = commit
changes = flog HEAD...FETCH_HEAD
checkout-worktree = "!git-zsh-autoload checkout-worktree"
checkout-worktree = "!git-external-script checkout-worktree"
cow = checkout-worktree
co = checkout
commit-last-msg = "!git-zsh-autoload commit-last-msg"
continue = "!git-zsh-autoload continue"
commit-last-msg = "!git-external-script commit-last-msg"
continue = "!git-external-script continue"
cont = continue
clm = commit-last-msg
last-msg = commit-last-msg
@@ -28,21 +29,21 @@
ft = fetch-tags-only
filter-repo = !git-filter-repo
fixes = log -1 --pretty=fixes
glog = "!git-zsh-autoload glog"
https-and-ssh = "!git-zsh-autoload https-and-ssh"
glog = "!git-external-script glog"
https-and-ssh = "!git-external-script https-and-ssh"
ssh-and-https = https-and-ssh
l = log
last-changed = "!git-zsh-autoload last-changed"
last-changed = "!git-external-script last-changed"
ls = ls-files
make-fork = "!git-zsh-autoload make-fork"
make-fork = "!git-external-script make-fork"
p = push
perm-stash = "!git-zsh-autoload perm-stash"
perm-stash = "!git-external-script perm-stash"
root = rev-parse --show-toplevel
signoff = rebase --signoff
ss = stash
ssync = "!git-zsh-autoload ssync"
submodule-rm = "!git-zsh-autoload submodule-rm"
track = "!git-zsh-autoload track"
ssync = "!git-external-script ssync"
submodule-rm = "!git-external-script submodule-rm"
track = "!git-external-script track"
branches = track
[blame]
date = short
@@ -51,6 +52,38 @@
sort = -committerdate
[clone]
filterSubmodules = yes
[color "diff"]
# Make all bold colors also bright. See diff_colors in git's diff.c
oldMoved = bold brightmagenta
oldMovedAlternative = bold brightblue
newMoved = bold brightcyan
newMovedAlternative = bold brightyellow
oldBold = bold brightred
newBold = bold brightgreen
[color "decorate"]
# Make all bold colors also bright. See decoration_colors in git's
# log-tree.c
branch = bold brightgreen
remoteBranch = bold brightred
tag = bold brightyellow
stash = bold brightmagenta
HEAD = bold brightcyan
grafted = bold brightblue
[color "grep"]
# Make all bold colors also bright. See GREP_OPT_INIT in git's grep.h
matchContext = bold brightred
matchSelected = bold brightred
[color "interactive"]
# Make all bold colors also bright. See init_add_i_state in git's
# add-interactive.c
help = bold brightred
prompt = bold brightblue
error = bold brightred
[color "remote"]
# Make all bold colors also bright. See keywords in git's sideband.c
warning = bold brightyellow
success = bold brightgreen
error = bold brightred
[color "status"]
added = 076
untracked = 014
@@ -68,7 +101,7 @@
abbrev = 12
#pager = delta
pager = diff-so-fancy | less --tabs=8 --RAW-CONTROL-CHARS
whitespace = trailing-spaces,space-before-tab,indent-with-non-tab
whitespace = trailing-spaces,space-before-tab,indent-with-non-tab,tabwidth=8
[delta]
navigate = true
commit-decoration-style = bold yellow box
@@ -101,6 +134,12 @@
singleKey = true
[log]
follow = true
# Make all colors bold and additionally use bright versions of
# previously bold-only colors. See column_colors_ansi in git's color.c
# used by graph.c
graphColors = bold red,bold green,bold yellow,bold blue,bold magenta,bold cyan,bold brightred,bold brightgreen,bold brightyellow,bold brightblue,bold brightmagenta,bold brightcyan
# Show all refs as decoration (e.g. also notes)
initialDecorationSet = all
[merge]
conflictstyle = diff3
log = true
@@ -117,7 +156,7 @@
[rerere]
enabled = false
[status]
submodulesummary = true
submoduleSummary = true
[submodule]
fetchJobs = 0
[trailer]
@@ -126,5 +165,6 @@
email = julian@druck.dev
name = Julian Prein
signingkey = C0A44F69F2E29F6586C86B96CA6B3A516FAC2555
[include]
path = user.config

View File

@@ -2,8 +2,9 @@
# SPDX-License-Identifier: MIT
# Copyright (c) 2025 Julian Prein
#
# Meant to be used in git aliases to launch an autoloadable zsh function in the
# correct directory.
# Meant to be used by git aliases to easily launch an external script from the
# ./scripts/ collection through its basename and in the correct directory (i.e.
# GIT_PREFIX).
if [ $# -eq 0 ]; then
printf >&2 "Usage: %s <function>\n" "$(basename "$0")"
@@ -12,7 +13,7 @@ fi
name="$1"
shift
BASE="${XDG_CONFIG_HOME:-$HOME/.config}/zsh/autoload/git"
BASE="$(dirname "$(realpath "$0")")/scripts"
# In git aliases, shell commands are executed from the top-level directory of
# the repo. GIT_PREFIX contains the original directory relative to the

View File

@@ -79,6 +79,8 @@ bindsym $mod+Shift+v split horizontal
bindsym $mod+f fullscreen toggle
# change container layout (stacked, tabbed, toggle split)
#bindsym $mod+s layout stacking
#bindsym $mod+w layout tabbed
bindsym $mod+e layout toggle split
# toggle tiling / floating
@@ -100,13 +102,15 @@ bindsym $mod+6 exec ~/.config/i3/multi-monitor-workspaces.sh -s 6
bindsym $mod+7 exec ~/.config/i3/multi-monitor-workspaces.sh -s 7
bindsym $mod+8 exec ~/.config/i3/multi-monitor-workspaces.sh -s 8
bindsym $mod+9 exec ~/.config/i3/multi-monitor-workspaces.sh -s 9
bindsym $mod+0 exec ~/.config/i3/multi-monitor-workspaces.sh -s 0
bindsym $mod+0 exec ~/.config/i3/multi-monitor-workspaces.sh -s 10
# switch back to the previous workspace
workspace_auto_back_and_forth yes
bindsym $mod+Tab exec i3-msg workspace "$( \
i3-msg -t get_workspaces | \
jq -r '.[] | select(.focused).name')"
bindsym $mod+Tab workspace back_and_forth
# switch workspaces forward and backward
bindsym $mod+Next workspace next
bindsym $mod+Prior workspace prev
# Switch visible workspaces (e.g. multi monitor setup)
bindsym $mod+Shift+Tab exec i3-msg workspace "$( \
@@ -124,7 +128,7 @@ bindsym $mod+Shift+6 exec ~/.config/i3/multi-monitor-workspaces.sh -m 6
bindsym $mod+Shift+7 exec ~/.config/i3/multi-monitor-workspaces.sh -m 7
bindsym $mod+Shift+8 exec ~/.config/i3/multi-monitor-workspaces.sh -m 8
bindsym $mod+Shift+9 exec ~/.config/i3/multi-monitor-workspaces.sh -m 9
bindsym $mod+Shift+0 exec ~/.config/i3/multi-monitor-workspaces.sh -m 0
bindsym $mod+Shift+0 exec ~/.config/i3/multi-monitor-workspaces.sh -m 10
# move focused container and switch to workspace
bindsym Mod1+Shift+1 exec ~/.config/i3/multi-monitor-workspaces.sh -ms 1
@@ -136,7 +140,7 @@ bindsym Mod1+Shift+6 exec ~/.config/i3/multi-monitor-workspaces.sh -ms 6
bindsym Mod1+Shift+7 exec ~/.config/i3/multi-monitor-workspaces.sh -ms 7
bindsym Mod1+Shift+8 exec ~/.config/i3/multi-monitor-workspaces.sh -ms 8
bindsym Mod1+Shift+9 exec ~/.config/i3/multi-monitor-workspaces.sh -ms 9
bindsym Mod1+Shift+0 exec ~/.config/i3/multi-monitor-workspaces.sh -ms 0
bindsym Mod1+Shift+0 exec ~/.config/i3/multi-monitor-workspaces.sh -ms 10
# reload the configuration file
bindsym $mod+Shift+c reload

View File

@@ -25,25 +25,12 @@ done
shift $((OPTIND - 1))
[ $# -gt 0 ] || usage
outputs="$(i3-msg -t get_outputs | jq -r '.[] | select(.active).name')"
num_outs="$(printf "%s\n" "$outputs" | wc -l)"
name="$(i3-msg -t get_tree \
| jq -r '.. | objects | select(.focused).output')"
if [ "$num_outs" -lt 2 ]; then
# only one monitor
workspace="$1"
else
name="$(i3-msg -t get_tree \
| jq -r '.. | objects | select(.focused).output')"
num="$(printf "%s\n" "$outputs" \
| grep -Fxn "$name" \
| cut -d: -f1)"
num="$((num - 1))"
# Omit the number on the first monitor
[ "$num" -gt 0 ] || num=
workspace="$num$1"
fi
# NOTE: See `strip-wsnames` in polybar config. With it every monitor has its own
# 1-10 workspaces
workspace="$1: $name"
if [ -z "$switch" ] && [ -z "$move" ]; then
printf "%s\n" "$workspace"

View File

@@ -7,21 +7,19 @@
# Print the current working directory of the focused kitty window. Returns 4 if
# none exist or is focused.
socket_path="${TMPDIR:-/tmp}/kitty.$USER/kitty${1:+-$1}.sock"
if [ -n "$KITTY_LISTEN_ON" ]; then
socket_path="${KITTY_LISTEN_ON#unix:}"
else
socket_path="${TMPDIR:-/tmp}/kitty.$USER/kitty${1:+-$1}.sock"
fi
[ -e "$socket_path" ] || exit 1
# NOTE: the backticks are used for hacky line-continuation, taken from
# https://stackoverflow.com/a/7729087/2092762c9
kitten @ --to unix:"$socket_path" ls \
| jq -er ".[]`
` | select(.is_focused).tabs.[]`
` | select(.is_focused).windows.[]`
` | select(.is_focused).cwd"
# An alternative version that uses recursive descent to find focused objects
# that also have a `.cwd` key:
#
# | jq -er "..`
# ` | objects`
# ` | select(.is_focused)`
# ` | to_entries.[]`
# ` | select(.key == \"cwd\").value"
# NOTE: Unfortunately kitten-@-ls(1) is slow, so communicate with the socket
# directly.
printf '\eP@kitty-cmd{%s,%s,%s}\e\\' \
'"cmd":"ls"' \
'"version":[0,26,0]' \
'"payload":{"match":"state:focused"}' \
| nc -U -q0 "$socket_path" \
| awk '{ print substr($0, 13, length($0) - 14) }' \
| jq -er ".data | fromjson | .[].tabs.[].windows.[].cwd"

View File

@@ -20,7 +20,7 @@
#: <https://sw.kovidgoyal.net/kitty/kittens/choose-fonts/#font-spec-
#: syntax>.
# font_size 11.0
font_size 12.0
#: Font size (in pts).
@@ -630,7 +630,7 @@ mouse_hide_wait -1
#: If empty (default) select_by_word_characters will be used for both
#: directions.
# click_interval -1.0
click_interval 0.4
#: The interval between successive clicks to detect double/triple
#: clicks (in seconds). Negative numbers will use the system default

View File

@@ -6,11 +6,17 @@
# NOTE: the current file can be edited with `v` already, but this doesn't work
# when reading from stdin
# NOTE: ^P omits the "done" message
# NOTE: '' jumps back to the previous position
#
# edit in vim without any ANSI SGR sequences (e.g. color)
e noaction g|$no-ansi-sgr | nvim -\n
# edit in vim without any ANSI escape sequences (e.g. color)
e noaction g|$no-ansi | nvim -\n''
# edit in vim while keeping them
E noaction g|$nvim -\n
E noaction g|$nvim -\n''
# edit current screen in vim
^E noaction |.no-ansi | nvim -\n
# copy whole file
^Y noaction g|$xclip -selection clipboard\n''
#env
# NOTE: Lines need a trailing space when concatenating

View File

@@ -40,6 +40,7 @@ enable-ipc = true
type = internal/i3
pin-workspaces = true
format = <label-state> <label-mode>
strip-wsnames = true
index-sort = true
wrapping-scroll = false

View File

@@ -22,10 +22,11 @@ done
if ! pgrep -ax polybar >/dev/null 2>&1; then
# launch Polybar on every monitor
# https://github.com/polybar/polybar/issues/763
while read -r m; do
export MONITOR="${m%%:*}"
polybar --reload -c "$BASE_DIR/config" main &
done <<<"$(polybar --list-monitors)"
polybar --list-monitors \
| cut -d: -f1 \
| xargs -I'{}' -P0 \
env MONITOR='{}' \
polybar --reload -c "$BASE_DIR/config" main &
echo "Polybar launched..."
else

View File

@@ -37,18 +37,30 @@ setlocal showbreak=NONE
" This is very hacky.
" Only if WinResized is supported
if has('##WinResized')
if exists('##WinResized')
augroup man_resized
" The reload has to be delayed slightly, since with an `edit` directly in
" the autocmd, the buffer will just be cleared? (TODO)
" NOTE: One could add a wrapper function that checks for the existence of
" already running timers similar to how it's done in the
" highlight_current group (see autocommands.vim), but this feels
" overkill here.
au! WinResized <buffer> call timer_start(10, function("s:redraw_delayed"))
au! WinResized <buffer> call s:redraw_man(v:event)
augroup END
function s:redraw_man(event)
if exists('w:disable_man_resizing')
return
endif
if exists('w:man_resizing_timer_id')
call timer_stop(w:man_resizing_timer_id)
endif
echo a:event
" TODO: make sure that a:event contains window number and that the width
" actually changed with getwininfo()
let w:man_resizing_timer_id = timer_start(10, function("s:redraw_delayed"))
endfunction
" The function can't be redefined during the reload of the ftplugin (i.e.
" triggered by `edit`), since it is currently executing (i.e. `edit`):
"
@@ -56,6 +68,8 @@ augroup END
"
if !exists("*s:redraw_delayed")
function s:redraw_delayed(timer_id)
unlet w:man_resizing_timer_id
" Try to keep the position as close as possible, since edit will move to
" the start of the file
" TODO: this should be more accurate
@@ -72,5 +86,5 @@ endif
" lines, messing up the whole buffer. Since this is distracting, turn it off.
setlocal nowrap
endif " has('##WinResized')
endif " exists('##WinResized')
" ------------------------------------------------------------------------------

View File

@@ -3,6 +3,9 @@ setlocal colorcolumn+=51
setlocal textwidth=72
" Spell checking always enabled
setlocal spell spelllang=en
" Disable C-indentation as it messes up formatting of paragraphs containing
" parentheses
setlocal nocindent
" Disable gutentags as it seems to regenerate the entire tags file when editing
" git-commits...
@@ -17,3 +20,27 @@ let g:gutentags_enabled = 0
" When aborting a commit I usually use :cq which I can't when committing through
" fugitive. Abbreviate it to something that works.
cabbrev <buffer> cq %d <Bar> x
" Fold file listings (staged, unstaged, untracked, ...) and diff
setlocal foldmethod=syntax
" Unfold staged files and diff. inspired by:
" https://vi.stackexchange.com/questions/4050/how-to-search-for-pattern-in-certain-syntax-regions/27008#27008
if has("patch-8.2.0915") || has("nvim-0.7.0")
function s:open_fold(group, content)
" Find line containing `content` that is highlighted with `group`
let l:line_nr = search(a:content, "n", 0, 0, { ->
\ synstack('.', col('.'))
\ ->map('synIDattr(v:val, "name")')
\ ->match(a:group) < 0 })
if l:line_nr <= 0
return
endif
execute l:line_nr->string() .. "foldopen"
endfunction
call s:open_fold("gitcommitSelected", "Changes to be committed:")
call s:open_fold("gitcommitDiff", "diff --")
endif " has("patch-8.2.0915") || has("nvim-0.7.0")

View File

@@ -1,5 +1,8 @@
" Turn on line-wrapping
setlocal wrap
" Disable C-indentation as it messes up formatting of paragraphs containing
" parentheses
setlocal nocindent
" Fold by sections
function! MdSectionFold()

View File

@@ -1,5 +1,8 @@
" Turn on line-wrapping
setlocal wrap
" Disable C-indentation as it messes up formatting of paragraphs containing
" parentheses
setlocal nocindent
" Close the quickfix window after a cursor movement
let g:vimtex_quickfix_autoclose_after_keystrokes = 1

View File

@@ -1,3 +1,7 @@
" Disable C-indentation as it messes up formatting of paragraphs containing
" parentheses
setlocal nocindent
" Don't highlight Unicode table separator (e.g. vertical box drawing character).
" See vimrc.d/looks.vim for w:ignore_non_ascii_chars
if vimwiki#vars#get_syntaxlocal('rxTableSep') !~ '[\d0-\d127]'

View File

@@ -26,10 +26,13 @@ endif
" ctags
if (executable('ctags'))
packadd vim-gutentags
" Don't index these folders
let g:gutentags_ctags_exclude = [
\ 'node_modules/*',
\ '.git/*',
\ 'build/*'
\ 'build/*',
\ 'venv/*',
\ '__pycache__/*'
\]
endif
@@ -38,6 +41,12 @@ if (exists("g:loaded_tmux_navigator"))
let g:tmux_navigator_disable_when_zoomed = 1
endif
if (get(g:, 'loaded_fzf_vim'))
let g:fzf_vim = {}
" Use location list instead of quickfix list
let g:fzf_vim.listproc = { list -> fzf#vim#listproc#location(list) }
endif
if (get(g:, 'loaded_vimwiki'))
" Use vertical box drawing character as table separator
call vimwiki#vars#set_syntaxlocal('rxTableSep', '│')
@@ -47,4 +56,6 @@ if exists("g:loaded_nrrw_rgn")
" Open narrow window above or to the left of the current window (default
" is topleft). See :h aboveleft etc.
let g:nrrw_topbot_leftright = 'aboveleft'
" Leave one more line of padding when the window is small
let g:nrrw_rgn_pad = 1
endif

View File

@@ -64,7 +64,7 @@ endif
" Make <CR> to accept selected completion item or notify coc.nvim to format
" <C-g>u starts a new undo break, please make your own choice.
inoremap <silent><expr> <CR> coc#pum#visible() ? coc#pum#confirm()
inoremap <silent><expr> <CR> coc#pum#visible() ? coc#_select_confirm()
\: "\<C-g>u\<CR>\<c-r>=coc#on_enter()\<CR>"
" Use `[g` and `]g` to navigate diagnostics

View File

@@ -119,6 +119,15 @@ if (exists('g:loaded_gitgutter'))
" lines have been changed.
set foldtext=gitgutter#fold#foldtext()
endif
" Use the number column for the signcolumn (e.g. gitgutter, lsp diagnostics),
" but don't fallback to 'auto' when &number is off
" TODO: install autocommand to set signcolumn to yes when number is turned off
" (and back to number when turned back on)
if &number
set signcolumn=number
else
set signcolumn=yes
endif
" Netrw
" Use tree style listing

View File

@@ -108,26 +108,39 @@ if (get(g:, 'loaded_fzf'))
endif
" Search for selected text.
" Modified from https://vim.fandom.com/wiki/Search_for_visually_selected_text
function! GetVisualSelection()
let l:old_reg = getreg('"')
let l:old_regtype = getregtype('"')
" Modified version of:
" https://vim.fandom.com/wiki/Search_for_visually_selected_text
" and https://github.com/neovim/neovim/blob/08847a9ea15a/runtime/lua/vim/_defaults.lua#L73-L79
function! GetVisualSelection(escape = "", byteescape = 'n')
let l:save_reg = getreginfo('"')
norm gvy
let l:sel = getreg('"')
call setreg('"', l:old_reg, l:old_regtype)
call setreg('"', l:save_reg)
let l:sel = l:sel->escape(a:escape)
for l:char in a:byteescape
let l:sel = l:sel->substitute('\'..l:char, '\\'..l:char, 'g')
endfor
return l:sel
endfunction
vmap * /\V<C-R>=escape(GetVisualSelection(),'/\')<CR><CR>
vmap # ?\V<C-R>=escape(GetVisualSelection(),'?\')<CR><CR>
" In case these do not exist already (At the time of writing only Neovim adds
" mappings for these)
if maparg('*', 'v', 0, 1) == {}
vmap * /\V<C-R>=GetVisualSelection('/\')<CR><CR>
vmap # ?\V<C-R>=GetVisualSelection('?\')<CR><CR>
endif
" Extended `*`. Starts vim search (without jump) and ripgrep
nmap <leader>* :let @/ = '\<' . expand('<cword>') . '\>' <bar>
\ set hlsearch <bar>
\ Rg \b<C-R>=expand('<cword>')<CR>\b<CR>
vmap <leader>* :<C-U>let @/ = "\\V<C-R>=escape(escape(GetVisualSelection(), '\'), '"\')<CR>" <bar>
" TODO: pass --multiline to rg when multiple lines selected
" TODO: Use ^ and $ anchors in visual-line mode
vmap <leader>* :<C-U>let @/ = "\\V<C-R>=escape(GetVisualSelection('\'), '"\')<CR>" <bar>
\ set hlsearch <bar>
\ Rg <C-R>=escape(GetVisualSelection(), '.\[]<bar>*+?{}^$()')<CR><CR>
\ Rg <C-R>=GetVisualSelection('.\[]<bar>*+?{}^$()', 'nt')<CR><CR>
nmap <leader>g* :let @/ = expand('<cword>') <bar>
\ set hlsearch <bar>
\ Rg <C-R>=expand('<cword>')<CR><CR>
@@ -168,6 +181,8 @@ if exists('g:loaded_fugitive')
nmap <leader>gcc <Cmd>G commit<CR>
" Amend the current commit and open the message in a split
nmap <leader>gca <Cmd>G commit --amend<CR>
" Commit with the last commit message as template
nmap <leader>gclm <Cmd>G commit-last-msg<CR>
" Move to root of directory
nmap <leader>gcd <Cmd>Gcd<CR>
" git blame in scroll bound vertical split (only the commit hashes, see
@@ -437,7 +452,7 @@ vnoremap <leader><C-L> gu
" `ExpandVisualSelection(1)` which results in a block selection that spans over
" all other TODOs as well.
function! ExpandVisualSelection(direction)
let l:sel = escape(GetVisualSelection(), '\')
let l:sel = GetVisualSelection('\')
normal gv
" Move the cursor onto the side of the selection that points in the

View File

@@ -50,14 +50,24 @@ if (get(g:, 'loaded_fzf'))
endif
endif
" Get red from my colorscheme
let s:red = {}
if exists("*onedark#GetColors")
let s:red = onedark#GetColors()->get("red", {})
endif
let s:red_cterm = s:red->get("cterm", "red")
let s:red_gui = s:red->get("gui", "red")
" Highlight trailing whitespaces
if match(&listchars, 'trail: \@!') > -1 && match(&listchars, '\vtab:( +)@!') > -1
" Use foreground for coloring if tabs and trailing spaces are displayed
" as non-space characters
highlight TrailingWhitespace ctermfg=red guifg=red
execute "highlight TrailingWhitespace ctermfg=" .. s:red_cterm
\ .. " guifg=" .. s:red_gui
else
" Background otherwise
highlight TrailingWhitespace ctermbg=red guibg=red
execute "highlight TrailingWhitespace ctermbg=" .. s:red_cterm
\ .. " guibg=" .. s:red_gui
endif
augroup HighlightTrailingWhitespace
au!
@@ -74,8 +84,10 @@ let g:spl_special_chars = {
\ 'fr': 'àâæçèéêëîïôœùûüÿÀÂÆÇÈÉÊËÎÏÔŒÙÛÜŸ',
\ }
" Highlight non-ASCII characters in the red used by my color scheme "OneDark"
highlight NonASCIIChars ctermfg=white guifg=white ctermbg=204 guibg=#e06c75
" Highlight non-ASCII characters in red
execute "highlight NonASCIIChars ctermfg=white guifg=white "
\ .. "ctermbg=" .. s:red_cterm .. " guibg=" .. s:red_gui
" Do not highlight special characters that are valid in the respective spelllang
function! HighlightNonASCIIChars()
if exists('w:non_ascii_match_id')

View File

@@ -0,0 +1,26 @@
#!/usr/bin/env zsh
# SPDX-License-Identifier: MIT
# Copyright (c) 2025 Julian Prein
#
# Rename a branch locally and on a given remote.
emulate -L zsh -o err_return -o no_unset
if (( # < 2 || # > 3 )); then
printf >&2 "Usage: %s OLD NEW [REMOTE]\n" "${0:t}"
return 1
fi
local old new remote
old="$1"
new="$2"
remote="${3:-origin}"
if ! git remote -v | awk '{ print $1 }' | uniq | grep -q "$remote"; then
printf >&2 "Remote '%s' does not exist\n" "$remote"
return 1
fi
git checkout-worktree "$old" <<EOF
git branch -m "$new" && git push -u && git push -d "$remote" "$old"
EOF

View File

@@ -31,11 +31,13 @@
emulate -L zsh -o err_return -o no_unset
local REPO_NAME WORKTREE_PATH
local git_dir cwd_offset REPO_NAME WORKTREE_PATH
# Use the folder name of the main working tree to make calls from another
# temporary working tree possible
REPO_NAME="${${${$(git rev-parse --git-dir):A}%%/.git*}:t}"
WORKTREE_PATH="$(mktemp -d -p "" "worktree.XXX.$REPO_NAME.${1//\//_}")"
git_dir="${$(git rev-parse --git-dir):A}"
[[ $git_dir == */.git/modules/* ]] || git_dir="${git_dir%%/.git*}"
REPO_NAME="${git_dir:t}"
WORKTREE_PATH="$(mktemp -d -p "" "wtree.$REPO_NAME.${1//\//_}.XXX")"
local errc ret=0
git worktree add "$WORKTREE_PATH" "$@" || ret=$?
@@ -47,11 +49,27 @@ fi
trap '
errc=$?
<&2 printf "Exiting abnormally. Check and possibly remove '$WORKTREE_PATH' manually.\n"
printf >&2 "Exiting abnormally. Check and possibly remove \"%s\" manually.\n" "'"$WORKTREE_PATH"'"
return $errc
' INT QUIT TERM EXIT
cwd_offset="${${PWD#$(git rev-parse --show-toplevel)}#/}"
pushd -q "$WORKTREE_PATH"
until [[ -d $cwd_offset || -z $cwd_offset ]]; do
cwd_offset="${cwd_offset:h}"
done
[[ -z $cwd_offset ]] || cd "$cwd_offset"
# Discard some environment variables that were set by git when calling this
# script through an alias.
#
# Is set for submodules and will confuse git in the subshell
unset GIT_DIR
# Not sure if this can bring any issues, but better be safe
unset GIT_PREFIX
# TODO: Do we want to unset this too? Could have been set on purpose by the user
# and not git. Maybe only for the subshell via `env`?
#unset GIT_EXEC_PATH
"$SHELL" && errc=$? || errc=$?
(( !errc )) || echo "shell exited with $errc"
@@ -59,7 +77,7 @@ pushd -q "$WORKTREE_PATH"
# Restart the shell (forcefully interactive) until the worktree is removed
until [[ ! -e "$WORKTREE_PATH" ]] || git worktree remove "$WORKTREE_PATH"; do
[[ -t 0 ]] ||
>&2 printf "Dropping into interactive shell to resolve conflicts\n"
printf >&2 "Dropping into interactive shell to resolve conflicts\n"
"$SHELL" -i && errc=$? || errc=$?
(( !errc )) || echo "shell exited with $errc"
done

View File

@@ -128,7 +128,7 @@ fi
# Use a reasonable time format
alias date='env LC_TIME=tk_TM date'
# List human readable sizes in order
alias sizes='du -sch * | sort -h'
alias sizes='() { du -sch ${1:-*} "${@[2,-1]}" | sort -h }'
# Count number of occurrences for every line in stdin
alias count='sort | uniq -c | sort -n'
# Inspired by https://stackoverflow.com/a/54541337

View File

@@ -0,0 +1 @@
../../.config/git/external-script.sh

View File

@@ -1 +0,0 @@
../../.config/git/zsh-autoload.sh

View File

@@ -3,5 +3,26 @@
# Copyright (c) 2025 Julian Prein
#
# Remove ANSI escape sequences.
#
# Additionally to the general form `\e[ -/]*[0-~]` this also tries to cover
# sequences that are followed by additional bytes (e.g. CSI, OSC). This script
# covers no C1 sequences.
#
# The patterns cover the following escape sequences (from top to bottom):
# - CSI
# - OSC, DCS, PM & APC
# - SOS
# - All remaining sequences
#
# See:
# - https://en.wikipedia.org/wiki/ANSI_escape_code
# - https://www.ecma-international.org/wp-content/uploads/ECMA-35_6th_edition_december_1994.pdf
# - https://www.ecma-international.org/wp-content/uploads/ECMA-48_5th_edition_june_1991.pdf
env LC_ALL=C sed 's/\[[0-?]*[ -/]*[@-~]//g'
env LC_ALL=C sed -E "$(printf "%b" \
's/' \
'\033\\[[0-?]*[ -/]*[@-~]' '|' \
'\033[]P^_][\010-\015 -~]*\033\\\\' '|' \
'\033X([^\033]|\033+[^\033X\\])*\033+\\\\' '|' \
'\033[ -/]*[0-~]' \
'//g')"

View File

@@ -5,4 +5,4 @@
# Remove ANSI SGR (Select Graphic Rendition) escape sequences, e.g. setting
# color or bold font.
env LC_ALL=C sed 's/\[[0-?]*[ -/]*m//g'
env LC_ALL=C sed "$(printf 's/\033\\[[0-?]*[ -/]*m//g')"

View File

@@ -62,4 +62,119 @@ git diff --staged --name-only --diff-filter=AT $against \
fi
done
[ "$abort" -eq 0 ] || die
}
} || exit
# Make sure that a deletion does not break any symlinks (including renaming a
# file)
# TODO: switch all these to null-terminated lines
deleted_files="$(git diff-index --cached --name-only --diff-filter=D $against)"
if [ -n "$deleted_files" ]; then
# First, check for broken symlinks in the tree
all_broken_links="$(find . -xtype l -exec stat -c '%N' '{}' '+')"
# NOTE: The cat could be replaced by instead adding the heredoc to the
# `done` of the loop, but would make the code much less readable
cat <<EOF \
| while read -r deletion
$deleted_files
EOF
do
# As a first heuristic, check if there is a broken symlink with
# a target with the same basename as the deleted file
#
# TODO: stat escapes quotes sometimes. Does everything work
# then?
possible_links="$(
grep "[\"'/]$(
basename "$deletion" \
| sed 's/[.[^$*\\]/\\&/g'
)[\"']\$" <<EOF
$all_broken_links
EOF
)"
[ -n "$possible_links" ] || continue
cat << EOF \
| while read -r link
$possible_links
EOF
do
# TODO: this is probably quite brittle, depending on how
# `stat` quotes source and target
target="${link##* -> [\"\']}"
target="${target%[\"\']}"
source="${link%%[\"\'] -> *}"
source="${source#[\"\']}"
if [ -z "${target##/*}" ]; then
# absolute link
if [ "$target" = "$PWD/$deletion" ]; then
die "You broke the symlink $link"
fi
else
# relative link
target="$(realpath -m "$source/../$target")"
if [ "$target" = "$PWD/$deletion" ]; then
die "You broke the symlink $link"
fi
fi
done || exit
done || exit
# Second, check all symlinks in the index if they still point to the
# deleted file
all_links_in_index="$(
git ls-files --format="%(objectmode) %(objectname) %(path)" \
| grep '^120000'
)"
cat <<EOF \
| while read -r deletion
$deleted_files
EOF
do
# As a first heuristic, get all links in the tree with a target
# with the same basename as the deleted file
possible_links="$(
cut -d' ' -f2 <<EOF \
| git cat-file --batch \
| grep -B1 "\(^\|/\)$(
basename "$deletion" \
| sed 's/[.[^$*\\]/\\&/g'
)\$" \
| paste - -
$all_links_in_index
EOF
)"
[ -n "$possible_links" ] || continue
cat << EOF \
| while read -r link
$possible_links
EOF
do
target="${link#* }"
source="$(
grep -F "${link%% *}" <<EOF \
| cut -d' ' -f3-
$all_links_in_index
EOF
)"
if [ -z "${target##/*}" ]; then
# absolute link
if [ "$target" = "$PWD/$deletion" ]; then
die "You broke the symlink \"$source\" -> \"$target\""
fi
else
# relative link
target="$(realpath -m "$source/../$target")"
if [ "$target" = "$PWD/$deletion" ]; then
die "You broke the symlink \"$source\" -> \"$target\""
fi
fi
done || exit
done || exit
# TODO: also check potential symlinks pointing to now empty directories
fi