vim9script set nocompatible set termguicolors set encoding=utf-8 scriptencoding utf-8 # Plugins plug#begin() Plug 'vimpostor/vim-lumen' Plug 'tpope/vim-commentary' Plug 'tpope/vim-eunuch' Plug 'tpope/vim-fugitive' Plug 'tpope/vim-repeat' Plug 'tpope/vim-surround' Plug 'arthurxavierx/vim-caser' Plug '/opt/homebrew/opt/fzf' Plug 'junegunn/fzf.vim' Plug 'vim-pandoc/vim-pandoc-syntax' Plug 'quarto-dev/quarto-vim' Plug 'HerringtonDarkholme/yats.vim' Plug 'elixir-editors/vim-elixir' Plug 'bullets-vim/bullets.vim' Plug 'maxbucknell/vim-mbnotes' Plug 'SirVer/ultisnips' Plug 'dense-analysis/ale' Plug 'prabirshrestha/asyncomplete.vim' plug#end() # Language config g:pandoc#syntax#conceal#use = 0 g:r_indent_align_args = 0 # Syntax and colors and things filetype plugin indent on syntax on # Disable Swapping set nobackup nowritebackup noswapfile # Statusline set laststatus=2 set statusline=—[%n\:\ %t]—%=—%y—[%l/%L,\ %c]—%m%r— set fillchars=stl:—,eob:\ set fillchars+=stlnc:— set fillchars+=vert:\| # Hide intro message set shortmess=I set nowrap # Relative numbering with absolute anchor set number relativenumber set signcolumn=number set cursorline cursorlineopt=both # Keep buffers open in memory when not visible set hidden # Keep buffers up to date with external changes set autoread set backspace=indent,eol,start # Show invisibles set list set listchars=tab:‣\ ,trail:·,extends:◣,precedes:◢,nbsp:○ # Disable folding set foldmethod=manual set nofoldenable # Search fixes set ignorecase smartcase incsearch hlsearch gdefault # Show incomplete command-based changes in realtime set showcmd # And breathe... set scrolloff=5 # I think left to write, top to bottom set splitright splitbelow # Basic whitespace set nojoinspaces set expandtab set shiftwidth=4 set softtabstop=4 set textwidth=79 set autoindent # Show me when my lines are too long # # I wish to limit my lines to 80 characters long. However, Vim creates # the n+1th character when you have n characters in a line. Hence, when # my line is 80 characters long, I see the red line. So, this is set to # 82, meaning that I only see the line when my lines actually are too long. matchadd('ColorColumn', '\%82v', 100) # Mappings etc g:mapleader = "\" g:maplocalleader = "," # Use jk to escape back to normal inoremap jk inoremap # Hide search highlights nnoremap :noh # Hide warning about exiting vim when I type ctrl-c to edit windows nnoremap # Switch between recent buffers nnoremap # Fix shift-semicolon to colon noremap ; : # I should map these to something useful inoremap inoremap inoremap inoremap noremap noremap # Update almost a decade later: I mapped these to something useful! noremap :cprev noremap :cnext # Case control nnoremap u viwU nnoremap l viwu # Moving lines around nnoremap - ddp== nnoremap _ :-1dpk== # Quick access vimrc nnoremap ev :tabedit $MYVIMRC nnoremap es :so $MYVIMRC # Pane management nnoremap nnoremap nnoremap nnoremap inoremap inoremap inoremap inoremap # I'm getting back into visual mode # And I'm cycling the modes nnoremap v V nnoremap V nnoremap v # FZF nnoremap o :Files nnoremap b :Buffers nnoremap f :Rg nnoremap g :RG g:fzf_vim = {} g:fzf_vim.preview_window = [] def BuildQuickfixList(lines: list) setqflist(map(copy(a:lines), '{ "filename": v:val, "lnum": 1 }')) copen cc enddef g:fzf_action = { \ 'ctrl-q': function('BuildQuickfixList'), \ 'ctrl-t': 'tab split', \ 'ctrl-x': 'split', \ 'ctrl-v': 'vsplit' } augroup FZF autocmd! autocmd FileType fzf tmap jk augroup END # Focus mode g:is_zoomed = false def Zoom() if g:is_zoomed g:is_zoomed = false wincmd = else g:is_zoomed = true wincmd _ wincmd | endif enddef # Git blame nnoremap a Zoom():Git blame nnoremap z Zoom() # Make directories in a filename if they don't exist. def EnsureDirExists() var required_dir = expand("%:h") if !isdirectory(required_dir) try mkdir(required_dir, 'p') catch echom "Could not create directory" exit endtry endif enddef augroup AutoMkdir autocmd! autocmd BufNewFile * EnsureDirExists() augroup END # Use tab for UltiSnips expansion, navigation, and g:ulti_expand_or_jump_res = 0 g:UltiSnipsExpandOrJumpTrigger = '' g:UltiSnipsSnippetStorageDirectoryForUltiSnipsEdit = $DOTFILES_PATH .. "/vim/vim.xdg.symlink/Ultisnips" def g:Ultisnips_expand(default: string): string UltiSnips#ExpandSnippetOrJump() if g:ulti_expand_or_jump_res == 0 return default else return "" endif enddef # inoremap Ulti_ExpandOrJump_and_getRes("\") # Notes config g:mbnotes_dir = $HOME .. "/Dropbox (Maestral)/Notes" g:mbnotes_out_dir = g:mbnotes_dir .. "/_output" g:mbnotes_open_daily_on_startup = true g:mbnotes_renderer_show = true g:mbnotes_renderer_close_on_end = true nnoremap t :MBNotesDaily nnoremap n :MBNotes nnoremap :MBNotesNew nnoremap :MBNotesNewSplit nnoremap :vertical MBNotesNewSplit g:markdown_fenced_languages = ['r', 'elixir', 'python', 'html', 'rust'] g:pandoc#syntax#codeblocks#embeds#langs = ['r', 'elixir', 'python', 'html', 'rust'] # Enable bullets.vim in Quarto files g:bullets_enabled_file_types = ['markdown', 'text', 'gitcommit', 'quarto', 'mbnotes', 'mbnotes.quarto'] # Disable the bullet changing on indents (for now) g:bullets_outline_levels = ['num', 'std-'] def EditCodeBlock() var b = bufnr("%") var name = b .. ".codeblock" # We only create one code block buffer per buffer. So if it already # exists, we will empty it out. If it doesn't already exist, we # create it. # # If it exists and has unsaved changes, we exit and warn. var code_buffer = bufnr(name, 1) if getbufvar(code_buffer, "&modified") echom "Unsaved changes in existing code block for this file." return endif # Store current cursor position for state restoration later. var p = getpos(".") # Set bottom mark for code block execute "silent normal! /^```\rmb" # Set top mark for code block execute "silent normal! ?^```\rmt" # Yank contents to source register execute "silent normal! j\"cy`b" # Yank filetype to type register, and reset position to top execute "silent normal! `t3l\"fy$`t" # Find offset position of cursor so the new buffer is in the # correct place var line = p[1] var col = p[2] var s = getpos("'t") var start_line = s[1] line = line - start_line # If code block buffer is visible, go there. If it is not visible, # then we should show it below. var window = bufwinnr(code_buffer) if window == -1 execute "below sbuffer " .. code_buffer else execute ":" .. window .. "windo :" execute "buffer " .. code_buffer endif set buftype=acwrite # Clear buffer and fill with new code silent :%d " silent :0put c normal! G"_dd # Position cursor correctly, and mark setpos(".", [0, line, col, 0]) # Link back to the original buffer for saving b:original_buffer = b # Set file type, if it is correctly annotated if @f != '`' @f = substitute(@f, "[\{\}]", "", "g") execute 'setf=' .. @f endif set nomodified enddef command -nargs=0 EditCodeBlock EditCodeBlock() def g:SaveCodeBlock() var b = bufnr("%") silent :%yank c normal! mc silent execute "buffer " .. b:original_buffer silent execute "normal! `tjd`b`t\"cp" silent execute "buffer " .. b set nomodified normal! `c echom "Code block updated" enddef augroup CodeBlocks autocmd! autocmd BufWriteCmd *.codeblock g:SaveCodeBlock() augroup END augroup Notes autocmd! autocmd FileType mbnotes imap =g:Ultisnips_expand("\") autocmd FileType mbnotes imap autocmd FileType mbnotes onoremap cb :execute "normal! /^```\rk$ms?^```\rj:noh\rv`s" autocmd FileType mbnotes nnoremap ec :EditCodeBlock autocmd FileType mbnotes inoremap :EditCodeBlock augroup END nnoremap x :silent keepp s/^- \[ \]/- [o]/e:silent keepp s/^- \[x\]/- [ ]/e:silent keepp s/^- \[o\]/- [x]/e augroup StartUp autocmd! autocmd VimResized * wincmd = augroup END # LSP and other completion g:ale_elixir_elixir_ls_release = '/opt/homebrew/opt/elixir-ls/libexec' g:ale_fix_on_save = 1 g:ale_fixers = { \ 'css': ['prettier'], \ 'elixir': ['mix_format'], \ 'html': ['prettier'], \ 'javascript': ['prettier'], \ 'javascriptreact': ['prettier'], \ 'md': ['prettier'], \ 'typescript': ['prettier'], \ 'typescriptreact': ['prettier'], \ 'yaml': ['prettier'], \ } g:ale_linters = { \ 'elixir': ['elixir-ls'], \ 'javascript': ['eslint'], \ } nnoremap za :ALEFirst nnoremap zn :ALENextWrap nnoremap zN :ALEPreviousWrap nnoremap d :ALEGoToDefinition nnoremap de :ALEGoToDefinition nnoremap dx :ALEGoToDefinition -split nnoremap dv :ALEGoToDefinition -vsplit nnoremap dt :ALEGoToDefinition -tab # au User asyncomplete_setup call asyncomplete#register_source(asyncomplete#sources#ale#get_source_options({ # \ 'priority': 10, " Provide your own overrides here # \ })) inoremap pumvisible() ? asyncomplete#close_popup() : "\" augroup Completion autocmd! autocmd User asyncomplete_setup { asyncomplete#register_source( asyncomplete#sources#mbnotes#get_source_options({ 'priority': 9 }) ) asyncomplete#register_source( asyncomplete#sources#ale#get_source_options({ 'priority': 10 }) ) asyncomplete#register_source( asyncomplete#sources#ultisnips#get_source_options({ 'priority': 11 }) ) } augroup END # File Running def PreviewQuarto() ClosePreview() echom 'Starting preview job' b:preview_job = job_start([ 'quarto', 'preview', expand('%') ]) enddef def ClosePreview() if exists("b:preview_job") echo 'Killing existing job...' job_stop(b:preview_job) endif enddef nnoremap r :echo 'No preview configured' nmap r augroup Previews autocmd! autocmd Filetype quarto nnoremap r PreviewQuarto() augroup END augroup TextFormatting autocmd! autocmd FileType make,go setl noet sw=8 sts=8 ts=8 autocmd FileType r,elixir setl et sw=2 sts=2 ts=2 augroup END # Show syntax highlighting groups for word under cursor # # This is useful for finding rogue elements I forgot in my colour # scheme. def SynStack() if !exists("*synstack") return endif echo map(synstack(line('.'), col('.')), 'synIDattr(v:val, "name")') enddef nnoremap \ SynStack() # Open syntax file for current # Syntax highlighting colorscheme mpwb