├── .chezmoiignore ├── dot_config ├── bat │ └── config ├── fish │ ├── conf.d │ │ ├── _fzf_init.fish │ │ ├── _zoxide_init.fish │ │ ├── _ghr_init.fish │ │ ├── abbreviations.fish │ │ └── _brew_env.fish │ ├── fish_plugins │ └── config.fish ├── nvim │ ├── after │ │ ├── ftplugin │ │ │ ├── gitconfig.lua │ │ │ ├── gitcommit.lua │ │ │ ├── json.lua │ │ │ ├── lua.lua │ │ │ ├── fish.lua │ │ │ ├── go.lua │ │ │ ├── python.lua │ │ │ └── markdown.lua │ │ └── plugin │ │ │ ├── abbreviations.rc.lua │ │ │ ├── abolish.rc.lua │ │ │ ├── usercommands.rc.lua │ │ │ ├── overrides │ │ │ └── unimpaired.rc.lua │ │ │ └── autocommands.rc.lua │ ├── lua │ │ └── my │ │ │ ├── nightly.lua │ │ │ ├── plugman.lua │ │ │ ├── plugins │ │ │ ├── filetypes.lua │ │ │ ├── misc.lua │ │ │ ├── navigation.lua │ │ │ ├── fzf.lua │ │ │ ├── coding.lua │ │ │ ├── ui.lua │ │ │ ├── treesitter.lua │ │ │ ├── integrations.lua │ │ │ ├── pde.lua │ │ │ ├── lspconfig.lua │ │ │ └── completion.lua │ │ │ ├── format.lua │ │ │ ├── utils.lua │ │ │ ├── maps.lua │ │ │ └── options.lua │ ├── stylua.toml │ ├── plugin │ │ ├── sync-term-colors.lua │ │ ├── bufonly.lua │ │ ├── live-server.lua │ │ ├── simple-statusline.lua │ │ └── spell-pop.lua │ ├── .luacheckrc │ └── init.lua ├── kitty │ ├── default-shell.conf.tmpl │ └── macos.conf ├── presenterm │ └── config.yaml ├── sketchybar │ ├── items │ │ ├── executable_cpu.sh │ │ ├── executable_calendar.sh │ │ ├── executable_volume.sh │ │ ├── executable_battery.sh │ │ ├── executable_media.sh │ │ ├── executable_front_app.sh │ │ └── executable_spaces.sh │ ├── plugins │ │ ├── executable_calendar.sh │ │ ├── executable_media.sh │ │ ├── executable_front_app.sh │ │ ├── executable_volume.sh │ │ ├── executable_cpu.sh │ │ ├── executable_space.sh │ │ ├── executable_battery.sh │ │ └── executable_icon_map_fn.sh │ ├── executable_colors.sh │ └── executable_sketchybarrc ├── alacritty │ └── alacritty.toml.tmpl ├── fzf │ └── config ├── ctags │ └── config.ctags ├── git │ ├── message │ ├── globalignore │ └── config.tmpl ├── yabai │ └── yabairc ├── private_karabiner │ ├── private_assets │ │ └── private_complex_modifications │ │ │ └── mine.json │ └── private_karabiner.json ├── skhd │ └── skhdrc └── tmux │ └── tmux.conf ├── .chezmoi.toml.tmpl ├── dot_local └── bin │ └── executable_tat └── README.md /.chezmoiignore: -------------------------------------------------------------------------------- 1 | README.md 2 | -------------------------------------------------------------------------------- /dot_config/bat/config: -------------------------------------------------------------------------------- 1 | --theme="Catppuccin Frappe" 2 | -------------------------------------------------------------------------------- /dot_config/fish/conf.d/_fzf_init.fish: -------------------------------------------------------------------------------- 1 | fzf --fish | source 2 | -------------------------------------------------------------------------------- /dot_config/fish/conf.d/_zoxide_init.fish: -------------------------------------------------------------------------------- 1 | zoxide init fish | source 2 | -------------------------------------------------------------------------------- /dot_config/nvim/after/ftplugin/gitconfig.lua: -------------------------------------------------------------------------------- 1 | vim.opt_local.expandtab = false 2 | -------------------------------------------------------------------------------- /dot_config/nvim/after/ftplugin/gitcommit.lua: -------------------------------------------------------------------------------- 1 | vim.opt_local.colorcolumn = { vim.bo.textwidth } 2 | -------------------------------------------------------------------------------- /dot_config/nvim/after/ftplugin/json.lua: -------------------------------------------------------------------------------- 1 | vim.opt_local.shiftwidth = 4 2 | vim.opt_local.tabstop = 4 3 | -------------------------------------------------------------------------------- /dot_config/kitty/default-shell.conf.tmpl: -------------------------------------------------------------------------------- 1 | env SHELL={{ .shell }} 2 | shell {{ .shell }} --login --interactive 3 | -------------------------------------------------------------------------------- /dot_config/fish/conf.d/_ghr_init.fish: -------------------------------------------------------------------------------- 1 | ! set -q GHR_INIT; and set -gx GHR_INIT true; and ghr shell fish | source 2 | -------------------------------------------------------------------------------- /dot_config/nvim/lua/my/nightly.lua: -------------------------------------------------------------------------------- 1 | -- Config specific for nightly 2 | if not vim.version().prerelease then 3 | return 4 | end 5 | -------------------------------------------------------------------------------- /dot_config/presenterm/config.yaml: -------------------------------------------------------------------------------- 1 | defaults: 2 | theme: terminal-dark 3 | image_protocol: kitty-local 4 | snippet: 5 | exec: 6 | enable: true 7 | -------------------------------------------------------------------------------- /dot_config/nvim/after/ftplugin/lua.lua: -------------------------------------------------------------------------------- 1 | -- nvim runtime overrides our `formatoptions` just remove the unwated stuff here 2 | vim.opt_local.formatoptions:remove('o') 3 | -------------------------------------------------------------------------------- /dot_config/nvim/after/ftplugin/fish.lua: -------------------------------------------------------------------------------- 1 | vim.opt_local.shiftwidth = 4 2 | vim.opt_local.tabstop = 4 3 | vim.opt_local.softtabstop = 4 4 | vim.opt_local.expandtab = false 5 | -------------------------------------------------------------------------------- /dot_config/nvim/after/ftplugin/go.lua: -------------------------------------------------------------------------------- 1 | vim.opt_local.shiftwidth = 4 2 | vim.opt_local.tabstop = 4 3 | vim.opt_local.softtabstop = 4 4 | vim.opt_local.expandtab = false 5 | -------------------------------------------------------------------------------- /dot_config/sketchybar/items/executable_cpu.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | sketchybar --add item cpu right \ 4 | --set cpu update_freq=2 icon=􀫥 script="$PLUGIN_DIR/cpu.sh" 5 | -------------------------------------------------------------------------------- /dot_config/nvim/stylua.toml: -------------------------------------------------------------------------------- 1 | column_width = 120 2 | line_endings = "Unix" 3 | indent_type = "Spaces" 4 | indent_width = 2 5 | quote_style = "AutoPreferSingle" 6 | call_parentheses = "NoSingleTable" 7 | -------------------------------------------------------------------------------- /dot_config/sketchybar/items/executable_calendar.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | sketchybar --add item calendar right \ 4 | --set calendar update_freq=10 icon=􀉉 script="$PLUGIN_DIR/calendar.sh" 5 | -------------------------------------------------------------------------------- /dot_config/sketchybar/items/executable_volume.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | sketchybar --add item volume right \ 4 | --set volume script="$PLUGIN_DIR/volume.sh" \ 5 | --subscribe volume volume_change 6 | -------------------------------------------------------------------------------- /dot_config/fish/fish_plugins: -------------------------------------------------------------------------------- 1 | jorgebucaran/fisher 2 | edc/bass 3 | danhper/fish-ssh-agent 4 | yujinyuz/tackle 5 | paysonwallach/fish-you-should-use 6 | meaningful-ooo/sponge 7 | catppuccin/fish 8 | wfxr/forgit 9 | jorgebucaran/hydro 10 | -------------------------------------------------------------------------------- /dot_config/nvim/after/plugin/abbreviations.rc.lua: -------------------------------------------------------------------------------- 1 | vim.cmd([[ 2 | cnoreabbrev W w 3 | cnoreabbrev W! w! 4 | cnoreabbrev Q q 5 | cnoreabbrev Q! q! 6 | cnoreabbrev Wq wq 7 | cnoreabbrev wQ wq 8 | cnoreabbrev Set set 9 | ]]) 10 | -------------------------------------------------------------------------------- /dot_config/sketchybar/items/executable_battery.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | sketchybar --add item battery right \ 4 | --set battery update_freq=120 script="$PLUGIN_DIR/battery.sh" \ 5 | --subscribe battery system_woke power_source_change 6 | -------------------------------------------------------------------------------- /dot_config/sketchybar/plugins/executable_calendar.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # The $NAME variable is passed from sketchybar and holds the name of 4 | # the item invoking this script: 5 | # https://felixkratz.github.io/SketchyBar/config/events#events-and-scripting 6 | 7 | sketchybar --set "$NAME" label="$(date '+%a, %b %d %H:%M')" 8 | -------------------------------------------------------------------------------- /dot_config/sketchybar/plugins/executable_media.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | STATE="$(echo "$INFO" | jq -r '.state')" 4 | if [ "$STATE" = "playing" ]; then 5 | MEDIA="$(echo "$INFO" | jq -r '.title + " - " + .artist')" 6 | sketchybar --set $NAME label="$MEDIA" drawing=on 7 | else 8 | sketchybar --set $NAME drawing=off 9 | fi 10 | -------------------------------------------------------------------------------- /dot_config/alacritty/alacritty.toml.tmpl: -------------------------------------------------------------------------------- 1 | import = ["~/.config/alacritty/catppuccin-frappe.toml"] 2 | 3 | [shell] 4 | program = "{{ .shell }}" 5 | args = ["-l"] 6 | 7 | [env] 8 | SHELL = "{{ .shell }}" 9 | 10 | [font] 11 | size = 14.0 12 | 13 | [font.normal] 14 | family = "SauceCodePro Nerd Font Mono" 15 | style = "Regular" 16 | 17 | [window] 18 | decorations = "None" 19 | -------------------------------------------------------------------------------- /dot_config/fzf/config: -------------------------------------------------------------------------------- 1 | --layout="reverse-list" 2 | --height="40%" 3 | --info="inline-right" 4 | --color="bg+:#3b3f53,bg:-1,spinner:#f4b8e5,hl:#f4b8e5,gutter:-1" 5 | --color="fg:#c6d0f6,header:#a5adcf,info:#737995,pointer:#f4b8e5" 6 | --color="marker:#f4b8e5,fg+:#c6d0f5,prompt:#f4b8e5,hl+:#f4b8e5" 7 | --color="query:#c6d0f6:regular,border:#8caaef,scrollbar:#8caaef,separator:#8caaef" 8 | -------------------------------------------------------------------------------- /dot_config/nvim/after/plugin/abolish.rc.lua: -------------------------------------------------------------------------------- 1 | -- Using pcall here since doing a fresh setup, Abolish might not have been installed 2 | -- pcall is basically similar to a try/catch in most programming languages 3 | pcall( 4 | vim.cmd, 5 | [[ 6 | Abolish {despa,sepe}rat{e,es,ed,ing,ely,ion,ions,or} {despe,sepa}rat{} 7 | Abolish {funct}i{no} {funct}i{on} 8 | ]] 9 | ) 10 | -------------------------------------------------------------------------------- /dot_config/fish/conf.d/abbreviations.fish: -------------------------------------------------------------------------------- 1 | ## abbreviations 2 | ## They are removed from the universal variables as of fish 3.6.0 3 | ## therefore, needs to be here so that it gets sourced 4 | abbr -a cp "cp -riv" 5 | abbr -a mv "mv -iv" 6 | abbr -a t tmux 7 | abbr -a l ll 8 | abbr -a v vi 9 | abbr -a vi nvim 10 | abbr -a j just 11 | abbr -a ju just 12 | abbr -a ch chezmoi 13 | abbr -a che chezmoi 14 | abbr -a ghq ghr 15 | -------------------------------------------------------------------------------- /dot_config/nvim/plugin/sync-term-colors.lua: -------------------------------------------------------------------------------- 1 | vim.api.nvim_create_user_command('SyncTermColors', function(opts) 2 | local normal = vim.api.nvim_get_hl(0, { name = 'Normal' }) 3 | if not normal.bg then 4 | return 5 | end 6 | 7 | if vim.env.TMUX then 8 | io.write(string.format('\027Ptmux;\027\027]11;#%06x\007\027\\', normal.bg)) 9 | else 10 | io.write(string.format('\027]11;#%06x\027\\', normal.bg)) 11 | end 12 | end, {}) 13 | -------------------------------------------------------------------------------- /dot_config/sketchybar/items/executable_media.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | sketchybar --add item media e \ 4 | --set media label.max_chars=20 \ 5 | icon.padding_left=0 \ 6 | scroll_texts=on \ 7 | icon=􀑪 \ 8 | background.drawing=off \ 9 | script="$PLUGIN_DIR/media.sh" \ 10 | --subscribe media media_change 11 | -------------------------------------------------------------------------------- /dot_config/nvim/.luacheckrc: -------------------------------------------------------------------------------- 1 | std = luajit 2 | codes = true 3 | 4 | self = false 5 | 6 | -- Glorious list of warnings: https://luacheck.readthedocs.io/en/stable/warnings.html 7 | ignore = { 8 | '212', -- Unused argument, In the case of callback function, _arg_name is easier to understand than _, so this option is set to off. 9 | '122', -- Indirectly setting a readonly global 10 | } 11 | 12 | -- Global objects defined by the C code 13 | read_globals = { 14 | 'vim', 15 | } 16 | -------------------------------------------------------------------------------- /dot_config/fish/conf.d/_brew_env.fish: -------------------------------------------------------------------------------- 1 | # Modified shellenv where we exclude fish_add_path and just manually add it in our config.fish instead 2 | # this is to avoid reording of PATH in fish shell. 3 | # It's not necessary to do this but sometimes when I invoke $SHELL within vim, it causes the $PATH 4 | # to reorder. 5 | if test (uname -m) = arm64 6 | eval (/opt/homebrew/bin/brew shellenv | grep -v fish_add_path) 7 | else 8 | eval (/usr/local/bin/brew shellenv | grep -v fish_add_path) 9 | end 10 | -------------------------------------------------------------------------------- /dot_config/nvim/init.lua: -------------------------------------------------------------------------------- 1 | -- _ _ 2 | -- (_)(_) 3 | -- _ _ _ _ _ _ _ __ _ _ _ _ ____ 4 | -- | | | || | | || || || '_ \ | | | || | | ||_ / 5 | -- | |_| || |_| || || || | | || |_| || |_| | / / 6 | -- \__, | \__,_|| ||_||_| |_| \__, | \__,_|/___| 7 | -- __/ | _/ | __/ | 8 | -- |___/ |__/ |___/ 9 | -- 10 | require('my.options') 11 | require('my.maps') 12 | require('my.plugman') 13 | require('my.nightly') 14 | -------------------------------------------------------------------------------- /dot_config/sketchybar/items/executable_front_app.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | sketchybar --add item front_app left \ 4 | --set front_app background.color=$GREY \ 5 | icon.color=$BAR_COLOR \ 6 | icon.font="sketchybar-app-font:Regular:16.0" \ 7 | label.color=$BAR_COLOR \ 8 | script="$PLUGIN_DIR/front_app.sh" \ 9 | --subscribe front_app front_app_switched 10 | -------------------------------------------------------------------------------- /dot_config/sketchybar/plugins/executable_front_app.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Some events send additional information specific to the event in the $INFO 4 | # variable. E.g. the front_app_switched event sends the name of the newly 5 | # focused application in the $INFO variable: 6 | # https://felixkratz.github.io/SketchyBar/config/events#events-and-scripting 7 | 8 | if [ "$SENDER" = "front_app_switched" ]; then 9 | sketchybar --set "$NAME" label="$INFO" icon="$($CONFIG_DIR/plugins/icon_map_fn.sh "$INFO")" 10 | fi 11 | -------------------------------------------------------------------------------- /.chezmoi.toml.tmpl: -------------------------------------------------------------------------------- 1 | {{ $email := promptString "email" -}} 2 | {{ $name := promptString "name" -}} 3 | {{ $preferredShell := promptString "preferredShell" -}} 4 | {{ $customSourceDir := promptString "customSourceDir" -}} 5 | 6 | sourceDir = {{ $customSourceDir | quote }} 7 | 8 | [data] 9 | email = {{ $email | quote }} 10 | name = {{ $name | quote }} 11 | shell = {{ $preferredShell | quote }} 12 | 13 | [merge] 14 | command = "nvim" 15 | args = ["-d", "{{ `{{ .Destination }}` }}", "{{ `{{ .Source }}` }}", "{{ `{{ .Target }}` }}"] 16 | -------------------------------------------------------------------------------- /dot_config/sketchybar/plugins/executable_volume.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # The volume_change event supplies a $INFO variable in which the current volume 4 | # percentage is passed to the script. 5 | 6 | if [ "$SENDER" = "volume_change" ]; then 7 | VOLUME="$INFO" 8 | 9 | case "$VOLUME" in 10 | [6-9][0-9]|100) ICON="󰕾" 11 | ;; 12 | [3-5][0-9]) ICON="󰖀" 13 | ;; 14 | [1-9]|[1-2][0-9]) ICON="󰕿" 15 | ;; 16 | *) ICON="󰖁" 17 | esac 18 | 19 | sketchybar --set "$NAME" icon="$ICON" label="$VOLUME%" 20 | fi 21 | -------------------------------------------------------------------------------- /dot_config/sketchybar/plugins/executable_cpu.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | CORE_COUNT=$(sysctl -n machdep.cpu.thread_count) 4 | CPU_INFO=$(ps -eo pcpu,user) 5 | CPU_SYS=$(echo "$CPU_INFO" | grep -v $(whoami) | sed "s/[^ 0-9\.]//g" | awk "{sum+=\$1} END {print sum/(100.0 * $CORE_COUNT)}") 6 | CPU_USER=$(echo "$CPU_INFO" | grep $(whoami) | sed "s/[^ 0-9\.]//g" | awk "{sum+=\$1} END {print sum/(100.0 * $CORE_COUNT)}") 7 | 8 | CPU_PERCENT="$(echo "$CPU_SYS $CPU_USER" | awk '{printf "%.0f\n", ($1 + $2)*100}')" 9 | 10 | sketchybar --set $NAME label="$CPU_PERCENT%" 11 | -------------------------------------------------------------------------------- /dot_config/nvim/after/ftplugin/python.lua: -------------------------------------------------------------------------------- 1 | local function copy_as_pytest() 2 | local navic_data = require('nvim-navic').get_data() 3 | 4 | local filepath = vim.fn.expand('%:p:.') 5 | local tbl = {} 6 | 7 | table.insert(tbl, filepath) 8 | for _, data in ipairs(navic_data) do 9 | table.insert(tbl, data.name) 10 | end 11 | 12 | local pytest_test_path = table.concat(tbl, '::') 13 | 14 | vim.fn.setreg('+', pytest_test_path) 15 | return pytest_test_path 16 | end 17 | 18 | -- Override the default keybinding to copy the current location as a pytest 19 | vim.keymap.set('n', '', function() 20 | vim.api.nvim_echo({ { copy_as_pytest(), 'String' } }, true, {}) 21 | end, { buffer = 0 }) 22 | -------------------------------------------------------------------------------- /dot_local/bin/executable_tat: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Attach or create tmux session named the same as current directory. 4 | 5 | path_name="$(basename "$PWD" | tr . -)" 6 | session_name=${1-$path_name} 7 | 8 | not_in_tmux() { 9 | [ -z "$TMUX" ] 10 | } 11 | 12 | session_exists() { 13 | tmux has-session -t "=$session_name" &>/dev/null 14 | } 15 | 16 | create_detached_session() { 17 | (TMUX='' tmux new-session -Ad -s "$session_name") 18 | } 19 | 20 | create_if_needed_and_attach() { 21 | if not_in_tmux; then 22 | tmux new-session -As "$session_name" 23 | else 24 | if ! session_exists; then 25 | create_detached_session 26 | fi 27 | tmux switch-client -t "$session_name" 28 | fi 29 | } 30 | 31 | create_if_needed_and_attach 32 | # vim:filetype=sh 33 | -------------------------------------------------------------------------------- /dot_config/ctags/config.ctags: -------------------------------------------------------------------------------- 1 | # GENERAL 2 | --exclude=.git 3 | --exclude=.DS_Store 4 | --exclude=*.jpg 5 | --exclude=*.png 6 | --exclude=*.gif 7 | --exclude=*.svg 8 | --exclude=*.ico 9 | --exclude=*.mp3 10 | --exclude=*.mp4 11 | --exclude=*.yaml 12 | 13 | # JAVASCRIPT 14 | --exclude=node_modules 15 | --exclude=package-lock.json 16 | --exclude=dist 17 | --exclude=docs 18 | --exclude=__snapshots__ 19 | --exclude=.next 20 | --exclude=*.min.js 21 | 22 | # CSS 23 | --exclude=*.css 24 | 25 | # Markdown 26 | --exclude=*.md 27 | --exclude=*/migrations/*auto*.py 28 | 29 | --exclude=*.csv 30 | --exclude=*.csv.org 31 | --exclude=*.csv*.* 32 | --exclude=*.json 33 | --exclude=*.log 34 | --exclude=*.log* 35 | --exclude=*.html 36 | --exclude=*.conf 37 | --exclude=*.ini 38 | --exclude=*.diff 39 | 40 | 41 | # Python 42 | --exclude=.tox 43 | -------------------------------------------------------------------------------- /dot_config/sketchybar/plugins/executable_space.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # The $SELECTED variable is available for space components and indicates if 4 | # the space invoking this script (with name: $NAME) is currently selected: 5 | # https://felixkratz.github.io/SketchyBar/config/components#space----associate-mission-control-spaces-with-an-item 6 | 7 | source "$CONFIG_DIR/colors.sh" # Loads all defined colors 8 | 9 | if [ $SELECTED = true ]; then 10 | sketchybar --set $NAME background.drawing=on \ 11 | background.color=$GREY \ 12 | label.color=$LABEL_COLOR \ 13 | icon.color=$BAR_COLOR 14 | else 15 | sketchybar --set $NAME background.drawing=off \ 16 | label.color=$LABEL_COLOR \ 17 | icon.color=$ICON_COLOR 18 | fi 19 | -------------------------------------------------------------------------------- /dot_config/sketchybar/plugins/executable_battery.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | PERCENTAGE="$(pmset -g batt | grep -Eo "\d+%" | cut -d% -f1)" 4 | CHARGING="$(pmset -g batt | grep 'AC Power')" 5 | 6 | source "$CONFIG_DIR/colors.sh" 7 | 8 | if [ "$PERCENTAGE" = "" ]; then 9 | exit 0 10 | fi 11 | 12 | case "${PERCENTAGE}" in 13 | 9[0-9]|100) ICON="􀛨" COLOR="$WHITE" 14 | ;; 15 | [6-8][0-9]) ICON="􀺸" COLOR="$WHITE" 16 | ;; 17 | [3-5][0-9]) ICON="􀺶" COLOR="$WHITE" 18 | ;; 19 | [1-2][0-9]) ICON="􀛩" COLOR="$RED" 20 | ;; 21 | *) ICON="􀛪" COLOR="$RED" 22 | esac 23 | 24 | if [[ "$CHARGING" != "" ]]; then 25 | ICON="􀢋" COLOR="$WHITE" 26 | fi 27 | 28 | # The item invoking this script (name $NAME) will get its icon and label 29 | # updated with the current battery status 30 | sketchybar --set "$NAME" icon="$ICON" icon.color="$COLOR" label="${PERCENTAGE}%" 31 | -------------------------------------------------------------------------------- /dot_config/sketchybar/executable_colors.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ### Catppuccin Frappe ### 4 | export BLACK=0xff181926 # #181926 5 | export WHITE=0xffcad3f5 # #cad3f5 6 | export RED=0xffed8796 # #ed8796 7 | export GREEN=0xffa6da95 # #a6da95 8 | export BLUE=0xff8aadf4 # #8aadf4 9 | export YELLOW=0xffeed49f # #eed49f 10 | export ORANGE=0xfff5a97f # #f5a97f 11 | export MAGENTA=0xffc6a0f6 # #c6a0f6 12 | export GREY=0xff939ab7 # #939ab7 13 | export TRANSPARENT=0x00000000 14 | export BG0=0xff1e1e2e # #1e1e2e 15 | export BG1=0x603c3e4f # #3c3e4f 16 | export BG2=0x60494d64 # #494d64 17 | 18 | # General bar colors 19 | export BAR_COLOR=$BG0 20 | export BAR_BORDER_COLOR=$BG2 21 | export BACKGROUND_1=$BG1 22 | export BACKGROUND_2=$BG2 23 | export ICON_COLOR=$WHITE # Color of all icons 24 | export LABEL_COLOR=$WHITE # Color of all labels 25 | export POPUP_BACKGROUND_COLOR=$BAR_COLOR 26 | export POPUP_BORDER_COLOR=$WHITE 27 | export SHADOW_COLOR=$BLACK 28 | -------------------------------------------------------------------------------- /dot_config/nvim/lua/my/plugman.lua: -------------------------------------------------------------------------------- 1 | local lazypath = vim.fn.stdpath('data') .. '/lazy/lazy.nvim' 2 | 3 | if not vim.uv.fs_stat(lazypath) then 4 | print('Downloading lazy.nvim...') 5 | vim.fn.system { 6 | 'git', 7 | 'clone', 8 | '--filter=blob:none', 9 | 'https://github.com/folke/lazy.nvim.git', 10 | '--branch=stable', -- latest stable release 11 | lazypath, 12 | } 13 | end 14 | 15 | vim.opt.rtp:prepend(lazypath) 16 | 17 | require('lazy').setup { 18 | spec = { 19 | { import = 'my.plugins' }, 20 | }, 21 | change_detection = { 22 | notify = false, 23 | }, 24 | install = { colorscheme = { 'catppuccin', 'habamax' } }, 25 | performance = { 26 | rtp = { 27 | disabled_plugins = { 28 | 'gzip', 29 | 'matchit', 30 | 'matchparen', 31 | 'netrwPlugin', 32 | 'tarPlugin', 33 | 'tohtml', 34 | 'zipPlugin', 35 | }, 36 | }, 37 | }, 38 | dev = { 39 | path = '~/Sources/github.com/yujinyuz', 40 | }, 41 | } 42 | -------------------------------------------------------------------------------- /dot_config/nvim/lua/my/plugins/filetypes.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | 'SidOfc/mkdx', 4 | ft = 'markdown', 5 | init = function() 6 | local settings = { 7 | -- Use GitHub supported toggles 8 | checkbox = { 9 | toggles = { ' ', 'x' }, 10 | }, 11 | enter = { 12 | shift = 1, 13 | }, 14 | } 15 | vim.g['mkdx#settings'] = settings 16 | end, 17 | }, 18 | { 19 | 'iamcco/markdown-preview.nvim', 20 | build = 'cd app && yarn install', 21 | ft = 'markdown', 22 | }, 23 | { 'Vimjas/vim-python-pep8-indent', ft = 'python', enabled = false }, 24 | { 'drmingdrmer/vim-indent-lua', ft = 'lua' }, 25 | { 'michaeljsmith/vim-indent-object', ft = 'python' }, 26 | { 'martinda/Jenkinsfile-vim-syntax', ft = { 'groovy', 'Jenkinsfile' } }, 27 | { 'thecodesmith/vim-groovy', ft = 'groovy' }, 28 | { 'fladson/vim-kitty', ft = 'kitty' }, 29 | { 'NoahTheDuke/vim-just', ft = 'just' }, 30 | { 'cuducos/yaml.nvim', ft = { 'yaml' } }, 31 | { 'HiPhish/jinja.vim', ft = { 'jinja' } }, 32 | } 33 | -------------------------------------------------------------------------------- /dot_config/nvim/after/ftplugin/markdown.lua: -------------------------------------------------------------------------------- 1 | vim.opt_local.spell = true 2 | vim.opt_local.conceallevel = 0 3 | vim.opt_local.concealcursor = 'n' 4 | vim.opt_local.shiftwidth = 2 5 | vim.opt_local.textwidth = 100 6 | vim.opt_local.formatprg = 'safe-par rTbqR B=.,\\?_A_a_0 Q=_s\\>\\| -w' .. vim.bo.textwidth 7 | vim.opt_local.colorcolumn = { vim.bo.textwidth } 8 | 9 | vim.keymap.set('i', ';H', 'yypv$r=', { buffer = 0 }) 10 | vim.keymap.set('i', ';h', 'yypv$r-', { buffer = 0 }) 11 | 12 | vim.keymap.set('i', ';d', function() 13 | return vim.fn.strftime('## %A, %B %d, %Y\n\n\n') 14 | end, { buffer = 0, expr = true }) 15 | 16 | vim.keymap.set('i', ';D', function() 17 | return vim.fn.strftime('### %Y-%m-%d\n\n\n') 18 | end, { buffer = 0, expr = true }) 19 | 20 | vim.keymap.set('i', ';t', function() 21 | return vim.fn.strftime('### %H:%M\n\n\n') 22 | end, { buffer = 0, expr = true }) 23 | 24 | vim.keymap.set('n', 'pm', 'MarkdownPreviewToggle', { buffer = 0 }) 25 | 26 | vim.keymap.set('i', ';e', '', { nowait = true }) 27 | vim.keymap.set('i', ';p', '', { nowait = true }) 28 | -------------------------------------------------------------------------------- /dot_config/nvim/plugin/bufonly.lua: -------------------------------------------------------------------------------- 1 | local g = vim.g 2 | local api = vim.api 3 | local option = api.nvim_buf_get_option 4 | 5 | local M = {} 6 | 7 | function M.BufOnly() 8 | local del_non_modifiable = g.bufonly_delete_non_modifiable or false 9 | 10 | local cur = api.nvim_get_current_buf() 11 | 12 | local deleted, modified = 0, 0 13 | 14 | for _, n in ipairs(api.nvim_list_bufs()) do 15 | -- If the iter buffer is modified one, then don't do anything 16 | if option(n, 'modified') then 17 | -- iter is not equal to current buffer 18 | -- iter is modifiable or del_non_modifiable == true 19 | -- `modifiable` check is needed as it will prevent closing file tree ie. NERD_tree 20 | modified = modified + 1 21 | elseif n ~= cur and (option(n, 'modifiable') or del_non_modifiable) then 22 | api.nvim_buf_delete(n, {}) 23 | deleted = deleted + 1 24 | end 25 | end 26 | 27 | print('BufOnly: ' .. deleted .. ' deleted buffer(s), ' .. modified .. ' modified buffer(s)') 28 | end 29 | 30 | vim.api.nvim_create_user_command('BufOnly', function() 31 | M.BufOnly() 32 | end, {}) 33 | 34 | vim.keymap.set('n', ';', 'BufOnly', {}) 35 | 36 | return M 37 | -------------------------------------------------------------------------------- /dot_config/git/message: -------------------------------------------------------------------------------- 1 | 2 | 3 | # feat: A new feature 4 | # fix: A bug fix 5 | # docs: Documentation only changes 6 | # chore: Changes to the build process or auxiliary tools 7 | # and libraries such as documentation generation. 8 | # style: Changes that do not affect the meaning of the code 9 | # (white-space, formatting, missing semi-colons, etc.) 10 | # refactor: A code change that neither fixes a bug or adds a feature 11 | # perf: A code change that improves performance 12 | # test: Adding missing tests 13 | # add ! to the type to indicate breaking changes. E.g. fix! or feat! 14 | 15 | 16 | 17 | # Whatever you place as a commit message, always 18 | # Read it as: If applied, this commit will . 19 | # [Add/Fix/Remove/Update/Refactor/Document] [issue #id] [summary] 20 | 21 | # Why is it necessary? (Bug fix, feature, improvements?) 22 | # - 23 | # How does it address the problem? 24 | # - 25 | # What side effects does this change have? 26 | # - 27 | # Include a link to the ticket, if any. 28 | # 29 | # Add co-authors if you worked on this code with others: 30 | # 31 | # Co-authored-by: Full Name 32 | # Co-authored-by: Full Name 33 | -------------------------------------------------------------------------------- /dot_config/git/globalignore: -------------------------------------------------------------------------------- 1 | # ctags 2 | tags 3 | tags.lock 4 | tags.temp 5 | 6 | # ignore tags but do not ignore directories named tags 7 | !tags/ 8 | # ruby stuffs 9 | .gems 10 | .rbenv-gemsets 11 | .ruby-version 12 | 13 | # python stuffs 14 | .python-version 15 | *.py[co] 16 | __pycache__/ 17 | .venv 18 | pyrightconfig.json 19 | htmlcov 20 | 21 | # .vscode stuffs 22 | .vscode/ 23 | 24 | # vim stuffs 25 | Session.vim 26 | .projections.json 27 | 28 | # node 29 | npm-debug.log* 30 | yarn-debug.log* 31 | yarn-error.log* 32 | node_modules 33 | .nvmrc 34 | 35 | # git bare 36 | .dotlocal 37 | 38 | # asdf 39 | .tool-versions 40 | .envrc 41 | 42 | # general 43 | tmp/ 44 | temp/ 45 | .DS_Store 46 | logs/* 47 | *.log 48 | tmp*/ 49 | 50 | 51 | # custom docker data folder 52 | dkdata 53 | 54 | # Added to every root of a project manually 55 | # sole purpose is for vim-gutentags to work properly 56 | # especially for projects that don't have a clear root directory 57 | .croot 58 | 59 | # Used for my custom fish function that automatically sources this file 60 | # whenever a virtualenv is activated 61 | exports.fish 62 | 63 | .disable-autofmt 64 | 65 | # neovim 66 | .nvim.lua 67 | 68 | # virtualfish 69 | .vfenv 70 | -------------------------------------------------------------------------------- /dot_config/nvim/plugin/live-server.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | -- Thin wrapper around the live-server npm plugin 4 | 5 | M.config = { 6 | port = '5555', 7 | } 8 | 9 | M.start = function() 10 | -- NOTE: uv.spawn or vim.system does not automatically close child processes when nvim closes 11 | -- so let's stick with the vim.fn.jobstart 12 | 13 | if not vim.fn.executable('live-server') then 14 | vim.notify('live-server is not installed. Please run npm -g install live-server', vim.log.levels.ERROR) 15 | return 16 | end 17 | 18 | M.pid = vim.fn.jobstart({ 'live-server', string.format('--port=%s', M.config.port) }, { 19 | on_exit = function() 20 | M.pid = nil 21 | end, 22 | }) 23 | end 24 | 25 | M.stop = function() 26 | if not M.pid then 27 | return 28 | end 29 | vim.fn.jobstop(M.pid) 30 | end 31 | 32 | M.preview = function() 33 | if not M.pid then 34 | M.start() 35 | end 36 | 37 | vim.ui.open(string.format('http://127.0.0.1:%s', M.config.port)) 38 | end 39 | 40 | vim.api.nvim_create_user_command('LiveServer', function(opts) 41 | if opts.args == 'stop' then 42 | M.stop() 43 | else 44 | M.preview() 45 | end 46 | end, { 47 | nargs = '?', 48 | complete = function(args) 49 | print(args) 50 | return { 'start', 'stop', 'preview' } 51 | end, 52 | }) 53 | -------------------------------------------------------------------------------- /dot_config/nvim/lua/my/format.lua: -------------------------------------------------------------------------------- 1 | local utils = require('my.utils') 2 | 3 | local M = {} 4 | 5 | M._enabled = true 6 | 7 | function M.is_enabled(bufnr) 8 | -- If the file is not in the ~/Sources directory, do not autoformat. 9 | -- If there is a .disable-autoformat file in the root of the project, do not autoformat. 10 | -- Otherwise, return the value of M._enabled 11 | 12 | bufnr = bufnr or vim.api.nvim_get_current_buf() 13 | local bufname = vim.api.nvim_buf_get_name(bufnr) 14 | 15 | -- Only perform autoformat it the file is in the ~/Sources directory 16 | if not bufname:match('/Sources/') then 17 | return false 18 | end 19 | 20 | -- Check if there is a .disable-autoformat file in the root of the project 21 | local disable_autoformat = 22 | not vim.tbl_isempty(vim.fs.find('.disable-autofmt', { upward = true, path = vim.fs.dirname(bufname) })) 23 | 24 | if disable_autoformat then 25 | return false 26 | end 27 | 28 | return M._enabled 29 | end 30 | 31 | function M.format() 32 | -- This will format the code even when not enabled 33 | require('conform').format { async = true, lsp_format = 'fallback' } 34 | end 35 | 36 | function M.toggle() 37 | M._enabled = not M._enabled 38 | if M._enabled then 39 | utils.info('enabled format on save', 'Toggle') 40 | else 41 | utils.warn('disabled format on save', 'Toggle') 42 | end 43 | end 44 | 45 | return M 46 | -------------------------------------------------------------------------------- /dot_config/nvim/after/plugin/usercommands.rc.lua: -------------------------------------------------------------------------------- 1 | -- Turn off relative numbers and a bunch of stuffs when collaborating 2 | vim.api.nvim_create_user_command('MuggleFriendlyModeToggle', function() 3 | vim.g.muggle_friendly_mode = not vim.g.muggle_friendly_mode 4 | 5 | if vim.g.muggle_friendly_mode then 6 | -- Muggles don't understand relative numbers 7 | vim.opt.relativenumber = false 8 | else 9 | vim.opt.relativenumber = true 10 | end 11 | end, {}) 12 | 13 | vim.api.nvim_create_user_command('CursorMiddleToggle', function() 14 | vim.opt.scrolloff = 999 - vim.o.scrolloff 15 | end, { desc = 'Always keep the cursor in the middle of the screen' }) 16 | 17 | vim.api.nvim_create_user_command('FormatJson', function(opts) 18 | local indent = tonumber(opts.args) or 2 19 | local start_line, end_line 20 | 21 | if opts.range == 0 then 22 | start_line, end_line = 1, vim.fn.line('$') 23 | else 24 | start_line, end_line = opts.line1, opts.line2 25 | end 26 | 27 | vim.cmd(start_line .. ',' .. end_line .. '!jq . --indent ' .. indent) 28 | end, { nargs = '?', range = true }) 29 | 30 | -- TODO: Add a parameter to existing FormatJson instead of having a separate command 31 | vim.api.nvim_create_user_command('FormatJsonSorted', function(opts) 32 | local indent = tonumber(opts.args) or 2 33 | local start_line, end_line 34 | 35 | if opts.range == 0 then 36 | start_line, end_line = 1, vim.fn.line('$') 37 | else 38 | start_line, end_line = opts.line1, opts.line2 39 | end 40 | 41 | vim.cmd(start_line .. ',' .. end_line .. '!jq . --indent ' .. indent .. ' --sort-keys') 42 | end, { nargs = '?', range = true }) 43 | 44 | vim.api.nvim_create_user_command('DiffOrig', function() 45 | local ft = vim.bo.filetype 46 | vim.cmd('leftabove vert new') 47 | vim.cmd('set ft=' .. ft) 48 | vim.cmd('set buftype=nofile | read ++edit # | 0d_ | diffthis | wincmd p | diffthis') 49 | end, { desc = 'Diff Orig file' }) 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # dotfiles 2 | My collection of dotfiles 3 | 4 | Days since last changed: `0` 5 | 6 | 7 | ## Setup 8 | 9 | 10 | Currently playing around with `chezmoi`. 11 | WIP. 12 | 13 | ```shell 14 | export GITHUB_USERNAME="" 15 | sh -c "$(curl -fsLS get.chezmoi.io)" -- init --apply $GITHUB_USERNAME 16 | 17 | # OR 18 | 19 | sh -c "$(curl -fsLS get.chezmoi.io)" -- init --apply username/dotfiles-x 20 | 21 | ``` 22 | 23 | Current tide config 24 | 25 | To see this, you need to go through `tide configure` and then choose `(p) Exit and print the config you just generated` 26 | 27 | 28 | Verbose 29 | ```fish 30 | tide configure --auto --style=Lean --prompt_colors='True color' --show_time='24-hour format' --lean_prompt_height='Two lines' --prompt_connection=Disconnected --prompt_spacing=Compact --icons='Many icons' --transient=No 31 | ``` 32 | 33 | Simple One Line no icons 34 | ```fish 35 | tide configure --auto --style=Lean --prompt_colors='True color' --show_time='24-hour format' --lean_prompt_height='One line' --prompt_spacing=Compact --icons='Few icons' --transient=No 36 | set -U tide_prompt_min_cols 512 # Always truncate path 37 | set --prepend tide_right_prompt_items shlvl 38 | 39 | _tide_find_and_remove os $tide_left_prompt_items 40 | set -U tide_git_icon 41 | ``` 42 | 43 | 44 | 45 | ``` 46 | ❯ echo $tide_right_prompt_items 47 | status cmd_duration context jobs direnv bun node python rustc java php pulumi ruby go gcloud kubectl distrobox toolbox terraform aws nix_shell crystal elixir zig time 48 | 49 | ❯ echo $tide_left_prompt_items 50 | pwd git character 51 | ``` 52 | 53 | 54 | ### hydro 55 | set -Ux hydro_color_pwd 00AFFF 56 | set -Ux hydro_color_git 5FD700 57 | set -Ux hydro_color_prompt --dim 5FD700 58 | set -Ux hydro_color_duration --dim $fish_color_normal 59 | set -Ux hydro_symbol_prompt ❯ 60 | 61 | 62 | 63 | 64 | set -Ux DOCKER_HOST unix:///Users/$USER/Library/Containers/com.docker.docker/Data/docker.raw.sock 65 | -------------------------------------------------------------------------------- /dot_config/nvim/lua/my/plugins/misc.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | 'tpope/vim-scriptease', 4 | cmd = { 'Scriptnames', 'Messages', 'Verbose' }, 5 | keys = { 'zS' }, 6 | }, 7 | { 8 | 'wakatime/vim-wakatime', 9 | event = 'BufReadPost', 10 | }, 11 | { 12 | 'letieu/hacker.nvim', 13 | dev = true, 14 | keys = { 15 | { 'ha', ':autocmd!HackFollow', silent = true }, 16 | }, 17 | }, 18 | { 19 | 'eandrju/cellular-automaton.nvim', 20 | keys = { 21 | { 'fml', 'CellularAutomaton make_it_rain', desc = 'Make it rain' }, 22 | }, 23 | }, 24 | { 25 | 'mistweaverco/kulala.nvim', 26 | ft = 'http', 27 | opts = function() 28 | return { 29 | default_view = 'headers_body', 30 | winbar = true, 31 | contenttypes = { 32 | ['text/plain'] = { 33 | formatter = function(body) 34 | return body 35 | end, 36 | }, 37 | ['application/json'] = { 38 | ft = 'json', 39 | formatter = { 'jq', '.' }, 40 | pathresolver = require('kulala.parser.jsonpath').parse, 41 | }, 42 | ['application/vnd.api+json'] = { 43 | ft = 'json', 44 | formatter = { 'jq', '.' }, 45 | pathresolver = require('kulala.parser.jsonpath').parse, 46 | }, 47 | }, 48 | } 49 | end, 50 | keys = { 51 | { 52 | '', 53 | function() 54 | require('kulala').run() 55 | end, 56 | ft = 'http', 57 | }, 58 | { 59 | 'r', 60 | function() 61 | require('kulala').run() 62 | end, 63 | ft = 'http', 64 | }, 65 | { 66 | 'v', 67 | function() 68 | require('kulala').toggle_view() 69 | end, 70 | ft = 'http', 71 | }, 72 | }, 73 | }, 74 | } 75 | -------------------------------------------------------------------------------- /dot_config/yabai/yabairc: -------------------------------------------------------------------------------- 1 | yabai -m config layout bsp 2 | yabai -m config window_placement second_child 3 | 4 | # padding 5 | yabai -m config top_padding 12 6 | yabai -m config bottom_padding 12 7 | yabai -m config left_padding 12 8 | yabai -m config right_padding 12 9 | yabai -m config window_gap 10 10 | 11 | # yabai -m config focus_follows_mouse autoraise 12 | yabai -m config mouse_follows_focus off 13 | yabai -m config mouse_modifier alt 14 | yabai -m config mouse_action1 move 15 | yabai -m config mouse_action2 resize 16 | # yabai -m mouse_drop_action swap 17 | 18 | yabai -m config external_bar all:35:0 19 | 20 | # Custom rules 21 | yabai -m rule --add app="^System Settings$" manage=off 22 | yabai -m rule --add app="^Ice$" manage=off 23 | yabai -m rule --add app="^OBS$" manage=off 24 | yabai -m rule --add app="^Raycast*" manage=off 25 | yabai -m rule --add app="^Docker*" manage=off 26 | yabai -m rule --add app="^IINA$" manage=off 27 | yabai -m rule --add app="^Calculator$" manage=off 28 | yabai -m rule --add app="^Karabiner-Elements$" manage=off 29 | yabai -m rule --add app="^Sync$" manage=off 30 | yabai -m rule --add app="^Finder$" manage=off 31 | yabai -m rule --add label="Activity Monitor" app="^Activity Monitor$" manage=off 32 | yabai -m rule --add label="App Store" app="^App Store$" manage=off 33 | yabai -m rule --add label="mpv" app="^mpv$" manage=off 34 | yabai -m rule --add label="Software Update" title="Software Update" manage=off 35 | yabai -m rule --add label="About This Mac" app="System Information" title="About This Mac" manage=off 36 | yabai -m rule --apply 37 | 38 | borders active_color=0xffc6d0f5 inactive_color=0x00000000 width=3.0 style=round blacklist="OBS,OBS Studio,Remux Recordings" & 39 | 40 | # Requires SIP to be disabled.. so I'll prefer not using it in the mean time 41 | # yabai -m signal --add event=dock_did_restart action="sudo yabai --load-sa" 42 | # sudo yabai --load-sa 43 | 44 | echo "yabai config applied!" 45 | 46 | # vim: ft=bash 47 | -------------------------------------------------------------------------------- /dot_config/sketchybar/items/executable_spaces.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | SPACE_SIDS=(1 2 3 4 5 6 7 8 9 10) 4 | 5 | 6 | for sid in "${SPACE_SIDS[@]}"; do 7 | sketchybar --add space space.$sid left \ 8 | --set space.$sid space=$sid \ 9 | icon=$sid \ 10 | label.font="sketchybar-app-font:Regular:16.0" \ 11 | label.y_offset=-1 \ 12 | label.padding_left=1 \ 13 | label.padding_right=1 \ 14 | script="$PLUGIN_DIR/space.sh" 15 | done 16 | 17 | 18 | # This is another variant of the above configuration but includes active icons of apps in the spaces. 19 | # for sid in "${SPACE_SIDS[@]}"; do 20 | # sketchybar --add space space.$sid left \ 21 | # --set space.$sid space=$sid \ 22 | # icon=$sid \ 23 | # label.font="sketchybar-app-font:Regular:16.0" \ 24 | # label.padding_right=20 \ 25 | # label.y_offset=-1 \ 26 | # script="$PLUGIN_DIR/space.sh" 27 | # done 28 | 29 | # sketchybar --add item space_separator left \ 30 | # --set space_separator icon="􀆊" \ 31 | # icon.padding_left=4 \ 32 | # label.drawing=off \ 33 | # background.drawing=off \ 34 | # script="$PLUGIN_DIR/space_windows.sh" \ 35 | # --subscribe space_separator space_windows_change 36 | # 37 | # 38 | -------------------------------------------------------------------------------- /dot_config/nvim/lua/my/plugins/navigation.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | 'tpope/vim-eunuch', 4 | cmd = { 'Delete', 'Move', 'Rename' }, 5 | }, 6 | { 7 | 'ludovicchabant/vim-gutentags', 8 | event = 'VeryLazy', 9 | init = function() 10 | vim.g.gutentags_project_root = { '.croot' } 11 | vim.g.gutentags_define_advanced_commands = true 12 | vim.g.gutentags_add_default_project_roots = false 13 | end, 14 | }, 15 | { 16 | 'yujinyuz/mini.files', 17 | dev = true, 18 | version = false, 19 | init = function() 20 | vim.g.mini_files_auto_confirm_on_simple_edits = true 21 | end, 22 | opts = { 23 | options = { 24 | use_as_default_explorer = false, 25 | }, 26 | mappings = { 27 | go_in_plus = '', 28 | }, 29 | }, 30 | keys = { 31 | { 32 | ',t', 33 | function() 34 | local mf = require('mini.files') 35 | if not mf.close() then 36 | mf.open(vim.api.nvim_buf_get_name(0)) 37 | mf.reveal_cwd() 38 | end 39 | end, 40 | }, 41 | }, 42 | }, 43 | { 44 | 'stevearc/oil.nvim', 45 | event = 'VeryLazy', 46 | opts = { 47 | columns = { 'icon' }, 48 | view_options = { 49 | show_hidden = false, 50 | }, 51 | win_options = { 52 | wrap = false, 53 | signcolumn = 'no', 54 | cursorcolumn = false, 55 | foldcolumn = '0', 56 | spell = false, 57 | list = false, 58 | conceallevel = 3, 59 | concealcursor = 'nvic', 60 | }, 61 | keymaps = { 62 | [''] = false, 63 | ['q'] = 'actions.close', 64 | [''] = false, 65 | [''] = 'actions.refresh', 66 | ['y.'] = 'actions.copy_entry_path', 67 | }, 68 | skip_confirm_for_simple_edits = true, 69 | }, 70 | }, 71 | { 72 | 'stevearc/aerial.nvim', 73 | opts = {}, 74 | cmd = { 'AerialToggle' }, 75 | keys = { 76 | { '\\t', 'AerialToggle', desc = 'Toggle Tags' }, 77 | }, 78 | }, 79 | { 80 | 'otavioschwanck/arrow.nvim', 81 | keys = { 82 | { ',a', desc = '[a]rrow' }, 83 | }, 84 | opts = { 85 | show_icons = true, 86 | leader_key = ',a', 87 | separate_by_branch = true, 88 | }, 89 | }, 90 | { 91 | 'pechorin/any-jump.vim', 92 | keys = { 93 | { 'j', 'AnyJump', mode = { 'n', 'v' } }, 94 | { 'Any', mode = 'c' }, 95 | }, 96 | }, 97 | } 98 | -------------------------------------------------------------------------------- /dot_config/kitty/macos.conf: -------------------------------------------------------------------------------- 1 | # vim:fileencoding=utf-8:ft=kitty:foldmethod=marker 2 | 3 | #: Fonts {{{ 4 | font_family SauceCodePro Nerd Font Mono 5 | font_size 14 6 | disable_ligatures cursor 7 | #: }}} 8 | 9 | #: Cursor customization {{{ 10 | cursor_blink_interval 0 11 | #: }}} 12 | 13 | #: Mouse {{{ 14 | url_prefixes http https file ftp 15 | copy_on_select yes 16 | #: }}} 17 | 18 | #: Performance tuning {{{ 19 | repaint_delay 2 20 | input_delay 0 21 | sync_to_monitor no 22 | wayland_enable_ime no 23 | #: }}} 24 | 25 | #: Terminal bell {{{ 26 | enable_audio_bell no 27 | #: }}} 28 | 29 | #: Window layout {{{ 30 | remember_window_size yes 31 | initial_window_width 80c 32 | initial_window_height 25c 33 | 34 | enabled_layouts Splits,Stack 35 | 36 | hide_window_decorations titlebar-only 37 | placement_strategy center 38 | window_margin_width 2.5 39 | resize_debounce_time 0.1 40 | confirm_os_window_close 1 41 | #: }}} 42 | 43 | #: Tab bar {{{ 44 | tab_bar_style powerline 45 | tab_separator " " 46 | tab_title_template "{title}" 47 | #: }}} 48 | 49 | #: Color scheme {{{ 50 | background_opacity 0.98 51 | dynamic_background_opacity yes 52 | dim_opacity 0.4 53 | #: }}} 54 | 55 | #: Advanced {{{ 56 | allow_remote_control socket-only 57 | listen_on unix:/tmp/kitty 58 | update_check_interval 0 59 | clipboard_control write-clipboard write-primary 60 | shell_integration no-cursor 61 | #: }}} 62 | 63 | #: OS specific tweaks {{{ 64 | macos_option_as_alt yes 65 | macos_traditional_fullscreen no 66 | macos_show_window_title_in none 67 | #: }}} 68 | 69 | #: Keyboard shortcuts {{{ 70 | kitty_mod ctrl+shift 71 | map kitty_mod+m toggle_layout stack 72 | map cmd+enter launch --location=hsplit --cwd=current 73 | map cmd+\ launch --location=split --cwd=current 74 | # : }}} 75 | 76 | #: Clipboard {{{ 77 | #: 78 | #: }}} 79 | 80 | #: Scrolling {{{ 81 | #: 82 | #: }}} 83 | 84 | #: Window management {{{ 85 | map kitty_mod+] next_window 86 | map kitty_mod+[ previous_window 87 | #: }}} 88 | 89 | #: Tab management {{{ 90 | #: 91 | #: }}} 92 | 93 | #: Layout management {{{ 94 | map kitty_mod+l next_layout 95 | #: }}} 96 | 97 | #: Font sizes {{{ 98 | #: 99 | #: }}} 100 | 101 | #: Select and act on visible text {{{ 102 | #: 103 | #: }}} 104 | 105 | #: Miscellaneous {{{ 106 | map alt+9 set_background_opacity +0.01 107 | map alt+0 set_background_opacity -0.01 108 | map alt+1 set_background_opacity 1 109 | map kitty_mod+a>d set_background_opacity default 110 | #: }}} 111 | -------------------------------------------------------------------------------- /dot_config/nvim/after/plugin/overrides/unimpaired.rc.lua: -------------------------------------------------------------------------------- 1 | local utils = require('my.utils') 2 | 3 | vim.keymap.set('n', 'yob', function() 4 | local _, gs = pcall(require, 'gitsigns') 5 | 6 | if not gs then 7 | utils.warn('gitsigns.nvim is not installed', '[unimpaired-overrides]') 8 | return 9 | end 10 | 11 | vim.b.gitsigns_t_state = not vim.b.gitsigns_t_state 12 | 13 | if vim.b.gitsigns_t_state then 14 | utils.info('enabled gitsigns', 'Toggle') 15 | else 16 | utils.warn('disabled gitsigns', 'Toggle') 17 | end 18 | 19 | gs.toggle_current_line_blame() 20 | gs.toggle_signs() 21 | gs.toggle_linehl() 22 | gs.toggle_word_diff() 23 | end, { desc = 'Toggle Gitsigns' }) 24 | 25 | vim.keymap.set('n', 'yof', function() 26 | require('my.format').toggle() 27 | end, { desc = 'Format on Save' }) 28 | 29 | vim.keymap.set('n', 'yol', function() 30 | utils.toggle_opt('list') 31 | end, {}) 32 | 33 | vim.keymap.set('n', 'yoL', function() 34 | vim.g.miniindentscope_disable = not vim.g.miniindentscope_disable 35 | 36 | if vim.g.miniindentscope_disable then 37 | utils.warn('disabled mini.indentscope', 'Toggle') 38 | else 39 | utils.info('enabled mini.indentscope', 'Toggle') 40 | end 41 | end) 42 | 43 | vim.keymap.set('n', 'yor', function() 44 | utils.toggle_opt('relativenumber') 45 | end) 46 | 47 | vim.keymap.set('n', 'yon', function() 48 | utils.toggle_opt('number') 49 | end) 50 | 51 | vim.keymap.set('n', 'yos', function() 52 | utils.toggle_opt('spell') 53 | end) 54 | vim.keymap.set('n', 'yow', function() 55 | utils.toggle_opt('wrap') 56 | end) 57 | 58 | vim.keymap.set('n', 'yom', function() 59 | vim.cmd('MuggleFriendlyModeToggle') 60 | if vim.g.muggle_friendly_mode then 61 | utils.info('enabled muggle friendly mode', 'Toggle') 62 | else 63 | utils.warn('disabled muggle friendly mode', 'Toggle') 64 | end 65 | end, { desc = 'toggle muggle friendly mode' }) 66 | 67 | vim.keymap.set('n', 'yoC', function() 68 | vim.b.colorcolumn_t_state = not vim.b.colorcolumn_t_state 69 | 70 | -- Check if colorcolumn_opt is set or use default value 71 | vim.b.colorcolumn_opt = vim.b.colorcolumn_opt or { 100 } 72 | 73 | if vim.b.colorcolumn_t_state then 74 | vim.opt_local.colorcolumn = vim.b.colorcolumn_opt 75 | utils.info('enabled cursorcolumn', 'Toggle') 76 | else 77 | vim.opt_local.colorcolumn = {} 78 | utils.warn('enabled cursorcolumn', 'Toggle') 79 | end 80 | end) 81 | 82 | vim.keymap.set('n', 'yoT', 'CatppuccinToggleTransparent', { desc = 'Toggle transparent background' }) 83 | -------------------------------------------------------------------------------- /dot_config/sketchybar/executable_sketchybarrc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source "$CONFIG_DIR/colors.sh" 4 | source "$CONFIG_DIR/icons.sh" 5 | FONT="SF Pro" # Needs to have Regular, Bold, Semibold, Heavy and Black variants 6 | 7 | # This is a demo config to showcase some of the most important commands. 8 | # It is meant to be changed and configured, as it is intentionally kept sparse. 9 | # For a (much) more advanced configuration example see my dotfiles: 10 | # https://github.com/FelixKratz/dotfiles 11 | 12 | PLUGIN_DIR="$CONFIG_DIR/plugins" 13 | ITEM_DIR="$CONFIG_DIR/items" 14 | 15 | ##### Bar Appearance ##### 16 | # Configuring the general appearance of the bar. 17 | # These are only some of the options available. For all options see: 18 | # https://felixkratz.github.io/SketchyBar/config/bar 19 | # If you are looking for other colors, see the color picker: 20 | # https://felixkratz.github.io/SketchyBar/config/tricks#color-picker 21 | 22 | config=( 23 | height=28 24 | blur_radius=30 25 | position=top 26 | sticky=off 27 | padding_left=10 28 | padding_right=10 29 | color=$BAR_COLOR 30 | ) 31 | 32 | sketchybar --bar "${config[@]}" 33 | 34 | ##### Changing Defaults ##### 35 | # For a full list of all available item properties see: 36 | # https://felixkratz.github.io/SketchyBar/config/items 37 | 38 | default=( 39 | icon.font="SF Pro:Semibold:15.0" 40 | icon.color="$ICON_COLOR" 41 | label.font="SF Pro:Semibold:15.0" 42 | label.color="$LABEL_COLOR" 43 | icon.padding_left=4 44 | icon.padding_right=4 45 | label.padding_left=4 46 | label.padding_right=4 47 | background.color=$BAR_COLOR 48 | background.corner_radius=5 49 | background.height=20 50 | padding_left=5 51 | padding_right=5 52 | ) 53 | sketchybar --default "${default[@]}" 54 | 55 | # -- Left Items -- 56 | source "$ITEM_DIR/spaces.sh" 57 | source "$ITEM_DIR/front_app.sh" 58 | 59 | # -- Right Side of Notch items -- 60 | source "$ITEM_DIR/media.sh" 61 | 62 | # -- Right Items -- 63 | source "$ITEM_DIR/calendar.sh" 64 | source "$ITEM_DIR/volume.sh" 65 | source "$ITEM_DIR/battery.sh" 66 | source "$ITEM_DIR/cpu.sh" 67 | 68 | ##### Force all scripts to run the first time (never do this in a script) ##### 69 | sketchybar --hotload true 70 | sketchybar --update 71 | 72 | 73 | # References: https://github.com/linkarzu/dotfiles-latest/blob/main/sketchybar/felixkratz/sketchybarrc 74 | # TODO: This works when I have another monitor 75 | # defaults write com.knollsoft.Rectangle screenEdgeGapTop -int 30 76 | # defaults write com.knollsoft.Rectangle screenEdgeGapBottom -int 6 77 | # defaults write com.knollsoft.Rectangle screenEdgeGapLeft -int 6 78 | # defaults write com.knollsoft.Rectangle screenEdgeGapRight -int 6 79 | # defaults write com.knollsoft.Rectangle screenEdgeGapTopNotch -int 1 80 | -------------------------------------------------------------------------------- /dot_config/nvim/lua/my/utils.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | M.t = function(str) 4 | return vim.api.nvim_replace_termcodes(str, true, true, true) 5 | end 6 | 7 | M.log = function(msg, hl, name) 8 | name = name or 'Neovim' 9 | hl = hl or 'Todo' 10 | vim.api.nvim_echo({ { name .. ': ', hl }, { msg } }, true, {}) 11 | end 12 | 13 | M.warn = function(msg, name) 14 | M.log(msg, 'DiagnosticWarn', name) 15 | end 16 | 17 | M.error = function(msg, name) 18 | M.log(msg, 'DiagnosticError', name) 19 | end 20 | 21 | M.info = function(msg, name) 22 | M.log(msg, 'DiagnosticInfo', name) 23 | end 24 | 25 | -- @param option 26 | -- @param [opt] silent 27 | -- @usage require("utils").toggle('relativenumber') 28 | M.toggle_opt = function(option, silent) 29 | vim.opt_local[option] = not vim.opt_local[option]:get() 30 | 31 | if silent ~= true then 32 | if vim.opt_local[option]:get() then 33 | M.info('enabled vim.opt_local.' .. option, 'Toggle') 34 | else 35 | M.warn('disabled vim.opt_local.' .. option, 'Toggle') 36 | end 37 | end 38 | end 39 | 40 | function M.lsp_config() 41 | local ret = {} 42 | for _, client in pairs(vim.lsp.get_active_clients()) do 43 | ret[client.name] = { root_dir = client.config.root_dir, settings = client.config.settings } 44 | end 45 | print(vim.inspect(ret)) 46 | end 47 | 48 | -- https://github.com/ibhagwan/nvim-lua/blob/main/lua/utils.lua#L280 49 | M.sudo_exec = function(cmd, print_output) 50 | vim.fn.inputsave() 51 | local password = vim.fn.inputsecret('Password: ') 52 | vim.fn.inputrestore() 53 | if not password or #password == 0 then 54 | M.warn('Invalid password, sudo aborted') 55 | return false 56 | end 57 | local out = vim.fn.system(string.format("sudo -p '' -S %s", cmd), password) 58 | if vim.v.shell_error ~= 0 then 59 | print('\r\r') 60 | M.error(out) 61 | return false 62 | end 63 | if print_output then 64 | print('\r\n', out) 65 | end 66 | return true 67 | end 68 | 69 | M.sudo_write = function(tmpfile, filepath) 70 | if not tmpfile then 71 | tmpfile = vim.fn.tempname() 72 | end 73 | if not filepath then 74 | filepath = vim.fn.expand('%') 75 | end 76 | if not filepath or #filepath == 0 then 77 | M.error('E32: No file name') 78 | return 79 | end 80 | -- `bs=1048576` is equivalent to `bs=1M` for GNU dd or `bs=1m` for BSD dd 81 | -- Both `bs=1M` and `bs=1m` are non-POSIX 82 | local cmd = string.format('dd if=%s of=%s bs=1048576', vim.fn.shellescape(tmpfile), vim.fn.shellescape(filepath)) 83 | -- no need to check error as this fails the entire function 84 | vim.api.nvim_exec2(string.format('write! %s', tmpfile), { output = true }) 85 | if M.sudo_exec(cmd) then 86 | -- refreshes the buffer and prints the "written" message 87 | vim.cmd.edit { bang = true } 88 | -- exit command mode 89 | vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes('', true, false, true), 'n', true) 90 | M.info(string.format('"%s" written', filepath)) 91 | end 92 | vim.fn.delete(tmpfile) 93 | end 94 | 95 | M.humanize_size = function(size) 96 | if size < 1024 then 97 | return string.format('%dB', size) 98 | elseif size < 1048576 then 99 | return string.format('%.2fKiB', size / 1024) 100 | else 101 | return string.format('%.2fMiB', size / 1048576) 102 | end 103 | end 104 | 105 | return M 106 | -------------------------------------------------------------------------------- /dot_config/nvim/plugin/simple-statusline.lua: -------------------------------------------------------------------------------- 1 | _G.SimpleStatusline = {} 2 | 3 | local H = {} 4 | 5 | H.is_truncated = function(trunc_width) 6 | local cur_width = vim.o.laststatus == 3 and vim.o.columns or vim.api.nvim_win_get_width(0) 7 | return cur_width < (trunc_width or -1) 8 | end 9 | 10 | H.fileprefix = function(args) 11 | local basename = vim.fn.fnamemodify(vim.fn.expand('%:h'), ':p:~:.') 12 | if basename == '' or basename == '.' then 13 | return '' 14 | else 15 | basename = basename:gsub('/$', '') .. '/' 16 | 17 | if H.is_truncated(args.trunc_width) then 18 | return vim.fn.pathshorten(basename) 19 | end 20 | 21 | return basename 22 | end 23 | end 24 | 25 | H.git_branch = function(args) 26 | if H.is_truncated(args.trunc_width) then 27 | return '' 28 | end 29 | 30 | local branch = vim.b.gitsigns_head and vim.b.gitsigns_head or vim.g.gitsigns_head 31 | 32 | if not branch or branch == '' then 33 | branch = '-' 34 | end 35 | 36 | return string.format('  %s ', branch) 37 | end 38 | 39 | H.file_info = function(args) 40 | if H.is_truncated(args.trunc_width) then 41 | return '' 42 | end 43 | local file_size = vim.b.bufsize_human 44 | 45 | if not file_size then 46 | return '%y ' 47 | end 48 | 49 | return string.format('%s %s ', '%y', file_size) 50 | end 51 | 52 | H.loc_info = function(args) 53 | if H.is_truncated(args.trunc_width) then 54 | return 'ℓ:%l 𝚌:%2v' 55 | end 56 | -- return 'ℓ:%l/%L 𝚌:%2v/%-2{virtcol("$")-1} %p%%' 57 | return 'ℓ:%l/%L 𝚌:%2v/%-2{virtcol("$")-1}' 58 | end 59 | 60 | H.gutter_padding = function() 61 | local line_count = #tostring(vim.api.nvim_buf_line_count(0)) 62 | local hl = vim.bo.modified and '%4*' or '%1*' 63 | 64 | -- Minimum of 2 spaces for the padding 65 | local rep = math.max(line_count, 3) 66 | 67 | -- Only expand the mode to the same width as the line count if 68 | -- H 69 | -- Handling even numbers is quite tricky, so we'll just remove one space 70 | -- from the left padding if the line count is even 71 | local padding = string.rep(' ', rep) 72 | 73 | return string.format('%s%s', hl, padding) 74 | end 75 | 76 | _G.SimpleStatusline.render = function() 77 | return table.concat { 78 | -- Show mode 79 | H.gutter_padding(), 80 | -- Show git branch (if available) 81 | '%5*', 82 | H.git_branch { trunc_width = 80 }, 83 | '%*', 84 | '%<', 85 | '%3*', 86 | string.format(' %s', H.fileprefix { trunc_width = 120 }), 87 | '%2*', 88 | '%t', 89 | -- Reset highlight 90 | '%* ', 91 | -- Show modified flag and readonly flag 92 | '%m%r%h%w', 93 | -- Start right aligned items 94 | '%=%*', 95 | -- Show filetype and file size 96 | H.file_info { trunc_width = 80 }, 97 | -- Show current line and total lines 98 | '%1* ', 99 | H.loc_info { trunc_width = 80 }, 100 | } 101 | end 102 | 103 | -- Set statusline 104 | vim.opt.statusline = '%!v:lua.SimpleStatusline.render()' 105 | 106 | -- Define custom highlights 107 | vim.api.nvim_set_hl(0, 'StatusLineCommonInfo', { link = 'ColorColumn', default = true }) 108 | vim.api.nvim_set_hl(0, 'StatusLineMode', { link = 'Cursor', default = true }) 109 | 110 | vim.api.nvim_create_autocmd({ 'UIEnter', 'ColorScheme' }, { 111 | callback = function() 112 | local tablinesel = vim.api.nvim_get_hl(0, { name = 'TabLineSel' }) 113 | local conceal = vim.api.nvim_get_hl(0, { name = 'Conceal' }) 114 | 115 | vim.api.nvim_set_hl(0, 'User1', { link = 'Cursor', default = true }) 116 | vim.api.nvim_set_hl(0, 'User3', vim.tbl_extend('keep', conceal, {})) -- file prefix 117 | vim.api.nvim_set_hl(0, 'User2', { bold = true, bg = conceal.bg }) -- file name 118 | vim.api.nvim_set_hl(0, 'User4', { bg = '#e78285' }) -- gutter 119 | vim.api.nvim_set_hl(0, 'User5', vim.tbl_extend('keep', { fg = 'none' }, tablinesel)) -- git branch 120 | 121 | vim.api.nvim_set_hl(0, 'StatusLine', { bg = 'none' }) 122 | end, 123 | }) 124 | -------------------------------------------------------------------------------- /dot_config/nvim/plugin/spell-pop.lua: -------------------------------------------------------------------------------- 1 | local create_spell_pop = function() 2 | -- If the user has provided a count, then use the built-in spell suggestions 3 | if vim.v.count > 0 then 4 | vim.cmd(string.format('norm! %dz=', vim.v.count)) 5 | return 6 | end 7 | 8 | local cursor_word = vim.fn.expand('') 9 | local spell_suggestions = vim.fn.spellsuggest(cursor_word, 15) 10 | 11 | -- I don't know a better way to handle this since I want to leverage 12 | -- the builtin message provided by spellsuggest if no suggestions are available 13 | -- without having to manually print the error message. 14 | -- So, calling the built-in z= if there are no suggestions for now 15 | if vim.tbl_isempty(spell_suggestions) then 16 | vim.cmd('norm! z=') 17 | return 18 | end 19 | 20 | local current_window = vim.api.nvim_get_current_win() 21 | local cursor_pos = vim.api.nvim_win_get_cursor(current_window) 22 | 23 | -- Define the popup window options 24 | local opts = { 25 | relative = 'cursor', -- Position the window relative to the cursor 26 | row = 1, -- Adjust the vertical position (rows below the cursor) 27 | col = 1, -- Adjust the horizontal position (columns to the right of the cursor) 28 | width = math.max(#cursor_word * 2, 25), -- Width of the popup window (min 20 chars 29 | height = #spell_suggestions, -- Height of the popup window 30 | style = 'minimal', -- Minimal style (no line numbers, etc.) 31 | border = 'rounded', -- Border style (none, single, double, rounded, solid, shadow) 32 | title = '> Spell Suggestions <', 33 | title_pos = 'center', 34 | } 35 | 36 | -- Create the popup window 37 | local buf = vim.api.nvim_create_buf(false, true) 38 | local popup_winid = vim.api.nvim_open_win(buf, true, opts) 39 | 40 | -- Prefercolemak homerow keys 41 | local keys = '1234567890neioarst' 42 | 43 | for index, suggestion in ipairs(spell_suggestions) do 44 | local key = keys:sub(index, index) 45 | 46 | vim.api.nvim_buf_set_lines(buf, index - 1, -1, false, { string.format('[%s] %s', key, suggestion) }) 47 | 48 | vim.schedule(function() 49 | vim.keymap.set('n', key, function() 50 | vim.api.nvim_win_close(popup_winid, true) 51 | vim.cmd(string.format('norm! "_ciw%s', suggestion)) 52 | end, { buffer = buf, noremap = true, nowait = true }) 53 | end) 54 | end 55 | 56 | vim.api.nvim_set_option_value( 57 | 'winhighlight', 58 | 'Normal:SpellPopNormal,FloatBorder:SpellPopFloatBorder', 59 | { win = popup_winid } 60 | ) 61 | vim.api.nvim_set_option_value('winfixbuf', true, { win = popup_winid }) 62 | vim.api.nvim_set_option_value('cursorline', true, { win = popup_winid }) 63 | vim.api.nvim_set_option_value('modifiable', false, { buf = buf }) 64 | vim.api.nvim_set_option_value('filetype', 'spellpopup', { buf = buf }) 65 | 66 | vim.keymap.set('n', '', function() 67 | vim.api.nvim_win_close(popup_winid, true) 68 | end, { buffer = buf, nowait = true }) 69 | 70 | vim.keymap.set('n', 'q', function() 71 | vim.api.nvim_win_close(popup_winid, true) 72 | end, { buffer = buf, nowait = true }) 73 | 74 | -- IDK how other plugins handle things when you just confirm with 75 | -- But since the current cursor line has a 1:1 mapping with the suggestions 76 | -- we can use the cursor line to apply the spelling suggestion by accessing 77 | -- the index of the line in the spell_suggestions table 78 | vim.keymap.set('n', '', function() 79 | local line_pos = vim.api.nvim_win_get_cursor(popup_winid)[1] 80 | vim.api.nvim_win_close(popup_winid, true) 81 | vim.cmd(string.format('norm! "_ciw%s', spell_suggestions[line_pos])) 82 | vim.api.nvim_win_set_cursor(current_window, cursor_pos) 83 | end, { buffer = buf, nowait = true, desc = 'Apply spelling based on current selected line' }) 84 | 85 | vim.api.nvim_create_autocmd({ 'WinLeave', 'BufLeave' }, { 86 | buffer = buf, 87 | once = true, 88 | callback = function() 89 | vim.api.nvim_win_close(popup_winid, true) 90 | end, 91 | }) 92 | end 93 | 94 | -- Override default spellsuggest mapping 95 | vim.keymap.set('n', 'z=', create_spell_pop, { noremap = true, silent = true }) 96 | -------------------------------------------------------------------------------- /dot_config/fish/config.fish: -------------------------------------------------------------------------------- 1 | # General 2 | set -gx EDITOR nvim 3 | set -gx VISUAL $EDITOR 4 | set -gx SUDO_EDITOR $EDITOR 5 | set -gx LANG en_US.UTF-8 6 | 7 | # i = case-insensitive searches, unless uppercase characters in search string 8 | # F = exit immediately if output fits on one screen 9 | # M = verbose prompt 10 | # R = ANSI color support 11 | # X = suppress alternate screen 12 | # -#.25 = scroll horizontally by quarter of screen width (default is half) 13 | set -gx LESS "-iFRMX-#.25" 14 | 15 | ## System 16 | ulimit -n 16384 # Increase resource usage limits to 16384 Default is 256 17 | 18 | ## Since we are either using tmux or just default shell we want to check if 19 | ## PARENT_TERM is set by our tmux config so we can use it for other programs 20 | set -q PARENT_TERM || set PARENT_TERM $TERM 21 | 22 | # Load universal config when it's changed 23 | set -l fish_config_mtime 24 | # Test if we are on macOS or Linux 25 | if test -d /Applications 26 | set fish_config_mtime (/usr/bin/stat -f %m $__fish_config_dir/config.fish) 27 | else 28 | set fish_config_mtime (/usr/bin/stat -c %Y $__fish_config_dir/config.fish) 29 | end 30 | 31 | set -l local_config $__fish_config_dir/config-local.fish 32 | if test -f $local_config 33 | source $__fish_config_dir/config-local.fish 34 | end 35 | 36 | if test "$fish_config_changed" = "$fish_config_mtime" 37 | exit 38 | else 39 | set -U fish_config_changed $fish_config_mtime 40 | end 41 | 42 | # Exports 43 | ## Use neovim as the default man pager. Type :h Man for more info 44 | set -Ux MANPAGER "nvim +Man!" 45 | set -Ux MANWIDTH 999 46 | set -Ux XDG_CONFIG_HOME $HOME/.config 47 | ## fzf 48 | set -Ux FZF_DEFAULT_OPTS_FILE $XDG_CONFIG_HOME/fzf/config 49 | ## virtualfish 50 | set -Ux VIRTUALFISH_HOME $HOME/.local/share/virtualenvs 51 | ## Bun 52 | set -Ux BUN_INSTALL $HOME/.bun 53 | ## whalebrew 54 | set -Ux WHALEBREW_INSTALL_PATH $HOME/.local/bin 55 | ## zk 56 | set -Ux ZK_SHELL /bin/zsh 57 | ## go 58 | set -Ux GOPATH $HOME/go 59 | ## homebrew cask 60 | set -Ux HOMEBREW_CASK_OPTS --no-quarantine 61 | 62 | # Path 63 | set -Ux fish_user_paths 64 | ## macos defaults 65 | fish_add_path /usr/local/bin 66 | ## homebrew bin 67 | fish_add_path $HOMEBREW_PREFIX/sbin $HOMEBREW_PREFIX/bin 68 | ## mysql client 69 | fish_add_path $HOMEBREW_PREFIX/opt/mysql-client/bin 70 | ## psql client 71 | fish_add_path $HOMEBREW_PREFIX/opt/libpq/bin 72 | ## python 73 | fish_add_path $HOMEBREW_PREFIX/opt/python/libexec/bin 74 | ## golang 75 | fish_add_path $GOPATH $GOPATH/bin 76 | ## cargo 77 | fish_add_path $HOME/.cargo/bin 78 | ## mise shims 79 | fish_add_path $HOME/.local/share/mise/shims 80 | ## docker 81 | fish_add_path $HOME/.docker/bin 82 | ## local binaries 83 | fish_add_path $HOME/.local/bin 84 | 85 | # aliases 86 | alias -s brewup "brew update; brew upgrade; brew cleanup; brew doctor" 87 | alias -s cat bat 88 | alias -s dc "docker compose" 89 | alias -s getip "curl ipinfo.io/ip" 90 | alias -s g git 91 | alias -s localip "ipconfig getifaddr en0" 92 | alias -s rscp "rsync -avhE --progress" # for copying local files 93 | alias -s rsmv "rsync -avhE --no-compress --progress --remove-source-files" 94 | alias -s tree "eza --tree" 95 | alias -s kd "rm /var/folders/*/*/*/com.apple.dock.iconcache; killall Dock" 96 | alias -s vifish "$EDITOR ~/.config/fish/config.fish" 97 | alias -s pmr "pm runserver" 98 | alias -s minvim "NVIM_APPNAME=minvim nvim" 99 | alias -s ssht "TERM=screen ssh" 100 | alias -s zki 'cd ~/Sync/notes/ && zk i' 101 | alias -s loadsshkeys "ls -d ~/.ssh/* -I '*.pub|config|environment|pems|known_hosts' | xargs ssh-add --apple-load-keychain &> /dev/null" 102 | alias -s untar "tar -xvf" 103 | alias -s ls "eza --color=always --icons --group-directories-first --classify" 104 | alias -s la "eza --color=always --icons --group-directories-first --classify --all" 105 | alias -s ll "eza --color=always --icons --group-directories-first --classify --all --long" 106 | alias -s ge graph-easy 107 | alias -s icat "kitty +kitten icat" 108 | alias -s ccurl "curl -OJL" # download file with original name 109 | alias -s nvim-upgrade-nightly "nvim -v && echo 'Updating neovim@nightly...' && mise uninstall neovim@nightly -q && mise install neovim@nightly -q && nvim -v" 110 | alias -s cls "clear; printf '\e[3J'" 111 | -------------------------------------------------------------------------------- /dot_config/nvim/lua/my/plugins/fzf.lua: -------------------------------------------------------------------------------- 1 | local keys = { 2 | { 3 | 'F', 4 | mode = 'c', 5 | }, 6 | { 7 | 'f', 8 | mode = 'c', 9 | }, 10 | { 11 | 'e', 12 | function() 13 | require('fzf-lua').files { 14 | cwd = '~/Sources/github.com/yujinyuz/dotfiles', 15 | fzf_opts = { ['--ansi'] = false }, 16 | file_icons = false, 17 | git_icons = false, 18 | winopts = { 19 | preview = { hidden = 'hidden' }, 20 | }, 21 | } 22 | end, 23 | desc = 'Edit dotfiles', 24 | }, 25 | { 26 | 'n', 27 | function() 28 | require('fzf-lua').files { 29 | cwd_prompt = false, 30 | fzf_opts = { ['--ansi'] = false }, 31 | file_icons = false, 32 | git_icons = false, 33 | winopts = { 34 | preview = { hidden = 'hidden' }, 35 | }, 36 | } 37 | end, 38 | desc = 'Find files', 39 | }, 40 | { 41 | ']', 42 | function() 43 | require('fzf-lua').tags { 44 | winopts = { preview = { hidden = 'hidden' } }, 45 | file_icons = false, 46 | git_icons = false, 47 | } 48 | end, 49 | desc = 'Tags', 50 | }, 51 | { 52 | 'F', 53 | function() 54 | require('fzf-lua').live_grep_glob { 55 | winopts = { preview = { hidden = 'hidden' } }, 56 | exec_empty_query = true, 57 | } 58 | end, 59 | desc = '[F]ind text', 60 | }, 61 | { 62 | 'R', 63 | 'FzfLua resume', 64 | desc = '[R]esume', 65 | }, 66 | { 67 | 'fb', 68 | 'FzfLua buffers', 69 | }, 70 | { 71 | 'b', 72 | 'FzfLua buffers', 73 | }, 74 | { 75 | 'fw', 76 | 'FzfLua grep_cword', 77 | }, 78 | { 79 | 'gr', 80 | 'FzfLua lsp_references', 81 | }, 82 | { 83 | '?', 84 | 'FzfLua lines', 85 | }, 86 | { 87 | 'N', 88 | 'FzfLua resume', 89 | }, 90 | { 91 | 'fh', 92 | 'FzfLua help_tags', 93 | }, 94 | { 95 | 'fo', 96 | 'FzfLua oldfiles', 97 | }, 98 | { 99 | '\\', 100 | 'FzfLua lsp_live_workspace_symbols', 101 | }, 102 | { 103 | ',b', 104 | 'FzfLua buffers', 105 | }, 106 | { 107 | 'hl', 108 | 'FzfLua highlights', 109 | }, 110 | { 111 | 'fq', 112 | 'FzfLua quickfix', 113 | }, 114 | { ',q', 'FzfLua quickfix' }, 115 | } 116 | 117 | local config = function() 118 | local fzf = require('fzf-lua') 119 | local actions = require('fzf-lua.actions') 120 | local defaults = require('fzf-lua.defaults').defaults 121 | 122 | fzf.setup { 123 | 'default-title', 124 | actions = { 125 | files = { 126 | ['default'] = actions.file_edit, 127 | ['ctrl-s'] = actions.file_split, 128 | ['ctrl-v'] = actions.file_vsplit, 129 | ['ctrl-t'] = actions.file_tabedit, 130 | ['alt-q'] = actions.file_sel_to_qf, 131 | }, 132 | buffers = { 133 | ['default'] = actions.buf_edit, 134 | ['ctrl-s'] = actions.buf_split, 135 | ['ctrl-v'] = actions.buf_vsplit, 136 | ['ctrl-t'] = actions.buf_tabedit, 137 | }, 138 | }, 139 | winopts = { 140 | backdrop = false, 141 | preview = { 142 | delay = 0, 143 | layout = 'flex', 144 | flip_columns = 130, 145 | }, 146 | height = 0.75, 147 | width = 0.80, 148 | }, 149 | fzf_opts = { 150 | ['--no-hscroll'] = '', 151 | ['--layout'] = 'default', 152 | }, 153 | fzf_colors = true, 154 | keymap = { 155 | builtin = { 156 | [''] = 'preview-page-down', 157 | [''] = 'preview-page-up', 158 | [''] = 'toggle-preview', 159 | [''] = 'toggle-preview-wrap', 160 | [''] = 'toggle-preview-cw', 161 | }, 162 | }, 163 | files = { 164 | fd_opts = '--strip-cwd-prefix ' .. defaults.files.fd_opts, 165 | git_icons = false, 166 | }, 167 | git = { 168 | files = { 169 | cmd = defaults.git.files.cmd .. ' --cached --others --deduplicate', 170 | git_icons = false, 171 | file_icons = false, 172 | }, 173 | }, 174 | grep = { 175 | git_icons = false, 176 | file_icons = false, 177 | multiline = 1, 178 | }, 179 | on_create = function() 180 | vim.keymap.set('t', '', '', { buffer = 0 }) 181 | end, 182 | } 183 | end 184 | 185 | return { 186 | 'ibhagwan/fzf-lua', 187 | config = config, 188 | keys = keys, 189 | } 190 | -------------------------------------------------------------------------------- /dot_config/private_karabiner/private_assets/private_complex_modifications/mine.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Personal Config @yujinyuz", 3 | "rules": [ 4 | { 5 | "description": "Change caps_lock to control if pressed with other keys, to escape if pressed alone.", 6 | "manipulators": [ 7 | { 8 | "from": { 9 | "key_code": "caps_lock", 10 | "modifiers": { 11 | "optional": [ 12 | "any" 13 | ] 14 | } 15 | }, 16 | "to": [ 17 | { 18 | "key_code": "left_control", 19 | "lazy": true 20 | } 21 | ], 22 | "to_if_alone": [ 23 | { 24 | "key_code": "escape", 25 | "lazy": true 26 | } 27 | ], 28 | "type": "basic" 29 | } 30 | ] 31 | }, 32 | { 33 | "manipulators": [ 34 | { 35 | "description": "Change left control to Hyper Key (command+control+option)", 36 | "from": { 37 | "key_code": "left_control", 38 | "modifiers": { 39 | "optional": [ 40 | "any" 41 | ] 42 | } 43 | }, 44 | "to": [ 45 | { 46 | "key_code": "left_option", 47 | "modifiers": [ 48 | "left_command", 49 | "left_control" 50 | ] 51 | } 52 | ], 53 | "type": "basic" 54 | } 55 | ] 56 | }, 57 | { 58 | "description": "Toggle caps_lock by pressing left_shift then right_shift", 59 | "manipulators": [ 60 | { 61 | "from": { 62 | "key_code": "left_shift", 63 | "modifiers": { 64 | "mandatory": [ 65 | "right_shift" 66 | ], 67 | "optional": [ 68 | "caps_lock" 69 | ] 70 | } 71 | }, 72 | "to": [ 73 | { 74 | "key_code": "caps_lock" 75 | } 76 | ], 77 | "to_if_alone": [ 78 | { 79 | "key_code": "left_shift" 80 | } 81 | ], 82 | "type": "basic" 83 | }, 84 | { 85 | "from": { 86 | "key_code": "right_shift", 87 | "modifiers": { 88 | "mandatory": [ 89 | "left_shift" 90 | ], 91 | "optional": [ 92 | "caps_lock" 93 | ] 94 | } 95 | }, 96 | "to": [ 97 | { 98 | "key_code": "caps_lock" 99 | } 100 | ], 101 | "to_if_alone": [ 102 | { 103 | "key_code": "right_shift" 104 | } 105 | ], 106 | "type": "basic" 107 | } 108 | ] 109 | }, 110 | { 111 | "description": "CTRL-W to delete-backward-word", 112 | "manipulators": [ 113 | { 114 | "conditions": [ 115 | { 116 | "bundle_identifiers": [ 117 | "com.googlecode.iterm2", 118 | "net.kovidgoyal.kitty", 119 | "co.zeit.hyper", 120 | "com.apple.Terminal", 121 | "io.alacritty", 122 | "com.valvesoftware.steam" 123 | ], 124 | "type": "frontmost_application_unless" 125 | } 126 | ], 127 | "from": { 128 | "key_code": "w", 129 | "modifiers": { 130 | "mandatory": [ 131 | "control" 132 | ], 133 | "optional": [ 134 | "any" 135 | ] 136 | } 137 | }, 138 | "to": [ 139 | { 140 | "key_code": "delete_or_backspace", 141 | "modifiers": [ 142 | "left_option" 143 | ] 144 | } 145 | ], 146 | "type": "basic" 147 | } 148 | ] 149 | }, 150 | { 151 | "description": "Map ctrl + [ to escape", 152 | "manipulators": [ 153 | { 154 | "from": { 155 | "key_code": "open_bracket", 156 | "modifiers": { 157 | "mandatory": [ 158 | "control" 159 | ], 160 | "optional": [ 161 | "any" 162 | ] 163 | } 164 | }, 165 | "to": [ 166 | { 167 | "key_code": "escape" 168 | } 169 | ], 170 | "type": "basic" 171 | } 172 | ] 173 | } 174 | ] 175 | } 176 | -------------------------------------------------------------------------------- /dot_config/skhd/skhdrc: -------------------------------------------------------------------------------- 1 | # Hyper Key: cmd + alt + ctrl 2 | # Leader Key: alt + ctrl 3 | # Move Key: alt + ctrl + shift 4 | # Mnemonic: shifting items around 5 | 6 | # open terminal 7 | # This prevents having multiple kitty windows in the Dock 8 | # cmd - return is used in multiple instances so I'm not sure if it's a good idea to use it 9 | # alt - return : pgrep -x kitty && kitty @ launch --type=os-window --cwd=~ &> /dev/null || kitty -1 -d ~ &> /dev/null; 10 | 11 | # window state & layout 12 | # alt + ctrl - return : yabai -m window --toggle split 13 | 14 | # Hyper key + shift 15 | # cmd + alt + ctrl + shift - 1 : yabai -m window --space 1 16 | # cmd + alt + ctrl + shift - 2 : yabai -m window --space 2 17 | # cmd + alt + ctrl + shift - 3 : yabai -m window --space 3 18 | # cmd + alt + ctrl + shift - 4 : yabai -m window --space 4 19 | # cmd + alt + ctrl + shift - 5 : yabai -m window --space 5 20 | # cmd + alt + ctrl + shift - 6 : yabai -m window --space 6 21 | 22 | # toggle desktop offset 23 | # cmd + alt + ctrl - g : yabai -m space --toggle padding; yabai -m space --toggle gap 24 | 25 | # alt + ctrl - space : yabai -m window --toggle split 26 | # alt + ctrl - y : yabai -m space --rotate 270 27 | # alt + ctrl - space : yabai -m space --layout "$(yabai -m query --spaces --space | jq -r 'if .type == "bsp" then "stack" else "bsp" end')" 28 | 29 | # alt + ctrl - f : yabai -m window --toggle zoom-fullscreen 30 | # alt + ctrl - e : yabai -m space --balance 31 | 32 | # float / unfloat a window and center it on screen 33 | # alt + ctrl - c : yabai -m window --toggle float --grid 4:4:1:1:2:2 34 | # alt + ctrl - t : yabai -m window --toggle float --grid 4:4:0:0:2:2 35 | 36 | 37 | # focus window 38 | # alt + ctrl - k : yabai -m window --focus north || \ 39 | # yabai -m window --focus south || \ 40 | # yabai -m window --focus west || \ 41 | # yabai -m window --focus east; \ 42 | # 43 | # alt + ctrl - j : yabai -m window --focus south || \ 44 | # yabai -m window --focus north || \ 45 | # yabai -m window --focus west || \ 46 | # yabai -m window --focus east; \ 47 | # 48 | # alt + ctrl - h : yabai -m window --focus west || \ 49 | # yabai -m window --focus east; \ 50 | # 51 | # alt + ctrl - l : yabai -m window --focus east || \ 52 | # yabai -m window --focus west; \ 53 | 54 | 55 | # swap window 56 | # alt + ctrl + shift - right : yabai -m window --swap east 57 | # alt + ctrl + shift - left : yabai -m window --swap west 58 | # alt + ctrl + shift - up : yabai -m window --swap north 59 | # alt + ctrl + shift - down : yabai -m window --swap south 60 | # 61 | # alt + ctrl + shift - h : yabai -m window --swap west || \ 62 | # yabai -m window --swap east; 63 | # alt + ctrl + shift - l : yabai -m window --swap east || \ 64 | # yabai -m window --swap west; 65 | # 66 | # alt + ctrl + shift - k : yabai -m window --swap north || \ 67 | # yabai -m window --swap south; 68 | # alt + ctrl + shift - j : yabai -m window --swap south || \ 69 | # yabai -m window --swap north; 70 | # 71 | # 72 | # # warp window 73 | # cmd + alt + ctrl - right : yabai -m window --warp east 74 | # cmd + alt + ctrl - left : yabai -m window --warp west 75 | # cmd + alt + ctrl - up : yabai -m window --warp north 76 | # cmd + alt + ctrl - down : yabai -m window --warp south 77 | # 78 | # cmd + alt + ctrl - h : yabai -m window --warp west 79 | # cmd + alt + ctrl - l : yabai -m window --warp east 80 | # cmd + alt + ctrl - k : yabai -m window --warp north 81 | # cmd + alt + ctrl - j : yabai -m window --warp south 82 | # 83 | # 84 | # # macOS go to desktop because you can't map multiple keys within 85 | # # system preferences keyboard shortcuts 86 | # # I have this because it's sometimes hard to reach the number keys 87 | # cmd + alt + ctrl - q : skhd -k "cmd + alt + ctrl - 4" 88 | # cmd + alt + ctrl - w : skhd -k "cmd + alt + ctrl - 5" 89 | # cmd + alt + ctrl - f : skhd -k "cmd + alt + ctrl - 6" 90 | # 91 | # 92 | # cmd + alt + ctrl + shift - q : skhd -k "cmd + alt + ctrl + shift - 4" 93 | # cmd + alt + ctrl + shift - w : skhd -k "cmd + alt + ctrl + shift - 5" 94 | # cmd + alt + ctrl + shift - f : skhd -k "cmd + alt + ctrl + shift - 6" 95 | # 96 | # 97 | # 98 | # # resize 99 | # alt + ctrl - up : yabai -m window --resize top:0:-10; yabai -m window --resize bottom:0:10 100 | # alt + ctrl - down : yabai -m window --resize top:0:10; yabai -m window --resize bottom:0:-10 101 | # alt + ctrl - left : yabai -m window --resize right:-10:0; yabai -m window --resize left:10:0 102 | # alt + ctrl - right : yabai -m window --resize right:10:0; yabai -m window --resize left:-10:0 103 | # 104 | # 105 | # alt + ctrl - y : yabai -m query --spaces --space | \ 106 | # jq -re ".type" | \ 107 | # xargs -I {} bash -c \ 108 | # "if [ {} = 'stack' ]; \ 109 | # then yabai -m space --layout bsp; \ 110 | # else yabai -m space --layout stack; \ 111 | # fi"; \ 112 | 113 | # vim: ft=bash 114 | -------------------------------------------------------------------------------- /dot_config/nvim/lua/my/plugins/coding.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | 'andymass/vim-matchup', 4 | enabled = false, 5 | event = 'BufReadPost', 6 | init = function() 7 | vim.g.matchup_matchparen_offscreen = { method = 'popup' } 8 | vim.g.matchup_surround_enabled = 1 9 | end, 10 | opts = {}, 11 | config = function(_, opts) 12 | local ok, cmp = pcall(require, 'cmp') 13 | 14 | -- https://github.com/hrsh7th/nvim-cmp/issues/1940 15 | if ok then 16 | cmp.event:on('menu_opened', function() 17 | vim.b.matchup_matchparen_enabled = false 18 | end) 19 | cmp.event:on('menu_closed', function() 20 | vim.b.matchup_matchparen_enabled = true 21 | end) 22 | end 23 | require('match-up').setup(opts) 24 | end, 25 | }, 26 | { 27 | 'Wansmer/treesj', 28 | keys = { 29 | { 'J', 'TSJToggle', desc = 'Join Toggle' }, 30 | }, 31 | opts = { use_default_keymaps = false, max_join_length = 150 }, 32 | }, 33 | { 34 | 'danymat/neogen', 35 | cmd = { 'Neogen' }, 36 | opts = { 37 | enabled = true, 38 | languages = { 39 | python = { 40 | template = { 41 | annotation_convention = 'reST', 42 | }, 43 | }, 44 | }, 45 | }, 46 | }, 47 | { 48 | 'numToStr/FTerm.nvim', 49 | config = function() 50 | local FTerm = require('FTerm') 51 | FTerm.setup { 52 | -- Makes things a little bit more stable with tmux since it 53 | -- does not inherit the environment variables 54 | clear_env = true, 55 | } 56 | 57 | local lazydocker = FTerm:new { 58 | ft = 'fterm_lazydocker', 59 | cmd = 'lazydocker', 60 | clear_nv = true, 61 | } 62 | 63 | vim.api.nvim_create_user_command('LazyDockerToggle', function() 64 | lazydocker:toggle() 65 | end, {}) 66 | 67 | local fterm1 = FTerm:new { 68 | cmd = vim.env.SHELL, 69 | ft = 'fterm_1', 70 | clear_env = true, 71 | } 72 | 73 | local fterm2 = FTerm:new { 74 | cmd = vim.env.SHELL, 75 | ft = 'fterm_2', 76 | clear_env = true, 77 | } 78 | 79 | vim.api.nvim_create_user_command('FTermToggle', FTerm.toggle, { bang = true }) 80 | vim.api.nvim_create_user_command('FTerm1Toggle', function() 81 | fterm1:toggle() 82 | end, { bang = true }) 83 | 84 | vim.api.nvim_create_user_command('FTerm2Toggle', function() 85 | fterm2:toggle() 86 | end, { bang = true }) 87 | 88 | vim.api.nvim_create_user_command('FTermCloseAllExcept', function(command) 89 | if command.args == '1' then 90 | FTerm.close() 91 | fterm2:close() 92 | elseif command.args == '2' then 93 | FTerm.close() 94 | fterm1:close() 95 | else 96 | fterm1:close() 97 | fterm2:close() 98 | end 99 | end, { 100 | complete = function() 101 | return { '0', '1', '2' } 102 | end, 103 | nargs = '?', 104 | }) 105 | end, 106 | cmd = { 107 | 'FTermToggle', 108 | 'FTerm1Toggle', 109 | 'FTerm2Toggle', 110 | 'LazyDockerToggle', 111 | }, 112 | keys = { 113 | { 114 | '', 115 | function() 116 | if vim.fn.mode() == 't' then 117 | vim.cmd('FTermCloseAllExcept 0') 118 | end 119 | require('FTerm').toggle() 120 | end, 121 | mode = { 'n', 't' }, 122 | }, 123 | { 124 | '', 125 | function() 126 | if vim.fn.mode() == 't' then 127 | vim.cmd('FTermCloseAllExcept 1') 128 | end 129 | vim.cmd('FTerm1Toggle') 130 | end, 131 | mode = { 'n', 't' }, 132 | }, 133 | { 134 | '', 135 | function() 136 | if vim.fn.mode() == 't' then 137 | vim.cmd('FTermCloseAllExcept 2') 138 | end 139 | vim.cmd('FTerm2Toggle') 140 | end, 141 | mode = { 'n', 't' }, 142 | }, 143 | }, 144 | }, 145 | { 146 | 'folke/trouble.nvim', 147 | opts = {}, 148 | cmd = 'Trouble', 149 | keys = { 150 | { 151 | 'xx', 152 | 'Trouble diagnostics toggle focus=true', 153 | desc = 'Diagnostics (Trouble)', 154 | }, 155 | { 156 | 'xX', 157 | 'Trouble diagnostics toggle filter.buf=0', 158 | desc = 'Buffer Diagnostics (Trouble)', 159 | }, 160 | { 161 | 'cs', 162 | 'Trouble symbols toggle focus=false', 163 | desc = 'Symbols (Trouble)', 164 | }, 165 | { 166 | 'cl', 167 | 'Trouble lsp toggle focus=false win.position=right', 168 | desc = 'LSP Definitions / references / ... (Trouble)', 169 | }, 170 | { 171 | 'xL', 172 | 'Trouble loclist toggle', 173 | desc = 'Location List (Trouble)', 174 | }, 175 | { 176 | 'xq', 177 | 'Trouble qflist toggle', 178 | desc = 'Quickfix List (Trouble)', 179 | }, 180 | }, 181 | }, 182 | { 183 | 'windwp/nvim-ts-autotag', 184 | event = { 'BufReadPre', 'BufNewFile' }, 185 | opts = {}, 186 | }, 187 | { 188 | 'folke/ts-comments.nvim', 189 | opts = { 190 | lang = { 191 | htmldjango = { 192 | '{# %s #}', 193 | }, 194 | }, 195 | }, 196 | }, 197 | { 198 | 'andrewferrier/debugprint.nvim', 199 | event = { 'BufReadPost' }, 200 | opts = {}, 201 | version = '*', 202 | }, 203 | } 204 | -------------------------------------------------------------------------------- /dot_config/nvim/lua/my/plugins/ui.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | 'catppuccin/nvim', 4 | lazy = false, 5 | name = 'catppuccin', 6 | priority = 1000, 7 | config = function() 8 | require('catppuccin').setup { 9 | background = { 10 | light = 'latte', 11 | dark = 'frappe', 12 | }, 13 | no_italic = false, -- Force no italic 14 | no_bold = false, 15 | styles = { 16 | comments = { 'italic' }, 17 | conditionals = { 'italic' }, 18 | }, 19 | transparent_background = true, 20 | float = { 21 | transparent = true, 22 | solid = true, 23 | }, 24 | custom_highlights = function(colors) 25 | return { 26 | StatuslineFilePrefix = { bg = colors.surface0, fg = colors.subtext0, style = { 'italic' } }, 27 | StatuslineFileName = { bg = colors.surface0, fg = colors.text, style = { 'bold' } }, 28 | StatusLineMode = { bg = colors.text, fg = colors.base }, 29 | MiniFilesNormal = { bg = colors.none, fg = colors.text }, 30 | } 31 | end, 32 | integrations = { 33 | aerial = true, 34 | cmp = true, 35 | fzf = true, 36 | gitsigns = true, 37 | leap = true, 38 | lsp_trouble = true, 39 | mason = true, 40 | markdown = true, 41 | mini = true, 42 | native_lsp = { 43 | enabled = true, 44 | virtual_text = { 45 | errors = { 'italic' }, 46 | hints = { 'italic' }, 47 | warnings = { 'italic' }, 48 | information = { 'italic' }, 49 | }, 50 | underlines = { 51 | errors = { 'undercurl' }, 52 | hints = { 'undercurl' }, 53 | warnings = { 'undercurl' }, 54 | information = { 'undercurl' }, 55 | }, 56 | inlay_hints = { 57 | background = true, 58 | }, 59 | }, 60 | treesitter = true, 61 | treesitter_context = true, 62 | which_key = true, 63 | }, 64 | } 65 | vim.cmd.colorscheme('catppuccin') 66 | 67 | vim.api.nvim_create_user_command('CatppuccinToggleTransparent', function() 68 | local cat = require('catppuccin') 69 | -- Change the compile path so whenever we restart neovim, it won't use 70 | -- the old compiled file 71 | cat.options.compile_path = string.format('%s/tmp-catppuccin', vim.fn.stdpath('cache')) 72 | cat.options.transparent_background = not cat.options.transparent_background 73 | 74 | if cat.options.transparent_background then 75 | require('my.utils').info('enabled catppuccin.transparent_background', 'Toggle') 76 | else 77 | require('my.utils').warn('disabled catppuccin.transparent_background', 'Toggle') 78 | end 79 | 80 | cat.compile() 81 | vim.cmd.colorscheme(vim.g.colors_name) 82 | end, {}) 83 | end, 84 | }, 85 | { 86 | 'echasnovski/mini.icons', 87 | lazy = true, 88 | opts = {}, 89 | init = function() 90 | package.preload['nvim-web-devicons'] = function() 91 | require('mini.icons').mock_nvim_web_devicons() 92 | return package.loaded['nvim-web-devicons'] 93 | end 94 | end, 95 | }, 96 | { 97 | 'j-hui/fidget.nvim', 98 | event = { 'BufRead' }, 99 | opts = { 100 | -- Copied from catppuccin theme recommendation 101 | notification = { 102 | window = { 103 | winblend = 0, 104 | }, 105 | }, 106 | }, 107 | }, 108 | { 109 | 'hiphish/rainbow-delimiters.nvim', 110 | event = 'BufReadPost', 111 | submodules = false, 112 | config = function() 113 | local rainbow = require('rainbow-delimiters') 114 | require('rainbow-delimiters.setup').setup { 115 | strategy = { 116 | [''] = function(bufnr) 117 | -- Disabled for very large files, global strategy for large files, 118 | -- local strategy otherwise 119 | local line_count = vim.api.nvim_buf_line_count(bufnr) 120 | if line_count > 10000 then 121 | return nil 122 | elseif line_count > 1000 then 123 | return rainbow.strategy['global'] 124 | end 125 | 126 | return nil 127 | end, 128 | }, 129 | highlight = { 130 | -- 'RainbowDelimiterRed', 131 | 'RainbowDelimiterYellow', 132 | 'RainbowDelimiterBlue', 133 | -- 'RainbowDelimiterOrange', 134 | -- 'RainbowDelimiterGreen', 135 | 'RainbowDelimiterViolet', 136 | 'RainbowDelimiterCyan', 137 | }, 138 | } 139 | end, 140 | }, 141 | { 142 | 'stevearc/dressing.nvim', 143 | event = 'VeryLazy', 144 | opts = { 145 | input = { 146 | enabled = false, 147 | }, 148 | }, 149 | }, 150 | { 151 | 'miversen33/sunglasses.nvim', 152 | enabled = false, 153 | event = 'UIEnter', 154 | dev = false, 155 | opts = { 156 | filter_type = 'NOSYNTAX', 157 | filter_percent = 0.35, 158 | excluded_filetypes = { 159 | 'spellpopup', 160 | 'fugitive', 161 | 'gitcommit', 162 | 'qf', 163 | 'http', 164 | 'text', 165 | 'grug-far', 166 | 'oil', 167 | }, 168 | excluded_highlights = { 169 | 'WinSeparator', 170 | { 'StatusLine*', glob = true }, 171 | { 'User*', glob = true }, 172 | }, 173 | }, 174 | config = function(_, opts) 175 | local sg = require('sunglasses') 176 | sg.setup(opts) 177 | end, 178 | }, 179 | } 180 | -------------------------------------------------------------------------------- /dot_config/nvim/lua/my/maps.lua: -------------------------------------------------------------------------------- 1 | -- General keymaps that aren't specific to plugins 2 | 3 | -- Prevent accidentally opening ex mode 4 | vim.keymap.set('n', 'Q', '"_') 5 | 6 | -- Create new file 7 | vim.keymap.set('n', 'fn', [[:e %:h]], { desc = 'Create new file relative to current file' }) 8 | 9 | vim.keymap.set('n', '', '', { desc = '[B]uffer [S]witch' }) 10 | 11 | -- Resize splits with Shift + Arrow Keys 12 | vim.keymap.set('n', '', '+') 13 | vim.keymap.set('n', '', '-') 14 | vim.keymap.set('n', '', '<') 15 | vim.keymap.set('n', '', '>') 16 | 17 | -- Windows: Move between windows 18 | -- The reason behind these keymaps is because I loved playing snake 19 | -- during the Nokia days and I was just using it with 1/9 or 3/7 on the keypad 20 | -- so even if I have more than 2 windows, these keymaps will just cycle through 21 | -- all windows 22 | vim.keymap.set('n', '', 'w') 23 | vim.keymap.set('n', '', 'W') 24 | 25 | -- Smooth scroll 26 | vim.keymap.set('n', '', '3') 27 | vim.keymap.set('n', '', '3') 28 | 29 | -- Use Alt for moving lines up/down 30 | vim.keymap.set('n', '', [[mz:m+`z]], { silent = true }) 31 | vim.keymap.set('n', '', [[mz:m-2`z]], { silent = true }) 32 | vim.keymap.set('v', '', [[:m'>+`mzgv`yo`z]], { silent = true }) 33 | vim.keymap.set('v', '', [[:m'<-2`>my`', '') 37 | vim.keymap.set('c', '', '') 38 | 39 | -- Don't lose selection when shifting sidewards 40 | vim.keymap.set('x', '<', '', '>gv') 42 | 43 | vim.keymap.set('t', '', [[]]) 44 | vim.keymap.set('t', '', [[h]]) 45 | vim.keymap.set('t', '', [[j]]) 46 | vim.keymap.set('t', '', [[k]]) 47 | vim.keymap.set('t', '', [[l]]) 48 | 49 | vim.keymap.set('c', 'w!!', require('my.utils').sudo_write, { silent = true, desc = 'Sudo Write' }) 50 | 51 | vim.keymap.set('n', '', ':e **/', { desc = 'Backup file finder' }) 52 | 53 | vim.keymap.set('n', 'qq', 'q!', { desc = '[Q]uick [q]uit without saving' }) 54 | vim.keymap.set('n', 'qa', 'qa!', { desc = '[Q]uit [a]ll without saving' }) 55 | 56 | vim.keymap.set('n', 'w', 'update', { desc = '[w]rite file changes if any' }) 57 | 58 | -- Store relative line number jumps in the jumplist if they exceed a threshold. 59 | vim.keymap.set('n', 'k', function() 60 | return (vim.v.count > 5 and "m'" .. vim.v.count or '') .. 'gk' 61 | end, { expr = true }) 62 | vim.keymap.set('n', 'j', function() 63 | return (vim.v.count > 5 and "m'" .. vim.v.count or '') .. 'gj' 64 | end, { expr = true }) 65 | 66 | vim.keymap.set('n', 'fixformat', function() 67 | print(':e ++ff=dos followed by :set ff=unix') 68 | end, { desc = 'Tells Vim to read the file again, forcing dos file format. Repairs ^M characters' }) 69 | 70 | -- Diagnostics. Not necessarily related to LSP 71 | vim.keymap.set('n', 'kd', function() 72 | if vim.b.diagnostic_virtual_text_config ~= nil then 73 | vim.diagnostic.config { virtual_text = vim.b.diagnostic_virtual_text_config } 74 | vim.b.diagnostic_virtual_text_config = nil 75 | else 76 | vim.b.diagnostic_virtual_text_config = vim.diagnostic.config().virtual_text 77 | vim.diagnostic.config { virtual_text = false } 78 | end 79 | end, { desc = '[k]ill [d]iagnostic' }) 80 | 81 | vim.keymap.set('n', '.', function() 82 | vim.cmd.edit('%:p:h') 83 | end, { desc = 'edit .' }) 84 | vim.keymap.set('n', '-', function() 85 | vim.cmd.edit('%:p:h') 86 | end, { desc = 'edit . (vim-vinegar navigation)' }) 87 | vim.keymap.set('n', '/', function() 88 | vim.cmd.edit('.') 89 | end, { desc = 'edit root' }) 90 | 91 | vim.keymap.set('n', 'y.', function() 92 | local filename = vim.fn.expand('%:t') 93 | vim.fn.setreg('+', filename) 94 | require('my.utils').info("Copied '" .. filename .. "' to system clipboard") 95 | end, { desc = 'copy current filename to system clipboard' }) 96 | 97 | vim.keymap.set('n', 'y/', function() 98 | local filepath = vim.fn.expand('%:p:.') 99 | vim.fn.setreg('+', filepath) 100 | require('my.utils').info("Copied '" .. filepath .. "' to system clipboard") 101 | end, { desc = 'copy current file path to system clipboard (without the root dir)' }) 102 | 103 | vim.keymap.set('n', 'y,', function() 104 | local filepath = vim.fn.expand('%:p') 105 | vim.fn.setreg('+', filepath) 106 | require('my.utils').info("Copied '" .. filepath .. "' to system clipboard") 107 | end, { desc = 'copy current absolute filename to system clipboard' }) 108 | 109 | vim.keymap.set({ 'n', 'v' }, 'cf', function() 110 | require('my.format').format() 111 | end, { desc = 'format buffer' }) 112 | 113 | vim.keymap.set('n', ',x', 'write | :source %', { desc = 'source & e[x]ecute' }) 114 | 115 | vim.keymap.set('n', ',,', ',', { noremap = true, desc = 'repeat last f/F t/T command' }) 116 | 117 | vim.keymap.set('n', 'gV', '`[v`]', { desc = 'Select recently pasted text' }) 118 | 119 | -- Disable the Type :qa! message when pressing in normal mode 120 | vim.keymap.set('n', '', '', { noremap = true }) 121 | 122 | -- Automatically center the screen when searching 123 | vim.keymap.set('n', 'n', 'nzzzv', { desc = "Fwd search '/' or '?'" }) 124 | vim.keymap.set('n', 'N', 'Nzzzv', { desc = "Back search '/' or '?'" }) 125 | vim.keymap.set('c', '', function() 126 | return vim.fn.getcmdtype() == '/' and 'zzzv' or '' 127 | end, { expr = true }) 128 | 129 | vim.keymap.set({ 'n', 'x' }, '@', function() 130 | vim.cmd('noautocmd norm! ' .. vim.v.count1 .. '@' .. vim.fn.getcharstr()) 131 | end, { noremap = true }) 132 | 133 | vim.keymap.set('n', 'dd', function() 134 | if vim.api.nvim_get_current_line():match('^%s*$') then 135 | return '"_dd' 136 | else 137 | return 'dd' 138 | end 139 | end, { noremap = true, expr = true, desc = 'Smart delete' }) 140 | -------------------------------------------------------------------------------- /dot_config/git/config.tmpl: -------------------------------------------------------------------------------- 1 | [alias] 2 | # Amend the currently staged files to the latest commit 3 | amend = commit --amend --reuse-message=HEAD 4 | aa = add --all 5 | ap = add --patch 6 | authors = shortlog -e -s -n 7 | br = "for-each-ref --sort=-committerdate refs/heads/ --format='%(committerdate:short) %(authorname) %(refname:short)'" 8 | brs = "for-each-ref --sort=-committerdate --format='%(color:blue)%(authordate:relative)\t%(color:cyan)%(authorname)\t%(color:white)%(color:bold)%(refname:short)' refs/remotes" 9 | c = commit 10 | ci = commit -v 11 | cleanstate = "!f() { git reset --hard && git clean -fd; }; f" 12 | cleanup = "!git branch --merged | grep -v '\\*\\|master\\|develop' | xargs -n 1 git branch -d" 13 | cm = commit -m 14 | ca = commit -a 15 | co = checkout 16 | contributors = shortlog --summary --numbered 17 | # Show what files changed in current branch 18 | df = diff --name-only ; 19 | # Fetch all 20 | fa = fetch --all 21 | # Find branches containing commit 22 | fb = "!f() { git branch -a --contains $1; }; f" 23 | # Find commits by source code 24 | fc = "!f() { git log --pretty=format:'%C(yellow)%h %Cblue%ad %Creset%s%Cgreen [%cn] %Cred%d' --decorate --date=short -S$1; }; f" 25 | # Find commits by commit message 26 | fm = "!f() { git log --pretty=format:'%C(yellow)%h %Cblue%ad %Creset%s%Cgreen [%cn] %Cred%d' --decorate --date=short --grep=$1; }; f" 27 | # Find tags containing commit 28 | ft = "!f() { git describe --always --contains $1; }; f" 29 | fl = log -u 30 | # https://stackoverflow.com/questions/13630849/git-difference-between-assume-unchanged-and-skip-worktree 31 | ignore = update-index --skip-worktree 32 | unignore = update-index --no-skip-worktree 33 | # Switch to a branch, creating it if necessary 34 | lg = "log -m --simplify-merges --color --graph --pretty=format:'%Cred%h%Creset %s %Cgreen(%ar) %Cblue%an <%ae>%Creset' --abbrev-commit --date=relative" 35 | ll = "log --name-status --date=relative --pretty=format:\"%C(red)%h %C(reset)(%cd) %C(green)%an %Creset%s %C(yellow)%d%Creset\"" 36 | # Usually used for listing files managed by git bare repo 37 | ls = ls-tree --full-tree -r --name-only HEAD 38 | modified = ls-files -m 39 | pu = push 40 | # It will halt the push operation if someone has pushed to the same branch while you were working on it (and haven’t pulled any changes). 41 | pf = push --force-with-lease 42 | pup = "!git push -u origin $(git rev-parse --abbrev-ref HEAD)" 43 | remotes = remote -v 44 | rename-branch = branch -m 45 | s = status --short --branch 46 | st = status 47 | staged = diff --cached --ignore-submodules=dirty 48 | unpushed = "cherry -v" 49 | unstage = "restore --staged ." 50 | wip = "!git add . && git commit -m '[WIP] Just reset via git reset HEAD~1'" 51 | # https://stackoverflow.com/a/62303/3788603 52 | l = log --reverse --no-merges --stat @{1}.. 53 | # Diff changes against last pull 54 | lcrev = log --reverse --no-merges --stat @{1}.. 55 | dw = diff --color --color-words='[^[:space:]]|([[:alnum:]]|UTF_8_GUARD)+' 56 | go = "!f() { git checkout -b \"$1\" 2> /dev/null || git checkout \"$1\"; }; f" 57 | [core] 58 | excludesfile = ~/.gitignoreglobal 59 | # S = chop long lines (rather than wrap them onto next line) 60 | # 61 | # This in addition to the "iFMRX" that we get via LESS environment variable. 62 | # (In the absence LESS, Git would use "FRX".) 63 | # pager = less -S 64 | pager = delta 65 | [commit] 66 | template = ~/.gitmessage 67 | verbose = true 68 | [rerere] 69 | enabled = true 70 | [color] 71 | ui = auto 72 | [color "status"] 73 | added = green 74 | changed = yellow 75 | untracked = blue 76 | [color "interactive"] 77 | prompt = blue reverse 78 | [color "diff"] 79 | commit = green 80 | meta = yellow 81 | frag = cyan 82 | old = red 83 | new = green 84 | whitespace = red reverse 85 | [color "diff-highlight"] 86 | newhighlight = reverse 87 | newreset = noreverse 88 | oldhighlight = reverse 89 | oldreset = noreverse 90 | [diff] 91 | algorithm = histogram 92 | compactionHeuristic = true 93 | # Detect copies as well as renames 94 | renames = copies 95 | # Highlight code that has been moved 96 | colorMoved = dimmed-zebra 97 | # colorMoved = default 98 | [diff "bin"] 99 | # Use `hexdump` to diff binary files 100 | textconv = hexdump -v -C 101 | [difftool] 102 | prompt = false 103 | [difftool "vimdiff"] 104 | cmd = nvim -d $LOCAL $REMOTE -c '$wincmd w' -c 'wincmd J' 105 | [fetch] 106 | prune = true 107 | [filter "lfs"] 108 | clean = git-lfs clean -- %f 109 | process = git-lfs filter-process 110 | required = true 111 | smudge = git-lfs smudge -- %f 112 | [init] 113 | templatedir = ~/.git_template 114 | defaultBranch = main 115 | [interactive] 116 | # diffFilter = diff-highlight 117 | # diffFilter = delta --color-only 118 | diffFilter = delta --color-only --features=interactive 119 | [log] 120 | decorate = short 121 | [merge] 122 | conflictStyle = zdiff3 123 | ff = no 124 | commit = no 125 | summary = true 126 | # Include summaries of merged commits in newly created merge commit messages 127 | log = true 128 | [pager] 129 | # diff = less -iFMRSX --pattern='^(commit|diff)' 130 | # log = less -iFMRSX --pattern='^(commit|diff)' 131 | # show = less -iFMRSX --pattern='^(commit|diff)' 132 | # whatchanged = less -iFMRSX --pattern='^(commit|diff)' 133 | show-branch = true 134 | status = true 135 | [delta] 136 | navigate = true 137 | diff-so-fancy = true 138 | syntax-theme = none 139 | keep-plus-minus-markers = false 140 | commit-style = raw 141 | file-style = raw 142 | file-decoration-style = ul 143 | hunk-header-decoration-style = none 144 | hunk-header-style = raw 145 | minus-style = raw 146 | file-added-label = [+] 147 | file-copied-label = [C] 148 | file-modified-label = [M] 149 | file-removed-label = [-] 150 | file-renamed-label = [R] 151 | [pull] 152 | rebase = true 153 | [push] 154 | ; https://willi.am/blog/2014/08/12/the-dark-side-of-the-force-push/ 155 | default = simple 156 | ; https://stackoverflow.com/a/26438076/3788603 157 | followTags = true 158 | [rebase] 159 | autoStash = true 160 | autoSquash = true 161 | [user] 162 | email = "{{ .email }}" 163 | name = "{{ .name }}" 164 | [ghq] 165 | root = ~/Sources 166 | [include] 167 | path = ~/.gitconfig.local 168 | 169 | # vim:noexpandtab:ts=4:sw=4:ft=gitconfig:commentstring=#\ %s 170 | -------------------------------------------------------------------------------- /dot_config/nvim/lua/my/plugins/treesitter.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | 'nvim-treesitter/nvim-treesitter', 4 | event = { 'BufNewFile', 'BufReadPost', 'VeryLazy' }, 5 | cmd = { 'TSUpdate', 'TSInstall' }, 6 | opts = { 7 | ensure_installed = { 8 | 'bash', 9 | 'c', 10 | 'cmake', 11 | 'cpp', 12 | 'css', 13 | 'diff', 14 | 'fennel', 15 | 'fish', 16 | 'git_config', 17 | 'git_rebase', 18 | 'gitcommit', 19 | 'gitignore', 20 | 'gitattributes', 21 | 'glimmer', -- handlebars 22 | 'go', 23 | 'gotmpl', 24 | 'html', 25 | 'htmldjango', 26 | 'javascript', 27 | 'latex', 28 | 'lua', 29 | 'luadoc', 30 | 'markdown', 31 | 'markdown_inline', 32 | 'nix', 33 | 'python', 34 | 'regex', 35 | 'ruby', 36 | 'rust', 37 | 'scss', 38 | 'svelte', 39 | 'toml', 40 | 'tsx', 41 | 'typescript', 42 | 'vim', 43 | 'vimdoc', 44 | 'vue', 45 | 'xml', 46 | 'yaml', 47 | -- 'comment', 48 | -- 'json', 49 | -- 'jsonc', 50 | }, 51 | highlight = { 52 | enable = true, 53 | disable = function(lang, bufnr) 54 | return vim.b.large_buf 55 | end, 56 | additional_vim_regex_highlighting = false, 57 | }, 58 | incremental_selection = { 59 | enable = true, 60 | keymaps = { 61 | init_selection = '', 62 | node_incremental = '', 63 | scope_incremental = '', 64 | node_decremental = '', 65 | }, 66 | }, 67 | query_linter = { 68 | enable = true, 69 | use_virtual_text = true, 70 | lint_events = { 'BufWrite', 'CursorHold' }, 71 | }, 72 | playground = { 73 | enable = true, 74 | disable = {}, 75 | updatetime = 25, -- Debounced time for highlighting nodes in the playground from source code 76 | persist_queries = true, -- Whether the query persists across vim sessions 77 | keybindings = { 78 | toggle_query_editor = 'o', 79 | toggle_hl_groups = 'i', 80 | toggle_injected_languages = 't', 81 | toggle_anonymous_nodes = 'a', 82 | toggle_language_display = 'I', 83 | focus_language = 'f', 84 | unfocus_language = 'F', 85 | update = 'R', 86 | goto_node = '', 87 | show_help = '?', 88 | }, 89 | }, 90 | indent = { enable = false }, 91 | yati = { enable = true, default_lazy = true, default_fallback = 'auto' }, 92 | textobjects = { 93 | select = { 94 | enable = true, 95 | 96 | -- Automatically jump forward to textobj, similar to targets.vim 97 | lookahead = true, 98 | keymaps = { 99 | -- You can use the capture groups defined in textobjects.scm 100 | ['af'] = { query = '@function.outer', desc = 'Select around function' }, 101 | ['if'] = { query = '@function.inner', desc = 'Select inside function' }, 102 | ['ac'] = { query = '@class.outer', desc = 'Select around class' }, 103 | ['ic'] = { query = '@class.inner', desc = 'Select inside class' }, 104 | 105 | ['a='] = { query = '@assignment.outer', desc = 'Select outer part of an assignment' }, 106 | ['i='] = { query = '@assignment.inner', desc = 'Select inside part of an assignment' }, 107 | 108 | -- ['=l'] = { query = '@assignment.lhs', desc = 'Select left-hand side of assignment' }, 109 | -- ['=r'] = { query = '@assignment.rhs', desc = 'Select right-hand side of assignment' }, 110 | 111 | ['lhs'] = { query = '@assignment.lhs', desc = 'Select left-hand side of assignment' }, 112 | ['rhs'] = { query = '@assignment.rhs', desc = 'Select right-hand side of assignment' }, 113 | 114 | ['aa'] = { query = '@parameter.outer', desc = 'Select around parameter/argument' }, 115 | ['ia'] = { query = '@parameter.inner', desc = 'Select inside parameter/argument' }, 116 | 117 | ['ax'] = { query = '@conditional.outer', desc = 'Select outer part of a conditional' }, 118 | ['ix'] = { query = '@conditional.inner', desc = 'Select inner part of a conditional' }, 119 | }, 120 | }, 121 | move = { 122 | enable = true, 123 | set_jumps = true, -- whether to set jumps in the jumplist 124 | goto_next_start = { [']m'] = '@function.outer', [']]'] = '@class.outer' }, 125 | goto_next_end = { [']M'] = '@function.outer', [']['] = '@class.outer' }, 126 | goto_previous_start = { ['[m'] = '@function.outer', ['[['] = '@class.outer' }, 127 | goto_previous_end = { ['[M'] = '@function.outer', ['[]'] = '@class.outer' }, 128 | }, 129 | swap = { 130 | enable = true, 131 | swap_next = { ['>'] = '@parameter.inner' }, 132 | swap_previous = { ['<'] = '@parameter.outer' }, 133 | }, 134 | lsp_interop = { 135 | enable = true, 136 | peek_definition_code = { 137 | ['gD'] = '@function.outer', 138 | }, 139 | }, 140 | }, 141 | refactor = { 142 | navigation = { 143 | enable = true, 144 | }, 145 | smart_rename = { 146 | enable = true, 147 | keymaps = { 148 | smart_rename = 'rn', 149 | }, 150 | }, 151 | }, 152 | autopairs = { enable = true }, 153 | endwise = { enable = true }, 154 | }, 155 | config = function(_, opts) 156 | require('nvim-treesitter.configs').setup(opts) 157 | vim.schedule(function() 158 | local ts_info = require('nvim-treesitter.info') 159 | vim.api.nvim_create_autocmd('FileType', { 160 | pattern = ts_info.installed_parsers(), 161 | callback = function() 162 | vim.opt_local.foldmethod = 'expr' 163 | vim.opt_local.foldexpr = 'v:lua.vim.treesitter.foldexpr()' 164 | end, 165 | desc = 'Set foldexpr for treesitter parsers', 166 | }) 167 | end) 168 | end, 169 | build = ':TSUpdate', 170 | dependencies = { 171 | { 'nvim-treesitter/nvim-treesitter-textobjects' }, 172 | { 'RRethy/nvim-treesitter-endwise' }, 173 | { 'nvim-treesitter/nvim-treesitter-refactor' }, 174 | { 'yioneko/nvim-yati' }, 175 | }, 176 | }, 177 | } 178 | -------------------------------------------------------------------------------- /dot_config/nvim/lua/my/plugins/integrations.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | 'L3MON4D3/LuaSnip', 4 | config = function() 5 | require('luasnip.loaders.from_vscode').lazy_load() 6 | end, 7 | keys = { 8 | { 9 | '', 10 | function() 11 | require('luasnip').expand() 12 | end, 13 | mode = 'i', 14 | }, 15 | }, 16 | -- build = 'make install_jsregexp', 17 | dependencies = 'rafamadriz/friendly-snippets', 18 | }, 19 | { 20 | 'stevearc/conform.nvim', 21 | event = 'BufReadPost', 22 | opts = { 23 | formatters = { 24 | kulala = { 25 | command = 'kulala-fmt', 26 | args = { '$FILENAME' }, 27 | stdin = false, 28 | }, 29 | }, 30 | formatters_by_ft = { 31 | lua = { 'stylua' }, 32 | javascript = { 'prettierd', 'eslint_d' }, 33 | -- javascript = { 'eslint_d', 'prettierd' }, 34 | python = { 'ruff_format', 'ruff_fix', 'ruff_organize_imports' }, 35 | fish = { 'fish_indent' }, 36 | json = { 'jq' }, 37 | jsonc = { 'fixjson' }, 38 | htmldjango = { 'djlint' }, 39 | toml = { 'taplo' }, 40 | http = { 'kulala' }, 41 | go = { 'goimports', 'gofmt', lsp_format = 'fallback' }, 42 | templ = { 'templ' }, 43 | }, 44 | format_on_save = function(bufnr) 45 | if not require('my.format').is_enabled(bufnr) then 46 | return nil 47 | end 48 | 49 | return { timeout_ms = 500, lsp_fallback = true } 50 | end, 51 | }, 52 | }, 53 | { 54 | 'mfussenegger/nvim-lint', 55 | event = { 'BufReadPost', 'BufNewFile' }, 56 | config = function() 57 | local lint = require('lint') 58 | 59 | lint.linters_by_ft = { 60 | fish = { 'fish' }, 61 | -- Used ruff 62 | -- python = { 'ruff' }, 63 | dockerfile = { 'hadolint' }, 64 | htmldjango = { 'djlint' }, 65 | } 66 | end, 67 | }, 68 | { 69 | 'tpope/vim-fugitive', 70 | keys = { 71 | { 'G', mode = 'c' }, 72 | { 'gs', 'Git', desc = 'Git' }, 73 | { 'gv', 'Gvdiffsplit', desc = 'Git' }, 74 | }, 75 | }, 76 | { 77 | 'TimUntersberger/neogit', 78 | cmd = 'Neogit', 79 | keys = { 80 | { 'gg', 'Neogit', desc = 'Neogit' }, 81 | }, 82 | opts = { 83 | kind = 'split_above', 84 | integrations = { diffview = true }, 85 | disable_commit_confirmation = true, 86 | sections = { 87 | untracked = { 88 | folded = true, 89 | }, 90 | }, 91 | mappings = { 92 | status = { 93 | ['='] = 'Toggle', 94 | }, 95 | }, 96 | }, 97 | dependencies = { 98 | 'nvim-lua/plenary.nvim', 99 | 'sindrets/diffview.nvim', 100 | }, 101 | }, 102 | { 103 | 'linrongbin16/gitlinker.nvim', 104 | opts = {}, 105 | keys = { 106 | { 'gy', 'GitLink', mode = { 'n', 'v' }, desc = 'Yank git link' }, 107 | { 'gY', 'GitLink!', mode = { 'n', 'v' }, desc = 'Open git link' }, 108 | }, 109 | }, 110 | { 111 | 'lewis6991/gitsigns.nvim', 112 | event = { 'BufReadPost', 'BufNewFile' }, 113 | opts = function() 114 | local gs = require('gitsigns') 115 | return { 116 | signs = { 117 | add = { text = '+' }, 118 | change = { text = '~' }, 119 | delete = { text = '_' }, 120 | topdelete = { text = '‾' }, 121 | changedelete = { text = '~' }, 122 | }, 123 | signcolumn = false, 124 | current_line_blame = false, 125 | current_line_blame_opts = { 126 | virt_text = true, 127 | virt_text_pos = 'eol', 128 | delay = 500, 129 | }, 130 | on_attach = function(bufnr) 131 | vim.keymap.set('n', ']c', function() 132 | if vim.wo.diff then 133 | vim.cmd.normal { ']c', bang = true } 134 | else 135 | gs.nav_hunk('next') 136 | vim.schedule(function() 137 | gs.preview_hunk_inline() 138 | end) 139 | end 140 | end, { buffer = bufnr, desc = 'Next Hunk' }) 141 | 142 | vim.keymap.set('n', '[c', function() 143 | if vim.wo.diff then 144 | vim.cmd.normal { '[c', bang = true } 145 | else 146 | gs.nav_hunk('prev') 147 | vim.schedule(function() 148 | gs.preview_hunk_inline() 149 | end) 150 | end 151 | end, { buffer = bufnr, desc = 'Prev Hunk' }) 152 | 153 | -- Actions 154 | vim.keymap.set('n', 'hs', gs.stage_hunk) 155 | vim.keymap.set('n', 'hr', gs.reset_hunk) 156 | vim.keymap.set('v', 'hs', function() 157 | gs.stage_hunk { vim.fn.line('.'), vim.fn.line('v') } 158 | end) 159 | vim.keymap.set('v', 'hr', function() 160 | gs.reset_hunk { vim.fn.line('.'), vim.fn.line('v') } 161 | end) 162 | vim.keymap.set('n', 'hS', gs.stage_buffer) 163 | vim.keymap.set('n', 'hu', gs.undo_stage_hunk) 164 | vim.keymap.set('n', 'hR', gs.reset_buffer) 165 | vim.keymap.set('n', 'hb', function() 166 | gs.blame_line { full = true } 167 | end) 168 | 169 | -- Commented this out since it conflicts with some of my mappings that starts 170 | -- with t. Will come back to this later 171 | vim.keymap.set('n', 'htb', gs.toggle_current_line_blame) 172 | vim.keymap.set('n', 'htd', gs.toggle_deleted) 173 | vim.keymap.set('n', 'hd', gs.diffthis) 174 | vim.keymap.set('n', 'hD', function() 175 | gs.diffthis('~') 176 | end) 177 | 178 | vim.keymap.set({ 'o', 'x' }, 'ih', ':Gitsigns select_hunk', { silent = true }) 179 | end, 180 | } 181 | end, 182 | }, 183 | { 184 | 'kristijanhusak/vim-dadbod-ui', 185 | dependencies = { 186 | { 'tpope/vim-dadbod', lazy = true }, 187 | { 'kristijanhusak/vim-dadbod-completion', ft = { 'sql', 'mysql', 'plsql' }, lazy = true }, 188 | }, 189 | cmd = { 190 | 'DBUI', 191 | 'DBUIToggle', 192 | 'DBUIAddConnection', 193 | 'DBUIFindBuffer', 194 | }, 195 | init = function() 196 | -- Your DBUI configuration 197 | vim.g.db_ui_use_nerd_fonts = 1 198 | end, 199 | keys = { 200 | { 201 | 'D', 202 | function() 203 | vim.cmd('DBUIToggle') 204 | end, 205 | }, 206 | }, 207 | }, 208 | } 209 | -------------------------------------------------------------------------------- /dot_config/nvim/lua/my/options.lua: -------------------------------------------------------------------------------- 1 | -- Shift 2 spaces when pressing tab 2 | vim.opt.tabstop = 2 3 | -- Shift 2 spaces when pressing < or > 4 | vim.opt.shiftwidth = 2 5 | -- Round indent spacing with the multiples of shiftwidth 6 | vim.opt.shiftround = true 7 | -- Use spaces instead of tabs 8 | vim.opt.expandtab = true 9 | -- Indents 10 | vim.opt.autoindent = true 11 | -- Make search case insensitive 12 | vim.opt.ignorecase = true 13 | -- .. unless it contains atleast one capital letter 14 | vim.opt.smartcase = true 15 | -- Turn on relative numbers 16 | vim.opt.relativenumber = true 17 | -- .. together with number 18 | vim.opt.number = true 19 | -- Allow vim to set title of the terminal 20 | vim.opt.title = true 21 | -- Change list characters 22 | vim.opt.list = true 23 | vim.opt.listchars = { 24 | tab = '▷⋯', -- WHITE RIGHT-POINTING TRIANGLE (U+25B7, UTF-8: E2 96 B7) + MIDLINE HORIZONTAL ELLIPSIS (U+22EF, UTF-8: E2 8B AF) 25 | trail = '·', 26 | -- eol = '↲', 27 | -- eol = '↴', 28 | nbsp = '☠', 29 | precedes = '…', 30 | extends = '…', 31 | conceal = '┊', 32 | } 33 | -- Hide buffer when switching to other files 34 | vim.opt.hidden = true 35 | -- Prefer sh for shell-related tasks 36 | vim.opt.shell = 'sh' 37 | -- Disable annoying swapfiles 38 | vim.opt.swapfile = false 39 | -- Use system clipboard 40 | vim.opt.clipboard = 'unnamedplus' 41 | -- Search relative to current file and directory 42 | vim.opt.path = '.,**' 43 | -- Split right by default 44 | vim.opt.splitright = true 45 | -- Split below by default 46 | vim.opt.splitbelow = true 47 | -- Always show tabs 48 | vim.opt.showtabline = 2 49 | -- Don't wrap words 50 | vim.opt.wrap = false 51 | -- Show highlight when performing substitutions 52 | vim.opt.inccommand = 'split' 53 | -- Enable mouse coz why not? 54 | vim.opt.mouse = 'nivcr' 55 | -- Use ripgrep instead of grep 56 | vim.opt.grepprg = 'rg --vimgrep --smart-case' 57 | vim.opt.grepformat = '%f:%l:%c:%m' 58 | 59 | vim.opt.shortmess = vim.opt.shortmess 60 | + 'a' -- use abbreviations in messages eg. `[RO]` instead of `[readonly]` 61 | + 'I' -- Disable intro message 62 | + 'c' -- Don't give |ins-completion-menu| messages 63 | 64 | -- Formatting 65 | vim.opt.formatoptions = vim.opt.formatoptions 66 | - 'a' -- Auto formatting is BAD. 67 | - 't' -- Don't auto format my code. I got linters for that. 68 | + 'c' -- In general, I like it when comments respect textwidth 69 | + 'q' -- Allow formatting comments w/ gq 70 | - 'o' -- O and o, don't continue comments 71 | + 'r' -- But do continue when pressing enter. 72 | + 'n' -- Indent past the formatlistpat, not underneath it. 73 | + 'j' -- Auto-remove comments if possible. 74 | - '2' -- I'm not in gradeschool anymore 75 | 76 | -- Pums 77 | vim.opt.completeopt = { 'menu', 'menuone', 'noselect' } 78 | vim.opt.pumheight = 15 79 | -- Always show sign columns 80 | vim.opt.signcolumn = 'number' 81 | -- Having longer update time leads to noticeable delays and poor UX 82 | vim.opt.updatetime = 250 83 | -- Start scrolling when we're 10 lines below 84 | vim.opt.scrolloff = 10 85 | -- and 3 lines from the side 86 | vim.opt.sidescrolloff = 3 87 | -- Dislay --INSERT-- 88 | vim.opt.showmode = true 89 | -- Enable backups 90 | vim.opt.backup = true 91 | -- Ensure filename uniqueness with // 92 | vim.opt.backupdir = { vim.fn.stdpath('data') .. '/backup//' } 93 | -- Enable persistent undo 94 | vim.opt.undofile = true 95 | 96 | vim.opt.wildmenu = true 97 | vim.opt.wildcharm = 26 -- Equivalent of 98 | vim.opt.wildmode = { 'longest', 'full' } 99 | vim.opt.wildoptions = 'pum' 100 | 101 | -- Number of folds available when starting to edit files 102 | -- Set to 0 all folds closed, 1 some folds closed, 99 no folds closed 103 | vim.opt.foldlevelstart = 99 104 | -- Use indent by default when tresesitter folds are not available 105 | vim.opt.foldmethod = 'indent' 106 | vim.opt.fillchars = { 107 | diff = '∙', -- BULLET OPERATOR (U+2219, UTF-8: E2 88 99) 108 | eob = ' ', -- NO-BREAK SPACE (U+00A0, UTF-8: C2 A0) to suppress ~ at EndOfBuffer 109 | fold = '·', -- MIDDLE DOT (U+00B7, UTF-8: C2 B7) 110 | vert = '┃', -- BOX DRAWINGS HEAVY VERTICAL (U+2503, UTF-8: E2 94 83) 111 | } 112 | 113 | vim.opt.fillchars:append { 114 | horiz = '━', 115 | horizup = '┻', 116 | horizdown = '┳', 117 | vert = '┃', 118 | vertleft = '┨', 119 | vertright = '┣', 120 | verthoriz = '╋', 121 | } 122 | 123 | -- Maximum number of nesting of folds for indend and syntax method 124 | vim.opt.foldnestmax = 4 125 | --Number of screenlines above which a fold can be displayed closed 126 | vim.opt.foldminlines = 2 127 | 128 | -- Used when `wrap` is enabled 129 | vim.opt.breakindent = true 130 | -- Make it so long that lines wrap smartly 131 | vim.opt.linebreak = true 132 | vim.opt.showbreak = ' ↪ ' 133 | 134 | -- Enable 24-bit RGB color 135 | vim.opt.termguicolors = true 136 | 137 | -- Prefer dark theme by default if NVIM_BACKGROUND is not set 138 | vim.opt.background = vim.env.NVIM_BACKGROUND or 'dark' 139 | 140 | -- Do not highlight on long lines 141 | vim.opt.synmaxcol = 512 142 | 143 | -- Use 1 Global statusline 144 | vim.opt.laststatus = 3 145 | 146 | -- Having `laststatus=3` makes other windows filename not get displayed 147 | -- so we will simulate the filename via winbar 148 | vim.opt.winbar = vim.opt.winbar 149 | + ' ' 150 | + "%{expand('%') == '' ? '[No Name]' : pathshorten(expand('%:~:.'))} " 151 | + '%m ' 152 | + '%{&readonly ? "󰍁 ":""}' 153 | 154 | -- Only show tabline if there are more than 1 tab 155 | vim.opt.showtabline = 1 156 | 157 | -- Automatically execute .nvim.lua files 158 | vim.opt.exrc = true 159 | 160 | -- Prevent moving windows around 161 | vim.opt.splitkeep = 'screen' 162 | 163 | -- Always ask for confirmation when closing unsaved buffers 164 | vim.opt.confirm = true 165 | 166 | -- Make vim diff better 167 | -- https://www.reddit.com/r/neovim/comments/1ihpvaf/the_linematch_diffopt_makes_builtin_diff_so_sweat/maz7fmu/ 168 | vim.opt.diffopt = 'filler,internal,closeoff,algorithm:histogram,context:5,linematch:60' 169 | 170 | -- Use as the leader key 171 | vim.g.mapleader = ' ' 172 | vim.g.loaded_netrw = 1 173 | vim.g.loaded_netrwPlugin = 1 174 | 175 | -- Diagnostic symbols in the sign column (gutter) 176 | -- vim.fn.sign_define('DiagnosticSignError', { text = '✖', texthl = 'DiagnosticSignError', numhl = '' }) 177 | -- vim.fn.sign_define('DiagnosticSignHint', { text = '➤', texthl = 'DiagnosticSignHint', numhl = '' }) 178 | -- vim.fn.sign_define('DiagnosticSignInfo', { text = '', texthl = 'DiagnosticSignInfo', numhl = '' }) 179 | -- vim.fn.sign_define('DiagnosticSignWarn', { text = '⚠', texthl = 'DiagnosticSignWarn', numhl = '' }) 180 | 181 | vim.diagnostic.config { 182 | underline = true, 183 | update_in_insert = false, 184 | virtual_text = { spacing = 2, prefix = ' ●' }, 185 | severity_sort = true, 186 | float = { 187 | source = true, 188 | }, 189 | signs = { 190 | text = { 191 | [vim.diagnostic.severity.INFO] = '', 192 | [vim.diagnostic.severity.ERROR] = '✖', 193 | [vim.diagnostic.severity.HINT] = '➤', 194 | [vim.diagnostic.severity.WARN] = '⚠', 195 | }, 196 | }, 197 | } 198 | -------------------------------------------------------------------------------- /dot_config/nvim/lua/my/plugins/pde.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 'tpope/vim-surround', event = 'VeryLazy' }, 3 | { 'tpope/vim-repeat', event = 'VeryLazy' }, 4 | { 'tpope/vim-unimpaired', keys = { 'yo', '[', ']' } }, 5 | { 'tpope/vim-rsi', event = 'InsertEnter' }, 6 | { 'tpope/vim-abolish', event = 'VeryLazy' }, 7 | { 8 | 'mbbill/undotree', 9 | init = function() 10 | vim.g.undotree_HighlightChangedWithSign = 0 11 | vim.g.undotree_WindowLayout = 4 12 | vim.g.undotree_SetFocusWhenToggle = 1 13 | end, 14 | keys = { 15 | { 'u', 'UndotreeToggle', desc = 'Undotree Toggle' }, 16 | }, 17 | }, 18 | { 19 | 'kevinhwang91/nvim-fundo', 20 | event = { 'BufWritePre' }, 21 | dependencies = { 'kevinhwang91/promise-async' }, 22 | config = function() 23 | require('fundo').install() 24 | end, 25 | }, 26 | { 27 | 'echasnovski/mini.indentscope', 28 | event = { 'BufReadPost', 'BufNewFile' }, 29 | version = false, 30 | init = function() 31 | vim.g.miniindentscope_disable = true 32 | end, 33 | config = function() 34 | require('mini.indentscope').setup { 35 | draw = { 36 | delay = 10, 37 | }, 38 | symbol = '│', 39 | options = { try_as_border = true }, 40 | } 41 | end, 42 | }, 43 | { 44 | 'echasnovski/mini.hipatterns', 45 | event = { 'BufReadPost', 'BufNewFile' }, 46 | version = false, 47 | config = function() 48 | local hipatterns = require('mini.hipatterns') 49 | hipatterns.setup { 50 | highlighters = { 51 | -- Highlight standalone 'FIXME', 'HACK', 'TODO', 'NOTE' 52 | fixme = { pattern = '%f[%w]()FIXME()%f[%W]', group = 'MiniHipatternsFixme' }, 53 | hack = { pattern = '%f[%w]()HACK()%f[%W]', group = 'MiniHipatternsHack' }, 54 | todo = { pattern = '%f[%w]()TODO()%f[%W]', group = 'MiniHipatternsTodo' }, 55 | note = { pattern = '%f[%w]()NOTE()%f[%W]', group = 'MiniHipatternsNote' }, 56 | coco = { pattern = '%f[%w]()COCO()%f[%W]', group = 'Debug' }, 57 | -- Highlight hex color strings (`#rrggbb`) using that color 58 | hex_color = hipatterns.gen_highlighter.hex_color(), 59 | }, 60 | } 61 | end, 62 | }, 63 | { 64 | 'shellRaining/hlchunk.nvim', 65 | config = function() 66 | require('hlchunk').setup { 67 | chunk = { 68 | enable = false, 69 | }, 70 | indent = { 71 | enable = false, 72 | }, 73 | line_num = { 74 | enable = false, 75 | }, 76 | blank = { 77 | enable = false, 78 | }, 79 | } 80 | end, 81 | keys = { 82 | { 83 | 'yoH', 84 | function() 85 | local utils = require('my.utils') 86 | local chunk_mod = require('hlchunk.mods.chunk') {} 87 | 88 | vim.b.hlindent_t_state = not vim.b.hlindent_t_state 89 | 90 | if vim.b.hlindent_t_state then 91 | chunk_mod:enable() 92 | utils.info('enabled hlchunk', 'Toggle') 93 | else 94 | chunk_mod:disable() 95 | utils.warn('disabled hlchunk', 'Toggle') 96 | end 97 | end, 98 | desc = 'Toggle hlchunk', 99 | }, 100 | }, 101 | }, 102 | { 103 | 'MagicDuck/grug-far.nvim', 104 | opts = { 105 | keymaps = { 106 | replace = 'R', 107 | }, 108 | headerMaxWidth = 80, 109 | startInInsertMode = false, 110 | windowCreationCommand = 'tabnew', 111 | transient = true, 112 | }, 113 | cmd = 'GrugFar', 114 | keys = { 115 | { 'S', 'GrugFar', desc = 'GrugFar' }, 116 | { 117 | 'sr', 118 | function() 119 | local grug = require('grug-far') 120 | local ext = vim.bo.buftype == '' and vim.fn.expand('%:e') 121 | grug.grug_far { 122 | transient = true, 123 | prefills = { 124 | filesFilter = ext and ext ~= '' and '*.' .. ext or nil, 125 | }, 126 | } 127 | end, 128 | mode = { 'n', 'v' }, 129 | desc = 'Search and Replace', 130 | }, 131 | }, 132 | }, 133 | { 'tversteeg/registers.nvim', event = 'VeryLazy' }, 134 | { 135 | 'gbprod/yanky.nvim', 136 | event = { 'BufReadPost' }, 137 | keys = { 'y', '', '', 'yy' }, 138 | config = function() 139 | require('yanky').setup { 140 | ring = { 141 | history_length = 100, 142 | storage = 'shada', 143 | sync_with_numbered_registers = true, 144 | cancel_event = 'update', 145 | ignore_registers = { '_' }, 146 | update_register_on_cycle = false, 147 | }, 148 | system_clipboard = { 149 | sync_with_ring = true, 150 | }, 151 | preserve_cursor_position = { 152 | enabled = true, 153 | }, 154 | highlight = { 155 | on_put = true, 156 | on_yank = true, 157 | timer = 200, 158 | }, 159 | } 160 | 161 | vim.keymap.set({ 'n', 'x' }, 'y', '(YankyYank)') 162 | vim.keymap.set({ 'n', 'x' }, 'p', '(YankyPutAfter)') 163 | vim.keymap.set({ 'n', 'x' }, 'P', '(YankyPutBefore)') 164 | vim.keymap.set({ 'n', 'x' }, 'gp', '(YankyGPutAfter)') 165 | vim.keymap.set({ 'n', 'x' }, 'gP', '(YankyGPutBefore)') 166 | vim.keymap.set({ 'n', 'x' }, 'gP', '(YankyGPutBefore)') 167 | 168 | vim.keymap.set('n', 'yy', 'YankyRingHistory') 169 | 170 | -- The unimpaired y feels awkard to press when using colemak layout 171 | vim.keymap.set('n', '', '(YankyPreviousEntry)') 172 | vim.keymap.set('n', '', '(YankyNextEntry)') 173 | end, 174 | }, 175 | { 176 | 'yujinyuz/vms.nvim', 177 | event = 'VeryLazy', 178 | opts = {}, 179 | dev = true, 180 | }, 181 | { 182 | 'yujinyuz/gitpad.nvim', 183 | dev = true, 184 | config = function() 185 | require('gitpad').setup { 186 | dir = '~/Sync/notes/gitpad', 187 | border = 'rounded', 188 | on_attach = function(bufnr) 189 | vim.api.nvim_buf_set_keymap(bufnr, 'n', 'q', 'silent! wq', { noremap = true, silent = true }) 190 | vim.opt_local.textwidth = 100 191 | end, 192 | } 193 | end, 194 | keys = { 195 | { 196 | 'pp', 197 | function() 198 | require('gitpad').toggle_gitpad { title = '󰊢 gitpad' } 199 | end, 200 | desc = 'gitpad project', 201 | }, 202 | { 203 | 'pb', 204 | function() 205 | require('gitpad').toggle_gitpad_branch() 206 | end, 207 | desc = 'gitpad branch', 208 | }, 209 | { 210 | 'pn', 211 | function() 212 | local date_filename = 'daily-' .. os.date('%Y-%m-%d.md') 213 | require('gitpad').toggle_gitpad { filename = date_filename, title = 'Daily Notes' } 214 | end, 215 | desc = 'gitpad daily notes', 216 | }, 217 | { 218 | 'pf', 219 | function() 220 | local filename = vim.fn.bufname() 221 | if filename == '' then 222 | vim.notify('empty bufname') 223 | return 224 | end 225 | filename = filename .. '.md' 226 | require('gitpad').toggle_gitpad { filename = filename } 227 | end, 228 | desc = 'gitpad per file notes', 229 | }, 230 | }, 231 | }, 232 | { 233 | 'echasnovski/mini.align', 234 | event = { 'BufReadPost', 'BufNewFile' }, 235 | version = false, 236 | opts = {}, 237 | }, 238 | } 239 | -------------------------------------------------------------------------------- /dot_config/nvim/lua/my/plugins/lspconfig.lua: -------------------------------------------------------------------------------- 1 | local lsp_config = function() 2 | -- Setup neoconfig before lspconfig 3 | local has_neoconf, neoconf = pcall(require, 'neoconf') 4 | if has_neoconf then 5 | neoconf.setup {} 6 | end 7 | 8 | -- Set up completion using nvim_cmp with LSP source 9 | local common_capabilities = require('cmp_nvim_lsp').default_capabilities() 10 | common_capabilities.textDocument.foldingRange = { 11 | dynamicRegistration = false, 12 | lineFoldingOnly = true, 13 | } 14 | 15 | local common_on_init = function(client, _) 16 | -- Disabled due to https://github.com/neovim/neovim/issues/23164 17 | -- I've been experiencing this annoying issue where there is a slight delay of applying 18 | -- highlights when opening certain files: 19 | -- * lua suddenly changes highlights for global variables 20 | -- * python (pyright and basedpyright) changes highlights and sometimes italicizes import 21 | -- statements. 22 | -- I do not want this. Just let treesitter perform the highlighting for now. 23 | client.server_capabilities.semanticTokensProvider = false 24 | end 25 | 26 | local common_on_attach_handler = function(client, bufnr) 27 | -- +lsp 28 | vim.keymap.set('n', 'grn', function() 29 | vim.lsp.buf.rename() 30 | end, { buffer = bufnr, desc = 'vim.lsp.buf.rename()' }) 31 | 32 | vim.keymap.set({ 'n', 'x' }, 'gra', function() 33 | vim.lsp.buf.code_action() 34 | end, { buffer = bufnr, desc = 'vim.lsp.buf.code_action()' }) 35 | 36 | vim.keymap.set('n', 'grr', function() 37 | vim.lsp.buf.references() 38 | end, { buffer = bufnr, desc = 'vim.lsp.buf.references()' }) 39 | 40 | vim.keymap.set('i', '', function() 41 | vim.lsp.buf.signature_help() 42 | end, { buffer = bufnr, desc = 'vim.lsp.buf.signature_help()' }) 43 | 44 | vim.keymap.set('n', 'gd', vim.lsp.buf.definition, { buffer = bufnr, desc = '[g]oto [d]efinition' }) 45 | vim.keymap.set('n', 'gI', vim.lsp.buf.implementation, { buffer = bufnr, desc = '[g]oto [I]mplementation' }) 46 | vim.keymap.set('i', '', vim.lsp.buf.signature_help, { buffer = bufnr, desc = 'code [s]ignature help' }) 47 | 48 | if client.server_capabilities.definitionProvider ~= false then 49 | vim.opt_local.tagfunc = 'v:lua.vim.lsp.tagfunc' 50 | end 51 | 52 | if client.server_capabilities.documentSymbolProvider then 53 | local has_navic, navic = pcall(require, 'nvim-navic') 54 | if has_navic then 55 | navic.attach(client, bufnr) 56 | end 57 | end 58 | end 59 | 60 | -- Server config 61 | local servers = { 62 | pyright = { 63 | enabled = false, 64 | settings = { 65 | pyright = { 66 | disableOrganizeImports = true, 67 | }, 68 | python = { 69 | analysis = { 70 | -- Ignore all files for analysis to exclusively use Ruff for linting 71 | ignore = { '*' }, 72 | }, 73 | }, 74 | }, 75 | }, 76 | basedpyright = { 77 | enabled = true, 78 | settings = { 79 | basedpyright = { 80 | disableOrganizeImports = true, 81 | -- https://github.com/DetachHead/basedpyright/issues/203 82 | typeCheckingMode = 'off', 83 | }, 84 | }, 85 | }, 86 | jedi_language_server = { 87 | enabled = false, 88 | init_options = { 89 | completion = { 90 | disableSnippets = true, 91 | }, 92 | }, 93 | }, 94 | ruff = { 95 | enabled = true, 96 | on_attach = function(client, bufnr) 97 | if client.name ~= 'ruff' then 98 | return 99 | end 100 | common_on_attach_handler(client, bufnr) 101 | client.server_capabilities.hoverProvider = false 102 | 103 | -- Create ruff commands 104 | vim.api.nvim_create_user_command('RuffAutoFix', function() 105 | vim.lsp.buf.execute_command { 106 | command = 'ruff.applyAutofix', 107 | arguments = { 108 | { uri = vim.uri_from_bufnr(bufnr) }, 109 | }, 110 | } 111 | end, { desc = 'Ruff: Fix all auto-fixable problems' }) 112 | 113 | vim.api.nvim_create_user_command('RuffOrganizeImports', function() 114 | vim.lsp.buf.execute_command { 115 | command = 'ruff.applyOrganizeImports', 116 | arguments = { 117 | { uri = vim.uri_from_bufnr(bufnr) }, 118 | }, 119 | } 120 | end, { desc = 'Ruff: Format imports' }) 121 | end, 122 | }, 123 | gopls = {}, 124 | html = {}, 125 | cssls = {}, 126 | emmet_language_server = {}, 127 | tailwindcss = {}, 128 | jsonls = {}, 129 | ts_ls = {}, 130 | volar = {}, 131 | lua_ls = { 132 | Lua = { 133 | workspace = { checkThirdParty = false }, 134 | telemetry = { enable = false }, 135 | completion = { 136 | callSnippet = 'Disable', 137 | }, 138 | codelens = { 139 | enable = true, 140 | }, 141 | }, 142 | }, 143 | taplo = {}, 144 | prosemd_lsp = {}, 145 | bashls = {}, 146 | marksman = {}, 147 | } 148 | 149 | local common_options = { 150 | enabled = true, 151 | on_init = common_on_init, 152 | on_attach = common_on_attach_handler, 153 | capabilities = common_capabilities, 154 | flags = { 155 | debounce_text_changes = 500, -- 150 seems to be the default by idk what this implies 156 | }, 157 | } 158 | 159 | local mason_lspconfig = require('mason-lspconfig') 160 | local setup_server_handler = function(server_name) 161 | if servers[server_name] == nil then 162 | return 163 | end 164 | 165 | local server_opts = vim.tbl_deep_extend('force', common_options, servers[server_name] or {}) 166 | 167 | if type(server_opts.capabilities) == 'function' then 168 | server_opts.capabilities = server_opts.capabilities() 169 | end 170 | 171 | if server_opts.enabled ~= false then 172 | require('lspconfig')[server_name].setup(server_opts) 173 | end 174 | end 175 | 176 | local ensure_installed = vim.tbl_filter(function(server_name) 177 | -- Checking whether it is ~= false since severs can be configured to have empty values 178 | return servers[server_name].enabled ~= false 179 | end, vim.tbl_keys(servers)) 180 | 181 | mason_lspconfig.setup { 182 | ensure_installed = ensure_installed, 183 | handlers = { setup_server_handler }, 184 | } 185 | end 186 | 187 | return { 188 | { 189 | 'neovim/nvim-lspconfig', 190 | event = { 'BufReadPre', 'BufNewFile' }, 191 | config = lsp_config, 192 | dependencies = { 193 | { 'folke/neoconf.nvim', cmd = 'Neoconf', config = false }, 194 | { 'folke/neodev.nvim', opts = {} }, 195 | { 196 | 'SmiteshP/nvim-navic', 197 | lazy = true, 198 | opts = { 199 | lazy_update_context = true, 200 | }, 201 | keys = { 202 | { 203 | '', 204 | function() 205 | print(require('nvim-navic').get_location()) 206 | end, 207 | desc = 'Show current location', 208 | }, 209 | }, 210 | }, 211 | 'williamboman/mason.nvim', 212 | 'williamboman/mason-lspconfig.nvim', 213 | }, 214 | }, 215 | { 216 | 'williamboman/mason.nvim', 217 | cmd = 'Mason', 218 | build = ':MasonUpdate', 219 | opts = { 220 | ensure_installed = { 221 | 'black', 222 | 'codespell', 223 | 'cspell', 224 | 'djlint', 225 | 'eslint_d', 226 | 'fixjson', 227 | 'hadolint', 228 | 'prettierd', 229 | 'stylua', 230 | 'taplo', 231 | 'write-good', 232 | }, 233 | }, 234 | config = function(_, opts) 235 | require('mason').setup(opts) 236 | local mr = require('mason-registry') 237 | 238 | local function ensure_installed() 239 | for _, tool in ipairs(opts.ensure_installed) do 240 | local p = mr.get_package(tool) 241 | if not p:is_installed() then 242 | p:install() 243 | end 244 | end 245 | end 246 | 247 | mr.refresh(ensure_installed) 248 | end, 249 | }, 250 | } 251 | -------------------------------------------------------------------------------- /dot_config/nvim/lua/my/plugins/completion.lua: -------------------------------------------------------------------------------- 1 | vim.g.nvim_cmp_t_state = true 2 | vim.api.nvim_set_hl(0, 'CmpGhostText', { link = 'Comment', default = true }) 3 | 4 | vim.keymap.set('n', 'yoq', function() 5 | vim.g.nvim_cmp_t_state = not vim.g.nvim_cmp_t_state 6 | 7 | if vim.g.nvim_cmp_t_state then 8 | require('my.utils').info('enabled autocomplete', 'Toggle') 9 | else 10 | require('my.utils').warn('disabled autocomplete', 'Toggle') 11 | end 12 | end, { desc = 'toggle autocomplete' }) 13 | 14 | local cmp_config = function() 15 | local cmp = require('cmp') 16 | 17 | cmp.setup { 18 | enabled = function() 19 | if vim.g.nvim_cmp_t_state and vim.api.nvim_get_option_value('buftype', { buf = 0 }) ~= 'prompt' then 20 | return true 21 | end 22 | 23 | return false 24 | end, 25 | preselect = cmp.PreselectMode.None, 26 | view = { 27 | entries = { 28 | follow_cursor = true, 29 | }, 30 | }, 31 | sources = cmp.config.sources { 32 | { name = 'nvim_lsp' }, 33 | { 34 | name = 'buffer', 35 | max_item_count = 10, 36 | option = { 37 | show_source = true, 38 | get_bufnrs = function() 39 | return vim.tbl_filter(function(bufnr) 40 | return vim.fn.buflisted(bufnr) == 1 41 | end, vim.api.nvim_list_bufs()) 42 | end, 43 | }, 44 | }, 45 | }, 46 | window = { 47 | documentation = cmp.config.window.bordered(), 48 | }, 49 | sorting = { 50 | comparators = { 51 | cmp.config.compare.offset, 52 | cmp.config.compare.exact, 53 | cmp.config.compare.score, 54 | cmp.config.compare.recently_used, 55 | require('cmp-under-comparator').under, -- for python 56 | cmp.config.compare.locality, 57 | cmp.config.compare.kind, 58 | cmp.config.compare.length, 59 | cmp.config.compare.order, 60 | }, 61 | }, 62 | snippet = { 63 | expand = function(args) 64 | -- FIXME: There is a bug where highlights gets left behind 65 | -- IDK what caused this so.... using luasnip for now 66 | -- vim.snippet.expand(args.body) 67 | require('luasnip').lsp_expand(args.body) 68 | end, 69 | }, 70 | mapping = cmp.mapping.preset.insert { 71 | [''] = cmp.mapping.scroll_docs(-4), 72 | [''] = cmp.mapping.scroll_docs(4), 73 | -- NOTE: C-n/C-p Insert behavior does not work well with snippets from LSP. 74 | -- Still considering whether it's worth keeping this or just use cmp.SelectBehavior.Select 75 | [''] = cmp.mapping.select_next_item { behavior = cmp.SelectBehavior.Insert }, 76 | [''] = cmp.mapping.select_prev_item { behavior = cmp.SelectBehavior.Insert }, 77 | [''] = function() 78 | if cmp.visible_docs() then 79 | cmp.close_docs() 80 | else 81 | cmp.open_docs() 82 | end 83 | end, 84 | [''] = cmp.mapping.complete(), 85 | [''] = cmp.mapping.confirm { select = true, behavior = cmp.ConfirmBehavior.Insert }, 86 | [''] = cmp.mapping(function(fallback) 87 | if require('luasnip').expand_or_jumpable() then 88 | require('luasnip').expand_or_jump() 89 | else 90 | fallback() 91 | end 92 | end), 93 | [''] = cmp.mapping(function(fallback) 94 | if require('luasnip').jumpable(-1) then 95 | require('luasnip').jump(-1) 96 | else 97 | fallback() 98 | end 99 | end), 100 | }, 101 | experimental = { 102 | ghost_text = { 103 | hl_group = 'CmpGhostText', 104 | }, 105 | }, 106 | formatting = { 107 | format = function(entry, vim_item) 108 | vim_item.menu = ({ 109 | buffer = '[Buf]', 110 | nvim_lsp = '[LSP]', 111 | rg = '[Grep]', 112 | mocword = '[Sugg]', 113 | cmp_yanky = '[Yanky]', 114 | })[entry.source.name] 115 | return vim_item 116 | end, 117 | }, 118 | } 119 | 120 | -- Setup filetype sources 121 | cmp.setup.filetype('html', { 122 | sources = cmp.config.sources({ 123 | { name = 'nvim_lsp' }, 124 | { name = 'luasnip' }, 125 | }, { 126 | { name = 'rg', max_item_count = 10 }, 127 | { name = 'buffer', max_item_count = 10 }, 128 | }), 129 | }) 130 | 131 | cmp.setup.filetype('markdown', { 132 | sources = cmp.config.sources { 133 | { name = 'nvim_lsp' }, 134 | { name = 'mocword' }, 135 | { name = 'rg', max_item_count = 10 }, 136 | { name = 'buffer', max_item_count = 10 }, 137 | }, 138 | }) 139 | 140 | cmp.setup.filetype('gitcommit', { 141 | sources = cmp.config.sources({ 142 | { name = 'mocword' }, 143 | { name = 'rg', max_item_count = 10 }, 144 | }, { 145 | { name = 'buffer', max_item_count = 10 }, 146 | }), 147 | }) 148 | 149 | cmp.setup.filetype('sql', { 150 | sources = cmp.config.sources { 151 | { name = 'vim-dadbod-completion' }, 152 | { name = 'buffer', max_item_count = 10 }, 153 | }, 154 | }) 155 | 156 | -- Following the vim philosophy keybindings 157 | -- @see `:h ins-completion` 158 | vim.keymap.set('i', '', function() 159 | cmp.complete { 160 | config = { 161 | sources = { 162 | { name = 'nvim_lsp' }, 163 | }, 164 | }, 165 | } 166 | end, { desc = 'LSP completion' }) 167 | 168 | vim.keymap.set('i', '', function() 169 | cmp.complete { 170 | config = { 171 | sources = { 172 | { name = 'luasnip' }, 173 | }, 174 | }, 175 | } 176 | end, { desc = 'Snippet completion' }) 177 | 178 | vim.keymap.set('i', '', function() 179 | cmp.complete { 180 | config = { 181 | sources = { 182 | { name = 'tags', max_item_count = 10 }, 183 | }, 184 | }, 185 | } 186 | end, { desc = 'ctags completion' }) 187 | 188 | vim.keymap.set('i', '', function() 189 | cmp.complete { 190 | config = { 191 | sources = { 192 | { name = 'rg' }, 193 | }, 194 | }, 195 | } 196 | end, { desc = 'ripgrep completion' }) 197 | 198 | vim.keymap.set('i', '', function() 199 | cmp.complete { 200 | config = { 201 | sources = { 202 | { name = 'cmp_yanky', kind_text = 'Clipboard' }, 203 | }, 204 | }, 205 | } 206 | end, { desc = 'yanky completion' }) 207 | 208 | vim.keymap.set('i', '', function() 209 | cmp.complete { 210 | config = { 211 | sources = { 212 | { name = 'copilot' }, 213 | }, 214 | }, 215 | } 216 | end, { desc = 'copilot (see :h i_CTRL-X_CTRL_U)' }) 217 | 218 | vim.keymap.set('i', '', function() 219 | cmp.complete { 220 | config = { 221 | sources = { 222 | { 223 | name = 'async_path', 224 | option = { 225 | trailing_slash = true, 226 | }, 227 | }, 228 | }, 229 | }, 230 | } 231 | end, { desc = 'Path completion (async)' }) 232 | 233 | vim.keymap.set('i', '', function() 234 | cmp.complete { 235 | config = { 236 | sources = { 237 | { 238 | name = 'mocword', 239 | }, 240 | }, 241 | }, 242 | } 243 | end, { desc = 'Mocword' }) 244 | end 245 | 246 | return { 247 | { 248 | 'hrsh7th/nvim-cmp', 249 | event = { 'InsertEnter' }, 250 | config = cmp_config, 251 | dependencies = { 252 | 'hrsh7th/cmp-nvim-lsp', 253 | 'hrsh7th/cmp-buffer', 254 | 'saadparwaiz1/cmp_luasnip', 255 | 'hrsh7th/cmp-nvim-lsp-signature-help', 256 | 'lukas-reineke/cmp-rg', 257 | 'lukas-reineke/cmp-under-comparator', 258 | 'chrisgrieser/cmp_yanky', 259 | 'yutkat/cmp-mocword', 260 | { 261 | 'yujinyuz/cmp-async-path', 262 | dev = true, 263 | }, 264 | { 265 | 'zbirenbaum/copilot-cmp', 266 | enabled = false, 267 | config = true, 268 | dependencies = { 269 | 'zbirenbaum/copilot.lua', 270 | opts = { 271 | suggestion = { enabled = false }, 272 | panel = { enabled = false }, 273 | }, 274 | }, 275 | }, 276 | }, 277 | }, 278 | { 279 | 'windwp/nvim-autopairs', 280 | event = { 'InsertEnter' }, 281 | opts = { 282 | disable_filetype = { 'vim', 'markdown', 'snacks_picker_input' }, 283 | map_c_w = true, 284 | check_ts = true, 285 | }, 286 | }, 287 | } 288 | -------------------------------------------------------------------------------- /dot_config/tmux/tmux.conf: -------------------------------------------------------------------------------- 1 | # General Config {{{--- 2 | set-option -g default-terminal "${TERM}" 3 | set-option -as terminal-features ',xterm-kitty:RGB' 4 | set-option -as terminal-overrides ',*:Smulx=\E[4::%p1%dm' # undercurl support 5 | set-option -as terminal-overrides ',*:Setulc=\E[58::2::%p1%{65536}%/%d::%p1%{256}%/%{255}%&%d::%p1%{255}%&%d%;m' # underscore colours - needs tmux-3.0 6 | 7 | # Make sure we always start at 1, even when invoked from a .tmux wrapper script 8 | set-environment -g SHLVL 0 9 | 10 | # Save the parent terminal so we can use it since $TERM gets overridden 11 | set-environment -g PARENT_TERM $TERM 12 | 13 | # Use vi key bindings 14 | set-option -g mode-keys vi 15 | 16 | # Mouse 17 | set-option -g mouse on 18 | 19 | # Increase repeat time for repeatable commands 20 | set-option -g repeat-time 1000 21 | 22 | # Start window index at 1 instead of 0 23 | set-option -g base-index 1 24 | 25 | # Start pane index at 1 instead of 0 26 | set-option -g pane-base-index 1 27 | 28 | # Highlight window when it has new activity 29 | set-option -g monitor-activity off 30 | set-option -g visual-activity off 31 | 32 | # Re-number windows when one is closed 33 | set-option -g renumber-windows on 34 | 35 | set-option -g set-titles on 36 | set-option -g set-titles-string '#T' 37 | 38 | # Don't wrap searchers; it's super confusing given tmux's reverse-ordering of 39 | # position in copy mode. 40 | set-option -w -g wrap-search off 41 | 42 | # Slightly more useful width in "main-vertical" layout; enough room for 3-digit 43 | # line number gutter in Vim + 80 columns of text + 1 column breathing room 44 | # (default looks to be about 79). 45 | set-option -w -g main-pane-width 85 46 | 47 | # Enable OSC 52 clipboard 48 | set-option -g set-clipboard on 49 | 50 | # Add : to the default list (" -_@") of word separators. 51 | set-option -ga word-separators :/ 52 | 53 | # Set escape-time to 0 to prevent delays 54 | # NOTE: This only occured while on a Macbook M1 55 | set-option -g escape-time 0 56 | 57 | set-option -g allow-passthrough on 58 | 59 | # Don't detach from tmux when a session is destroyed 60 | set-option -g detach-on-destroy off 61 | 62 | # ---}}} 63 | 64 | # Key Bindings {{{--- 65 | unbind-key C-b 66 | # set-option -g prefix C-a 67 | # When we actually want to send `C-a` instead of the prefix, 68 | # We press `C-a` twice so we get the actual `C-a`. 69 | # bind-key C-a send-prefix 70 | 71 | ## C-Space as the leader key 72 | set-option -g prefix C-Space 73 | bind-key C-Space send-prefix 74 | 75 | # Open new/split panes with the path of the current pane 76 | unbind-key % 77 | bind-key % split-window -h -c '#{pane_current_path}' 78 | unbind-key '"' 79 | bind-key '"' split-window -v -c '#{pane_current_path}' 80 | 81 | # This key suspends the current tmux client and I don't know how to unsuspend 82 | # it. Better off disabling this since I've never really used it. 83 | # Pressing Prefix + z and Prefix + makes me accidentally press this 84 | unbind C-z 85 | 86 | # Sensible new/split panes key bindings 87 | bind-key | split-window -h -c '#{pane_current_path}' 88 | bind-key \\ split-window -h -c '#{pane_current_path}' 89 | bind-key - split-window -v -c '#{pane_current_path}' 90 | 91 | # tmux < 3.3a 92 | # bind-key v split-window -v -c '#{pane_current_path}' -p 30 \; split-window -h -c '#{pane_current_path}' -p 66 \; split-window -h -c '#{pane_current_path}' -p 50 \; 93 | 94 | # tmux >= 3.4 95 | bind-key v split-window -v -c '#{pane_current_path}' -l 30% \; split-window -h -c '#{pane_current_path}' -l 66% \; split-window -h -c '#{pane_current_path}' -l 50% \; 96 | 97 | 98 | # Vim-like keybindings for pane navigation (uses the arrow keys by default) 99 | unbind-key h 100 | bind-key h select-pane -L 101 | unbind-key j 102 | bind-key j select-pane -D 103 | unbind-key k 104 | bind-key k select-pane -U 105 | unbind-key l # normally used for last-window 106 | bind-key l select-pane -R 107 | 108 | unbind-key i 109 | bind-key i last-window 110 | unbind-key e 111 | bind-key e switch-client -l 112 | 113 | # Repeatedly resize-pane using HJKL 114 | bind-key -r H resize-pane -L 2 115 | bind-key -r J resize-pane -D 2 116 | bind-key -r K resize-pane -U 2 117 | bind-key -r L resize-pane -R 2 118 | 119 | # Swap panes 120 | bind-key Up swap-pane -U 121 | bind-key Down swap-pane -D 122 | 123 | # Setup 'v' to begin selection like Vim 124 | bind-key -T copy-mode-vi 'v' send-keys -X begin-selection 125 | bind-key -T copy-mode-vi y send-keys -X copy-pipe-and-cancel 'pbcopy' 126 | bind-key -T copy-mode-vi Enter send-keys -X copy-pipe-and-cancel 'pbcopy' 127 | bind-key -T copy-mode-vi WheelUpPane send-keys -X scroll-up 128 | bind-key -T copy-mode-vi WheelDownPane send-keys -X scroll-down 129 | 130 | # Move window to left 131 | bind-key < swap-window -t -1 132 | # Move window to right 133 | bind-key > swap-window -t +1 134 | 135 | # Stay in copy-mode on drag end 136 | bind-key -T copy-mode-vi MouseDragEnd1Pane send-keys -X stop-selection 137 | 138 | # Scroll 3 lines at a time instead of default 5; don't extend dragged selections. 139 | bind-key -T copy-mode-vi WheelUpPane select-pane\; send-keys -t'{mouse}' -X clear-selection\; send-keys -t'{mouse}' -X -N 3 scroll-up 140 | bind-key -T copy-mode-vi WheelDownPane select-pane\; send-keys -t'{mouse}' -X clear-selection\; send-keys -t'{mouse}' -X -N 3 scroll-down 141 | 142 | # Make double and triple click work outside of copy mode (already works inside it with default bindings). 143 | bind-key -T root DoubleClick1Pane if-shell -Ft'{mouse}' '#{alternate_on}' "send-keys -M" "copy-mode -t'{mouse}'; send-keys -X select-word" 144 | bind-key -T root TripleClick1Pane if-shell -Ft'{mouse}' '#{alternate_on}' "send-keys -M" "copy-mode -t'{mouse}'; send-keys -X select-line" 145 | 146 | # break session and kill session 147 | # https://forum.upcase.com/t/how-do-you-manage-organize-sessions-projects-with-tmux-workflow/740/5 148 | bind-key C-b send-keys 'tat && exit' 'C-m' 149 | 150 | # toggle between synchronizing panes 151 | bind-key y set synchronize-panes\; display 'synchronize-panes #{?synchronize-panes,on,off}' 152 | 153 | # Reload tmux config 154 | bind-key R source-file ~/.config/tmux/tmux.conf \; display "Config reloaded." 155 | 156 | # Search back to last prompt (mnemonic: "[b]ack"); Only works when you use 157 | # pure prompt 158 | bind-key b copy-mode\; send-keys -X start-of-line\; send-keys -X search-backward "❯"\; send-keys -X next-word 159 | 160 | bind-key -T copy-mode-vi / command-prompt -i -p "search down" "send -X search-forward-incremental \"%%%\"" 161 | bind-key -T copy-mode-vi ? command-prompt -i -p "search up" "send -X search-backward-incremental \"%%%\"" 162 | 163 | 164 | # Analagous with naked C-l which resets/clears the terminal. 165 | bind-key C-l clear-history 166 | 167 | 168 | # Bind Shift+Enter on tmux-3.2a above 169 | bind-key -n S-Enter send-keys Escape "[13;2u" 170 | # ---}}} 171 | 172 | # Status Bar {{{--- 173 | set-option -g status-style "fg=white bright italics" 174 | set-option -g status-left-length 40 175 | set-option -g status-left '#[fg=yellow,bold,italics]#S ⅏ ' # ⅏ Unicode 214F 176 | set-option -g status-right "#[fg=yellow,bold,italics]☰ #(whoami)@#h #[fg=magenta]%R" # ☰ Unicode 2630 177 | set-option -g status-interval 60 # Default is 15. 178 | 179 | # Highlight active window. 180 | set-option -w -g window-status-current-style "bg=#078ec2,fg=#fefefa" 181 | # Dim nonactive windows 182 | set-option -w -g window-status-style "fg=gray" 183 | 184 | # Make widths constant with or without flags. 185 | set-option -w -g window-status-current-format ' #I:#W#F ' 186 | set-option -w -g window-status-format ' #I:#W#{?#{==:#F,}, ,#F }' 187 | 188 | # ---}}} 189 | 190 | # Plugins {{{--- 191 | # From https://github.com/tmux-plugins/tpm#installation 192 | # Put at the bottom of the conf 193 | # List of plugins 194 | # Install: Prefix + I 195 | # Update: Prefix + U 196 | # Remove: Prefix + Alt + U 197 | set -g @plugin 'tmux-plugins/tpm' 198 | set -g @plugin 'tmux-plugins/tmux-sensible' 199 | 200 | # Install custom plugins here 201 | set -g @plugin 'tmux-plugins/tmux-resurrect' 202 | set -g @plugin 'tmux-plugins/tmux-continuum' 203 | set -g @plugin 'tmux-plugins/tmux-open' 204 | set -g @plugin 'tmux-plugins/tmux-copycat' 205 | set -g @plugin 'wfxr/tmux-fzf-url' 206 | set -g @plugin 'Morantron/tmux-fingers' 207 | 208 | set -g @continuum-save-interval '20' 209 | set -g @fingers-key F 210 | set -g @fingers-jump-key T 211 | set -g @fingers-keyboard-layout 'colemak-left-hand' 212 | set -g @fingers-show-copied-notification 1 213 | 214 | # Automatically install tpm 215 | if "test ! -d ~/.tmux/plugins/tpm" \ 216 | "run 'git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm && ~/.tmux/plugins/tpm/bin/install_plugins'" 217 | 218 | # Initialize TMUX plugin manager (keep this line at the very bottom of tmux.conf) 219 | run '~/.tmux/plugins/tpm/tpm' 220 | # ---}}} 221 | 222 | # Local config 223 | if-shell "[ -f ~/.tmux-local.conf ]" 'source ~/.tmux-local.conf' 224 | # vim:filetype=tmux sw=4 foldmethod=marker tw=78 expandtab: 225 | -------------------------------------------------------------------------------- /dot_config/nvim/after/plugin/autocommands.rc.lua: -------------------------------------------------------------------------------- 1 | local function augroup(name) 2 | return vim.api.nvim_create_augroup('pde_' .. name, { clear = true }) 3 | end 4 | 5 | -- Check if we need to reload the file when it changed 6 | vim.api.nvim_create_autocmd({ 'FocusGained', 'TermClose', 'TermLeave' }, { 7 | group = augroup('checktime'), 8 | callback = function() 9 | if vim.o.buftype ~= 'nofile' then 10 | vim.cmd('checktime') 11 | end 12 | end, 13 | }) 14 | 15 | -- Highight on yank 16 | vim.api.nvim_create_autocmd('TextYankPost', { 17 | pattern = { '*' }, 18 | group = augroup('highlight_yank'), 19 | callback = function() 20 | vim.highlight.on_yank { 21 | on_visual = false, 22 | timeout = 200, 23 | } 24 | end, 25 | desc = 'Highight on Yank', 26 | }) 27 | 28 | -- Strip Trailing Whitespace 29 | vim.api.nvim_create_autocmd('BufWritePre', { 30 | pattern = { '*' }, 31 | group = augroup('strip_trailing_whitespace'), 32 | callback = function(event) 33 | local ft = vim.bo[event.buf].filetype 34 | local buflisted = vim.bo[event.buf].buflisted 35 | 36 | if not buflisted then 37 | return 38 | end 39 | 40 | if ft:match('commit') or ft:match('rebase') then 41 | return 42 | end 43 | 44 | local winview = vim.fn.winsaveview() 45 | vim.cmd([[%s/\s\+$//e]]) 46 | vim.fn.winrestview(winview) 47 | end, 48 | desc = 'Strip Trailing Whitespace', 49 | }) 50 | 51 | vim.api.nvim_create_autocmd('TermOpen', { 52 | pattern = { '*' }, 53 | group = augroup('terminal_insert'), 54 | callback = function() 55 | vim.opt_local.signcolumn = 'no' 56 | end, 57 | desc = 'Start Terminal Insert', 58 | }) 59 | 60 | vim.api.nvim_create_autocmd({ 61 | 'BufEnter', 62 | 'FocusGained', 63 | 'InsertLeave', 64 | 'WinEnter', 65 | }, { 66 | pattern = { '*' }, 67 | group = augroup('enable_relative_number'), 68 | callback = function() 69 | if vim.g.muggle_friendly_mode then 70 | return 71 | end 72 | 73 | if vim.opt.number:get() and vim.fn.mode() ~= 'i' then 74 | vim.opt.relativenumber = true 75 | end 76 | end, 77 | desc = 'Enable relativenumber', 78 | }) 79 | 80 | vim.api.nvim_create_autocmd({ 81 | 'BufLeave', 82 | 'FocusLost', 83 | 'InsertEnter', 84 | 'WinLeave', 85 | }, { 86 | pattern = { '*' }, 87 | group = augroup('disable_relative_number'), 88 | callback = function() 89 | if vim.g.muggle_friendly_mode then 90 | return 91 | end 92 | 93 | if vim.opt.number:get() then 94 | vim.opt.relativenumber = false 95 | end 96 | end, 97 | desc = 'Disable relative number', 98 | }) 99 | 100 | vim.api.nvim_create_autocmd('VimResized', { 101 | pattern = { '*' }, 102 | group = augroup('resize_splits'), 103 | callback = function() 104 | local current_tab = vim.fn.tabpagenr() 105 | local current_win = vim.api.nvim_get_current_win() 106 | 107 | vim.cmd('tabdo wincmd =') 108 | vim.cmd('tabnext ' .. current_tab) 109 | 110 | -- Needed to prevent the cursor from moving somewhere else when resizing splits 111 | vim.api.nvim_set_current_win(current_win) 112 | end, 113 | desc = 'Automatically Resize Windows Equally', 114 | }) 115 | 116 | vim.api.nvim_create_autocmd('BufWritePre', { 117 | pattern = { '*' }, 118 | group = augroup('rename_auto_backup_files'), 119 | callback = function(event) 120 | if not vim.bo[event.buf].buflisted then 121 | return 122 | end 123 | vim.cmd([[let &bex = '±' .. strftime("%F∴%H:%M") .. '~']]) 124 | end, 125 | desc = 'Rename backup files', 126 | }) 127 | 128 | vim.api.nvim_create_autocmd('BufWritePost', { 129 | group = augroup('kitty_auto_reload'), 130 | pattern = { '*/kitty/*.conf' }, 131 | callback = function() 132 | -- auto-reload kitty upon kitty.conf write 133 | -- https://github.com/kovidgoyal/kitty/discussions/5416#discussioncomment-3473122 134 | vim.cmd([[:silent !pgrep -i kitty | xargs kill -SIGUSR1]]) 135 | end, 136 | }) 137 | 138 | vim.api.nvim_create_autocmd({ 'BufWritePost', 'BufReadPost', 'InsertLeave' }, { 139 | group = augroup('auto_lint'), 140 | callback = function() 141 | require('lint').try_lint() 142 | end, 143 | }) 144 | 145 | -- go to last loc when opening a buffer 146 | vim.api.nvim_create_autocmd('BufReadPost', { 147 | group = augroup('last_loc'), 148 | callback = function(event) 149 | local exclude_filetype = { 'gitcommit' } 150 | 151 | local buf = event.buf 152 | if vim.tbl_contains(exclude_filetype, vim.bo[buf].filetype) or vim.b[buf].pde_last_loc then 153 | return 154 | end 155 | 156 | vim.b[buf].pde_last_loc = true 157 | 158 | local mark = vim.api.nvim_buf_get_mark(buf, '"') 159 | local lcount = vim.api.nvim_buf_line_count(buf) 160 | if mark[1] > 0 and mark[1] <= lcount then 161 | pcall(vim.api.nvim_win_set_cursor, 0, mark) 162 | 163 | -- if we jumped to a fold, open it 164 | if vim.fn.foldclosed(mark[1]) ~= -1 then 165 | print('fold was closed.. opening it') 166 | vim.cmd('normal! zvzz') 167 | end 168 | end 169 | end, 170 | }) 171 | 172 | -- close some filetypes with 173 | vim.api.nvim_create_autocmd('FileType', { 174 | group = augroup('close_with_q'), 175 | pattern = { 176 | 'PlenaryTestPopup', 177 | 'help', 178 | 'lspinfo', 179 | 'notify', 180 | 'qf', 181 | 'query', 182 | 'spectre_panel', 183 | 'startuptime', 184 | 'tsplayground', 185 | 'neotest-output', 186 | 'checkhealth', 187 | 'neotest-summary', 188 | 'neotest-output-panel', 189 | 'grug-far', 190 | 'fugitive', 191 | 'fugitiveblame', 192 | 'fugitive://*', 193 | }, 194 | callback = function(event) 195 | vim.bo[event.buf].buflisted = false 196 | vim.keymap.set('n', 'q', 'close', { buffer = event.buf, silent = true }) 197 | end, 198 | }) 199 | 200 | -- make it easier to close man-files when opened inline 201 | vim.api.nvim_create_autocmd('FileType', { 202 | group = augroup('man_unlisted'), 203 | pattern = { 'man' }, 204 | callback = function(event) 205 | vim.bo[event.buf].buflisted = false 206 | end, 207 | }) 208 | 209 | -- Fix conceallevel for json files 210 | vim.api.nvim_create_autocmd({ 'FileType' }, { 211 | group = augroup('json_conceal'), 212 | pattern = { 'json', 'jsonc', 'json5' }, 213 | callback = function() 214 | vim.opt_local.conceallevel = 0 215 | end, 216 | }) 217 | 218 | -- Enable spell for gitcommit and markdown 219 | vim.api.nvim_create_autocmd({ 'FileType' }, { 220 | group = augroup('enable_spell'), 221 | pattern = { 'gitcommit', 'markdown' }, 222 | callback = function() 223 | vim.opt_local.spell = true 224 | end, 225 | }) 226 | 227 | -- Enable htmldjango for html files 228 | vim.api.nvim_create_autocmd({ 'FileType' }, { 229 | group = augroup('enable_htmldjango'), 230 | pattern = { 'html' }, 231 | callback = function(event) 232 | -- We should probably check first if we are inside a django project 233 | if 234 | #vim.fs.find('manage.py', { upward = true, path = vim.fs.dirname(vim.api.nvim_buf_get_name(event.buf)) }) == 0 235 | then 236 | return 237 | end 238 | 239 | vim.bo[event.buf].filetype = 'htmldjango' 240 | end, 241 | }) 242 | 243 | if vim.fn.executable('chezmoi') == 1 then 244 | vim.api.nvim_create_autocmd({ 'BufWritePost' }, { 245 | group = augroup('chezmoi_auto_apply'), 246 | pattern = { vim.fs.normalize('~/Sources/github.com/yujinyuz/dotfiles/*') }, 247 | callback = function(event) 248 | local bufname = vim.fn.pathshorten(vim.api.nvim_buf_get_name(event.buf)) 249 | 250 | vim.uv.spawn('chezmoi', { 251 | args = { 252 | 'apply', 253 | '--force', 254 | }, 255 | }, function(code, signal) 256 | vim.schedule(function() 257 | if vim.o.columns < 80 then 258 | return 259 | end 260 | local msg = string.format('applied %s code: %s, signal: %s', bufname, code, signal) 261 | require('my.utils').info(msg, '[chezmoi]') 262 | end) 263 | end) 264 | end, 265 | }) 266 | end 267 | 268 | vim.api.nvim_create_autocmd('BufReadPost', { 269 | group = augroup('relative_path_fix'), 270 | pattern = { '*' }, 271 | callback = function() 272 | -- Sometimes buffer names become absolute paths and that messes up the 273 | -- name in the tabline. 274 | vim.cmd.lcd('.') 275 | end, 276 | }) 277 | 278 | vim.api.nvim_create_autocmd('FileType', { 279 | group = augroup('man_toc_reminder'), 280 | pattern = { 'man' }, 281 | callback = function() 282 | vim.api.nvim_echo({ { 'Press gO to toggle table of contents', 'DiagnosticInfo' } }, true, {}) 283 | end, 284 | desc = 'Reminder to press gO to toggle table of contents', 285 | }) 286 | 287 | vim.api.nvim_create_autocmd({ 'BufReadPre', 'BufWritePost' }, { 288 | group = augroup('bufsize'), 289 | pattern = '*', 290 | callback = function(event) 291 | local stats = vim.uv.fs_stat(vim.api.nvim_buf_get_name(event.buf)) 292 | local size_threshold = 5000 * 1024 -- 5mb 293 | 294 | if not stats then 295 | vim.b.bufsize = 0 296 | else 297 | vim.b.bufsize = stats.size 298 | end 299 | 300 | vim.b.bufsize_human = require('my.utils').humanize_size(vim.b.bufsize) 301 | 302 | if vim.b.bufsize > size_threshold then 303 | vim.b.large_buf = true 304 | else 305 | vim.b.large_buf = false 306 | end 307 | end, 308 | desc = 'Set buffer size and large_buf flag', 309 | }) 310 | 311 | vim.api.nvim_create_autocmd('CursorMoved', { 312 | group = augroup('auto_hlsearch'), 313 | callback = function() 314 | if vim.v.hlsearch == 1 and vim.fn.searchcount().exact_match == 0 then 315 | vim.schedule(function() 316 | vim.cmd.nohlsearch() 317 | end) 318 | end 319 | end, 320 | desc = 'Automatically clear hlsearch when cursor moves', 321 | }) 322 | 323 | vim.api.nvim_create_autocmd({ 'UIEnter', 'ColorScheme' }, { 324 | group = augroup('term_color_sync'), 325 | callback = function() 326 | local normal = vim.api.nvim_get_hl(0, { name = 'Normal' }) 327 | if not normal.bg then 328 | return 329 | end 330 | 331 | if vim.env.TMUX then 332 | io.write(string.format('\027Ptmux;\027\027]11;#%06x\007\027\\', normal.bg)) 333 | else 334 | io.write(string.format('\027]11;#%06x\027\\', normal.bg)) 335 | end 336 | end, 337 | desc = 'Automatically sync colorscheme with terminal', 338 | }) 339 | 340 | vim.api.nvim_create_autocmd('UILeave', { 341 | group = augroup('term_color_unsync'), 342 | callback = function() 343 | if vim.env.TMUX then 344 | io.write('\027Ptmux;\027\027]111;\007\027\\') 345 | else 346 | io.write('\027]111\027\\') 347 | end 348 | end, 349 | desc = 'Automatically sync colorscheme with terminal', 350 | }) 351 | 352 | vim.api.nvim_create_autocmd('TabNew', { 353 | group = augroup('overhead'), 354 | callback = function() 355 | if #vim.api.nvim_list_tabpages() > 2 then 356 | require('my.utils').warn('Hard to procses more than 2 tabs', '[brain]') 357 | end 358 | end, 359 | desc = 'Prevent overhead with multiple tabs', 360 | }) 361 | 362 | vim.api.nvim_create_autocmd('VimEnter', { 363 | group = augroup('has_last_session'), 364 | callback = function() 365 | local file = require('persistence').current() 366 | 367 | if vim.o.columns < 80 then 368 | return 369 | end 370 | 371 | if vim.fn.filereadable(file) ~= 0 then 372 | require('my.utils').info('existing session found for this project', '[reminder]') 373 | end 374 | end, 375 | }) 376 | -------------------------------------------------------------------------------- /dot_config/sketchybar/plugins/executable_icon_map_fn.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ### START-OF-ICON-MAP 4 | function __icon_map() { 5 | case "$1" in 6 | "Live") 7 | icon_result=":ableton:" 8 | ;; 9 | "Adobe Bridge 2024") 10 | icon_result=":adobe_bridge:" 11 | ;; 12 | "Affinity Designer") 13 | icon_result=":affinity_designer:" 14 | ;; 15 | "Affinity Designer 2") 16 | icon_result=":affinity_designer_2:" 17 | ;; 18 | "Affinity Photo") 19 | icon_result=":affinity_photo:" 20 | ;; 21 | "Affinity Photo 2") 22 | icon_result=":affinity_photo_2:" 23 | ;; 24 | "Affinity Publisher") 25 | icon_result=":affinity_publisher:" 26 | ;; 27 | "Affinity Publisher 2") 28 | icon_result=":affinity_publisher_2:" 29 | ;; 30 | "Airmail") 31 | icon_result=":airmail:" 32 | ;; 33 | "Alacritty") 34 | icon_result=":alacritty:" 35 | ;; 36 | "Alfred") 37 | icon_result=":alfred:" 38 | ;; 39 | "Android Messages") 40 | icon_result=":android_messages:" 41 | ;; 42 | "Android Studio") 43 | icon_result=":android_studio:" 44 | ;; 45 | "Anytype") 46 | icon_result=":anytype:" 47 | ;; 48 | "App Eraser") 49 | icon_result=":app_eraser:" 50 | ;; 51 | "App Store") 52 | icon_result=":app_store:" 53 | ;; 54 | "Arc") 55 | icon_result=":arc:" 56 | ;; 57 | "Atom") 58 | icon_result=":atom:" 59 | ;; 60 | "Audacity") 61 | icon_result=":audacity:" 62 | ;; 63 | "Bambu Studio") 64 | icon_result=":bambu_studio:" 65 | ;; 66 | "MoneyMoney") 67 | icon_result=":bank:" 68 | ;; 69 | "Bear") 70 | icon_result=":bear:" 71 | ;; 72 | "BetterTouchTool") 73 | icon_result=":bettertouchtool:" 74 | ;; 75 | "Bilibili" | "哔哩哔哩") 76 | icon_result=":bilibili:" 77 | ;; 78 | "Bitwarden") 79 | icon_result=":bit_warden:" 80 | ;; 81 | "Blender") 82 | icon_result=":blender:" 83 | ;; 84 | "BluOS Controller") 85 | icon_result=":bluos_controller:" 86 | ;; 87 | "Calibre") 88 | icon_result=":book:" 89 | ;; 90 | "Brave Browser") 91 | icon_result=":brave_browser:" 92 | ;; 93 | "Calculator" | "Calculette") 94 | icon_result=":calculator:" 95 | ;; 96 | "Calendar" | "日历" | "Fantastical" | "Cron" | "Amie" | "Calendrier" | "Notion Calendar") 97 | icon_result=":calendar:" 98 | ;; 99 | "Caprine") 100 | icon_result=":caprine:" 101 | ;; 102 | "Citrix Workspace" | "Citrix Viewer") 103 | icon_result=":citrix:" 104 | ;; 105 | "ClickUp") 106 | icon_result=":click_up:" 107 | ;; 108 | "Code" | "Code - Insiders") 109 | icon_result=":code:" 110 | ;; 111 | "Color Picker" | "数码测色计") 112 | icon_result=":color_picker:" 113 | ;; 114 | "CotEditor") 115 | icon_result=":coteditor:" 116 | ;; 117 | "Cypress") 118 | icon_result=":cypress:" 119 | ;; 120 | "DataGrip") 121 | icon_result=":datagrip:" 122 | ;; 123 | "DataSpell") 124 | icon_result=":dataspell:" 125 | ;; 126 | "DaVinci Resolve") 127 | icon_result=":davinciresolve:" 128 | ;; 129 | "Default") 130 | icon_result=":default:" 131 | ;; 132 | "CleanMyMac X") 133 | icon_result=":desktop:" 134 | ;; 135 | "DEVONthink 3") 136 | icon_result=":devonthink3:" 137 | ;; 138 | "DingTalk" | "钉钉" | "阿里钉") 139 | icon_result=":dingtalk:" 140 | ;; 141 | "Discord" | "Discord Canary" | "Discord PTB") 142 | icon_result=":discord:" 143 | ;; 144 | "Docker" | "Docker Desktop") 145 | icon_result=":docker:" 146 | ;; 147 | "GrandTotal" | "Receipts") 148 | icon_result=":dollar:" 149 | ;; 150 | "Double Commander") 151 | icon_result=":doublecmd:" 152 | ;; 153 | "Drafts") 154 | icon_result=":drafts:" 155 | ;; 156 | "Dropbox") 157 | icon_result=":dropbox:" 158 | ;; 159 | "Element") 160 | icon_result=":element:" 161 | ;; 162 | "Emacs") 163 | icon_result=":emacs:" 164 | ;; 165 | "Evernote Legacy") 166 | icon_result=":evernote_legacy:" 167 | ;; 168 | "FaceTime" | "FaceTime 通话") 169 | icon_result=":face_time:" 170 | ;; 171 | "Figma") 172 | icon_result=":figma:" 173 | ;; 174 | "Final Cut Pro") 175 | icon_result=":final_cut_pro:" 176 | ;; 177 | "Finder" | "访达") 178 | icon_result=":finder:" 179 | ;; 180 | "Firefox") 181 | icon_result=":firefox:" 182 | ;; 183 | "Firefox Developer Edition" | "Firefox Nightly") 184 | icon_result=":firefox_developer_edition:" 185 | ;; 186 | "Folx") 187 | icon_result=":folx:" 188 | ;; 189 | "Fusion") 190 | icon_result=":fusion:" 191 | ;; 192 | "System Preferences" | "System Settings" | "系统设置" | "Réglages Système") 193 | icon_result=":gear:" 194 | ;; 195 | "GitHub Desktop") 196 | icon_result=":git_hub:" 197 | ;; 198 | "Godot") 199 | icon_result=":godot:" 200 | ;; 201 | "GoLand") 202 | icon_result=":goland:" 203 | ;; 204 | "Chromium" | "Google Chrome" | "Google Chrome Canary") 205 | icon_result=":google_chrome:" 206 | ;; 207 | "Grammarly Editor") 208 | icon_result=":grammarly:" 209 | ;; 210 | "Home Assistant") 211 | icon_result=":home_assistant:" 212 | ;; 213 | "Hyper") 214 | icon_result=":hyper:" 215 | ;; 216 | "IntelliJ IDEA") 217 | icon_result=":idea:" 218 | ;; 219 | "Inkdrop") 220 | icon_result=":inkdrop:" 221 | ;; 222 | "Inkscape") 223 | icon_result=":inkscape:" 224 | ;; 225 | "Insomnia") 226 | icon_result=":insomnia:" 227 | ;; 228 | "Iris") 229 | icon_result=":iris:" 230 | ;; 231 | "iTerm" | "iTerm2") 232 | icon_result=":iterm:" 233 | ;; 234 | "Jellyfin Media Player") 235 | icon_result=":jellyfin:" 236 | ;; 237 | "Joplin") 238 | icon_result=":joplin:" 239 | ;; 240 | "카카오톡" | "KakaoTalk") 241 | icon_result=":kakaotalk:" 242 | ;; 243 | "Kakoune") 244 | icon_result=":kakoune:" 245 | ;; 246 | "KeePassXC") 247 | icon_result=":kee_pass_x_c:" 248 | ;; 249 | "Keyboard Maestro") 250 | icon_result=":keyboard_maestro:" 251 | ;; 252 | "Keynote" | "Keynote 讲演") 253 | icon_result=":keynote:" 254 | ;; 255 | # 256 | "kitty") 257 | icon_result=":kitty:" 258 | ;; 259 | "League of Legends") 260 | icon_result=":league_of_legends:" 261 | ;; 262 | "LibreWolf") 263 | icon_result=":libre_wolf:" 264 | ;; 265 | "Adobe Lightroom") 266 | icon_result=":lightroom:" 267 | ;; 268 | "Lightroom Classic") 269 | icon_result=":lightroomclassic:" 270 | ;; 271 | "LINE") 272 | icon_result=":line:" 273 | ;; 274 | "Linear") 275 | icon_result=":linear:" 276 | ;; 277 | "LM Studio") 278 | icon_result=":lm_studio:" 279 | ;; 280 | "LocalSend") 281 | icon_result=":localsend:" 282 | ;; 283 | "Logic Pro") 284 | icon_result=":logicpro:" 285 | ;; 286 | "Logseq") 287 | icon_result=":logseq:" 288 | ;; 289 | "Canary Mail" | "HEY" | "Mail" | "Mailspring" | "MailMate" | "Superhuman" | "邮件") 290 | icon_result=":mail:" 291 | ;; 292 | "MAMP" | "MAMP PRO") 293 | icon_result=":mamp:" 294 | ;; 295 | "Maps" | "Google Maps") 296 | icon_result=":maps:" 297 | ;; 298 | "Matlab") 299 | icon_result=":matlab:" 300 | ;; 301 | "Mattermost") 302 | icon_result=":mattermost:" 303 | ;; 304 | "Messages" | "信息" | "Nachrichten") 305 | icon_result=":messages:" 306 | ;; 307 | "Messenger") 308 | icon_result=":messenger:" 309 | ;; 310 | "Microsoft Edge") 311 | icon_result=":microsoft_edge:" 312 | ;; 313 | "Microsoft Excel") 314 | icon_result=":microsoft_excel:" 315 | ;; 316 | "Microsoft Outlook") 317 | icon_result=":microsoft_outlook:" 318 | ;; 319 | "Microsoft PowerPoint") 320 | icon_result=":microsoft_power_point:" 321 | ;; 322 | "Microsoft Remote Desktop") 323 | icon_result=":microsoft_remote_desktop:" 324 | ;; 325 | "Microsoft Teams" | "Microsoft Teams (work or school)") 326 | icon_result=":microsoft_teams:" 327 | ;; 328 | "Microsoft Word") 329 | icon_result=":microsoft_word:" 330 | ;; 331 | "Min") 332 | icon_result=":min_browser:" 333 | ;; 334 | "Miro") 335 | icon_result=":miro:" 336 | ;; 337 | "MongoDB Compass"*) 338 | icon_result=":mongodb:" 339 | ;; 340 | "mpv") 341 | icon_result=":mpv:" 342 | ;; 343 | "Mullvad Browser") 344 | icon_result=":mullvad_browser:" 345 | ;; 346 | "Music" | "音乐" | "Musique") 347 | icon_result=":music:" 348 | ;; 349 | "Neovide" | "neovide") 350 | icon_result=":neovide:" 351 | ;; 352 | "Neovim" | "neovim" | "nvim") 353 | icon_result=":neovim:" 354 | ;; 355 | "网易云音乐") 356 | icon_result=":netease_music:" 357 | ;; 358 | "Noodl" | "Noodl Editor") 359 | icon_result=":noodl:" 360 | ;; 361 | "NordVPN") 362 | icon_result=":nord_vpn:" 363 | ;; 364 | "Notability") 365 | icon_result=":notability:" 366 | ;; 367 | "Notes" | "备忘录") 368 | icon_result=":notes:" 369 | ;; 370 | "Notion") 371 | icon_result=":notion:" 372 | ;; 373 | "Nova") 374 | icon_result=":nova:" 375 | ;; 376 | "Numbers" | "Numbers 表格") 377 | icon_result=":numbers:" 378 | ;; 379 | "Obsidian") 380 | icon_result=":obsidian:" 381 | ;; 382 | "OBS") 383 | icon_result=":obsstudio:" 384 | ;; 385 | "OmniFocus") 386 | icon_result=":omni_focus:" 387 | ;; 388 | "1Password") 389 | icon_result=":one_password:" 390 | ;; 391 | "ChatGPT") 392 | icon_result=":openai:" 393 | ;; 394 | "OpenVPN Connect") 395 | icon_result=":openvpn_connect:" 396 | ;; 397 | "Opera") 398 | icon_result=":opera:" 399 | ;; 400 | "OrcaSlicer") 401 | icon_result=":orcaslicer:" 402 | ;; 403 | "Orion" | "Orion RC") 404 | icon_result=":orion:" 405 | ;; 406 | "Pages" | "Pages 文稿") 407 | icon_result=":pages:" 408 | ;; 409 | "Parallels Desktop") 410 | icon_result=":parallels:" 411 | ;; 412 | "Parsec") 413 | icon_result=":parsec:" 414 | ;; 415 | "Preview" | "预览" | "Skim" | "zathura" | "Aperçu") 416 | icon_result=":pdf:" 417 | ;; 418 | "PDF Expert") 419 | icon_result=":pdf_expert:" 420 | ;; 421 | "Adobe Photoshop"*) 422 | icon_result=":photoshop:" 423 | ;; 424 | "Pi-hole Remote") 425 | icon_result=":pihole:" 426 | ;; 427 | "Pine") 428 | icon_result=":pine:" 429 | ;; 430 | "Podcasts" | "播客") 431 | icon_result=":podcasts:" 432 | ;; 433 | "PomoDone App") 434 | icon_result=":pomodone:" 435 | ;; 436 | "Postman") 437 | icon_result=":postman:" 438 | ;; 439 | "PrusaSlicer" | "SuperSlicer") 440 | icon_result=":prusaslicer:" 441 | ;; 442 | "PyCharm") 443 | icon_result=":pycharm:" 444 | ;; 445 | "QQ") 446 | icon_result=":qq:" 447 | ;; 448 | "QQ音乐" | "QQMusic") 449 | icon_result=":qqmusic:" 450 | ;; 451 | "Quantumult X") 452 | icon_result=":quantumult_x:" 453 | ;; 454 | "qutebrowser") 455 | icon_result=":qute_browser:" 456 | ;; 457 | "Raindrop.io") 458 | icon_result=":raindrop_io:" 459 | ;; 460 | "Reeder") 461 | icon_result=":reeder5:" 462 | ;; 463 | "Reminders" | "提醒事项" | "Rappels") 464 | icon_result=":reminders:" 465 | ;; 466 | "Replit") 467 | icon_result=":replit:" 468 | ;; 469 | "Rider" | "JetBrains Rider") 470 | icon_result=":rider:" 471 | ;; 472 | "Safari" | "Safari浏览器" | "Safari Technology Preview") 473 | icon_result=":safari:" 474 | ;; 475 | "Sequel Ace") 476 | icon_result=":sequel_ace:" 477 | ;; 478 | "Sequel Pro") 479 | icon_result=":sequel_pro:" 480 | ;; 481 | "Setapp") 482 | icon_result=":setapp:" 483 | ;; 484 | "SF Symbols") 485 | icon_result=":sf_symbols:" 486 | ;; 487 | "Signal") 488 | icon_result=":signal:" 489 | ;; 490 | "Sketch") 491 | icon_result=":sketch:" 492 | ;; 493 | "Skype") 494 | icon_result=":skype:" 495 | ;; 496 | "Slack") 497 | icon_result=":slack:" 498 | ;; 499 | "Spark Desktop") 500 | icon_result=":spark:" 501 | ;; 502 | "Spotify") 503 | icon_result=":spotify:" 504 | ;; 505 | "Spotlight") 506 | icon_result=":spotlight:" 507 | ;; 508 | "Sublime Text") 509 | icon_result=":sublime_text:" 510 | ;; 511 | "Tana") 512 | icon_result=":tana:" 513 | ;; 514 | "TeamSpeak 3") 515 | icon_result=":team_speak:" 516 | ;; 517 | "Telegram") 518 | icon_result=":telegram:" 519 | ;; 520 | "Terminal" | "终端") 521 | icon_result=":terminal:" 522 | ;; 523 | "Typora") 524 | icon_result=":text:" 525 | ;; 526 | "Microsoft To Do" | "Things") 527 | icon_result=":things:" 528 | ;; 529 | "Thunderbird") 530 | icon_result=":thunderbird:" 531 | ;; 532 | "TickTick") 533 | icon_result=":tick_tick:" 534 | ;; 535 | "TIDAL") 536 | icon_result=":tidal:" 537 | ;; 538 | "Tiny RDM") 539 | icon_result=":tinyrdm:" 540 | ;; 541 | "Todoist") 542 | icon_result=":todoist:" 543 | ;; 544 | "Toggl Track") 545 | icon_result=":toggl_track:" 546 | ;; 547 | "Tor Browser") 548 | icon_result=":tor_browser:" 549 | ;; 550 | "Tower") 551 | icon_result=":tower:" 552 | ;; 553 | "Transmit") 554 | icon_result=":transmit:" 555 | ;; 556 | "Trello") 557 | icon_result=":trello:" 558 | ;; 559 | "Tweetbot" | "Twitter") 560 | icon_result=":twitter:" 561 | ;; 562 | "MacVim" | "Vim" | "VimR") 563 | icon_result=":vim:" 564 | ;; 565 | "Vivaldi") 566 | icon_result=":vivaldi:" 567 | ;; 568 | "VLC") 569 | icon_result=":vlc:" 570 | ;; 571 | "VMware Fusion") 572 | icon_result=":vmware_fusion:" 573 | ;; 574 | "VSCodium") 575 | icon_result=":vscodium:" 576 | ;; 577 | "Warp") 578 | icon_result=":warp:" 579 | ;; 580 | "WebStorm") 581 | icon_result=":web_storm:" 582 | ;; 583 | "微信" | "WeChat") 584 | icon_result=":wechat:" 585 | ;; 586 | "企业微信" | "WeCom") 587 | icon_result=":wecom:" 588 | ;; 589 | "WezTerm") 590 | icon_result=":wezterm:" 591 | ;; 592 | "WhatsApp" | "‎WhatsApp") 593 | icon_result=":whats_app:" 594 | ;; 595 | "Xcode") 596 | icon_result=":xcode:" 597 | ;; 598 | "Яндекс Музыка") 599 | icon_result=":yandex_music:" 600 | ;; 601 | "Yuque" | "语雀") 602 | icon_result=":yuque:" 603 | ;; 604 | "Zed") 605 | icon_result=":zed:" 606 | ;; 607 | "Zeplin") 608 | icon_result=":zeplin:" 609 | ;; 610 | "zoom.us") 611 | icon_result=":zoom:" 612 | ;; 613 | "Zotero") 614 | icon_result=":zotero:" 615 | ;; 616 | "Zulip") 617 | icon_result=":zulip:" 618 | ;; 619 | *) 620 | icon_result=":default:" 621 | ;; 622 | esac 623 | } 624 | ### END-OF-ICON-MAP 625 | 626 | function __icon_map_overrides { 627 | case "$1" in 628 | "kitty") 629 | icon_result=":terminal:" 630 | ;; 631 | "Spark") 632 | icon_result=":mail:" 633 | ;; 634 | "Hubstaff") 635 | icon_result=":toggl_track:" 636 | ;; 637 | "Sync") 638 | icon_result=":dropbox:" 639 | ;; 640 | "Restfox") 641 | icon_result=":postman:" 642 | ;; 643 | esac 644 | } 645 | 646 | # Original Source: https://github.com/kvndrsslr/sketchybar-app-font 647 | 648 | __icon_map "$1" 649 | __icon_map_overrides "$1" 650 | 651 | echo "$icon_result" 652 | -------------------------------------------------------------------------------- /dot_config/private_karabiner/private_karabiner.json: -------------------------------------------------------------------------------- 1 | { 2 | "global": { "show_in_menu_bar": false }, 3 | "profiles": [ 4 | { 5 | "complex_modifications": { 6 | "parameters": { "basic.to_if_alone_timeout_milliseconds": 500 }, 7 | "rules": [ 8 | { 9 | "description": "Change caps_lock to control if pressed with other keys, to escape if pressed alone.", 10 | "manipulators": [ 11 | { 12 | "from": { 13 | "key_code": "caps_lock", 14 | "modifiers": { "optional": ["any"] } 15 | }, 16 | "to": [{ "key_code": "left_control" }], 17 | "to_if_alone": [{ "key_code": "escape" }], 18 | "type": "basic" 19 | } 20 | ] 21 | }, 22 | { 23 | "manipulators": [ 24 | { 25 | "description": "Change left control to Hyper Key (command+control+option)", 26 | "from": { 27 | "key_code": "left_control", 28 | "modifiers": { "optional": ["any"] } 29 | }, 30 | "to": [ 31 | { 32 | "key_code": "left_option", 33 | "modifiers": ["left_command", "left_control"] 34 | } 35 | ], 36 | "type": "basic" 37 | } 38 | ] 39 | }, 40 | { 41 | "description": "Toggle caps_lock by pressing left_shift then right_shift", 42 | "manipulators": [ 43 | { 44 | "from": { 45 | "key_code": "left_shift", 46 | "modifiers": { 47 | "mandatory": ["right_shift"], 48 | "optional": ["caps_lock"] 49 | } 50 | }, 51 | "to": [{ "key_code": "caps_lock" }], 52 | "to_if_alone": [{ "key_code": "left_shift" }], 53 | "type": "basic" 54 | }, 55 | { 56 | "from": { 57 | "key_code": "right_shift", 58 | "modifiers": { 59 | "mandatory": ["left_shift"], 60 | "optional": ["caps_lock"] 61 | } 62 | }, 63 | "to": [{ "key_code": "caps_lock" }], 64 | "to_if_alone": [{ "key_code": "right_shift" }], 65 | "type": "basic" 66 | } 67 | ] 68 | } 69 | ] 70 | }, 71 | "devices": [ 72 | { 73 | "disable_built_in_keyboard_if_exists": true, 74 | "identifiers": { 75 | "is_keyboard": true, 76 | "product_id": 591, 77 | "vendor_id": 1452 78 | } 79 | } 80 | ], 81 | "fn_function_keys": [ 82 | { 83 | "from": { "key_code": "f3" }, 84 | "to": [{ "key_code": "mission_control" }] 85 | }, 86 | { 87 | "from": { "key_code": "f4" }, 88 | "to": [{ "key_code": "launchpad" }] 89 | }, 90 | { 91 | "from": { "key_code": "f5" }, 92 | "to": [{ "key_code": "illumination_decrement" }] 93 | }, 94 | { 95 | "from": { "key_code": "f6" }, 96 | "to": [{ "key_code": "illumination_increment" }] 97 | }, 98 | { 99 | "from": { "key_code": "f9" }, 100 | "to": [{ "consumer_key_code": "fastforward" }] 101 | } 102 | ], 103 | "name": "Default profile", 104 | "virtual_hid_keyboard": { "country_code": 0 } 105 | }, 106 | { 107 | "complex_modifications": { 108 | "rules": [ 109 | { 110 | "description": "Change caps_lock to control if pressed with other keys, to escape if pressed alone.", 111 | "manipulators": [ 112 | { 113 | "from": { 114 | "key_code": "caps_lock", 115 | "modifiers": { "optional": ["any"] } 116 | }, 117 | "to": [ 118 | { 119 | "key_code": "left_control", 120 | "lazy": true 121 | } 122 | ], 123 | "to_if_alone": [ 124 | { 125 | "key_code": "escape", 126 | "lazy": true 127 | } 128 | ], 129 | "type": "basic" 130 | } 131 | ] 132 | }, 133 | { 134 | "description": "Toggle caps_lock by pressing right_command + right_shift at the same time", 135 | "manipulators": [ 136 | { 137 | "from": { 138 | "key_code": "right_command", 139 | "modifiers": { 140 | "mandatory": ["right_shift"], 141 | "optional": ["caps_lock"] 142 | } 143 | }, 144 | "to": [{ "key_code": "caps_lock" }], 145 | "to_if_alone": [{ "key_code": "right_command" }], 146 | "type": "basic" 147 | }, 148 | { 149 | "from": { 150 | "key_code": "right_shift", 151 | "modifiers": { 152 | "mandatory": ["right_command"], 153 | "optional": ["caps_lock"] 154 | } 155 | }, 156 | "to": [{ "key_code": "caps_lock" }], 157 | "to_if_alone": [{ "key_code": "right_shift" }], 158 | "type": "basic" 159 | } 160 | ] 161 | }, 162 | { 163 | "manipulators": [ 164 | { 165 | "description": "Change left control to Hyper Key (command+control+option)", 166 | "from": { 167 | "key_code": "left_control", 168 | "modifiers": { "optional": ["any"] } 169 | }, 170 | "to": [ 171 | { 172 | "key_code": "left_option", 173 | "modifiers": ["left_command", "left_control"] 174 | } 175 | ], 176 | "type": "basic" 177 | } 178 | ] 179 | }, 180 | { 181 | "description": "Toggle caps_lock by pressing left_shift then right_shift", 182 | "manipulators": [ 183 | { 184 | "from": { 185 | "key_code": "left_shift", 186 | "modifiers": { 187 | "mandatory": ["right_shift"], 188 | "optional": ["caps_lock"] 189 | } 190 | }, 191 | "to": [{ "key_code": "caps_lock" }], 192 | "to_if_alone": [{ "key_code": "left_shift" }], 193 | "type": "basic" 194 | }, 195 | { 196 | "from": { 197 | "key_code": "right_shift", 198 | "modifiers": { 199 | "mandatory": ["left_shift"], 200 | "optional": ["caps_lock"] 201 | } 202 | }, 203 | "to": [{ "key_code": "caps_lock" }], 204 | "to_if_alone": [{ "key_code": "right_shift" }], 205 | "type": "basic" 206 | } 207 | ] 208 | }, 209 | { 210 | "description": "Map ctrl + [ to escape", 211 | "manipulators": [ 212 | { 213 | "from": { 214 | "key_code": "open_bracket", 215 | "modifiers": { 216 | "mandatory": ["control"], 217 | "optional": ["any"] 218 | } 219 | }, 220 | "to": [{ "key_code": "escape" }], 221 | "type": "basic" 222 | } 223 | ] 224 | }, 225 | { 226 | "description": "CTRL-W to delete-backward-word", 227 | "manipulators": [ 228 | { 229 | "conditions": [ 230 | { 231 | "bundle_identifiers": [ 232 | "com.googlecode.iterm2", 233 | "net.kovidgoyal.kitty", 234 | "co.zeit.hyper", 235 | "com.apple.Terminal", 236 | "io.alacritty", 237 | "com.valvesoftware.steam" 238 | ], 239 | "type": "frontmost_application_unless" 240 | } 241 | ], 242 | "from": { 243 | "key_code": "w", 244 | "modifiers": { "mandatory": ["control"] } 245 | }, 246 | "to": [ 247 | { 248 | "key_code": "delete_or_backspace", 249 | "modifiers": ["left_option"] 250 | } 251 | ], 252 | "type": "basic" 253 | } 254 | ] 255 | } 256 | ] 257 | }, 258 | "devices": [ 259 | { 260 | "identifiers": { 261 | "is_keyboard": true, 262 | "product_id": 835, 263 | "vendor_id": 1452 264 | }, 265 | "simple_modifications": [ 266 | { 267 | "from": { "apple_vendor_top_case_key_code": "keyboard_fn" }, 268 | "to": [{ "key_code": "left_control" }] 269 | } 270 | ] 271 | }, 272 | { 273 | "identifiers": { 274 | "is_keyboard": true, 275 | "product_id": 591, 276 | "vendor_id": 1452 277 | }, 278 | "treat_as_built_in_keyboard": true 279 | } 280 | ], 281 | "name": "Mach", 282 | "selected": true, 283 | "virtual_hid_keyboard": { 284 | "country_code": 0, 285 | "keyboard_type_v2": "ansi" 286 | } 287 | }, 288 | { 289 | "complex_modifications": { 290 | "rules": [ 291 | { 292 | "description": "Change caps_lock to control if pressed with other keys, to escape if pressed alone.", 293 | "manipulators": [ 294 | { 295 | "from": { 296 | "key_code": "caps_lock", 297 | "modifiers": { "optional": ["any"] } 298 | }, 299 | "to": [ 300 | { 301 | "key_code": "left_control", 302 | "lazy": true 303 | } 304 | ], 305 | "to_if_alone": [ 306 | { 307 | "key_code": "escape", 308 | "lazy": true 309 | } 310 | ], 311 | "type": "basic" 312 | } 313 | ] 314 | }, 315 | { 316 | "description": "Toggle caps_lock by pressing right_command + right_shift at the same time", 317 | "manipulators": [ 318 | { 319 | "from": { 320 | "key_code": "right_command", 321 | "modifiers": { 322 | "mandatory": ["right_shift"], 323 | "optional": ["caps_lock"] 324 | } 325 | }, 326 | "to": [{ "key_code": "caps_lock" }], 327 | "to_if_alone": [{ "key_code": "right_command" }], 328 | "type": "basic" 329 | }, 330 | { 331 | "from": { 332 | "key_code": "right_shift", 333 | "modifiers": { 334 | "mandatory": ["right_command"], 335 | "optional": ["caps_lock"] 336 | } 337 | }, 338 | "to": [{ "key_code": "caps_lock" }], 339 | "to_if_alone": [{ "key_code": "right_shift" }], 340 | "type": "basic" 341 | } 342 | ] 343 | }, 344 | { 345 | "manipulators": [ 346 | { 347 | "description": "Change left control to Hyper Key (command+control+option)", 348 | "from": { 349 | "key_code": "left_control", 350 | "modifiers": { "optional": ["any"] } 351 | }, 352 | "to": [ 353 | { 354 | "key_code": "left_option", 355 | "modifiers": ["left_command", "left_control"] 356 | } 357 | ], 358 | "type": "basic" 359 | } 360 | ] 361 | }, 362 | { 363 | "description": "Toggle caps_lock by pressing left_shift then right_shift", 364 | "manipulators": [ 365 | { 366 | "from": { 367 | "key_code": "left_shift", 368 | "modifiers": { 369 | "mandatory": ["right_shift"], 370 | "optional": ["caps_lock"] 371 | } 372 | }, 373 | "to": [{ "key_code": "caps_lock" }], 374 | "to_if_alone": [{ "key_code": "left_shift" }], 375 | "type": "basic" 376 | }, 377 | { 378 | "from": { 379 | "key_code": "right_shift", 380 | "modifiers": { 381 | "mandatory": ["left_shift"], 382 | "optional": ["caps_lock"] 383 | } 384 | }, 385 | "to": [{ "key_code": "caps_lock" }], 386 | "to_if_alone": [{ "key_code": "right_shift" }], 387 | "type": "basic" 388 | } 389 | ] 390 | }, 391 | { 392 | "description": "Map ctrl + [ to escape", 393 | "manipulators": [ 394 | { 395 | "from": { 396 | "key_code": "open_bracket", 397 | "modifiers": { 398 | "mandatory": ["control"], 399 | "optional": ["any"] 400 | } 401 | }, 402 | "to": [{ "key_code": "escape" }], 403 | "type": "basic" 404 | } 405 | ] 406 | } 407 | ] 408 | }, 409 | "name": "Games", 410 | "virtual_hid_keyboard": { "country_code": 0 } 411 | } 412 | ] 413 | } --------------------------------------------------------------------------------