├── .gitignore ├── .stylua.toml ├── README.md ├── dot-patches ├── files ├── alacritty │ ├── alacritty.toml │ ├── colors │ │ ├── catppuccin-latte.toml │ │ └── catppuccin-mocha.toml │ └── keymaps.toml ├── aliases ├── bashrc ├── bin │ ├── delta-git-diff │ ├── fzf-delta │ ├── gh-create-pr │ ├── git-cleanup │ ├── kitty-update │ ├── prepare-commit-msg │ ├── preview-colors │ ├── sqlize │ ├── tmux-dev │ ├── tmux-smartsplit │ └── wez-dev ├── functions ├── fzf.custom ├── git-config-base ├── kitty │ ├── catppuccin.conf │ ├── kitty.conf │ └── tokyonight.conf ├── nvim │ ├── after │ │ ├── ftplugin │ │ │ ├── dart.lua │ │ │ ├── gitcommit.lua │ │ │ ├── go.lua │ │ │ ├── javascript.vim │ │ │ ├── markdown.lua │ │ │ ├── python.vim │ │ │ ├── typescript.vim │ │ │ ├── vue.lua │ │ │ └── yaml.lua │ │ ├── lsp │ │ │ ├── bashls.lua │ │ │ ├── dartls.lua │ │ │ ├── efm.lua │ │ │ ├── gopls.lua │ │ │ ├── jsonls.lua │ │ │ ├── lua_ls.lua │ │ │ ├── pyright.lua │ │ │ ├── rust_analyzer.lua │ │ │ ├── ts_ls.lua │ │ │ ├── volar.lua │ │ │ └── yamlls.lua │ │ └── plugin │ │ │ ├── autocmd.lua │ │ │ ├── lsp │ │ │ ├── autocmd.lua │ │ │ └── init.lua │ │ │ └── zoomer.vim │ ├── autoload │ │ └── termcmd.vim │ ├── init.lua │ └── lua │ │ └── ag │ │ ├── diagnostics.lua │ │ ├── lsp │ │ ├── common.lua │ │ ├── completion.lua │ │ └── init.lua │ │ ├── mappings.lua │ │ ├── plugins │ │ ├── aerial.lua │ │ ├── alpha.lua │ │ ├── blink.lua │ │ ├── catppuccin.lua │ │ ├── copilot.lua │ │ ├── fterm.lua │ │ ├── git.lua │ │ ├── local.lua │ │ ├── lsp.lua │ │ ├── lualine.lua │ │ ├── luasnip.lua │ │ ├── markdown.lua │ │ ├── misc.lua │ │ ├── snacks.lua │ │ ├── swagger-preview.lua │ │ ├── tokyonight.lua │ │ └── treesitter.lua │ │ ├── snippets │ │ ├── dart.lua │ │ ├── init.lua │ │ ├── python.lua │ │ └── typescript.lua │ │ └── utils.lua ├── profile ├── quarter-life.zsh-theme ├── sketchybar │ ├── colors.sh │ ├── icons.sh │ ├── items │ │ ├── amethyst.sh │ │ ├── app.sh │ │ ├── battery.sh │ │ ├── bluetooth.sh │ │ ├── date-time.sh │ │ ├── net.sh │ │ ├── network.sh │ │ ├── now_playing.sh │ │ ├── settings.sh │ │ └── spaces.sh │ ├── plugins │ │ ├── battery.sh │ │ ├── bluetooth.sh │ │ ├── clock.sh │ │ ├── front_app.sh │ │ ├── net.sh │ │ ├── network.sh │ │ ├── space.sh │ │ ├── spotify.sh │ │ └── window_title.sh │ └── sketchybarrc ├── tmux.conf ├── wezterm.lua ├── zshenv └── zshrc └── setup.sh /.gitignore: -------------------------------------------------------------------------------- 1 | .netrwhist 2 | lazy-lock.json 3 | dash.dash 4 | -------------------------------------------------------------------------------- /.stylua.toml: -------------------------------------------------------------------------------- 1 | indent_type = "Spaces" 2 | indent_width = 4 3 | collapse_simple_statement = "Always" 4 | 5 | [sort_requires] 6 | enabled = true 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Dotfiles 2 | 3 | My own personal configurations, `setup.sh` sort of works to get things set up 4 | 5 | ## Neovim 6 | - [init.lua](./files/nvim/init.lua): Config entry point. Configures basic options, loads [Lazy](https://github.com/folke/lazy.nvim) plugin manager 7 | - [lua/ag/mappings.lua](./files/nvim/lua/ag/mappings.lua): All *general* mappings, nothing plugin specific 8 | - [lua/ag/plugins/](./files/nvim/lua/ag/plugins/): All the plugins I use 9 | - [lua/ag/lsp_config.lua](./files/nvim/lua/ag/lsp_config.lua): LSP configs for the languages I typically use 10 | - [lua/ag/snippets](./files/nvim/lua/ag/snippets/): [LuaSnip](https://github.com/L3MON4D3/LuaSnip) snippet definitions, loaded by [luasnip.lua](./files/nvim/lua/ag/plugins/luasnip.lua) plugin 11 | - [after/plugin/autocmd.lua](./files/nvim/after/plugin/autocmd.lua): Place to stuff all my autocommands 12 | - [after/ftplugin/](./files/nvim/after/ftplugin/): Language-specific editor configuration (special mappings, tab width, etc) 13 | 14 | ## Shell/Terminal 15 | - [zshrc](./files/zshrc): Main ZSH configuration, uses [oh-my-zsh](https://ohmyz.sh/) and pulls in a few other scripts 16 | - [quarter-life.zsh-theme](./files/quarter-life.zsh-theme): A simpler version of the half-life oh-my-zsh theme 17 | - [functions](./files/functions): More complex terminal functions, primarily focused on [FZF](https://github.com/junegunn/fzf) integration 18 | - [wezterm.lua](./files/wezterm.lua): My current terminal config 19 | - [tmux.conf](./files/tmux.conf): My tmux config for when I can't use wezterm 20 | 21 | ## Sketchybar 22 | A customizable MacOS menu bar - https://github.com/FelixKratz/SketchyBar 23 | 24 | All configuration is in [files/sketchybar/](./files/sketchybar/) 25 | 26 | TODO: 27 | - **Use `g` commands more** 28 | 29 | ## GH PR review plugin 30 | **Goal:** Add comments to a PR and submit a review from nvim 31 | 32 | ### Entry 33 | `:ReviewGithub open ` 34 | 1. checkout branch associated w/ PR (`gh pr checkout `) 35 | 2. diff against base branch base branch = `gh pr view --json baseRefName --jq .baseRefName` -> `:DiffviewOpen ` 36 | 37 | ### Functionality 38 | - [ ] `:ReviewGithub start` 39 | - begin new review (?) 40 | - [ ] `:ReviewGithub comment ` 41 | - modes: n, v 42 | - adds comment to current line, selected lines 43 | - [ ] `:ReviewGithub submit|approve|reject` 44 | 45 | ### Unknowns 46 | > [!QUESTION] 47 | > What are the "states" of a pull request? 48 | 49 | > [!QUESTION] 50 | > How do you add/store comments without submitting the review? 51 | 52 | -------------------------------------------------------------------------------- /dot-patches: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Helper to more easily generate/apply commit patches in case work firewalls don't let me push to public github 3 | 4 | 5 | function gen_patches() { 6 | branch_name="$(git branch --show-current)" 7 | if [ "$branch_name" == "master" ]; then 8 | echo "Already on master, nothing to do" 9 | exit 0 10 | fi 11 | 12 | patch_from="$2" 13 | if [ -z "$patch_from" ]; then 14 | patch_from="origin/master" 15 | fi 16 | 17 | today=$(date +%Y-%m-%d) 18 | patch_dir="${HOME}/Documents/patches-${today}" 19 | if [ -d "$patch_dir" ]; then 20 | rm -rf "$patch_dir" 21 | fi 22 | mkdir -p "$patch_dir" 23 | 24 | # Generate patches 25 | gen_patch_cmd="git format-patch -o ${patch_dir} ${patch_from}..HEAD" 26 | echo "$gen_patch_cmd" && eval "$gen_patch_cmd" 27 | 28 | # Zip result 29 | zip_cmd="zip -j ${patch_dir}/patch-${today}.zip ${patch_dir}/*.patch" 30 | echo "$zip_cmd" && eval "$zip_cmd" 31 | 32 | echo "Patch output written to ${patch_dir}/patch-${today}.zip" 33 | exit 0 34 | } 35 | 36 | function apply_patches { 37 | patch_dir="$1" 38 | 39 | if [ ! -d "$patch_dir" ]; then 40 | echo "$patch_dir does not exist, exiting" 41 | exit 1 42 | fi 43 | 44 | cmd="git am ${patch_dir}/*.patch" 45 | echo "$cmd" && eval "$cmd" 46 | } 47 | 48 | case "$1" in 49 | "gen") 50 | gen_patches "$2" 51 | ;; 52 | "apply") 53 | apply_patches "$2" 54 | ;; 55 | "*") 56 | echo "$0 [gen,apply]" 57 | exit 1 58 | esac 59 | -------------------------------------------------------------------------------- /files/alacritty/alacritty.toml: -------------------------------------------------------------------------------- 1 | [bell] 2 | command = "None" 3 | duration = 0 4 | 5 | [cursor] 6 | unfocused_hollow = true 7 | vi_mode_style = "Block" 8 | 9 | [cursor.style] 10 | blinking = "Off" 11 | shape = "Beam" 12 | 13 | [font] 14 | size = 14.0 15 | 16 | [font.normal] 17 | family = "JetBrainsMono Nerd Font Mono" 18 | style = "Regular" 19 | 20 | [hints] 21 | alphabet = "jfkdls;ahgurieowpq" 22 | 23 | # open links 24 | [[hints.enabled]] 25 | command = "open" 26 | post_processing = true 27 | regex = "(ipfs:|ipns:|magnet:|mailto:|gemini:|gopher:|https:|http:|news:|file:|git:|ssh:|ftp:)[^\u0000-\u001F\u007F-Ÿ<>\"\\s{-}\\^⟨⟩`]+" 28 | [hints.enabled.binding] 29 | key = "U" 30 | mods = "Control|Shift" 31 | 32 | # copy aws ARN 33 | [[hints.enabled]] 34 | action = "Copy" 35 | post_processing = true 36 | regex = "(arn:aws:)[A-Za-z0-9:/\\-_]+" 37 | [hints.enabled.binding] 38 | key = "A" 39 | mods = "Control|Shift" 40 | 41 | [scrolling] 42 | history = 10000 43 | multiplier = 3 44 | 45 | [selection] 46 | semantic_escape_chars = ''',│`|:"' ()[]{}<> /''' 47 | 48 | [terminal.shell] 49 | args = ["--login"] 50 | program = "/bin/zsh" 51 | 52 | [window] 53 | decorations = "buttonless" 54 | dynamic_padding = true 55 | dynamic_title = false 56 | startup_mode = "Maximized" 57 | option_as_alt = "OnlyLeft" 58 | 59 | [window.padding] 60 | x = 5 61 | y = 5 62 | 63 | [general] 64 | live_config_reload = true 65 | import = ["colors/catppuccin-mocha.toml", "keymaps.toml"] 66 | 67 | [env] 68 | # https://unix.stackexchange.com/questions/597445/why-would-i-set-term-to-xterm-256color-when-using-alacritty 69 | TERM = "alacritty" 70 | -------------------------------------------------------------------------------- /files/alacritty/colors/catppuccin-latte.toml: -------------------------------------------------------------------------------- 1 | [colors.primary] 2 | background = "#eff1f5" 3 | foreground = "#4c4f69" 4 | dim_foreground = "#8c8fa1" 5 | bright_foreground = "#4c4f69" 6 | 7 | [colors.cursor] 8 | text = "#eff1f5" 9 | cursor = "#dc8a78" 10 | 11 | [colors.vi_mode_cursor] 12 | text = "#eff1f5" 13 | cursor = "#7287fd" 14 | 15 | [colors.search.matches] 16 | foreground = "#eff1f5" 17 | background = "#6c6f85" 18 | 19 | [colors.search.focused_match] 20 | foreground = "#eff1f5" 21 | background = "#40a02b" 22 | 23 | [colors.footer_bar] 24 | foreground = "#eff1f5" 25 | background = "#6c6f85" 26 | 27 | [colors.hints.start] 28 | foreground = "#eff1f5" 29 | background = "#df8e1d" 30 | 31 | [colors.hints.end] 32 | foreground = "#eff1f5" 33 | background = "#6c6f85" 34 | 35 | [colors.selection] 36 | text = "#eff1f5" 37 | background = "#dc8a78" 38 | 39 | [colors.normal] 40 | black = "#bcc0cc" 41 | red = "#d20f39" 42 | green = "#40a02b" 43 | yellow = "#df8e1d" 44 | blue = "#1e66f5" 45 | magenta = "#ea76cb" 46 | cyan = "#179299" 47 | white = "#5c5f77" 48 | 49 | [colors.bright] 50 | black = "#acb0be" 51 | red = "#d20f39" 52 | green = "#40a02b" 53 | yellow = "#df8e1d" 54 | blue = "#1e66f5" 55 | magenta = "#ea76cb" 56 | cyan = "#179299" 57 | white = "#6c6f85" 58 | 59 | [[colors.indexed_colors]] 60 | index = 16 61 | color = "#fe640b" 62 | 63 | [[colors.indexed_colors]] 64 | index = 17 65 | color = "#dc8a78" 66 | -------------------------------------------------------------------------------- /files/alacritty/colors/catppuccin-mocha.toml: -------------------------------------------------------------------------------- 1 | [colors.primary] 2 | background = "#1e1e2e" 3 | foreground = "#cdd6f4" 4 | dim_foreground = "#7f849c" 5 | bright_foreground = "#cdd6f4" 6 | 7 | [colors.cursor] 8 | text = "#1e1e2e" 9 | cursor = "#f5e0dc" 10 | 11 | [colors.vi_mode_cursor] 12 | text = "#1e1e2e" 13 | cursor = "#b4befe" 14 | 15 | [colors.search.matches] 16 | foreground = "#1e1e2e" 17 | background = "#a6adc8" 18 | 19 | [colors.search.focused_match] 20 | foreground = "#1e1e2e" 21 | background = "#a6e3a1" 22 | 23 | [colors.footer_bar] 24 | foreground = "#1e1e2e" 25 | background = "#a6adc8" 26 | 27 | [colors.hints.start] 28 | foreground = "#1e1e2e" 29 | background = "#f38ba8" 30 | 31 | [colors.hints.end] 32 | foreground = "#1e1e2e" 33 | background = "#a6adc8" 34 | 35 | [colors.selection] 36 | text = "#1e1e2e" 37 | background = "#f5e0dc" 38 | 39 | [colors.normal] 40 | black = "#45475a" 41 | red = "#f38ba8" 42 | green = "#a6e3a1" 43 | yellow = "#f9e2af" 44 | blue = "#89b4fa" 45 | magenta = "#f5c2e7" 46 | cyan = "#94e2d5" 47 | white = "#bac2de" 48 | 49 | [colors.bright] 50 | black = "#585b70" 51 | red = "#f38ba8" 52 | green = "#a6e3a1" 53 | yellow = "#f9e2af" 54 | blue = "#89b4fa" 55 | magenta = "#f5c2e7" 56 | cyan = "#94e2d5" 57 | white = "#a6adc8" 58 | 59 | [[colors.indexed_colors]] 60 | index = 16 61 | color = "#fab387" 62 | 63 | [[colors.indexed_colors]] 64 | index = 17 65 | color = "#f5e0dc" 66 | -------------------------------------------------------------------------------- /files/alacritty/keymaps.toml: -------------------------------------------------------------------------------- 1 | [keyboard] 2 | 3 | # "normal" keybindings 4 | [[keyboard.bindings]] 5 | action = "ResetFontSize" 6 | key = "Period" 7 | mods = "Command" 8 | 9 | [[keyboard.bindings]] 10 | action = "IncreaseFontSize" 11 | key = "Equals" 12 | mods = "Command" 13 | 14 | [[keyboard.bindings]] 15 | action = "DecreaseFontSize" 16 | key = "Minus" 17 | mods = "Command" 18 | 19 | [[keyboard.bindings]] 20 | action = "Quit" 21 | key = "Q" 22 | mods = "Command" 23 | 24 | [[keyboard.bindings]] 25 | action = "None" 26 | key = "W" 27 | mods = "Command" 28 | 29 | [[keyboard.bindings]] 30 | action = "SpawnNewInstance" 31 | key = "N" 32 | mods = "Command" 33 | 34 | [[keyboard.bindings]] 35 | action = "ToggleViMode" 36 | key = "J" 37 | mode = "~Search" 38 | mods = "Shift|Control" 39 | 40 | # VI mode keybindings 41 | [[keyboard.bindings]] 42 | action = "ClearSelection" 43 | key = "Escape" 44 | mode = "Vi|~Search" 45 | 46 | [[keyboard.bindings]] 47 | action = "ToggleViMode" 48 | key = "C" 49 | mode = "Vi|~Search" 50 | mods = "Control" 51 | 52 | [[keyboard.bindings]] 53 | action = "ScrollLineUp" 54 | key = "Y" 55 | mode = "Vi|~Search" 56 | mods = "Control" 57 | 58 | [[keyboard.bindings]] 59 | action = "ScrollLineDown" 60 | key = "E" 61 | mode = "Vi|~Search" 62 | mods = "Control" 63 | 64 | [[keyboard.bindings]] 65 | action = "ScrollToTop" 66 | key = "G" 67 | mode = "Vi|~Search" 68 | 69 | [[keyboard.bindings]] 70 | action = "ScrollToBottom" 71 | key = "G" 72 | mode = "Vi|~Search" 73 | mods = "Shift" 74 | 75 | [[keyboard.bindings]] 76 | action = "ScrollPageUp" 77 | key = "B" 78 | mode = "Vi|~Search" 79 | mods = "Control" 80 | 81 | [[keyboard.bindings]] 82 | action = "ScrollPageDown" 83 | key = "F" 84 | mode = "Vi|~Search" 85 | mods = "Control" 86 | 87 | [[keyboard.bindings]] 88 | action = "ScrollHalfPageUp" 89 | key = "U" 90 | mode = "Vi|~Search" 91 | mods = "Control" 92 | 93 | [[keyboard.bindings]] 94 | action = "ScrollHalfPageDown" 95 | key = "D" 96 | mode = "Vi|~Search" 97 | mods = "Control" 98 | 99 | [[keyboard.bindings]] 100 | action = "Copy" 101 | key = "Y" 102 | mode = "Vi|~Search" 103 | 104 | [[keyboard.bindings]] 105 | action = "ClearSelection" 106 | key = "Y" 107 | mode = "Vi|~Search" 108 | 109 | [[keyboard.bindings]] 110 | action = "ToggleNormalSelection" 111 | key = "V" 112 | mode = "Vi|~Search" 113 | 114 | [[keyboard.bindings]] 115 | action = "ToggleLineSelection" 116 | key = "V" 117 | mode = "Vi|~Search" 118 | mods = "Shift" 119 | 120 | [[keyboard.bindings]] 121 | action = "ToggleBlockSelection" 122 | key = "V" 123 | mode = "Vi|~Search" 124 | mods = "Control" 125 | 126 | [[keyboard.bindings]] 127 | action = "ToggleSemanticSelection" 128 | key = "V" 129 | mode = "Vi|~Search" 130 | mods = "Alt" 131 | 132 | [[keyboard.bindings]] 133 | action = "Open" 134 | key = "Return" 135 | mode = "Vi|~Search" 136 | 137 | [[keyboard.bindings]] 138 | action = "Up" 139 | key = "K" 140 | mode = "Vi|~Search" 141 | 142 | [[keyboard.bindings]] 143 | action = "Down" 144 | key = "J" 145 | mode = "Vi|~Search" 146 | 147 | [[keyboard.bindings]] 148 | action = "Left" 149 | key = "H" 150 | mode = "Vi|~Search" 151 | 152 | [[keyboard.bindings]] 153 | action = "Right" 154 | key = "L" 155 | mode = "Vi|~Search" 156 | 157 | [[keyboard.bindings]] 158 | action = "Up" 159 | key = "Up" 160 | mode = "Vi|~Search" 161 | 162 | [[keyboard.bindings]] 163 | action = "Down" 164 | key = "Down" 165 | mode = "Vi|~Search" 166 | 167 | [[keyboard.bindings]] 168 | action = "Left" 169 | key = "Left" 170 | mode = "Vi|~Search" 171 | 172 | [[keyboard.bindings]] 173 | action = "Right" 174 | key = "Right" 175 | mode = "Vi|~Search" 176 | 177 | [[keyboard.bindings]] 178 | action = "High" 179 | key = "H" 180 | mode = "Vi|~Search" 181 | mods = "Shift" 182 | 183 | [[keyboard.bindings]] 184 | action = "Middle" 185 | key = "M" 186 | mode = "Vi|~Search" 187 | mods = "Shift" 188 | 189 | [[keyboard.bindings]] 190 | action = "Low" 191 | key = "L" 192 | mode = "Vi|~Search" 193 | mods = "Shift" 194 | 195 | [[keyboard.bindings]] 196 | action = "SemanticLeft" 197 | key = "B" 198 | mode = "Vi|~Search" 199 | 200 | [[keyboard.bindings]] 201 | action = "SemanticRight" 202 | key = "W" 203 | mode = "Vi|~Search" 204 | 205 | [[keyboard.bindings]] 206 | action = "SemanticRightEnd" 207 | key = "E" 208 | mode = "Vi|~Search" 209 | 210 | [[keyboard.bindings]] 211 | action = "WordLeft" 212 | key = "B" 213 | mode = "Vi|~Search" 214 | mods = "Shift" 215 | 216 | [[keyboard.bindings]] 217 | action = "WordRight" 218 | key = "W" 219 | mode = "Vi|~Search" 220 | mods = "Shift" 221 | 222 | [[keyboard.bindings]] 223 | action = "WordRightEnd" 224 | key = "E" 225 | mode = "Vi|~Search" 226 | mods = "Shift" 227 | 228 | [[keyboard.bindings]] 229 | action = "SearchForward" 230 | key = "Slash" 231 | mode = "Vi|~Search" 232 | 233 | [[keyboard.bindings]] 234 | action = "SearchBackward" 235 | key = "Slash" 236 | mode = "Vi|~Search" 237 | mods = "Shift" 238 | 239 | [[keyboard.bindings]] 240 | action = "SearchNext" 241 | key = "N" 242 | mode = "Vi|~Search" 243 | 244 | [[keyboard.bindings]] 245 | action = "SearchPrevious" 246 | key = "N" 247 | mode = "Vi|~Search" 248 | mods = "Shift" 249 | -------------------------------------------------------------------------------- /files/aliases: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Essentials 4 | if [[ $(command -v eza) ]]; then 5 | alias ll='eza -hal --icons=auto' 6 | alias la='eza -a' 7 | alias show='eza -hal $(fzf-ls)' 8 | alias tree="eza -T" 9 | else 10 | alias ll='ls -la' 11 | alias la='ls -a' 12 | alias show='ls -la $(fzf-ls)' 13 | fi 14 | alias v='nvim' 15 | alias c='cd $(fzf-cd)' 16 | alias td='tmux-dev' 17 | alias wd='source $HOME/bin/wez-dev' 18 | 19 | alias pp='pbpaste' 20 | alias pc='pbcopy' 21 | 22 | # Typos 23 | alias claer='clear' 24 | alias clera='clear' 25 | alias :wq='echo "Wrong pane"' 26 | alias :w='echo "Wrong pane"' 27 | alias :q='echo "Wrong pane"' 28 | 29 | # Git 30 | alias gs='git status' 31 | alias gd='git diff' 32 | alias gdc='git diff --cached' 33 | 34 | alias gl="git log \ 35 | --graph \ 36 | --stat \ 37 | --stat-graph-width=15 \ 38 | --pretty='%C(#a6e3a1)%h%Creset -%C(auto)%d%Creset %C(bold)%C(#f5e0dc)%s%Creset %C(#a6adc8)(%as - %an)%Creset'" 39 | alias gc='fzf-git-checkout' 40 | alias gpf='gpush --force-with-lease' 41 | alias gf='git commit --fixup="$(fzf-git-commits -q)"' 42 | alias cpr='gh-create-pr' 43 | alias gpush='git push' 44 | 45 | alias kitty-update='curl -L https://sw.kovidgoyal.net/kitty/installer.sh | sh /dev/stdin' 46 | 47 | # sqlize, but use clipboard as in/out 48 | alias pbsqlize='pbpaste | sqlize | pbcopy' 49 | -------------------------------------------------------------------------------- /files/bashrc: -------------------------------------------------------------------------------- 1 | # ~/.bashrc: executed by bash(1) for non-login shells. 2 | # see /usr/share/doc/bash/examples/startup-files (in the package bash-doc) 3 | # for examples 4 | 5 | # If not running interactively, don't do anything 6 | case $- in 7 | *i*) ;; 8 | *) return;; 9 | esac 10 | 11 | # don't put duplicate lines or lines starting with space in the history. 12 | # See bash(1) for more options 13 | HISTCONTROL=ignoreboth 14 | 15 | # append to the history file, don't overwrite it 16 | shopt -s histappend 17 | 18 | # for setting history length see HISTSIZE and HISTFILESIZE in bash(1) 19 | HISTSIZE=1000 20 | HISTFILESIZE=2000 21 | 22 | # check the window size after each command and, if necessary, 23 | # update the values of LINES and COLUMNS. 24 | shopt -s checkwinsize 25 | 26 | # If set, the pattern "**" used in a pathname expansion context will 27 | # match all files and zero or more directories and subdirectories. 28 | #shopt -s globstar 29 | 30 | # make less more friendly for non-text input files, see lesspipe(1) 31 | [ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)" 32 | 33 | # set variable identifying the chroot you work in (used in the prompt below) 34 | if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then 35 | debian_chroot=$(cat /etc/debian_chroot) 36 | fi 37 | 38 | # set a fancy prompt (non-color, unless we know we "want" color) 39 | case "$TERM" in 40 | xterm-color|*-256color) color_prompt=yes;; 41 | esac 42 | 43 | # uncomment for a colored prompt, if the terminal has the capability; turned 44 | # off by default to not distract the user: the focus in a terminal window 45 | # should be on the output of commands, not on the prompt 46 | #force_color_prompt=yes 47 | 48 | if [ -n "$force_color_prompt" ]; then 49 | if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then 50 | # We have color support; assume it's compliant with Ecma-48 51 | # (ISO/IEC-6429). (Lack of such support is extremely rare, and such 52 | # a case would tend to support setf rather than setaf.) 53 | color_prompt=yes 54 | else 55 | color_prompt= 56 | fi 57 | fi 58 | 59 | if [ "$color_prompt" = yes ]; then 60 | PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ ' 61 | else 62 | PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ ' 63 | fi 64 | unset color_prompt force_color_prompt 65 | 66 | # If this is an xterm set the title to user@host:dir 67 | case "$TERM" in 68 | xterm*|rxvt*) 69 | PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1" 70 | ;; 71 | *) 72 | ;; 73 | esac 74 | 75 | # enable color support of ls and also add handy aliases 76 | if [ -x /usr/bin/dircolors ]; then 77 | test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)" 78 | alias ls='ls --color=auto' 79 | #alias dir='dir --color=auto' 80 | #alias vdir='vdir --color=auto' 81 | 82 | alias grep='grep --color=auto' 83 | alias fgrep='fgrep --color=auto' 84 | alias egrep='egrep --color=auto' 85 | fi 86 | 87 | # colored GCC warnings and errors 88 | export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01' 89 | 90 | # Add an "alert" alias for long running commands. Use like so: 91 | # sleep 10; alert 92 | alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"' 93 | 94 | # Alias definitions. 95 | # You may want to put all your additions into a separate file like 96 | # ~/.bash_aliases, instead of adding them here directly. 97 | # See /usr/share/doc/bash-doc/examples in the bash-doc package. 98 | 99 | if [ -f ~/.bash_aliases ]; then 100 | . ~/.bash_aliases 101 | fi 102 | if [ -f ~/.aliases ]; then 103 | . ~/.aliases 104 | fi 105 | 106 | # enable programmable completion features (you don't need to enable 107 | # this, if it's already enabled in /etc/bash.bashrc and /etc/profile 108 | # sources /etc/bash.bashrc). 109 | if ! shopt -oq posix; then 110 | if [ -f /usr/share/bash-completion/bash_completion ]; then 111 | . /usr/share/bash-completion/bash_completion 112 | elif [ -f /etc/bash_completion ]; then 113 | . /etc/bash_completion 114 | fi 115 | fi 116 | 117 | # === *** === 118 | # My configs 119 | # === *** === 120 | if [ "$USER" == "agarcia02" ]; then 121 | # Setup fds certificates 122 | export FDS_CERT=/mnt/c/ProgramData/DesktopSystems/Git/ca-bundle.crt 123 | export REQUESTS_CA_BUNDLE="$FDS_CERT" 124 | echo "cacert=$FDS_CERT" > ~/.curlrc 125 | export HOMEBREW_CURLRC=1 126 | export NODE_EXTRA_CA_CERT="$FDS_CERT" 127 | export NODE_EXTRA_CA_CERTS="$FDS_CERT" 128 | export SSL_CERT_FILE="$FDS_CERT" 129 | fi 130 | # Essentials 131 | export EDITOR='nvim' 132 | set -o vi 133 | # use bat for manpager 134 | export MANPAGER="sh -c 'col -bx | bat -l man -p'" 135 | 136 | # If ~/.inputrc doesn't exist yet: First include the original /etc/inputrc 137 | # so it won't get overriden 138 | if [ ! -a ~/.inputrc ]; then echo '$include /etc/inputrc' > ~/.inputrc; fi 139 | # Add shell-option to ~/.inputrc to enable case-insensitive tab completion 140 | echo 'set completion-ignore-case On' >> ~/.inputrc 141 | # NO BELLS 142 | echo 'set bell-style none' >> ~/.inputrc 143 | 144 | # Let gcc play with brew 145 | export LDFLAGS="-L$(brew --prefix)/opt/zlib/lib -L$(brew --prefix)/opt/bzip2/lib" 146 | export CPPFLAGS="-I$(brew --prefix)/opt/zlib/include -I$(brew --prefix)/opt/bzip2/include" 147 | export CFLAGS="-O2" 148 | 149 | # Look && feel 150 | # PS1 helper 151 | parse_git_branch() { 152 | git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/ (\1)/' 153 | } 154 | # green cwd (yellow git branch name if any) $ 155 | export PS1="\[\033[32m\]\w\[\033[33m\]\$(parse_git_branch)\[\033[00m\] $ " 156 | # Pick up base16_colors, set by running `base16_{color name}` in shell 157 | BASE16_SHELL="$HOME/.config/base16-shell/" 158 | [ -n "$PS1" ] && \ 159 | [ -s "$BASE16_SHELL/profile_helper.sh" ] && \ 160 | eval "$("$BASE16_SHELL/profile_helper.sh")" 161 | 162 | # FZF 163 | [ -f ~/.fzf.bash ] && source ~/.fzf.bash 164 | export FZF_DEFAULT_COMMAND='rg --files --smart-case' 165 | export FZF_CTRL_T_COMMAND='rg --files --smart-case' 166 | export FZF_DEFAULT_OPTS="--height 40% --reverse" 167 | # Preview files (but not everything else) with bat 168 | export FZF_CTRL_T_OPTS="$FZF_DEFAULT_OPTS \ 169 | --preview 'bat --color=always --line-range=:40 --style=numbers,changes {}'" 170 | 171 | # Node 172 | export NVM_DIR="$HOME/.nvm" 173 | [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm 174 | [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion 175 | 176 | # Pyenv default python 177 | export PYENV_VERSION="3.8.11" 178 | 179 | # Lua ls 180 | export PATH="$PATH:$HOME/lua-language-server/bin/Linux/" 181 | alias luamake=/home/agarcia/lua-language-server/3rd/luamake/luamake 182 | -------------------------------------------------------------------------------- /files/bin/delta-git-diff: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | status_output=$1 4 | if [[ -z "$status_output" ]]; then 5 | exit 0 6 | fi 7 | 8 | fname="${status_output##* }" 9 | status_cols="${status_output% *}" 10 | 11 | if [[ "$status_cols" == 'M ' ]]; then 12 | # staged changes 13 | git diff --staged --color=always -- "$fname" | fzf-delta 14 | elif [[ "$status_cols" == '??' ]]; then 15 | # new file 16 | bat --color=always -- "$fname" 17 | else 18 | git diff --color=always -- "$fname" | fzf-delta 19 | fi 20 | -------------------------------------------------------------------------------- /files/bin/fzf-delta: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cols=${FZF_PREVIEW_COLUMNS:-$COLUMNS} 4 | if [[ ! "$cols" ]]; then 5 | delta "$@" 6 | exit 0 7 | fi 8 | 9 | if [[ $cols -gt 175 ]]; then 10 | DELTA_FEATURES=+side-by-side delta -w "$cols" "$@" 11 | else 12 | delta -w "$cols" "$@" 13 | fi 14 | -------------------------------------------------------------------------------- /files/bin/gh-create-pr: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | function get_jira_ticket() { 4 | local branch="$1" 5 | local jira_ticket="$(echo $cur_branch | grep -Eo '\w+-\d+')" 6 | echo "$jira_ticket" 7 | } 8 | 9 | function prepare_title() { 10 | local cur_branch="$1" 11 | local base_branch="$2" 12 | 13 | # parse branch info into PR title 14 | # ideally ["feature","bugfix","chore"]// 15 | # -> feat(description): [jira ticket] 16 | local branch_type="$(echo $cur_branch | cut -d/ -f1)" 17 | # simplify subject 18 | if [[ "$branch_type" == *feat* ]]; then branch_type="feat"; fi 19 | if [[ "$branch_type" == *bug* || "$branch_type" == *fix* ]]; then branch_type="fix"; fi 20 | 21 | local jira_ticket=$(get_jira_ticket $cur_branch) 22 | if [ -n "$jira_ticket" ]; then 23 | local branch_desc="$(echo $cur_branch | cut -d/ -f3)" 24 | else 25 | local branch_desc="$(echo $cur_branch | cut -d/ -f2)" 26 | fi 27 | 28 | # Compute how we're starting the PR title 29 | # feature/my-branch -> feat(my-branch): 30 | # lazy-branch-name -> lazy-branch-name: 31 | local title_prefix 32 | if [ -n "$branch_desc" ]; then 33 | title_prefix="$branch_type($branch_desc):" 34 | else 35 | title_prefix="$branch_type:" 36 | fi 37 | 38 | # Like the GH UI, if we only have a single commit, use its title 39 | # as the PR title 40 | if [ -n "$(is_single_commit $cur_branch $base_branch)" ]; then 41 | local commit_title="$(git log -1 --pretty=%B | head -n1)" 42 | title_prefix="$commit_title" # completely overwrites $title_prefix to avoid duplicate "chore(foo):" 43 | fi 44 | 45 | # If we have jira info, attach that to the end of the title 46 | [ -n "$jira_ticket" ] && title_prefix="$title_prefix [$jira_ticket]" 47 | 48 | local title_desc 49 | title_desc="$(read_with_default $title_prefix)" 50 | echo "$title_desc" 51 | } 52 | 53 | function read_with_default() { 54 | local input="$1" 55 | vared -M emacs input # https://stackoverflow.com/questions/67046056/line-editing-with-zshs-vared-from-within-script 56 | print -lr -- "$input" 57 | } 58 | 59 | function is_single_commit() { 60 | local cur_branch="$1" 61 | local base_branch="$2" 62 | local ahead_commits="$(git rev-list --count $base_branch..$cur_branch)" 63 | if [ "$ahead_commits" -eq 1 ]; then 64 | echo "yes" 65 | fi 66 | } 67 | 68 | function create_pr_body { 69 | local fname="$1" 70 | local cur_branch="$2" 71 | local base_branch="$3" 72 | 73 | if [ -n "$(is_single_commit $cur_branch $base_branch)" ]; then 74 | local commit_msg="$(git log -1 --pretty=%B | tail +2)" 75 | [ -n "$commit_msg" ] && echo "$commit_msg" >> "$tmp_file" 76 | fi 77 | 78 | local jira_ticket="$(get_jira_ticket $cur_branch)" 79 | [ -n "$jira_ticket" ] && echo "\n\n[$jira_ticket]($JIRA_BASE_URL/browse/$jira_ticket)" >> "$tmp_file" 80 | local nvim_cmd="nvim --cmd 'set ft=markdown' --cmd 'set foldlevelstart=99' -- $fname" 81 | eval "$nvim_cmd" 82 | } 83 | 84 | function cpr() { 85 | command -v "gh" > /dev/null 2>&1 || (echo -e "${RED}gh cli not installed${NC}" && exit 1) 86 | 87 | # Select PR base branch 88 | echo -e "${BLUE}Select base branch${NC}" 89 | local base_branch="$(fzf-git-branch 'Base')" 90 | local cur_branch="$(git branch --show-current)" 91 | 92 | echo -e "${BLUE}Enter PR title${NC}" 93 | local title="$(prepare_title $cur_branch $base_branch)" 94 | 95 | local tmp_file="$(mktemp)" 96 | create_pr_body "$tmp_file" "$cur_branch" "$base_branch" 97 | 98 | gh pr new --assignee="@me" --base="$base_branch" --body-file="$tmp_file" --title="$title" "$@" 99 | } 100 | 101 | cpr "$@" 102 | -------------------------------------------------------------------------------- /files/bin/git-cleanup: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | main() { 4 | local branches 5 | branches="$(git branch --list)" 6 | local primary 7 | if echo "$branches" | grep -q 'main'; then 8 | primary="main" 9 | elif echo "$branches" | grep -q 'master'; then 10 | primary="master" 11 | fi 12 | 13 | if [[ -z "$primary" ]]; then 14 | exit 0 15 | fi 16 | 17 | local cmd 18 | cmd="git branch --merged $primary | grep -Ev '$primary|qa|develop' | xargs git branch -d" 19 | 20 | eval "$cmd" 21 | } 22 | 23 | main 24 | -------------------------------------------------------------------------------- /files/bin/kitty-update: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | curl -L https://sw.kovidgoyal.net/kitty/installer.sh | sh /dev/stdin 4 | -------------------------------------------------------------------------------- /files/bin/prepare-commit-msg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | COMMIT_MSG_FILE=$1 4 | COMMIT_SOURCE=$2 5 | SHA1=$3 6 | 7 | if ! command -v "llm" >/dev/null 2>&1; then 8 | exit 0 9 | fi 10 | 11 | echo "Generating commit message..." 12 | changes="$(git diff --cached)" 13 | prompt="Describe the following changes in the form of a git commit message. Make sure to include a brief summary as the title, and a bulleted list of changes below.\nCHANGES:\n$changes" 14 | echo "$prompt" | llm | cat - "$COMMIT_MSG_FILE" > "/tmp/cat-commit" && mv "/tmp/cat-commit" "$COMMIT_MSG_FILE" 15 | -------------------------------------------------------------------------------- /files/bin/preview-colors: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Stolen from https://askubuntu.com/questions/821157/print-a-256-color-test-pattern-in-the-terminal 4 | 5 | # Tom Hale, 2016. MIT Licence. 6 | # Print out 256 colours, with each number printed in its corresponding colour 7 | # See http://askubuntu.com/questions/821157/print-a-256-color-test-pattern-in-the-terminal/821163#821163 8 | 9 | set -eu # Fail on errors or undeclared variables 10 | 11 | printable_colours=256 12 | 13 | # Return a colour that contrasts with the given colour 14 | # Bash only does integer division, so keep it integral 15 | function contrast_colour { 16 | local r g b luminance 17 | colour="$1" 18 | 19 | if (( colour < 16 )); then # Initial 16 ANSI colours 20 | (( colour == 0 )) && printf "15" || printf "0" 21 | return 22 | fi 23 | 24 | # Greyscale # rgb_R = rgb_G = rgb_B = (number - 232) * 10 + 8 25 | if (( colour > 231 )); then # Greyscale ramp 26 | (( colour < 244 )) && printf "15" || printf "0" 27 | return 28 | fi 29 | 30 | # All other colours: 31 | # 6x6x6 colour cube = 16 + 36*R + 6*G + B # Where RGB are [0..5] 32 | # See http://stackoverflow.com/a/27165165/5353461 33 | 34 | # r=$(( (colour-16) / 36 )) 35 | g=$(( ((colour-16) % 36) / 6 )) 36 | # b=$(( (colour-16) % 6 )) 37 | 38 | # If luminance is bright, print number in black, white otherwise. 39 | # Green contributes 587/1000 to human perceived luminance - ITU R-REC-BT.601 40 | (( g > 2)) && printf "0" || printf "15" 41 | return 42 | 43 | # Uncomment the below for more precise luminance calculations 44 | 45 | # # Calculate percieved brightness 46 | # # See https://www.w3.org/TR/AERT#color-contrast 47 | # # and http://www.itu.int/rec/R-REC-BT.601 48 | # # Luminance is in range 0..5000 as each value is 0..5 49 | # luminance=$(( (r * 299) + (g * 587) + (b * 114) )) 50 | # (( $luminance > 2500 )) && printf "0" || printf "15" 51 | } 52 | 53 | # Print a coloured block with the number of that colour 54 | function print_colour { 55 | local colour="$1" contrast 56 | contrast=$(contrast_colour "$1") 57 | printf "\e[48;5;%sm" "$colour" # Start block of colour 58 | printf "\e[38;5;%sm%3d" "$contrast" "$colour" # In contrast, print number 59 | printf "\e[0m " # Reset colour 60 | } 61 | 62 | # Starting at $1, print a run of $2 colours 63 | function print_run { 64 | local i 65 | for (( i = "$1"; i < "$1" + "$2" && i < printable_colours; i++ )) do 66 | print_colour "$i" 67 | done 68 | printf " " 69 | } 70 | 71 | # Print blocks of colours 72 | function print_blocks { 73 | local start="$1" i 74 | local end="$2" # inclusive 75 | local block_cols="$3" 76 | local block_rows="$4" 77 | local blocks_per_line="$5" 78 | local block_length=$((block_cols * block_rows)) 79 | 80 | # Print sets of blocks 81 | for (( i = start; i <= end; i += (blocks_per_line-1) * block_length )) do 82 | printf "\n" # Space before each set of blocks 83 | # For each block row 84 | for (( row = 0; row < block_rows; row++ )) do 85 | # Print block columns for all blocks on the line 86 | for (( block = 0; block < blocks_per_line; block++ )) do 87 | print_run $(( i + (block * block_length) )) "$block_cols" 88 | done 89 | (( i += block_cols )) # Prepare to print the next row 90 | printf "\n" 91 | done 92 | done 93 | } 94 | 95 | print_run 0 16 # The first 16 colours are spread over the whole spectrum 96 | printf "\n" 97 | print_blocks 16 231 6 6 3 # 6x6x6 colour cube between 16 and 231 inclusive 98 | print_blocks 232 255 12 2 1 # Not 50, but 24 Shades of Grey 99 | -------------------------------------------------------------------------------- /files/bin/sqlize: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import sys 3 | 4 | 5 | def main(): 6 | lines = [] 7 | for line in sys.stdin: 8 | if line.strip() == 'END': 9 | break 10 | if len(line.strip()) > 0: 11 | lines.append(f"'{line.strip()}'") 12 | print(','.join(lines)) 13 | 14 | 15 | if __name__ == '__main__': 16 | main() 17 | -------------------------------------------------------------------------------- /files/bin/tmux-dev: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | function work { 4 | local session='dev' 5 | if [ -n "${TMUX}" ]; then 6 | if tmux list-sessions | grep -q "^$session:"; then 7 | return 8 | fi 9 | fi 10 | tmux new-session -d -s "$session" -c "$HOME/work" # working session 11 | 12 | # open terminal in vertical split pane 13 | tmux split-window -h -c "$HOME/work" 14 | # Keep focus in original pane 15 | tmux select-pane -t "$session:1.1" 16 | # Adjust pane sizes if necessary (this only sort of works) 17 | local width 18 | width=$(tput cols) 19 | if [ "$width" -gt 300 ]; then 20 | tmux resize-pane -t "$session:1.1" -x '66%' 21 | fi 22 | } 23 | 24 | function notes { 25 | local session='notes' 26 | if [ -n "${TMUX}" ]; then 27 | if tmux list-sessions | grep -q "^$session:"; then 28 | return 29 | fi 30 | fi 31 | 32 | tmux new-session -d -s "$session" -c "$HOME/notes" 33 | } 34 | 35 | function dotfiles { 36 | local session='dotfiles' 37 | if [ -n "${TMUX}" ]; then 38 | if tmux list-sessions | grep -q "^$session:"; then 39 | return 40 | fi 41 | fi 42 | 43 | tmux new-session -d -s "$session" -c "$HOME/dotfiles" 44 | } 45 | 46 | function apps { 47 | open '/Applications/Slack.app/' 48 | open '/Applications/Obsidian.app/' 49 | open 'https://gmail.com' 'https://calendar.google.com' 50 | [ -n "${JIRA_URL}" ] && open "${JIRA_URL}" 51 | } 52 | 53 | function main { 54 | dotfiles 55 | work 56 | # open slack 57 | if [[ "$1" == true ]]; then 58 | apps 59 | fi 60 | 61 | # no tmux active 62 | if [[ -z "${TMUX:-}" ]]; then 63 | tmux attach-session -t 'dev' 64 | tmux select-pane -t 'dev:1.1' 65 | fi 66 | } 67 | 68 | open_progs=true 69 | for arg in "$@"; do 70 | if [[ "$arg" == "-q" ]]; then 71 | open_progs=false 72 | fi 73 | done 74 | 75 | main "$open_progs" 76 | -------------------------------------------------------------------------------- /files/bin/tmux-smartsplit: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Usage: 4 | # tmux-smartsplit [CWD] 5 | 6 | main() { 7 | cols="$(tmux display-message -p -F '#{pane_width}')" 8 | cur_path="$(tmux display-message -p -F '#{pane_current_path}')" 9 | 10 | if [[ ! "$cols" ]]; then 11 | tmux split-window -h -c "$cur_path" 12 | exit 0 13 | fi 14 | 15 | if [[ $cols -gt 300 ]]; then 16 | tmux split-window -h -c "$cur_path" -l "$(( cols / 3 ))" 17 | else 18 | tmux split-window -h -c "$cur_path" 19 | fi 20 | exit 0 21 | } 22 | 23 | main 24 | -------------------------------------------------------------------------------- /files/bin/wez-dev: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | function work { 4 | local max_cols=300 5 | work="$HOME/work" 6 | cd "$work" || exit 7 | if [[ $COLUMNS -gt $max_cols || $COLUMS -eq $max_cols ]]; then 8 | percent=33 9 | wezterm cli split-pane --cwd "$work" --right --percent "$percent" 10 | fi 11 | } 12 | 13 | function dotfiles { 14 | wezterm cli spawn --cwd "$HOME/dotfiles" --new-window --workspace "dotfiles" -- /bin/zsh -l 15 | } 16 | 17 | function notes { 18 | wezterm cli spawn --cwd "$HOME/notes" --new-window --workspace "notes" -- /bin/zsh -l 19 | } 20 | 21 | function main { 22 | work > /dev/null 23 | dotfiles > /dev/null 24 | notes > /dev/null 25 | wezterm cli activate-tab --tab-id 0 26 | 27 | if [[ "$1" == true ]]; then 28 | # open up gmail, calendar 29 | open 'https://gmail.com' 'https://calendar.google.com' 30 | if [[ -n "${JIRA_URL}" ]]; then 31 | open "$JIRA_URL" 32 | fi 33 | 34 | # open slack 35 | open '/Applications/Slack.app/' 36 | fi 37 | } 38 | 39 | open_progs=true 40 | for arg in "$@"; do 41 | if [[ "$arg" == "-q" ]]; then 42 | open_progs=false 43 | fi 44 | done 45 | 46 | main "$open_progs" 47 | -------------------------------------------------------------------------------- /files/functions: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | export RED='\033[0;31m' 3 | export GREEN='\033[0;32m' 4 | export YELLOW='\033[0;33m' 5 | export BLUE='\033[0;34m' 6 | export NC='\033[0m' # No Color 7 | 8 | join-lines() { 9 | local item 10 | while read item; do 11 | echo -n "${(q)item} " 12 | done 13 | } 14 | 15 | # Git 16 | cg () { 17 | is-git-repo || { echo 'Not in git repo'; return 0 } 18 | cd $(git rev-parse --show-toplevel) 19 | } 20 | 21 | is-git-repo() { 22 | git rev-parse HEAD > /dev/null 2>&1 23 | } 24 | 25 | # CD helpers 26 | function cdp() { 27 | cd "${HOME}/Projects/${1}" 28 | } 29 | compdef '_path_files -/ -W $HOME/Projects' cdp 30 | function cdw() { 31 | cd "${HOME}/work/${1}" 32 | } 33 | compdef '_path_files -/ -W $HOME/work' cdw 34 | 35 | # send keys to all visible wezterm panes 36 | ws() { 37 | local cmd="$@" 38 | 39 | if [[ -z "$cmd" ]]; then 40 | return 41 | fi 42 | 43 | local wez_list="$(wezterm cli list --format json)" 44 | local cur_pane_id="$WEZTERM_PANE" 45 | 46 | # get current tab 47 | local cur_tab_id="$(echo $wez_list | jq -r --arg PANE $WEZTERM_PANE '.[] | select(.pane_id==($PANE | tonumber)).tab_id')" 48 | # get all panes in current tab 49 | local cur_tab_panes="$(echo $wez_list | jq -r --arg TAB $cur_tab_id '.[] | select(.tab_id==($TAB | tonumber)).pane_id')" 50 | 51 | for pane_id in $(echo $cur_tab_panes); do 52 | echo "${cmd}" | wezterm cli send-text --no-paste --pane-id "${pane_id}" 53 | done 54 | } 55 | 56 | # update all panes in current tab to the given directory 57 | cda() { 58 | local target_dir="$1" 59 | if [[ -z "${target_dir}" ]]; then 60 | target_dir="$HOME" 61 | fi 62 | 63 | ws "cd ${target_dir}" 64 | } 65 | compdef '_path_files -/' cda 66 | 67 | # FZF 68 | zle -N ctrl-t-widget 69 | ctrl-t-widget() { 70 | local result='' 71 | # If the current command is 'git add ', 'git restore ', or 'git checkout ' fuzzy find changed files 72 | if [[ $LBUFFER =~ '^git (add|restore|checkout|stash) ' || $LBUFFER =~ '^ga ' ]]; then 73 | result=$(fzf-git-changed | join-lines) 74 | # Find only '.spec' files 75 | elif [[ $LBUFFER =~ '^(yarn|pnpm) test ' ]]; then 76 | result=$(fzf-js-test | join-lines) 77 | elif [[ $LBUFFER =~ 'pytest' ]]; then 78 | result=$(fzf-pytest | join-lines) 79 | # Otherwise do default and fuzzy search all files 80 | else 81 | result=$(fzf-ctrl-t | join-lines) 82 | fi 83 | zle reset-prompt 84 | LBUFFER+=$result 85 | } 86 | bindkey '' ctrl-t-widget 87 | 88 | vs() { 89 | local cmd='fd -tf' 90 | local fzf_cmd="fzf \ 91 | --scheme path \ 92 | --list-label 'Files' \ 93 | --preview 'bat --color=always --style=numbers,changes {}' \ 94 | --header 'enter: open in \$EDITOR' \ 95 | --bind 'enter:become(${EDITOR:-nvim} {+})'" 96 | 97 | eval "$cmd" | eval "$fzf_cmd" 98 | } 99 | 100 | fzf-ctrl-t() { 101 | local cmd='fd -tf' 102 | local fzf_cmd="fzf \ 103 | --scheme path \ 104 | --list-label 'Files' \ 105 | --preview 'bat --color=always --style=numbers,changes {}' \ 106 | --bind 'enter:execute(echo {q})+accept'" 107 | eval "$cmd" | eval "$fzf_cmd" 108 | } 109 | 110 | fzf-js-test() { 111 | local cmd="rg -n -m 1 'describe' --glob '*.spec.ts' --line-number --no-heading" 112 | local fzf_cmd="fzf \ 113 | --multi \ 114 | --scheme path \ 115 | --delimiter : \ 116 | --nth 1 \ 117 | --accept-nth 1 \ 118 | --list-label='Test Files' \ 119 | --header 'ctrl-f: All files | ctrl-g Test files' \ 120 | --bind 'ctrl-f:change-list-label(Files)+reload($FZF_DEFAULT_COMMAND)' \ 121 | --bind 'ctrl-g:change-list-label(Test Files)+reload($cmd)' \ 122 | --preview 'bat --color=always --style=plain --highlight-line={2} {1}'" 123 | eval "$cmd" | "$fzf_cmd" 124 | } 125 | 126 | fzf-pytest() { 127 | local cmd="fd -tf -g 'test_*.py'" 128 | eval "$cmd" | 129 | fzf \ 130 | --multi \ 131 | --scheme path \ 132 | --header 'ctrl-f: All files | ctrl-g Test files' \ 133 | --bind "ctrl-f:change-list-label(Files)+reload($FZF_DEFAULT_COMMAND)" \ 134 | --bind "ctrl-g:change-list-label(Test Files)+reload($cmd)" \ 135 | --list-label "Test Files" \ 136 | --preview "bat --color=always {}" 137 | } 138 | 139 | fzf-git-checkout() { 140 | is-git-repo || { echo 'Not in git repo'; return 0 } 141 | 142 | # pass args straight to git-checkout if provided 143 | arg=$1 144 | if [[ -n $arg ]]; then 145 | git switch "$@" 146 | return 147 | fi 148 | 149 | local git_cmd="git branch --color=always --sort=-committerdate" 150 | local format="grep -v HEAD | sed 's/^..//' | sed 's,remotes/,,' | cut -d' ' -f1" 151 | eval "$git_cmd --all | $format" | 152 | fzf \ 153 | --ansi \ 154 | --header "ctrl-a: checkout -b | ctrl-t: checkout --track | ctrl-r: All branches | ctrl-l: Local branches" \ 155 | --bind "enter:execute(git switch {..})+accept" \ 156 | --bind "ctrl-a:execute(git switch -c {q})+accept" \ 157 | --bind "ctrl-t:execute(git switch --track {..})+accept" \ 158 | --bind "ctrl-r:reload($git_cmd --all | $format)+change-list-label(All Branches)" \ 159 | --bind "ctrl-l:reload($git_cmd | $format)+change-list-label(Local Branches)" \ 160 | --list-label "All Branches" \ 161 | --preview 'git log --oneline --graph --date=short --color=always --pretty="format:%C(auto)%cd %h%d %s" {}' 162 | } 163 | 164 | zle -N git-commit-widget 165 | fzf-git-commits() { 166 | is-git-repo || { echo 'Not in git repo'; return 0 } 167 | 168 | diff_cmd="git show --color=always --format=medium --stat -p {1} | fzf-delta" 169 | diffview_cmd='nvim -c "DiffviewOpen {1}^..{1}"' 170 | local fzf_cmd="fzf \ 171 | --ansi \ 172 | --multi \ 173 | --scheme 'history' \ 174 | --list-label 'Commits' \ 175 | --accept-nth 1 \ 176 | --header 'Ctrl-a: open in delta | Ctrl-t: open in nvim' \ 177 | --bind 'ctrl-a:execute($diff_cmd)' \ 178 | --bind 'ctrl-t:execute($diffview_cmd)+abort' \ 179 | --preview '$diff_cmd'" 180 | 181 | if [[ "$1" == "-q" ]]; then 182 | fzf_cmd="$fzf_cmd --sync --bind 'start:jump'" 183 | fi 184 | 185 | cmd="git log --date-order --abbrev-commit --oneline --decorate --color=always" 186 | eval "$cmd" | eval "$fzf_cmd" 187 | } 188 | 189 | git-commit-widget() { 190 | result=$(fzf-git-commits | join-lines) 191 | zle reset-prompt 192 | LBUFFER+=$result 193 | } 194 | bindkey '' git-commit-widget 195 | 196 | zle -N git-branch-widget 197 | fzf-git-branch() { 198 | is-git-repo || { echo 'Not in git repo'; return 0 } 199 | local prompt="${1:-Branches}" 200 | local git_cmd="git branch --color=always --sort=-committerdate" 201 | local format="grep -v HEAD | sed 's/^..//' | sed 's,remotes/,,' | cut -d' ' -f1" 202 | 203 | eval "$git_cmd | $format" | 204 | fzf \ 205 | --ansi \ 206 | --multi \ 207 | --list-label "${prompt}" \ 208 | --header "ctrl-a: All branches | ctrl-l: Local branches" \ 209 | --bind "ctrl-a:reload($git_cmd --all | $format)+change-list-label(Branches (all))" \ 210 | --bind "ctrl-l:reload($git_cmd | $format)+change-list-label(Branches)" \ 211 | --preview 'git log --oneline --graph --date=short --color=always --pretty="format:%C(auto)%cd %h%d %s" {}' 212 | } 213 | git-branch-widget() { 214 | result=$(fzf-git-branch | join-lines) 215 | zle reset-prompt 216 | LBUFFER+=$result 217 | } 218 | bindkey '' git-branch-widget 219 | 220 | fzf-git-changed() { 221 | cmd="git -c color.status=always status --short" 222 | diff_cmd="delta-git-diff {}" 223 | bat_cmd="bat --color=always {}" 224 | 225 | eval "$cmd" | 226 | fzf \ 227 | --multi \ 228 | --ansi \ 229 | --scheme path \ 230 | --header 'ctrl-f: All files | ctrl-g: Changed files' \ 231 | --bind "ctrl-f:change-list-label(Files)+change-preview($bat_cmd)+reload($FZF_DEFAULT_COMMAND)" \ 232 | --bind "ctrl-g:change-list-label(Changed Files)+change-preview($diff_cmd)+reload($cmd)" \ 233 | --list-label "Changed Files" \ 234 | --preview 'delta-git-diff {..}' | 235 | sed 's/.* //' 236 | } 237 | 238 | zle -N fzf-ls-widget 239 | fzf-ls() { 240 | file_preview="bat --color=always --line-range=:40 --style=numbers,changes {}" 241 | dir_preview="eza --color=always -T --level 2 {}" 242 | 243 | fd -tf | 244 | fzf \ 245 | --ansi \ 246 | --multi \ 247 | --scheme path \ 248 | --header "ctrl-d: Directories / ctrl-f: Files" \ 249 | --bind "ctrl-d:change-list-label(Directories)+reload(fd -td)+change-preview(${dir_preview})" \ 250 | --bind "ctrl-f:change-list-label(Files)+reload(fd -tf)+change-preview(${file_preview})" \ 251 | --preview "${file_preview}"\ 252 | --list-label "Files" 253 | } 254 | fzf-ls-widget() { 255 | result=$(fzf-ls | join-lines) 256 | zle reset-prompt 257 | LBUFFER+=$result 258 | } 259 | bindkey '' fzf-ls-widget 260 | 261 | fzf-cd() { 262 | fd -td -H -E '*.git' | 263 | fzf \ 264 | --ansi \ 265 | --no-multi \ 266 | --preview='eza -hal {..}' \ 267 | --list-label "Directories" 268 | } 269 | 270 | # Others 271 | source-envfile() { 272 | set -a 273 | source "$1" 274 | set +a 275 | } 276 | -------------------------------------------------------------------------------- /files/fzf.custom: -------------------------------------------------------------------------------- 1 | # vim: ft=zsh 2 | 3 | [ -f ~/.fzf.zsh ] && source ~/.fzf.zsh 4 | export FZF_DEFAULT_COMMAND='fd -tf' 5 | export FZF_CTRL_T_COMMAND="$FZF_DEFAULT_COMMAND" 6 | 7 | # "smart" layout -> vertical on small terminals, horiz on wide ones 8 | TRANSFORMER=' 9 | if [[ ${FZF_COLS:-$COLUMNS} -lt 120 ]]; then 10 | echo "+change-preview-window(50%,down)" 11 | else 12 | echo "+change-preview-window(right)" 13 | fi 14 | ' 15 | 16 | border_style="rounded" 17 | 18 | # Global opts 19 | export FZF_DEFAULT_OPTS="--height 90% \ 20 | --border=none \ 21 | --info=inline-right \ 22 | --scrollbar=▏▕ \ 23 | --reverse \ 24 | --multi \ 25 | --pointer='' \ 26 | --marker='' \ 27 | --input-label='Search' \ 28 | --list-border=$border_style \ 29 | --header-border=$border_style \ 30 | --input-border=$border_style \ 31 | --preview-label='Preview ( to toggle)' \ 32 | --bind 'resize,start:transform:$TRANSFORMER' \ 33 | --bind 'ctrl-b:preview-half-page-up,ctrl-f:preview-half-page-down' \ 34 | --bind 'ctrl-h:toggle-preview'\ 35 | --bind 'ctrl-y:jump-accept'" 36 | 37 | export FZF_CTRL_R_OPTS="--scheme history \ 38 | --list-label 'History' 39 | --bind 'ctrl-y:execute-silent(echo -n {2..} | pbcopy)+abort' \ 40 | --header 'ctrl-y: Copy command to clipboard'" 41 | 42 | # Color schemes -- https://github.com/catppuccin/fzf 43 | # "mocha" 44 | export FZF_COLOR_OPTS="--color=bg+:#313244,bg:#1e1e2e,spinner:#f5e0dc,hl:#f38ba8 \ 45 | --color=fg:#cdd6f4,info:#cba6f7,pointer:#f5e0dc \ 46 | --color=marker:#f5e0dc,fg+:#cdd6f4,prompt:#cba6f7,hl+:#f38ba8 \ 47 | --color=selected-bg:#45475a \ 48 | --color=list-border:#a6e3a1,list-label:#a6e3a1 \ 49 | --color=input-border:#cba6f7,input-label:#cba6f7 \ 50 | --color=preview-border:#f38ba8,preview-label:#f39ba8 \ 51 | --color=header-border:#89b4fa,header-label:#89b4fa" 52 | 53 | # "latte" 54 | [[ "$THEME_MODE" == "Light" ]] && export FZF_COLOR_OPTS=" \ 55 | --color=bg+:#ccd0da,bg:#eff1f5,spinner:#dc8a78,hl:#d20f39 \ 56 | --color=fg:#4c4f69,header:#d20f39,info:#8839ef,pointer:#dc8a78 \ 57 | --color=marker:#dc8a78,fg+:#4c4f69,prompt:#8839ef,hl+:#d20f39 \ 58 | --color=selected-bg:#bcc0cc \ 59 | --color=list-border:#40a02b,list-label:#40a02b \ 60 | --color=input-border:#8839ef,input-label:#8839ef \ 61 | --color=preview-border:#d20f39,preview-label:#d20f39 \ 62 | --color=header-border:#1e66f5,header-label:#1e66f5" 63 | 64 | export FZF_DEFAULT_OPTS="$FZF_DEFAULT_OPTS $FZF_COLOR_OPTS" 65 | -------------------------------------------------------------------------------- /files/git-config-base: -------------------------------------------------------------------------------- 1 | # vim: ft=gitconfig 2 | 3 | [alias] 4 | update = "fetch origin" 5 | cleanup = "! git-cleanup" 6 | rockstars = "shortlog -s -n --no-merges" 7 | amend = "commit --amend" 8 | [init] 9 | defaultBranch = main 10 | [merge] 11 | conflictstyle = zdiff3 12 | [column] 13 | ui = auto 14 | [help] 15 | autocorrect = prompt # prompt to fix 'git comit' to 'git commit' (for example) 16 | [branch] 17 | sort = -committerdate 18 | [tag] 19 | sort = version:refname 20 | [core] 21 | pager = fzf-delta 22 | [push] 23 | autoSetupRemote = true 24 | [rebase] 25 | updateRefs = true 26 | autosquash = true 27 | autostash = true 28 | [rerere] 29 | enabled = true 30 | autoupdate = true 31 | [fetch] 32 | prune = true 33 | [pull] 34 | rebase = true 35 | [diff] 36 | colorMoved = default 37 | algorithm = histogram 38 | renames = true 39 | [log] 40 | graphColors = "#df8e1d,#40a02b,#8839ef,#d20f39,#179299,#fe640b,#7287fd" 41 | [include] 42 | path = "~/.catppuccin-delta.gitconfig" 43 | [delta] 44 | features = decorations catppuccin-mocha 45 | navigate = true 46 | file-style = brightgreen overline 47 | hunk-header-style = omit 48 | line-numbers = true 49 | minus-style = syntax auto 50 | minus-emph-style = syntax ul auto 51 | minus-empty-line-marker-style = syntax auto 52 | plus-style = syntax auto 53 | plus-emph-style = syntax ul auto 54 | plus-empty-line-marker-style = syntax auto 55 | [absorb] 56 | maxStack = 20 57 | -------------------------------------------------------------------------------- /files/kitty/catppuccin.conf: -------------------------------------------------------------------------------- 1 | # vim:ft=kitty 2 | 3 | ## name: Catppuccin-Mocha 4 | ## author: Pocco81 (https://github.com/Pocco81) 5 | ## license: MIT 6 | ## upstream: https://github.com/catppuccin/kitty/blob/main/mocha.conf 7 | ## blurb: Soothing pastel theme for the high-spirited! 8 | 9 | 10 | 11 | # The basic colors 12 | foreground #CDD6F4 13 | background #1E1E2E 14 | selection_foreground #1E1E2E 15 | selection_background #F5E0DC 16 | 17 | # Cursor colors 18 | cursor #F5E0DC 19 | cursor_text_color #1E1E2E 20 | 21 | # URL underline color when hovering with mouse 22 | url_color #F5E0DC 23 | 24 | # Kitty window border colors 25 | active_border_color #B4BEFE 26 | inactive_border_color #6C7086 27 | bell_border_color #F9E2AF 28 | 29 | # OS Window titlebar colors 30 | wayland_titlebar_color system 31 | macos_titlebar_color system 32 | 33 | # Tab bar colors 34 | active_tab_foreground #11111B 35 | active_tab_background #CBA6F7 36 | inactive_tab_foreground #CDD6F4 37 | inactive_tab_background #181825 38 | tab_bar_background #11111B 39 | 40 | # Colors for marks (marked text in the terminal) 41 | mark1_foreground #1E1E2E 42 | mark1_background #B4BEFE 43 | mark2_foreground #1E1E2E 44 | mark2_background #CBA6F7 45 | mark3_foreground #1E1E2E 46 | mark3_background #74C7EC 47 | 48 | # The 16 terminal colors 49 | 50 | # black 51 | color0 #45475A 52 | color8 #585B70 53 | 54 | # red 55 | color1 #F38BA8 56 | color9 #F38BA8 57 | 58 | # green 59 | color2 #A6E3A1 60 | color10 #A6E3A1 61 | 62 | # yellow 63 | color3 #F9E2AF 64 | color11 #F9E2AF 65 | 66 | # blue 67 | color4 #89B4FA 68 | color12 #89B4FA 69 | 70 | # magenta 71 | color5 #F5C2E7 72 | color13 #F5C2E7 73 | 74 | # cyan 75 | color6 #94E2D5 76 | color14 #94E2D5 77 | 78 | # white 79 | color7 #BAC2DE 80 | color15 #A6ADC8 81 | -------------------------------------------------------------------------------- /files/kitty/tokyonight.conf: -------------------------------------------------------------------------------- 1 | # vim:ft=kitty 2 | 3 | ## name: Tokyo Night 4 | ## license: MIT 5 | ## author: Folke Lemaitre 6 | ## upstream: https://github.com/folke/tokyonight.nvim/raw/main/extras/kitty/tokyonight_night.conf 7 | 8 | 9 | background #1a1b26 10 | foreground #c0caf5 11 | selection_background #33467c 12 | selection_foreground #c0caf5 13 | url_color #73daca 14 | cursor #c0caf5 15 | cursor_text_color #1a1b26 16 | 17 | # Tabs 18 | active_tab_background #7aa2f7 19 | active_tab_foreground #16161e 20 | inactive_tab_background #292e42 21 | inactive_tab_foreground #545c7e 22 | #tab_bar_background #15161e 23 | 24 | # Windows 25 | active_border_color #7aa2f7 26 | inactive_border_color #292e42 27 | 28 | # normal 29 | color0 #15161e 30 | color1 #f7768e 31 | color2 #9ece6a 32 | color3 #e0af68 33 | color4 #7aa2f7 34 | color5 #bb9af7 35 | color6 #7dcfff 36 | color7 #a9b1d6 37 | 38 | # bright 39 | color8 #414868 40 | color9 #f7768e 41 | color10 #9ece6a 42 | color11 #e0af68 43 | color12 #7aa2f7 44 | color13 #bb9af7 45 | color14 #7dcfff 46 | color15 #c0caf5 47 | 48 | # extended colors 49 | color16 #ff9e64 50 | color17 #db4b4b 51 | -------------------------------------------------------------------------------- /files/nvim/after/ftplugin/dart.lua: -------------------------------------------------------------------------------- 1 | vim.bo.shiftwidth = 2 2 | vim.bo.tabstop = 2 3 | vim.bo.expandtab = true 4 | -------------------------------------------------------------------------------- /files/nvim/after/ftplugin/gitcommit.lua: -------------------------------------------------------------------------------- 1 | vim.opt_local.wrap = true 2 | vim.bo.textwidth = 80 3 | -- enable auto formatting as I type 4 | vim.opt.formatoptions = vim.opt.formatoptions + "ta" 5 | -------------------------------------------------------------------------------- /files/nvim/after/ftplugin/go.lua: -------------------------------------------------------------------------------- 1 | vim.bo.expandtab = false 2 | vim.bo.tabstop = 4 3 | vim.bo.shiftwidth = 4 4 | -------------------------------------------------------------------------------- /files/nvim/after/ftplugin/javascript.vim: -------------------------------------------------------------------------------- 1 | setlocal shiftwidth=2 2 | setlocal tabstop=2 3 | setlocal softtabstop=2 4 | -------------------------------------------------------------------------------- /files/nvim/after/ftplugin/markdown.lua: -------------------------------------------------------------------------------- 1 | -- Obsidian go to "definition" (file) 2 | local function get_text_inside_double_square_brackets() 3 | local cursor_pos = vim.api.nvim_win_get_cursor(0) 4 | local cursor_row = cursor_pos[1] 5 | 6 | local line = vim.fn.getline(cursor_row) 7 | local text = line:match("%[%[(.+)%]%]") 8 | 9 | return text 10 | end 11 | 12 | vim.keymap.set("n", "", function() 13 | local text = get_text_inside_double_square_brackets() 14 | if text ~= nil then 15 | local fname = get_text_inside_double_square_brackets() .. ".md" 16 | vim.cmd("find ++edit" .. fname, { desc = "Goto file reference" }) 17 | end 18 | end) 19 | 20 | vim.bo.textwidth = 120 21 | vim.bo.shiftwidth = 2 22 | vim.bo.tabstop = 2 23 | vim.bo.softtabstop = 2 24 | vim.opt_local.wrap = true 25 | -------------------------------------------------------------------------------- /files/nvim/after/ftplugin/python.vim: -------------------------------------------------------------------------------- 1 | " Fix weird indentation behavior: always add 1 indent to line after open paren 2 | let g:pyindent_nested_paren=shiftwidth() 3 | let g:pyindent_open_paren=shiftwidth() 4 | -------------------------------------------------------------------------------- /files/nvim/after/ftplugin/typescript.vim: -------------------------------------------------------------------------------- 1 | setlocal shiftwidth=2 2 | setlocal tabstop=2 3 | setlocal softtabstop=2 4 | -------------------------------------------------------------------------------- /files/nvim/after/ftplugin/vue.lua: -------------------------------------------------------------------------------- 1 | vim.bo.shiftwidth = 2 2 | vim.bo.tabstop = 2 3 | vim.bo.softtabstop = 2 4 | 5 | -- special commenting for vue SFCs 6 | require("Comment").setup({ 7 | pre_hook = require("ts_context_commentstring.integrations.comment_nvim").create_pre_hook(), 8 | }) 9 | 10 | --[[ 11 | Mappings shamelessly stolen from medium article: 12 | https://medium.com/scoro-engineering/5-smart-mini-snippets-for-making-text-editing-more-fun-in-neovim-b55ffb96325a 13 | --]] 14 | -- automatically add "" when adding attributes in vue 15 | vim.keymap.set("i", "=", function() 16 | -- The cursor location does not give us the correct node in this case, so we 17 | -- need to get the node to the left of the cursor 18 | local cursor = vim.api.nvim_win_get_cursor(0) 19 | local left_of_cursor_range = { cursor[1] - 1, cursor[2] - 1 } 20 | 21 | local node = vim.treesitter.get_node({ pos = left_of_cursor_range }) 22 | local nodes_active_in = { 23 | "attribute_name", 24 | "directive_argument", 25 | "directive_name", 26 | } 27 | if not node or not vim.tbl_contains(nodes_active_in, node:type()) then 28 | -- The cursor is not on an attribute node 29 | return "=" 30 | end 31 | 32 | return '=""' 33 | end, { expr = true, buffer = true, desc = "Smart vue attribute insert" }) 34 | 35 | -- auto close tag when I type `/` inside a tag 36 | vim.keymap.set("i", "/", function() 37 | local node = vim.treesitter.get_node() 38 | if not node then return "/" end 39 | 40 | local first_sibling_node = node:prev_named_sibling() 41 | if not first_sibling_node then return "/" end 42 | 43 | local parent_node = node:parent() 44 | local is_tag_writing_in_progress = node:type() == "text" and parent_node:type() == "element" 45 | 46 | local is_start_tag = first_sibling_node:type() == "start_tag" 47 | 48 | local start_tag_text = vim.treesitter.get_node_text(first_sibling_node, 0) 49 | local tag_is_already_terminated = string.match(start_tag_text, ">$") 50 | 51 | if is_tag_writing_in_progress and is_start_tag and not tag_is_already_terminated then 52 | local char_at_cursor = vim.fn.strcharpart(vim.fn.strpart(vim.fn.getline("."), vim.fn.col(".") - 2), 0, 1) 53 | local already_have_space = char_at_cursor == " " 54 | 55 | -- We can also automatically add a space if there isn't one already 56 | return already_have_space and "/>" or " />" 57 | end 58 | 59 | return "/" 60 | end, { expr = true, buffer = true, desc = "Auto close vue tag" }) 61 | 62 | -- automatically turn {{| into {{ | }} in vue templates 63 | local Rule = require("nvim-autopairs.rule") 64 | local ts_conds = require("nvim-autopairs.ts-conds") 65 | require("nvim-autopairs").add_rules({ 66 | Rule("{{", " }", "vue"):set_end_pair_length(2):with_pair(ts_conds.is_ts_node("text")), 67 | }) 68 | -------------------------------------------------------------------------------- /files/nvim/after/ftplugin/yaml.lua: -------------------------------------------------------------------------------- 1 | vim.bo.shiftwidth = 2 2 | vim.bo.tabstop = 2 3 | vim.bo.softtabstop = 2 4 | 5 | vim.keymap.set( 6 | "n", 7 | "cf", 8 | "Forecast! %", 9 | { silent = true, noremap = true, desc = "Run forecast cli on current file", buffer = 0 } 10 | ) 11 | 12 | vim.api.nvim_create_autocmd("User", { 13 | pattern = "ForecastFinished", 14 | callback = function() vim.notify("Forecast Complete", vim.log.levels.INFO) end, 15 | }) 16 | -------------------------------------------------------------------------------- /files/nvim/after/lsp/bashls.lua: -------------------------------------------------------------------------------- 1 | local custom_attach = require("ag.lsp.common").custom_attach 2 | 3 | return { 4 | cmd = { "bash-language-server", "start" }, 5 | on_attach = custom_attach, 6 | filetypes = { "bash", "sh", "zsh" }, 7 | } 8 | -------------------------------------------------------------------------------- /files/nvim/after/lsp/dartls.lua: -------------------------------------------------------------------------------- 1 | local custom_attach = require("ag.lsp.common").custom_attach 2 | 3 | return { 4 | on_attach = function(client, bufnr) 5 | custom_attach(client, bufnr, { allowed_clients = { "dartls" }, format_on_save = true }) 6 | end, 7 | } 8 | -------------------------------------------------------------------------------- /files/nvim/after/lsp/efm.lua: -------------------------------------------------------------------------------- 1 | local custom_attach = require("ag.lsp.common").custom_attach 2 | local autopep8 = require("efmls-configs.formatters.autopep8") 3 | local black = require("efmls-configs.formatters.black") 4 | local eslint = require("efmls-configs.linters.eslint_d") 5 | local flake8 = require("efmls-configs.linters.flake8") 6 | local prettier = require("efmls-configs.formatters.prettier_d") 7 | local pylint = require("efmls-configs.linters.pylint") 8 | local ruff_fmt = require("efmls-configs.formatters.ruff") 9 | local ruff_lint = require("efmls-configs.linters.ruff") 10 | local shellcheck = require("efmls-configs.linters.shellcheck") 11 | local stylua = require("efmls-configs.formatters.stylua") 12 | 13 | local languages = { 14 | lua = { stylua }, 15 | typescript = { prettier, eslint }, 16 | javascript = { prettier, eslint }, 17 | vue = { prettier, eslint }, 18 | python = { black, autopep8, flake8, pylint, ruff_lint, ruff_fmt }, 19 | bash = { shellcheck }, 20 | sh = { shellcheck }, 21 | } 22 | 23 | -- special handling for python to use virtual envs w/o activating 24 | local python_venv_path = require("ag.utils").get_python_venv_path() 25 | if python_venv_path ~= nil then 26 | local cmd_prefix = python_venv_path .. "/bin/" 27 | for _, prog in ipairs(languages["python"]) do 28 | if prog["formatCommand"] then prog["formatCommand"] = cmd_prefix .. prog["formatCommand"] end 29 | if prog["lintCommand"] then prog["lintCommand"] = cmd_prefix .. prog["lintCommand"] end 30 | end 31 | end 32 | 33 | -- explicitly point stylua to my config 34 | local stylua_format_cmd = languages["lua"][1]["formatCommand"] 35 | if not stylua_format_cmd:match(".*config%-path.*") then 36 | local new_cmd = stylua_format_cmd:gsub("(stylua)", "%1 --config-path .stylua.toml") 37 | languages["lua"][1]["formatCommand"] = new_cmd 38 | end 39 | 40 | ---custom handler to clean up linter diagnostics 41 | local custom_publish_diagnostics = function(_, result, ctx, _) 42 | -- filter out duplicitive diagnostics from flake8 that pyright 43 | -- already covers 44 | local flake8_ignore_codes = { 45 | "841", -- F841: unused variable 46 | "401", -- F401: unused import 47 | } 48 | result.diagnostics = vim.tbl_filter(function(diagnostic) 49 | if diagnostic.source ~= "efm/flake8" then return true end 50 | return not vim.list_contains(flake8_ignore_codes, diagnostic.code) 51 | end, result.diagnostics) 52 | 53 | for _, diagnostic in pairs(result.diagnostics) do 54 | -- flake8 reports everything as error, force it back to hint 55 | -- (it's never that serious) 56 | if 57 | (diagnostic.source == "efm/flake8" or diagnostic.source == "efm/pylint") 58 | and diagnostic.severity == vim.diagnostic.severity.ERROR 59 | then 60 | diagnostic.severity = vim.diagnostic.severity.HINT 61 | end 62 | end 63 | vim.lsp.diagnostic.on_publish_diagnostics(_, result, ctx) 64 | end 65 | 66 | local efmls_config = { 67 | filetypes = vim.tbl_keys(languages), 68 | settings = { 69 | rootMarkers = { ".git/" }, 70 | languages = languages, 71 | }, 72 | init_options = { 73 | documentFormatting = true, 74 | documentRangeFormatting = true, 75 | }, 76 | } 77 | 78 | return vim.tbl_extend("force", efmls_config, { 79 | cmd = { "efm-langserver" }, 80 | filetypes = vim.tbl_keys(languages), 81 | on_attach = function(client, bufnr) custom_attach(client, bufnr, { allowed_clients = { "efm" } }) end, 82 | handlers = { 83 | ["textDocument/publishDiagnostics"] = custom_publish_diagnostics, 84 | }, 85 | }) 86 | -------------------------------------------------------------------------------- /files/nvim/after/lsp/gopls.lua: -------------------------------------------------------------------------------- 1 | local custom_attach = require("ag.lsp.common").custom_attach 2 | 3 | return { 4 | filetypes = { "go" }, 5 | on_attach = function(client, bufnr) 6 | custom_attach(client, bufnr, { allowed_clients = { "gopls" }, format_on_save = true }) 7 | -- auto organize imports 8 | vim.api.nvim_create_autocmd("BufWritePre", { 9 | pattern = "*.go", 10 | callback = function() 11 | vim.lsp.buf.code_action({ 12 | context = { only = { "source.organizeImports" } }, 13 | apply = true, 14 | }) 15 | end, 16 | }) 17 | end, 18 | } 19 | -------------------------------------------------------------------------------- /files/nvim/after/lsp/jsonls.lua: -------------------------------------------------------------------------------- 1 | local custom_attach = require("ag.lsp.common").custom_attach 2 | 3 | return { 4 | filetypes = { "json" }, 5 | cmd = { "vscode-json-language-server", "--stdio" }, 6 | on_attach = custom_attach, 7 | } 8 | 9 | -------------------------------------------------------------------------------- /files/nvim/after/lsp/lua_ls.lua: -------------------------------------------------------------------------------- 1 | local custom_attach = require("ag.lsp.common").custom_attach 2 | 3 | return { 4 | cmd = { "lua-language-server", "--stdio" }, 5 | filetypes = { "lua" }, 6 | on_attach = function(client, bufnr) 7 | custom_attach(client, bufnr, { allowed_clients = { "efm" }, format_on_save = true }) 8 | end, 9 | settings = { 10 | Lua = { 11 | runtime = { 12 | -- Tell the language server which version of Lua you're using 13 | -- (most likely LuaJIT in the case of Neovim) 14 | version = "LuaJIT", 15 | }, 16 | -- Make the server aware of Neovim runtime files 17 | workspace = { 18 | checkThirdParty = false, 19 | library = { 20 | vim.env.VIMRUNTIME, 21 | }, 22 | }, 23 | diagnostics = { 24 | -- Get the language server to recognize the `vim` global 25 | globals = { "vim" }, 26 | }, 27 | }, 28 | }, 29 | } 30 | -------------------------------------------------------------------------------- /files/nvim/after/lsp/pyright.lua: -------------------------------------------------------------------------------- 1 | local custom_attach = require("ag.lsp.common").custom_attach 2 | 3 | local pyright_organize_imports = function(client) 4 | local params = { 5 | command = "pyright.organizeimports", 6 | arguments = { vim.uri_from_bufnr(0) }, 7 | } 8 | 9 | client:request("workspace/executeCommand", params, nil, 0) 10 | end 11 | 12 | return { 13 | filetypes = { "python" }, 14 | cmd = { "pyright-langserver", "--stdio" }, 15 | -- manually set root_dir to avoid it getting overriden by the `pythonPath` setting 16 | root_dir = function(bufnr, cb) 17 | local root = vim.fs.root(bufnr, { "pyproject.toml", "requirements.txt", "Pipfile" }) 18 | cb(root) 19 | end, 20 | -- automatically set the language server's python path to the project's virtual environment, 21 | -- even if it's not explicitly active when I start nvim 22 | before_init = function(_, config) 23 | local python_path = require("ag.utils").get_python_path() 24 | if python_path ~= nil then config.settings.python = { pythonPath = python_path } end 25 | end, 26 | on_attach = function(client, bufnr) 27 | custom_attach(client, bufnr, { allowed_clients = { "efm" } }) 28 | vim.keymap.set("n", "ii", function() pyright_organize_imports(client) end, { 29 | buffer = bufnr, 30 | silent = true, 31 | noremap = true, 32 | }) 33 | end, 34 | settings = { 35 | pyright = { 36 | disableOrganizeImports = false, 37 | analysis = { 38 | useLibraryCodeForTypes = true, 39 | autoSearchPaths = true, 40 | diagnosticMode = "workspace", 41 | autoImportCompletions = true, 42 | }, 43 | }, 44 | }, 45 | } 46 | -------------------------------------------------------------------------------- /files/nvim/after/lsp/rust_analyzer.lua: -------------------------------------------------------------------------------- 1 | local custom_attach = require("ag.lsp.common").custom_attach 2 | 3 | return { 4 | filetypes = { "rust" }, 5 | on_attach = function(client, bufnr) 6 | custom_attach(client, bufnr, { format_on_save = true, allowed_clients = { "rust_analyzer" } }) 7 | end, 8 | } 9 | -------------------------------------------------------------------------------- /files/nvim/after/lsp/ts_ls.lua: -------------------------------------------------------------------------------- 1 | local custom_attach = require("ag.lsp.common").custom_attach 2 | 3 | return { 4 | cmd = { "typescript-language-server", "--stdio" }, 5 | on_attach = function(client, bufnr) 6 | custom_attach(client, bufnr, { allowed_clients = { "efm" }, format_on_save = false }) 7 | end, 8 | filetypes = { "javascript", "typescript", "vue" }, 9 | root_dir = function(bufnr, cb) 10 | local root = vim.fs.root(bufnr, { "package.json", "tsconfig.json", "jsconfig.json" }) 11 | cb(root) 12 | end, 13 | init_options = { 14 | plugins = { 15 | { 16 | name = "@vue/typescript-plugin", 17 | location = vim.fn.expand( 18 | "$NVM_DIR/versions/node/$DEFAULT_NODE_VERISON/lib/node_modeuls/@vue/typescript-plugin" 19 | ), 20 | languages = { 21 | "javascript", 22 | "typescript", 23 | "vue", 24 | }, 25 | }, 26 | }, 27 | }, 28 | } 29 | -------------------------------------------------------------------------------- /files/nvim/after/lsp/volar.lua: -------------------------------------------------------------------------------- 1 | return {} 2 | -------------------------------------------------------------------------------- /files/nvim/after/lsp/yamlls.lua: -------------------------------------------------------------------------------- 1 | local custom_attach = require("ag.lsp.common").custom_attach 2 | 3 | return { 4 | cmd = { "yaml-language-server", "--stdio" }, 5 | filetypes = { "yaml" }, 6 | on_attach = custom_attach, 7 | settings = { 8 | yaml = { 9 | customTags = { 10 | "!fn", 11 | "!And", 12 | "!If", 13 | "!Not", 14 | "!Not sequence", 15 | "!Equals", 16 | "!Equals sequence", 17 | "!Or", 18 | "!FindInMap sequence", 19 | "!Base64", 20 | "!Cidr", 21 | "!Ref", 22 | "!Sub", 23 | "!Sub sequence", 24 | "!GetAtt", 25 | "!GetAZs", 26 | "!ImportValue", 27 | "!Select", 28 | "!Split", 29 | "!Join sequence", 30 | "!GetAtt", 31 | "!GetAtt sequence", 32 | }, 33 | schemaStore = { 34 | enable = false, 35 | }, 36 | }, 37 | }, 38 | } 39 | -------------------------------------------------------------------------------- /files/nvim/after/plugin/autocmd.lua: -------------------------------------------------------------------------------- 1 | local augroup = vim.api.nvim_create_augroup 2 | local au = vim.api.nvim_create_autocmd 3 | 4 | local exit_if_last = function() 5 | if vim.fn.winnr("$") == 1 then vim.cmd("q") end 6 | end 7 | 8 | local term_group = augroup("term", { clear = false }) 9 | au("TermOpen", { 10 | group = term_group, 11 | pattern = "*", 12 | desc = "Terminal display configuration", 13 | callback = function() 14 | vim.cmd("startinsert") 15 | vim.opt_local.number = false 16 | vim.opt_local.relativenumber = false 17 | vim.opt_local.cursorline = false 18 | vim.opt_local.signcolumn = "no" 19 | end, 20 | }) 21 | au("BufEnter", { 22 | group = term_group, 23 | pattern = "*", 24 | desc = "Auto enter insert mode when entering terminal buffer", 25 | callback = function() 26 | local buftype = vim.opt.buftype:get() 27 | if buftype == "terminal" then 28 | -- quit if the terminal is the last buffer open 29 | exit_if_last() 30 | -- enter insert mode automatically when entering terminal 31 | vim.cmd("startinsert") 32 | end 33 | end, 34 | }) 35 | 36 | au("BufEnter", { 37 | pattern = "*", 38 | desc = "Never auto-format text in insert mode", 39 | command = "set formatoptions-=t", 40 | }) 41 | 42 | au("VimResized", { 43 | command = "wincmd =", 44 | desc = "Keep splits even when vim resized", 45 | }) 46 | 47 | local gitcommit_group = augroup("gitcommit", { clear = true }) 48 | au("FileType", { 49 | group = gitcommit_group, 50 | desc = "gitcommit formatopts", 51 | pattern = "gitcommit", 52 | callback = function() vim.opt_local.formatoptions = "tcrnqj" end, 53 | }) 54 | 55 | au("BufEnter", { 56 | pattern = "Dockerfile.*", 57 | desc = "Detect Dockerfiles with different extensions", 58 | callback = function() vim.opt_local.filetype = "dockerfile" end, 59 | }) 60 | 61 | au("BufEnter", { 62 | pattern = "*.tmTheme", 63 | callback = function() vim.opt_local.filetype = "tmTheme" end, 64 | }) 65 | 66 | local nvim_tree_group = augroup("NvimTree", { clear = true }) 67 | au("FileType", { 68 | group = nvim_tree_group, 69 | pattern = "NvimTree", 70 | desc = "Quit nvim if NvimTree is the only buffer", 71 | callback = function() 72 | exit_if_last() 73 | vim.opt_local.cursorline = true 74 | end, 75 | }) 76 | 77 | au("BufReadPost", { 78 | pattern = "kitty.conf", 79 | desc = "Open kitty with all folds closed", 80 | callback = function() vim.opt_local.foldlevel = 0 end, 81 | }) 82 | 83 | -- Aerial specific mapping 84 | au("FileType", { 85 | pattern = "aerial", 86 | callback = function() 87 | vim.keymap.set("n", "q", ":q", { noremap = true, silent = true, buffer = true, desc = "quit aerial" }) 88 | end, 89 | }) 90 | 91 | au("FileType", { 92 | pattern = "vue", 93 | desc = "Treesitter indenting for vue files", 94 | command = "TSBufEnable indent", 95 | }) 96 | 97 | au("FileType", { 98 | pattern = "gitrebase", 99 | desc = "EZ rebase keybinds", 100 | callback = function() 101 | for _, key in ipairs({ "p", "r", "e", "s", "f", "d", "x", "b", "l", "r", "t", "m" }) do 102 | vim.keymap.set("n", key, "ciw" .. key .. "", { noremap = true, silent = true, buffer = true }) 103 | end 104 | end, 105 | }) 106 | -------------------------------------------------------------------------------- /files/nvim/after/plugin/lsp/autocmd.lua: -------------------------------------------------------------------------------- 1 | vim.api.nvim_create_autocmd("LspNotify", { 2 | callback = function(args) 3 | if args.data.method == "textDocument/didOpen" then vim.lsp.foldclose("imports", vim.fn.bufwinid(args.buf)) end 4 | end, 5 | }) 6 | 7 | vim.api.nvim_create_autocmd("LspAttach", { 8 | callback = function(args) 9 | local client = vim.lsp.get_client_by_id(args.data.client_id) 10 | -- if LSP client supports it, use LSP for folding instead of TreeSitter 11 | if client ~= nil and client:supports_method("textDocument/foldingRange") then 12 | local win = vim.api.nvim_get_current_win() 13 | vim.wo[win][0].foldexpr = "v:lua.vim.lsp.foldexpr()" 14 | end 15 | end, 16 | }) 17 | -------------------------------------------------------------------------------- /files/nvim/after/plugin/lsp/init.lua: -------------------------------------------------------------------------------- 1 | local common = require("ag.lsp.common") 2 | 3 | local lsp_dir = vim.fn.stdpath("config") .. "/after/lsp" 4 | local client_names = {} 5 | 6 | for name, type in vim.fs.dir(lsp_dir) do 7 | if type == "file" and name:match("%.lua$") then 8 | local fname = name:gsub("%.lua$", "") 9 | table.insert(client_names, fname) 10 | end 11 | end 12 | 13 | for _, client in ipairs(client_names) do 14 | common.register_if_installed(client) 15 | end 16 | -------------------------------------------------------------------------------- /files/nvim/after/plugin/zoomer.vim: -------------------------------------------------------------------------------- 1 | " Zoomer 2 | let g:zoomer_expanded='false' 3 | function! ToggleFocus() 4 | if( g:zoomer_expanded ==? 'false' ) 5 | wincmd | 6 | wincmd _ 7 | let g:zoomer_expanded = 'true' 8 | else 9 | wincmd = 10 | let g:zoomer_expanded = 'false' 11 | endif 12 | endfunction 13 | -------------------------------------------------------------------------------- /files/nvim/autoload/termcmd.vim: -------------------------------------------------------------------------------- 1 | function! termcmd#vert() abort 2 | let l:win_width = winwidth(0) 3 | let l:term_width = l:win_width / 3 4 | execute l:term_width .. "vs | term" 5 | endfunction 6 | 7 | function! termcmd#horiz() abort 8 | let l:win_height = winheight(0) 9 | let l:term_height = l:win_height / 3 10 | execute l:term_height .. "sp | term" 11 | endfunction 12 | -------------------------------------------------------------------------------- /files/nvim/init.lua: -------------------------------------------------------------------------------- 1 | -- Essentials 2 | vim.g.mapleader = " " 3 | vim.g.bulitin_lsp = true 4 | vim.opt.termguicolors = true 5 | 6 | -- Disable providers for faster startup 7 | vim.g.loaded_python3_provider = 0 8 | vim.g.loaded_ruby_provider = 0 9 | vim.g.loaded_perl_provider = 0 10 | vim.g.loaded_node_provider = 0 11 | 12 | -- Plugins 13 | vim.loader.enable() -- cache lua modules (https://github.com/neovim/neovim/pull/22668) 14 | local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" 15 | if not vim.loop.fs_stat(lazypath) then 16 | vim.fn.system({ 17 | "git", 18 | "clone", 19 | "--filter=blob:none", 20 | "https://github.com/folke/lazy.nvim.git", 21 | "--branch=stable", -- latest stable release 22 | lazypath, 23 | }) 24 | end 25 | vim.opt.rtp:prepend(lazypath) 26 | require("lazy").setup("ag.plugins", { 27 | change_detection = { 28 | -- automatically check for config file changes and reload the ui 29 | enabled = true, 30 | notify = false, 31 | }, 32 | }) 33 | 34 | -- Keymaps 35 | require("ag.mappings") 36 | -- Diagnostics 37 | require("ag.diagnostics") 38 | -- Built in LSP configuration 39 | require("ag.lsp") 40 | 41 | -- Behaviors 42 | vim.opt.belloff = "all" -- NO BELLS! 43 | vim.opt.completeopt = { "menuone", "noselect", "fuzzy" } -- ins-completion how I like it 44 | vim.opt.swapfile = false -- no swap files 45 | vim.opt.inccommand = "nosplit" -- preview %s commands live as I type 46 | vim.opt.undofile = true -- keep track of my 'undo's between sessions 47 | vim.opt.grepprg = "rg --vimgrep --smart-case --no-heading" -- search with rg 48 | vim.opt.grepformat = "%f:%l:%c:%m" -- filename:line number:column number:error message 49 | vim.opt.mouse = "nv" -- use mouse in normal, visual modes 50 | vim.opt.mousescroll = "ver:3,hor:0" -- scroll vertically by 3 lines, no horizontal scrolling 51 | vim.opt.scrolloff = 10 -- padding between cursor and top/bottom of window 52 | vim.opt.foldlevelstart = 99 -- open files with all folds open 53 | vim.opt.splitright = true -- prefer vsplitting to the right 54 | vim.opt.splitbelow = true -- prefer splitting below 55 | vim.opt.splitkeep = "screen" -- keep text on screen the same when splitting 56 | vim.opt.wrap = false -- don't wrap my text 57 | vim.opt.linebreak = true -- if I toggle `wrap` ON, only break between words 58 | vim.opt.diffopt = "internal,filler,closeoff,indent-heuristic,linematch:60,algorithm:histogram" -- smarter diff detection 59 | -- internal : builtin diff library 60 | -- filler : show "filler" lines to keep text aligned 61 | -- closeoff : automatically run ":diffoff" if there's only 1 diff buffer left open 62 | -- indent-heuristic : take into account indentation when computing diffs 63 | -- linematch:{n} : re-arrange up to {n} lines in a hunk to place similar lines side-by-side 64 | -- algorighm:histogram : https://tiarkrompf.github.io/notes/?/diff-algorithm/ 65 | 66 | -- Indentation 67 | vim.opt.autoindent = true -- continue indentation to new line 68 | vim.opt.smartindent = true -- add extra indent when it makes sense 69 | vim.opt.smarttab = true -- at the start of a line behaves as expected 70 | vim.opt.expandtab = true -- inserts spaces 71 | vim.opt.shiftwidth = 4 -- >>, << shift line by 4 spaces 72 | vim.opt.tabstop = 4 -- appears as 4 spaces 73 | vim.opt.softtabstop = 4 -- behaves as 4 spaces when editing 74 | vim.opt.breakindent = true -- when `wrap` is on, continue line at same indentation level as previous 75 | 76 | -- Colors 77 | vim.cmd("colorscheme catppuccin") 78 | if vim.fn.environ()["THEME_MODE"] == "Light" then 79 | vim.opt.background = "light" 80 | else 81 | vim.opt.background = "dark" 82 | end 83 | 84 | -- Look and feel 85 | vim.opt.number = true 86 | vim.opt.relativenumber = true 87 | vim.opt.signcolumn = "yes" -- show the sign column always 88 | vim.opt.list = true -- show list chars 89 | vim.opt.foldtext = "" -- show normal buffer content (w/ highlights) through fold 90 | vim.opt.showbreak = "> " -- prefix wrapped lines with '>' 91 | vim.opt.listchars = { 92 | -- these list chars 93 | tab = "<->", 94 | nbsp = "␣", 95 | extends = "…", 96 | precedes = "…", 97 | trail = "·", 98 | multispace = "·", -- show chars if I have multiple spaces between text 99 | leadmultispace = " ", -- ...but don't show any when they're at the start 100 | } 101 | -- more defined window border 102 | vim.opt.fillchars:append({ 103 | vert = "┃", 104 | horiz = "━", 105 | horizup = "┻", 106 | horizdown = "┳", 107 | vertleft = "┫", 108 | vertright = "┣", 109 | verthoriz = "╋", 110 | diff = "╱", 111 | }) 112 | vim.opt.cursorline = true -- hightlight line cursor is on 113 | vim.opt.laststatus = 3 -- single global statusline 114 | vim.opt.formatoptions = "lrqjn" -- default format options, can be overridden by builtin ftplugins 115 | 116 | -- Searching 117 | vim.opt.wildmenu = true -- tab complete on command line 118 | vim.opt.ignorecase = true -- case insensitive search... 119 | vim.opt.smartcase = true -- unless I use caps 120 | vim.opt.hlsearch = true -- highlight matching text 121 | vim.opt.incsearch = true -- update results while I type 122 | -------------------------------------------------------------------------------- /files/nvim/lua/ag/diagnostics.lua: -------------------------------------------------------------------------------- 1 | -- global diagnostic config 2 | vim.diagnostic.config({ 3 | severity_sort = true, 4 | virtual_lines = { 5 | current_line = true, 6 | -- only show ERROR level diagnostics with virtual lines 7 | format = function(diagnostic) 8 | if diagnostic.severity ~= vim.diagnostic.severity.ERROR then return nil end 9 | return "[" .. diagnostic.source .. "] " .. diagnostic.message 10 | end, 11 | }, 12 | virtual_text = false, 13 | -- virtual_text = { 14 | -- severity = vim.diagnostic.severity.ERROR, 15 | -- source = "if_many", 16 | -- hl_mode = "blend", 17 | -- }, 18 | float = { 19 | severity_sort = true, 20 | source = "if_many", 21 | border = "single", 22 | header = { 23 | "", 24 | "DiagnosticSignWarn", 25 | }, 26 | prefix = function(diagnostic) 27 | local diag_to_format = { 28 | [vim.diagnostic.severity.ERROR] = { "Error", "DiagnosticError" }, 29 | [vim.diagnostic.severity.WARN] = { "Warning", "DiagnosticWarn" }, 30 | [vim.diagnostic.severity.INFO] = { "Info", "DaignosticInfo" }, 31 | [vim.diagnostic.severity.HINT] = { "Hint", "DiagnosticHint" }, 32 | } 33 | local res = diag_to_format[diagnostic.severity] 34 | return string.format("(%s) ", res[1]), res[2] 35 | end, 36 | }, 37 | }) 38 | 39 | -- keymaps 40 | vim.keymap.set( 41 | "n", 42 | "dk", 43 | function() vim.diagnostic.open_float({ border = "rounded" }) end, 44 | { silent = true, desc = "View Current Line Diagnostics" } 45 | ) 46 | vim.keymap.set( 47 | "n", 48 | "dn", 49 | function() vim.diagnostic.jump({ count = 1 }) end, 50 | { silent = true, desc = "Goto next diagnostic" } 51 | ) 52 | vim.keymap.set( 53 | "n", 54 | "dp", 55 | function() vim.diagnostic.jump({ count = -1 }) end, 56 | { silent = true, desc = "Goto prev diagnostic" } 57 | ) 58 | vim.keymap.set("n", "da", vim.diagnostic.setqflist, { silent = true, desc = "Populate qf list" }) 59 | vim.keymap.set("n", "do", function() 60 | if vim.diagnostic.is_enabled() then 61 | vim.diagnostic.enable(false) 62 | else 63 | vim.diagnostic.enable() 64 | end 65 | end, { silent = true, desc = "Toggle diagnostics" }) 66 | -------------------------------------------------------------------------------- /files/nvim/lua/ag/lsp/common.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | -- restricted format 4 | ---@param bufnr number buffer to format 5 | ---@param allowed_clients string[] client names to allow formatting 6 | local function format_by_client(bufnr, allowed_clients) 7 | vim.lsp.buf.format({ 8 | bufnr = bufnr, 9 | filter = function(client) 10 | if not allowed_clients then return true end 11 | return vim.tbl_contains(allowed_clients, client.name) 12 | end, 13 | }) 14 | end 15 | 16 | ---@param bufnr number 17 | ---@param allowed_clients string[] 18 | local function register_format_on_save(bufnr, allowed_clients) 19 | local format_group = vim.api.nvim_create_augroup("LspFormatting", { clear = true }) 20 | vim.api.nvim_create_autocmd("BufWritePre", { 21 | group = format_group, 22 | buffer = bufnr, 23 | callback = function() format_by_client(bufnr, allowed_clients) end, 24 | }) 25 | end 26 | 27 | ---@param client vim.lsp.Client the lsp client instance 28 | ---@param bufnr number buffer we're attaching to 29 | ---@param format_opts table how to deal with formatting, takes the following keys: 30 | -- allowed_clients (string[]): names of the lsp clients that are allowed to handle vim.lsp.buf.format() when this client is attached 31 | -- format_on_save (bool): whether or not to auto format on save 32 | M.custom_attach = function(client, bufnr, format_opts) 33 | local keymap_opts = { buffer = bufnr, silent = true, noremap = true } 34 | local with_desc = function(opts, desc) return vim.tbl_extend("force", opts, { desc = desc }) end 35 | 36 | vim.keymap.set("n", "K", function() vim.lsp.buf.hover({ border = "rounded" }) end, with_desc(keymap_opts, "Hover")) 37 | vim.keymap.set("n", "", vim.lsp.buf.definition, with_desc(keymap_opts, "Goto Definition")) 38 | vim.keymap.set("n", "gr", vim.lsp.buf.references, with_desc(keymap_opts, "Find References")) 39 | vim.keymap.set("n", "gr", vim.lsp.buf.rename, with_desc(keymap_opts, "Rename")) 40 | vim.keymap.set("n", "H", vim.lsp.buf.code_action, with_desc(keymap_opts, "Code Actions")) 41 | vim.keymap.set( 42 | "n", 43 | "ti", 44 | function() vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled()) end, 45 | with_desc(keymap_opts, "Toggle inlay hints") 46 | ) 47 | vim.keymap.set("n", "rr", function() 48 | vim.lsp.stop_client(vim.lsp.get_clients()) 49 | vim.cmd("edit") 50 | end, with_desc(keymap_opts, "Restart all LSP clients")) -- restart clients 51 | 52 | if format_opts ~= nil then 53 | vim.keymap.set( 54 | "n", 55 | "F", 56 | function() format_by_client(bufnr, format_opts.allowed_clients or { client.name }) end, 57 | with_desc(keymap_opts, "Format") 58 | ) -- format 59 | 60 | if format_opts.format_on_save then 61 | register_format_on_save(bufnr, format_opts.allowed_clients or { client.name }) 62 | end 63 | end 64 | end 65 | 66 | ---If the configured client's "cmd" is available, enable it 67 | ---Otherwise do nothing 68 | ---@param client string 69 | M.register_if_installed = function(client) 70 | local config = vim.lsp.config[client] 71 | if config == nil or config.cmd == nil then return end 72 | 73 | local cmd = nil 74 | if type(config.cmd) == "table" then 75 | cmd = config.cmd[1] 76 | elseif type(config.cmd) == "string" then 77 | cmd = config.cmd 78 | end 79 | 80 | if cmd == nil then return end 81 | 82 | local output = vim.fn.trim(vim.fn.system({ "which", cmd })) 83 | 84 | if vim.fn.filereadable(output) then vim.lsp.enable(client) end 85 | end 86 | 87 | return M 88 | -------------------------------------------------------------------------------- /files/nvim/lua/ag/lsp/completion.lua: -------------------------------------------------------------------------------- 1 | -- enable built-in autocompletion for LSPs 2 | vim.api.nvim_create_autocmd("LspAttach", { 3 | callback = function(args) 4 | vim.bo.completeopt = "menuone,noselect,fuzzy,popup" 5 | local client = vim.lsp.get_client_by_id(args.data.client_id) 6 | if client == nil then return end 7 | -- automatically trigger autocomplete 8 | vim.api.nvim_create_autocmd({ "InsertCharPre" }, { 9 | buffer = args.buf, 10 | callback = function() vim.lsp.completion.get() end, 11 | }) 12 | 13 | vim.lsp.completion.enable(true, client.id, args.buf, { autotrigger = true }) 14 | end, 15 | }) 16 | -------------------------------------------------------------------------------- /files/nvim/lua/ag/lsp/init.lua: -------------------------------------------------------------------------------- 1 | vim.lsp.log.set_level(vim.log.levels.INFO) 2 | -- require("ag.lsp.completion") 3 | 4 | return { 5 | filetypes = { 6 | "python", 7 | "javascript", 8 | "typescript", 9 | "lua", 10 | "bash", 11 | "sh", 12 | "yaml", 13 | "json", 14 | "rust", 15 | "go", 16 | "dart", 17 | "vue", 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /files/nvim/lua/ag/mappings.lua: -------------------------------------------------------------------------------- 1 | -- Mapping helper 2 | ---@param mode string 3 | ---@param key string 4 | ---@param result function | string 5 | ---@param desc? string 6 | local mapper = function(mode, key, result, desc) 7 | vim.keymap.set(mode, key, result, { noremap = true, silent = true, desc = desc }) 8 | end 9 | 10 | -- command line abbreviations to fix common typos 11 | local cabbrev = function(before, after) vim.cmd("cnorea " .. before .. " " .. after) end 12 | 13 | -- Essentials 14 | mapper("i", "jj", "") 15 | mapper("n", "no", ":nohl") 16 | mapper("n", "", "daw") 17 | mapper("n", "", ":e:echo") 18 | mapper("n", "", "") 19 | mapper("n", "I", "0I") 20 | 21 | -- Fix common typos 22 | cabbrev("w'", "w") 23 | cabbrev("w;", "w") 24 | cabbrev("W", "w") 25 | 26 | -- Movemint 27 | -- move by line even with `wrap` set 28 | mapper("n", "j", "gj") 29 | mapper("n", "k", "gk") 30 | -- Readline-like insert mode mappings 31 | mapper("i", "", "$", "End of line") 32 | mapper("i", "", "0", "Beginning of line") 33 | -- Move between windows 34 | mapper("n", "", "j", "Window down") 35 | mapper("n", "", "h", "Window left") 36 | mapper("n", "", "k", "Window up") 37 | mapper("n", "", "l", "Window right") 38 | -- Term 39 | mapper("t", "", [[]], "Terminal esc") 40 | mapper("t", "", [[j]], "Window down") 41 | mapper("t", "", [[h]], "Window left") 42 | mapper("t", "", [[k]], "Window up") 43 | mapper("t", "", [[l]], "Window right") 44 | -- Quickfix 45 | mapper("n", "", "cnext", "Next quickfix") 46 | mapper("n", "", "cprev", "Prev quickfix") 47 | mapper("n", "", "cclose", "Close quickfix") 48 | mapper("n", "", "copen", "Open quickfix") 49 | 50 | -- Others 51 | mapper("n", "", [["pdd"pp]], "Move line down") 52 | mapper("n", "", [["pddk"pP]], "Move line up") 53 | mapper("n", "", "3") -- scroll down more quickly 54 | mapper("n", "", "3") -- scroll up more quickly 55 | mapper("n", "bn", ":bn", "Next buffer") 56 | mapper("n", "bp", ":bp", "Prev buffer") 57 | mapper("n", "bd", ":bp | bd #", "Delete current buffer") 58 | mapper("n", "+", "=", "Format") 59 | mapper("i", "", [[:set pastei":set nopastea]], "'set paste' automatically") 60 | mapper("n", "tn", "tabn", "Next tab") 61 | mapper("n", "tp", "tabp", "Prev tab") 62 | mapper("n", "tq", "tabcl", "Close tab") 63 | -------------------------------------------------------------------------------- /files/nvim/lua/ag/plugins/aerial.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "stevearc/aerial.nvim", 3 | dependencies = { 4 | "nvim-treesitter/nvim-treesitter", 5 | }, 6 | keys = { 7 | { 8 | "ou", 9 | "AerialToggle!", 10 | desc = "Open code outline", 11 | }, 12 | }, 13 | opts = { 14 | backends = { "treesitter" }, 15 | layout = { 16 | max_width = 40, 17 | min_width = 20, 18 | }, 19 | close_automatic_events = { "switch_buffer" }, 20 | manage_folds = false, 21 | link_folds_to_tree = false, 22 | link_tree_to_folds = true, 23 | treesitter = { 24 | update_delay = 100, 25 | }, 26 | filter_kind = { 27 | "Class", 28 | "Constructor", 29 | "Enum", 30 | "Function", 31 | "Interface", 32 | "Module", 33 | "Method", 34 | "Struct", 35 | "Field", 36 | "Key", 37 | "Namespace", 38 | "Property", 39 | }, 40 | }, 41 | } 42 | -------------------------------------------------------------------------------- /files/nvim/lua/ag/plugins/alpha.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "goolord/alpha-nvim", 3 | lazy = false, 4 | dependencies = { 5 | "nvim-tree/nvim-web-devicons", 6 | }, 7 | config = function() 8 | local dashboard = require("alpha.themes.dashboard") 9 | local nvim_web_devicons = require("nvim-web-devicons") 10 | local path = require("plenary.path") 11 | local cdir = vim.fn.getcwd() 12 | 13 | local header = { 14 | type = "text", 15 | val = cdir, 16 | opts = { 17 | position = "center", 18 | hl = "Bold", 19 | }, 20 | } 21 | 22 | ---Get file extension 23 | ---@param fn string filename 24 | ---@return string 25 | local function get_extension(fn) 26 | local match = fn:match("^.+(%..+)$") 27 | local ext = "" 28 | if match ~= nil then ext = match:sub(2) end 29 | return ext 30 | end 31 | 32 | ---Get the icon corresponding to a file extension 33 | ---@param fn string filename 34 | ---@return string, string 35 | local function icon(fn) 36 | local nwd = require("nvim-web-devicons") 37 | local ext = get_extension(fn) 38 | return nwd.get_icon(fn, ext, { default = true }) 39 | end 40 | 41 | ---@param fn string filename 42 | ---@param sc string shortcut key 43 | ---@param short_fn string | nil shortened filename 44 | ---@return table 45 | local function file_button(fn, sc, short_fn) 46 | short_fn = short_fn or fn 47 | local ico_txt 48 | local fb_hl = {} 49 | 50 | local ico, hl = icon(fn) 51 | local hl_option_type = type(nvim_web_devicons.highlight) 52 | if hl_option_type == "boolean" then 53 | if hl and nvim_web_devicons.highlight then table.insert(fb_hl, { hl, 0, 1 }) end 54 | end 55 | if hl_option_type == "string" then table.insert(fb_hl, { nvim_web_devicons.highlight, 0, 1 }) end 56 | ico_txt = ico .. " " 57 | 58 | local file_button_el = dashboard.button(sc, ico_txt .. short_fn, "e " .. fn .. " ") 59 | local fn_start = short_fn:match(".*/") 60 | if fn_start ~= nil then table.insert(fb_hl, { "Comment", #ico_txt - 2, #fn_start + #ico_txt }) end 61 | file_button_el.opts.hl = fb_hl 62 | return file_button_el 63 | end 64 | 65 | local default_mru_ignore = { "gitcommit" } 66 | 67 | local mru_opts = { 68 | ignore = function(path, ext) 69 | return (string.find(path, "COMMIT_EDITMSG")) or (vim.tbl_contains(default_mru_ignore, ext)) 70 | end, 71 | } 72 | 73 | ---Get most recently used files 74 | ---@param cwd string current dir 75 | ---@param num_items number|nil number of recent files to fetch 76 | ---@param opts table|nil 77 | ---@return table 78 | local function mru(cwd, num_items, opts) 79 | opts = opts or mru_opts 80 | num_items = num_items or 9 81 | 82 | local oldfiles = {} 83 | for _, v in pairs(vim.v.oldfiles) do 84 | if #oldfiles == num_items then break end 85 | local cwd_cond 86 | if not cwd then 87 | cwd_cond = true 88 | else 89 | cwd_cond = vim.startswith(v, cwd) 90 | end 91 | local ignore = (opts.ignore and opts.ignore(v, get_extension(v))) or false 92 | if (vim.fn.filereadable(v) == 1) and cwd_cond and not ignore then oldfiles[#oldfiles + 1] = v end 93 | end 94 | 95 | local target_width = 35 96 | 97 | local tbl = {} 98 | for i, fn in ipairs(oldfiles) do 99 | local short_fn 100 | if cwd then 101 | short_fn = vim.fn.fnamemodify(fn, ":.") 102 | else 103 | short_fn = vim.fn.fnamemodify(fn, ":~") 104 | end 105 | 106 | if #short_fn > target_width then 107 | short_fn = path.new(short_fn):shorten(1, { -2, -1 }) 108 | if #short_fn > target_width then short_fn = path.new(short_fn):shorten(1, { -1 }) end 109 | if #short_fn > target_width then short_fn = short_fn:sub(1, target_width - 3) .. "..." end 110 | end 111 | 112 | local shortcut = tostring(i) 113 | 114 | local file_button_el = file_button(fn, " " .. shortcut, short_fn) 115 | tbl[i] = file_button_el 116 | end 117 | return { 118 | type = "group", 119 | val = tbl, 120 | opts = {}, 121 | } 122 | end 123 | 124 | local buttons = { 125 | type = "group", 126 | val = { 127 | { type = "text", val = "Quick links", opts = { hl = "SpecialComment", position = "center" } }, 128 | { type = "padding", val = 1 }, 129 | dashboard.button("e", " New file", ":enew :lua require('snacks').explorer.open()"), 130 | dashboard.button("f", " Find file", ":lua require('snacks').picker.files()"), 131 | dashboard.button("g", " Live grep", ":lua require('snacks').picker.grep()"), 132 | dashboard.button("d", " Open Diffview", ":DiffviewOpen"), 133 | dashboard.button("s", " Update Plugins", ":Lazy sync"), 134 | dashboard.button("q", "󰩈 Quit", ":qa"), 135 | }, 136 | position = "center", 137 | } 138 | 139 | local section_mru = { 140 | type = "group", 141 | val = { 142 | { 143 | type = "text", 144 | val = "Recent files", 145 | opts = { 146 | hl = "SpecialComment", 147 | shrink_margin = false, 148 | position = "center", 149 | }, 150 | }, 151 | { type = "padding", val = 1 }, 152 | { 153 | type = "group", 154 | val = function() return { mru(cdir, 9) } end, 155 | opts = { shrink_margin = false }, 156 | }, 157 | }, 158 | } 159 | 160 | local opts = { 161 | layout = { 162 | { type = "padding", val = 2 }, 163 | header, 164 | { type = "padding", val = 2 }, 165 | section_mru, 166 | { type = "padding", val = 2 }, 167 | buttons, 168 | }, 169 | opts = { 170 | margin = 5, 171 | }, 172 | } 173 | require("alpha").setup(opts) 174 | end, 175 | } 176 | -------------------------------------------------------------------------------- /files/nvim/lua/ag/plugins/blink.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "saghen/blink.cmp", 3 | event = "InsertEnter", 4 | dependencies = { 5 | { 6 | "L3MON4D3/LuaSnip", 7 | version = "v2.*", 8 | }, 9 | }, 10 | -- use a release tag to download pre-built binaries 11 | version = "v0.*", 12 | opts = { 13 | -- disable for special buffers 14 | enabled = function() return not vim.tbl_contains({ "snacks_picker_input", "copilot-chat" }, vim.bo.filetype) end, 15 | 16 | -- For the most part keep default keymaps, but trigger with instead of 17 | keymap = { 18 | preset = "default", 19 | [""] = { "show", "show_documentation", "hide_documentation" }, 20 | [""] = { "hide", "fallback" }, 21 | [""] = { "select_and_accept", "fallback" }, 22 | 23 | [""] = { "select_prev", "fallback" }, 24 | [""] = { "select_next", "fallback" }, 25 | 26 | [""] = { "scroll_documentation_up", "fallback" }, 27 | [""] = { "scroll_documentation_down", "fallback" }, 28 | }, 29 | 30 | appearance = { 31 | nerd_font_variant = "mono", 32 | }, 33 | 34 | sources = { 35 | default = { "snippets", "lsp", "path", "buffer" }, 36 | per_filetype = { yaml = { "path", "buffer" } }, 37 | min_keyword_length = 0, 38 | providers = { 39 | markdown = { 40 | name = "RenderMarkdown", 41 | module = "render-markdown.integ.blink", 42 | fallbacks = { "lsp" }, 43 | }, 44 | lsp = { 45 | name = "LSP", 46 | module = "blink.cmp.sources.lsp", 47 | fallbacks = { "buffer" }, 48 | }, 49 | path = { 50 | name = "Path", 51 | module = "blink.cmp.sources.path", 52 | fallbacks = { "buffer" }, 53 | opts = { 54 | -- complete path from vim CWD rather than buffer directory 55 | get_cwd = function(_) return vim.fn.getcwd() end, 56 | }, 57 | }, 58 | }, 59 | }, 60 | 61 | cmdline = { 62 | enabled = false, 63 | }, 64 | 65 | completion = { 66 | -- disable automatically adding brackets on accept: really annoying for adding imports 67 | accept = { auto_brackets = { enabled = false } }, 68 | 69 | documentation = { 70 | -- show documentation popup by default 71 | auto_show = true, 72 | }, 73 | 74 | -- show ghost text of top completion item 75 | ghost_text = { enabled = false }, 76 | 77 | -- use entire word under cursor for completion, not just the part before the cursor 78 | keyword = { range = "full" }, 79 | 80 | list = { 81 | -- Limit number of results shown in menu 82 | max_items = 25, 83 | -- allow cycling on either end of the list 84 | cycle = { 85 | from_bottom = true, 86 | from_top = true, 87 | }, 88 | selection = { 89 | preselect = false, 90 | auto_insert = true, 91 | }, 92 | }, 93 | 94 | menu = { 95 | -- Show completion menu by default 96 | auto_show = true, 97 | -- menu looks more like nvim-cmp 98 | border = "single", 99 | draw = { 100 | columns = { { "label", "label_description", gap = 1 }, { "kind_icon", "kind" } }, 101 | }, 102 | }, 103 | }, 104 | 105 | -- Enable experimental signature help support 106 | signature = { 107 | enabled = true, 108 | window = { 109 | border = "single", 110 | }, 111 | }, 112 | 113 | -- enable luasnip as snippet backend 114 | snippets = { 115 | preset = "luasnip", 116 | expand = function(snippet) require("luasnip").lsp_expand(snippet) end, 117 | active = function(filter) 118 | if filter and filter.direction then return require("luasnip").jumpable(filter.direction) end 119 | return require("luasnip").in_snippet() 120 | end, 121 | jump = function(direction) require("luasnip").jump(direction) end, 122 | }, 123 | }, 124 | -- allows extending the providers array elsewhere in your config 125 | -- without having to redefine it 126 | opts_extend = { "sources.default" }, 127 | } 128 | -------------------------------------------------------------------------------- /files/nvim/lua/ag/plugins/catppuccin.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "catppuccin/nvim", 3 | name = "catppuccin", 4 | build = ":CatppuccinCompile", 5 | lazy = false, 6 | priority = 1000, 7 | enabled = true, 8 | opts = { 9 | transparent_background = false, 10 | flavour = "auto", 11 | term_colors = true, 12 | compile = { 13 | enabled = true, 14 | path = vim.fn.stdpath("cache") .. "/catppuccin", 15 | }, 16 | background = { 17 | light = "latte", 18 | dark = "mocha", 19 | }, 20 | styles = { 21 | comments = { "italic" }, 22 | }, 23 | custom_highlights = function(colors) 24 | return { 25 | -- More pronounced treesitter context background 26 | TreesitterContext = { 27 | bg = colors.mantle, 28 | }, 29 | } 30 | end, 31 | default_integrations = false, 32 | integrations = { 33 | aerial = true, 34 | alpha = true, 35 | blink_cmp = true, 36 | diffview = true, 37 | gitsigns = true, 38 | native_lsp = { 39 | enabled = true, 40 | inlay_hints = { 41 | background = false, 42 | }, 43 | virtual_text = {}, 44 | underlines = { 45 | errors = { "underline" }, 46 | }, 47 | }, 48 | render_markdown = true, 49 | semantic_tokens = true, 50 | snacks = { 51 | enabled = true, 52 | indent_scope_color = "blue", 53 | }, 54 | treesitter = true, 55 | treesitter_context = true, 56 | }, 57 | }, 58 | } 59 | -------------------------------------------------------------------------------- /files/nvim/lua/ag/plugins/copilot.lua: -------------------------------------------------------------------------------- 1 | local copilot = { 2 | "zbirenbaum/copilot.lua", 3 | keys = { 4 | { 5 | "", 6 | function() require("copilot.suggestion").next() end, 7 | mode = "i", 8 | desc = "Next copilot suggestion", 9 | }, 10 | { 11 | "", 12 | function() require("copilot.suggestion").prev() end, 13 | mode = "i", 14 | desc = "Prev copilot suggestion", 15 | }, 16 | { 17 | "", 18 | function() require("copilot.suggestion").accept_line() end, 19 | mode = "i", 20 | desc = "Accept copilot suggestion", 21 | }, 22 | }, 23 | cmd = { 24 | "Copilot", 25 | }, 26 | opts = { 27 | suggestion = { 28 | enabled = true, 29 | auto_trigger = false, 30 | hide_during_completion = true, 31 | keymap = { 32 | accept = "", 33 | next = "", 34 | prev = "", 35 | dismiss = "", 36 | }, 37 | }, 38 | panel = { 39 | enabled = true, 40 | keymap = { 41 | jump_prev = "cp", 42 | jump_next = "cn", 43 | accept = "", 44 | refresh = "gr", 45 | }, 46 | }, 47 | filetypes = { 48 | markdown = false, 49 | gitrebase = false, 50 | help = false, 51 | gitcommit = false, 52 | ["*"] = true, 53 | }, 54 | }, 55 | } 56 | 57 | local chat = { 58 | "CopilotC-Nvim/CopilotChat.nvim", 59 | branch = "main", 60 | dependencies = { 61 | { "zbirenbaum/copilot.lua" }, 62 | { "nvim-lua/plenary.nvim" }, 63 | }, 64 | opts = { 65 | debug = false, 66 | model = "gpt-4o", 67 | window = { 68 | layout = "float", 69 | border = "rounded", 70 | }, 71 | prompts = { 72 | PythonExpert = { 73 | system_prompt = "You are an expert Python developer with knowledge of language best practices, helping an experienced software engineer in their day to day work", 74 | }, 75 | }, 76 | mappings = { 77 | -- Swap default "submit" and "accept" mappings - I don't really use diff mappings and is more common for me 78 | submit_prompt = { 79 | normal = "", 80 | insert = "", 81 | }, 82 | accept_diff = { 83 | normal = "", 84 | insert = "", 85 | }, 86 | }, 87 | }, 88 | keys = { 89 | { 90 | "cc", 91 | function() 92 | -- make sure telescope UI select is loaded first 93 | require("telescope").load_extension("ui-select") 94 | 95 | -- Pick a prompt using vim.ui.select 96 | local actions = require("CopilotChat.actions") 97 | actions.pick(actions.prompt_actions({ 98 | selection = require("CopilotChat.select").visual, 99 | })) 100 | end, 101 | mode = { "n", "v" }, 102 | desc = "Copilot Chat Action", 103 | }, 104 | { 105 | "co", 106 | function() require("CopilotChat").open() end, 107 | mode = { "n", "v" }, 108 | }, 109 | }, 110 | cmd = { 111 | "CopilotChat", 112 | "CopilotChatOpen", 113 | "CopilotChatToggle", 114 | "CopilotChatExplain", 115 | "CopilotChatReview", 116 | "CopilotChatFix", 117 | "CopilotChatOptimize", 118 | "CopilotChatDocs", 119 | "CopilotChatTests", 120 | "CopilotChatFixDiagnostic", 121 | "CopilotChatCommit", 122 | "CopilotChatCommitStaged", 123 | "CopilotChatModels", 124 | }, 125 | } 126 | 127 | return { 128 | copilot, 129 | chat, 130 | } 131 | -------------------------------------------------------------------------------- /files/nvim/lua/ag/plugins/fterm.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "numToStr/FTerm.nvim", 3 | keys = { 4 | { "", function() require("FTerm").toggle() end, mode = { "n", "t", "i" }, desc = "toggle floatterm" }, 5 | { "tt", "FTest", mode = "n", desc = "test current file" }, 6 | { "ta", "FTest all", mode = "n", desc = "run test suite" }, 7 | }, 8 | cmd = { 9 | "FTest", 10 | }, 11 | config = function() 12 | local get_pytest_prefix = function() 13 | local cmd = "pytest" 14 | local pipenv_venv_path = require("ag.utils").get_python_venv_path() 15 | if pipenv_venv_path ~= nil then cmd = pipenv_venv_path .. "/bin/pytest" end 16 | 17 | return cmd 18 | end 19 | 20 | local test_commands = { 21 | python = get_pytest_prefix, 22 | } 23 | 24 | vim.api.nvim_create_user_command("FTest", function(opts) 25 | local buf = vim.api.nvim_buf_get_name(0) 26 | local filetype = vim.filetype.match({ filename = buf }) 27 | local runner = test_commands[filetype] 28 | local scratch_cmd = {} 29 | 30 | if vim.tbl_contains(opts["fargs"], "all") then 31 | scratch_cmd = { runner() } 32 | else 33 | scratch_cmd = { runner(), buf } 34 | end 35 | 36 | if runner ~= nil then require("FTerm").scratch({ cmd = scratch_cmd }) end 37 | end, { desc = "Test current file", nargs = "?" }) 38 | 39 | -- display 40 | require("FTerm").setup({ 41 | border = "rounded", 42 | cmd = { "/bin/zsh", "-l" }, 43 | }) 44 | end, 45 | } 46 | -------------------------------------------------------------------------------- /files/nvim/lua/ag/plugins/git.lua: -------------------------------------------------------------------------------- 1 | local fugitive = { 2 | "tpope/vim-fugitive", 3 | dependencies = { 4 | "tpope/vim-rhubarb", 5 | }, 6 | init = function() 7 | local ent_url = vim.fn.environ()["GH_ENTERPRISE_URL"] 8 | if ent_url ~= nil then 9 | vim.g.github_enterprise_urls = { 10 | [ent_url] = "https://" .. ent_url, 11 | } 12 | end 13 | end, 14 | keys = { 15 | { 16 | "gs", 17 | ":tab Git", 18 | desc = "Git status in new tab", 19 | }, 20 | { 21 | "gx", 22 | ":GBrowse", 23 | desc = "Open current file in GitHub", 24 | }, 25 | }, 26 | cmd = "Git", 27 | } 28 | local gitsigns = { 29 | "lewis6991/gitsigns.nvim", 30 | opts = { 31 | preview_config = { 32 | border = "single", 33 | style = "minimal", 34 | relative = "cursor", 35 | row = 0, 36 | col = 1, 37 | }, 38 | signcolumn = true, 39 | numhl = true, 40 | current_line_blame = true, 41 | current_line_blame_opts = { 42 | virt_text = true, 43 | virt_text_pos = "right_align", 44 | }, 45 | on_attach = function(bufnr) 46 | local keymap_opts = { silent = true, noremap = true, buffer = bufnr } 47 | vim.keymap.set( 48 | "n", 49 | "=", 50 | "Gitsigns preview_hunk", 51 | vim.tbl_extend("force", keymap_opts, { desc = "Gitsigns float preview" }) 52 | ) 53 | vim.keymap.set( 54 | "n", 55 | "rh", 56 | "Gitsigns reset_hunk", 57 | vim.tbl_extend("force", keymap_opts, { desc = "Gitsigns float preview" }) 58 | ) 59 | vim.keymap.set( 60 | "n", 61 | "sh", 62 | "Gitsigns stage_hunk", 63 | vim.tbl_extend("force", keymap_opts, { desc = "Gitsigns stage" }) 64 | ) 65 | vim.keymap.set( 66 | "n", 67 | "gn", 68 | function() 69 | require("gitsigns").nav_hunk( 70 | "next", 71 | { wrap = true, navigation_message = true, foldopen = false, preview = false } 72 | ) 73 | end, 74 | vim.tbl_extend("force", keymap_opts, { desc = "Gitsigns goto next" }) 75 | ) 76 | vim.keymap.set( 77 | "n", 78 | "gp", 79 | function() 80 | require("gitsigns").nav_hunk( 81 | "prev", 82 | { wrap = true, navigation_message = true, foldopen = false, preview = false } 83 | ) 84 | end, 85 | vim.tbl_extend("force", keymap_opts, { desc = "Gitsigns goto prev" }) 86 | ) 87 | vim.keymap.set( 88 | "n", 89 | "U", 90 | function() require("gitsigns").undo_stage_hunk() end, 91 | vim.tbl_extend("force", keymap_opts, { desc = "Undo last stage hunk" }) 92 | ) 93 | end, 94 | }, 95 | } 96 | local diffview = { 97 | "sindrets/diffview.nvim", 98 | keys = { 99 | { 100 | "gd", 101 | "DiffviewOpen", 102 | desc = "Open changed files", 103 | }, 104 | }, 105 | cmd = { 106 | "DiffviewOpen", 107 | "DiffviewFileHistory", 108 | }, 109 | opts = { 110 | enhanced_diff_hl = true, 111 | view = { 112 | merge_tool = { 113 | layout = "diff3_mixed", 114 | }, 115 | }, 116 | }, 117 | } 118 | 119 | return { 120 | fugitive, 121 | gitsigns, 122 | diffview, 123 | } 124 | -------------------------------------------------------------------------------- /files/nvim/lua/ag/plugins/local.lua: -------------------------------------------------------------------------------- 1 | -- load any maching-specific plugins 2 | local custom_plugins = vim.fn.environ()["CUSTOM_NVIM_PLUGINS"] 3 | local misc_plugins = {} 4 | 5 | if custom_plugins == nil then return misc_plugins end 6 | 7 | for _, plugin_dir in ipairs(vim.split(custom_plugins, ",", { trimempty = true })) do 8 | if vim.fn.isdirectory(plugin_dir) then table.insert(misc_plugins, { dir = plugin_dir, dev = true }) end 9 | end 10 | 11 | return misc_plugins 12 | -------------------------------------------------------------------------------- /files/nvim/lua/ag/plugins/lsp.lua: -------------------------------------------------------------------------------- 1 | local efm = { 2 | "creativenull/efmls-configs-nvim", 3 | version = "v1.x.x", 4 | ft = { 5 | "lua", 6 | "typescript", 7 | "javascript", 8 | "vue", 9 | "python", 10 | "bash", 11 | "sh", 12 | }, 13 | } 14 | 15 | return { 16 | efm, 17 | } 18 | -------------------------------------------------------------------------------- /files/nvim/lua/ag/plugins/lualine.lua: -------------------------------------------------------------------------------- 1 | local IS_WIDE = function() return vim.o.columns > 150 end 2 | 3 | return { 4 | "nvim-lualine/lualine.nvim", 5 | dependencies = { 6 | "nvim-tree/nvim-web-devicons", 7 | "AndreM222/copilot-lualine", 8 | }, 9 | opts = { 10 | sections = { 11 | --+-------------------------------------------------+-- 12 | --| A | B | C X | Y | Z |-- 13 | --+-------------------------------------------------+-- 14 | lualine_a = { 15 | { 16 | "mode", 17 | fmt = function(m) return IS_WIDE() and m or m:sub(1, 1) end, 18 | }, 19 | }, 20 | lualine_b = { "branch" }, 21 | lualine_c = { 22 | { 23 | "diff", 24 | symbols = { 25 | modified = "~", 26 | removed = "-", 27 | added = "+", 28 | }, 29 | }, 30 | -- add empty section to center filename 31 | { 32 | "%=", 33 | }, 34 | -- A hack to change the path type if the window gets too short. Lualine doesn't accept a function for the 35 | -- `path` option, so just swap out the entire component 36 | { 37 | "filename", 38 | path = 1, -- full file path 39 | color = { fg = "#ffffff", gui = "bold" }, 40 | shorting_target = 30, 41 | cond = IS_WIDE, 42 | }, 43 | { 44 | "filename", 45 | path = 0, -- just the filename 46 | color = { fg = "#ffffff", gui = "bold" }, 47 | shorting_target = 30, 48 | cond = function() return not IS_WIDE() end, 49 | }, 50 | }, 51 | lualine_x = { 52 | { 53 | "copilot", 54 | show_colors = true, 55 | show_status = true, 56 | color = { gui = "bold" }, 57 | symbols = { 58 | status = { 59 | enabled = " ", 60 | sleep = " ", 61 | disabled = " ", 62 | warning = " ", 63 | unknown = " ", 64 | }, 65 | }, 66 | }, 67 | }, 68 | lualine_y = { 69 | { 70 | "lsp_status", 71 | icon = " LSP:", 72 | color = { gui = "bold" }, 73 | cond = IS_WIDE, 74 | }, 75 | { 76 | "diagnostics", 77 | sources = { "nvim_diagnostic" }, 78 | }, 79 | }, 80 | lualine_z = { 81 | { "filetype" }, 82 | { "location", cond = IS_WIDE }, 83 | { "progress", cond = IS_WIDE }, 84 | }, 85 | }, 86 | tabline = { 87 | lualine_a = { 88 | { 89 | "buffers", 90 | mode = 0, -- name only 91 | max_length = vim.o.columns / 2, 92 | use_mode_colors = true, 93 | }, 94 | }, 95 | lualine_b = {}, 96 | lualine_c = {}, 97 | lualine_x = {}, 98 | lualine_y = {}, 99 | lualine_z = { "tabs" }, 100 | }, 101 | options = { 102 | section_separators = { left = "", right = "" }, 103 | component_separators = { left = "", right = "" }, 104 | theme = "catppuccin", 105 | globalstatus = true, 106 | disabled_filetypes = { "alpha" }, 107 | }, 108 | extensions = { 109 | "aerial", 110 | "fugitive", 111 | "lazy", 112 | "man", 113 | "quickfix", 114 | }, 115 | }, 116 | } 117 | -------------------------------------------------------------------------------- /files/nvim/lua/ag/plugins/luasnip.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "L3MON4D3/LuaSnip", -- snippets 3 | name = "luasnip", 4 | version = "v2.*", 5 | build = "make install_jsregexp", 6 | config = function() 7 | local ls = require("luasnip") 8 | local types = require("luasnip.util.types") 9 | local snippets = require("ag.snippets") 10 | 11 | ---#Config 12 | ls.setup({ 13 | keep_roots = false, 14 | link_roots = false, 15 | link_children = false, 16 | -- Update snippet text in _real time_ 17 | updateevents = { "TextChanged", "TextChangedI" }, 18 | enable_autosnippets = true, 19 | delete_check_events = { "InsertLeave" }, 20 | -- Show virtual text hints for node types 21 | ext_opts = { 22 | [types.insertNode] = { 23 | active = { 24 | virt_text = { { "●", "Operator" } }, 25 | }, 26 | }, 27 | [types.choiceNode] = { 28 | active = { 29 | virt_text = { { "●", "Constant" } }, 30 | }, 31 | }, 32 | }, 33 | }) 34 | -- load vscode style snippets from other plugins 35 | require("luasnip.loaders.from_vscode").lazy_load() 36 | 37 | ---#Mappings 38 | -- Previous snippet region 39 | vim.keymap.set({ "i", "s" }, "", function() 40 | if ls.jumpable(-1) then ls.jump(-1) end 41 | end, { silent = true, desc = "Next snippet node" }) 42 | 43 | -- Expand snippet, or go to next snippet region 44 | vim.keymap.set({ "i", "s" }, "", function() 45 | if ls.expand_or_jumpable() then ls.expand_or_jump() end 46 | end, { silent = true, desc = "Prev snippet node" }) 47 | 48 | -- Cycle "choices" for current snippet region 49 | vim.keymap.set({ "i", "s" }, "", function() 50 | if ls.choice_active() then ls.change_choice(1) end 51 | end, { silent = true, desc = "Next snippet choice" }) 52 | 53 | -- load my custom snippets 54 | ls.add_snippets("typescript", snippets.typescript) 55 | ls.add_snippets("dart", snippets.dart) 56 | ls.add_snippets("python", snippets.python) 57 | end, 58 | ft = { 59 | "vue", 60 | "typescript", 61 | "javascript", 62 | "dart", 63 | "rust", 64 | "python", 65 | }, 66 | } 67 | -------------------------------------------------------------------------------- /files/nvim/lua/ag/plugins/markdown.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "MeanderingProgrammer/render-markdown.nvim", 3 | as = "render-markdown", 4 | dependencies = { 5 | "nvim-treesitter/nvim-treesitter", 6 | }, 7 | ft = { 8 | "markdown", 9 | }, 10 | main = "render-markdown", 11 | opts = { 12 | latex = { 13 | enabled = false, 14 | }, 15 | anti_conceal = { 16 | enabled = true, 17 | }, 18 | heading = { 19 | position = "overlay", 20 | border = true, 21 | above = "", 22 | below = "▔", 23 | width = "block", 24 | -- no background highlight for headings 25 | backgrounds = { 26 | "", 27 | "", 28 | "", 29 | "", 30 | "", 31 | "", 32 | }, 33 | }, 34 | code = { 35 | style = "full", -- show language highlights and name in code blocks 36 | width = "block", 37 | right_pad = 2, 38 | }, 39 | link = { 40 | custom = { 41 | github = { 42 | pattern = "^http[s]?://[%w%.%-]*github[%w%.%-]*%.com", 43 | icon = " ", 44 | highlight = "RenderMarkdownTableLink", 45 | }, 46 | docs = { 47 | pattern = "^http[s]?://docs.google.com", 48 | icon = "󰈙 ", 49 | highlight = "RenderMarkdownTableLink", 50 | }, 51 | }, 52 | }, 53 | overrides = { 54 | buftype = { 55 | nofile = { 56 | code = { 57 | style = "normal", -- no language info in LSP hover windows 58 | width = "full", 59 | }, 60 | }, 61 | }, 62 | }, 63 | }, 64 | } 65 | -------------------------------------------------------------------------------- /files/nvim/lua/ag/plugins/misc.lua: -------------------------------------------------------------------------------- 1 | return { 2 | -- utility functions 3 | "nvim-lua/plenary.nvim", 4 | 5 | "tpope/vim-surround", 6 | "tpope/vim-repeat", 7 | -- commenting Just Works 8 | { "numToStr/Comment.nvim", config = true, enabled = false }, 9 | -- autopairs 10 | { 11 | "windwp/nvim-autopairs", 12 | opts = { 13 | map_cr = true, -- send closing symbol to its own line 14 | check_ts = true, -- use treesitter 15 | }, 16 | cond = function() return not vim.tbl_contains({ "TelescopePrompt", "fugitive" }, vim.opt.filetype) end, 17 | event = "InsertEnter", 18 | }, 19 | -- devicons 20 | { 21 | "nvim-tree/nvim-web-devicons", 22 | lazy = true, 23 | }, 24 | -- highlight color codes 25 | { 26 | "norcalli/nvim-colorizer.lua", 27 | config = function() require("colorizer").setup(nil, { css = true }) end, 28 | }, 29 | -- convert quotes to template string quotes automatically 30 | { 31 | "axelvc/template-string.nvim", 32 | config = true, 33 | ft = { 34 | "typescript", 35 | "vue", 36 | "javascript", 37 | "python", 38 | }, 39 | }, 40 | -- align text 41 | { "godlygeek/tabular", cmd = "Tabularize" }, 42 | -- json schema provider 43 | "b0o/schemastore.nvim", 44 | } 45 | -------------------------------------------------------------------------------- /files/nvim/lua/ag/plugins/snacks.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "folke/snacks.nvim", 3 | priority = 1000, 4 | lazy = false, 5 | opts = { 6 | explorer = { 7 | enabled = true, 8 | }, 9 | indent = { 10 | enabled = true, 11 | animate = { 12 | enabled = false, 13 | }, 14 | filter = function(buf) 15 | local disabled_buftypes = { "copilot-chat", "snacks_picker_input" } 16 | local buftype = vim.b[buf].buftype 17 | return not vim.tbl_contains(disabled_buftypes, buftype) 18 | end, 19 | }, 20 | notifier = { 21 | enabled = true, 22 | }, 23 | picker = { 24 | enabled = true, 25 | prompt = "» ", 26 | matcher = { fuzzy = true, smartcase = true, ignorecase = true, frecency = false }, 27 | ui_select = true, 28 | formatters = { 29 | file = { 30 | filename_first = false, -- display filename before the file path 31 | truncate = 40, -- truncate the file path to (roughly) this length 32 | filename_only = false, -- only show the filename 33 | icon_width = 2, -- width of the icon (in characters) 34 | git_status_hl = false, -- use the git status highlight group for the filename 35 | }, 36 | }, 37 | jump = { 38 | reuse_win = false, -- reuse an existing window if the buffer is already open 39 | jumplist = true, -- save current position in the jumplist 40 | }, 41 | }, 42 | statuscolumn = { 43 | enabled = true, 44 | }, 45 | }, 46 | keys = { 47 | -- pickers 48 | { 49 | "fb", 50 | function() 51 | require("snacks").picker.buffers({ 52 | win = { 53 | input = { 54 | keys = { 55 | [""] = { "bufdelete", mode = { "n", "i" } }, 56 | [""] = { "edit_split", mode = { "n", "i" } }, 57 | }, 58 | }, 59 | }, 60 | }) 61 | end, 62 | desc = "Fuzzy find buffers", 63 | }, 64 | { 65 | "ff", 66 | function() 67 | require("snacks").picker.files({ 68 | win = { 69 | input = { 70 | keys = { 71 | [""] = { "edit_split", mode = { "n", "i" } }, 72 | }, 73 | }, 74 | }, 75 | }) 76 | end, 77 | desc = "Fuzzy find Files", 78 | }, 79 | { "gg", function() require("snacks").picker.grep() end, desc = "Live grep" }, 80 | { "qf", function() require("snacks").picker.qflist() end, desc = "Fuzzy find in qflist" }, 81 | { "fl", function() require("snacks").picker.lines() end, desc = "Fuzzy find in file" }, 82 | { "fs", function() require("snacks").picker.lsp_symbols() end, desc = "Find LSP symbols" }, 83 | -- explorer (also a picker) 84 | { "nt", function() require("snacks").explorer.open() end, desc = "Open filetree" }, 85 | { "nf", function() require("snacks").explorer.reveal() end, desc = "Open current file in filetree" }, 86 | }, 87 | } 88 | -------------------------------------------------------------------------------- /files/nvim/lua/ag/plugins/swagger-preview.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "vinnymeller/swagger-preview.nvim", 3 | build = "npm install -g swagger-ui-watcher", 4 | enabled = true, 5 | opts = { 6 | port = 8000, 7 | host = "localhost", 8 | }, 9 | cmd = { "SwaggerPreview", "SwaggerPreviewToggle" }, 10 | } 11 | -------------------------------------------------------------------------------- /files/nvim/lua/ag/plugins/tokyonight.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "folke/tokyonight.nvim", -- the other lua colorscheme 3 | lazy = false, 4 | priority = 1000, 5 | enabled = false, 6 | opts = { 7 | style = "night", 8 | transparent = false, 9 | terminal_colors = true, 10 | styles = { 11 | comments = { italic = true }, 12 | }, 13 | on_highlights = function(hl, c) 14 | local prompt = "#2d3149" 15 | -- borderless telescope 16 | hl.TelescopeNormal = { 17 | bg = c.bg_dark, 18 | fg = c.fg_dark, 19 | } 20 | hl.TelescopeBorder = { 21 | bg = c.bg_dark, 22 | fg = c.bg_dark, 23 | } 24 | hl.TelescopePromptNormal = { 25 | bg = prompt, 26 | } 27 | hl.TelescopePromptBorder = { 28 | bg = prompt, 29 | fg = prompt, 30 | } 31 | hl.TelescopePromptTitle = { 32 | bg = prompt, 33 | fg = prompt, 34 | } 35 | hl.TelescopePreviewTitle = { 36 | bg = c.bg_dark, 37 | fg = c.bg_dark, 38 | } 39 | hl.TelescopeResultsTitle = { 40 | bg = c.bg_dark, 41 | fg = c.bg_dark, 42 | } 43 | end, 44 | sidebars = { "qf", "help", "aerial", "packer" }, 45 | }, 46 | } 47 | -------------------------------------------------------------------------------- /files/nvim/lua/ag/plugins/treesitter.lua: -------------------------------------------------------------------------------- 1 | local ts = { 2 | "nvim-treesitter/nvim-treesitter", 3 | main = "nvim-treesitter.configs", 4 | build = ":TSUpdate", 5 | lazy = false, 6 | dependencies = { 7 | -- extra textobjects 8 | "nvim-treesitter/nvim-treesitter-textobjects", 9 | -- commenting for vue SFCs 10 | { 11 | "JoosepAlviste/nvim-ts-context-commentstring", 12 | ft = { "vue" }, 13 | init = function() vim.g.skip_ts_context_commentstring_module = true end, 14 | config = true, 15 | }, 16 | -- auto insert closing tags 17 | { 18 | "windwp/nvim-ts-autotag", 19 | ft = { 20 | "html", 21 | "vue", 22 | }, 23 | }, 24 | }, 25 | init = function() 26 | vim.opt.foldmethod = "expr" -- use function to determine folds 27 | vim.opt.foldexpr = "v:lua.vim.treesitter.foldexpr()" -- use TS for folding 28 | end, 29 | opts = { 30 | -- either "all" or a list of languages 31 | ensure_installed = "all", 32 | ignore_install = { "fusion", "blueprint", "jsonc", "t32" }, -- issues with tarball extraction 33 | highlight = { 34 | -- false will disable the whole extension 35 | enable = true, 36 | additional_vim_regex_highlighting = false, 37 | }, 38 | indent = { 39 | enable = true, 40 | }, 41 | -- custom text objects 42 | textobjects = { 43 | -- change/delete/select in function or class 44 | select = { 45 | enable = true, 46 | lookahead = true, 47 | keymaps = { 48 | ["af"] = "@function.outer", 49 | ["if"] = "@function.inner", 50 | ["ac"] = "@class.outer", 51 | ["ic"] = "@class.inner", 52 | }, 53 | }, 54 | -- easily move to next function/class 55 | move = { 56 | enable = true, 57 | set_jumps = true, -- track in jumplist (, ) 58 | goto_next_start = { 59 | ["]["] = "@function.outer", 60 | [")("] = "@class.outer", 61 | }, 62 | goto_next_end = { 63 | ["]]"] = "@function.outer", 64 | ["))"] = "@class.outer", 65 | }, 66 | goto_previous_start = { 67 | ["[["] = "@function.outer", 68 | ["(("] = "@class.outer", 69 | }, 70 | goto_previous_end = { 71 | ["[]"] = "@function.outer", 72 | ["()"] = "@class.outer", 73 | }, 74 | }, 75 | -- peek definitions from LSP 76 | lsp_interop = { 77 | enable = true, 78 | border = "single", 79 | peek_definition_code = { 80 | ["pf"] = "@function.outer", 81 | ["pc"] = "@class.outer", 82 | }, 83 | }, 84 | swap = { 85 | enable = true, 86 | swap_next = { 87 | ["l"] = "@parameter.inner", 88 | }, 89 | swap_previous = { 90 | ["h"] = "@parameter.inner", 91 | }, 92 | }, 93 | }, 94 | autotag = { 95 | enable = true, 96 | filetypes = { "html", "vue" }, 97 | }, 98 | }, 99 | } 100 | 101 | local ts_context = { 102 | "nvim-treesitter/nvim-treesitter-context", 103 | init = function() 104 | vim.api.nvim_set_hl(0, "TreesitterContextBottom", { 105 | underline = true, 106 | sp = "Grey", 107 | }) 108 | vim.api.nvim_set_hl(0, "TreesitterContextLineNumberBottom", { 109 | underline = true, 110 | sp = "Grey", 111 | }) 112 | end, 113 | opts = { 114 | enable = false, 115 | max_lines = 5, -- How many lines the window should span 116 | min_window_height = 25, 117 | line_numbers = true, 118 | multiline_threshold = 5, -- Maximum number of lines to show for a single context 119 | trim_scope = "outer", -- Which context lines to discard if `max_lines` is exceeded. Choices: 'inner', 'outer' 120 | mode = "topline", -- Line used to calculate context. Choices: 'cursor', 'topline' 121 | }, 122 | } 123 | 124 | return { 125 | ts, 126 | ts_context, 127 | } 128 | -------------------------------------------------------------------------------- /files/nvim/lua/ag/snippets/dart.lua: -------------------------------------------------------------------------------- 1 | require("luasnip.session.snippet_collection").clear_snippets("dart") 2 | 3 | local success, ls = pcall(require, "luasnip") 4 | if not success then return end 5 | local s = ls.snippet 6 | local i = ls.insert_node 7 | local f = ls.function_node 8 | local fmt = require("luasnip.extras.fmt").fmt 9 | local rep = require("luasnip.extras").rep 10 | 11 | return { 12 | s( 13 | "StatelessWidget", 14 | fmt( 15 | [[ 16 | class {name} extends StatelessWidget {{ 17 | {name_rep}({{super.key}}); 18 | 19 | @override 20 | Widget build(BuildContext context) {{ 21 | return {body} 22 | }} 23 | }} 24 | ]], 25 | { 26 | name = i(1, "WidgetName"), 27 | name_rep = rep(1), 28 | body = i(0), 29 | } 30 | ) 31 | ), 32 | s( 33 | "StatefulWidget", 34 | fmt( 35 | [[ 36 | class {name} extends StatefulWidget {{ 37 | {name_rep}({{super.key}}); 38 | 39 | @override 40 | State<{name_rep}> createState() => {impl_name}(); 41 | }} 42 | 43 | class {impl_name} extends State<{name_rep}> {{ 44 | @override 45 | Widget build(BuildContext context) {{ 46 | return {body} 47 | }} 48 | }} 49 | ]], 50 | { 51 | name = i(1, "WidgetName"), 52 | name_rep = rep(1), 53 | impl_name = f(function(args) 54 | local widget_name = args[1][1] 55 | return "_" .. widget_name .. "State" 56 | end, { 1 }), 57 | body = i(0), 58 | } 59 | ) 60 | ), 61 | } 62 | -------------------------------------------------------------------------------- /files/nvim/lua/ag/snippets/init.lua: -------------------------------------------------------------------------------- 1 | local dart = require("ag.snippets.dart") 2 | local python = require("ag.snippets.python") 3 | local typescript = require("ag.snippets.typescript") 4 | 5 | return { 6 | typescript = typescript, 7 | dart = dart, 8 | python = vim.tbl_values(python), 9 | } 10 | -------------------------------------------------------------------------------- /files/nvim/lua/ag/snippets/python.lua: -------------------------------------------------------------------------------- 1 | require("luasnip.session.snippet_collection").clear_snippets("python") 2 | local success, ls = pcall(require, "luasnip") 3 | if not success then return end 4 | local s = ls.snippet 5 | local sn = ls.snippet_node 6 | local i = ls.insert_node 7 | local t = ls.text_node 8 | local c = ls.choice_node 9 | local r = ls.restore_node 10 | local fmt = require("luasnip.extras.fmt").fmt 11 | 12 | local M = {} 13 | 14 | ---Choice snippet to toggle between python docstring and empty text node 15 | ---@param order number where in the root snippet the docstring appears 16 | ---@param default 'DOC' | 'NONE' the default choice to be returned 17 | ---@param placeholder string | nil default text to put as the docstring placeholder 18 | local optional_docstring_choice = function(order, default, placeholder) 19 | local desc = placeholder or "description" 20 | local docstr = sn(nil, { 21 | t({ '"""', "\t" }), 22 | i(1, desc), 23 | t({ "", '\t"""', "\t" }), 24 | }) 25 | 26 | if default == "DOC" then return c(order, { 27 | docstr, 28 | t(""), 29 | }) end 30 | return c(order, { 31 | t(""), 32 | docstr, 33 | }) 34 | end 35 | 36 | --- 37 | local function_fmt = [[ 38 | def {name}({params}){ret}: 39 | {doc}{body} 40 | ]] 41 | M.function_snippet = s( 42 | "def", 43 | fmt(function_fmt, { 44 | doc = optional_docstring_choice(1, "DOC"), 45 | name = i(2, "function_name"), 46 | params = i(3), 47 | ret = c(4, { 48 | sn(nil, { 49 | t({ " -> " }), 50 | r(1, "return_type", i(nil, "None")), 51 | }), 52 | t(""), 53 | }), 54 | body = i(0, "..."), 55 | }, { 56 | stored = { 57 | ["return_type"] = i(nil, "None"), 58 | ["func_name"] = i(nil, "function_name"), 59 | }, 60 | }) 61 | ) 62 | --- 63 | 64 | --- 65 | local test_fmt = [[ 66 | def test_{test_name}({params}): 67 | {doc}{body} 68 | ]] 69 | M.test_function_snippet = s( 70 | "def test", 71 | fmt(test_fmt, { 72 | doc = optional_docstring_choice(1, "DOC", "Test that ..."), 73 | test_name = i(2, "test_name"), 74 | params = i(3), 75 | body = i(0, "assert True"), 76 | }) 77 | ) 78 | --- 79 | 80 | --- 81 | local class_fmt = [[ 82 | class {cls}{parent}: 83 | {doc}{body} 84 | ]] 85 | M.class_snippet = s( 86 | "class", 87 | fmt(class_fmt, { 88 | doc = optional_docstring_choice(1, "DOC"), 89 | cls = i(2, "ClassName"), 90 | parent = c(3, { 91 | t(""), 92 | sn(nil, { 93 | t("("), 94 | i(1, "ParentClass"), 95 | t(")"), 96 | }), 97 | }), 98 | body = i(0, "..."), 99 | }) 100 | ) 101 | --- 102 | 103 | --- 104 | local if_name_main_fmt = [[ 105 | if __name__ == "__main__": 106 | {main} 107 | ]] 108 | M.if_name_main_snippet = s("inm", fmt(if_name_main_fmt, { main = i(0) })) 109 | --- 110 | 111 | --- 112 | local printf_fmt = [[ 113 | print(f"{str}") 114 | ]] 115 | M.printf = s("printf", fmt(printf_fmt, { str = i(0) })) 116 | --- 117 | 118 | return M 119 | -------------------------------------------------------------------------------- /files/nvim/lua/ag/snippets/typescript.lua: -------------------------------------------------------------------------------- 1 | require("luasnip.session.snippet_collection").clear_snippets("typescript") 2 | local success, ls = pcall(require, "luasnip") 3 | if not success then return end 4 | local s = ls.snippet 5 | local sn = ls.snippet_node 6 | local i = ls.insert_node 7 | local isn = ls.indent_snippet_node 8 | local t = ls.text_node 9 | local d = ls.dynamic_node 10 | local c = ls.choice_node 11 | local r = ls.restore_node 12 | local fmt = require("luasnip.extras.fmt").fmt 13 | 14 | local ts_function_fmt = [[ 15 | {doc} 16 | {type} {async}{name}({params}): {ret} {{ 17 | {body} 18 | }} 19 | ]] 20 | local ts_function_snippet = function(type) 21 | return fmt(ts_function_fmt, { 22 | doc = isn(1, { 23 | t({ "/**", " " }), 24 | i(1, "function description"), 25 | c(2, { 26 | sn(nil, { 27 | t({ "", " @returns " }), 28 | i(1, "return description"), 29 | }), 30 | t(""), 31 | }), 32 | t({ "", "/" }), 33 | }, "$PARENT_INDENT *"), 34 | type = t(type), 35 | async = c(2, { t("async "), t("") }), 36 | name = i(3, "funcName"), 37 | params = i(4), 38 | ret = d(5, function(args) 39 | local async = string.match(args[1][1], "async") 40 | if async == nil then 41 | return sn(nil, { 42 | r(1, "return_type", i(nil, "void")), 43 | }) 44 | end 45 | return sn(nil, { 46 | t("Promise<"), 47 | r(1, "return_type", i(nil, "void")), 48 | t(">"), 49 | }) 50 | end, { 2 }), 51 | body = i(0), 52 | }, { 53 | stored = { 54 | ["return_type"] = i(nil, "void"), 55 | }, 56 | }) 57 | end 58 | 59 | local ts_loop_fmt = [[ 60 | .{type}({async}({item}) => {{ 61 | {body} 62 | }}) 63 | ]] 64 | local ts_loop_snippet = function(type) 65 | return fmt(ts_loop_fmt, { 66 | type = t(type), 67 | async = c(1, { t(""), t("async ") }), 68 | item = c(2, { i(1, "item"), sn(nil, { t("{ "), i(1, "field"), t(" }") }) }), 69 | body = i(0), 70 | }) 71 | end 72 | 73 | return { 74 | -- methods 75 | s("public", ts_function_snippet("public")), 76 | s("private", ts_function_snippet("private")), 77 | -- array methods 78 | s({ trig = ".map", wordTrig = false }, ts_loop_snippet("map")), 79 | s({ trig = ".filter", wordTrig = false }, ts_loop_snippet("filter")), 80 | s({ trig = ".forEach", wordTrig = false }, ts_loop_snippet("forEach")), 81 | s({ trig = ".find", wordTrig = false }, ts_loop_snippet("find")), 82 | s({ trig = ".some", wordTrig = false }, ts_loop_snippet("some")), 83 | s({ trig = ".every", wordTrig = false }, ts_loop_snippet("every")), 84 | -- block comments 85 | s( 86 | { trig = "/**", snippetType = "autosnippet" }, 87 | fmt( 88 | [[ 89 | /** 90 | * {comment} 91 | */ 92 | ]], 93 | { 94 | comment = isn(0, { 95 | i(1), 96 | }, "$PARENT_INDENT *"), 97 | } 98 | ) 99 | ), 100 | -- tests 101 | s( 102 | "describe", 103 | fmt( 104 | [[ 105 | describe('{suite}', () => {{ 106 | {body} 107 | }}); 108 | ]], 109 | { 110 | suite = i(1, "function or module"), 111 | body = i(0), 112 | } 113 | ) 114 | ), 115 | s( 116 | "it", 117 | fmt( 118 | [[ 119 | it('{test_case}', {async}() => {{ 120 | {body} 121 | }}); 122 | ]], 123 | { 124 | test_case = i(1, "does something"), 125 | async = c(2, { t("async "), t("") }), 126 | body = i(0), 127 | } 128 | ) 129 | ), 130 | } 131 | -------------------------------------------------------------------------------- /files/nvim/lua/ag/utils.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | ---Get the path to the current pipenv managed virtual environment (if one exists) 4 | ---@return string | nil 5 | local get_pipenv_venv_path = function() 6 | local pipenv_venv = vim.fn.trim(vim.fn.system("pipenv --venv")) 7 | if pipenv_venv == "" then return nil end 8 | local split = vim.split(pipenv_venv, "\n") 9 | for _, line in ipairs(split) do 10 | if string.match(line, "^/") ~= nil then 11 | if vim.fn.isdirectory(line) then return line end 12 | end 13 | end 14 | 15 | return nil 16 | end 17 | 18 | local get_venv_path = function() 19 | if vim.fn.isdirectory(".venv") ~= 0 then return ".venv" end 20 | return nil 21 | end 22 | 23 | ---Get the path to the virtual environment for the current project 24 | ---@return string | nil 25 | M.get_python_venv_path = function() 26 | local venv = get_venv_path() 27 | if venv ~= nil then return venv end 28 | local pipenv = get_pipenv_venv_path() 29 | if pipenv ~= nil then return pipenv end 30 | 31 | return nil 32 | end 33 | 34 | ---Get the python executable path for the current project 35 | ---@return string 36 | M.get_python_path = function() 37 | local venv_path = M.get_python_venv_path() 38 | if venv_path ~= nil then 39 | return venv_path .. "/bin/python" 40 | else 41 | return vim.fn.trim(vim.fn.system("python -c 'import sys; print(sys.executable)'")) 42 | end 43 | end 44 | 45 | -- Use project-local typescript installation if available, fallback to global install 46 | -- assumes typescript installed globally w/ nvm 47 | M.get_typescript_server_path = function(root_dir) 48 | local lspconfig = require("lspconfig") 49 | local global_ts = vim.fn.expand("$NVM_DIR/versions/node/$DEFAULT_NODE_VERSION/lib/node_modules/typescript/lib") 50 | local project_ts = "" 51 | local function check_dir(path) 52 | project_ts = lspconfig.util.path.join(path, "node_modules", "typescript", "lib") 53 | if vim.fn.isdirectory(project_ts) then return path end 54 | end 55 | if lspconfig.util.search_ancestors(root_dir, check_dir) then 56 | return project_ts 57 | else 58 | return global_ts 59 | end 60 | end 61 | 62 | return M 63 | -------------------------------------------------------------------------------- /files/profile: -------------------------------------------------------------------------------- 1 | # ~/.profile: executed by the command interpreter for login shells. 2 | # This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login 3 | # exists. 4 | # see /usr/share/doc/bash/examples/startup-files for examples. 5 | # the files are located in the bash-doc package. 6 | 7 | # the default umask is set in /etc/profile; for setting the umask 8 | # for ssh logins, install and configure the libpam-umask package. 9 | #umask 022 10 | 11 | # Make sure VPN works 12 | sudo service wsl-vpnkit start > /dev/null 2>&1 13 | # brew 14 | eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" 15 | # pyenv 16 | export PYENV_ROOT="$HOME/.pyenv" 17 | export PATH="$PYENV_ROOT/bin:$PATH" 18 | 19 | # if running bash 20 | if [ -n "$BASH_VERSION" ]; then 21 | # include .bashrc if it exists 22 | if [ -f "$HOME/.bashrc" ]; then 23 | . "$HOME/.bashrc" 24 | # more pyenv 25 | eval "$(pyenv init --path)" 26 | fi 27 | fi 28 | 29 | # set PATH so it includes user's private bin if it exists 30 | if [ -d "$HOME/bin" ] ; then 31 | PATH="$HOME/bin:$PATH" 32 | fi 33 | 34 | # set PATH so it includes user's private bin if it exists 35 | if [ -d "$HOME/.local/bin" ] ; then 36 | PATH="$HOME/.local/bin:$PATH" 37 | fi 38 | -------------------------------------------------------------------------------- /files/quarter-life.zsh-theme: -------------------------------------------------------------------------------- 1 | # prompt style and colors based on Steve Losh's Prose theme: 2 | # https://github.com/sjl/oh-my-zsh/blob/master/themes/prose.zsh-theme 3 | # 4 | # vcs_info modifications from Bart Trojanowski's zsh prompt: 5 | # http://www.jukie.net/bart/blog/pimping-out-zsh-prompt 6 | # 7 | # git untracked files modification from Brian Carper: 8 | # https://briancarper.net/blog/570/git-info-in-your-zsh-prompt 9 | 10 | #use extended color palette if available 11 | if [[ $TERM = (*256color|*rxvt*|alacritty*) ]]; then 12 | if [[ "$THEME_MODE" == "Light" ]]; then 13 | turquoise="%{${(%):-"%F{69}"}%}" 14 | orange="%{${(%):-"%F{202}"}%}" 15 | purple="%{${(%):-"%F{129}"}%}" 16 | hotpink="%{${(%):-"%F{161}"}%}" 17 | limegreen="%{${(%):-"%F{34}"}%}" 18 | else 19 | turquoise="%{${(%):-"%F{81}"}%}" 20 | orange="%{${(%):-"%F{166}"}%}" 21 | purple="%{${(%):-"%F{135}"}%}" 22 | hotpink="%{${(%):-"%F{161}"}%}" 23 | limegreen="%{${(%):-"%F{118}"}%}" 24 | fi 25 | else 26 | turquoise="%{${(%):-"%F{cyan}"}%}" 27 | orange="%{${(%):-"%F{yellow}"}%}" 28 | purple="%{${(%):-"%F{magenta}"}%}" 29 | hotpink="%{${(%):-"%F{red}"}%}" 30 | limegreen="%{${(%):-"%F{green}"}%}" 31 | fi 32 | 33 | autoload -Uz vcs_info 34 | # enable VCS systems you use 35 | zstyle ':vcs_info:*' enable git 36 | 37 | # check-for-changes can be really slow. 38 | # you should disable it, if you work with large repositories 39 | zstyle ':vcs_info:*:prompt:*' check-for-changes true 40 | 41 | # set formats 42 | # %b - branchname 43 | # %u - unstagedstr (see below) 44 | # %c - stagedstr (see below) 45 | # %a - action (e.g. rebase-i) 46 | # %R - repository path 47 | # %S - path in the repository 48 | PR_RST="%{${reset_color}%}" 49 | FMT_BRANCH=" on ${turquoise}%b%u%c${PR_RST}" 50 | FMT_ACTION=" performing a ${limegreen}%a${PR_RST}" 51 | FMT_UNSTAGED="${orange} ●" 52 | FMT_STAGED="${limegreen} ●" 53 | 54 | zstyle ':vcs_info:*:prompt:*' unstagedstr "${FMT_UNSTAGED}" 55 | zstyle ':vcs_info:*:prompt:*' stagedstr "${FMT_STAGED}" 56 | zstyle ':vcs_info:*:prompt:*' actionformats "${FMT_BRANCH}${FMT_ACTION}" 57 | zstyle ':vcs_info:*:prompt:*' formats "${FMT_BRANCH}" 58 | zstyle ':vcs_info:*:prompt:*' nvcsformats "" 59 | 60 | 61 | function steeef_chpwd { 62 | PR_GIT_UPDATE=1 63 | } 64 | 65 | function steeef_preexec { 66 | case "$2" in 67 | *git*|*svn*) PR_GIT_UPDATE=1 ;; 68 | esac 69 | } 70 | 71 | function steeef_precmd { 72 | (( PR_GIT_UPDATE )) || return 73 | 74 | # check for untracked files or updated submodules, since vcs_info doesn't 75 | if [[ -n "$(git ls-files --other --exclude-standard 2>/dev/null)" ]]; then 76 | PR_GIT_UPDATE=1 77 | FMT_BRANCH="${PM_RST} ${turquoise} %b%u%c${hotpink} ●${PR_RST}" 78 | else 79 | FMT_BRANCH="${PM_RST} ${turquoise} %b%u%c${PR_RST}" 80 | fi 81 | zstyle ':vcs_info:*:prompt:*' formats "${FMT_BRANCH}" 82 | 83 | vcs_info 'prompt' 84 | PR_GIT_UPDATE= 85 | } 86 | 87 | # vcs_info running hooks 88 | PR_GIT_UPDATE=1 89 | 90 | autoload -U add-zsh-hook 91 | add-zsh-hook chpwd steeef_chpwd 92 | add-zsh-hook precmd steeef_precmd 93 | add-zsh-hook preexec steeef_preexec 94 | 95 | # ruby prompt settings 96 | ZSH_THEME_RUBY_PROMPT_PREFIX="with%F{red} " 97 | ZSH_THEME_RUBY_PROMPT_SUFFIX="%{$reset_color%}" 98 | ZSH_THEME_RVM_PROMPT_OPTIONS="v g" 99 | 100 | setopt prompt_subst 101 | PROMPT="${limegreen}%~%{$reset_color%}\$(ruby_prompt_info)\$vcs_info_msg_0_${orange} λ%{$reset_color%} " 102 | -------------------------------------------------------------------------------- /files/sketchybar/colors.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # Color Palette 4 | DARKER_BLACK=0xff1a1b26 5 | BLACK=0xff15161e 6 | WHITE=0xffd4d4d5 7 | RED=0xfff7768e 8 | GREEN=0xff9ece6a 9 | BLUE=0x7aa2f7 10 | CYAN=0xff7dcfff 11 | YELLOW=0xffe0af68 12 | ORANGE=0xffff9e64 13 | MAGENTA=0xffbb9af7 14 | GREY=0xffa9b1d6 15 | TRANSPARENT=0x00000000 16 | 17 | # General bar colors 18 | BAR_COLOR=$DARKER_BLACK # Black bar 19 | ICON_COLOR=$CYAN # Color of all icons 20 | LABEL_COLOR=$GREEN # Color of all labels 21 | 22 | POPUP_BACKGROUND_COLOR=$BLACK 23 | POPUP_BORDER_COLOR=$GREY 24 | 25 | SHADOW_COLOR=$DARKER_BLACK 26 | -------------------------------------------------------------------------------- /files/sketchybar/icons.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # Battery Icons 4 | BATTERY_100= 5 | BATTERY_75= 6 | BATTERY_50= 7 | BATTERY_25= 8 | BATTERY_0= 9 | BATTERY_CHARGING= 10 | 11 | # Wifi Icons 12 | WIFI_OFF=睊 13 | WIFI_DISCONNECTED=睊 14 | WIFI_CONNECTED= 15 | 16 | # Download/Upload Speed Icons 17 | UPLOAD= 18 | DOWNLOAD= 19 | -------------------------------------------------------------------------------- /files/sketchybar/items/amethyst.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | sketchybar --add item amethyst right \ 4 | --set amethyst icon= \ 5 | icon.padding_right=-1 \ 6 | icon.color=$MAGENTA \ 7 | icon.font="JetBrainsMono Nerd Font Mono:Bold:20.0" \ 8 | click_script="open -a amethyst" 9 | -------------------------------------------------------------------------------- /files/sketchybar/items/app.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | sketchybar --add item front_app left \ 4 | --set front_app script="$PLUGIN_DIR/front_app.sh" \ 5 | icon.drawing=off \ 6 | background.color=$RED \ 7 | label.color=$BLACK \ 8 | --subscribe front_app front_app_switched 9 | -------------------------------------------------------------------------------- /files/sketchybar/items/battery.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | sketchybar --add item battery right \ 4 | --set battery script="$PLUGIN_DIR/battery.sh" \ 5 | update_freq=10 \ 6 | background.color=$YELLOW \ 7 | label.color=$BLACK \ 8 | icon.color=$BLACK \ 9 | --subscribe battery system_woke 10 | -------------------------------------------------------------------------------- /files/sketchybar/items/bluetooth.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | sketchybar -m --add event bluetooth_change "com.apple.bluetooth.status" \ 4 | --add item bluetooth right \ 5 | --set bluetooth script="$PLUGIN_DIR/bluetooth.sh" \ 6 | update_freq=5 \ 7 | icon.color=$BLUE \ 8 | --subscribe bluetooth bluetooth_change 9 | -------------------------------------------------------------------------------- /files/sketchybar/items/date-time.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | sketchybar --add item clock right \ 4 | --set clock update_freq=1 \ 5 | script="$PLUGIN_DIR/clock.sh" \ 6 | background.color=$CYAN \ 7 | label.color=$BLACK \ 8 | icon.color=$BLACK 9 | -------------------------------------------------------------------------------- /files/sketchybar/items/net.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | sketchybar --add item net right \ 4 | --set net script="$PLUGIN_DIR/net.sh" \ 5 | update_freq=1 \ 6 | background.color=$GREEN \ 7 | label.color=$BLACK \ 8 | icon.color=$BLACK \ 9 | label.y_offset=1 10 | -------------------------------------------------------------------------------- /files/sketchybar/items/network.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | sketchybar --add item network right \ 4 | --set network label.padding_right=4 \ 5 | background.color=$GREEN \ 6 | label.color=$BLACK \ 7 | icon.color=$BLACK \ 8 | icon= \ 9 | label.padding_right=10 \ 10 | update_freq=1 \ 11 | script="$PLUGIN_DIR/network.sh" 12 | -------------------------------------------------------------------------------- /files/sketchybar/items/now_playing.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | sketchybar -m --add event spotify_change "com.spotify.client.PlaybackStateChanged" \ 4 | --add item spotify "${SKETCHYBAR_SPOTIFY_LOC:-center}" \ 5 | --set spotify label.color=$GREEN \ 6 | script="$PLUGIN_DIR/spotify.sh" \ 7 | click_script="open -a spotify" \ 8 | --subscribe spotify spotify_change 9 | -------------------------------------------------------------------------------- /files/sketchybar/items/settings.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | sketchybar --add item settings right \ 4 | --set settings icon= \ 5 | icon.color=$WHITE \ 6 | click_script="open -a 'system settings'" 7 | -------------------------------------------------------------------------------- /files/sketchybar/items/spaces.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | SPACE_ICONS=("1" "2" "3" "4" "5" "6" "7" "8" "9" "10") 4 | 5 | for i in "${!SPACE_ICONS[@]}" 6 | do 7 | sid=$(($i+1)) 8 | sketchybar --add space space.$sid left \ 9 | --set space.$sid associated_space=$sid \ 10 | icon=${SPACE_ICONS[i]} \ 11 | background.color=0x44ffffff \ 12 | background.corner_radius=5 \ 13 | background.height=22 \ 14 | background.drawing=off \ 15 | label.drawing=off \ 16 | icon.color=$WHITE \ 17 | script="$PLUGIN_DIR/space.sh" 18 | done 19 | 20 | sketchybar --add bracket spaces '/space\..*/' \ 21 | --set spaces background.color=$GREY 22 | -------------------------------------------------------------------------------- /files/sketchybar/plugins/battery.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | source "$HOME/.config/sketchybar/icons.sh" 4 | 5 | PERCENTAGE=$(pmset -g batt | grep -Eo "\d+%" | cut -d% -f1) 6 | CHARGING=$(pmset -g batt | grep 'AC Power') 7 | 8 | if [ $PERCENTAGE = "" ]; then 9 | exit 0 10 | fi 11 | 12 | case ${PERCENTAGE} in 13 | 9[0-9]|100) ICON="$BATTERY_100" 14 | ;; 15 | [6-8][0-9]) ICON="$BATTERY_75" 16 | ;; 17 | [3-5][0-9]) ICON="$BATTERY_50" 18 | ;; 19 | [1-2][0-9]) ICON="$BATTERY_25" 20 | ;; 21 | *) ICON="" 22 | esac 23 | 24 | if [[ $CHARGING != "" ]]; then 25 | ICON="$BATTERY_CHARGING" 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" label="${PERCENTAGE}%" 31 | -------------------------------------------------------------------------------- /files/sketchybar/plugins/bluetooth.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | STATE=$(blueutil -p) 4 | 5 | if [ $STATE = 0 ]; then 6 | sketchybar --set $NAME label="" icon= 7 | else 8 | sketchybar --set $NAME label="" icon= 9 | fi 10 | -------------------------------------------------------------------------------- /files/sketchybar/plugins/clock.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 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 '+%m/%d %H:%M')" 8 | 9 | -------------------------------------------------------------------------------- /files/sketchybar/plugins/front_app.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 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 | sketchybar --set $NAME label="$INFO" 9 | -------------------------------------------------------------------------------- /files/sketchybar/plugins/net.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | source "$HOME/.config/sketchybar/icons.sh" 4 | source "$HOME/.config/sketchybar/colors.sh" 5 | 6 | wdutil="$(sudo wdutil info)" 7 | STATUS=$(echo "$wdutil" | grep -m 1 'Power' | sed -rn 's/.*\[(.+)\].*/\1/p') 8 | LABEL=$(echo "$wdutil" | grep -E '\bSSID\s+:' | cut -d':' -f2 | xargs) # HACKY 9 | 10 | if [ "${STATUS}" = "Off" ]; then 11 | sketchybar -m --set net icon=$WIFI_OFF \ 12 | icon.color=$RED \ 13 | label.padding_right=2 14 | 15 | elif [ -z "${LABEL}" ]; then 16 | sketchybar -m --set net icon=$WIFI_DISCONNECTED \ 17 | icon.color=$RED \ 18 | label.padding_right=2 19 | else 20 | sketchybar -m --set net icon=$WIFI_CONNECTED \ 21 | icon.color=$BLACK \ 22 | label.padding_right=2 23 | fi 24 | 25 | sketchybar -m --set net label="$LABEL" 26 | -------------------------------------------------------------------------------- /files/sketchybar/plugins/network.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | source "$HOME/.config/sketchybar/icons.sh" 4 | source "$HOME/.config/sketchybar/colors.sh" 5 | 6 | airport=$(/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport -I) 7 | AIRPORT=$(echo "$airport" | awk 'NR==1 {print $2}') 8 | LABEL=$(echo "$airport" | grep -o "SSID: .*" | sed 's/^SSID: //') 9 | UPDOWN=$(ifstat -i "en0" -b 0.1 1 | tail -n1) 10 | DOWN_SPEED=$(echo $UPDOWN | awk "{ print \$1 }" | cut -f1 -d ".") 11 | UP_SPEED=$(echo $UPDOWN | awk "{ print \$2 }" | cut -f1 -d ".") 12 | DOWN_SPEED=$(($DOWN_SPEED/8)) 13 | UP_SPEED=$(($UP_SPEED/8)) 14 | SPEED="" 15 | 16 | if [ $AIRPORT = "Off" ] || [ -z "$LABEL" ]; then 17 | sketchybar -m --set network icon.drawing=off 18 | elif [ "$UP_SPEED" -gt "$DOWN_SPEED" ]; then 19 | sketchybar -m --set network icon.drawing=on icon=$UPLOAD 20 | if [ "$UP_SPEED" -gt "999" ]; then 21 | SPEED=$(echo $UP_SPEED | awk '{ printf "%.1f MB/s", $1 / 1000}') 22 | else 23 | SPEED=$(echo $UP_SPEED | awk '{ printf "%.1f KB/s", $1}') 24 | fi 25 | else 26 | sketchybar -m --set network icon.drawing=on icon=$DOWNLOAD 27 | if [ "$DOWN_SPEED" -gt "999" ]; then 28 | SPEED=$(echo $DOWN_SPEED | awk '{ printf "%.1f MB/s", $1 / 1000}') 29 | else 30 | SPEED=$(echo $DOWN_SPEED | awk '{ printf "%.1f KB/s", $1}') 31 | fi 32 | fi 33 | sketchybar -m --set network label="$SPEED" 34 | -------------------------------------------------------------------------------- /files/sketchybar/plugins/space.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 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 | sketchybar --set $NAME background.drawing=$SELECTED 8 | -------------------------------------------------------------------------------- /files/sketchybar/plugins/spotify.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | RUNNING=$(osascript -e 'if application "Spotify" is running then return 0') 4 | if [ "$RUNNING" == "" ]; then 5 | RUNNING=1 6 | fi 7 | PLAYING=1 8 | TRACK="" 9 | ALBUM="" 10 | ARTIST="" 11 | if [ "$(osascript -e 'if application "Spotify" is running then tell application "Spotify" to get player state')" == "playing" ]; then 12 | PLAYING=0 13 | TRACK=$(osascript -e 'tell application "Spotify" to get name of current track') 14 | ARTIST=$(osascript -e 'tell application "Spotify" to get artist of current track') 15 | ALBUM=$(osascript -e 'tell application "Spotify" to get album of current track') 16 | sketchybar -m --set $NAME drawing=on 17 | fi 18 | if [ $RUNNING -eq 0 ] && [ $PLAYING -eq 0 ]; then 19 | if [ "$ARTIST" == "" ]; then 20 | sketchybar -m --set $NAME label=" $TRACK - $ALBUM" 21 | else 22 | sketchybar -m --set $NAME label=" $TRACK - $ARTIST" 23 | fi 24 | else 25 | sketchybar -m --set $NAME label="" 26 | fi 27 | -------------------------------------------------------------------------------- /files/sketchybar/plugins/window_title.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | sketchybar --set $NAME label="$INFO" 4 | -------------------------------------------------------------------------------- /files/sketchybar/sketchybarrc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # This is a demo config to show some of the most important commands more easily. 4 | # This is meant to be changed and configured, as it is intentionally kept sparse. 5 | # For a more advanced configuration example see my dotfiles: 6 | # https://github.com/FelixKratz/dotfiles 7 | 8 | source "$HOME/.config/sketchybar/icons.sh" 9 | source "$HOME/.config/sketchybar/colors.sh" 10 | if [[ -f "$HOME/.custom" ]]; then 11 | source "$HOME/.custom" 12 | fi 13 | 14 | PLUGIN_DIR="$HOME/.config/sketchybar/plugins" 15 | ITEM_DIR="$HOME/.config/sketchybar/items" 16 | 17 | ##### Bar Appearance ##### 18 | # Configuring the general appearance of the bar, these are only some of the 19 | # options available. For all options see: 20 | # https://felixkratz.github.io/SketchyBar/config/bar 21 | # If you are looking for other colors, see the color picker: 22 | # https://felixkratz.github.io/SketchyBar/config/tricks#color-picker 23 | 24 | sketchybar --bar height=${SKETCHYBAR_HEIGHT:-24} \ 25 | blur_radius=50 \ 26 | position=top \ 27 | sticky=on \ 28 | padding_left=0 \ 29 | padding_right=0 \ 30 | color=$BAR_COLOR 31 | 32 | ##### Changing Defaults ##### 33 | # We now change some default values that are applied to all further items 34 | # For a full list of all available item properties see: 35 | # https://felixkratz.github.io/SketchyBar/config/items 36 | 37 | sketchybar --default updates=when_shown \ 38 | drawing=on \ 39 | icon.font="JetBrainsMono Nerd Font Mono:Bold:18.0" \ 40 | icon.color=$WHITE \ 41 | label.font="JetBrainsMono Nerd Font Mono:Bold:14.0" \ 42 | label.color=$WHITE \ 43 | label.padding_left=4 \ 44 | label.padding_right=4 \ 45 | icon.padding_left=4 \ 46 | icon.padding_right=4 47 | 48 | # Left 49 | source "$ITEM_DIR/spaces.sh" 50 | sketchybar --add item space_separator left \ 51 | --set space_separator icon= \ 52 | background.padding_left=15 \ 53 | background.padding_right=15 \ 54 | label.drawing=off \ 55 | icon.color=$RED 56 | source "$ITEM_DIR/app.sh" 57 | 58 | # Right 59 | source "$ITEM_DIR/date-time.sh" 60 | source "$ITEM_DIR/battery.sh" 61 | source "$ITEM_DIR/network.sh" 62 | source "$ITEM_DIR/net.sh" 63 | source "$ITEM_DIR/settings.sh" 64 | 65 | # Center 66 | source "$ITEM_DIR/now_playing.sh" 67 | 68 | ##### Finalizing Setup ##### 69 | # The below command is only needed at the end of the initial configuration and 70 | # should never be run in an item script. 71 | 72 | sketchybar --update 73 | 74 | echo "sketchybar configuration loaded.." 75 | -------------------------------------------------------------------------------- /files/tmux.conf: -------------------------------------------------------------------------------- 1 | # Global Options 2 | # definitely use zsh 3 | set -g default-shell /bin/zsh 4 | 5 | # vim bindings 6 | set -g mode-keys vi 7 | 8 | # arrays start at one 9 | set -g base-index 1 10 | set -g pane-base-index 1 11 | 12 | # automatically renumber windows when they are closed 13 | set -g renumber-windows on 14 | 15 | # let the mouse scroll 16 | set -g mouse on 17 | 18 | # nvim told me to 19 | set -sg escape-time 10 20 | set -g focus-events on 21 | set-option -a terminal-overrides 'alacritty:RGB' 22 | 23 | # Look and feel 24 | # --> Catppuccin (Latte) 25 | # set -ogq @thm_bg "#eff1f5" 26 | # set -ogq @thm_fg "#4c4f69" 27 | # 28 | # # Colors 29 | # set -ogq @thm_rosewater "#dc8a78" 30 | # set -ogq @thm_flamingo "#dd7878" 31 | # set -ogq @thm_rosewater "#dc8a78" 32 | # set -ogq @thm_pink "#ea76cb" 33 | # set -ogq @thm_mauve "#8839ef" 34 | # set -ogq @thm_red "#d20f39" 35 | # set -ogq @thm_maroon "#e64553" 36 | # set -ogq @thm_peach "#fe640b" 37 | # set -ogq @thm_yellow "#df8e1d" 38 | # set -ogq @thm_green "#40a02b" 39 | # set -ogq @thm_teal "#179299" 40 | # set -ogq @thm_sky "#04a5e5" 41 | # set -ogq @thm_sapphire "#209fb5" 42 | # set -ogq @thm_blue "#1e66f5" 43 | # set -ogq @thm_lavender "#7287fd" 44 | # 45 | # # Surfaces and overlays 46 | # set -ogq @thm_subtext_1 "#6c6f85" 47 | # set -ogq @thm_subtext_0 "#5c5f77" 48 | # set -ogq @thm_overlay_2 "#7c7f93" 49 | # set -ogq @thm_overlay_1 "#8c8fa1" 50 | # set -ogq @thm_overlay_0 "#9ca0b0" 51 | # set -ogq @thm_surface_2 "#acb0be" 52 | # set -ogq @thm_surface_1 "#bcc0cc" 53 | # set -ogq @thm_surface_0 "#ccd0da" 54 | # set -ogq @thm_mantle "#e6e9ef" 55 | # set -ogq @thm_crust "#dce0e8" 56 | 57 | # --> Catppuccin (Mocha) -- https://github.com/catppuccin/tmux/blob/e894efea8377958fa73adbe2954997a004a22210/themes/catppuccin_mocha_tmux.conf 58 | set -ogq @thm_bg "#1e1e2e" 59 | set -ogq @thm_fg "#cdd6f4" 60 | 61 | # Colors 62 | set -ogq @thm_rosewater "#f5e0dc" 63 | set -ogq @thm_flamingo "#f2cdcd" 64 | set -ogq @thm_rosewater "#f5e0dc" 65 | set -ogq @thm_pink "#f5c2e7" 66 | set -ogq @thm_mauve "#cba6f7" 67 | set -ogq @thm_red "#f38ba8" 68 | set -ogq @thm_maroon "#eba0ac" 69 | set -ogq @thm_peach "#fab387" 70 | set -ogq @thm_yellow "#f9e2af" 71 | set -ogq @thm_green "#a6e3a1" 72 | set -ogq @thm_teal "#94e2d5" 73 | set -ogq @thm_sky "#89dceb" 74 | set -ogq @thm_sapphire "#74c7ec" 75 | set -ogq @thm_blue "#89b4fa" 76 | set -ogq @thm_lavender "#b4befe" 77 | 78 | # Surfaces and overlays 79 | set -ogq @thm_subtext_1 "#a6adc8" 80 | set -ogq @thm_subtext_0 "#bac2de" 81 | set -ogq @thm_overlay_2 "#9399b2" 82 | set -ogq @thm_overlay_1 "#7f849c" 83 | set -ogq @thm_overlay_0 "#6c7086" 84 | set -ogq @thm_surface_2 "#585b70" 85 | set -ogq @thm_surface_1 "#45475a" 86 | set -ogq @thm_surface_0 "#313244" 87 | set -ogq @thm_mantle "#181825" 88 | set -ogq @thm_crust "#11111b" 89 | 90 | # statusbar 91 | set -g status-style 'bg=#{@thm_mantle},fg=#{@thm_fg}' 92 | set -g status-position bottom 93 | set -g status-justify left 94 | set -g status-left ' #[fg=#{@thm_mantle}#,bg=#{@thm_peach}] #S #[default] ' 95 | set -g status-left-length 20 96 | set -g status-right '#[fg=#{@thm_surface_2}]%H:%M %d-%b#[default] #[fg=#{@thm_mantle}#,bg=#{@thm_mauve}] #{pane_current_command} #[default]#{?client_prefix, #[fg=#{@thm_yellow}][Prefix]#[default],}#{?pane_in_mode, #[fg=#{@thm_red}][Vim]#[default],} ' 97 | # window options 98 | set -g window-status-separator ' ' 99 | set -g window-status-style 'fg=#{@thm_subtext_0}' 100 | set -g window-status-current-style 'fg=#{@thm_green}' 101 | set -g window-status-format '#{pane_current_command} @ #{b:pane_current_path}#[fg=#{@thm_surface_2}]#F#[default]' 102 | set -g window-status-current-format '#{pane_current_command} @ #{b:pane_current_path}#[fg=#{@thm_surface_2}]#F#[default]' 103 | 104 | # Pane layouts 105 | # "Main" pane is 2/3 screen width 106 | set -g main-pane-width '66%' 107 | set -g main-pane-height '75%' 108 | 109 | # Mappings 110 | # remap prefix from 'C-b' to 'C-' 111 | unbind C-Space 112 | unbind C-b 113 | set -g prefix C-Space 114 | bind-key C-Space send-prefix 115 | 116 | # vim navigation 117 | bind h select-pane -L 118 | bind j select-pane -D 119 | bind k select-pane -U 120 | bind l select-pane -R 121 | 122 | # vim resizing 123 | bind < resize-pane -L 5 124 | bind > resize-pane -R 5 125 | bind + resize-pane -U 5 126 | bind - resize-pane -D 5 127 | 128 | # vim visual mode mappings in copy mode 129 | bind -T copy-mode-vi v send-keys -X begin-selection 130 | bind -T copy-mode-vi C-v send-keys -X rectangle-toggle 131 | bind -T copy-mode-vi y send-keys -X copy-selection-and-cancel 132 | 133 | # layout shortcuts 134 | bind t select-layout main-vertical # main pane on left 2/3, rest stacked vertically on right 1/3 135 | bind = select-layout even-horizontal # panes evenly distributed side by side 136 | bind a select-layout main-horizontal # panes on top of each other 137 | 138 | # eXchange panes 139 | bind x swap-pane -s 1 -t 2 140 | 141 | # pictoral splits 142 | bind _ split-pane -v -c "#{pane_current_path}" 143 | bind | run-shell "~/bin/tmux-smartsplit" 144 | bind \\ split-pane -h -c "#{pane_current_path}" 145 | 146 | # move panes around 147 | bind -n S-Up move-pane -h -t ".{up-of}" 148 | bind -n S-Right move-pane -t ".{right-of}" 149 | bind -n S-Left move-pane -t ".{left-of}" 150 | bind -n S-down move-pane -h -t ".{down-of}" 151 | -------------------------------------------------------------------------------- /files/wezterm.lua: -------------------------------------------------------------------------------- 1 | local wezterm = require("wezterm") 2 | local act = wezterm.action 3 | 4 | local config = {} 5 | 6 | if wezterm.config_builder then config = wezterm.config_builder() end 7 | config.automatically_reload_config = true 8 | 9 | -- startup 10 | config.default_prog = { "/bin/zsh", "-l" } 11 | config.audible_bell = "Disabled" -- NO BELLS 12 | config.window_close_confirmation = "NeverPrompt" -- Shutdown w/o requiring confirmation 13 | 14 | -- colors 15 | local function get_appearance() 16 | local appearance = "Dark" 17 | if wezterm.gui then appearance = wezterm.gui.get_appearance() end 18 | return appearance 19 | end 20 | 21 | local function scheme_for_appearance(appearance) 22 | if appearance:find("Light") then 23 | return "Catppuccin Latte" 24 | else 25 | return "Catppuccin Mocha" 26 | end 27 | end 28 | config.color_scheme = scheme_for_appearance(get_appearance()) 29 | config.set_environment_variables = { 30 | THEME_MODE = get_appearance(), 31 | } 32 | 33 | -- look & feel 34 | local font_size = 14.0 35 | config.adjust_window_size_when_changing_font_size = false 36 | config.window_frame = { 37 | font = wezterm.font({ family = "JetBrainsMono Nerd Font Mono" }), 38 | font_size = font_size, 39 | } 40 | config.window_decorations = "RESIZE" 41 | config.font = wezterm.font("JetBrainsMono Nerd Font Mono", { weight = "Medium" }) 42 | config.font_size = font_size 43 | config.max_fps = 240 44 | config.window_padding = { 45 | left = 5, 46 | right = 5, 47 | top = 10, 48 | bottom = 10, 49 | } 50 | 51 | wezterm.on("window-resized", function(window, pane) 52 | local tab = pane:tab() 53 | if tab == nil then return end 54 | local cols = tab:get_size().cols 55 | local overrides = window:get_config_overrides() or {} 56 | local default_font_size = 14 57 | if cols >= 300 then overrides.font_size = 15 end 58 | 59 | if overrides.font_size ~= default_font_size then window:set_config_overrides({ font_size = default_font_size }) end 60 | end) 61 | 62 | -- tab bar 63 | config.tab_max_width = 36 64 | config.tab_bar_at_bottom = true 65 | config.use_fancy_tab_bar = false 66 | wezterm.on("format-tab-title", function(tab, tabs, panes, cfg, hover, max_width) 67 | local cwd = tab.active_pane.current_working_dir 68 | local process_text = tab.active_pane.foreground_process_name 69 | local is_zoomed = false 70 | for _, pane in ipairs(tab.panes) do 71 | if pane.is_zoomed then is_zoomed = true end 72 | end 73 | local label = "" 74 | 75 | if process_text == nil then process_text = "" end 76 | 77 | if cwd == nil then cwd = "" end 78 | 79 | local dir_name = tostring(cwd):match("([^/]+)$") 80 | local process = tostring(process_text):match("([^/]+)$") 81 | 82 | if process == nil or process == "zsh" then 83 | label = dir_name ~= nil and dir_name or "-*-" 84 | else 85 | label = process .. " @ " .. dir_name 86 | end 87 | 88 | if is_zoomed then label = "*" .. label end 89 | 90 | if #label > max_width - 2 then label = string.sub(label, 1, max_width - 3) .. "…" end 91 | 92 | return " " .. label .. " " 93 | end) 94 | 95 | -- mappings 96 | config.leader = { key = " ", mods = "CTRL", timeout_milliseconds = 500 } -- keep my tmux muscle memory 97 | config.keys = { 98 | { 99 | key = "r", 100 | mods = "CMD|SHIFT", 101 | action = act.ReloadConfiguration, 102 | }, 103 | { 104 | key = "l", 105 | mods = "ALT", 106 | action = act.ShowLauncherArgs({ flags = "FUZZY|LAUNCH_MENU_ITEMS|WORKSPACES|COMMANDS|TABS" }), 107 | }, 108 | { 109 | key = "l", 110 | mods = "CMD|SHIFT", 111 | action = act.ShowLauncherArgs({ flags = "FUZZY|LAUNCH_MENU_ITEMS|WORKSPACES|COMMANDS|TABS" }), 112 | }, 113 | { 114 | key = "p", 115 | mods = "CMD", 116 | action = wezterm.action.ActivateCommandPalette, 117 | }, 118 | -- "smart" split horizontally based on width 119 | { 120 | key = "|", 121 | mods = "LEADER", 122 | action = wezterm.action_callback(function(_, pane) 123 | local dimensions = pane:get_dimensions() 124 | local size = 0.5 125 | if dimensions.cols >= 300 then size = 0.33 end 126 | pane:split({ direction = "Right", size = size }) 127 | end), 128 | }, 129 | -- "normal" split horizontally 130 | { 131 | key = "\\", 132 | mods = "LEADER", 133 | action = act.SplitHorizontal({ domain = "CurrentPaneDomain" }), 134 | }, 135 | { 136 | key = "_", 137 | mods = "LEADER", 138 | action = act.SplitVertical({ domain = "CurrentPaneDomain" }), 139 | }, 140 | { 141 | key = "h", 142 | mods = "LEADER", 143 | action = act.ActivatePaneDirection("Left"), 144 | }, 145 | { 146 | key = "j", 147 | mods = "LEADER", 148 | action = act.ActivatePaneDirection("Down"), 149 | }, 150 | { 151 | key = "k", 152 | mods = "LEADER", 153 | action = act.ActivatePaneDirection("Up"), 154 | }, 155 | { 156 | key = "l", 157 | mods = "LEADER", 158 | action = act.ActivatePaneDirection("Right"), 159 | }, 160 | { 161 | key = "r", 162 | mods = "LEADER", 163 | action = act.ActivateKeyTable({ 164 | name = "resize_pane", 165 | one_shot = false, 166 | }), 167 | }, 168 | { 169 | key = "z", 170 | mods = "LEADER", 171 | action = act.TogglePaneZoomState, 172 | }, 173 | { 174 | key = "s", 175 | mods = "LEADER", 176 | action = act.ShowLauncherArgs({ flags = "WORKSPACES|FUZZY" }), 177 | }, 178 | { 179 | key = " ", 180 | mods = "LEADER", 181 | action = act.RotatePanes("Clockwise"), 182 | }, 183 | { 184 | key = "f", 185 | mods = "LEADER", 186 | action = act.PaneSelect, 187 | }, 188 | { 189 | key = "x", 190 | mods = "LEADER", 191 | action = act.PaneSelect({ mode = "SwapWithActive" }), 192 | }, 193 | { 194 | key = "t", 195 | mods = "LEADER", 196 | action = wezterm.action_callback(function(window, cur_pane) 197 | local cur_tab = window:active_tab() 198 | local panes = cur_tab:panes_with_info() 199 | 200 | local get_newest_tab = function() 201 | local tabs = window:mux_window():tabs_with_info() 202 | local max_idx = 0 203 | local newest_tab = nil 204 | for _, tab in ipairs(tabs) do 205 | if tab.index >= max_idx then 206 | max_idx = tab.index 207 | newest_tab = tab.tab 208 | end 209 | end 210 | 211 | return newest_tab 212 | end 213 | 214 | local contains = function(tbl, val) 215 | for _, entry in ipairs(tbl) do 216 | if entry == val then return true end 217 | end 218 | 219 | return false 220 | end 221 | 222 | window:perform_action(act.SpawnTab({ DomainName = "local" }), cur_pane) 223 | local new_tab = get_newest_tab() 224 | new_tab:activate() 225 | 226 | local working_new_pane = new_tab:active_pane() 227 | local seen_pane_ids = {} 228 | local last_left_col = 0 229 | local last_top_row = 0 230 | while #seen_pane_ids ~= #panes do 231 | for _, pane in ipairs(panes) do 232 | if contains(seen_pane_ids, pane.pane:pane_id()) then goto continue end 233 | local cwd = pane.pane:get_current_working_dir() 234 | 235 | -- "main" pane already exists 236 | if pane.left == 0 and pane.top == 0 then 237 | table.insert(seen_pane_ids, pane.pane:pane_id()) 238 | goto continue 239 | end 240 | 241 | -- same starting col -> split into top/bottom 242 | if pane.left == last_left_col then 243 | working_new_pane = working_new_pane:split({ cwd = cwd.path, direction = "Bottom" }) 244 | last_top_row = pane.top 245 | 246 | -- same starting row -> split into left/right 247 | elseif pane.top == last_top_row then 248 | working_new_pane = working_new_pane:split({ cwd = cwd.path, direction = "Right" }) 249 | last_left_col = pane.left 250 | end 251 | 252 | table.insert(seen_pane_ids, pane.pane:pane_id()) 253 | ::continue:: 254 | end 255 | end 256 | end), 257 | }, 258 | { key = "+", mods = "CMD", action = act.IncreaseFontSize }, 259 | { key = "-", mods = "CMD", action = act.DecreaseFontSize }, 260 | { key = ".", mods = "CMD", action = act.ResetFontSize }, 261 | { key = "u", mods = "LEADER", action = act.QuickSelect }, 262 | { 263 | key = ",", 264 | mods = "LEADER", 265 | action = act.PromptInputLine({ 266 | description = "New tab name", 267 | action = wezterm.action_callback(function(window, pane, line) 268 | if line then window:active_tab():set_title(line) end 269 | end), 270 | }), 271 | }, 272 | { 273 | key = "$", 274 | mods = "LEADER", 275 | action = act.PromptInputLine({ 276 | description = "New session name", 277 | action = wezterm.action_callback(function(window, pane, line) 278 | if line then wezterm.mux.rename_workspace(wezterm.mux.get_active_workspace(), line) end 279 | end), 280 | }), 281 | }, 282 | } 283 | 284 | config.key_tables = { 285 | resize_pane = { 286 | { key = "LeftArrow", action = act.AdjustPaneSize({ "Left", 1 }) }, 287 | { key = "RightArrow", action = act.AdjustPaneSize({ "Right", 1 }) }, 288 | { key = "UpArrow", action = act.AdjustPaneSize({ "Up", 1 }) }, 289 | { key = "DownArrow", action = act.AdjustPaneSize({ "Down", 1 }) }, 290 | -- Cancel the mode by pressing escape 291 | { key = "Escape", action = "PopKeyTable" }, 292 | }, 293 | } 294 | 295 | -- better hyperlink detection 296 | local link_rules = wezterm.default_hyperlink_rules() 297 | table.insert(link_rules, { 298 | regex = [[\b([A-Z]{2,9}?-\d+?)\b]], 299 | format = "https://jira.kdc.capitalone.com/browse/$1", 300 | }) 301 | config.hyperlink_rules = link_rules 302 | 303 | return config 304 | -------------------------------------------------------------------------------- /files/zshenv: -------------------------------------------------------------------------------- 1 | autoload -U +X compinit && compinit 2 | 3 | source ~/.fzf.custom 4 | source ~/.functions 5 | -------------------------------------------------------------------------------- /files/zshrc: -------------------------------------------------------------------------------- 1 | # If you come from bash you might have to change your $PATH. 2 | export PATH=$HOME/bin:$HOME/.local/bin:/usr/local/bin:$PATH 3 | 4 | # Path to your oh-my-zsh installation. 5 | export ZSH=$HOME/.oh-my-zsh 6 | 7 | # Set name of the theme to load --- if set to "random", it will 8 | # load a random theme each time oh-my-zsh is loaded, in which case, 9 | # to know which specific one was loaded, run: echo $RANDOM_THEME 10 | # See https://github.com/robbyrussell/oh-my-zsh/wiki/Themes 11 | ZSH_THEME="quarter-life" 12 | # 13 | # Set list of themes to pick from when loading at random 14 | # Setting this variable when ZSH_THEME=random will cause zsh to load 15 | # a theme from this variable instead of looking in ~/.oh-my-zsh/themes/ 16 | # If set to an empty array, this variable will have no effect. 17 | # ZSH_THEME_RANDOM_CANDIDATES=( "robbyrussell" "agnoster" ) 18 | 19 | # Uncomment the following line to use case-sensitive completion. 20 | # CASE_SENSITIVE="true" 21 | 22 | # Uncomment the following line to use hyphen-insensitive completion. 23 | # Case-sensitive completion must be off. _ and - will be interchangeable. 24 | HYPHEN_INSENSITIVE="true" 25 | 26 | # Uncomment the following line to disable bi-weekly auto-update checks. 27 | # DISABLE_AUTO_UPDATE="true" 28 | 29 | # Uncomment the following line to automatically update without prompting. 30 | # DISABLE_UPDATE_PROMPT="true" 31 | # Uncomment the following line to change how often to auto-update (in days). 32 | # export UPDATE_ZSH_DAYS=13 33 | 34 | # Uncomment the following line if pasting URLs and other text is messed up. 35 | # DISABLE_MAGIC_FUNCTIONS=true 36 | 37 | # Uncomment the following line to disable colors in ls. 38 | # DISABLE_LS_COLORS="true" 39 | 40 | # Uncomment the following line to disable auto-setting terminal title. 41 | DISABLE_AUTO_TITLE="true" 42 | 43 | # Uncomment the following line to enable command auto-correction. 44 | ENABLE_CORRECTION="false" 45 | unsetopt correct_all 46 | 47 | # Uncomment the following line to display red dots whilst waiting for completion. 48 | COMPLETION_WAITING_DOTS="true" 49 | 50 | # Uncomment the following line if you want to disable marking untracked files 51 | # under VCS as dirty. This makes repository status check for large repositories 52 | # much, much faster. 53 | DISABLE_UNTRACKED_FILES_DIRTY="true" 54 | 55 | # Uncomment the following line if you want to change the command execution time 56 | # stamp shown in the history command output. 57 | # You can set one of the optional three formats: 58 | # "mm/dd/yyyy"|"dd.mm.yyyy"|"yyyy-mm-dd" 59 | # or set a custom format using the strftime function format specifications, 60 | # see 'man strftime' for details. 61 | # HIST_STAMPS="mm/dd/yyyy" 62 | 63 | # Would you like to use another custom folder than $ZSH/custom? 64 | # ZSH_CUSTOM=/path/to/new-custom-folder 65 | 66 | # Zsh setup 67 | zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}' 'r:|=*' 'l:|=* r:|=*' 68 | autoload -U add-zsh-hook # hooks 69 | 70 | # Preferred editor for local and remote sessions 71 | if [[ -n $SSH_CONNECTION ]]; then 72 | export EDITOR='vim' 73 | else 74 | export EDITOR='nvim' 75 | fi 76 | 77 | # Brew 78 | if [ -d /opt/homebrew ]; then 79 | eval "$(/opt/homebrew/bin/brew shellenv)" 80 | # Autocomplete from installed apps 81 | FPATH="$(brew --prefix)/share/zsh/site-functions:$FPATH" 82 | # Let gcc play with brew 83 | export LDFLAGS="-L$(brew --prefix)/opt/zlib/lib -L$(brew --prefix)/opt/bzip2/lib -L$(brew --prefix openssl)/lib" 84 | export CPPFLAGS="-I$(brew --prefix)/opt/zlib/include -I$(brew --prefix)/opt/bzip2/include -I$(brew --prefix openssl)/include" 85 | export CFLAGS="-I$(brew --prefix openssl)/include \ 86 | -I$(brew --prefix bzip2)/include \ 87 | -I$(brew --prefix readline)/include \ 88 | -I$(xcrun --show-sdk-path)/usr/include" 89 | fi 90 | # End Brew 91 | 92 | # use `bat` for manpager 93 | if type bat &> /dev/null; then 94 | export BAT_THEME="Catppuccin Mocha" 95 | [[ "$THEME_MODE" == "Light" ]] && export BAT_THEME="Catppuccin Latte" 96 | fi 97 | 98 | [ -f ~/.fzf.custom ] && source ~/.fzf.custom 99 | 100 | # Python 101 | [ -d "$HOME/.pyenv" ] && eval "$(pyenv init -)" 102 | [ -f "$HOME/.rye/env" ] && source "$HOME/.rye/env" 103 | 104 | # NVM 105 | export NVM_DIR="$HOME/.nvm" 106 | [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm 107 | [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion 108 | if [[ -d "$NVM_DIR" ]]; then 109 | nvm_default="$(nvm which default)" 110 | export DEFAULT_NODE_VERSION="$("$nvm_default" --version)" 111 | # Automatically use nvm version specified in .nvmrc (if any) 112 | # Intentionally not very flexible to avoid calling nvm every time we change directory 113 | function load-nvmrc { 114 | local nvmrc_path=".nvmrc" 115 | 116 | if [ -f "$nvmrc_path" ]; then 117 | local nvmrc_node_version=$(nvm version "$(cat "${nvmrc_path}")") 118 | 119 | if [ "$nvmrc_node_version" = "N/A" ]; then 120 | nvm install 121 | elif [ "$nvmrc_node_version" != "$(nvm version)" ]; then 122 | nvm use 123 | fi 124 | fi 125 | } 126 | 127 | # Load nvmrc if I'm switching branches 128 | branching=false 129 | function nvm-git-branch { 130 | local cmd="$1" 131 | if [[ $cmd && $cmd =~ "^git (checkout|branch)" && ! $braching ]]; then 132 | branching=true 133 | elif [[ $branching ]]; then 134 | load-nvmrc 135 | branching=false 136 | fi 137 | } 138 | 139 | add-zsh-hook preexec nvm-git-branch 140 | add-zsh-hook precmd nvm-git-branch 141 | add-zsh-hook chpwd load-nvmrc 142 | fi 143 | # NVM end 144 | 145 | # OMZ config 146 | plugins=( 147 | git 148 | zsh-interactive-cd 149 | zsh-vi-mode 150 | ) 151 | # must come *after* FPATH is set by brew to make sure tab complete works 152 | # automatically runs `compinit` 153 | source "$ZSH/oh-my-zsh.sh" 154 | 155 | load_syntax_highlights() { 156 | # https://github.com/catppuccin/zsh-syntax-highlighting 157 | syntax_highlights_theme="$HOME/.zsh/catppuccin_mocha-zsh-syntax-highlighting.zsh" 158 | [[ "$THEME_MODE" == "Light" ]] && syntax_highlights_theme="$HOME/.zsh/catppuccin_latte-zsh-syntax-highlighting.zsh" 159 | [ -f "$syntax_highlights_theme" ] && source "$syntax_highlights_theme" 160 | # syntax highlights, must run after compinit - https://github.com/zsh-users/zsh-syntax-highlighting?tab=readme-ov-file#faq 161 | syntax_highlights="$(brew --prefix)/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh" 162 | [ -f "$syntax_highlights" ] && source "$syntax_highlights" 163 | } 164 | load_syntax_highlights 165 | 166 | # vi mode 167 | # NOTE: edit command in $EDITOR happens from zsh-vi-mode with `vv` 168 | 169 | # make sure fzf keybindings still apply 170 | zvm_after_init() { 171 | eval "$(fzf --zsh)" 172 | [ -f "$HOME/.functions" ] && source "$HOME/.functions" 173 | load_syntax_highlights 174 | } 175 | # Do vim surround on the command line 176 | export ZVM_VI_SURROUND_BINDKEY='classic' 177 | # OMZ end 178 | 179 | # Other configs 180 | [ -s "$HOME/.aliases" ] && source "$HOME/.aliases" 181 | [ -s "$HOME/.functions" ] && source "$HOME/.functions" 182 | # End other configs 183 | 184 | # PATH 185 | # Lua ls 186 | export PATH="$PATH:$HOME/lua-language-server/bin" 187 | 188 | # rust 189 | export PATH="$HOME/.cargo/bin:$PATH" 190 | 191 | # pnpm 192 | export PNPM_HOME="$HOME/Library/pnpm" 193 | export PATH="$PNPM_HOME:$PATH" 194 | # pnpm end 195 | 196 | # wez 197 | export PATH="$PATH:/Applications/WezTerm.app/Contents/MacOS" 198 | # alacritty 199 | export PATH="$PATH:/Applications/Alacritty.app/Contents/MacOS" 200 | 201 | # go 202 | if command -v go > /dev/null 2>&1; then 203 | export PATH="$PATH:$(go env GOROOT)/bin" 204 | export PATH="$PATH:$(go env GOPATH)/bin" 205 | fi 206 | 207 | # flutter 208 | export PATH="$HOME/devel/flutter/bin:$PATH" 209 | # end PATH 210 | 211 | # Machine-specific configs 212 | [ -f "$HOME/.custom" ] && . "$HOME/.custom" 213 | -------------------------------------------------------------------------------- /setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export CONFIG_HOME=${XDG_CONFIG_HOME:-$HOME/.config} 4 | if [[ ! -d "$CONFIG_HOME" ]]; then 5 | mkdir -p "$CONFIG_HOME" 6 | fi 7 | export NVIM_HOME=$CONFIG_HOME/nvim 8 | export DF_HOME=$HOME/dotfiles 9 | 10 | HAS_PYENV="$(command -v pyenv)" 11 | HAS_BREW="$(command -v brew)" 12 | HAS_NPM="$(command -v npm)" 13 | HAS_NVIM="$(command -v nvim)" 14 | 15 | function runcmd { 16 | echo "$@" 17 | "$@" 18 | } 19 | 20 | function replace_file { 21 | local old_file=$1 22 | local new_file=$2 23 | if [[ -e "${old_file}" ]]; then 24 | if [[ -L "${old_file}" ]]; then 25 | runcmd unlink "${old_file}" 26 | else 27 | runcmd mv "${old_file}" "${old_file}.backup" 28 | fi 29 | fi 30 | 31 | if [[ -n "${new_file}" && -n "${old_file}" ]]; then 32 | ln -s "${new_file}" "${old_file}" 33 | fi 34 | } 35 | 36 | function replace_dir { 37 | local old_dir=$1 38 | local new_dir=$2 39 | if [[ -d "${old_dir}" ]]; then 40 | # Symlink, just remove it 41 | if [[ -L "${old_dir}" ]]; then 42 | runcmd unlink "${old_dir}" 43 | else 44 | runcmd mv "${old_dir}" "${old_dir} backup" 45 | fi 46 | fi 47 | 48 | if [[ -n "${new_dir}" && -n "${old_dir}" ]]; then 49 | ln -s "${new_dir}" "${old_dir}" 50 | fi 51 | } 52 | 53 | function install_npm { 54 | if [[ -d "$HOME/.nvm" ]]; then 55 | echo "found nvm installation $(nvm --verison)" 56 | else 57 | echo "installing nvm" 58 | curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash 59 | export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")" 60 | [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm 61 | fi 62 | 63 | if [[ -z "$(command -v node)" ]]; then 64 | echo "installing node" 65 | runcmd nvm install --latest-npm 66 | fi 67 | } 68 | 69 | function install_brew { 70 | if [[ -n "${HAS_BREW}" ]]; then 71 | echo "Existing brew installation found at ${HAS_BREW}" 72 | return 73 | fi 74 | # no brew, install it 75 | echo "No brew installation found, installing..." 76 | runcmd /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" 77 | eval "$(/opt/homebrew/bin/brew shellenv)" 78 | runcmd brew update 79 | } 80 | 81 | function install_sketchybar { 82 | runcmd brew tap FelixKratz/formulae 83 | runcmd brew install sketchybar 84 | 85 | replace_dir "$CONFIG_HOME/sketchybar" "$DF_HOME/files/sketchybar" 86 | runcmd brew services start sketchybar 87 | } 88 | 89 | function install_packages { 90 | if [[ -z "${HAS_BREW}" ]]; then 91 | echo "No brew installation found, exiting" 92 | exit 1 93 | fi 94 | 95 | echo "" 96 | echo "Installing from brew..." 97 | local brew_packages=( 'gcc' 'fzf' 'bat' 'ripgrep' 'eza' 'pyenv' 'yarn' 'neovim' 'xz' 'sqlite' 'unixodbc' 'tmux' 'ninja' 'zsh' 'git-delta' 'stylua' 'git-absorb' 'lua-language-server' 'efm-langserver' 'shellcheck' 'gh' ) 98 | local brew_installed 99 | brew_installed="$(brew list)" 100 | for pkg in "${brew_packages[@]}"; do 101 | if [[ "$brew_installed" == *"$pkg"* ]]; then 102 | echo "$pkg already installed, skipping" 103 | else 104 | runcmd brew install "$pkg" 105 | fi 106 | done 107 | 108 | # extra setup for some pacakges 109 | # fzf 110 | if [[ -f "$(brew --prefix)/opt/fzf/install" ]]; then 111 | "$(brew --prefix)"/opt/fzf/install --no-update-rc 112 | fi 113 | if [[ -n "$(command -v pyenv)" ]]; then 114 | eval "$(pyenv init -)" 115 | fi 116 | 117 | if [[ -z "${HAS_NPM}" ]]; then 118 | echo "No npm installation found, exiting" 119 | exit 1 120 | fi 121 | echo "Installing from npm..." 122 | local npm_packages=( 'bash-language-server' 'pyright' 'typescript-language-server' 'vscode-langservers-extracted' 'yaml-language-server' 'eslint_d' '@fsouza/prettierd' '@vue/language-server' 'typescript' ) 123 | local npm_installed 124 | npm_installed=$(npm -g list) 125 | for pkg in "${npm_packages[@]}"; do 126 | if [[ "$npm_installed" == *"$pkg"* ]]; then 127 | echo "$pkg already installed, skipping" 128 | else 129 | runcmd npm i -g "$pkg" 130 | fi 131 | done 132 | 133 | } 134 | 135 | # Catppuccin 136 | function install_colorscheme { 137 | # zsh syntax highlighting 138 | mkdir -p "$HOME/.zsh" 139 | curl -o- https://raw.githubusercontent.com/catppuccin/zsh-syntax-highlighting/main/themes/catppuccin_frappe-zsh-syntax-highlighting.zsh \ 140 | > "$HOME/.zsh/catppuccin_frappe-zsh-syntax-highlighting.zsh" 141 | curl -o- https://raw.githubusercontent.com/catppuccin/zsh-syntax-highlighting/main/themes/catppuccin_latte-zsh-syntax-highlighting.zsh \ 142 | > "$HOME/.zsh/catppuccin_latte-zsh-syntax-highlighting.zsh" 143 | curl -o- https://raw.githubusercontent.com/catppuccin/zsh-syntax-highlighting/main/themes/catppuccin_mocha-zsh-syntax-highlighting.zsh \ 144 | > "$HOME/.zsh/catppuccin_mocha-zsh-syntax-highlighting.zsh" 145 | curl -o- https://raw.githubusercontent.com/catppuccin/zsh-syntax-highlighting/main/themes/catppuccin_macchiato-zsh-syntax-highlighting.zsh \ 146 | > "$HOME/.zsh/catppuccin_macchiato-zsh-syntax-highlighting.zsh" 147 | 148 | if command -v bat; then 149 | # bat themes 150 | mkdir -p "$(bat --config-dir)/themes" 151 | curl -o- https://raw.githubusercontent.com/enkia/enki-theme/master/scheme/Enki-Tokyo-Night.tmTheme \ 152 | > "$(bat --config-dir)/themes/tokyonight_moon.tmTheme" 153 | curl -o- https://raw.githubusercontent.com/catppuccin/bat/main/themes/Catppuccin%20Mocha.tmTheme \ 154 | > "$(bat --config-dir)/themes/Catppuccin Mocha.tmTheme" 155 | curl -o- https://raw.githubusercontent.com/catppuccin/bat/main/themes/Catppuccin%20Frappe.tmTheme \ 156 | > "$(bat --config-dir)/themes/Catppuccin Frappe.tmTheme" 157 | curl -o- https://raw.githubusercontent.com/catppuccin/bat/main/themes/Catppuccin%20Latte.tmTheme \ 158 | > "$(bat --config-dir)/themes/Catppuccin Latte.tmTheme" 159 | curl -o- https://raw.githubusercontent.com/catppuccin/bat/main/themes/Catppuccin%20Macchiato.tmTheme \ 160 | > "$(bat --config-dir)/themes/Catppuccin Macchiato.tmTheme" 161 | runcmd bat cache --build 162 | fi 163 | 164 | if command -v delta; then 165 | # delta themes 166 | curl -o- https://raw.githubusercontent.com/catppuccin/delta/refs/heads/main/catppuccin.gitconfig \ 167 | > "${HOME}/.catppuccin-delta.gitconfig" 168 | fi 169 | } 170 | 171 | function install_python { 172 | if [[ -z "${HAS_PYENV}" ]]; then 173 | echo "No pyenv installation found, exiting" 174 | exit 1 175 | fi 176 | 177 | echo "" 178 | echo "Installing python" 179 | runcmd git clone https://github.com/momo-lab/xxenv-latest.git "$(pyenv root)"/plugins/xxenv-latest 180 | runcmd pyenv latest install --skip-existing 181 | if [[ "$PYENV_VERSION" != "" ]]; then 182 | # Also install defined version 183 | runcmd pyenv install --skip-existing "$PYENV_VERSION" 184 | fi 185 | } 186 | 187 | 188 | function setup_nvim { 189 | if [[ -z "${HAS_NVIM}" ]]; then 190 | echo "No neovim installation found, installing from brew" 191 | brew install neovim > /dev/null 2>&1 || echo "Unable to install neovim, exiting" && exit 1 192 | fi 193 | mkdir -p "$NVIM_HOME" 194 | replace_dir "$NVIM_HOME" "$DF_HOME/files/nvim" 195 | # Set up neovim python virtualenv 196 | if [[ ! -d "$HOME/py3nvim" && "$(python --version)" != 2* ]]; then 197 | runcmd python -m venv "$HOME/py3nvim" 198 | runcmd source "$HOME/py3nvim/bin/activate" 199 | runcmd pip install --upgrade pip 200 | runcmd pip install pynvim 201 | runcmd deactivate 202 | fi 203 | if [[ -n "${HAS_NPM}" && "$(npm ls -g)" != *neovim* ]]; then 204 | runcmd npm i -g neovim 205 | fi 206 | } 207 | 208 | function setup_tmux { 209 | replace_file "$HOME/.tmux.conf" "$DF_HOME/files/tmux.conf" 210 | } 211 | 212 | function setup_zsh { 213 | if [[ ! $(command -v zsh) ]]; then 214 | echo "Command zsh not found, install it first" 215 | exit 1 216 | fi 217 | # get oh-my-zsh first 218 | if [ ! -d "$HOME/.oh-my-zsh" ]; then 219 | echo "Installing oh-my-zsh" 220 | runcmd sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended 221 | fi 222 | 223 | DEFAULT_ZSH_CUSTOM="$HOME/.oh-my-zsh/custom" 224 | mkdir -p "${DEFAULT_ZSH_CUSTOM}/plugins" 225 | mkdir -p "${DEFAULT_ZSH_CUSTOM}/themes" 226 | 227 | # get plugins 228 | # vi mode 229 | local vi_mode="${ZSH_CUSTOM:-$DEFAULT_ZSH_CUSTOM}/plugins/zsh-vi-mode" 230 | if [[ ! -d "${vi_mode}" ]]; then 231 | runcmd git clone https://github.com/jeffreytse/zsh-vi-mode "${vi_mode}" 232 | fi 233 | 234 | # syntax highlighting 235 | local syntax_highlighting="${ZSH_CUSTOM:-$DEFAULT_ZSH_CUSTOM}/plugins/zsh-vi-mode" 236 | if [[ ! -d "${syntax_highlighting}" ]]; then 237 | runcmd git clone https://github.com/zsh-users/zsh-syntax-highlighting.git "${syntax_highlighting}" 238 | fi 239 | 240 | # main 241 | replace_file "$HOME/.zshrc" "$DF_HOME/files/zshrc" 242 | replace_file "$HOME/.aliases" "$DF_HOME/files/aliases" 243 | replace_file "$HOME/.functions" "$DF_HOME/files/functions" 244 | # custom theme 245 | replace_file "${ZSH_CUSTOM:-$DEFAULT_ZSH_CUSTOM}/themes/quarter-life.zsh-theme" "$DF_HOME/files/quarter-life.zsh-theme" 246 | 247 | } 248 | 249 | function install_scripts { 250 | # link files 1 by 1 to avoid overwriting any other custom stuff in there 251 | local dir="$HOME/bin" 252 | mkdir -p "$dir" 253 | local files 254 | files=$(ls "$DF_HOME/files/bin/") 255 | for file in "${files[@]}"; do 256 | replace_file "$HOME/bin/$file" "$DF_HOME/files/bin/$file" 257 | done 258 | } 259 | 260 | function setup_kitty { 261 | replace_dir "$CONFIG_HOME/kitty" "$DF_HOME/files/kitty" 262 | } 263 | 264 | function setup_alacritty { 265 | replace_dir "$CONFIG_HOME/alacritty" "$DF_HOME/files/alacritty" 266 | } 267 | 268 | function setup_wez { 269 | # Download & compile wezterm terminfo 270 | local tempfile 271 | tempfile=$(mktemp) \ 272 | && curl -o "$tempfile" https://raw.githubusercontent.com/wez/wezterm/main/termwiz/data/wezterm.terminfo \ 273 | && tic -x -o ~/.terminfo "$tempfile" \ 274 | && rm "$tempfile" 275 | 276 | replace_file "$HOME/.wezterm.lua" "$DF_HOME/files/wezterm.lua" 277 | } 278 | 279 | function setup_dev { 280 | # first install package managers 281 | install_brew 282 | install_npm 283 | 284 | # install packages 285 | install_packages 286 | install_colorscheme 287 | 288 | # install tools 289 | install_python 290 | setup_tmux 291 | setup_nvim 292 | install_scripts 293 | 294 | # shell 295 | setup_zsh 296 | 297 | # terminal 298 | setup_wez 299 | 300 | runcmd source "$HOME/.zshrc" 301 | } 302 | 303 | function usage { 304 | echo "USAGE: source $0 [dev, packages, sketchybar, wezterm, kitty, alacritty, colors]" 305 | } 306 | 307 | 308 | for conf in "$@"; do 309 | case "$conf" in 310 | "dev") 311 | setup_dev 312 | ;; 313 | "packages") 314 | install_packages 315 | ;; 316 | "sketchybar") 317 | install_sketchybar 318 | ;; 319 | "wezterm") 320 | setup_wez 321 | ;; 322 | "kitty") 323 | setup_kitty 324 | ;; 325 | "alacritty") 326 | setup_alacritty 327 | ;; 328 | "colors") 329 | install_colorscheme 330 | ;; 331 | "*") 332 | usage 333 | ;; 334 | esac 335 | done 336 | echo "Done!" 337 | exit 0 338 | --------------------------------------------------------------------------------