summaryrefslogtreecommitdiffstats
path: root/.config
diff options
context:
space:
mode:
authorThomas Vanbesien <tvanbesi@proton.me>2026-05-04 08:44:50 +0200
committerThomas Vanbesien <tvanbesi@proton.me>2026-05-06 16:43:16 +0200
commit0bc002288b984d8ec8123c135456570c78a22da3 (patch)
tree020ed3f6a7f28a081687a3e46ea190e3aa724f7c /.config
downloaddotfiles-0bc002288b984d8ec8123c135456570c78a22da3.tar.gz
dotfiles-0bc002288b984d8ec8123c135456570c78a22da3.zip
feat: initial setup
- `dotfiles` (this project's CLI) - foot configuration - tmux configuration - bash configuration - nvim (as a git submodule) + configuration - ranger configuration - fzf configuration - KDE global shortcuts - Other miscellaneous dependencies
Diffstat (limited to '.config')
-rw-r--r--.config/bash/bashrc62
-rw-r--r--.config/bash/inputrc88
-rw-r--r--.config/bash/vi.inputrc8
-rw-r--r--.config/foot/foot.ini37
-rw-r--r--.config/fzf/fzf.bash69
-rw-r--r--.config/kglobalshortcutsrc293
-rw-r--r--.config/nvim/after/ftplugin/bash.lua17
-rw-r--r--.config/nvim/after/ftplugin/gitcommit.lua27
-rw-r--r--.config/nvim/after/ftplugin/lua.lua36
-rw-r--r--.config/nvim/after/ftplugin/markdown.lua80
-rw-r--r--.config/nvim/after/ftplugin/qf.lua1
-rw-r--r--.config/nvim/after/queries/gitcommit/injections.scm4
-rw-r--r--.config/nvim/init.lua178
-rw-r--r--.config/nvim/plugin/10-treesitter.lua37
-rw-r--r--.config/nvim/plugin/50-autoformat.lua24
-rw-r--r--.config/nvim/plugin/50-autopairs.lua17
-rw-r--r--.config/nvim/plugin/50-colors.lua99
-rw-r--r--.config/nvim/plugin/50-completion.lua72
-rw-r--r--.config/nvim/plugin/50-dap.lua28
-rw-r--r--.config/nvim/plugin/50-dotfiles.lua36
-rw-r--r--.config/nvim/plugin/50-fold.lua22
-rw-r--r--.config/nvim/plugin/50-ftdetect.lua18
-rw-r--r--.config/nvim/plugin/50-highlight.lua101
-rw-r--r--.config/nvim/plugin/50-local.lua8
-rw-r--r--.config/nvim/plugin/50-lorem.lua35
-rw-r--r--.config/nvim/plugin/50-lsp.lua90
-rw-r--r--.config/nvim/plugin/50-netrw.lua25
-rw-r--r--.config/nvim/plugin/50-session.lua69
-rw-r--r--.config/nvim/plugin/50-spell.lua34
-rw-r--r--.config/nvim/plugin/50-statusline.lua48
-rw-r--r--.config/nvim/queries/markdown/injections.scm26
-rw-r--r--.config/nvim/spell/en.utf-8.add27
-rw-r--r--.config/nvim/spell/fr.utf-8.add19
-rw-r--r--.config/ranger/rc.conf7
-rw-r--r--.config/tmux/tmux.conf31
35 files changed, 1773 insertions, 0 deletions
diff --git a/.config/bash/bashrc b/.config/bash/bashrc
new file mode 100644
index 0000000..bd440fc
--- /dev/null
+++ b/.config/bash/bashrc
@@ -0,0 +1,62 @@
+# bashrc
+#
+# Sourced by `~/.bashrc` (which is executed by non-login interactive shells)
+
+[[ $- != *i* ]] && return # if not running interactively, stop
+
+function source_if_readable() {
+ local f="${1:?file argument missing}"
+ # shellcheck disable=1090
+ if [[ -r $f ]]; then source "$f"; fi
+}
+
+# The terminal consumes certain characters before the shell see them. This
+# disables them so Readline can bind them.
+#
+# `stty` settings live on the terminal device, not in the shell process.
+#
+# -ixon Ctrl+S and Ctrl+Q (output flow control)
+# werase undef Ctrl+W (erase word)
+stty -ixon werase undef
+
+# ** expands to all files and directories recursively
+# **/ expands to all directories recursively
+shopt -s globstar
+shopt -s extglob # extended pattern matching (like `?(a|b|c)`)
+
+alias r="fc -s" # See `help fc`
+alias wl-copy="wl-copy --trim-newline"
+
+export INPUTRC="$HOME/.config/bash/inputrc" # Readline configuration
+export VISUAL=nvim EDITOR=nvim # used by various programs like `git`, `fc`, `man`, …
+export MANPAGER="nvim +Man!" MANWIDTH=999 # `nvim` as pager for `man`
+
+# Colors and prompt
+# The terminal emulator sets $TERM
+if [[ $TERM == +(xterm-256color|tmux-256color|foot) ]]; then
+ eval "$(dircolors --bourne-shell)" # Set LS_COLORS which is used by other programs
+ alias ls='ls --color=auto'
+ alias grep='grep --color=auto'
+ alias yay='yay --color auto'
+ alias pacman='pacman --color auto'
+ alias bat='bat --color=always'
+ export LESS="--RAW-CONTROL-CHARS" # `less` display colors instead of the raw escape sequences
+ # Prompt
+ PS1='\[\033[01;32m\][\u@\h\[\033[01;37m\] \W :$SHLVL :\j\[\033[01;32m\]]\$\[\033[00m\] '
+fi
+
+# History
+shopt -s histappend # append to instead of overwriting HISTFILE
+export HISTFILE="$HOME/.config/bash/bash_history" # history file
+export HISTSIZE=1000 # number of commands to save in history
+export HISTTIMEFORMAT='%F %T ' # history entry timesptamp format, also enables multi-line entries
+export HISTFILESIZE=-1 # don't truncate history
+export HISTCONTROL="ignoreboth" # don't save duplicate lines or lines starting with a space
+
+# Completion
+source_if_readable /usr/share/bash-completion/bash_completion # see https://github.com/scop/bash-completion/#bash-completion
+source_if_readable "$HOME/.config/fzf/fzf.bash" # fzf configuration
+
+source_if_readable "$HOME/.config/bash/localrc" # local configuration
+
+# vim: ft=bash
diff --git a/.config/bash/inputrc b/.config/bash/inputrc
new file mode 100644
index 0000000..c56068e
--- /dev/null
+++ b/.config/bash/inputrc
@@ -0,0 +1,88 @@
+# ------------------------------------------------------------------------------
+# Readline configuration file
+# ------------------------------------------------------------------------------
+#
+# https://www.gnu.org/software/bash/manual/bash.html#Readline-Init-File
+#
+# Executed by Readline when a program starts the Readline library
+#
+# Options that take a string parameter cannot have a comment next to them, e.g.
+# `set bell-style none # Some comment` will not work.
+
+# ------------------------------------------------------------------------------
+# Variable settings
+# ------------------------------------------------------------------------------
+
+# Completion configuration
+#
+# It's worth noting what's going on here since it's not clear from the
+# documentation.
+#
+# There are three cases to cover for the behavior I want:
+# - Only one match → complete
+# - Multiple matches → show the list
+# - Multiple matches with common prefix → complete prefix and show the list
+#
+# By default, `menu-complete()` will select the first completion, this covers
+# the first case. `show-all-if-ambiguous` covers the second case by showing the
+# list when there are multiple choices. `menu-complete-display-prefix` covers
+# the third case by completing the common prefix.
+set show-all-if-ambiguous on
+set menu-complete-display-prefix on
+
+set editing-mode vi # Vi keybindings
+set match-hidden-files off # Don't match hidden files, unless a leading '.' is typed explicitely
+set completion-ignore-case on # Ignore case when mathching completions
+set search-ignore-case on # Ignore case when searching
+set skip-completed-text on # Don't insert match when when completing in the middle of a word
+set completion-query-items 100 # Prompt before showing more than this number of completions
+set completion-display-width 100 # 100 columns for completion results
+set print-completions-horizontally off # Sort completions horizontally
+set colored-stats on # Show completions using colors depending on file type
+set visible-stats on # Append a character denoting file type
+set colored-completion-prefix on # Color the common prefix of completions
+set expand-tilde off # Don't expand tilde automatically
+set show-mode-in-prompt on # Show current mode (vi-insert, vi-command) in prompt
+# String to display for each mode
+set vi-cmd-mode-string -CMD-
+set vi-ins-mode-string -INS-
+# Don't ring the terminal bell
+set bell-style none
+
+# ------------------------------------------------------------------------------
+# Key bindings
+# ------------------------------------------------------------------------------
+#
+# To unbind: bind to `""`
+#
+# https://www.gnu.org/software/bash/manual/bash.html#Bindable-Readline-Commands-1
+
+$if mode=vi
+
+# vi-insert ____________________________________________________________________
+set keymap vi-insert
+$include ~/.config/bash/vi.inputrc
+
+"\e\t": shell-expand-line # Alt+Tab perform shell expansion
+"\C-i": menu-complete # Tab cycle completions forward
+"\e[Z": menu-complete-backward # Shift+Tab cycle completions backward
+"\C-a": insert-completions # Ctrl+a insert all completions
+"\e!": dynamic-complete-history # Alt+! complete from history entries (not lines!)
+"\eh": backward-char # Alt+h one char backward
+"\el": forward-char # Alt+l one char forward
+"\C-b": beginning-of-line # Ctrl+b beginning of line
+"\C-e": end-of-line # Ctrl+e end of line
+
+$if Bash
+
+"\ee": "ranger\r" # Alt+e open `ranger`
+
+$endif
+
+# vi-command ___________________________________________________________________
+set keymap vi-command
+$include ~/.config/bash/vi.inputrc
+
+"u": vi-undo # u undo
+
+$endif
diff --git a/.config/bash/vi.inputrc b/.config/bash/vi.inputrc
new file mode 100644
index 0000000..4ec6049
--- /dev/null
+++ b/.config/bash/vi.inputrc
@@ -0,0 +1,8 @@
+# Readline key bindings for both the vi-insert and vi-command keymaps
+
+"\C-l": clear-screen # Ctrl+l clear screen
+"\C-w": unix-filename-rubout # Ctrl+w erase word backward (hyphens included)
+"\C-k": history-search-backward # Ctrl+k search history backward (non-incremental)
+"\C-j": history-search-forward # Ctrl+j search history forward (non-incremental)
+
+# vim: filetype=readline
diff --git a/.config/foot/foot.ini b/.config/foot/foot.ini
new file mode 100644
index 0000000..66c5f44
--- /dev/null
+++ b/.config/foot/foot.ini
@@ -0,0 +1,37 @@
+# foot configuration file
+#
+# See `/etc/xdg/foot/foot.ini` and `man 5 foot.ini`
+# Use `foot --check-config` to verify the configuration
+
+shell=/usr/bin/tmux
+term=foot
+login-shell=no
+app-id=foot
+title=foot
+locked-title=no
+; https://github.com/source-foundry/Hack
+font=Hack Nerd Font Mono:style=Regular:size=9
+initial-color-theme=dark
+initial-window-size-chars=130x40
+initial-window-mode=windowed
+
+[scrollback]
+lines=1000
+
+[key-bindings]
+fullscreen=F11
+color-theme-toggle=F10
+
+[colors-dark]
+background=242424
+foreground=e6e6e6
+regular0=242424
+regular7=e6e6e6
+
+[colors-light]
+background=e6e6e6
+foreground=242424
+regular0=e6e6e6
+regular7=242424
+
+# vim: ft=dosini
diff --git a/.config/fzf/fzf.bash b/.config/fzf/fzf.bash
new file mode 100644
index 0000000..f567a6d
--- /dev/null
+++ b/.config/fzf/fzf.bash
@@ -0,0 +1,69 @@
+# ——————————————————————————————————————————————————————————————————————————————
+# fzf configuration
+#
+# See https://github.com/junegunn/fzf
+# ——————————————————————————————————————————————————————————————————————————————
+
+fzf_default_usage='Alt+Y copy to clipboard
+Alt+/ move/hide preview'
+fzf_ctrl_t_usage='Ctrl+Y select
+Alt+Y copy to clipboard
+Alt+/ move/hide preview'
+fzf_ctrl_r_usage='Alt+R show surrounding entries
+Ctrl+R sort by relevance/recency
+Alt+Y copy to clipboard'
+fzf_alt_c_usage='Alt+Y copy to clipboard
+Alt+/ move/hide preview'
+
+# This is used by the Ctrl+T, Ctrl+R, and Alt+C bindings, unless redefined
+export FZF_DEFAULT_OPTS="
+--walker file,dir,follow,hidden
+--walker-skip .git,node_modules
+
+--bind tab:down,btab:up
+--bind 'alt-y:execute-silent(wl-copy {..})+abort'
+--bind 'alt-/:change-preview-window(down|hidden|)'
+
+--layout reverse --height 50%
+--color header:italic
+--footer '$fzf_default_usage'
+"
+
+# ——————————————————————————————————————————————————————————————————————————————
+# Ctrl+T, Ctrl+R, Alt+C function options
+#
+# See https://github.com/junegunn/fzf#key-bindings-for-command-line
+# ——————————————————————————————————————————————————————————————————————————————
+
+# (Ctrl+T) Paste the selected files and directories onto the command-line
+export FZF_CTRL_T_OPTS="
+--walker file,follow,hidden
+--preview 'bat --number --color=always {}'
+--bind ctrl-y:toggle
+--bind 'alt-/:change-preview-window(down|hidden|)'
+--footer '$fzf_ctrl_t_usage'
+"
+
+# (Ctrl+R) Paste the selected command from history onto the command-line
+export FZF_CTRL_R_OPTS="
+--bind 'alt-y:execute-silent(wl-copy {2..})+abort'
+--footer '$fzf_ctrl_r_usage'
+"
+
+# (Alt+C) `cd` into the selected directory
+export FZF_ALT_C_OPTS="
+--walker dir,follow,hidden
+--preview 'tree -C {}'
+--bind 'alt-/:change-preview-window(down|hidden|)'
+--footer '$fzf_alt_c_usage'
+"
+
+# ——————————————————————————————————————————————————————————————————————————————
+# ** fuzzy completion
+#
+# See https://github.com/junegunn/fzf#customizing-fuzzy-completion-for-bash-and-zsh
+# ——————————————————————————————————————————————————————————————————————————————
+
+# ——————————————————————————————————————————————————————————————————————————————
+
+eval "$(fzf --bash)"
diff --git a/.config/kglobalshortcutsrc b/.config/kglobalshortcutsrc
new file mode 100644
index 0000000..1be6366
--- /dev/null
+++ b/.config/kglobalshortcutsrc
@@ -0,0 +1,293 @@
+[ActivityManager]
+_k_friendly_name=Activity Manager
+switch-to-activity-4ec92300-2853-4661-b146-41fc38818210=none,none,Switch to activity "Default"
+
+[KDE Keyboard Layout Switcher]
+Switch to Last-Used Keyboard Layout=Meta+Alt+L,Meta+Alt+L,Switch to Last-Used Keyboard Layout
+Switch to Next Keyboard Layout=Meta+Alt+K,Meta+Alt+K,Switch to Next Keyboard Layout
+_k_friendly_name=Keyboard Layout Switcher
+
+[kaccess]
+Toggle Screen Reader On and Off=Meta+Alt+S,Meta+Alt+S,Toggle Screen Reader On and Off
+_k_friendly_name=Accessibility
+
+[kmix]
+_k_friendly_name=Audio Volume
+decrease_microphone_volume=Microphone Volume Down,Microphone Volume Down,Decrease Microphone Volume
+decrease_volume=Volume Down,Volume Down,Decrease Volume
+decrease_volume_small=Shift+Volume Down,Shift+Volume Down,Decrease Volume by 1%
+increase_microphone_volume=Microphone Volume Up,Microphone Volume Up,Increase Microphone Volume
+increase_volume=Volume Up,Volume Up,Increase Volume
+increase_volume_small=Shift+Volume Up,Shift+Volume Up,Increase Volume by 1%
+mic_mute=Microphone Mute\tMeta+Volume Mute,Microphone Mute\tMeta+Volume Mute,Mute Microphone
+mute=Volume Mute,Volume Mute,Mute
+
+[ksmserver]
+Halt Without Confirmation=none,,Shut Down Without Confirmation
+Lock Session=Meta+Shift+L,Meta+L\tScreensaver,Lock Session
+Log Out=Ctrl+Alt+Del,Ctrl+Alt+Del,Show Logout Screen
+Log Out Without Confirmation=none,,Log Out Without Confirmation
+LogOut=none,,Log Out
+Reboot=none,,Reboot
+Reboot Without Confirmation=none,,Reboot Without Confirmation
+Shut Down=none,,Shut Down
+_k_friendly_name=Session Management
+
+[kwin]
+Activate Window Demanding Attention=Meta+Ctrl+A,Meta+Ctrl+A,Activate Window Demanding Attention
+Cycle Overview=none,none,Cycle through Overview and Grid View
+Cycle Overview Opposite=none,none,Cycle through Grid View and Overview
+Decrease Opacity=none,,Decrease Opacity of Active Window by 5%
+Edit Tiles=none,Meta+T,Toggle Tiles Editor
+Expose=Ctrl+F9,Meta+F9\tCtrl+F9,Toggle Present Windows (Current desktop)
+ExposeAll=Ctrl+F10\tLaunch (C),Meta+F10\tLaunch (C)\tCtrl+F10,Toggle Present Windows (All desktops)
+ExposeClass=Ctrl+F7,Meta+F7\tCtrl+F7,Toggle Present Windows (Window class)
+ExposeClassCurrentDesktop=none,none,Toggle Present Windows (Window class on current desktop)
+Grid View=Meta+G,Meta+G,Toggle Grid View
+Increase Opacity=none,,Increase Opacity of Active Window by 5%
+Kill Window=Meta+Q\tMeta+Ctrl+Esc,Meta+Ctrl+Esc,Kill Window
+Move Tablet to Next LogicalOutput=none,none,Move the tablet to the next output
+Move Tablet to Next Output=none,none,Move the tablet to the next output
+MoveMouseToCenter=Meta+F6,Meta+F6,Move Mouse to Center
+MoveMouseToFocus=Meta+F5,Meta+F5,Move Mouse to Focus
+MoveZoomDown=none,none,Move Zoomed Area Downwards
+MoveZoomLeft=none,none,Move Zoomed Area to Left
+MoveZoomRight=none,none,Move Zoomed Area to Right
+MoveZoomUp=none,none,Move Zoomed Area Upwards
+Overview=Meta+W,Meta+W,Toggle Overview
+Setup Window Shortcut=none,,Setup Window Shortcut
+Show Desktop=Meta+D,Meta+D,Peek at Desktop
+Switch One Desktop Down=Meta+Ctrl+Down,Meta+Ctrl+Down,Switch One Desktop Down
+Switch One Desktop Up=Meta+Ctrl+Up,Meta+Ctrl+Up,Switch One Desktop Up
+Switch One Desktop to the Left=Meta+Ctrl+Left,Meta+Ctrl+Left,Switch One Desktop to the Left
+Switch One Desktop to the Right=Meta+Ctrl+Right,Meta+Ctrl+Right,Switch One Desktop to the Right
+Switch Window Down=Meta+Alt+Down,Meta+Alt+Down,Switch to Window Below
+Switch Window Left=Meta+Alt+Left,Meta+Alt+Left,Switch to Window to the Left
+Switch Window Right=Meta+Alt+Right,Meta+Alt+Right,Switch to Window to the Right
+Switch Window Up=Meta+Alt+Up,Meta+Alt+Up,Switch to Window Above
+Switch to Desktop 1=Ctrl+F1,Meta+F1\tCtrl+F1,Switch to Desktop 1
+Switch to Desktop 10=none,,Switch to Desktop 10
+Switch to Desktop 11=none,,Switch to Desktop 11
+Switch to Desktop 12=none,,Switch to Desktop 12
+Switch to Desktop 13=none,,Switch to Desktop 13
+Switch to Desktop 14=none,,Switch to Desktop 14
+Switch to Desktop 15=none,,Switch to Desktop 15
+Switch to Desktop 16=none,,Switch to Desktop 16
+Switch to Desktop 17=none,,Switch to Desktop 17
+Switch to Desktop 18=none,,Switch to Desktop 18
+Switch to Desktop 19=none,,Switch to Desktop 19
+Switch to Desktop 2=Ctrl+F2,Meta+F2\tCtrl+F2,Switch to Desktop 2
+Switch to Desktop 20=none,,Switch to Desktop 20
+Switch to Desktop 21=,,Switch to Desktop 21
+Switch to Desktop 22=,,Switch to Desktop 22
+Switch to Desktop 23=,,Switch to Desktop 23
+Switch to Desktop 24=,,Switch to Desktop 24
+Switch to Desktop 25=,,Switch to Desktop 25
+Switch to Desktop 3=Ctrl+F3,Meta+F3\tCtrl+F3,Switch to Desktop 3
+Switch to Desktop 4=Ctrl+F4,Meta+F4\tCtrl+F4,Switch to Desktop 4
+Switch to Desktop 5=none,,Switch to Desktop 5
+Switch to Desktop 6=none,,Switch to Desktop 6
+Switch to Desktop 7=none,,Switch to Desktop 7
+Switch to Desktop 8=none,,Switch to Desktop 8
+Switch to Desktop 9=none,,Switch to Desktop 9
+Switch to Next Desktop=none,,Switch to Next Desktop
+Switch to Next Screen=none,,Switch to Next Screen
+Switch to Previous Desktop=none,,Switch to Previous Desktop
+Switch to Previous Screen=none,,Switch to Previous Screen
+Switch to Screen 0=none,,Switch to Screen 0
+Switch to Screen 1=none,,Switch to Screen 1
+Switch to Screen 2=none,,Switch to Screen 2
+Switch to Screen 3=none,,Switch to Screen 3
+Switch to Screen 4=none,,Switch to Screen 4
+Switch to Screen 5=none,,Switch to Screen 5
+Switch to Screen 6=none,,Switch to Screen 6
+Switch to Screen 7=none,,Switch to Screen 7
+Switch to Screen Above=none,,Switch to Screen Above
+Switch to Screen Below=none,,Switch to Screen Below
+Switch to Screen to the Left=none,,Switch to Screen to the Left
+Switch to Screen to the Right=none,,Switch to Screen to the Right
+Toggle Night Color=none,none,Suspend/Resume Night Light
+Toggle Window Raise/Lower=none,,Toggle Window Raise/Lower
+Walk Through Windows=Meta+Tab,Meta+Tab\tAlt+Tab,Walk Through Windows
+Walk Through Windows (Reverse)=Meta+Shift+Tab,Meta+Shift+Tab\tAlt+Shift+Tab,Walk Through Windows (Reverse)
+Walk Through Windows Alternative=none,none,Walk Through Windows Alternative
+Walk Through Windows Alternative (Reverse)=none,none,Walk Through Windows Alternative (Reverse)
+Walk Through Windows of Current Application=Meta+`,Meta+`\tAlt+`,Walk Through Windows of Current Application
+Walk Through Windows of Current Application (Reverse)=Meta+~,Meta+~\tAlt+~,Walk Through Windows of Current Application (Reverse)
+Walk Through Windows of Current Application Alternative=none,none,Walk Through Windows of Current Application Alternative
+Walk Through Windows of Current Application Alternative (Reverse)=none,none,Walk Through Windows of Current Application Alternative (Reverse)
+Window Above Other Windows=Meta+O,,Keep Window Above Others
+Window Below Other Windows=none,,Keep Window Below Others
+Window Close=Meta+C,Alt+F4,Close Window
+Window Custom Quick Tile Bottom=none,,Custom Quick Tile Window to the Bottom
+Window Custom Quick Tile Left=none,,Custom Quick Tile Window to the Left
+Window Custom Quick Tile Right=none,,Custom Quick Tile Window to the Right
+Window Custom Quick Tile Top=none,,Custom Quick Tile Window to the Top
+Window Fullscreen=none,,Make Window Fullscreen
+Window Grow Horizontal=none,,Expand Window Horizontally
+Window Grow Vertical=none,,Expand Window Vertically
+Window Lower=none,,Lower Window
+Window Maximize=Meta+K\tMeta+PgUp,Meta+PgUp,Maximize Window
+Window Maximize Horizontal=none,,Maximize Window Horizontally
+Window Maximize Vertical=none,,Maximize Window Vertically
+Window Minimize=Meta+J\tMeta+PgDown,Meta+PgDown,Minimize Window
+Window Move=none,,Move Window
+Window Move Center=none,,Move Window to the Center
+Window No Border=none,,Toggle Window Titlebar and Frame
+Window On All Desktops=none,,Keep Window on All Desktops
+Window One Desktop Down=Meta+Ctrl+Shift+Down,Meta+Ctrl+Shift+Down,Window One Desktop Down
+Window One Desktop Up=Meta+Ctrl+Shift+Up,Meta+Ctrl+Shift+Up,Window One Desktop Up
+Window One Desktop to the Left=Meta+Ctrl+Shift+Left,Meta+Ctrl+Shift+Left,Window One Desktop to the Left
+Window One Desktop to the Right=Meta+Ctrl+Shift+Right,Meta+Ctrl+Shift+Right,Window One Desktop to the Right
+Window One Screen Down=none,,Move Window One Screen Down
+Window One Screen Up=none,,Move Window One Screen Up
+Window One Screen to the Left=none,,Move Window One Screen to the Left
+Window One Screen to the Right=none,,Move Window One Screen to the Right
+Window Operations Menu=Alt+F3,Alt+F3,Window Menu
+Window Pack Down=none,,Move Window Down
+Window Pack Left=none,,Move Window Left
+Window Pack Right=none,,Move Window Right
+Window Pack Up=none,,Move Window Up
+Window Quick Tile Bottom=Meta+Down,Meta+Down,Quick Tile Window to the Bottom
+Window Quick Tile Bottom Left=none,,Quick Tile Window to the Bottom Left
+Window Quick Tile Bottom Right=none,,Quick Tile Window to the Bottom Right
+Window Quick Tile Left=Meta+Left\tMeta+H,Meta+Left,Quick Tile Window to the Left
+Window Quick Tile Right=Meta+L\tMeta+Right,Meta+Right,Quick Tile Window to the Right
+Window Quick Tile Top=Meta+Up,Meta+Up,Quick Tile Window to the Top
+Window Quick Tile Top Left=none,,Quick Tile Window to the Top Left
+Window Quick Tile Top Right=none,,Quick Tile Window to the Top Right
+Window Raise=none,,Raise Window
+Window Resize=none,,Resize Window
+Window Shrink Horizontal=none,,Shrink Window Horizontally
+Window Shrink Vertical=none,,Shrink Window Vertically
+Window to Desktop 1=none,,Window to Desktop 1
+Window to Desktop 10=none,,Window to Desktop 10
+Window to Desktop 11=none,,Window to Desktop 11
+Window to Desktop 12=none,,Window to Desktop 12
+Window to Desktop 13=none,,Window to Desktop 13
+Window to Desktop 14=none,,Window to Desktop 14
+Window to Desktop 15=none,,Window to Desktop 15
+Window to Desktop 16=none,,Window to Desktop 16
+Window to Desktop 17=none,,Window to Desktop 17
+Window to Desktop 18=none,,Window to Desktop 18
+Window to Desktop 19=none,,Window to Desktop 19
+Window to Desktop 2=none,,Window to Desktop 2
+Window to Desktop 20=none,,Window to Desktop 20
+Window to Desktop 21=,,Window to Desktop 21
+Window to Desktop 22=,,Window to Desktop 22
+Window to Desktop 23=,,Window to Desktop 23
+Window to Desktop 24=,,Window to Desktop 24
+Window to Desktop 25=,,Window to Desktop 25
+Window to Desktop 3=none,,Window to Desktop 3
+Window to Desktop 4=none,,Window to Desktop 4
+Window to Desktop 5=none,,Window to Desktop 5
+Window to Desktop 6=none,,Window to Desktop 6
+Window to Desktop 7=none,,Window to Desktop 7
+Window to Desktop 8=none,,Window to Desktop 8
+Window to Desktop 9=none,,Window to Desktop 9
+Window to Next Desktop=none,,Window to Next Desktop
+Window to Next Screen=Meta+Shift+Right,Meta+Shift+Right,Move Window to Next Screen
+Window to Previous Desktop=none,,Window to Previous Desktop
+Window to Previous Screen=Meta+Shift+Left,Meta+Shift+Left,Move Window to Previous Screen
+Window to Screen 0=none,,Move Window to Screen 0
+Window to Screen 1=none,,Move Window to Screen 1
+Window to Screen 2=none,,Move Window to Screen 2
+Window to Screen 3=none,,Move Window to Screen 3
+Window to Screen 4=none,,Move Window to Screen 4
+Window to Screen 5=none,,Move Window to Screen 5
+Window to Screen 6=none,,Move Window to Screen 6
+Window to Screen 7=none,,Move Window to Screen 7
+_k_friendly_name=KWin
+disableInputCapture=Meta+Shift+Esc,Meta+Shift+Esc,Disable Active Input Capture
+view_actual_size=Meta+0,Meta+0,Zoom to Actual Size
+view_zoom_in=Meta++\tMeta+=,Meta++\tMeta+=,Zoom In
+view_zoom_out=Meta+-,Meta+-,Zoom Out
+
+[mediacontrol]
+_k_friendly_name=Media Controller
+mediavolumedown=none,,Media volume down
+mediavolumeup=none,,Media volume up
+nextmedia=Media Next,Media Next,Media playback next
+pausemedia=Media Pause,Media Pause,Pause media playback
+playmedia=none,,Play media playback
+playpausemedia=Media Play,Media Play,Play/Pause media playback
+previousmedia=Media Previous,Media Previous,Media playback previous
+seekbackwardmedia=Media Rewind,Media Rewind,Media playback seek backward 5s
+seekbackwardmedialong=,,Media playback seek backward 30s
+seekforwardmedia=Media Fast Forward,Media Fast Forward,Media playback seek forward 5s
+seekforwardmedialong=,,Media playback seek forward 30s
+stopmedia=Media Stop,Media Stop,Stop media playback
+
+[org_kde_powerdevil]
+Decrease Keyboard Brightness=Keyboard Brightness Down,Keyboard Brightness Down,Decrease Keyboard Brightness
+Decrease Screen Brightness=Monitor Brightness Down,Monitor Brightness Down,Decrease Screen Brightness
+Decrease Screen Brightness Small=Shift+Monitor Brightness Down,Shift+Monitor Brightness Down,Decrease Screen Brightness by 1%
+Hibernate=Hibernate,Hibernate,Hibernate
+Increase Keyboard Brightness=Keyboard Brightness Up,Keyboard Brightness Up,Increase Keyboard Brightness
+Increase Screen Brightness=Monitor Brightness Up,Monitor Brightness Up,Increase Screen Brightness
+Increase Screen Brightness Small=Shift+Monitor Brightness Up,Shift+Monitor Brightness Up,Increase Screen Brightness by 1%
+PowerDown=Power Down,Power Down,Power Down
+PowerOff=Power Off,Power Off,Power Off
+Sleep=Sleep,Sleep,Suspend
+Toggle Keyboard Backlight=Keyboard Light On/Off,Keyboard Light On/Off,Toggle Keyboard Backlight
+Turn Off Screen=none,none,Turn Off Screen
+_k_friendly_name=Power Management
+powerProfile=none,Battery\tMeta+B,Switch Power Profile
+
+[plasmashell]
+Slideshow Wallpaper Next Image=none,,Next Wallpaper Image
+_k_friendly_name=plasmashell
+activate application launcher=none,Meta\tAlt+F1,Activate Application Launcher
+activate task manager entry 1=Meta+1,Meta+1,Activate Task Manager Entry 1
+activate task manager entry 10=none,,Activate Task Manager Entry 10
+activate task manager entry 2=Meta+2,Meta+2,Activate Task Manager Entry 2
+activate task manager entry 3=Meta+3,Meta+3,Activate Task Manager Entry 3
+activate task manager entry 4=Meta+4,Meta+4,Activate Task Manager Entry 4
+activate task manager entry 5=Meta+5,Meta+5,Activate Task Manager Entry 5
+activate task manager entry 6=Meta+6,Meta+6,Activate Task Manager Entry 6
+activate task manager entry 7=Meta+7,Meta+7,Activate Task Manager Entry 7
+activate task manager entry 8=Meta+8,Meta+8,Activate Task Manager Entry 8
+activate task manager entry 9=Meta+9,Meta+9,Activate Task Manager Entry 9
+activate widget 25=none,none,Activate Icons-and-Text Task Manager Widget
+activate widget 26=none,none,Activate Application Menu Widget
+activate widget 27=Alt+Space,none,Activate Application Menu Widget
+clear-history=none,,Clear Clipboard History
+clipboard_action=Meta+Ctrl+X,Meta+Ctrl+X,Automatic Action Popup Menu
+cycle-panels=Meta+Alt+P,Meta+Alt+P,Move keyboard focus between panels
+cycleNextAction=none,,Next History Item
+cyclePrevAction=none,,Previous History Item
+edit_clipboard=none,,Edit Contents…
+manage activities=none,Meta+Q,Show Activity Switcher
+next activity=none,none,Walk through activities
+previous activity=none,none,Walk through activities (Reverse)
+repeat_action=none,,Manually Invoke Action on Current Clipboard
+show dashboard=Ctrl+F12,Ctrl+F12,Show Desktop
+show-barcode=none,,Show Barcode…
+show-on-mouse-pos=Meta+V,Meta+V,Show Clipboard Items at Mouse Position
+switch to next activity=none,,Switch to Next Activity
+switch to previous activity=none,,Switch to Previous Activity
+toggle do not disturb=none,,Toggle do not disturb
+
+[services][firefox.desktop]
+_launch=Meta+Shift+B
+
+[services][foot.desktop]
+_launch=Meta+Shift+T
+
+[services][net.local.open_wiki_index_firefox.bash.desktop]
+_launch=Meta+Ctrl+I
+
+[services][net.local.open_wiki_index_nvim.bash.desktop]
+_launch=Meta+I
+
+[services][org.kde.konsole.desktop]
+_launch=none
+
+[services][org.kde.krunner.desktop]
+_launch=Search\tAlt+F2\tMeta
+
+[services][org.keepassxc.KeePassXC.desktop]
+_launch=Meta+K
+
+[services][org.mozilla.Thunderbird.desktop]
+_launch=Meta+Shift+M
diff --git a/.config/nvim/after/ftplugin/bash.lua b/.config/nvim/after/ftplugin/bash.lua
new file mode 100644
index 0000000..d46657d
--- /dev/null
+++ b/.config/nvim/after/ftplugin/bash.lua
@@ -0,0 +1,17 @@
+vim.opt_local.textwidth = 80 -- gw wraps at this value
+vim.opt_local.colorcolumn = "+1" -- Highlight one column after 'textwidth'
+vim.opt_local.complete = {
+ "o", -- 'omnifunc'
+}
+
+vim.b.autoformat = true
+vim.b.format_func = function()
+ local ret = vim.system({ "shfmt" }, { stdin = vim.api.nvim_buf_get_lines(0, 0, -1, false) }):wait()
+ if ret.code ~= 0 then
+ vim.notify("shfmt failed (" .. ret.code .. "):\n" .. ret.stderr, vim.log.levels.WARN)
+ return
+ end
+ local view = vim.fn.winsaveview()
+ vim.cmd("%!shfmt")
+ vim.fn.winrestview(view)
+end
diff --git a/.config/nvim/after/ftplugin/gitcommit.lua b/.config/nvim/after/ftplugin/gitcommit.lua
new file mode 100644
index 0000000..e52a2d8
--- /dev/null
+++ b/.config/nvim/after/ftplugin/gitcommit.lua
@@ -0,0 +1,27 @@
+vim.opt_local.colorcolumn = "+1" -- Highlight one column after 'textwidth'
+vim.opt_local.tabstop = 2 -- CommonMark expects two spaces for indentation
+vim.opt_local.shiftwidth = 0
+vim.opt_local.softtabstop = -1
+vim.opt_local.expandtab = true -- Change tabs to spaces
+vim.opt_local.spelllang = "en_us"
+vim.opt_local.complete = {
+ "w", -- other windows
+ ".", -- current buffer
+}
+
+vim.api.nvim_create_autocmd("BufWinEnter", {
+ desc = "Set up gitcommit buffer",
+ group = vim.g.dotfiles.augroup,
+ buffer = 0,
+ callback = function()
+ local gitcommit_window = vim.api.nvim_get_current_win()
+ -- Open cached diff window
+ vim.cmd.DiffGitCached()
+ vim.cmd.wincmd("L")
+ -- Enable English spell check in the original window
+ -- If `'spell'` is set before `:DiffGitChached` it propagates to the cached diff window
+ vim.api.nvim_set_option_value("spell", true, { win = gitcommit_window })
+ -- The current window is the diff window
+ vim.o.filetype = "diff"
+ end,
+})
diff --git a/.config/nvim/after/ftplugin/lua.lua b/.config/nvim/after/ftplugin/lua.lua
new file mode 100644
index 0000000..784915e
--- /dev/null
+++ b/.config/nvim/after/ftplugin/lua.lua
@@ -0,0 +1,36 @@
+local function format()
+ local view = vim.fn.winsaveview()
+ local buf_str = ""
+ for _, v in ipairs(vim.api.nvim_buf_get_lines(0, 0, -1, false)) do
+ buf_str = buf_str .. v .. "\n"
+ end
+ local tempname = vim.fn.tempname()
+ local tempfile = assert(io.open(tempname, "w"), "Could not open temporary file")
+ tempfile:write(buf_str)
+ tempfile:close()
+ local r_check = vim.system({ "stylua", "--check", tempname }):wait()
+ if r_check.code == 0 then
+ return
+ elseif r_check.code ~= 1 then
+ vim.notify("stylua failed (" .. r_check.code .. "):\n" .. r_check.stderr)
+ end
+ local r_format = vim.system({ "stylua", tempname }):wait()
+ if r_format.code ~= 0 then
+ vim.notify("stylua failed (" .. r_format.code .. "):\n" .. r_format.stderr)
+ end
+ local formatted_lines = {}
+ for line in io.lines(tempname) do
+ formatted_lines[#formatted_lines + 1] = line
+ end
+ vim.api.nvim_buf_set_lines(0, 0, -1, false, formatted_lines)
+ vim.fn.winrestview(view)
+end
+
+vim.opt_local.textwidth = 120 -- gw wraps at this value
+vim.opt_local.colorcolumn = "+1" -- Highlight one column after
+vim.opt_local.complete = {
+ "o", -- 'omnifunc'
+}
+
+vim.b.autoformat = true
+vim.b.format_func = format
diff --git a/.config/nvim/after/ftplugin/markdown.lua b/.config/nvim/after/ftplugin/markdown.lua
new file mode 100644
index 0000000..755b9aa
--- /dev/null
+++ b/.config/nvim/after/ftplugin/markdown.lua
@@ -0,0 +1,80 @@
+local function format(callback)
+ local view = vim.fn.winsaveview()
+ local buf_str = ""
+ for _, v in ipairs(vim.api.nvim_buf_get_lines(0, 0, -1, false)) do
+ buf_str = buf_str .. v .. "\n"
+ end
+ local tempname = vim.fn.tempname()
+ local tempfile = assert(io.open(tempname, "w"), "Could not open temporary file")
+ tempfile:write(buf_str)
+ tempfile:close()
+
+ local r_check = vim.system({
+ "mdformat",
+ "--number",
+ "--extensions",
+ "tables",
+ "--extensions",
+ "frontmatter",
+ "--wrap",
+ tostring(vim.bo.textwidth),
+ "--check",
+ tempname,
+ }):wait()
+ if r_check.code == 0 then
+ return
+ elseif r_check.code ~= 1 then
+ vim.notify("mdformat failed (" .. r_check.code .. "):\n" .. r_check.stderr)
+ end
+ local r_format = vim.system({
+ "mdformat",
+ "--number",
+ "--extensions",
+ "tables",
+ "--extensions",
+ "frontmatter",
+ "--wrap",
+ tostring(vim.bo.textwidth),
+ tempname,
+ }):wait()
+ if r_format.code ~= 0 then
+ vim.notify("mdformat failed (" .. r_format.code .. "):\n" .. r_format.stderr)
+ end
+ local formatted_lines = {}
+ for line in io.lines(tempname) do
+ formatted_lines[#formatted_lines + 1] = line
+ end
+ vim.api.nvim_buf_set_lines(0, 0, -1, false, formatted_lines)
+
+ vim.fn.winrestview(view)
+ if callback then
+ callback()
+ end
+end
+
+vim.opt_local.tabstop = 2 -- CommonMark expects two spaces for indentation
+vim.opt_local.shiftwidth = 0
+vim.opt_local.softtabstop = -1
+vim.opt_local.expandtab = true -- Change tabs to spaces
+-- Nothing in the gutter, except sign columns if necessary
+vim.opt_local.number = false
+vim.opt_local.relativenumber = false
+vim.opt_local.signcolumn = "auto"
+vim.opt_local.foldcolumn = "0"
+--
+vim.opt_local.textwidth = 120 -- gw wraps at this value
+vim.opt_local.colorcolumn = "+1" -- Highlight one column after 'textwidth'
+vim.opt_local.foldlevel = 1
+-- Replace concealed text with a character from `'listchars'`
+-- With `'foldmethod'` set to `expr` and `'foldlevel'` set to 2 fenced code blocks are concealed and completely invisible
+-- I guess that's a TODO for later, find a way to use `'conceallevel'` = 2 but with folded fenced code blocks visible
+vim.opt_local.conceallevel = 1
+vim.opt_local.complete = {
+ "o", -- 'omnifunc'
+ ".", -- current buffer
+}
+-- Visible link labels
+vim.api.nvim_set_hl(0, "@markup.link.label.markdown_inline", { underline = true, update = true })
+
+vim.b.autoformat = true
+vim.b.format_func = format
diff --git a/.config/nvim/after/ftplugin/qf.lua b/.config/nvim/after/ftplugin/qf.lua
new file mode 100644
index 0000000..80aec64
--- /dev/null
+++ b/.config/nvim/after/ftplugin/qf.lua
@@ -0,0 +1 @@
+vim.opt.wrap = false
diff --git a/.config/nvim/after/queries/gitcommit/injections.scm b/.config/nvim/after/queries/gitcommit/injections.scm
new file mode 100644
index 0000000..5996a50
--- /dev/null
+++ b/.config/nvim/after/queries/gitcommit/injections.scm
@@ -0,0 +1,4 @@
+((message) @injection.content
+ (#set! injection.language "markdown_inline"))
+((message_line) @injection.content
+ (#set! injection.language "markdown_inline"))
diff --git a/.config/nvim/init.lua b/.config/nvim/init.lua
new file mode 100644
index 0000000..0a116d5
--- /dev/null
+++ b/.config/nvim/init.lua
@@ -0,0 +1,178 @@
+if vim.env.DOTFILES_DIR == nil then
+ vim.notify("DOTFILES_DIR is not set!", vim.log.levels.WARN)
+end
+
+vim.g.dotfiles = { augroup = vim.api.nvim_create_augroup("dotfiles", {}) }
+
+------------------------------------------------------------------------------------------------------------------------
+-- Local functions
+------------------------------------------------------------------------------------------------------------------------
+
+-- Show the diff between the current buffer and the file it was loaded from
+local function show_buf_diff_orig()
+ vim.cmd.new({ mods = { vertical = true } })
+ vim.b.buftype = "nofile"
+ vim.cmd.read("++edit #")
+ vim.api.nvim_buf_set_lines(0, 0, 2, true, {})
+ vim.cmd.diffthis()
+ vim.cmd.wincmd("p")
+ vim.cmd.diffthis()
+end
+
+local function reload_buffer()
+ local view = vim.fn.winsaveview()
+ if vim.o.filetype == "netrw" then
+ vim.cmd.edit(".")
+ else
+ vim.cmd.edit()
+ end
+ vim.fn.winrestview(view)
+end
+
+local function toggle_wrap()
+ vim.o.wrap = not vim.o.wrap
+end
+
+------------------------------------------------------------------------------------------------------------------------
+-- Miscellaneous
+------------------------------------------------------------------------------------------------------------------------
+
+vim.g.mapleader = " " -- Set before any `vim.keymap.set()` call
+
+-- Highlight on yank
+vim.api.nvim_create_autocmd("TextYankPost", {
+ desc = "Highlight on yank",
+ group = vim.g.dotfiles.augroup,
+ callback = function()
+ vim.hl.on_yank()
+ end,
+})
+
+-- Start terminal mode automatically
+vim.api.nvim_create_autocmd({ "WinEnter", "TermOpen" }, {
+ desc = "Start terminal mode",
+ group = vim.g.dotfiles.augroup,
+ pattern = "term://*",
+ callback = function()
+ vim.cmd.startinsert()
+ end,
+})
+
+------------------------------------------------------------------------------------------------------------------------
+-- Plugins
+------------------------------------------------------------------------------------------------------------------------
+
+vim.pack.add({
+ "https://github.com/qadzek/link.vim", -- Tidy URLs
+ "https://github.com/tpope/vim-surround", -- Manipulate delimiters
+ "https://github.com/airblade/vim-gitgutter", -- Show git status in the gutter
+})
+
+------------------------------------------------------------------------------------------------------------------------
+-- Commands (there's more in the different plugins)
+------------------------------------------------------------------------------------------------------------------------
+
+vim.api.nvim_create_user_command("DiffOrig", show_buf_diff_orig, { desc = "Show diff between current buffer and file" })
+
+------------------------------------------------------------------------------------------------------------------------
+-- Keymaps (there's more in the different plugins)
+------------------------------------------------------------------------------------------------------------------------
+-- See `:help key-notation` and `:help <Cmd>`
+
+-- Miscellaneous
+vim.keymap.set("n", "<Leader>s", "<Cmd>update<CR>", { desc = "Save buffer" })
+vim.keymap.set("n", "<Leader>be", reload_buffer, { desc = "Reload buffer" })
+vim.keymap.set("n", "<Leader>bd", "<Cmd>bdelete<CR>", { desc = "Delete current buffer" })
+vim.keymap.set("n", "<Leader>bb", "<Cmd>close<CR>", { desc = "Delete current window" })
+vim.keymap.set("n", "<Leader>bw", toggle_wrap, { desc = "Toggle text wrap" })
+vim.keymap.set("n", "<M-z>", "zA", { desc = "Toggle fold (recursively) under cursor" })
+vim.keymap.set("n", "ZR", vim.cmd.SessionRestart, { desc = "Save and load default session and restart" })
+vim.keymap.set("n", "ZZ", vim.cmd.SessionExitSave, { desc = "Save to default session and exit" })
+vim.keymap.set("n", "ZQ", vim.cmd.SessionExitNoSave, { desc = "Save to default session and exit" })
+vim.keymap.set("t", "<C-\\><C-\\>", "<C-\\><C-n>", { desc = "Exit terminal mode" })
+vim.keymap.set("n", "<Leader>mm", "<Cmd>messages<CR>", { desc = "Show all messages" })
+vim.keymap.set("n", "<Leader>mc", "<Cmd>messages clear<CR>", { desc = "Clear all messages" })
+vim.keymap.set("n", "<Leader>lh", vim.cmd.LspHintToggle, { desc = "Toggle inlay hints (LSP)" })
+-- These two mappings work well together to start command mode and insert from history in two keystrokes.
+vim.keymap.set("n", "<C-p>", ":", { desc = "Enter command mode" })
+vim.keymap.set("c", "<C-p>", "<Up>", { desc = "Insert previous history entry" })
+-- Navigate files
+vim.keymap.set("n", "<M-e>", vim.cmd.GotoExplorer, { desc = "Open/close/focus netrw window" })
+-- Navigate window
+vim.keymap.set({ "n", "i" }, "<M-h>", "<C-w>h", { desc = "Move left a window" })
+vim.keymap.set({ "n", "i" }, "<M-j>", "<C-w>j", { desc = "Move down a window" })
+vim.keymap.set({ "n", "i" }, "<M-k>", "<C-w>k", { desc = "Move up a window" })
+vim.keymap.set({ "n", "i" }, "<M-l>", "<C-w>l", { desc = "Move right a window" })
+vim.keymap.set("t", "<M-h>", "<C-\\><C-n><C-w>h", { desc = "Move left a window" })
+vim.keymap.set("t", "<M-j>", "<C-\\><C-n><C-w>j", { desc = "Move down a windowd" })
+vim.keymap.set("t", "<M-k>", "<C-\\><C-n><C-w>k", { desc = "Move up a window" })
+vim.keymap.set("t", "<M-l>", "<C-\\><C-n><C-w>l", { desc = "Move right a window" })
+-- Navigate tab
+vim.keymap.set({ "n", "i", "t" }, "<M-n>", "<Cmd>tabnext #<CR>", { desc = "Move to last accessed tab page" })
+vim.keymap.set({ "n", "i", "t" }, "<M-n>", "<Cmd>tabnext<CR>", { desc = "Move to next tab page" })
+vim.keymap.set({ "n", "i", "t" }, "<M-b>", "<Cmd>tabprevious<CR>", { desc = "Move to previous tab page" })
+vim.keymap.set("i", "<M-h>", "<Space><BS><Left>")
+vim.keymap.set("i", "<M-l>", "<Space><BS><Right>")
+-- Navigate in command/insert mode
+vim.keymap.set({ "c", "i" }, "<M-h>", "<Space><BS><Left>")
+vim.keymap.set({ "c", "i" }, "<M-l>", "<Space><BS><Right>")
+vim.keymap.set("c", "<M-H>", "<C-Left>")
+vim.keymap.set("c", "<M-L>", "<C-Right>")
+-- Non incremental history search, works when the completion menu is active
+vim.keymap.set("c", "<C-k>", function()
+ return vim.fn.pumvisible() == 1 and "<C-e><Up>" or "<Up>"
+end, { expr = true })
+vim.keymap.set("c", "<C-j>", function()
+ return vim.fn.pumvisible() == 1 and "<C-e><Down>" or "<Down>"
+end, { expr = true })
+
+------------------------------------------------------------------------------------------------------------------------
+-- Options
+------------------------------------------------------------------------------------------------------------------------
+
+vim.opt.shell = "/usr/bin/bash"
+vim.opt.foldenable = true -- Folds are closed by default
+vim.opt.pumheight = 0 -- Popup menu height
+vim.opt.confirm = true -- Confirm before losing buffer unsaved changes
+vim.opt.splitbelow = false
+vim.opt.splitright = false
+vim.opt.clipboard = "unnamedplus" -- Sync clipboard
+vim.opt.cursorline = true -- Highlight the line where the cursor is on.
+vim.opt.scrolloff = 2 -- Keep this many screen lines above/below the cursor
+vim.opt.ignorecase = true -- Search ignores case by default
+vim.opt.smartcase = true -- Search is case-sensitive if searching for uppercase characters
+vim.opt.conceallevel = 2 -- Hide text with the "conceal" syntax attribute
+vim.opt.list = true -- Display <Tab> and other non-printables
+vim.opt.listchars = { -- Characters used by 'list'
+ tab = "> ", -- Tab
+ trail = "-", -- Trailing space
+ nbsp = "+", -- Non-breakable space
+ extends = "→", -- Last column when 'wrap' is off
+ precedes = "←", -- First column when there is text before it
+}
+-- See `'cpoptions'`
+-- Use a `\` like `CTRL_V` in mappings, abbreviations, user commands and the "to" part of menu commands
+-- Useful for example for matching mappings that start with space: `:map \ `
+vim.opt.cpoptions:remove("B")
+-- Backup
+vim.opt.swapfile = true -- Store a swap file, see `:help swap-file`
+vim.opt.undofile = true -- Save buffer undo history
+vim.opt.backup = true -- Backup file before overwriting
+vim.opt.backupdir = { vim.fn.stdpath("state") .. "/nvim/backup//" }
+vim.opt.writebackup = true -- Keep backup after writing file
+-- Gutter
+vim.opt.number = true -- Show line number
+vim.opt.relativenumber = true -- Show relative line number
+vim.opt.numberwidth = 4 -- Minimal number of columns for line number (includes the space before the text)
+vim.opt.signcolumn = "auto" -- Always show sign column
+vim.opt.foldcolumn = "0" -- Fixed number of fold columns
+-- Wrapping
+vim.opt.wrap = false -- Don't wrap text by default
+vim.opt.showbreak = "+++ " -- String to show wrapped lines
+vim.opt.linebreak = true -- Wrap at characters in 'breakat'
+vim.opt.breakindent = true -- Indent wrapped lines
+-- Tab and backspace (See `help 30.5`)
+vim.opt.tabstop = 4 -- <Tab> and <Bs> visually expand at columns multiple of 'tabstop'
+vim.opt.shiftwidth = 0 -- Number of space in first indendation. If 0 use 'tabstop' value.
+vim.opt.softtabstop = -1 -- <Tab> and <Bs> stop at columns multiple of 'softtabstop'. If <0 use 'shiftwidth' value.
+vim.opt.expandtab = false -- Don't turn tabs into spaces
diff --git a/.config/nvim/plugin/10-treesitter.lua b/.config/nvim/plugin/10-treesitter.lua
new file mode 100644
index 0000000..4602519
--- /dev/null
+++ b/.config/nvim/plugin/10-treesitter.lua
@@ -0,0 +1,37 @@
+--
+-- Treesitter parsers
+--
+
+vim.pack.add({ "https://github.com/nvim-treesitter/nvim-treesitter" })
+
+require("nvim-treesitter").install({
+ "bash",
+ "diff",
+ "gitcommit",
+ "ini",
+ "json",
+ "lua",
+ "markdown",
+ "markdown_inline",
+ "readline",
+ "vim",
+ "vimdoc",
+})
+
+-- Parse the tree as early as possible, which is as soon as we know the filetype
+--
+-- Event handlers for the same event are triggered in the order they were created. This must be the first FileType
+-- handler created so that the tree is parsed for other FileType handlers (which often need the parsed tree). To create
+-- it first put this in a file that comes before alphabetically in the `plugin/` directory.
+vim.api.nvim_create_autocmd("FileType", {
+ desc = "Start treesitter",
+ group = vim.g.dotfiles.augroup,
+ callback = function()
+ local parser = vim.treesitter.get_parser(0)
+ if parser == nil then
+ return
+ end
+ parser:parse() -- Parse once asynchronously; used by logic that needs the parsed tree (like extmarks)
+ vim.treesitter.start()
+ end,
+})
diff --git a/.config/nvim/plugin/50-autoformat.lua b/.config/nvim/plugin/50-autoformat.lua
new file mode 100644
index 0000000..4761097
--- /dev/null
+++ b/.config/nvim/plugin/50-autoformat.lua
@@ -0,0 +1,24 @@
+--
+-- Autoformat plugin
+--
+
+local function toggle_autoformat()
+ vim.b.autoformat = not vim.b.autoformat
+end
+
+-- Autoformat
+vim.api.nvim_create_autocmd("BufWritePre", {
+ desc = "Autoformat buffer",
+ group = vim.g.dotfiles.augroup,
+ callback = function(ev)
+ if vim.b.autoformat then
+ if vim.b.format_func == nil then
+ vim.notify("No formatter set for " .. ev.file .. " (" .. vim.o.filetype .. ")", vim.log.levels.WARN)
+ return
+ end
+ vim.b.format_func()
+ end
+ end,
+})
+
+vim.api.nvim_create_user_command("AutoformatToggle", toggle_autoformat, { desc = "Toggle autoformatting" })
diff --git a/.config/nvim/plugin/50-autopairs.lua b/.config/nvim/plugin/50-autopairs.lua
new file mode 100644
index 0000000..2ab41c8
--- /dev/null
+++ b/.config/nvim/plugin/50-autopairs.lua
@@ -0,0 +1,17 @@
+--
+-- Autopairs configuration (inserting matching delimiters while inserting)
+--
+-- See https://github.com/windwp/nvim-autopairs
+
+vim.pack.add({ "https://github.com/windwp/nvim-autopairs" })
+
+local Rule = require("nvim-autopairs.rule")
+local npairs = require("nvim-autopairs")
+local cond = require("nvim-autopairs.conds")
+
+npairs.setup()
+
+npairs.add_rules({
+ Rule("*", "*", "markdown"):with_cr(cond.none()),
+ Rule("~", "~", "markdown"):with_cr(cond.none()),
+})
diff --git a/.config/nvim/plugin/50-colors.lua b/.config/nvim/plugin/50-colors.lua
new file mode 100644
index 0000000..f713a74
--- /dev/null
+++ b/.config/nvim/plugin/50-colors.lua
@@ -0,0 +1,99 @@
+--
+-- Color scheme plugin
+--
+vim.pack.add({ "https://github.com/maxmx03/solarized.nvim" }) -- Solarized color scheme
+
+local solarized_colors = {
+ base03 = "#002b36",
+ base02 = "#073642",
+ base01 = "#586e75",
+ base00 = "#657b83",
+ base0 = "#839496",
+ base1 = "#93a1a1",
+ base2 = "#eee8d5",
+ base3 = "#fdf6e3",
+ yellow = "#b58900",
+ orange = "#cb4b16",
+ red = "#dc322f",
+ magenta = "#d33682",
+ violet = "#6c71c4",
+ blue = "#268bd2",
+ cyan = "#2aa198",
+ green = "#859900",
+}
+
+local function adjust_highlight()
+ if vim.g.colors_name == "solarized" then
+ -- General highlight
+ vim.api.nvim_set_hl(0, "EndOfBuffer", { fg = solarized_colors.base0, update = true })
+ vim.api.nvim_set_hl(0, "MatchParen", { link = "CurSearch" })
+ if vim.o.background == "light" then
+ vim.api.nvim_set_hl(0, "TabLineSel", { bg = "#edffd5" })
+ vim.api.nvim_set_hl(0, "Cursorline", { bg = "#edffd5" })
+ vim.api.nvim_set_hl(0, "NormalFloat", { bg = solarized_colors.base2 })
+ elseif vim.o.background == "dark" then
+ vim.api.nvim_set_hl(0, "TabLineSel", { bg = "#043624" })
+ vim.api.nvim_set_hl(0, "Cursorline", { bg = "#043624" })
+ vim.api.nvim_set_hl(0, "NormalFloat", { bg = solarized_colors.base02 })
+ end
+
+ -- Markdown highlight
+ if vim.o.background == "light" then
+ vim.api.nvim_set_hl(0, "@markup.raw", { bg = solarized_colors.base2, update = true })
+ elseif vim.o.background == "dark" then
+ vim.api.nvim_set_hl(0, "@markup.raw", { bg = solarized_colors.base02, update = true })
+ end
+ vim.api.nvim_set_hl(0, "@markup.raw.block", { fg = solarized_colors.cyan, update = true })
+ vim.api.nvim_set_hl(0, "@markup.heading.1", { link = "@markup.heading" })
+ vim.api.nvim_set_hl(0, "@markup.heading.2", { link = "@markup.heading" })
+ vim.api.nvim_set_hl(0, "@markup.heading.3", { link = "@markup.heading" })
+ vim.api.nvim_set_hl(0, "@markup.heading.4", { link = "@markup.heading" })
+ vim.api.nvim_set_hl(0, "@markup.heading.5", { link = "@markup.heading" })
+ vim.api.nvim_set_hl(0, "@markup.heading.6", { link = "@markup.heading" })
+ end
+end
+
+local function next_colorscheme()
+ local colorschemes = vim.fn.getcompletion("", "color")
+ vim.g.colors_name = vim.g.colors_name or "default"
+ for i = 1, #colorschemes do
+ if colorschemes[i] == vim.g.colors_name then
+ vim.cmd.colorscheme(colorschemes[(i % #colorschemes) + 1])
+ vim.notify("Color scheme set to " .. vim.g.colors_name)
+ return
+ end
+ end
+end
+
+local function random_colorscheme()
+ local colorschemes = vim.fn.getcompletion("", "color")
+ vim.cmd.colorscheme(colorschemes[math.random(#colorschemes)])
+ vim.notify("Color scheme set to " .. vim.g.colors_name)
+end
+
+local function toggle_theme()
+ vim.opt.background = vim.o.background == "light" and "dark" or "light"
+ vim.notify("Color theme set to " .. vim.o.background)
+end
+
+-- Adjust colors after the color scheme has loaded
+vim.api.nvim_create_autocmd("ColorScheme", {
+ desc = "Adjust color scheme",
+ group = vim.g.dotfiles.augroup,
+ callback = adjust_highlight,
+})
+
+-- Adjust colors when the theme (light/dark) changes
+vim.api.nvim_create_autocmd("OptionSet", {
+ desc = "Adjust color scheme",
+ pattern = "background",
+ group = vim.g.dotfiles.augroup,
+ callback = adjust_highlight,
+})
+
+vim.cmd.colorscheme("solarized") -- Default colorscheme
+vim.opt.background = "dark" -- Default theme
+
+vim.api.nvim_create_user_command("ColorsNext", next_colorscheme, { desc = "Load next color scheme" })
+vim.api.nvim_create_user_command("ColorsRandom", random_colorscheme, { desc = "Load random color scheme" })
+vim.api.nvim_create_user_command("ColorsThemeToggle", toggle_theme, { desc = "Toggle light/dark theme" })
diff --git a/.config/nvim/plugin/50-completion.lua b/.config/nvim/plugin/50-completion.lua
new file mode 100644
index 0000000..94b4cbb
--- /dev/null
+++ b/.config/nvim/plugin/50-completion.lua
@@ -0,0 +1,72 @@
+--
+-- Completion configuration plugin
+--
+
+------------------------------------------------------------------------------------------------------------------------
+-- Insert mode completion
+------------------------------------------------------------------------------------------------------------------------
+-- See `:help ins-completion-menu`
+
+vim.opt.autocomplete = true -- Show completion menu automatically
+vim.opt.completeopt = {
+ "noselect", -- No item selected initially
+ "fuzzy",
+ "menuone", -- Show matches in a menu, even if there's only one match
+ "popup", -- Menu items show extra ingo in the popup window
+ "preview", -- Show extra info in the preview window
+}
+-- Completion sources (in order of priority)
+vim.opt.complete = {
+ "o", -- 'omnifunc'
+}
+vim.opt.pumwidth = 25
+vim.keymap.set("i", "<Tab>", function()
+ return vim.fn.pumvisible() == 1 and "<C-n>" or "<Tab>"
+end, { expr = true })
+vim.keymap.set("i", "<S-Tab>", function()
+ return vim.fn.pumvisible() == 1 and "<C-p>" or "<S-Tab>"
+end, { expr = true })
+
+------------------------------------------------------------------------------------------------------------------------
+-- Command-line mode completion
+------------------------------------------------------------------------------------------------------------------------
+-- See `:help cmdline-completion` and `:help cmdline-autocompletion`
+
+-- Show completion menu automatically
+vim.api.nvim_create_autocmd({ "CmdlineChanged", "CmdlineEnter" }, {
+ desc = "Autocompletion",
+ group = vim.g.dotfiles.augroup,
+ pattern = "[:\\/\\?]",
+ callback = function()
+ vim.cmd.call("wildtrigger()")
+ end,
+})
+vim.opt.wildmenu = true -- Show completions in a menu
+vim.opt.wildchar = 9 -- Char code assigned to command line wildcard expansion
+vim.opt.wildoptions = {
+ "exacttext", -- Discard regex artifacts when performing search pattern completion
+ "pum", -- Show completions in a popup menu
+ "tagfile", -- Show tag kind and file
+ "fuzzy", -- Fuzzy matching (doesn't work with files/dirs, see `:help 'wildoptions'`, but patterns do work!)
+}
+-- Completion modes triggered in order by `wildtrigger()` or 'wildchar'
+vim.opt.wildmode = {
+ "noselect", -- List matches without inserting
+ "full", -- List matches and insert first full match
+}
+-- Insert unique match
+vim.keymap.set("c", string.format("%c", vim.o.wildchar), function()
+ local complete_info = vim.fn.cmdcomplete_info()
+ if complete_info.pum_visible == 1 then
+ return #complete_info.matches == 1 and "<C-n><Space><BS>" or "<C-n>"
+ end
+ vim.fn.wildtrigger()
+end, { expr = true, desc = "Command line wildcard expansion" })
+-- Show next completion choices after accepting an entry with `<C-y>`
+vim.keymap.set("c", "<C-y>", function()
+ local complete_info = vim.fn.cmdcomplete_info()
+ if complete_info.pum_visible == 1 then
+ return complete_info.selected ~= -1 and "<Space><BS>" or "<C-e>"
+ end
+ return "<C-y>"
+end, { expr = true })
diff --git a/.config/nvim/plugin/50-dap.lua b/.config/nvim/plugin/50-dap.lua
new file mode 100644
index 0000000..683984c
--- /dev/null
+++ b/.config/nvim/plugin/50-dap.lua
@@ -0,0 +1,28 @@
+--
+-- DAP client/adapter configurations
+--
+
+vim.pack.add({ "https://github.com/mfussenegger/nvim-dap" }) -- DAP (Debug Adapter Protocol) client
+local dap = require("dap")
+
+-- OSV configuration
+vim.pack.add({ "https://github.com/jbyuki/one-small-step-for-vimkind" }) -- DAP adapter for Neovim Lua
+local osv = require("osv")
+
+dap.configurations.lua = {
+ {
+ type = "nlua",
+ request = "attach",
+ name = "Attach to running Neovim instance",
+ },
+}
+dap.adapters.nlua = function(callback, config)
+ callback({ type = "server", host = config.host or "127.0.0.1", port = config.port or 8086 })
+end
+vim.api.nvim_create_user_command("OSVLaunch", function()
+ osv.launch({ port = 8086 })
+end, { desc = "Launch OSV server" })
+vim.api.nvim_create_user_command("OSVStatus", function()
+ vim.notify("OSV server running: " .. tostring(osv.is_running()))
+ vim.notify("OSV client attached: " .. tostring(osv.is_attached()))
+end, { desc = "Show OSV status" })
diff --git a/.config/nvim/plugin/50-dotfiles.lua b/.config/nvim/plugin/50-dotfiles.lua
new file mode 100644
index 0000000..122912c
--- /dev/null
+++ b/.config/nvim/plugin/50-dotfiles.lua
@@ -0,0 +1,36 @@
+--
+-- dotfiles plugin
+--
+
+-- Returns true if the current buffer is part of the Dotfiles repository
+local function detect_dotfiles_file()
+ if vim.env.DOTFILES_DIR == nil then
+ return false
+ end
+ local ret = vim.system(
+ { "git", "--git-dir=" .. vim.env.DOTFILES_DIR, "--work-tree=" .. vim.env.HOME, "ls-files" },
+ { text = true }
+ ):wait()
+ local buf_file_name = string.sub(vim.api.nvim_buf_get_name(0), #vim.env.HOME + 2)
+ for _, dotfiles_filename in ipairs(vim.split(ret.stdout, "\n", { trimempty = true })) do
+ if dotfiles_filename == buf_file_name then
+ return true
+ end
+ end
+ return false
+end
+
+vim.api.nvim_create_autocmd("BufEnter", {
+ desc = "Detect dotfiles file",
+ group = vim.g.dotfiles.augroup,
+ callback = function()
+ vim.b.dotfiles_file = detect_dotfiles_file()
+ end,
+})
+
+vim.api.nvim_create_user_command("DotfilesOn", function()
+ vim.g.gitgutter_git_args = "--git-dir=" .. vim.env.DOTFILES_DIR .. " --work-tree=" .. vim.env.HOME
+end, { desc = "Activate dotfiles (set git env)" })
+vim.api.nvim_create_user_command("DotfilesOff", function()
+ vim.g.gitgutter_git_args = ""
+end, { desc = "Deactivate dotfiles (unset git env)" })
diff --git a/.config/nvim/plugin/50-fold.lua b/.config/nvim/plugin/50-fold.lua
new file mode 100644
index 0000000..c7013bb
--- /dev/null
+++ b/.config/nvim/plugin/50-fold.lua
@@ -0,0 +1,22 @@
+--
+-- fold plugin
+--
+
+-- Initialize folds with foldmethod = expr if a treesitter parser is available, then switch back to manual
+-- This is to have the folds calculated and closed when editing the file initially, but with foldmethod set to manual
+-- Without foldmethod set to manual folds are created while writing in insert mode which is annoying
+--
+-- Skip floating windows, because they often are documentation (and thus should be visible by default)
+vim.api.nvim_create_autocmd("FileType", {
+ desc = "Initialize folds",
+ group = vim.g.dotfiles.augroup,
+ callback = function(ev)
+ if vim.api.nvim_win_get_config(0).relative ~= "" or vim.treesitter.get_parser(0) == nil then
+ return
+ end
+ vim.opt_local.foldexpr = "v:lua.vim.treesitter.foldexpr()"
+ vim.opt_local.foldmethod = "expr"
+ vim.cmd.normal({ "zX", bang = true })
+ vim.opt_local.foldmethod = "manual"
+ end,
+})
diff --git a/.config/nvim/plugin/50-ftdetect.lua b/.config/nvim/plugin/50-ftdetect.lua
new file mode 100644
index 0000000..49fc6d6
--- /dev/null
+++ b/.config/nvim/plugin/50-ftdetect.lua
@@ -0,0 +1,18 @@
+--
+-- Filetype detection plugin
+--
+
+-- Detect bash files
+vim.api.nvim_create_autocmd({ "BufRead", "BufNewFile" }, {
+ desc = "Detect bash file",
+ group = vim.g.dotfiles.augroup,
+ pattern = "*",
+ callback = function()
+ if
+ string.find(vim.api.nvim_buf_get_name(0), "%.bash$")
+ or string.find(vim.api.nvim_buf_get_lines(0, 0, 1, false)[1] or "", "^#!/usr/bin/bash")
+ then
+ vim.bo.filetype = "bash"
+ end
+ end,
+})
diff --git a/.config/nvim/plugin/50-highlight.lua b/.config/nvim/plugin/50-highlight.lua
new file mode 100644
index 0000000..0e8fb97
--- /dev/null
+++ b/.config/nvim/plugin/50-highlight.lua
@@ -0,0 +1,101 @@
+--
+-- Custom highlighting plugin (in `after/` to that the autocommand in `treesitter/init.lua` can be set first in order)
+--
+
+-- Returns an iterator over the ascendants of `node`, starting at the root node
+local function node_ascendants(node)
+ local root = node:tree():root()
+ local current = root
+ return function()
+ if current:equal(node) then
+ return nil
+ end
+ current = assert(current:child_with_descendant(node))
+ return current
+ end
+end
+
+-- Returns true if `node` or any of its parent has the type `type`
+local function node_within_type(node, type)
+ local next_ascendant = node_ascendants(node)
+ local next = next_ascendant()
+ while next do
+ if next:type() == type then
+ return true
+ end
+ next = next_ascendant()
+ end
+ return false
+end
+
+-- Returns an iterator over the positions (`{ col1, col2, row }`) of matches of pattern in lines
+local function pmatches(lines, pattern)
+ local col1, col2, row = nil, nil, 1
+ return function()
+ while row < #lines do
+ col1, col2 = string.find(lines[row], pattern, (col2 or 0) + 1)
+ if col1 then
+ return { col1 = col1, col2 = col2, row = row }
+ else
+ col1, col2, row = 0, 0, row + 1
+ end
+ end
+ return nil
+ end
+end
+
+-- Set extmarks are the positions (`{ col1, col2, row }`) given by `next_pos()`
+-- `opts`: {
+-- ns: highlight namespace
+-- predicate: is passed row and col, if true then set the mark
+-- hl_group: highlight group
+-- }
+local function set_extmarks(next_pos, opts)
+ for pos in next_pos do
+ local marks = vim.api.nvim_buf_get_extmarks(
+ 0,
+ opts.ns,
+ { pos.row - 1, pos.col1 - 1 },
+ { pos.row - 1, pos.col2 - 1 },
+ {}
+ )
+ if #marks == 0 and opts.predicate(pos.row - 1, pos.col1 - 1) then
+ vim.api.nvim_buf_set_extmark(
+ 0,
+ opts.ns,
+ pos.row - 1,
+ pos.col1 - 1,
+ { end_col = pos.col2, hl_group = opts.hl_group }
+ )
+ end
+ pos = next_pos()
+ end
+end
+
+-- TODO a better way to do this:
+-- For code, only check in "comment" node ranges
+-- For non-code, do it per type. For Markdown, only check "paragraph" nodes
+local function hl_todo_predicate(row, col)
+ if vim.o.filetype == "markdown" or vim.treesitter.get_parser() == nil then
+ return true
+ end
+ local node = assert(vim.treesitter.get_node({ pos = { row, col } }))
+ return node_within_type(node, "comment")
+end
+
+local patterns = { todo = "TODO" }
+local hl_ns = vim.api.nvim_create_namespace("extmarks")
+
+vim.api.nvim_set_hl(hl_ns, "dotfiles.Todo", { bg = "Yellow", fg = "Black", bold = true })
+local extmarks_todo_opts = { ns = hl_ns, hl_group = "dotfiles.Todo", predicate = hl_todo_predicate }
+
+-- Initialize extmarks
+vim.api.nvim_create_autocmd("FileType", {
+ desc = "Initialize extmarks",
+ group = vim.g.dotfiles.augroup,
+ callback = function()
+ vim.api.nvim_win_set_hl_ns(vim.api.nvim_get_current_win(), hl_ns)
+ local lines = vim.api.nvim_buf_get_lines(0, 0, -1, false)
+ set_extmarks(pmatches(lines, patterns.todo), extmarks_todo_opts)
+ end,
+})
diff --git a/.config/nvim/plugin/50-local.lua b/.config/nvim/plugin/50-local.lua
new file mode 100644
index 0000000..88c63c5
--- /dev/null
+++ b/.config/nvim/plugin/50-local.lua
@@ -0,0 +1,8 @@
+--
+-- local include plugin
+--
+
+local local_config_file = vim.fn.stdpath("config") .. "/local.lua"
+if vim.uv.fs_stat(local_config_file) then
+ dofile(local_config_file)
+end
diff --git a/.config/nvim/plugin/50-lorem.lua b/.config/nvim/plugin/50-lorem.lua
new file mode 100644
index 0000000..8970574
--- /dev/null
+++ b/.config/nvim/plugin/50-lorem.lua
@@ -0,0 +1,35 @@
+--
+-- Lorem plugin (command to insert "lorem ipsum" words)
+--
+
+-- Returns lorem ipsum words
+local function iter_lorem()
+ local filename = vim.env.HOME .. "/.local/share/dotfiles/lorem.txt"
+ local file = assert(io.open(filename, "r"))
+ local string = file:read("*all")
+ io.close(file)
+ local lorem_words = vim.split(vim.trim(string), " ", { trimempty = true })
+ local i = 0
+ return function()
+ i = i % #lorem_words + 1
+ return lorem_words[i]
+ end
+end
+
+-- Returns a n words long "lorem ipsum" string
+local function get_lorem(n)
+ local iter = iter_lorem()
+ local words = {}
+ for i = 1, n do
+ words[i] = iter()
+ end
+ return table.concat(words, " ")
+end
+
+local function put_lorem(n)
+ vim.api.nvim_put({ get_lorem(n) }, "c", true, true)
+end
+
+vim.api.nvim_create_user_command("Lorem", function(opts)
+ put_lorem(tonumber(opts.args))
+end, { desc = "Put lorem ipsum string", nargs = 1 })
diff --git a/.config/nvim/plugin/50-lsp.lua b/.config/nvim/plugin/50-lsp.lua
new file mode 100644
index 0000000..de86ecd
--- /dev/null
+++ b/.config/nvim/plugin/50-lsp.lua
@@ -0,0 +1,90 @@
+--
+-- LSP client configurations
+--
+
+local function inspect_lsp()
+ local client = vim.lsp.get_clients()[1]
+ if client == nil then
+ vim.notify("No LSP client loaded")
+ return
+ end
+ vim.notify(vim.inspect(client.server_capabilities), vim.log.levels.INFO)
+end
+
+vim.pack.add({ "https://github.com/neovim/nvim-lspconfig" })
+
+vim.api.nvim_create_user_command("LspInspect", inspect_lsp, { desc = "Inpsect LSP client" })
+
+-- Enable LSP server capabilities if available when attaching, see `:help lsp-attach`
+vim.api.nvim_create_autocmd("LspAttach", {
+ desc = "Enable LSP capabilities",
+ group = vim.g.dotfiles.augroup,
+ callback = function(ev)
+ local client = assert(vim.lsp.get_client_by_id(ev.data.client_id))
+ if client:supports_method("textDocument/completion") then
+ vim.lsp.completion.enable(true, client.id, ev.buf, { autotrigger = true })
+ else
+ vim.notify("Client " .. client.name .. " does not support completion", vim.log.levels.WARN)
+ end
+ if client:supports_method("textDocument/inlayHint") then
+ vim.lsp.inlay_hint.enable(true, { bufnr = 0 })
+ else
+ vim.notify("Client " .. client.name .. " does not support inlay hints", vim.log.levels.WARN)
+ end
+ end,
+})
+
+vim.api.nvim_create_user_command("LspHintToggle", function()
+ vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled({ bufnr = 0 }), { bufnr = 0 })
+end, { desc = "Toggle LSP inlay hints" })
+
+------------------------------------------------------------------------------------------------------------------------
+-- Lua
+------------------------------------------------------------------------------------------------------------------------
+
+vim.lsp.config("lua_ls", {
+ on_init = function(client)
+ -- Use `.luarc.json` or `.luarc.jsonc` if available, then exit
+ -- See `:help vim.lsp.ClientConfig` for `workspace_folders`
+ if client.workspace_folders then
+ local path = client.workspace_folders[1].name
+ if
+ path ~= vim.fn.stdpath("config")
+ and (vim.uv.fs_stat(path .. "/.luarc.json") or vim.uv.fs_stat(path .. "/.luarc.jsonc"))
+ then
+ return
+ end
+ end
+ -- See Lua language server configuration settings at https://luals.github.io/wiki/settings
+ client.config.settings.Lua = vim.tbl_deep_extend("force", client.config.settings.Lua, {
+ runtime = {
+ version = "Lua 5.1",
+ path = { "?.lua", "?/init.lua" }, -- See `:h lua-module-load`
+ },
+ workspace = {
+ checkThirdParty = false,
+ library = vim.api.nvim_get_runtime_file("", true), -- Load all folders in 'runtimepath'
+ },
+ })
+ end,
+})
+vim.lsp.enable("lua_ls")
+
+------------------------------------------------------------------------------------------------------------------------
+-- Bash
+------------------------------------------------------------------------------------------------------------------------
+
+vim.lsp.enable("bashls")
+
+------------------------------------------------------------------------------------------------------------------------
+-- Markdown
+------------------------------------------------------------------------------------------------------------------------
+
+vim.lsp.config("marksman", { filetypes = { "markdown" } })
+vim.lsp.enable("marksman")
+
+------------------------------------------------------------------------------------------------------------------------
+-- Vimscript
+------------------------------------------------------------------------------------------------------------------------
+
+vim.lsp.enable("vimls")
diff --git a/.config/nvim/plugin/50-netrw.lua b/.config/nvim/plugin/50-netrw.lua
new file mode 100644
index 0000000..4fdbfa6
--- /dev/null
+++ b/.config/nvim/plugin/50-netrw.lua
@@ -0,0 +1,25 @@
+--
+-- netrw plugin
+--
+
+local function explore()
+ local windows = vim.api.nvim_tabpage_list_wins(0)
+ for _, win in ipairs(windows) do
+ local buf = vim.api.nvim_win_get_buf(win)
+ local ft = vim.api.nvim_get_option_value("filetype", { buf = buf })
+ if ft == "netrw" then
+ if win ~= vim.api.nvim_get_current_win() then
+ vim.api.nvim_set_current_win(win)
+ return
+ end
+ break
+ end
+ end
+ vim.cmd.Lexplore()
+end
+
+vim.g.netrw_liststyle = 3 -- 3: list style
+vim.g.netrw_winsize = -30 -- 30 colums wide
+vim.g.netrw_banner = 0 -- No banner
+
+vim.api.nvim_create_user_command("GotoExplorer", explore, { desc = "Open/close/focus netrw window" })
diff --git a/.config/nvim/plugin/50-session.lua b/.config/nvim/plugin/50-session.lua
new file mode 100644
index 0000000..b4aadda
--- /dev/null
+++ b/.config/nvim/plugin/50-session.lua
@@ -0,0 +1,69 @@
+--
+-- Session plugin
+--
+
+local session_dir = vim.fn.stdpath("state") .. "/sessions"
+local session_default = session_dir .. "/default.vim"
+if not vim.uv.fs_stat(session_dir) then
+ vim.uv.fs_mkdir(session_dir, tonumber("755", 8))
+ vim.notify("Sessions save directory created at " .. session_dir)
+end
+
+local function save_session(path)
+ vim.cmd.mksession({ path, bang = true })
+end
+
+local function load_session(path)
+ vim.cmd.source(path)
+end
+
+local function reload_session(path)
+ save_session(path)
+ vim.cmd.restart({ args = { "+qall", "SessionLoad", path } })
+end
+
+local function delete_session(path)
+ vim.fs.rm(path)
+end
+
+local function session_completefunc(arg_lead, _, _)
+ local completions = {}
+ for path in vim.fs.dir(session_dir) do
+ if string.match(path, "^" .. arg_lead) and string.match(path, ".vim$") then
+ completions[#completions + 1] = path:sub(1, -5)
+ end
+ end
+ return completions
+end
+
+local function session_op(base, op)
+ local path = #base > 0 and base or session_default
+ if not string.match(path, "^" .. session_dir) then
+ path = session_dir .. "/" .. path
+ end
+ if not string.match(path, "%.vim$") then
+ path = path .. ".vim"
+ end
+ op(path)
+end
+
+vim.api.nvim_create_user_command("SessionSave", function(ev)
+ session_op(ev.args, save_session)
+end, { desc = "Save session", nargs = "?", complete = session_completefunc })
+vim.api.nvim_create_user_command("SessionLoad", function(ev)
+ session_op(ev.args, load_session)
+end, { desc = "Load session", nargs = "?", complete = session_completefunc })
+vim.api.nvim_create_user_command("SessionDelete", function(ev)
+ session_op(ev.args, delete_session)
+end, { desc = "Delete session", nargs = "?", complete = session_completefunc })
+vim.api.nvim_create_user_command("SessionRestart", function(ev)
+ session_op(ev.args, reload_session)
+end, { desc = "Reload session", nargs = "?", complete = session_completefunc })
+vim.api.nvim_create_user_command("SessionExitSave", function(ev)
+ session_op(ev.args, save_session)
+ vim.cmd.qall()
+end, { desc = "Save and exit session", nargs = "?", complete = session_completefunc })
+vim.api.nvim_create_user_command("SessionExitNoSave", function(ev)
+ session_op(ev.args, save_session)
+ vim.cmd.qall({ bang = true })
+end, { desc = "Save and exit session", nargs = "?", complete = session_completefunc })
diff --git a/.config/nvim/plugin/50-spell.lua b/.config/nvim/plugin/50-spell.lua
new file mode 100644
index 0000000..56d4c5f
--- /dev/null
+++ b/.config/nvim/plugin/50-spell.lua
@@ -0,0 +1,34 @@
+--
+-- Spell check plugin
+--
+
+local function toggle_spell()
+ vim.o.spell = not vim.o.spell
+end
+
+local function set_spell_en()
+ vim.opt.spelllang = { "en_us" }
+end
+
+local function set_spell_fr()
+ vim.opt.spelllang = { "fr" }
+end
+
+local function set_spell_en_fr()
+ vim.opt.spelllang = { "en_us", "fr" }
+end
+
+vim.opt.spelllang = "en_us" -- Initial spell language
+vim.opt.spellfile = { -- Spellfiles for zg, zw, z=, etc
+ "/home/tvanbesi/.config/nvim/spell/en.utf-8.add",
+ "/home/tvanbesi/.config/nvim/spell/fr.utf-8.add",
+}
+
+vim.api.nvim_create_user_command("SpellToggle", toggle_spell, { desc = "Toggle spell checking" })
+vim.api.nvim_create_user_command("SpellSetEn", set_spell_en, { desc = "Set spell language to English" })
+vim.api.nvim_create_user_command("SpellSetFr", set_spell_fr, { desc = "Set spell language to French" })
+vim.api.nvim_create_user_command(
+ "SpellSetEnFr",
+ set_spell_en_fr,
+ { desc = "Set spell languages to English and French" }
+)
diff --git a/.config/nvim/plugin/50-statusline.lua b/.config/nvim/plugin/50-statusline.lua
new file mode 100644
index 0000000..092f08f
--- /dev/null
+++ b/.config/nvim/plugin/50-statusline.lua
@@ -0,0 +1,48 @@
+--
+-- Status line configuration plugin
+--
+-- I use lualine, see https://github.com/nvim-lualine/lualine.nvim#configuring-lualine-in-initvim
+
+vim.pack.add({
+ "https://github.com/nvim-tree/nvim-web-devicons",
+ "https://github.com/nvim-lualine/lualine.nvim",
+})
+local lualine = require("lualine")
+
+local function spell_status()
+ if vim.o.spelllang == "fr" then
+ return "+S(fr)"
+ elseif vim.o.spelllang == "en_us" then
+ return "+S(en)"
+ elseif vim.o.spelllang == "en_us,fr" then
+ return "+S(en,fr)"
+ end
+end
+
+local function statuses()
+ return (vim.b.autoformat and "+F" or "") .. (vim.o.spell and spell_status() or "")
+end
+
+local lualine_sections = {
+ lualine_c = { statuses, "filename" },
+ lualine_x = { "encoding", "fileformat", "filetype", "lsp_status" },
+}
+
+-- Adjust colors when the theme (light/dark) changes
+vim.api.nvim_create_autocmd("OptionSet", {
+ desc = "Adjust color scheme",
+ pattern = "background",
+ group = vim.g.dotfiles.augroup,
+ callback = function()
+ lualine.setup({
+ options = { theme = vim.o.background == "light" and "solarized_light" or "solarized_dark" },
+ sections = lualine_sections,
+ })
+ end,
+})
+
+lualine.setup({ options = { theme = "solarized_light" }, sections = lualine_sections })
+
+vim.api.nvim_create_user_command("LualineConfig", function()
+ vim.notify(vim.inspect(lualine.get_config()))
+end, { desc = "Show lualine configuration" })
diff --git a/.config/nvim/queries/markdown/injections.scm b/.config/nvim/queries/markdown/injections.scm
new file mode 100644
index 0000000..c24cbd8
--- /dev/null
+++ b/.config/nvim/queries/markdown/injections.scm
@@ -0,0 +1,26 @@
+; See /home/tvanbesi/.local/share/nvim/site/queries/markdown/injections.scm
+; It's the same but with language-specific highlighting disabled in fenced code blocks
+
+(fenced_code_block
+ (code_fence_content) @injection.content)
+
+((html_block) @injection.content
+ (#set! injection.language "html")
+ (#set! injection.combined)
+ (#set! injection.include-children))
+
+((minus_metadata) @injection.content
+ (#set! injection.language "yaml")
+ (#offset! @injection.content 1 0 -1 0)
+ (#set! injection.include-children))
+
+((plus_metadata) @injection.content
+ (#set! injection.language "toml")
+ (#offset! @injection.content 1 0 -1 0)
+ (#set! injection.include-children))
+
+([
+ (inline)
+ (pipe_table_cell)
+] @injection.content
+ (#set! injection.language "markdown_inline"))
diff --git a/.config/nvim/spell/en.utf-8.add b/.config/nvim/spell/en.utf-8.add
new file mode 100644
index 0000000..3f63cf8
--- /dev/null
+++ b/.config/nvim/spell/en.utf-8.add
@@ -0,0 +1,27 @@
+self-consciousness
+self-aware
+MDMA
+stimming
+hyperfixations
+lol
+fuck-ups
+Christelle
+ChatGPT
+dataset
+whitelist
+Konsole
+nvim
+prepends
+cheatsheets
+TLS
+Neovim
+keybinds
+README
+gitignore
+autocommand
+Dotfiles
+dotfiles
+Cheatsheet
+tmux
+fzf
+submodule
diff --git a/.config/nvim/spell/fr.utf-8.add b/.config/nvim/spell/fr.utf-8.add
new file mode 100644
index 0000000..16cfe93
--- /dev/null
+++ b/.config/nvim/spell/fr.utf-8.add
@@ -0,0 +1,19 @@
+j'apprenne
+histrionique
+psy
+kétamine
+addictologue
+t'allais
+conso
+lol
+seum
+super-héros
+niqués
+qu'intéragir
+hyperfixation
+Repens-toi
+Jean-Philippe
+Christelle
+dermatophagie
+dit-il
+mdr
diff --git a/.config/ranger/rc.conf b/.config/ranger/rc.conf
new file mode 100644
index 0000000..b0ab044
--- /dev/null
+++ b/.config/ranger/rc.conf
@@ -0,0 +1,7 @@
+# ranger configuration file
+#
+# ranger first load a system-wide set of defaults before reading this file
+# You can see it with `ranger --copy-config` or at `/usr/share/doc/ranger/config`
+
+# `gio` is provided by `glib2`
+map dT shell gio trash %s
diff --git a/.config/tmux/tmux.conf b/.config/tmux/tmux.conf
new file mode 100644
index 0000000..967f5c0
--- /dev/null
+++ b/.config/tmux/tmux.conf
@@ -0,0 +1,31 @@
+# tmux configuration file
+
+# See `man 1 tmux`
+# Ran when tmux's server start (not the client)
+# To reload: `source-file ~/.config/tmux/tmux.conf`
+
+set-option -g default-shell /usr/bin/bash
+set-option -g mode-keys vi
+set-option -g status-keys vi
+set-option -g mouse on
+set-option -g status-right-length 50
+set-option -g status-left-length 20
+
+bind-key -T root M-: command-prompt
+bind-key -T root M-M choose-tree
+
+bind-key -T root M-T new-window
+bind-key -T root M-N next-window
+bind-key -T root M-B previous-window
+bind-key -T root M-P last-window
+bind-key -T prefix < swap-window -d -t -1
+bind-key -T prefix > swap-window -d -t +1
+bind-key -T prefix r command-prompt -I "#W" { rename-window "%%" }
+bind-key -T prefix R command-prompt -I "#S" { rename-session "%%" }
+
+bind-key -T root M-H select-pane -L
+bind-key -T root M-J select-pane -D
+bind-key -T root M-K select-pane -U
+bind-key -T root M-L select-pane -R
+bind-key -T root M-S split-window
+bind-key -T root M-V split-window -h