Skip to content

Instantly share code, notes, and snippets.

@rochacbruno
Last active August 28, 2025 00:51
Show Gist options
  • Save rochacbruno/47cabfe57a427cbfee50384be634e440 to your computer and use it in GitHub Desktop.
Save rochacbruno/47cabfe57a427cbfee50384be634e440 to your computer and use it in GitHub Desktop.
VIM 9 Config - NOTE: This is not a Neovim config, this is VIM 9+ config with plugins
" -----------------------------
" rochaCbruno Vim 9.1 config
" -----------------------------
" --- Leader keys ---
let mapleader = ","
let maplocalleader = ","
source ~/.vim/functions.vim
source ~/.vim/commands.vim
source ~/.vim/plugins.vim
source ~/.vim/flagmarks.vim
source ~/.vim/custom_colors.vim
source ~/.vim/options.vim
source ~/.vim/mappings.vim
" Define a custom command 'EHere' that opens a file in the current file's
" directory
command! -nargs=1 EHere edit %:h/<args>
" Auto commands
" On normal mode numbers are relative but in insert mode they are absolute
augroup numbertoggle
autocmd!
autocmd InsertEnter * set norelativenumber
autocmd InsertLeave * set relativenumber
augroup END
" Automatic reload changed files
" when files are changes externally automatically reload them
set autoread
autocmd FocusGained,BufEnter * checktime
" -- Status line
function! s:ApplyCustomColors()
highlight! link MistflyNormal DiffChange
highlight! link MistflyInsert WildMenu
highlight! link MistflyVisual IncSearch
highlight! link MistflyCommand WildMenu
highlight! link MistflyReplace ErrorMsg
endfunction
" Apply colors on startup
call s:ApplyCustomColors()
" Reapply colors on various events
augroup CustomColors
autocmd!
" Reapply after color scheme changes
autocmd ColorScheme * call s:ApplyCustomColors()
" Reapply when entering/leaving Goyo
autocmd User GoyoEnter nested call s:ApplyCustomColors()
autocmd User GoyoLeave nested call s:ApplyCustomColors()
" Reapply on window enter/leave
autocmd WinEnter * call s:ApplyCustomColors()
" Reapply after any plugin window closes
autocmd BufWinEnter * call s:ApplyCustomColors()
augroup END

Flag Marks Manager for Vim

A powerful global marks manager for Vim that provides visual indicators, quick navigation, and enhanced mark management capabilities.

Features

  • Visual Signs: Shows marks in the gutter with green >A, >B, etc. indicators
  • Interactive Popup Menu: Navigate marks with a visual popup showing file, line, and content preview
  • Smart Window Navigation: Automatically switches to existing split windows when going to marks
  • Smart File Matching: Robust file path comparison for accurate mark management
  • Go History: Toggle between recently visited marks
  • Quickfix Integration: View all marks in quickfix window for easy navigation
  • Batch Operations: Clear marks by file or globally

Installation

Add the following to your .vimrc:

source ~/.vim/flagmarks.vim

Commands

Command Description
:FlagAdd Add a new global mark at current position (uses next free A-Z)
:FlagDelete Delete mark on current line
:FlagNext Go to next mark in sequence
:FlagPrev Go to previous mark in sequence
:FlagList List all marks in a formatted table
:FlagMenu Open interactive popup menu to go to marks
:FlagClearFile Clear all marks in current file
:FlagClearAll Clear all global marks (A-Z)
:FlagToggle Toggle visibility of mark signs in gutter
:FlagGo [letter] Go to specific mark (window-aware) or toggle between last two
:FlagGoSame [letter] Go to specific mark (force same window)
:FlagQuick Populate quickfix with all marks
:FlagDebug Show debug information about marks and file matching

Key Mappings

Basic Operations (Window-Aware by Default)

Mapping Action
ma Add mark at cursor position
md Delete mark on current line
mn Go to next mark (switches to existing window if open)
mp Go to previous mark (switches to existing window if open)
ml List all marks
mc Clear marks in current file
mC Clear all marks globally
mt Toggle sign visibility
mm Toggle between last two marks (switches to existing window if open)
mq Populate quickfix with all marks
<leader>m Open interactive popup menu (window-aware)

Direct Go Mappings (Window-Aware)

Mapping Action
mga Go to mark A (switches to existing window if open)
mgb Go to mark B (switches to existing window if open)
mgc Go to mark C (switches to existing window if open)
... ...
mgz Go to mark Z (switches to existing window if open)

Force Same-Window Navigation (Uppercase M)

Mapping Action
Mm Toggle between last two marks (same window)
Mn Go to next mark (same window)
Mp Go to previous mark (same window)
<leader>M Open interactive popup menu (same window)
Mga - Mgz Go to specific mark A-Z (same window)

Popup Menu

The popup menu (triggered by <leader>m) shows:

  • Key: Lowercase letter to press for going
  • File: Name of the file containing the mark
  • Line: Line number of the mark
  • Preview: First 30 characters of the marked line content

Popup Navigation

  • Press a-z to go to corresponding mark (A-Z)
  • Press Esc or q to close without going

Go History

The plugin maintains a history of your last two mark destinations:

  • Use mm (or :FlagGo without arguments) to toggle between them
  • History is automatically updated when you go to marks
  • Useful for quickly switching between two working locations
  • Window-aware by default (use Mm to force same window)

Window-Aware Navigation

By default, all navigation commands are window-aware:

  • If the target file is already open in another split window, the cursor moves to that window
  • If not, the file opens in the current window
  • Use uppercase M commands to force navigation in the same window

Quickfix Integration

Use mq to populate the quickfix window with all marks:

  • Shows all marks with their locations and line previews
  • Navigate using standard quickfix commands (:cn, :cp)
  • Click entries to go directly to marks

Sign Management

Visual indicators in the gutter can be toggled on/off:

  • Signs appear as green >A, >B, etc. in the sign column
  • Use mt to toggle visibility
  • Signs automatically update when marks change
  • Sign column is automatically enabled when plugin loads

Advanced Usage

Batch Mark Management

" Clear all marks in current project file
:FlagClearFile

" Reset all global marks across all files
:FlagClearAll

Quick Navigation Pattern

" Set marks at important locations
ma  " Mark current position as A
" ... navigate elsewhere ...
mb  " Mark another position as B

" Now toggle between them
mm  " Go to A (switches window if open)
mm  " Go back to B (switches window if open)

" Force same window navigation
Mm  " Go to A (same window)
Mm  " Go back to B (same window)

Direct Go Without Menu

" Go directly to mark E (window-aware)
mge

" Force same window
Mge

" Or use command form
:FlagGo e       " Window-aware
:FlagGoSame e   " Same window

Using Quickfix

" View all marks in quickfix
mq

" Navigate quickfix entries
:cn  " Next mark
:cp  " Previous mark

Troubleshooting

If marks aren't working as expected:

  1. Run :FlagDebug to see parsing and file matching details
  2. Check that your Vim version supports getmarklist() function
  3. Ensure sign column is visible: :set signcolumn=auto

Requirements

  • Vim 8.0+ (for sign and popup features)
  • Support for getmarklist() function

Configuration

The plugin uses these global variables (set before sourcing):

" Example: Start with signs hidden
let g:flag_signs_visible = 0
source ~/.vim/flagmarks.vim

Notes

  • Only manages global marks (A-Z), not local marks (a-z)
  • Marks persist across Vim sessions (standard Vim behavior)
  • File path matching handles relative and absolute paths automatically
  • Preview shows first 30 non-whitespace characters of marked lines
" =====================================
" Flag Marks Manager - Vim9script
" =====================================
" Global variables
let g:flag_marks = []
let g:last_mark = ''
let g:flag_signs_visible = 1
let g:flag_go_history = []
" ---------------------------
" Initialize signs for marks
" ---------------------------
function! s:InitSigns()
" Define signs for all uppercase letters
for l:i in range(char2nr('A'), char2nr('Z'))
let l:letter = nr2char(l:i)
let l:sign_name = 'FlagMark' . l:letter
if empty(sign_getdefined(l:sign_name))
" Use '>' + letter for better visibility in gutter
call sign_define(l:sign_name, {'text': '>' . l:letter, 'texthl': 'DiffAdd', 'linehl': ''})
endif
endfor
endfunction
" Initialize signs on startup
call s:InitSigns()
" Ensure sign column is visible
if !exists('&signcolumn') || &signcolumn == 'no'
set signcolumn=auto
endif
" ---------------------------
" Helper function to compare files
" ---------------------------
function! s:FilesMatch(file1, file2)
" Remove any whitespace
let l:f1 = trim(a:file1)
let l:f2 = trim(a:file2)
" Direct comparison
if l:f1 ==# l:f2
return 1
endif
" Get full paths
let l:f1_full = fnamemodify(l:f1, ':p')
let l:f2_full = fnamemodify(l:f2, ':p')
" Full path comparison
if l:f1_full != '' && l:f2_full != '' && l:f1_full ==# l:f2_full
return 1
endif
" Try resolving relative to current directory
let l:f1_resolved = resolve(l:f1)
let l:f2_resolved = resolve(l:f2)
if l:f1_resolved ==# l:f2_resolved
return 1
endif
" Compare just filenames as last resort
let l:f1_tail = fnamemodify(l:f1, ':t')
let l:f2_tail = fnamemodify(l:f2, ':t')
if l:f1_tail != '' && l:f2_tail != '' && l:f1_tail ==# l:f2_tail
return 1
endif
return 0
endfunction
" ---------------------------
" Update signs for all marks
" ---------------------------
function! s:UpdateSigns()
" Ensure signs are initialized
call s:InitSigns()
" Clear all existing flag mark signs
call sign_unplace('FlagMarks')
" Only place signs if they're visible
if !g:flag_signs_visible
return
endif
" Place signs for current marks
for l:m in g:flag_marks
try
" Get the file path - it might be relative or absolute
let l:file_path = trim(l:m.file)
" Try different ways to find the buffer
let l:bufnr = -1
" Check all buffers for a match
for l:buf in range(1, bufnr('$'))
if !bufexists(l:buf)
continue
endif
let l:bufname = bufname(l:buf)
if l:bufname == ''
continue
endif
if s:FilesMatch(l:bufname, l:file_path)
let l:bufnr = l:buf
break
endif
endfor
" If no buffer found, try to create one if file exists
if l:bufnr == -1
let l:full_path = fnamemodify(l:file_path, ':p')
if filereadable(l:full_path)
let l:bufnr = bufnr(l:full_path, 1)
elseif filereadable(l:file_path)
let l:bufnr = bufnr(l:file_path, 1)
endif
endif
if l:bufnr != -1 && bufexists(l:bufnr)
let l:sign_name = 'FlagMark' . l:m.mark
let l:sign_id = char2nr(l:m.mark) * 1000 + str2nr(l:m.line)
call sign_place(l:sign_id, 'FlagMarks', l:sign_name, l:bufnr, {'lnum': str2nr(l:m.line), 'priority': 100})
endif
catch
" Debug: show errors
echom "Sign place error for mark " . l:m.mark . ": " . v:exception
endtry
endfor
endfunction
" ---------------------------
" Collect all global marks (A-Z)
" ---------------------------
function! s:CollectMarks()
try
" Get marks info using getmarklist()
let l:marks = getmarklist()
let g:flag_marks = []
" Process each mark
for l:mark_info in l:marks
" Only process uppercase marks A-Z
let l:mark_char = l:mark_info.mark[1] " Remove the leading '
if l:mark_char =~# '^[A-Z]$'
" Get position info
let l:pos = l:mark_info.pos
let l:bufnr = l:pos[0]
let l:line_num = l:pos[1]
let l:col = l:pos[2]
" Get filename from buffer number
let l:file = ''
if l:bufnr > 0
let l:file = bufname(l:bufnr)
if l:file == ''
" Try to get file from buffer info
let l:file = fnamemodify(bufname(l:bufnr), ':p')
endif
endif
" If we still don't have a file, try getting it from mark position
if l:file == ''
" Try to get file using getpos
let l:mark_pos = getpos("'" . l:mark_char)
if l:mark_pos[0] > 0
let l:file = bufname(l:mark_pos[0])
endif
endif
if l:file != ''
let l:markinfo = {'mark': l:mark_char, 'line': string(l:line_num), 'col': string(l:col), 'file': l:file}
call add(g:flag_marks, l:markinfo)
endif
endif
endfor
" sort by mark
call sort(g:flag_marks, {a,b -> a.mark < b.mark ? -1 : a.mark > b.mark ? 1 : 0})
" Update signs after collecting marks
call s:UpdateSigns()
catch /E283/
" No marks set
let g:flag_marks = []
catch
" Other errors - try to continue
echom "Error collecting marks: " . v:exception
endtry
endfunction
" ---------------------------
" Find next free mark
" ---------------------------
function! s:NextFreeMark()
call s:CollectMarks()
for l:c in range(char2nr('A'), char2nr('Z'))
let l:m = nr2char(l:c)
let l:exists = filter(copy(g:flag_marks), {_,v -> v.mark ==# l:m})
if empty(l:exists)
return l:m
endif
endfor
return ''
endfunction
" ---------------------------
" Add new global mark
" ---------------------------
function! FlagAdd()
" Check if there's already a mark on this line in this file
call s:CollectMarks()
let l:lnum = line('.')
let l:fname = expand('%:p')
for l:existing in g:flag_marks
let l:mark_file = fnamemodify(l:existing.file, ':p')
if l:mark_file ==# l:fname && str2nr(l:existing.line) == l:lnum
echo "Mark " . l:existing.mark . " already exists on this line"
return
endif
endfor
let l:m = s:NextFreeMark()
if l:m == ''
echo "No free global marks!"
return
endif
execute 'mark ' . l:m
" Add to jump history
if empty(g:flag_go_history)
call add(g:flag_go_history, l:m)
elseif len(g:flag_go_history) == 1
if g:flag_go_history[0] != l:m
call insert(g:flag_go_history, l:m, 0)
endif
else
if g:flag_go_history[0] != l:m
let g:flag_go_history[1] = g:flag_go_history[0]
let g:flag_go_history[0] = l:m
endif
endif
call s:CollectMarks()
echo "Set global mark " . l:m
endfunction
" ---------------------------
" Delete mark on current line
" ---------------------------
function! FlagDelete()
call s:CollectMarks()
let l:lnum = line('.')
let l:current_file = expand('%:p')
let l:current_name = expand('%:t')
for l:m in g:flag_marks
" Check if line numbers match
if str2nr(l:m.line) != l:lnum
continue
endif
" Check if files match using helper function
if s:FilesMatch(l:current_file, l:m.file)
execute 'delmarks ' . l:m.mark
echo "Deleted mark " . l:m.mark
call s:CollectMarks()
return
endif
endfor
echo "No mark on line " . l:lnum . " (checked " . len(g:flag_marks) . " marks)"
endfunction
" ---------------------------
" Clear all marks in file
" ---------------------------
function! FlagClearFile()
call s:CollectMarks()
let l:current_file = expand('%:p')
let l:marks = []
for l:m in g:flag_marks
" Check if files match using helper function
if s:FilesMatch(l:current_file, l:m.file)
call add(l:marks, l:m.mark)
endif
endfor
if !empty(l:marks)
" Ask for confirmation
let l:file_name = fnamemodify(l:current_file, ':t')
let l:marks_str = join(l:marks, ', ')
echo "Clear marks [" . l:marks_str . "] in " . l:file_name . "? (y/N): "
let l:confirm = nr2char(getchar())
if l:confirm ==? 'y'
execute 'delmarks ' . join(l:marks, '')
echo "Cleared " . len(l:marks) . " marks in current file"
call s:CollectMarks()
else
echo "Cancelled"
endif
else
echo "No marks in this file (checked " . len(g:flag_marks) . " total marks)"
endif
endfunction
" ---------------------------
" Clear all marks globally
" ---------------------------
function! FlagClearAll()
call s:CollectMarks()
if empty(g:flag_marks)
echo "No global marks to clear"
return
endif
" Ask for confirmation
let l:count = len(g:flag_marks)
let l:marks = map(copy(g:flag_marks), 'v:val.mark')
let l:marks_str = join(l:marks, ', ')
echo "Clear ALL " . l:count . " global marks [" . l:marks_str . "]? (y/N): "
let l:confirm = nr2char(getchar())
if l:confirm ==? 'y'
execute 'delmarks A-Z'
call s:CollectMarks()
call s:UpdateSigns()
echo "Cleared all global marks"
else
echo "Cancelled"
endif
endfunction
" ---------------------------
" Same-window versions (force same window)
" ---------------------------
function! FlagGoSame(...)
if a:0 == 0
call FlagGo('', 0)
else
call FlagGo(a:1, 0)
endif
endfunction
function! FlagNextSame()
call FlagNext(0)
endfunction
function! FlagPrevSame()
call FlagPrev(0)
endfunction
function! FlagMenuSame()
let g:flag_menu_window_aware = 0
call FlagMenu()
endfunction
function! FlagMenuWindow()
let g:flag_menu_window_aware = 1
call FlagMenu()
endfunction
" ---------------------------
" Populate quickfix with marks
" ---------------------------
function! FlagQuick()
call s:CollectMarks()
if empty(g:flag_marks)
echo "No marks to add to quickfix"
return
endif
let l:qf_list = []
for l:m in g:flag_marks
" Get buffer number for the file
let l:bufnr = bufnr(l:m.file)
if l:bufnr == -1
" Try to create buffer if file exists
if filereadable(fnamemodify(l:m.file, ':p'))
let l:bufnr = bufnr(fnamemodify(l:m.file, ':p'), 1)
elseif filereadable(l:m.file)
let l:bufnr = bufnr(l:m.file, 1)
endif
endif
" Get line text for preview
let l:text = s:GetLinePreview(l:m.file, str2nr(l:m.line))
" Add to quickfix list
call add(l:qf_list, {
\ 'bufnr': l:bufnr,
\ 'filename': l:m.file,
\ 'lnum': str2nr(l:m.line),
\ 'col': str2nr(l:m.col),
\ 'text': 'Mark ' . l:m.mark . ': ' . l:text,
\ 'type': 'M'
\ })
endfor
" Set quickfix list
call setqflist(l:qf_list)
" Open quickfix window
copen
echo "Added " . len(l:qf_list) . " marks to quickfix"
endfunction
" ---------------------------
" Jump next/prev mark
" ---------------------------
function! FlagNext(...)
" Default to window-aware (1) unless explicitly passed 0
let l:window_aware = (a:0 > 0) ? a:1 : 1
call s:CollectMarks()
if empty(g:flag_marks)
echo "No marks"
return
endif
let l:marks = map(copy(g:flag_marks), 'v:val.mark')
let idx = index(l:marks, get(g:, 'last_mark', ''))
let idx = (idx + 1) % len(l:marks)
let g:last_mark = l:marks[idx]
call s:JumpToMark(g:last_mark, l:window_aware)
endfunction
function! FlagPrev(...)
" Default to window-aware (1) unless explicitly passed 0
let l:window_aware = (a:0 > 0) ? a:1 : 1
call s:CollectMarks()
if empty(g:flag_marks)
echo "No marks"
return
endif
let l:marks = map(copy(g:flag_marks), 'v:val.mark')
let idx = index(l:marks, get(g:, 'last_mark', ''))
let idx = (idx - 1 + len(l:marks)) % len(l:marks)
let g:last_mark = l:marks[idx]
call s:JumpToMark(g:last_mark, l:window_aware)
endfunction
" ---------------------------
" List marks aligned
" ---------------------------
function! FlagList()
call s:CollectMarks()
if empty(g:flag_marks)
echo "No marks"
return
endif
let l:maxfile = max(map(copy(g:flag_marks), 'len(fnamemodify(v:val.file, ":t"))'))
echo printf("%-4s %-*s %s", "Mark", l:maxfile, "File", "Line")
echo repeat("-", 6 + l:maxfile + 5)
for l:m in g:flag_marks
let l:file_short = fnamemodify(l:m.file, ":t")
echo printf("%-4s %-*s %s", l:m.mark, l:maxfile, l:file_short, l:m.line)
endfor
endfunction
" ---------------------------
" Toggle sign visibility
" ---------------------------
function! FlagToggle()
let g:flag_signs_visible = !g:flag_signs_visible
if g:flag_signs_visible
call s:UpdateSigns()
echo "Flag signs enabled"
else
call sign_unplace('FlagMarks')
echo "Flag signs disabled"
endif
endfunction
" ---------------------------
" Get line content preview
" ---------------------------
function! s:GetLinePreview(file, line_num)
" Try to get the line content
let l:content = ''
let l:bufnr = bufnr(a:file)
if l:bufnr != -1 && bufloaded(l:bufnr)
" Buffer is loaded, get line directly
let l:lines = getbufline(l:bufnr, a:line_num)
if !empty(l:lines)
let l:content = l:lines[0]
endif
elseif filereadable(a:file)
" File exists but not loaded, read it
let l:lines = readfile(a:file, '', a:line_num)
if len(l:lines) >= a:line_num
let l:content = l:lines[a:line_num - 1]
endif
endif
" Clean and truncate the content
if l:content != ''
" Remove leading whitespace
let l:content = substitute(l:content, '^\s\+', '', '')
" Truncate to first 30 chars
if len(l:content) > 30
let l:content = strpart(l:content, 0, 27) . '...'
endif
else
let l:content = '<no preview>'
endif
return l:content
endfunction
" ---------------------------
" Find window containing file
" ---------------------------
function! s:FindWindowWithFile(file)
" Get full path of target file
let l:target_file = fnamemodify(a:file, ':p')
" Check all windows
for l:winnr in range(1, winnr('$'))
let l:bufnr = winbufnr(l:winnr)
if l:bufnr != -1
let l:win_file = fnamemodify(bufname(l:bufnr), ':p')
if l:win_file ==# l:target_file || bufname(l:bufnr) ==# a:file
return l:winnr
endif
endif
endfor
return 0
endfunction
" ---------------------------
" Go to mark with window awareness
" ---------------------------
function! s:JumpToMark(mark, window_aware)
" Check if mark exists
let l:mark_info = 0
for m in getmarklist()
if m.mark[1] ==# a:mark
let l:mark_info = m
break
endif
endfor
if type(l:mark_info) == type({})
let l:target_bufnr = l:mark_info.pos[0]
let l:target_file = bufname(l:target_bufnr)
if a:window_aware && l:target_file != ''
" Check if file is open in another window
let l:target_winnr = s:FindWindowWithFile(l:target_file)
if l:target_winnr > 0 && l:target_winnr != winnr()
" Switch to that window
execute l:target_winnr . 'wincmd w'
" Go to the mark in that window
execute "normal! '" . a:mark
redraw | echo "Went to mark " . a:mark . " in window " . l:target_winnr
return 1
endif
endif
" Normal jump (same window)
silent! execute "normal! '" . a:mark
redraw | echo "Went to mark " . a:mark
return 1
endif
return 0
endfunction
" ---------------------------
" Go to specific mark
" ---------------------------
function! FlagGo(...)
" Check for window_aware flag (second argument), default to 1 (window-aware)
let l:window_aware = (a:0 >= 2) ? a:2 : 1
if a:0 == 0 || (a:0 == 1 && a:1 == '')
" No argument - toggle between last two marks
if len(g:flag_go_history) >= 2
" Check if both marks still exist
let l:mark1_exists = 0
let l:mark2_exists = 0
for m in getmarklist()
if m.mark[1] ==# g:flag_go_history[0]
let l:mark1_exists = 1
endif
if m.mark[1] ==# g:flag_go_history[1]
let l:mark2_exists = 1
endif
endfor
if l:mark1_exists && l:mark2_exists
" Swap last two entries
let l:temp = g:flag_go_history[0]
let g:flag_go_history[0] = g:flag_go_history[1]
let g:flag_go_history[1] = l:temp
" Go to the new first entry
call s:JumpToMark(g:flag_go_history[0], l:window_aware)
else
" Clean up non-existent marks from history
let g:flag_go_history = []
echo "Jump history marks no longer exist"
endif
elseif len(g:flag_go_history) == 1
" Check if the single mark exists
let l:mark_exists = 0
for m in getmarklist()
if m.mark[1] ==# g:flag_go_history[0]
let l:mark_exists = 1
break
endif
endfor
if l:mark_exists
call s:JumpToMark(g:flag_go_history[0], l:window_aware)
else
let g:flag_go_history = []
echo "Mark " . g:flag_go_history[0] . " no longer exists"
endif
else
" No history - try to go to any existing mark
call s:CollectMarks()
if !empty(g:flag_marks)
let l:first_mark = g:flag_marks[0].mark
call FlagGo(l:first_mark, l:window_aware)
else
echo "No marks set"
endif
endif
else
" Go to specific mark
let l:mark = toupper(a:1)
if l:mark =~# '^[A-Z]$'
" Check if mark exists
let l:mark_exists = 0
for m in getmarklist()
if m.mark[1] ==# l:mark
let l:mark_exists = 1
break
endif
endfor
if l:mark_exists
" Update jump history
if empty(g:flag_go_history)
" First mark in history
call add(g:flag_go_history, l:mark)
elseif len(g:flag_go_history) == 1
if g:flag_go_history[0] != l:mark
" Add second mark
call insert(g:flag_go_history, l:mark, 0)
endif
else
" We have 2 marks in history
if g:flag_go_history[0] != l:mark
" Replace oldest with current
let g:flag_go_history[1] = g:flag_go_history[0]
let g:flag_go_history[0] = l:mark
endif
endif
if !s:JumpToMark(l:mark, l:window_aware)
echo "Failed to go to mark " . l:mark
endif
else
echo "Mark " . l:mark . " not set"
endif
else
echo "Invalid mark: " . a:1
endif
endif
endfunction
" ---------------------------
" Popup menu: type letter
" ---------------------------
function! s:PopupFilter(winid, key)
" Convert lowercase to uppercase for marks
let l:key = toupper(a:key)
" Check if it's a valid mark letter
if l:key =~# '^[A-Z]$'
" Find and go to the mark
for l:m in g:flag_marks
if l:m.mark ==# l:key
call popup_close(a:winid)
" Add to jump history and jump (with window awareness if set)
" Default is window-aware (1), unless explicitly set to 0
let l:window_aware = get(g:, 'flag_menu_window_aware', 1)
silent! call FlagGo(l:key, l:window_aware)
unlet! g:flag_menu_window_aware " Clean up
redraw
return 1
endif
endfor
" Mark not found
call popup_close(a:winid)
echo "Mark " . l:key . " not found"
return 1
endif
" Close on Escape or q
if a:key ==# "\<Esc>" || a:key ==# 'q'
call popup_close(a:winid)
return 1
endif
" Ignore other keys
return 1
endfunction
function! FlagMenu()
call s:CollectMarks()
if empty(g:flag_marks)
echo "No marks"
return
endif
" Build content for popup
let l:content = []
call add(l:content, ' Key │ File │ Line │ Preview')
call add(l:content, '─────┼─────────────────┼──────┼────────────────────────────────')
for l:m in g:flag_marks
" Only show uppercase marks A-Z
if l:m.mark =~# '^[A-Z]$'
let l:file_short = fnamemodify(l:m.file, ":t")
" Ensure file name fits in column
if len(l:file_short) > 16
let l:file_short = strpart(l:file_short, 0, 13) . '...'
endif
" Get line preview
let l:preview = s:GetLinePreview(l:m.file, str2nr(l:m.line))
" Show lowercase letter for user to press
let l:lower_key = tolower(l:m.mark)
let l:line_text = printf(" %s │ %-16s│ %4s │ %s", l:lower_key, l:file_short, l:m.line, l:preview)
call add(l:content, l:line_text)
endif
endfor
call add(l:content, '')
call add(l:content, ' Press a-z to jump, Esc/q to close')
" Create popup
let l:opts = {
\ 'filter': 's:PopupFilter',
\ 'title': ' Global Marks ',
\ 'border': [],
\ 'padding': [0, 1, 0, 1],
\ 'pos': 'center',
\ 'mapping': 0,
\ 'highlight': 'Normal'
\ }
call popup_create(l:content, l:opts)
endfunction
" ---------------------------
" Debug function
" ---------------------------
function! s:DebugMarks()
let l:current_file = expand('%:p')
echo "=== Current State ==="
echo "Current file: '" . l:current_file . "'"
echo "Current line: " . line('.')
echo ""
echo "=== File Matching Test ==="
for m in g:flag_marks
let l:result = s:FilesMatch(l:current_file, m.file)
echo " Mark " . m.mark . " @ line " . m.line . ": " . (l:result ? "MATCH" : "NO MATCH")
echo " Mark file: '" . m.file . "'"
if !l:result
echo " Current: '" . l:current_file . "'"
echo " Mark full: '" . fnamemodify(m.file, ':p') . "'"
endif
endfor
echo ""
echo "=== All Open Buffers ==="
for l:buf in range(1, bufnr('$'))
if bufexists(l:buf) && bufname(l:buf) != ''
echo " Buffer " . l:buf . ": '" . bufname(l:buf) . "'"
endif
endfor
echo ""
echo "=== Buffers with Signs ==="
let l:found_signs = 0
for l:buf in range(1, bufnr('$'))
if bufexists(l:buf)
let l:signs = sign_getplaced(l:buf, {'group': 'FlagMarks'})
if !empty(l:signs) && !empty(l:signs[0].signs)
echo " Buffer " . l:buf . " (" . bufname(l:buf) . "): " . len(l:signs[0].signs) . " signs"
let l:found_signs = 1
endif
endif
endfor
if !l:found_signs
echo " No signs found in any buffer"
endif
endfunction
" ---------------------------
" Commands
" ---------------------------
command! FlagAdd call FlagAdd()
command! FlagDelete call FlagDelete()
command! FlagNext call FlagNext()
command! FlagPrev call FlagPrev()
command! FlagClearFile call FlagClearFile()
command! FlagClearAll call FlagClearAll()
command! FlagList call FlagList()
command! FlagMenu call FlagMenu()
command! FlagDebug call s:DebugMarks()
command! FlagToggle call FlagToggle()
command! -nargs=* FlagGo call FlagGo(<f-args>)
command! -nargs=? FlagGoSame call FlagGoSame(<f-args>)
command! FlagNextSame call FlagNextSame()
command! FlagPrevSame call FlagPrevSame()
command! FlagMenuSame call FlagMenuSame()
command! FlagMenuWindow call FlagMenuWindow()
command! FlagQuick call FlagQuick()
" ---------------------------
" Keymaps
" ---------------------------
nnoremap <silent> ma :FlagAdd<CR>
nnoremap <silent> md :FlagDelete<CR>
nnoremap <silent> mn :FlagNext<CR>
nnoremap <silent> mp :FlagPrev<CR>
nnoremap <silent> mc :FlagClearFile<CR>
nnoremap <silent> mC :FlagClearAll<CR>
nnoremap <silent> ml :FlagList<CR>
nnoremap <silent> mt :FlagToggle<CR>
nnoremap <silent> mq :FlagQuick<CR>
" Window-aware mappings (lowercase m - default behavior)
nnoremap <silent> mm :FlagGo<CR>
nnoremap <silent> mn :FlagNext<CR>
nnoremap <silent> mp :FlagPrev<CR>
nnoremap <silent> <leader>m :FlagMenuWindow<CR>
" Window-aware go to specific marks
for s:i in range(char2nr('a'), char2nr('z'))
let s:letter = nr2char(s:i)
execute 'nnoremap <silent> mg' . s:letter . ' :FlagGo ' . s:letter . '<CR>'
endfor
" Same-window mappings (uppercase M - force same window)
nnoremap <silent> Mm :FlagGoSame<CR>
nnoremap <silent> Mn :FlagNextSame<CR>
nnoremap <silent> Mp :FlagPrevSame<CR>
nnoremap <silent> <leader>M :FlagMenuSame<CR>
" Same-window go to specific marks
for s:i in range(char2nr('a'), char2nr('z'))
let s:letter = nr2char(s:i)
execute 'nnoremap <silent> Mg' . s:letter . ' :FlagGoSame ' . s:letter . '<CR>'
endfor
" ---------------------------
" Auto-update signs on buffer enter
" ---------------------------
augroup FlagMarksAutoUpdate
autocmd!
autocmd BufEnter,BufRead,BufWritePost * silent! call s:CollectMarks()
autocmd VimEnter * silent! call s:InitSigns() | silent! call s:CollectMarks()
augroup END
function! Alert(msg)
augroup MyAlerts
autocmd!
execute 'autocmd VimEnter * echomsg "' . a:msg . '"'
augroup END
endfunction
" --- Buffers-as-tabs tabline (clickable) ---
function! BufferTabLine() abort
let s = ''
for i in range(1, bufnr('$'))
if buflisted(i)
let name = bufname(i)
if empty(name)
let name = '[No Name]'
else
let name = fnamemodify(name, ':t')
endif
if i == bufnr('%')
let s .= '%#TabLineSel#'
else
let s .= '%#TabLine#'
endif
let s .= '%' . i . 'T' " clickable buffer switch
let s .= i . ': ' . name . ' '
endif
endfor
let s .= '%#TabLineFill#%T'
return s
endfunction
if !exists("*DeleteHiddenBuffers") " Clear all hidden buffers when running
function DeleteHiddenBuffers() " Vim with the 'hidden' option
let tpbl=[]
call map(range(1, tabpagenr('$')), 'extend(tpbl, tabpagebuflist(v:val))')
for buf in filter(range(1, bufnr('$')), 'bufexists(v:val) && index(tpbl, v:val)==-1')
silent execute 'bwipeout' buf
endfor
endfunction
endif
command! DeleteHiddenBuffers call DeleteHiddenBuffers()
" LSP configuration for Vim
call LspOptionsSet(#{
\ aleSupport: v:true,
\ autoComplete: v:true,
\ autoHighlight: v:false,
\ autoHighlightDiags: v:true,
\ autoPopulateDiags: v:false,
\ completionMatcher: 'case',
\ completionMatcherValue: 1,
\ diagSignErrorText: 'E>',
\ diagSignHintText: 'H>',
\ diagSignInfoText: 'I>',
\ diagSignWarningText: 'W>',
\ echoSignature: v:false,
\ hideDisabledCodeActions: v:false,
\ highlightDiagInline: v:true,
\ hoverInPreview: v:false,
\ ignoreMissingServer: v:false,
\ keepFocusInDiags: v:true,
\ keepFocusInReferences: v:true,
\ completionTextEdit: v:true,
\ diagVirtualTextAlign: 'above',
\ diagVirtualTextWrap: 'default',
\ noNewlineInCompletion: v:false,
\ omniComplete: v:null,
\ outlineOnRight: v:false,
\ outlineWinSize: 20,
\ popupBorder: v:true,
\ popupBorderHighlight: 'Title',
\ popupBorderHighlightPeek: 'Special',
\ popupBorderSignatureHelp: v:false,
\ popupHighlightSignatureHelp: 'Pmenu',
\ popupHighlight: 'Normal',
\ semanticHighlight: v:true,
\ showDiagInBalloon: v:true,
\ showDiagInPopup: v:true,
\ showDiagOnStatusLine: v:false,
\ showDiagWithSign: v:true,
\ showDiagWithVirtualText: v:false,
\ showInlayHints: v:false,
\ showSignature: v:true,
\ snippetSupport: v:false,
\ ultisnipsSupport: v:false,
\ useBufferCompletion: v:false,
\ usePopupInCodeAction: v:false,
\ useQuickfixForLocations: v:false,
\ vsnipSupport: v:false,
\ bufferCompletionTimeout: 100,
\ customCompletionKinds: v:false,
\ completionKinds: {},
\ filterCompletionDuplicates: v:false,
\ condensedCompletionMenu: v:false,
\ })
" Rust language server
if executable('/usr/lib/rustup/bin/rust-analyzer')
call LspAddServer([#{
\ name: 'rustlang',
\ filetype: ['rust'],
\ path: '/usr/lib/rustup/bin/rust-analyzer',
\ args: [],
\ syncInit: v:true,
\ initializationOptions: #{
\ inlayHints: #{
\ typeHints: #{
\ enable: v:true
\ },
\ parameterHints: #{
\ enable: v:true
\ }
\ },
\ }
\ }])
else
call Alert("Rust language server not found. Please install rust-analyzer.")
endif
" Bash
if executable('/usr/bin/bash-language-server')
call LspAddServer([#{name: 'bashls',
\ filetype: 'sh',
\ path: '/usr/bin/bash-language-server',
\ args: ['start']
\ }])
else
call Alert("Bash language server not found. Please install bash-language-server.")
endif
" DOC language server
if executable('/home/rochacbruno/.local/bin/doc-lsp1')
call LspAddServer([#{
\ name: 'doc-lsp',
\ filetype: 'python',
\ path: '/home/rochacbruno/.local/bin/doc-lsp'
\ }])
else
call Alert('Doc-LSP language server not found. Please install Doc LSP')
endif
if executable('/usr/bin/pyright-langserver')
call LspAddServer([#{name: 'pyright',
\ filetype: 'python',
\ path: '/usr/bin/pyright-langserver',
\ args: ['--stdio'],
\ workspaceConfig: #{
\ python: #{
\ pythonPath: '.venv/bin/python'
\ }}
\ }])
else
call Alert("Pyright language server not found. Please install pyright.")
endif
if executable('/usr/bin/yaml-language-server')
call LspAddServer([#{
\ name: 'yaml-language-server',
\ filetype: 'yaml',
\ path: '/usr/bin/yaml-language-server',
\ args: ['--stdio'],
\ workspaceConfig: #{
\ yaml: #{
\ schemas: {
\ "https://raw.githubusercontent.com/compose-spec/compose-spec/master/schema/compose-spec.json" : [
\ "**/*docker-compose*.yaml"
\ ],
\ "https://json.schemastore.org/chart.json": [
\ "**helm/values*.yaml"
\ ]
\ }
\ }
\ }
\ }])
else
call Alert("YAML language server not found. Please install yaml-language-server.")
endif
" TOML language server
if executable('/home/rochacbruno/.local/bin/tombi')
call LspAddServer([#{name: 'tombi',
\ filetype: 'toml',
\ args: ['lsp'],
\ path: '/home/rochacbruno/.local/bin/tombi'
\ }])
else
call Alert("TOML language server not found. Please install tombi.")
endif
" ---- PURE VIM MAPPINGS
" --- Tabs ---
" Tabs are useless.
nnoremap <leader>tn :tabnew<CR>
nnoremap <leader>to :tabonly<CR>
nnoremap <leader>tc :tabclose<CR>
nnoremap <leader>tl :tabnext<CR>
nnoremap <leader>th :tabprevious<CR>
" --- Buffers ---
nnoremap <leader>bl :ls<CR>:b<Space> " list buffers and prompt for buffer number
nnoremap [q :bp<CR> " previous buffer
nnoremap ]q :bn<CR> " next buffer
nnoremap bda :DeleteHiddenBuffers<CR> " delete all hidden buffers
for n in range(1, 9)
execute 'nnoremap <silent> <leader>' . n . ' :buffer ' . n . '<CR>'
endfor
"Map buffer quick switch keys"
nnoremap <silent> <leader><Tab> <C-^>
" --- Window management (splits) ---
nnoremap <leader>= :resize +3<CR>
nnoremap <leader>- :resize -3<CR>
nnoremap <leader>> :vertical resize +3<CR>
nnoremap <leader>< :vertical resize -3<CR>
" C-w-f = open current file in new split
" C-w-v = split file vertically
" C-w-s = split file horizontally
" --- Quick save/quit & QoL ---
nnoremap <leader>w :write<CR>
nnoremap <leader>q :quit<CR>
nnoremap <leader>x :xit<CR>
nnoremap <leader>h :nohlsearch<CR>
" ------ Term mode ------
tnoremap <C-v><Esc> <C-\><C-n>
nnoremap <leader>c :botright term<CR>
" -- replace current word --
"NOTE: this is also a VM mode feature but I like having it in pure vim too
" on VM: ctrl+d to select word then \\A to select all instances then c to
" change
nnoremap <leader>r :%s/\<<C-r><C-w>\>/<C-r><C-w>/gI<Left><Left><Left>
" -- Reload vim config --
nnoremap <leader><leader>r :source ~/.vimrc<CR>
" Make Ctrl+s save the file in normal and insert mode
nnoremap <C-s> :update<CR>
inoremap <C-s> <Esc>:update<CR>a
xnoremap <C-s> <Esc>:update<CR>gv
" Make Ctrl+z undo in normal and insert mode
nnoremap <C-z> u
inoremap <C-z> <Esc>ua
xnoremap <C-z> <Esc>ugv
" Emacs style cursor movement in insert mode
inoremap <C-a> <Home>
inoremap <C-e> <End>
inoremap <C-f> <Right>
inoremap <C-b> <Left>
inoremap <C-d> <Del>
inoremap <C-k> <C-o>D
inoremap <M-Backspace> <C-o>dB
" Emacs style in command mode too
cnoremap <C-a> <Home>
cnoremap <C-e> <End>
cnoremap <C-f> <Right>
cnoremap <C-b> <Left>
cnoremap <C-d> <Del>
cnoremap <C-k> <C-u>
cnoremap <M-Backspace> <C-w>
" Move lines up and down in normal and visual mode
nnoremap <M-j> :m .+1<CR>==
nnoremap <M-k> :m .-2<CR>==
inoremap <M-j> <Esc>:m .+1<CR>==gi
inoremap <M-k> <Esc>:m .-2<CR>==gi
xnoremap <M-j> :m '>+1<CR>gv=gv
xnoremap <M-k> :m '<-2<CR>gv=gv
" Also using arrows
nnoremap <M-Down> :m .+1<CR>==
nnoremap <M-Up> :m .-2<CR>==
inoremap <M-Down> <Esc>:m .+1<CR>==gi
inoremap <M-Up> <Esc>:m .-2<CR>==gi
xnoremap <M-Down> :m '>+1<CR>gv=gv
xnoremap <M-Up> :m '<-2<CR>gv=gv
" Stay in indent mode when indenting in visual mode
xnoremap < <gv
xnoremap > >gv
" Sane paste without overwriting the default register
xnoremap p "_dP
vnoremap p "_dP
" Disable annoying Q command
nnoremap Q <Nop>
" Better navigation for wrapped lines
" nnoremap j gj
" nnoremap k gk
" nnoremap gj j
" nnoremap gk k
" Make a script executable from vim
nnoremap <leader>x :!chmod +x %<CR>
"
"
"
" --- Colors Theme ---
colorscheme purify
" --- Better defaults ---
set nocompatible
set number
set relativenumber
set hidden
set mouse=a
set clipboard=unnamedplus
set tabstop=4 shiftwidth=4 expandtab
set smartindent
set autoindent
set ignorecase smartcase
set incsearch hlsearch
set showmatch
set splitbelow splitright
set termguicolors
set signcolumn=auto
set undofile
set wildmenu
set wildmode=longest:full,full
set wildignorecase
set ttimeout ttimeoutlen=10
set timeout timeoutlen=500
set encoding=UTF-8
" --- Syntax & filetype ---
syntax on
filetype plugin indent on
" --- Status line ---
set laststatus=2
set showcmd
set noshowmode
set ruler
"set statusline=%f\ %h%m%r%=%-14.(%l,%c%V%)\ %P
set showtabline=2
set tabline=%!BufferTabLine()
" Search upwards for a manually created .viminfo file or use a default
let &viminfofile=findfile('.viminfo','.;') ?? $HOME . '/.vim/viminfo'
" --- Built-in Plugins
" -------------- File explorer (netrw) --------------------
let g:netrw_banner = 0
let g:netrw_liststyle = 3
let g:netrw_browse_split = 4
let g:netrw_altv = 1
let g:netrw_winsize = 25
let g:netrw_keepdir = 0
runtime! plugin/netrwPlugin.vim
nnoremap <leader>e :Lexplore<CR>
nnoremap <leader>E :Vexplore<CR>
" ---------------------------------------------------------
" ----------------- LSP --------------------
" Ensure you have installed the LSP servers you want to use
" https://github.com/yegappan/lsp
if empty(glob('~/.vim/pack/downloads/opt/lsp'))
echo "Installing LSP plugin..."
silent !mkdir -p $HOME/.vim/pack/downloads/opt
silent !cd $HOME/.vim/pack/downloads/opt && git clone https://github.com/yegappan/lsp
silent !vim -u NONE -c "helptags $HOME/.vim/pack/downloads/opt/lsp/doc" -c q
echo "LSP plugin installed successfully"
endif
packadd lsp
source ~/.vim/lsp.vim
nnoremap <leader>a :LspCodeAction<CR>
nnoremap <leader>d :LspGotoDefinition<CR>
nnoremap <leader>k :LspHover<CR>
" -----------------------------------------
"----------------- PLUGINS MANAGED BY VIM-PLUG --------------------
" Ensure vim-plug is installed
if empty(glob('~/.vim/autoload/plug.vim'))
silent !curl -fLo ~/.vim/autoload/plug.vim --create-dirs
\ https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
autocmd VimEnter * PlugInstall --sync | source $MYVIMRC
endif
call plug#begin()
" ----------------- VIM SENSIBLE --------------------
" Basic default settings for a better experience
"
Plug 'tpope/vim-sensible'
" ---------------------------------------------------------
" ----------------- Better % matching --------------------
" % to jump between matching pairs of (), {}, [], <>
" Also works in visual mode
" Also works with HTML tags
" Also works with custom defined pairs, see :help matchit-custom
"
Plug 'chrisbra/matchit'
" ---------------------------------------------------------
" ----------------- File searching and navigation --------------------
" fzf (requires FZF installed)
" check if fzf is installed
if executable('fzf')
Plug 'junegunn/fzf.vim'
nnoremap <silent> <leader>l :Lines<CR>
nnoremap <silent> <leader>f :Files<CR>
nnoremap <silent> <leader>F :Rg<CR>
nnoremap <silent> <leader>b :Buffers<CR>
nnoremap <silent> <leader>g :GFiles<CR>
else
echo "fzf is not installed, please install it to use fzf.vim"
endif
" ---------------------------------------------------------
" ----------------- Autocompletion --------------------
" Requires: npm, nodejs, yarn
" Linters and formatters
Plug 'dense-analysis/ale'
" Disable ALE's LSP in favour of standalone LSP plugin"
"let g:ale_disable_lsp = 1
" Show linting errors with highlights"
"* Can also be viewed in the loclist with :lope"
"let g:ale_set_signs = 1
"let g:ale_set_highlights = 1
"let g:ale_virtualtext_cursor = 1
"highlight ALEError ctermbg=none cterm=underline
" Define when to lint"
"let g:ale_lint_on_save = 1
"let g:ale_lint_on_insert_leave = 1
"let g:ale_lint_on_text_change = 'never'
" Set linters for individual filetypes"
"let g:ale_linters_explicit = 1
"let g:ale_linters = {
" \ 'python': ['ruff', 'mypy', 'pylsp'],
" \ 'rust': ['analyzer', 'cargo'],
" \ 'sh': ['shellcheck'],
"\ }
" Specify fixers for individual filetypes"
"let g:ale_fixers = {
" \ '*': ['trim_whitespace'],
" \ 'python': ['ruff'],
" \ 'rust': ['rustfmt'],
"\ }
"Rust specific settings
"let g:ale_rust_cargo_use_clippy = 1
"let g:ale_rust_cargo_check_tests = 1
"let g:ale_rust_cargo_check_examples = 1
" Don't warn about trailing whitespace, as it is auto-fixed by '*' above"
"let g:ale_warn_about_trailing_whitespace = 0
" Show info, warnings, and errors; Write which linter produced the message"
"let g:ale_lsp_show_message_severity = 'information'
"'let g:ale_echo_msg_format = '[%linter%] [%severity%:%code%] %s'
" Specify Containerfiles as Dockerfiles"
"let g:ale_linter_aliases = {"Containerfile": "dockerfile"}
" Mapping to run fixers on file"
"nnoremap <leader>L :ALEFix<CR>
" ---------------------------------------------------------
" ----------------- GitHub Copilot --------------------
" <M-]> Cycle next suggestion
" <M-[> Cycle previous suggestion
" <M-\> Request suggestion
" <M-Right> accept next word
" <M-C-Right> Accept next line
" Tab Accept suggestion (in insert mode)
" :Copilot panel to open the copilot panel
Plug 'github/copilot.vim'
" ---------------------------------------------------------
" ----------------- Icons --------------------
" Devicons
" Requires a patched font, like Nerd Font
Plug 'ryanoasis/vim-devicons'
" ---------------------------------------------------------
" ----------------- Status Line --------------------
Plug 'bluz71/vim-mistfly-statusline'
let g:mistflyWithSearchCount = v:true
let g:mistflyWithIndentStatus = v:true
" ---------------------------------------------------------
" ----------------- Auto Pairs --------------------
" <M-b back insert pair
" <M-n jump to next closed pair
" <M-p tooggle auto pairs on and off
Plug 'jiangmiao/auto-pairs'
let g:AutoPairsMoveCharacter = ""
let g:AutoPairsShortcutBackInsert = ""
let g:AutoPairsShortcutFastWrap = ""
" ---------------------------------------------------------
"
" ----------------- Git Gutter --------------------
" Show git diff in the sign column
" + added, ~ modified, - removed
Plug 'airblade/vim-gitgutter'
" ---------------------------------------------------------
" ------------------ Which Key --------------------
" , to open which-key
" :WhichKey to open which-key
Plug 'liuchengxu/vim-which-key', { 'on': ['WhichKey', 'WhichKey!'] }
nnoremap <silent> <leader> :WhichKey ','<CR>
" ---------------------------------------------------------
" ------------------ Highlight Colors --------------------
" :ColorHighlight
Plug 'chrisbra/Colorizer'
" ---------------------------------------------------------
" ------------------ Multiple Cursors --------------------
" C-D select words, C-move add cur, Shift move single char,
" n/N Next/Prev - [] next/prev cur, q skip, Q remove cursor
" C-d to select word under cursor and then \\A to select all instances
" then c to change all instances
Plug 'mg979/vim-visual-multi', {'branch': 'master'}
let g:VM_maps = {}
let g:VM_maps['Find Under'] = '<C-d>' " replace C-n
let g:VM_maps['Find Subword Under'] = '<C-d>' " replace visual C-n
nmap <C-LeftMouse> <Plug>(VM-Mouse-Cursor)
nmap <C-RightMouse> <Plug>(VM-Mouse-Word)
nmap <M-C-RightMouse> <Plug>(VM-Mouse-Column)
" ---------------------------------------------------------
"------------------- Git Integration --------------------
" Git
" :Gstatus, :Gblame, :Gdiff, :Gread, :Gwrite, :Gmove, :Gremove, :Gcommit etc
Plug 'tpope/vim-fugitive'
Plug 'tpope/vim-rhubarb' " required by fugitive to :Gbrowse
" Show git commit under cursor
Plug 'rhysd/git-messenger.vim'
let g:git_messenger_no_default_mappings = v:true
nmap <C-g>m <Plug>(git-messenger)
" ---------------------------------------------------------
" ------------------ Commenting --------------------
" gcc to comment/uncomment a line
" gc in visual mode to comment/uncomment selection
" gc{motion} to comment/uncomment motion
" Example: gcip to comment inner paragraph
Plug 'tpope/vim-commentary'
" ---------------------------------------------------------
" " ------------------ Undo Tree --------------------
Plug 'mbbill/undotree'
let g:undotree_WindowLayout = 2
let g:undotree_ShortIndicators = 1
let g:undotree_SetFocusWhenToggle = 1
" ---------------------------------------------------------
" " ------------------ Indentation Guides --------------------
Plug 'Yggdroot/indentLine'
" ------------------- Highlight on Yank --------------------
Plug 'machakann/vim-highlightedyank'
" ------------------ HIghlight Cursor Word --------------------
Plug 'RRethy/vim-illuminate'
" ------------------ Dim Inactive Windows --------------------
Plug 'blueyed/vim-diminactive'
" ---------------------------------------------------------
" ----------- Alternative fuzzy finder to fzf --------------
Plug 'liuchengxu/vim-clap', { 'do': ':Clap install-binary' }
" ---------------------------------------------------------
" ------------------ Surround --------------------
" Manipulate surrounding chars such as quotes and brackets
" Assuming | as a cursor
" fo|o - ysiw' - 'foo'
" 'fo|o' - ds' - foo
" 'fo|o' - cs'" - "foo"
" yssb - (surround entire line)
" Shift + V to enter visual line mode then S{ to surround selection with { line break }
Plug 'tpope/vim-surround'
Plug 'tpope/vim-repeat' " repeat surround with .
" ---------------------------------------------------------
" ------------------ Speed Dating --------------------
" CTRL-A and CTRL-X to increment/decrement dates, times, numbers, hex colors,
Plug 'tpope/vim-speeddating'
" ---------------------------------------------------------
" ------------------ Results of commands as buffers --------------------
" Interact with output of commands
" e.g :Bufferize cargo watch
Plug 'AndrewRadev/bufferize.vim'
" ---------------------------------------------------------
" ------------------ File operations --------------------
" File/Buffer operations :Rename, :Move, :Delete, :Chmod, :SudoEdit
Plug 'tpope/vim-eunuch'
"" Make me dirs when saving a full path
Plug 'pbrisbin/vim-mkdir'
" ---------------------------------------------------------
" ------------------ Better Cut and Delete --------------------
" Delete instead of cut (cut is mapped to x, single char is dl)
Plug 'svermeulen/vim-cutlass'
nnoremap x d
xnoremap x d
nnoremap xx dd
nnoremap X D
" ---------------------------------------------------------
" ------------------ Scratch Buffer --------------------
" gs in normal mode to open a scratch buffer in insert mode
" gs in visual mode to open a scratch buffer with the selection
" Scratch buffer persists between sessions in ~/.vim/scratch.md
" :Scratch to open a scratch buffer in normal mode
Plug 'mtth/scratch.vim'
let g:scratch_persistence_file = '~/.vim/scratch.md'
" ---------------------------------------------------------
" ------------------ Window Based on Selection --------------------
"" Split window based on visual selection
" C-W-gsa creates a split above with the selection C-W-gss on right
" CW-gr resizes to selection
Plug 'wellle/visual-split.vim'
for m in ['n', 'x']
execute m . "noremap <C-w>gr :VSResize<CR>"
execute m . "noremap <C-w>gss :VSSplit<CR>"
execute m . "noremap <C-w>gsa :VSSplitAbove<CR>"
execute m . "noremap <C-w>gsb :VSSplitBelow<CR>"
endfor
" ---------------------------------------------------------
" ------------------ Color Picker --------------------
" ALT-c in insert mode and ALT-w in normal mode
Plug 'KabbAmine/vCoolor.vim'
" ---------------------------------------------------------
" ------------------ Distraction Free Writing --------------------
" <C-w>g opens goyo distraction free mode
Plug 'junegunn/goyo.vim'
nnoremap <C-w>g :Goyo<CR>
inoremap <C-w>g <Esc>:Goyo<CR>
" ---------------------------------------------------------
" ------------------ Zoom Window --------------------
" Window Zoom in out
" <C-w>m to toggle zoom
Plug 'dhruvasagar/vim-zoom'
" ---------------------------------------------------------
" " ------------------ Better Substitutions --------------------
Plug 'tpope/vim-abolish'
Plug 'svermeulen/vim-subversive'
" Subversive Subvert
" s+motion to substitute with yanked text
nmap s <plug>(SubversiveSubstitute)
" ss to substitute current line with yanked text
nmap ss <plug>(SubversiveSubstituteLine)
" S to substitute from cursor to end of line with yanked text
nmap S <plug>(SubversiveSubstituteToEndOfLine)
" <leader>s+motion to substitute with prompted text
" example: <leader>siwip to select inner word and range inner paragraph to
" substitute with prompted text
nmap <leader>s <plug>(SubversiveSubstituteRange)
xmap <leader>s <plug>(SubversiveSubstituteRange)
" <leader>ssie to select current word and range entire buffer to substitute
" with prompted text
nmap <leader>ss <plug>(SubversiveSubstituteWordRange)
" Same as above but use Subvert so matches different text casing
" ,,ssie will match "Word", "word", "WORD", etc
nmap <leader><leader>s <plug>(SubversiveSubvertRange)
xmap <leader><leader>s <plug>(SubversiveSubvertRange)
nmap <leader><leader>ss <plug>(SubversiveSubvertWordRange)
" ---------------------------------------------------------
" ------------------ Yoink - Better Yank and Paste --------------------
Plug 'svermeulen/vim-yoink'
let g:yoinkIncludeDeleteOperations = 1
let g:yoinkMaxItems = 20
nmap <c-n> <plug>(YoinkPostPasteSwapBack)
nmap <c-p> <plug>(YoinkPostPasteSwapForward)
nmap p <plug>(YoinkPaste_p)
nmap P <plug>(YoinkPaste_P)
" Also replace the default gp with yoink paste so we can toggle paste in this case too
nmap gp <plug>(YoinkPaste_gp)
nmap gP <plug>(YoinkPaste_gP)
" Rotate the yank buffer
nmap [y <plug>(YoinkRotateBack)
nmap ]y <plug>(YoinkRotateForward)
" maintain cursor position when yanking
nmap y <plug>(YoinkYankPreserveCursorPosition)
xmap y <plug>(YoinkYankPreserveCursorPosition)
" ---------------------------------------------------------
" ------------------ Find and Replace --------------------
" Find and Replace in multiple files
" :Far pattern replacement files_or_glob
" Example: :Far foo bar **/*.txt
" After running execute :Fardo to apply
Plug 'brooth/far.vim'
" ---------------------------------------------------------
" ------------------ Extra Text Objects --------------------
" Extra wrapper target text objects
" cI, = change inner comma (any type)
" da, = delete around comma (any type)
Plug 'wellle/targets.vim' " IS this conflicting with Subvert?
" ai = around indentation
" cai = change around indentation
" ii = inner indentation
" cii = change inner indentation
" aI = around including lines above/below
" iI = inner no lines above/below
Plug 'michaeljsmith/vim-indent-object'
" ie = inner entire buffer
" cie = change inner entire buffer
" vie = visually select inner entire buffer
" die = delete inner entire buffer
onoremap ie :exec "normal! ggVG"<cr>
" iv = current viewable text in the buffer
" civ = change current viewable text in the buffer
" viv = visually select current viewable text in the buffer
" div = delete current viewable text in the buffer
onoremap iv :exec "normal! HVL"<cr>
" ---------------------------------------------------------
" ------------------ Easy Motion --------------------
" ,,motion
" ,,fa = find the next `a` with visual hints
Plug 'easymotion/vim-easymotion'"
" ---------------------------------------------------------
" ------------------ Avoid meesing with window layout --------------------
" Avoid deleting buffer and messing with window layout
" :Bdelete to delete buffer without messing with window layout
Plug 'moll/vim-bbye'
nnoremap <leader>bd :Bdelete<CR> " delete buffer
nnoremap <leader>bx :Bdelete!<CR> " delete buffer without saving
" ---------------------------------------------------------
" ------------------- Substitute with preview --------------------
" :OverCommandLine
" > %s/foo/bar/gc
" Press Enter to preview substitutions
Plug 'osyo-manga/vim-over'
" ---------------------------------------------------------
" " ------------------- Most Recently Used Files --------------------
":MRU list
Plug 'yegappan/mru'
" ---------------------------------------------------------
" ------------------- Swap Windows --------------------
" Navigate to a window by its marker
" - opens overlay with window numbers to choose from
" then: s to swap, S to swap and stay, - to previous, -ss swap with previous
Plug 't9md/vim-choosewin'
let g:choosewin_overlay_enable = 1
nmap - <Plug>(choosewin)
" ---------------------------------------------------------
"
"
"
"
" Why Copilot keeps removing my blank lines?
" --- PLUGINS END ---
call plug#end()
" ==============================================================================
" Name: purify
" Author: Kyoz
" Repository: https://github.com/kyoz/purify/
" License: The MIT License (MIT)
" Copyright: Kyoz ([email protected])
"
" Clean and beautiful colorscheme for vim (neovim)
" ==============================================================================
highlight clear
if exists('syntax_on')
syntax reset
endif
set background=dark
if &term == 'screen'
set t_Co=256
endif
let g:colors_name = 'purify'
" Color Defines {{{
let s:override_colors = get(g:, 'purify_override_colors', {})
let s:colors = {
\ 'black': get(s:override_colors, 'black', { 'gui': '#282C34', 'cterm': '235' }),
\ 'white': get(s:override_colors, 'white', { 'gui': '#FFFFFF', 'cterm': '15' }),
\ 'red': get(s:override_colors, 'red', { 'gui': '#FF0000', 'cterm': '196' }),
\ 'green': get(s:override_colors, 'green', { 'gui': '#5FFF87', 'cterm': '84' }),
\ 'blue': get(s:override_colors, 'blue', { 'gui': '#5FAFFF', 'cterm': '75' }),
\ 'yellow': get(s:override_colors, 'yellow', { 'gui': '#FFFF87', 'cterm': '228' }),
\ 'pink': get(s:override_colors, 'pink', { 'gui': '#FF79C6', 'cterm': '212' }),
\ 'salmon': get(s:override_colors, 'salmon', { 'gui': '#FF875F', 'cterm': '209' }),
\ 'purple': get(s:override_colors, 'purple', { 'gui': '#AF87FF', 'cterm': '141' }),
\ 'dark_yellow': get(s:override_colors, 'dark_yellow', { 'gui': '#D19A66', 'cterm': '173' }),
\ 'comment_grey': get(s:override_colors, 'comment_grey', { 'gui': '#5F5F87', 'cterm': '61' }),
\ 'cursor_grey': get(s:override_colors, 'cursor_grey', { 'gui': '#2C323C', 'cterm': '236' }),
\ 'gutter_grey_fg': get(s:override_colors, 'gutter_grey_fg', { 'gui': '#4B5263', 'cterm': '238' }),
\ 'blur_grey': get(s:override_colors, 'blur_grey', { 'gui': '#3B4048', 'cterm': '238' }),
\ 'menu_grey': get(s:override_colors, 'menu_grey', { 'gui': '#3E4452', 'cterm': '237' }),
\ 'visual_grey': get(s:override_colors, 'visual_grey', { 'gui': '#3E4452', 'cterm': '237' }),
\ 'visual_black': get(s:override_colors, 'visual_black', { 'gui': 'NONE', 'cterm': 'NONE' }),
\ 'none': get(s:override_colors, 'none', { 'gui': 'NONE', 'cterm': 'NONE' })
\ }
" Main colors
let s:black = s:colors.black
let s:white = s:colors.white
let s:red = s:colors.red
let s:green = s:colors.green
let s:blue = s:colors.blue
let s:yellow = s:colors.yellow
let s:pink = s:colors.pink
let s:salmon = s:colors.salmon
let s:purple = s:colors.purple
let s:dark_yellow = s:colors.dark_yellow
" Other colors
let s:comment_grey = s:colors.comment_grey
let s:cursor_grey = s:colors.cursor_grey
let s:gutter_grey_fg = s:colors.gutter_grey_fg
let s:blur_grey = s:colors.blur_grey
let s:menu_grey = s:colors.menu_grey
let s:visual_grey = s:colors.visual_grey
let s:visual_black = s:colors.visual_black
let s:none = s:colors.none
" }}}
" Styles Defines {{{
if !exists('g:purify_bold')
let g:purify_bold = 1
endif
if !exists('g:purify_italic')
let g:purify_italic = 1
endif
if !exists('g:purify_underline')
let g:purify_underline = 1
endif
if !exists('g:purify_undercurl') && g:purify_underline != 0
let g:purify_undercurl = 1
endif
if !exists('g:purify_inverse')
let g:purify_inverse = 1
endif
let s:styles = {
\ 'bold': g:purify_bold == 1 ? 'bold' : 0,
\ 'italic': g:purify_italic == 1 ? 'italic' : 0,
\ 'underline': g:purify_underline == 1 ? 'underline' : 0,
\ 'undercurl': g:purify_undercurl == 1 ? 'undercurl' : 0,
\ 'inverse': g:purify_inverse == 1 ? 'inverse' : 0,
\ }
" }}}
" Functions {{{
function! s:hi(group_name, options)
let l:fg = has_key(a:options, 'fg') ? copy(a:options.fg) : s:none
let l:bg = has_key(a:options, 'bg') ? a:options.bg : s:none
let l:sp = has_key(a:options, 'sp') ? a:options.sp : s:none
let l:style_list = filter(has_key(a:options, 'styles') ? a:options.styles : [], 'type(v:val) == 1')
let l:styles = len(l:style_list) > 0 ? join(l:style_list, ',') : 'NONE'
if l:sp.gui !=# 'NONE' && l:fg.gui ==# 'NONE' && !has('gui_running')
let l:fg = copy(l:sp)
endif
execute 'highlight!' a:group_name
\ 'guifg=' l:fg.gui 'ctermfg=' l:fg.cterm
\ 'guibg=' l:bg.gui 'ctermbg=' l:bg.cterm
\ 'gui=' l:styles 'cterm=' l:styles
\ 'guisp=' l:sp.gui
endfunction
" }}}
" Syntax Groups (:h w18) {{{
call s:hi('Comment', { 'fg': s:comment_grey, 'styles': [s:styles.italic] })
call s:hi('Constant', { 'fg': s:yellow })
call s:hi('String', { 'fg': s:yellow })
call s:hi('Character', { 'fg': s:pink })
call s:hi('Number', { 'fg': s:salmon })
call s:hi('Boolean', { 'fg': s:salmon })
call s:hi('Float', { 'fg': s:salmon })
call s:hi('Identifier', { 'fg': s:blue, 'styles': [s:styles.italic] })
call s:hi('Function', { 'fg': s:blue })
call s:hi('Statement', { 'fg': s:pink, 'styles': [s:styles.italic] })
call s:hi('Conditional', { 'fg': s:pink, 'styles': [s:styles.italic] })
call s:hi('Repeat', { 'fg': s:pink, 'styles': [s:styles.italic] })
call s:hi('Label', { 'fg': s:pink, 'styles': [s:styles.italic] })
call s:hi('Operator', { 'fg': s:pink })
call s:hi('Keyword', { 'fg': s:blue, 'styles': [s:styles.italic] })
call s:hi('Exception', { 'fg': s:pink, 'styles': [s:styles.italic] })
call s:hi('PreProc', { 'fg': s:pink })
call s:hi('Include', { 'fg': s:pink })
call s:hi('Define', { 'fg': s:pink })
call s:hi('Macro', { 'fg': s:pink })
call s:hi('PreCondit', { 'fg': s:pink })
call s:hi('Type', { 'fg': s:green, 'styles': [s:styles.italic] })
call s:hi('StorageClass', { 'fg': s:green, 'styles': [s:styles.italic] })
call s:hi('Structure', { 'fg': s:green, 'styles': [s:styles.italic] })
call s:hi('Typedef', { 'fg': s:green, 'styles': [s:styles.italic] })
call s:hi('Special', { 'fg': s:yellow })
call s:hi('SpecialChar', { 'fg': s:salmon, 'styles': [s:styles.underline] })
call s:hi('Tag', { 'fg': s:yellow, 'styles': [s:styles.underline] })
call s:hi('Delimiter', { 'fg': s:pink })
call s:hi('SpecialComment', { 'fg': s:salmon, 'styles': [s:styles.underline] })
call s:hi('Debug', { 'fg': s:yellow })
call s:hi('Underlined', { 'fg': s:blue })
call s:hi('Ignore', {})
call s:hi('Error', { 'fg': s:white, 'bg': s:red })
call s:hi('Todo', { 'fg': s:black, 'bg': s:yellow })
" }}}
" Highlighting Groups (:h highlight-groups) {{{
call s:hi('ColorColumn', { 'bg': s:cursor_grey })
call s:hi('Conceal', {})
call s:hi('Cursor', { 'fg': s:black, 'bg': s:blue })
call s:hi('CursorIM', {})
call s:hi('CursorColumn', {})
call s:hi('CursorLine', { 'styles': [s:styles.underline] })
call s:hi('Directory', { 'fg': s:blue })
call s:hi('ErrorMsg', { 'fg': s:salmon })
call s:hi('VertSplit', { 'fg': s:pink })
call s:hi('Folded', { 'fg': s:comment_grey })
call s:hi('FoldColumn', {})
call s:hi('SignColumn', {})
call s:hi('IncSearch', { 'fg': s:yellow, 'bg': s:comment_grey })
call s:hi('LineNr', { 'fg': s:gutter_grey_fg })
call s:hi('CursorLineNr', { 'fg': s:yellow })
call s:hi('MatchParen', { 'fg': s:blue, 'styles': [s:styles.underline] })
call s:hi('ModeMsg', {})
call s:hi('MoreMsg', {})
call s:hi('NonText', { 'fg': s:blur_grey })
call s:hi('Normal', {})
call s:hi('Pmenu', { 'bg': s:menu_grey })
call s:hi('PmenuSel', { 'fg': s:black, 'bg': s:blue })
call s:hi('PmenuSbar', { 'bg': s:blur_grey })
call s:hi('PmenuThumb', { 'bg': s:pink })
call s:hi('Question', { 'fg': s:pink })
call s:hi('Search', { 'fg': s:blur_grey, 'bg': s:yellow })
call s:hi('QuickFixLine', { 'fg': s:blur_grey, 'bg': s:blue })
call s:hi('SpecialKey', { 'fg': s:blur_grey })
call s:hi('SpellBad', { 'fg': s:salmon, 'styles': [s:styles.underline] })
call s:hi('SpellCap', { 'fg': s:dark_yellow })
call s:hi('SpellLocal', { 'fg': s:dark_yellow })
call s:hi('SpellRare', { 'fg': s:dark_yellow })
call s:hi('StatusLine', { 'fg': s:white, 'bg': s:cursor_grey })
call s:hi('StatusLineNC', { 'fg': s:comment_grey })
call s:hi('TabLine', { 'fg': s:comment_grey })
call s:hi('TabLineFill', {})
call s:hi('TabLineSel', { 'fg': s:white })
call s:hi('Title', { 'fg': s:green })
call s:hi('Visual', { 'fg': s:visual_black, 'bg': s:visual_grey })
call s:hi('VisualNOS', { 'bg': s:visual_grey })
call s:hi('WarningMsg', { 'fg': s:yellow })
call s:hi('WildMenu', { 'fg': s:black, 'bg': s:blue })
" }}}
" Languages {{{
" HTML {{{
call s:hi('htmlError', { 'fg': s:salmon })
call s:hi('htmlString', { 'fg': s:yellow })
call s:hi('htmlValue', { 'fg': s:yellow })
call s:hi('htmlEndTag', { 'fg': s:blue })
call s:hi('htmlTag', { 'fg': s:blue })
call s:hi('htmlTagN', { 'fg': s:blue })
call s:hi('htmlTagError', { 'fg': s:salmon })
call s:hi('htmlTagName', { 'fg': s:pink })
call s:hi('htmlSpecialChar', { 'fg': s:salmon })
call s:hi('htmlSpecialTagName', { 'fg': s:salmon, 'styles': [s:styles.italic] })
call s:hi('htmlArg', { 'fg': s:green, 'styles': [s:styles.italic] })
call s:hi('htmlEvent', { 'fg': s:green, 'styles': [s:styles.italic] })
call s:hi('htmlEventSQ', { 'fg': s:salmon, 'styles': [s:styles.italic] })
call s:hi('htmlEventDQ', { 'fg': s:salmon, 'styles': [s:styles.italic] })
call s:hi('htmlComment', { 'fg': s:comment_grey })
call s:hi('htmlCommentError', { 'fg': s:salmon })
function! s:overwrite_html_highlight()
call s:hi('javaScript', { 'fg': s:white })
endfunction
augroup purify_html
autocmd!
autocmd Filetype html call s:overwrite_html_highlight()
augroup END
" }}}
" CSS {{{
call s:hi('cssAttrComma', { 'fg': s:pink })
call s:hi('cssAttributeSelector', { 'fg': s:green })
call s:hi('cssBraces', { 'fg': s:blue })
call s:hi('cssComment', { 'fg': s:comment_grey, 'styles': [s:styles.italic] })
call s:hi('cssClassName', { 'fg': s:yellow, 'styles': [s:styles.italic] })
call s:hi('cssClassNameDot', { 'fg': s:pink })
call s:hi('cssDefinition', { 'fg': s:yellow })
call s:hi('cssFontAttr', { 'fg': s:yellow })
call s:hi('cssFontDescriptor', { 'fg': s:yellow })
call s:hi('cssFunctionName', { 'fg': s:blue })
call s:hi('cssIdentifier', { 'fg': s:blue })
call s:hi('cssImportant', { 'fg': s:yellow })
call s:hi('cssInclude', { 'fg': s:white })
call s:hi('cssIncludeKeyword', { 'fg': s:yellow })
call s:hi('cssMediaType', { 'fg': s:yellow })
call s:hi('cssProp', { 'fg': s:white })
call s:hi('cssPseudoClassId', { 'fg': s:blue })
call s:hi('cssSelectorOp', { 'fg': s:blue })
call s:hi('cssSelectorOp2', { 'fg': s:blue })
call s:hi('cssTagName', { 'fg': s:pink, 'styles': [s:styles.italic] })
" }}}
" SASS {{{
call s:hi('sassAmpersand', { 'fg': s:salmon })
call s:hi('sassClass', { 'fg': s:yellow, 'styles': [s:styles.italic] })
call s:hi('sassClassChar', { 'fg': s:pink })
call s:hi('sassControl', { 'fg': s:blue })
call s:hi('sassFunctionDecl', { 'fg': s:pink })
call s:hi('sassExtend', { 'fg': s:blue })
call s:hi('sassFor', { 'fg': s:white })
call s:hi('sassFunction', { 'fg': s:blue })
call s:hi('sassId', { 'fg': s:blue })
call s:hi('sassInclude', { 'fg': s:blue })
call s:hi('sassMedia', { 'fg': s:blue })
call s:hi('sassMediaOperators', { 'fg': s:white })
call s:hi('sassMixin', { 'fg': s:blue })
call s:hi('sassMixinName', { 'fg': s:blue })
call s:hi('sassMixing', { 'fg': s:blue })
call s:hi('sassVariable', { 'fg': s:green })
" }}}
" SCSS {{{
call s:hi('scssExtend', { 'fg': s:blue })
call s:hi('scssImport', { 'fg': s:blue })
call s:hi('scssInclude', { 'fg': s:blue })
call s:hi('scssMixin', { 'fg': s:blue })
call s:hi('scssSelectorName', { 'fg': s:yellow })
call s:hi('scssVariable', { 'fg': s:green })
" }}}
" LESS {{{
call s:hi('lessClass', { 'fg': s:yellow, 'styles': [s:styles.italic] })
call s:hi('lessClassChar', { 'fg': s:pink })
" }}}
" JSON {{{
call s:hi('jsonBraces', { 'fg': s:blue })
call s:hi('jsonString', { 'fg': s:green })
call s:hi('jsonNoise', { 'fg': s:pink })
call s:hi('jsonKeyword', { 'fg': s:pink, 'styles': [s:styles.italic] })
call s:hi('jsonKeywordMatch', { 'fg': s:white, 'styles': [s:styles.italic] })
call s:hi('jsonEscape', { 'fg': s:salmon })
call s:hi('jsonStringSQError', { 'fg': s:red })
call s:hi('jsonSemicolonError', { 'fg': s:red })
call s:hi('jsonTrailingCommaError', { 'fg': s:red })
call s:hi('jsonMissingCommaError', { 'fg': s:red })
" }}}
" XML {{{
call s:hi('xmlTagName', { 'fg': s:pink, 'styles': [s:styles.italic] })
call s:hi('xmlTag', { 'fg': s:blue })
call s:hi('xmlEndTag', { 'fg': s:pink })
call s:hi('xmlNamespace', { 'fg': s:blue })
call s:hi('xmlString', { 'fg': s:yellow })
call s:hi('xmlAttrib', { 'fg': s:green, 'styles': [s:styles.italic] })
call s:hi('xmlComment', { 'fg': s:comment_grey })
call s:hi('xmlError', { 'fg': s:red })
call s:hi('xmlEntity', { 'fg': s:red })
" TODO: need regex to add syntax for close tag ( </ > )
" }}}
" JAVASCRIPT {{{
call s:hi('javaScriptComment', { 'fg': s:comment_grey, 'styles': [s:styles.italic] })
call s:hi('javaScriptLineComment', { 'fg': s:comment_grey, 'styles': [s:styles.italic] })
call s:hi('javaScriptCommentTodo', { 'fg': s:black, 'bg': s:yellow })
call s:hi('javaScriptSpecial', { 'fg': s:yellow })
call s:hi('javaScriptStringS', { 'fg': s:yellow })
call s:hi('javaScriptStringD', { 'fg': s:yellow })
call s:hi('javaScriptCharacter', { 'fg': s:yellow })
call s:hi('javaScriptSpecialCharacter', { 'fg': s:yellow })
call s:hi('javaScriptType', { 'fg': s:green, 'styles': [s:styles.italic] })
call s:hi('javaScriptOperator', { 'fg': s:pink, 'styles': [s:styles.italic] })
call s:hi('javaScriptNull', { 'fg': s:salmon })
call s:hi('javaScriptNumber', { 'fg': s:salmon })
call s:hi('javaScriptRegexpString', { 'fg': s:yellow })
call s:hi('javaScriptStatement', { 'fg': s:pink, 'styles': [s:styles.italic] })
call s:hi('javaScriptFunction', { 'fg': s:blue, 'styles': [s:styles.italic] })
call s:hi('javaScriptBraces', { 'fg': s:blue })
call s:hi('javaScriptParens', { 'fg': s:pink })
call s:hi('javaScriptError', { 'fg': s:white, 'bg': s:red })
call s:hi('javaScrParenError', { 'fg': s:white, 'bg': s:red })
call s:hi('javaScriptException', { 'fg': s:yellow, 'styles': [s:styles.italic] })
call s:hi('javaScriptGlobal', { 'fg': s:blue, 'styles': [s:styles.italic] })
call s:hi('javaScriptMember', { 'fg': s:blue, 'styles': [s:styles.italic] })
call s:hi('javaScriptDeprecated', { 'fg': s:pink, 'styles': [s:styles.italic] })
call s:hi('javaScriptReserved', { 'fg': s:blue, 'styles': [s:styles.italic] })
function! s:overwrite_javascript_highlight()
silent! syn clear javaScriptIdentifier
silent! syn clear javaScriptReserved
call s:hi('javascriptEndColons', { 'fg': s:pink })
call s:hi('javascriptLogicSymbols', { 'fg': s:salmon })
call s:hi('javascriptOpSymbols', { 'fg': s:pink })
call s:hi('javascriptLabel', { 'fg': s:pink, 'styles': [s:styles.italic] })
call s:hi('javaScriptThis', { 'fg': s:blue, 'styles': [s:styles.italic] })
call s:hi('javaScriptCustomIdentifier', { 'fg': s:green, 'styles': [s:styles.italic] })
call s:hi('javaScriptCustomReserved', { 'fg': s:blue, 'styles': [s:styles.italic] })
endfunction
augroup purify_javascript
autocmd!
autocmd Filetype javascript call s:overwrite_javascript_highlight()
augroup END
" }}}
" TYPESCRIPT {{{
" https://github.com/leafgarland/typescript-vim/pull/166
let g:typescript_ignore_browserwords = 1
" https://github.com/leafgarland/typescript-vim
call s:hi('typescriptBrowserObjects', { 'fg': s:blue, 'styles': [s:styles.italic] })
call s:hi('typescriptDOMObjects', { 'fg': s:blue, 'styles': [s:styles.italic] })
call s:hi('typescriptExceptions', { 'fg': s:yellow, 'styles': [s:styles.italic] })
call s:hi('typescriptFuncKeyword', { 'fg': s:blue, 'styles': [s:styles.italic] })
call s:hi('typescriptReserved', { 'fg': s:blue, 'styles': [s:styles.italic] })
call s:hi('typescriptOperator', { 'fg': s:pink, 'styles': [s:styles.italic] })
call s:hi('typescriptOpSymbols', { 'fg': s:pink })
call s:hi('typescriptLogicSymbols', { 'fg': s:salmon })
call s:hi('typescriptEndColons', { 'fg': s:pink })
" }}}
" PYTHON {{{
call s:hi('pythonStatement', { 'fg': s:pink, 'styles': [s:styles.italic] })
call s:hi('pythonConditional', { 'fg': s:pink, 'styles': [s:styles.italic] })
call s:hi('pythonRepeat', { 'fg': s:pink, 'styles': [s:styles.italic] })
call s:hi('pythonOperator', { 'fg': s:pink, 'styles': [s:styles.italic] })
call s:hi('pythonException', { 'fg': s:yellow, 'styles': [s:styles.italic] })
call s:hi('pythonInclude', { 'fg': s:blue, 'styles': [s:styles.italic] })
call s:hi('pythonAsync', { 'fg': s:pink, 'styles': [s:styles.italic] })
call s:hi('pythonDecorator', { 'fg': s:green, 'styles': [s:styles.italic] })
call s:hi('pythonDecoratorName', { 'fg': s:green, 'styles': [s:styles.italic] })
call s:hi('pythonFunction', { 'fg': s:blue, 'styles': [s:styles.italic] })
call s:hi('pythonComment', { 'fg': s:comment_grey, 'styles': [s:styles.italic] })
call s:hi('pythonTodo', { 'fg': s:blur_grey, 'bg': s:yellow })
call s:hi('pythonString', { 'fg': s:yellow })
call s:hi('pythonRawString', { 'fg': s:yellow })
call s:hi('pythonNumber', { 'fg': s:salmon })
call s:hi('pythonBuiltin', { 'fg': s:blue, 'styles': [s:styles.italic] })
call s:hi('pythonExceptions', { 'fg': s:salmon })
call s:hi('pythonSpaceError', { 'fg': s:red })
function! s:overwrite_python_highlight()
call s:hi('pythonBraces', { 'fg': s:blue })
call s:hi('pythonParens', { 'fg': s:pink })
call s:hi('pythonOpSymbols', { 'fg': s:pink })
call s:hi('pythonEndColons', { 'fg': s:pink })
call s:hi('pythonLogicSymbols', { 'fg': s:blue })
endfunction
augroup purify_python
autocmd!
autocmd Filetype python call s:overwrite_python_highlight()
augroup END
" }}}
" GO {{{
call s:hi('goDirective', { 'fg': s:blue, 'styles': [s:styles.italic] })
call s:hi('goDeclaration', { 'fg': s:blue, 'styles': [s:styles.italic] })
call s:hi('goDeclType', { 'fg': s:blue, 'styles': [s:styles.italic] })
call s:hi('goStatement', { 'fg': s:pink, 'styles': [s:styles.italic] })
call s:hi('goConditional', { 'fg': s:pink, 'styles': [s:styles.italic] })
call s:hi('goLabel', { 'fg': s:pink, 'styles': [s:styles.italic] })
call s:hi('goRepeat', { 'fg': s:pink, 'styles': [s:styles.italic] })
call s:hi('goType', { 'fg': s:green, 'styles': [s:styles.italic] })
call s:hi('goSignedInts', { 'fg': s:green, 'styles': [s:styles.italic] })
call s:hi('goUnsignedInts', { 'fg': s:green, 'styles': [s:styles.italic] })
call s:hi('goFloats', { 'fg': s:green, 'styles': [s:styles.italic] })
call s:hi('goComplexes', { 'fg': s:green, 'styles': [s:styles.italic] })
call s:hi('goBuiltins', { 'fg': s:blue, 'styles': [s:styles.italic] })
call s:hi('goConstants', { 'fg': s:salmon, 'styles': [s:styles.italic] })
call s:hi('goCharacter', { 'fg': s:yellow })
function! s:overwrite_go_highlight()
call s:hi('goDeclarationOverwrite', { 'fg': s:green, 'styles': [s:styles.italic] })
call s:hi('goBraces', { 'fg': s:blue })
call s:hi('goParens', { 'fg': s:pink })
call s:hi('goOpSymbols', { 'fg': s:pink })
call s:hi('goEndColons', { 'fg': s:pink })
call s:hi('goLogicSymbols', { 'fg': s:blue })
endfunction
augroup purify_go
autocmd!
autocmd Filetype go call s:overwrite_go_highlight()
augroup END
" }}}
" C {{{
call s:hi('cStatement', { 'fg': s:pink, 'styles': [s:styles.italic] })
call s:hi('cLabel', { 'fg': s:pink, 'styles': [s:styles.italic] })
call s:hi('cConditional', { 'fg': s:pink, 'styles': [s:styles.italic] })
call s:hi('cRepeat', { 'fg': s:pink, 'styles': [s:styles.italic] })
call s:hi('cTodo', { 'fg': s:blur_grey, 'bg': s:yellow })
call s:hi('cBadContinuation', { 'fg': s:red })
call s:hi('cSpecial', { 'fg': s:salmon })
call s:hi('cFormat', { 'fg': s:yellow })
call s:hi('cString', { 'fg': s:yellow })
call s:hi('cCppString', { 'fg': s:yellow })
call s:hi('cCppSkip', { 'fg': s:yellow })
call s:hi('cCharacter', { 'fg': s:salmon })
call s:hi('cSpecialCharacter', { 'fg': s:salmon })
call s:hi('cSpecialError', { 'fg': s:red })
call s:hi('cSpaceError', { 'bg': s:red })
call s:hi('cComment', { 'fg': s:comment_grey, 'styles': [s:styles.italic] })
call s:hi('cType', { 'fg': s:green, 'styles': [s:styles.italic] })
call s:hi('cStructure', { 'fg': s:blue, 'styles': [s:styles.italic] })
call s:hi('cStorageClass', { 'fg': s:green, 'styles': [s:styles.italic] })
call s:hi('cConstant', { 'fg': s:salmon })
call s:hi('cDefine', { 'fg': s:blue, 'styles': [s:styles.italic] })
call s:hi('cInclude', { 'fg': s:blue, 'styles': [s:styles.italic] })
call s:hi('cIncluded', { 'fg': s:yellow })
function! s:overwrite_c_highlight()
call s:hi('cDeclarationOverwrite', { 'fg': s:green, 'styles': [s:styles.italic] })
call s:hi('cBraces', { 'fg': s:blue })
call s:hi('cParens', { 'fg': s:pink })
call s:hi('cOpSymbols', { 'fg': s:pink })
call s:hi('cEndColons', { 'fg': s:pink })
call s:hi('cLogicSymbols', { 'fg': s:blue })
endfunction
augroup purify_c
autocmd!
autocmd Filetype c call s:overwrite_c_highlight()
augroup END
" }}}
" CPP {{{
call s:hi('cppStatement', { 'fg': s:pink, 'styles': [s:styles.italic] })
call s:hi('cppAccess', { 'fg': s:blue, 'styles': [s:styles.italic] })
call s:hi('cppModifier', { 'fg': s:blue, 'styles': [s:styles.italic] })
call s:hi('cppType', { 'fg': s:green, 'styles': [s:styles.italic] })
call s:hi('cppExceptions', { 'fg': s:yellow, 'styles': [s:styles.italic] })
call s:hi('cppOperator', { 'fg': s:salmon, 'styles': [s:styles.italic] })
call s:hi('cppStructure', { 'fg': s:blue, 'styles': [s:styles.italic] })
call s:hi('cppConstant', { 'fg': s:salmon, 'styles': [s:styles.italic] })
call s:hi('cppStorageClass', { 'fg': s:salmon, 'styles': [s:styles.italic] })
call s:hi('cppExceptions', { 'fg': s:salmon, 'styles': [s:styles.italic] })
call s:hi('cppBoolean', { 'fg': s:salmon })
call s:hi('cppNumber', { 'fg': s:salmon })
call s:hi('cppMinMax', { 'fg': s:red })
function! s:overwrite_cpp_highlight()
call s:hi('cppDeclarationOverwrite', { 'fg': s:green, 'styles': [s:styles.italic] })
call s:hi('cppBraces', { 'fg': s:blue })
call s:hi('cppParens', { 'fg': s:pink })
call s:hi('cppOpSymbols', { 'fg': s:pink })
call s:hi('cppEndColons', { 'fg': s:pink })
call s:hi('cppLogicSymbols', { 'fg': s:blue })
endfunction
augroup purify_cpp
autocmd!
autocmd Filetype cpp call s:overwrite_cpp_highlight()
augroup END
" }}}
" Ruby {{{
call s:hi('rubyInclude', { 'fg': s:blue, 'styles': [s:styles.italic] })
call s:hi('rubyStringDelimiter', { 'fg': s:yellow })
function! s:overwrite_ruby_highlight()
call s:hi('rubyBraces', { 'fg': s:blue })
call s:hi('rubyParens', { 'fg': s:pink })
call s:hi('rubyOpSymbols', { 'fg': s:pink })
call s:hi('rubyEndColons', { 'fg': s:pink })
call s:hi('rubyLogicSymbols', { 'fg': s:blue })
endfunction
augroup purify_ruby
autocmd!
autocmd Filetype ruby call s:overwrite_ruby_highlight()
augroup END
" }}}
" }}}
" Frameworks {{{
" Reactjs {{{
" Support for 'MaxMEllon/vim-jsx-pretty'
call s:hi('jsxTag', { 'fg': s:white })
call s:hi('jsxTagName', { 'fg': s:pink })
call s:hi('jsxComponentName', { 'fg': s:salmon })
call s:hi('jsxOpenPunct', { 'fg': s:blue })
call s:hi('jsxClosePunct', { 'fg': s:blue })
call s:hi('jsxCloseString', { 'fg': s:blue })
function! s:overwrite_javascriptreact_highlight()
silent! syn clear javaScriptIdentifier
silent! syn clear javaScriptReserved
call s:hi('jsxDeclarationOverwrite', { 'fg': s:green, 'styles': [s:styles.italic] })
call s:hi('jsxBraces', { 'fg': s:blue })
call s:hi('jsxParens', { 'fg': s:pink })
call s:hi('jsxOpSymbols', { 'fg': s:pink })
call s:hi('jsxEndColons', { 'fg': s:pink })
call s:hi('jsxLogicSymbols', { 'fg': s:blue })
call s:hi('jsxCustomIdentifier', { 'fg': s:green, 'styles': [s:styles.italic] })
call s:hi('jsxCustomReserved', { 'fg': s:blue, 'styles': [s:styles.italic] })
" Javascript init (in case you open jsx file only)
call s:hi('javascriptEndColons', { 'fg': s:pink })
call s:hi('javascriptLogicSymbols', { 'fg': s:salmon })
call s:hi('javascriptOpSymbols', { 'fg': s:pink })
call s:hi('javascriptLabel', { 'fg': s:pink, 'styles': [s:styles.italic] })
call s:hi('javaScriptThis', { 'fg': s:blue, 'styles': [s:styles.italic] })
call s:hi('javaScriptCustomIdentifier', { 'fg': s:green, 'styles': [s:styles.italic] })
call s:hi('javaScriptCustomReserved', { 'fg': s:blue, 'styles': [s:styles.italic] })
endfunction
augroup purify_jsx
autocmd!
autocmd Filetype javascriptreact call s:overwrite_javascriptreact_highlight()
augroup END
" }}}
" }}}
" Plugins {{{
" fzf.vim
" https://github.com/junegunn/fzf/wiki/Color-schemes
let g:fzf_colors =
\ { 'fg': ['fg', 'Normal'],
\ 'bg': ['bg', 'Normal'],
\ 'hl': ['fg', 'String'],
\ 'hl+': ['fg', 'Statement'],
\ 'fg+': ['fg', 'CursorLine', 'CursorColumn', 'Normal'],
\ 'bg+': ['bg', 'CursorLine', 'CursorColumn'],
\ 'info': ['fg', 'Keyword'],
\ 'border': ['fg', 'Ignore'],
\ 'prompt': ['fg', 'Statement'],
\ 'pointer': ['fg', 'Statement'],
\ 'marker': ['fg', 'Keyword'],
\ 'spinner': ['fg', 'Label'],
\ 'header': ['fg', 'Comment'] }
" vim-easymotion
call s:hi("EasyMotionTarget", { "fg": s:green })
call s:hi("EasyMotionTarget2First", { "fg": s:green })
call s:hi("EasyMotionTarget2Second", { "fg": s:blue })
call s:hi("EasyMotionShade", { "fg": s:comment_grey })
" gitsigns.nvim
call s:hi('GitSignsAdd', { 'fg': s:green })
call s:hi('GitSignsChange', { 'fg': s:dark_yellow })
call s:hi('GitSignsDelete', { 'fg': s:red })
" }}}
" Try setting background and foreground colors if user using GUI version
if has("gui_running") || exists('g:GuiLoaded')
hi Normal guifg=#FFFFFF
hi Normal guibg=#252834
endif
execute 'set background=dark'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment