require('vis') require('plugins/vis-ctags') local build = require('build') local pickers = require('pickers') -- --------------------------------------------------------------------------- -- Global options, key mappings and commands -- --------------------------------------------------------------------------- vis.events.subscribe(vis.events.INIT, function() vis:command('set escdelay 1') vis:command('set autoindent off') vis:command('set ignorecase on') vis:command('set theme custom_zen') -- jump list vis:map(vis.modes.NORMAL, "", "g>") vis:map(vis.modes.NORMAL, "", "g<") -- pickers vis:map(vis.modes.NORMAL, '', pickers.files, 'Fuzzy find / create a file') vis:map(vis.modes.NORMAL, '', pickers.grep, 'Live grep the project with ripgrep') vis:map(vis.modes.VISUAL, '', pickers.grep_selection, 'Live grep for the selected text') vis:map(vis.modes.NORMAL, '', pickers.fm, 'terminal file manager') vis:map(vis.modes.NORMAL, '', pickers.errors, 'Browse errors from the last build') -- picker commands vis:command_register('files', function() pickers.files() return true end, 'Fuzzy find / create a file') vis:command_register('grep', function() pickers.grep() return true end, 'Live grep the project with ripgrep') vis:command_register('fm', function() pickers.fm() return true end, 'Pick a file with a terminal file manager') vis:command_register('git', function() pickers.git() return true end, 'Open gitu') vis:command_register('errors', function() pickers.errors() return true end, 'Browse errors from the last build') -- build.sh setup vis:map(vis.modes.NORMAL, '', function() build.run({}) end, 'Run ./build.sh') vis:command_register('build', function(argv) local args = {} for i = 1, #argv do table.insert(args, argv[i]) end build.run(args) return true end, 'Run ./build.sh with optional flags, e.g :build run') -- system clipboard local function clip_copy() vis:feedkeys(':>wl-copy 2>/dev/null') vis:feedkeys('') -- drop the selection / leave visual mode end local function clip_paste() vis:feedkeys(':') vis:feedkeys('') -- clear any selection left on the pasted text end vis:map(vis.modes.VISUAL, '', clip_copy, 'Copy selection to system clipboard') vis:map(vis.modes.VISUAL, '', clip_paste, 'Paste system clipboard at cursor') vis:map(vis.modes.NORMAL, '', clip_paste, 'Paste system clipboard at cursor') -- ctag navigation vis:map(vis.modes.NORMAL, 'gd', '', 'Go to definition (ctags picker)') end) -- --------------------------------------------------------------------------- -- Per-window options -- --------------------------------------------------------------------------- vis.events.subscribe(vis.events.WIN_OPEN, function(win) vis:command('set tabwidth 4') vis:command('set expandtab on') vis:command('set number on') end) -- --------------------------------------------------------------------------- -- Syntax highlighting: ~/.config/vis/lexers/odin.lua -- --------------------------------------------------------------------------- if vis.ftdetect then -- vis 0.9 and earlier if vis.ftdetect.filetypes then vis.ftdetect.filetypes.odin = { ext = { '%.odin$' } } end end -- --------------------------------------------------------------------------- -- On save: strip trailing spaces/tabs and extra blank lines at the end of -- the file. Skips files where trailing whitespace means something. -- --------------------------------------------------------------------------- local keep_whitespace = { md = true, markdown = true, diff = true, patch = true } vis.events.subscribe(vis.events.FILE_SAVE_PRE, function(file, path) local ext = path and path:match('%.(%w+)$') if ext and keep_whitespace[ext:lower()] then return true end -- trailing spaces/tabs (not \r, so CRLF files stay CRLF); -- read every line first, then rewrite only the ones that changed local trimmed, n = {}, 0 for line in file:lines_iterator() do n = n + 1 local s = line:find('[ \t]+$') if s then trimmed[n] = line:sub(1, s - 1) end end for i, line in pairs(trimmed) do file.lines[i] = line end -- blank lines at the end: keep exactly one final newline local size = file.size local tail = file:content(math.max(0, size - 256), math.min(size, 256)) local extra = tail:match('\n(\n+)$') if extra then file:delete(size - #extra, #extra) end return true end)