commit 4989797e9117dfff2f0c9523e0b942f7337e9100 Author: Just Midi Date: Mon Aug 9 07:44:56 2021 +0000 My first lua config Directories are self explanatory + ui/* for ui stuff + statusbar in ui + keymap/* for keymaps + general for very minimal, required stuff diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a11f5bf --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +plugins/* +.hidden/* diff --git a/README.md b/README.md new file mode 100644 index 0000000..b091c6a --- /dev/null +++ b/README.md @@ -0,0 +1,25 @@ +# Vim Config + +My vim config written in lua designed for *smol boi minimal vibes* + +Most of the code is in separate modules. Each will later be its own true plugin. + + +## OLD +### TODO + +Remove colemak w/ opt-in +```sh +sh -c 'curl -fLo \ +"${XDG_DATA_HOME:-$HOME/.local/share}"/nvim/site/autoload/plug.vim --create-dirs \ +https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim' +``` +`pip3 install --user pynvim`` + +```vim +:PlugInstall +:UpdateRemotePlugins +``` + +> /usr/share/dict/words +Install `words` diff --git a/init.lua b/init.lua new file mode 100755 index 0000000..ffd2462 --- /dev/null +++ b/init.lua @@ -0,0 +1,3 @@ +require('general') +require('keymap') +require('ui') diff --git a/lua/general.lua b/lua/general.lua new file mode 100755 index 0000000..6443d94 --- /dev/null +++ b/lua/general.lua @@ -0,0 +1,29 @@ +-- see `:help` for any questions +-- use `&` to show value of vimscript variable + + +-- API -- +local o = vim.o -- options +local go = vim.go -- only-global options +local bo = vim.bo -- buffer local options +local wo = vim.wo -- window local options + +local cmd = vim.cmd -- vim commands +local fn = vim.fn -- vim functions +local opt = vim.opt -- vim option object + +local g = vim.g -- global variables +local b = vim.b -- buffer local variables +local w = vim.w -- window local variables +local t = vim.t -- tab local variables +local v = vim.v -- variables +local env = vim.env -- environment variables + + +vim.g.mapleader = ' ' + +o.mouse = '' -- mouse off + +bo.fileformat = 'unix' + +o.hidden = true diff --git a/lua/keymap/functional.lua b/lua/keymap/functional.lua new file mode 100755 index 0000000..6731a23 --- /dev/null +++ b/lua/keymap/functional.lua @@ -0,0 +1,6 @@ +function bind(f,...) + local args={...} + return function(...) + return f(unpack(args),...) + end +end diff --git a/lua/keymap/init.lua b/lua/keymap/init.lua new file mode 100755 index 0000000..8d389a3 --- /dev/null +++ b/lua/keymap/init.lua @@ -0,0 +1,331 @@ +-- see `:help` for any questions +-- use `&` to show value of vimscript variable + +require('keymap/functional') + +-- API -- +local o = vim.o -- options +local go = vim.go -- only-global options +local bo = vim.bo -- buffer local options +local wo = vim.wo -- window local options + +local cmd = vim.cmd -- vim commands +local fn = vim.fn -- vim functions +local opt = vim.opt -- vim option object + +local g = vim.g -- global variables +local b = vim.b -- buffer local variables +local w = vim.w -- window local variables +local t = vim.t -- tab local variables +local v = vim.v -- variables +local env = vim.env -- environment variables + + +local layouts = { + 'qwerty', + 'colemak' +} +local layout = layouts[2] + +local map = vim.api.nvim_set_keymap + +local function modes_map(modes) + local functions = {} + for _,mode in pairs(modes) do + table.insert(functions, bind(map,mode)) + end + return functions +end + +local function keys_modes_map(modes, new_keys, old_keys) + for i = 1, #new_keys do + for _,f in pairs(modes_map(modes)) do + f(new_keys[i], old_keys[i], {noremap = true}) + end + end +end + +local nvo = {'n','v','o'} + +if layout == 'qwerty' then + -- + -- Qwerty: General Bindings + -- + + -- Splits + for _,key in pairs({'j','k','l','J','K','L'}) do + for _,f in pairs(modes_map({'n', 'v'})) do + f('w'..key, ''..key, {noremap = true}) + end + end + + -- + -- Qwerty: Plugin Bindings + -- + + -- NERDTree defaults + vim.g.NERDTreeMapOpenSplit = 'i' -- i + vim.g.NERDTreeMapPreviewSplit = 'I' -- gi + vim.g.NERDTreeMapJumpFirstChild = 'K' -- K + vim.g.NERDTreeMapJumpLastChild = 'J' -- J + vim.g.NERDTreeMapJumpNextSibling = '' -- . + vim.g.NERDTreeMapJumpPrevSibling = '' -- + vim.g.NERDTreeMapChangeRoot = 'l' -- C + -- see "All layout" bindings too + +elseif layout == 'colemak' then + -- + -- Colemak: General Bindings + -- + + -- Motion + -- up(e) down(n) left(h) right(i) + keys_modes_map( + nvo, + {'h','n','e','i'}, + {'h','j','k','l'} + ) + + -- word(y) WORD(Y) back(l) BACK(L) end(u) END(U) + keys_modes_map( + nvo, + {'l','L','u','U','y','Y'}, + {'b','B','e','E','w','W'} + ) + + -- (a)ppend (r)eplace in(s)ert change(w) + keys_modes_map( + {'n'}, + {'s','S'}, -- see Visual Line Mode Patch + {'i','I'} + ) + keys_modes_map( + nvo, + {'w','W'}, + {'c','C'} + ) + + -- (c)opy (p)aste cut(x,d) + keys_modes_map( + nvo, + {'c','C'}, + {'y','Y'} + ) + + -- (u)ndo (r)edo + local c_undo_redo = {'z','gz','Z'} + keys_modes_map( + {'n'}, + c_undo_redo, + {'u','U','redo' + } + ) + + -- Visual Line Mode Patch + vim.cmd([[ + xnoremap s (mode() =~# "[V]" ? "\0o$I" : "I") + xnoremap S (mode() =~# "[V]" ? "\0o$I" : "I") + ]]) + + -- (g)oto + -- ge = visual line up + -- gn = visual line down + keys_modes_map( + nvo, + {'ge','gn'}, + {'gk','gj'} + ) + + -- Search + -- (f)ind (F)ind (t)il (T)il next(k) prev(K) + keys_modes_map( + nvo, + {'k','K'}, + {'n','N'} + ) + + -- Text Objects + -- inner(s) (a) + map('o', 's', 'i', {noremap = true}) + + -- Folds + keys_modes_map( + {'n','x'}, + {'j','jn','je','jo','jc','ja'}, + {'z','zn','ze','zo','zc','za'} + ) + + -- Help(B) + map('n', 'B', 'K', {noremap = true}) + + -- Splits + local split = { + colemak = {'n','e','i','N','E','I'}, + qwerty = {'j','k','l','J','K','L'} + } + for i = 1, #split.colemak do + for _,f in pairs(modes_map({'n','v'})) do + f('w'..split.colemak[i], ''..split.qwerty[i], {noremap = true}) + end + end + + -- Screen / Scroll / Page + -- H = top screen + -- M = mid screen + -- I = bottom screen + -- E = half page up + -- N = half page down + keys_modes_map( + {'n','v'}, + {'I','E', 'N'}, + {'L','',''} + ) + + -- + -- Colemak: Plugin Bindings + -- + + -- NERDTree defaults + vim.g.NERDTreeMapOpenSplit = 's' -- i + vim.g.NERDTreeMapPreviewSplit = 'S' -- gi + vim.g.NERDTreeMapJumpFirstChild = 'E' -- K + vim.g.NERDTreeMapJumpLastChild = 'N' -- J + vim.g.NERDTreeMapJumpNextSibling = '' -- . + vim.g.NERDTreeMapJumpPrevSibling = '' -- + vim.g.NERDTreeMapChangeRoot = 'i' -- C + -- see "All layout" bindings too + +end + +-- +-- All layouts: General Bindings +-- + +-- Splits +for _,key in pairs({'h','H','t','q',''}) do + for _,f in pairs(modes_map({'n', 'v'})) do + if key ~= 't' then + f('w'..key, ''..key, {noremap = true}) + else + f('wt', 'T', {noremap = true}) + end + end +end + +-- Search +keys_modes_map( + {'n','v'}, + {'/', '?'}, + {'q/i','q?i'} +) + +-- Remove left over search highlights +map('n', '', ':nohlsearch', {noremap = true}) + +-- Move current line to center of screen +map('n', 'm', 'z.', {noremap = true}) + +-- Buffers +local buffer_keys = { + new = {'',''}, + old = {'n', 'p', 'd'} +} +for i = 1, #buffer_keys.new do + for _,f in pairs(modes_map({'n','v','x'})) do + f( + ''..buffer_keys.new[i], + ':b'..buffer_keys.old[i]..'', + {noremap = true} + ) + end +end + +-- Command mode +keys_modes_map( + {'n', 'v', 'x'}, + {':', ';;', ';e', ';h', ';v'}, + {'q:i','q:i!','q:ie term://','q:isp term://','q:ivs term://'} +) + +-- Filetype specific +cmd('autocmd FileType zig lua zig_maps()') +function zig_maps() + map('n', 'ft', ':vertical !zig test %', {noremap = true}) + map('n', 'fr', ':vertical !zig run %', {noremap = true}) +end + +-- +-- All layouts: Plugin Bindings +-- + +-- LSP +function lsp_shortcuts() + local lsp_commands = { + new = {'d','r','f','t','x','a','c','C','h','s','m'}, + old = { + '#textDocument_definition', -- d + '#textDocument_rename', -- r + '#textDocument_formatting', -- f + '#textDocument_typeDefinition', -- t + '#textDocument_references', -- x + '_workspace_applyEdit', -- a + '#textDocument_completion', -- c + '#textDocument_codeAction', -- C + '#textDocument_hover', -- h + '_textDocument_documentSymbol', -- s + '_contextMenu' -- m + } + } + for i = 1, #lspcommands.new do + for _,f in pairs(modes_map({'n'})) do + f('l'..key_pair.new[i], + ':call LanguageClient'..key_pair.old[i]..'()', {noremap = true}) + end + end +end + +-- NERDTree defaults +map('n', 'n', ':NERDTree', {noremap = true}) +vim.g.NERDTreeMapActivateNode = 'o' -- o +vim.g.NERDTreeMapPreview = 'go' -- go +vim.g.NERDTreeMapOpenInTab = 't' -- t +vim.g.NERDTreeMapOpenInTabSilent = 'T' -- T +vim.g.NERDTreeMapOpenVSplit = 'v' -- s +vim.g.NERDTreeMapPreviewVSplit = 'V' -- gs +vim.g.NERDTreeMapCustomOpen = '' -- +vim.g.NERDTreeMapOpenRecursively = 'O' -- O +vim.g.NERDTreeMapCloseDir = 'x' -- x +vim.g.NERDTreeMapCloseChildren = 'X' -- X +vim.g.NERDTreeMapOpenExpl = '' -- e +vim.g.NERDTreeMapDeleteBookmark = 'd' -- D +vim.g.NERDTreeMapJumpRoot = 'P' -- P +vim.g.NERDTreeMapJumpParent = 'p' -- p +vim.g.NERDTreeMapUpdir = 'h' -- u +vim.g.NERDTreeMapUpdirKeepOpen = 'H' -- U +vim.g.NERDTreeMapRefresh = 'r' -- r +vim.g.NERDTreeMapRefreshRoot = 'R' -- R +vim.g.NERDTreeMapMenu = 'm' -- m +vim.g.NERDTreeMapChdir = 'c' -- cd +vim.g.NERDTreeMapCWD = 'C' -- CD +vim.g.NERDTreeMapToggleHidden = '.' -- I +vim.g.NERDTreeMapToggleFilters = 'F' -- f +vim.g.NERDTreeMapToggleFiles = 'f' -- F +vim.g.NERDTreeMapToggleBookmarks = 'b' -- B +vim.g.NERDTreeMapQuit = 'q' -- q +vim.g.NERDTreeMapToggleZoom = 'z' -- A +vim.g.NERDTreeMapHelp = '?' -- ? + +-- Limelight +map('n', 'ul', ':call LimelightToggle()', {noremap = true}) + +-- Transparent +map('n', 'ut', ':TransparentToggle', {noremap = true}) diff --git a/lua/ui/init.lua b/lua/ui/init.lua new file mode 100755 index 0000000..352eca9 --- /dev/null +++ b/lua/ui/init.lua @@ -0,0 +1,113 @@ +-- see `:help` for any questions +-- use `&` to show value of vimscript variable + +require('ui/statusbar') + +-- API -- +local o = vim.o -- options +local go = vim.go -- only-global options +local bo = vim.bo -- buffer local options +local wo = vim.wo -- window local options + +local cmd = vim.cmd -- vim commands +local fn = vim.fn -- vim functions +local opt = vim.opt -- vim option object + +local g = vim.g -- global variables +local b = vim.b -- buffer local variables +local w = vim.w -- window local variables +local t = vim.t -- tab local variables +local v = vim.v -- variables +local env = vim.env -- environment variables + + + +o.showcmd = true +wo.cursorline = true +cmd 'filetype plugin indent on' +o.lazyredraw = true +o.showmatch = true -- matching bracket + + +-- Completion Menu +o.wildmenu = true +o.wildmode = 'list:longest,full' + + +-- Character Representation +o.sbr = '…' -- line wrap character +o.list = true +opt.listchars = { -- white space representation + tab = '▸ ', + trail = '•', + nbsp = '␣', + extends = '⟩', + precedes = '⟨' +} + + +-- Hybrid Numbers +function hybrid_numbers(x) + wo.number = true + wo.relativenumber = x +end +cmd([[ +autocmd BufEnter,FocusGained,InsertLeave * lua hybrid_numbers(true) +autocmd BufLeave,FocusLost,InsertEnter * lua hybrid_numbers(false) +]]) + + +-- Search +o.incsearch = true -- show matching patterns +o.hlsearch = true -- highlight all patterns + + +-- Status Bar +o.laststatus = 2 -- always visible +vim.o.statusline = "%!luaeval('status_bar()')" + + +-- Tabs +local indent_size = 4 --change to filetype +opt.expandtab = true -- tab key inserts spaces +opt.tabstop = indent_size +opt.shiftwidth = indent_size +opt.softtabstop = 0 -- to disable +opt.smarttab = true + +--adjust to filetype +function no_ro_retab() + if vim.inspect(opt.readonly:get()) == false then + cmd '%retab' + end +end +cmd 'autocmd BufReadPost,BufWritePre,BufWritePost,BufNewFile * lua no_ro_retab()' + + +-- Text Width +wo.wrap = true +wo.linebreak = true +bo.textwidth = 70 + +bo.formatoptions = table.concat({ + 'j', -- remove comment when joining lines + 'w', -- non-white space at end of line means end of paragraph + 'c', -- insert comment when auto wrapping textwidth + 'r', -- insert comment after hitting + 'o', -- insert comment after hitting "o" + 'q', -- format comments with "gq" + 'l' -- long lines are not broken in insert mode +}) + +cmd([[ +autocmd BufEnter * highlight OverLength ctermbg=darkgrey guibg=#592929 +autocmd BufEnter * match OverLength /\%71v.*/ +]]) --rewrite in lua + + +--WIP +-- Filetype: txt, md, tex +-- break lines, autowrap, autoformat, recognize numbered lists +--fix before enabling +--autocmd BufRead,BufNewFile *.md,*.txt,*.tex set fo-=l +--autocmd BufRead,BufNewFile *.md,*.txt,*.tex set fo+=tan diff --git a/lua/ui/statusbar.lua b/lua/ui/statusbar.lua new file mode 100755 index 0000000..30b742a --- /dev/null +++ b/lua/ui/statusbar.lua @@ -0,0 +1,113 @@ +-- see `:help` for any questions +-- use `&` to show value of vimscript variable + +-- API -- +local o = vim.o -- options +local go = vim.go -- only-global options +local bo = vim.bo -- buffer local options +local wo = vim.wo -- window local options + +local cmd = vim.cmd -- vim commands +local fn = vim.fn -- vim functions +local opt = vim.opt -- vim option object + +local g = vim.g -- global variables +local b = vim.b -- buffer local variables +local w = vim.w -- window local variables +local t = vim.t -- tab local variables +local v = vim.v -- variables +local env = vim.env -- environment variables + + +--Later generalize into plugin +-- read from bottom up to understand `status_bar()` + +local function file_state() + if vim.bo.modified then + return "+" + elseif vim.bo.readonly then + return "-" + end + return "" +end + +local function diagnostics() + local buffer_number = vim.fn.bufnr('%') + local severity_levels = { + -- level,prefix + errors = {'Error', 'E:'}, + warnings = {'Warning', 'W:'}, + info = {'Information', 'I:'}, + hints = {'Hint', 'H:'} + } + local out = '' + for _,v in pairs(severity_levels) do + local d = vim.lsp.diagnostic.get_count( + buffer_number, + v[1] -- level + ) + if d > 0 then + out = out .. v[2] .. d .. ' ' + end + end + return out +end + +local function highlight(group, color) + cmd('highlight ' .. group .. ' cterm='..color .. ' gui='..color) +end + +highlight('StatusLine', 'bold,reverse') +highlight('StatusLineDark', 'bold') + +local light_highlight = '%#StatusLine#' +local dark_highlight = '%#StatusLineDark#' + +function section(items) + local out = '' + for _,item in pairs(items) do + if item ~= '' and item ~= nil then + if out == '' then + out = item + else + out = out .. ' | ' .. item + end + end + end + return ' ' .. out .. ' ' +end + +function sections(items) + local out = {} + local n = 1 + for _,item in pairs(items) do + if item == '%=' then + table.insert(out, item) + n = 1 -- reset coloring at different parts + else + if (n % 2) == 1 then + table.insert(out, light_highlight..section(item)) + else + table.insert(out, dark_highlight..section(item)) + end + n = n + 1 + end + end + return out +end + +function status_bar() + return table.concat(sections({ + -- Stage Left + {'%f', file_state()}, + {diagnostics()}, + '%=', + -- Stage Right + { + vim.b.gitsigns_status, + vim.bo.filetype + }, + {'%p%%'}, + {'%c,%l'} + })) +end