diff --git a/LICENSE b/LICENSE index 2071b23..56d72f5 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) +Copyright (c) 2021 FollieHiyuki Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/README.md b/README.md index 35adf29..f2dedb9 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,16 @@ -# dotfiles-ansible +## dotfiles v2 -A lighter version of dotfiles, managed with ansible \ No newline at end of file +This is the continuation of my old dotfiles, which now only contains stuff I really need. +Managed with `ansible`. + +### Notes + +I use Alpine-edge aka. the best binary distro on Earth :). Therefore some tasks won't work on other distros (eg. `apk` tasks) + +### 🌟 Credits + +- [eoli3n/dotfiles](https://github.com/eoli3n/dotfiles) for the idea + +### 📄 License + +MIT diff --git a/dotfiles.yml b/dotfiles.yml new file mode 100644 index 0000000..c087451 --- /dev/null +++ b/dotfiles.yml @@ -0,0 +1,4 @@ +- name: Setup local dotfiles + hosts: localhost + roles: + - nvim diff --git a/hosts b/hosts new file mode 100644 index 0000000..13cfabe --- /dev/null +++ b/hosts @@ -0,0 +1,2 @@ +[local] +localhost ansible_connection=local diff --git a/roles/nvim/files/.luacheckrc b/roles/nvim/files/.luacheckrc new file mode 100644 index 0000000..11c8e2e --- /dev/null +++ b/roles/nvim/files/.luacheckrc @@ -0,0 +1,3 @@ +std = 'min' +cache = true +new_globals = {'vim'} diff --git a/roles/nvim/files/after/ftplugin/json.vim b/roles/nvim/files/after/ftplugin/json.vim new file mode 100644 index 0000000..aab32ce --- /dev/null +++ b/roles/nvim/files/after/ftplugin/json.vim @@ -0,0 +1,15 @@ +setlocal autoindent +setlocal conceallevel=0 +setlocal expandtab +setlocal foldmethod=syntax +setlocal formatoptions=tcq2l +setlocal shiftwidth=4 +setlocal softtabstop=4 +setlocal tabstop=8 + +let s:bufname = expand('%:e') +if s:bufname && s:bufname ==# 'jsonschema' + setlocal shiftwidth=2 + setlocal softtabstop=2 + setlocal tabstop=4 +endif diff --git a/roles/nvim/files/after/ftplugin/jsonc.vim b/roles/nvim/files/after/ftplugin/jsonc.vim new file mode 100644 index 0000000..f413562 --- /dev/null +++ b/roles/nvim/files/after/ftplugin/jsonc.vim @@ -0,0 +1,8 @@ +setlocal autoindent +setlocal conceallevel=0 +setlocal expandtab +setlocal foldmethod=syntax +setlocal formatoptions=tcq2l +setlocal shiftwidth=2 +setlocal softtabstop=2 +setlocal tabstop=4 diff --git a/roles/nvim/files/after/ftplugin/make.vim b/roles/nvim/files/after/ftplugin/make.vim new file mode 100644 index 0000000..691deb7 --- /dev/null +++ b/roles/nvim/files/after/ftplugin/make.vim @@ -0,0 +1,6 @@ +setlocal noexpandtab +" https://mattn.kaoriya.net/software/vim/20070821175457.htm +setlocal isfname-== isfname+=32 isfname-=I isfname-=L +setlocal shiftwidth=2 +setlocal softtabstop=2 +setlocal tabstop=2 \ No newline at end of file diff --git a/roles/nvim/files/after/ftplugin/markdown.vim b/roles/nvim/files/after/ftplugin/markdown.vim new file mode 100644 index 0000000..b39525b --- /dev/null +++ b/roles/nvim/files/after/ftplugin/markdown.vim @@ -0,0 +1,3 @@ +" setlocal spell +setlocal wrap +setlocal nonumber norelativenumber diff --git a/roles/nvim/files/after/ftplugin/tex.vim b/roles/nvim/files/after/ftplugin/tex.vim new file mode 100644 index 0000000..b39525b --- /dev/null +++ b/roles/nvim/files/after/ftplugin/tex.vim @@ -0,0 +1,3 @@ +" setlocal spell +setlocal wrap +setlocal nonumber norelativenumber diff --git a/roles/nvim/files/after/ftplugin/vim.vim b/roles/nvim/files/after/ftplugin/vim.vim new file mode 100644 index 0000000..7664d4d --- /dev/null +++ b/roles/nvim/files/after/ftplugin/vim.vim @@ -0,0 +1,3 @@ +setlocal colorcolumn=120 +setlocal iskeyword+=:,# +setlocal tags+=$DATA_PATH/tags diff --git a/roles/nvim/files/after/ftplugin/yaml.vim b/roles/nvim/files/after/ftplugin/yaml.vim new file mode 100644 index 0000000..a08c872 --- /dev/null +++ b/roles/nvim/files/after/ftplugin/yaml.vim @@ -0,0 +1,7 @@ +setlocal autoindent +setlocal expandtab +setlocal indentkeys-=<:> +setlocal iskeyword+=-,$,# +setlocal shiftwidth=2 +setlocal softtabstop=2 +setlocal tabstop=2 diff --git a/roles/nvim/files/asynctasks.ini b/roles/nvim/files/asynctasks.ini new file mode 100644 index 0000000..37d9cfa --- /dev/null +++ b/roles/nvim/files/asynctasks.ini @@ -0,0 +1,61 @@ +{cmake} + +[project-init] +command=mkdir build && cd build && cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=1 .. && ln -s compile_commands.json .. +cwd= +errorformat= +output=terminal +[project-build] +command=cmake --build build +cwd= +errorformat=%f:%l:%c --> %m +output=terminal +[project-run] +command=build/$(VIM_PRONAME) +cwd= +output=terminal + +{meson} + +[project-init] +command=mkdir build && meson setup --wipe build && ln -s build/compile_commands.json . +cwd= +errorformat= +output=terminal +[project-build] +command=ninja -C build +cwd= +errorformat=%f:%l:%c --> %m +output=terminal +[project-run] +command=build/$(VIM_PRONAME) +cwd= +output=terminal + +{single} + +[file-run] +command="$(VIM_FILEPATH)" +command:c,cpp="$(VIM_PATHNOEXT)" +command:go="$(VIM_PATHNOEXT)" +command:python=python "$(VIM_FILENAME)" +command:make=make -f "$(VIM_FILENAME)" run +command:emake=emake -e "$(VIM_FILENAME)" +command:javascript=node "$(VIM_FILENAME)" +command:lua=lua "$(VIM_FILENAME)" +command:perl=perl "$(VIM_FILENAME)" +command:ruby=ruby "$(VIM_FILENAME)" +command:sh=sh "$(VIM_FILENAME)" +command:zsh=zsh "$(VIM_FILENAME)" +command:bash=bash "$(VIM_FILENAME)" +command:fish=fish "$(VIM_FILENAME)" +command:php=php "$(VIM_FILENAME)" +command:erlang=escript "$(VIM_FILENAME)" +command:ps1=powershell -file "$(VIM_FILENAME)" +command:scala=scala "$(VIM_FILENAME)" +command:haskell=ghci "$(VIM_FILENAME)" +command:applescript=osascript "$(VIM_FILENAME)" +command:vim=:source % +output=terminal +cwd=$(VIM_FILEDIR) +save=2 diff --git a/roles/nvim/files/colors/nord.lua b/roles/nvim/files/colors/nord.lua new file mode 100644 index 0000000..07cb489 --- /dev/null +++ b/roles/nvim/files/colors/nord.lua @@ -0,0 +1 @@ +require('themes').set('nord') diff --git a/roles/nvim/files/colors/onedark.lua b/roles/nvim/files/colors/onedark.lua new file mode 100644 index 0000000..ade657c --- /dev/null +++ b/roles/nvim/files/colors/onedark.lua @@ -0,0 +1 @@ +require('themes').set('onedark') diff --git a/roles/nvim/files/init.lua b/roles/nvim/files/init.lua new file mode 100644 index 0000000..81d1bf5 --- /dev/null +++ b/roles/nvim/files/init.lua @@ -0,0 +1,13 @@ +local async +async = vim.loop.new_async(vim.schedule_wrap(function() + require('autocmd') + require('plugins') + require('mappings') + async:close() +end)) + +local options = require('options') + +options.disable_default_plugins() +options.load_options() +async:send() diff --git a/roles/nvim/files/lua/autocmd.lua b/roles/nvim/files/lua/autocmd.lua new file mode 100644 index 0000000..6a9b5cf --- /dev/null +++ b/roles/nvim/files/lua/autocmd.lua @@ -0,0 +1,37 @@ +local definitions = { + bufs = { + -- Reload vim config automatically + {'BufWritePost', [[$VIM_PATH/{*.vim,*.yaml,vimrc} nested source $MYVIMRC | redraw]]}, + -- Reload Vim script automatically if setlocal autoread + {'BufWritePost,FileWritePost', '*.vim', [[nested if &l:autoread > 0 | source | echo 'source ' . bufname('%') | endif]]}, + -- No undo for temporary files + {'BufWritePre', '/tmp/*', 'setlocal noundofile'}, + {'BufWritePre', 'COMMIT_EDITMSG', 'setlocal noundofile'}, + {'BufWritePre', 'MERGE_MSG', 'setlocal noundofile'}, + {'BufWritePre', '*.tmp', 'setlocal noundofile'}, + {'BufWritePre', '*.bak', 'setlocal noundofile'} + }, + + wins = { + -- Equalize window dimensions when resizing vim window + {'VimResized', '*', 'tabdo wincmd ='}, + -- Force writing shada on leaving nvim + {'VimLeave', '*', [[if has('nvim') | wshada! | else | wviminfo! | endif]]}, + -- Check if file changed when its window is focus, more eager than 'autoread' + {'FocusGained', '* checktime'} + }, + + yank = { + {'TextYankPost', [[* silent! lua vim.highlight.on_yank({higroup='IncSearch', timeout=300})]]} + } +} + +for group_name, definition in pairs(definitions) do + vim.api.nvim_command('augroup ' .. group_name) + vim.api.nvim_command('autocmd!') + for _, def in ipairs(definition) do + local command = table.concat(vim.tbl_flatten{'autocmd', def}, ' ') + vim.api.nvim_command(command) + end + vim.api.nvim_command('augroup END') +end diff --git a/roles/nvim/files/lua/mappings.lua b/roles/nvim/files/lua/mappings.lua new file mode 100644 index 0000000..4dc5e75 --- /dev/null +++ b/roles/nvim/files/lua/mappings.lua @@ -0,0 +1,444 @@ +local api = vim.api +local wk = require('which-key') + +-- Escape to normal mode in terminal buffer +api.nvim_set_keymap('t', '', '', {noremap = true, silent = true}) + +-- Continuous indent +api.nvim_set_keymap('v', '<', '', '>gv', {noremap = true, silent = true}) + +-- Also move up/down virual lines (:set wrap) +api.nvim_set_keymap('n', 'j', 'gj', {noremap = true, silent = true}) +api.nvim_set_keymap('n', 'k', 'gk', {noremap = true, silent = true}) + +-- winshift.nvim +api.nvim_set_keymap('n', '', ':WinShift', {noremap = true, silent = true}) +api.nvim_set_keymap('n', 'm', ':WinShift', {noremap = true, silent = true}) +api.nvim_set_keymap('n', '', ':WinShift left', {noremap = true, silent = true}) +api.nvim_set_keymap('n', '', ':WinShift down', {noremap = true, silent = true}) +api.nvim_set_keymap('n', '', ':WinShift up', {noremap = true, silent = true}) +api.nvim_set_keymap('n', '', ':WinShift right', {noremap = true, silent = true}) + +----------------- +-- Normal mode -- +----------------- +wk.register({ + -- Better Y + Y = {'y$', 'Yank to eol'}, + + -- Easier start and end of line + H = {'^', 'Start of the line'}, + L = {'$', 'End of the line'}, + + -- Close a window + [''] = {'q', 'Quit current window'}, + + -- Close current buffer + [''] = {':bdelete', 'Close current buffer'}, + + -- Copy the whole buffer + [''] = {':%y+', 'Copy whole buffer'}, + + -- Remove trailing whitespace + [''] = {':%s/\\s\\+$//e', 'Remove trailing'}, + + -- Resize buffer + [''] = {':resize -2', 'Resize vertical -2'}, + [''] = {':resize +2', 'Resize vertical +2'}, + [''] = {':vertical resize -2', 'Resize horizontal -2'}, + [''] = {':vertical resize +2', 'Resize horizontal +2'}, + + -- Switch between tabs and spaces + [''] = { + function() + if vim.opt.expandtab:get() then + vim.opt.expandtab = false + vim.opt.smarttab = false + vim.opt.softtabstop = 0 -- reset to default + vim.notify('Indent with Tabs.', vim.log.levels.INFO) + else + vim.opt.expandtab = true + vim.opt.smarttab = true + vim.opt.softtabstop = -1 -- fallback to shiftwidth + vim.notify('Indent with Spaces.', vim.log.levels.INFO) + end + end, + 'Switch indent style' + }, + + -- Naming common keys + ['['] = { + name = 'Block motions (previous)', + d = {':Lspsaga diagnostic_jump_prev', 'Previous diagnostics'}, + g = 'Previous git hunk', + m = 'Previous start of outer class', + M = 'Previous end of outer class', + ['['] = 'Previous start of outer function', + [']'] = 'Previous end of outer function' + }, + [']'] = { + name = 'Block motions (next)', + d = {':Lspsaga diagnostic_jump_next', 'Next diagnostics'}, + g = 'Next git hunk', + m = 'Next start of outer class', + M = 'Next end of outer class', + ['['] = 'Next start of outer function', + [']'] = 'Next end of outer function' + }, + g = { + name = 'Goto motions', + b = { + name = 'Block', + c = 'Comment' + }, + c = { + name = 'Comment', + c = 'Current line' + }, + d = {':lua vim.lsp.buf.definition()', 'Go to definition'}, + D = {':lua vim.lsp.buf.declaration()', 'Go to declaration'}, + i = {':Lspsaga implement', 'Implementations'}, + I = {':Telescope lsp_implementations', 'Implementations (Telescope)'}, + n = { + name = 'Incremental selection', + i = 'Initialize selection' + }, + r = {':TroubleToggle lsp_references', 'References'}, + R = {':Telescope lsp_references', 'References (Telescope)'}, + t = {':TodoTrouble', 'Todo list'} + }, + K = {':Lspsaga hover_doc', 'Hover doc'}, + z = {name = 'Misc utils'}, + + -- Move between tabs + [''] = {':BufferLineCycleNext', 'Next buffer'}, + [''] = {':BufferLineCyclePrev', 'Previous buffer'}, + + -- NvimTree + [''] = {':NvimTreeToggle', 'NvimTree'}, + + -- ToggleTerm + [''] = {':ToggleTerm', 'Toggle terminal'}, + [''] = {':ToggleTerm direction=float', 'Toggle float terminal'}, + + -- hop.nvim + S = {':HopWord', 'Hop to word'}, + [''] = {':HopChar1', 'Hop to character'}, + [''] = {':HopPattern', 'Hop to pattern'} +}) + +----------------- +-- Visual mode -- +----------------- +wk.register({ + a = { + c = 'Outer class', + f = 'Outer function' + }, + + i = { + c = 'Inner class', + f = 'Inner function' + }, + + g = { + c = 'Comment', + n = { + name = 'Incremental selection', + n = 'Increment node', + s = 'Increment scope', + m = 'Decrement node' + } + } +}, {mode = 'v'}) + +----------------------------------- +-- Normal mode (with leader key) -- +----------------------------------- +wk.register({ + b = { + name = 'Buffer', + c = {':ColorizerToggle', 'Colorizer'}, + d = { + name = 'Delete', + a = {':BDelete all', 'All buffers'}, + d = {':BDelete this', 'Current buffer'}, + h = {':BDelete hidden', 'Hidden buffers'}, + n = {':BDelete nameless', 'Buffers without name'}, + o = {':BDelete other', 'Other buffers'} + }, + j = {':BufferLineCyclePrev', 'Previous buffer'}, + k = {':BufferLineCycleNext', 'Next buffer'}, + n = {':enew', 'New buffer'}, + u = {':UndotreeToggle', 'Undotree'} + }, + + d = { + name = 'DAP', + b = 'Toggle breakpoint', + B = 'Set breakpoint with condition', + c = 'Run to cursor', + d = 'Disconnect adapter', + e = 'Hover under cursor (UI)', + f = 'Open float window (UI)', + i = 'Step into function/method', + l = 'List breakpoints', + n = 'Resume the execution', + o = 'Step out of function/method', + r = 'Inspect in REPL', + t = 'Toggle UI', + v = 'Run again 1 step', + z = 'Re-run the last adapter' + }, + + e = { + name = 'Editor', + a = {':EasyAlign', 'Align elements'}, + g = 'Generate annotations', + h = {':TSHighlightCapturesUnderCursor', 'Syntax under cursor'}, + s = {':ISwapWith', 'Swap elements'}, + t = {':Twilight', 'Twilight mode'}, + v = { + function() + local venn_enabled = vim.inspect(vim.b.venn_enabled) + if venn_enabled == 'nil' then + vim.b.venn_enabled = true + vim.api.nvim_command('setlocal virtualedit=all') + -- Draw lines with HJKL keystroke + vim.api.nvim_buf_set_keymap(0, 'n', 'H', 'h:VBox', {noremap = true, silent = true}) + vim.api.nvim_buf_set_keymap(0, 'n', 'J', 'j:VBox', {noremap = true, silent = true}) + vim.api.nvim_buf_set_keymap(0, 'n', 'K', 'k:VBox', {noremap = true, silent = true}) + vim.api.nvim_buf_set_keymap(0, 'n', 'L', 'l:VBox', {noremap = true, silent = true}) + -- Draw boxes by pressing 'f' with visual selection + vim.api.nvim_buf_set_keymap(0, 'v', 'f', ':VBox', {noremap = true, silent = true}) + vim.notify('Virtual box edit enabled.', vim.log.levels.INFO) + else + vim.b.venn_enabled = nil + vim.api.nvim_command('setlocal virtualedit=block') + -- vim.api.nvim_command('mapclear ') -- quicker, but also deletes buf keymap for lsp + vim.api.nvim_buf_del_keymap(0, 'v', 'f') + vim.api.nvim_buf_del_keymap(0, 'n', 'H') + vim.api.nvim_buf_del_keymap(0, 'n', 'J') + vim.api.nvim_buf_del_keymap(0, 'n', 'K') + vim.api.nvim_buf_del_keymap(0, 'n', 'L') + vim.notify('Virtual box edit disabled.', vim.log.levels.INFO) + end + end, + 'Toggle virtual box edit' + }, + z = {':ZenMode', 'Zen mode'} + }, + + -- Telescope + f = { + name = 'Telescope', + a = {':Telescope autocommands', 'Autocommands'}, + b = {':Telescope buffers', 'Buffers'}, + c = {':Telescope commands', 'Commands'}, + d = {':Telescope projects', 'Recent directories'}, + e = {':Telescope file_browser', 'File browser'}, + f = {':Telescope find_files', 'Find files'}, + g = {':Telescope live_grep', 'Live grep'}, + h = {':Telescope help_tags', 'Help tags'}, + i = {':Telescope highlights', 'Highlight groups'}, + j = {':Telescope symbols', 'Pick emojis'}, + k = {':Telescope keymaps', 'Normal keymaps'}, + m = {':Telescope marks', 'Bookmarks'}, + n = {':Telescope man_pages', 'Man pages'}, + o = {':Telescope oldfiles', 'Recent files'}, + p = {':Telescope project display_type=full', 'Projects'}, + r = {':Telescope reloader', 'Reload lua modules'}, + s = {':Telescope treesitter', 'Treesitter'}, + t = {':TodoTelescope', 'Todo list'}, + u = {':Telescope current_buffer_fuzzy_find', 'Search current buffer'}, + v = {':Telescope vim_options', 'Vim options'}, + y = {':Telescope filetypes', 'Filetypes'}, + z = {':Telescope registers', 'Vim registers'} + }, + + -- Git + g = { + name = 'Git', + a = {':Telescope git_stash', 'Stash'}, + b = 'Blame current line', + c = {':Telescope git_bcommits', 'Buffer commits'}, + C = {':Telescope git_commits', 'Commits'}, + m = {':Telescope git_branches', 'Branches'}, + n = {':Neogit', 'Neogit'}, + p = 'Preview hunk', + r = 'Reset hunk', + R = 'Reset all hunks in buffer', + s = 'Stage hunk', + S = 'Stage buffer', + t = {':Telescope git_status', 'Status'}, + u = 'Undo hunk', + U = 'Reset buffer index', + y = 'Get remote url for cursorline', + Y = 'Get remote url' + }, + + -- translate-shell.vim + j = { + name = 'Translate', + t = {':Trans', 'Translate'}, + d = {':TransSelectDirection', 'Translate with direction'}, + r = {'cw=system(\'trans -brief -no-ansi\', getreg(""))[:-2]', 'Translate and replace'}, + c = {'cw=system(\'trans -brief -no-ansi :\', getreg(""))[:-2]', 'Translate and replace with direction'} + }, + + l = { + name = 'LSP', + a = {':lua vim.lsp.buf.add_workspace_folder()', 'Add workspace folder'}, + b = {':TroubleToggle lsp_document_diagnostics', 'Buffer diagnostics'}, + B = {':Telescope lsp_document_diagnostics', 'Buffer diagnostics (Telescope)'}, + c = {':Lspsaga code_action', 'Code action'}, + C = {':Telescope lsp_code_actions', 'Code action (Telescope)'}, + d = {':TroubleToggle lsp_definitions', 'Definitions'}, + D = {':Telescope lsp_definitions', 'Definitions (Telescope)'}, + e = {':Lspsaga show_line_diagnostics', 'Line diagnostics'}, + f = {':Lspsaga lsp_finder', 'Finder'}, + g = {':SymbolsOutline', 'Symbol outline'}, + l = {':TroubleToggle loclist', 'Diagnostics loclist'}, + n = {':Lspsaga rename', 'Rename'}, + o = 'Format buffer', + p = {':Lspsaga preview_definition', 'Preview definition'}, + r = {':lua vim.lsp.buf.remove_workspace_folder()', 'Remove workspace folder'}, + s = {':Telescope lsp_document_symbols', 'Buffer symbols'}, + S = {':Telescope lsp_workspace_symbols', 'Workspace symbols'}, + t = {':TroubleToggle', 'Toggle Trouble'}, + w = {':TroubleToggle lsp_workspace_diagnostics', 'Workspace diagnostics'}, + W = {':Telescope lsp_workspace_diagnostics', 'Workspace diagnostics (Telescope)'}, + x = {':lua vim.lsp.buf.signature_help()', 'Signature help'}, + y = {':lua vim.notify(vim.inspect(vim.lsp.buf.list_workspace_folders()), vim.log.levels.INFO)', 'List workspace folders'} + }, + + p = { + name = 'Find/Replace', + o = 'Open spectre', + p = 'Search in current file', + w = 'Find/replace cursorword' + }, + + r = { + name = 'REST', + c = {'RestNvim', 'Run request under cursor'}, + p = {'RestNvimPreview', 'Preview request cURL command'}, + l = {'RestNvimLast', 'Re-run last request'} + }, + + s = { + name = 'Session', + s = 'Save session for current directory', + d = 'Stop automatically saving', + l = 'Load last session', + r = 'Load session for current directory' + }, + + w = {':WindowPick', 'Pick window'} + +}, {prefix = ''}) + +----------------------------------- +-- Visual mode (with leader key) -- +----------------------------------- +wk.register({ + a = { + name = 'Action', + a = {':EasyAlign', 'Range align'} + }, + + d = { + name = 'DAP', + e = 'Hover on range (UI)' + }, + + g = { + name = 'Git', + r = 'Reset hunk', + s = 'Stage hunk', + y = 'Get remote url for range' + }, + + j = { + name = 'Translate', + t = {':Trans', 'Translate'}, + d = {':TransSelectDirection', 'Translate with direction'}, + r = {'c=system(\'trans -brief -no-ansi\', getreg(""))[:-2]', 'Translate and replace'}, + c = {'c=system(\'trans -brief -no-ansi :\', getreg(""))[:-2]', 'Translate and replace with direction'} + }, + + l = { + name = 'LSP', + c = {':Lspsaga range_code_action', 'Range code action'}, + C = {':Telescope lsp_range_code_actions', 'Range code action (Telescope)'}, + o = 'Range format' + }, + + p = 'Find/Replace' +}, {mode = 'v', prefix = ''}) + +------------------------ +-- Filetype specified -- +------------------------ +-- FIX: not working????? +vim.api.nvim_command [[ +autocmd FileType org lua WhichkeyOrg() +autocmd FileType markdown lua WhichkeyMarkdown() +autocmd FileType html lua WhichkeyHtml() +]] + +function WhichkeyOrg() + wk.register({ + ['o'] = { + name = 'Org', + a = 'Agenda', + A = 'Toggle ARCHIVE', + c = 'Capture', + e = 'Export', + i = { + name = 'Insert', + h = 'Add headline', + t = 'Add TODO heading and content', + T = 'Add TODO heading', + }, + J = 'Move subtree down', + K = 'Move subtree up', + o = 'Open at point', + r = 'Refile', + t = 'Set tags', + ['$'] = 'Archive current headline' + }, + [''] = 'Org meta return', + [''] = 'Org increase date', + [''] = 'Org decrease date', + ['cid'] = 'Org change date', + ['cit'] = 'Org TODO', + ['ciT'] = 'Org TODO prev', + [''] = 'Org toggle checkbox', + [''] = 'Org cycle folding', + [''] = 'Org cycle global folding', + ['<<'] = 'Org promote headline', + ['>>'] = 'Org demote headline', + ['s'] = 'Org demote subtree', + ['}'] = 'Org next visible heading', + ['{'] = 'Org previous visible heading', + [']]'] = 'Org forward heading', + ['[['] = 'Org backward heading', + ['g{'] = 'Org parent heading', + ['?'] = 'Org help' + }, {buffer = vim.api.nvim_get_current_buf()}) +end + +function WhichkeyMarkdown() + wk.register({ + ['bp'] = {':MarkdownPreviewToggle', 'Preview markdown'} + }, {buffer = vim.api.nvim_get_current_buf()}) +end + +function WhichkeyHtml() + wk.register({ + ['bp'] = {':Bracey', 'Preview html'} + }, {buffer = vim.api.nvim_get_current_buf()}) +end diff --git a/roles/nvim/files/lua/modules/completion.lua b/roles/nvim/files/lua/modules/completion.lua new file mode 100644 index 0000000..f65a478 --- /dev/null +++ b/roles/nvim/files/lua/modules/completion.lua @@ -0,0 +1,223 @@ +local M = {} + +function M.cmp_conf() + local cmp = require('cmp') + local luasnip = require('luasnip') + + local has_words_before = function() + local line, col = unpack(vim.api.nvim_win_get_cursor(0)) + return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match('%s') == nil + end + + cmp.setup { + sorting = { + comparators = { + cmp.config.compare.offset, + cmp.config.compare.exact, + cmp.config.compare.score, + require('cmp-under-comparator').under, + cmp.config.compare.kind, + cmp.config.compare.sort_text, + cmp.config.compare.length, + cmp.config.compare.order + } + }, + formatting = { + format = function(entry, vim_item) + local lspkind_icons = { + Text = '', + Method = '', + Function = '', + Constructor = '', + Field = 'ﰠ', + Variable = '', + Class = 'ﴯ', + Interface = '', + Module = '', + Property = 'ﰠ', + Unit = '塞', + Value = '', + Enum = '', + Keyword = '', + Snippet = '', + Color = '', + File = '', + Reference = '', + Folder = '', + EnumMember = '', + Constant = '', + Struct = '', + Event = '', + Operator = '', + TypeParameter = '' + } + -- load lspkind icons + vim_item.kind = string.format('%s %s', lspkind_icons[vim_item.kind], vim_item.kind) + + vim_item.menu = ({ + luasnip = '[SNIP]', + path = '[PATH]', + buffer = '[BUF]', + calc = '[CALC]', + dictionary = '[DICT]', + nvim_lsp = '[LSP]', + -- cmp_tabnine = '[TN]', + latex_symbols = '[TEX]', + conjure = '[CJ]', + orgmode = '[ORG]' + })[entry.source.name] + + return vim_item + end + }, + documentation = { + border = { '┌','─', '┐', '│', '┘', '─', '└', '│'} + }, + mapping = { + [''] = cmp.mapping.confirm({select = true}), + [''] = cmp.mapping.complete(), + [''] = cmp.mapping.select_prev_item(), + [''] = cmp.mapping.select_next_item(), + [''] = cmp.mapping.scroll_docs(-4), + [''] = cmp.mapping.scroll_docs(4), + [''] = cmp.mapping.close(), + -- Change choice nodes for luasnip + [''] = cmp.mapping(function(fallback) + if luasnip.choice_active() then + luasnip.change_choice(-1) + else + fallback() + end + end, {'i', 's'}), + [''] = cmp.mapping(function(fallback) + if luasnip.choice_active() then + luasnip.change_choice(1) + else + fallback() + end + end, {'i', 's'}), + -- supertab-like mapping + [''] = cmp.mapping(function(fallback) + if cmp.visible() then + cmp.select_next_item() + elseif luasnip.expand_or_jumpable() then + luasnip.expand_or_jump() + elseif has_words_before() then + cmp.complete() + else + fallback() + end + end, {'i', 's'}), + [''] = cmp.mapping(function(fallback) + if cmp.visible() then + cmp.select_prev_item() + elseif luasnip.jumpable(-1) then + luasnip.jump(-1) + else + fallback() + end + end, {'i', 's'}) + }, + snippet = { + expand = function(args) + luasnip.lsp_expand(args.body) + end + }, + sources = { + {name = 'luasnip'}, + {name = 'path'}, + {name = 'buffer'}, + {name = 'calc'}, + {name = 'dictionary', keyword_length = 2}, + {name = 'nvim_lsp'}, + -- {name = 'cmp_tabnine'}, + {name = 'latex_symbols'}, + {name = 'conjure'}, + {name = 'orgmode'} + } + } + + -- Setup for cmp-dictionary + -- TODO: do this on FileType * (cmp.setup.buffer) with custom dicts + -- vim.opt.dictionary = {'/usr/share/dict/words'} +end + +-- function M.tabnine_conf() +-- local tabnine = require('cmp_tabnine.config') +-- tabnine:setup { +-- max_lines = 1000, +-- max_num_results = 20, +-- sort = true, +-- run_on_every_keystroke = true +-- } +-- end + +function M.autopairs_conf() + require('nvim-autopairs').setup { + disable_filetype = {'TelescopePrompt', 'spectre_panel'}, + disable_in_macro = false, -- disable when recording or executing a macro + ignored_next_char = string.gsub([[ [%w%%%'%[%"%.] ]], '%s+', ''), + enable_moveright = true, + enable_afterquote = true, -- add bracket pairs after quote + enable_check_bracket_line = true, -- check bracket in same line + check_ts = true, -- use treesitter + ts_config = { + lua = {'string', 'source'}, + javascript = {'string', 'template_string'} + }, + map_bs = true, -- map the key + map_c_w = true, + map_cr = true, + fast_wrap = { + map = '', + chars = { '{', '[', '(', '"', "'" }, + pattern = string.gsub([[ [%'%"%)%>%]%)%}%,] ]], '%s+', ''), + offset = 0, -- Offset from pattern match + end_key = '$', + keys = 'qwertyuiopzxcvbnmasdfghjkl', + check_comma = true, + highlight = 'Search', + highlight_grey = 'Comment' + } + } + + -- Setup for cmp + local cmp_autopairs = require('nvim-autopairs.completion.cmp') + local cmp = require('cmp') + cmp.event:on('confirm_done', cmp_autopairs.on_confirm_done()) +end + +function M.snippets_conf() + local types = require('luasnip.util.types') + + require('luasnip').config.set_config({ + updateevents = 'TextChanged, TextChangedI', + history = true, + ext_opts = { + [types.choiceNode] = { + active = { + virt_text = {{'●', 'LuaSnipChoice'}} + } + }, + [types.insertNode] = { + active = { + virt_text = {{'●', 'LuaSnipInsert'}} + } + } + } + }) + + -- Loading vscode-like snippets from 'friendly-snippets' + require('luasnip/loaders/from_vscode').load() +end + +function M.autotag_conf() + require('nvim-ts-autotag').setup { + filetypes = { + 'html', 'javascript', 'javascriptreact', 'typescript', + 'typescriptreact', 'svelte', 'vue' + } + } +end + +return M diff --git a/roles/nvim/files/lua/modules/editor.lua b/roles/nvim/files/lua/modules/editor.lua new file mode 100644 index 0000000..2cd53f1 --- /dev/null +++ b/roles/nvim/files/lua/modules/editor.lua @@ -0,0 +1,393 @@ +local M = {} + +function M.colorizer_conf() + require('colorizer').setup( + {'*'}, + { + RGB = true, -- #RGB hex codes + RRGGBB = true, -- #RRGGBB hex codes + names = true, -- "Name" codes like Blue + RRGGBBAA = true, -- #RRGGBBAA hex codes + rgb_fn = true, -- CSS rgb() and rgba() functions + hsl_fn = true, -- CSS hsl() and hsla() functions + css = true, -- Enable all CSS features: rgb_fn, hsl_fn, names, RGB, RRGGBB + css_fn = true, -- Enable all CSS *functions*: rgb_fn, hsl_fn + mode = 'background' -- Set the display mode. + }) +end + +function M.illuminate_conf() + vim.g.Illuminate_delay = 500 + vim.g.Illuminate_ftblacklist = {'alpha', 'NvimTree', 'undotree', 'packer'} +end + +function M.blankline_conf() + require('indent_blankline').setup { + char = '│', + -- space_char_blankline = '·', + show_first_indent_level = true, + filetype_exclude = { + 'startify', 'dashboard', 'alpha', 'log', 'gitcommit', 'packer', 'vimwiki', + 'markdown', 'org', 'json', 'txt', 'help', 'NvimTree', 'git', 'TelescopePrompt', + 'undotree', 'dotooagenda', 'fugitive', + '' -- for all buffers without a filetype + }, + buftype_exclude = {'terminal', 'nofile'}, + show_trailing_blankline_indent = false, + -- show_end_of_line = true, + show_current_context = true, + context_patterns = { + 'class', 'function', 'method', 'block', 'list_literal', 'selector', '^if', + '^table', 'if_statement', 'while', 'for' + }, + use_treesitter = true + } + + -- Refresh often, since it is lazy-loaded + -- vim.api.nvim_command('autocmd CursorMoved * IndentBlanklineRefresh') +end + +function M.treesitter_conf() + -- Additional parser for rest.nvim (*.http files) + local parser_configs = require('nvim-treesitter.parsers').get_parser_configs() + parser_configs.http = { + install_info = { + url = 'https://github.com/NTBBloodbath/tree-sitter-http', + files = {'src/parser.c'}, + branch = 'main' + } + } + + require('nvim-treesitter.configs').setup { + ensure_installed = 'maintained', + highlight = {enable = true}, + incremental_selection = { + enable = true, + keymaps = { + init_selection = 'gni', + node_incremental = 'gnn', + scope_incremental = 'gns', + node_decremental = 'gnm' + } + }, + -- indent = {enable = true}, + textobjects = { + select = { + enable = true, + lookahead = true, + keymaps = { + ['af'] = '@function.outer', + ['if'] = '@function.inner', + ['ac'] = '@class.outer', + ['ic'] = '@class.inner' + } + }, + move = { + enable = true, + set_jumps = true, -- whether to set jumps in the jumplist + goto_next_start = { + [']['] = '@function.outer', + [']m'] = '@class.outer' + }, + goto_next_end = { + [']]'] = '@function.outer', + [']M'] = '@class.outer' + }, + goto_previous_start = { + ['[['] = '@function.outer', + ['[m'] = '@class.outer' + }, + goto_previous_end = { + ['[]'] = '@function.outer', + ['[M'] = '@class.outer' + } + } + }, + matchup = {enable = true}, + rainbow = { + enable = true, + extended_mode = true, + max_file_lines = 1000 + }, + playground = { + enable = true, + disable = {}, + updatetime = 25, + persist_queries = false, + keybindings = { + toggle_query_editor = 'o', + toggle_hl_groups = 'i', + toggle_injected_languages = 't', + toggle_anonymous_nodes = 'a', + toggle_language_display = 'I', + focus_language = 'f', + unfocus_language = 'F', + update = 'R', + goto_node = '', + show_help = '?' + } + }, + query_linter = { + enable = true, + use_virtual_text = true, + lint_events = {'BufWrite', 'CursorHold'} + }, + context_commentstring = { + enable = true, + enable_autocmd = false, + config = { + fish = '# %s', + lisp = ';; %s' + } + } + } + + -- tree-sitter based folding + vim.opt.foldmethod = 'expr' + vim.opt.foldexpr = 'nvim_treesitter#foldexpr()' +end + +function M.iswap_conf() + require('iswap').setup { + -- The keys that will be used as a selection, in order + -- ('asdfghjklqwertyuiopzxcvbnm' by default) + -- keys = 'qwertyuiop', + + -- Grey out the rest of the text when making a selection + -- (enabled by default) + -- grey = 'disable', + + -- Highlight group for the sniping value (asdf etc.) + -- default 'Search' + -- hl_snipe = 'ErrorMsg', + + -- Highlight group for the visual selection of terms + -- default 'Visual' + -- hl_selection = 'WarningMsg', + + -- Highlight group for the greyed background + -- default 'Comment' + hl_grey = 'LineNr', + + -- Automatically swap with only two arguments + -- default nil + autoswap = true + } +end + +function M.matchup_conf() + vim.g.matchup_matchparen_offscreen = {method = 'popup'} +end + +function M.twilight_conf() + require('twilight').setup { + dimming = { + alpha = 0.25, -- amount of dimming + -- we try to get the foreground from the highlight groups or fallback color + color = {'Normal', '#ffffff'}, + inactive = false -- when true, other windows will be fully dimmed (unless they contain the same buffer) + }, + context = 10, + treesitter = true, + expand = { -- for treesitter, we we always try to expand to the top-most ancestor with these types + 'function', + 'method', + 'table', + 'if_statement' + }, + exclude = {'alpha', 'packer', 'NvimTree', 'qf'} + } +end + +function M.zenmode_conf() + require('zen-mode').setup { + window = { + options = { + signcolumn = 'no', + number = false, + relativenumber = false, + cursorline = false, + cursorcolumn = false, + foldcolumn = '0' + } + }, + -- on_open = function() + -- vim.api.nvim_command('TSContextDisable') + -- vim.api.nvim_command('IndentBlanklineDisable') + -- end, + -- on_close = function() + -- vim.api.nvim_command('TSContextEnable') + -- vim.api.nvim_command('IndentBlanklineEnable') + -- end + } +end + +function M.betterescape_conf() + require('better_escape').setup { + mapping = {'jk', 'kj'}, + timeout = vim.opt.timeoutlen:get(), + clear_empty_lines = false, + keys = '' + } +end + +function M.hop_conf() + require('hop').setup {keys = 'etovxqpdygfblzhckisuran'} +end + +function M.eft_conf() + vim.g.eft_index_function = {all = function() return true end} + + -- Mappings + vim.api.nvim_set_keymap('n', 'f', '(eft-f)', {silent = true}) + vim.api.nvim_set_keymap('x', 'f', '(eft-f)', {silent = true}) + vim.api.nvim_set_keymap('n', 'F', '(eft-F)', {silent = true}) + vim.api.nvim_set_keymap('x', 'F', '(eft-F)', {silent = true}) + vim.api.nvim_set_keymap('n', 't', '(eft-t)', {silent = true}) + vim.api.nvim_set_keymap('x', 't', '(eft-t)', {silent = true}) + vim.api.nvim_set_keymap('n', 'T', '(eft-T)', {silent = true}) + vim.api.nvim_set_keymap('x', 'T', '(eft-T)', {silent = true}) + vim.api.nvim_set_keymap('n', ';', '(eft-repeat)', {silent = true}) + vim.api.nvim_set_keymap('x', ';', '(eft-repeat)', {silent = true}) +end + +function M.dial_conf() + local dial = require('dial') + + -- Custom augends + dial.augends['custom#boolean'] = dial.common.enum_cyclic{ + name = 'boolean', + strlist = {'true', 'false'} + } + dial.augends['custom#boolean2'] = dial.common.enum_cyclic{ + name = 'boolean', + strlist = {'True', 'False'} + } + + dial.config.searchlist.normal = { + 'number#decimal#int', + 'number#decimal#fixed#zero', + 'number#hex', + 'number#binary', + 'date#[%Y/%m/%d]', + 'date#[%m/%d]', + 'date#[%Y-%m-%d]', + 'date#[%H:%M:%S]', + 'date#[%H:%M]', + 'date#[%jA]', + 'color#hex', + 'markup#markdown#header', + 'custom#boolean', + 'custom#boolean2' + } + dial.config.searchlist.visual = { + 'number#decimal#int', + 'number#decimal#fixed#zero', + 'number#hex', + 'number#binary', + 'date#[%Y/%m/%d]', + 'date#[%m/%d]', + 'date#[%Y-%m-%d]', + 'date#[%H:%M:%S]', + 'date#[%H:%M]', + 'date#[%jA]', + 'char#alph#small#word', + 'char#alph#capital#word', + 'color#hex' + } + + -- Mappings + vim.api.nvim_set_keymap('n', '', '(dial-increment)', {silent = true}) + vim.api.nvim_set_keymap('v', '', '(dial-increment)', {silent = true}) + vim.api.nvim_set_keymap('n', '', '(dial-decrement)', {silent = true}) + vim.api.nvim_set_keymap('v', '', '(dial-decrement)', {silent = true}) + vim.api.nvim_set_keymap('v', 'g', '(dial-increment-additional)', {silent = true}) + vim.api.nvim_set_keymap('v', 'g', '(dial-decrement-additional)', {silent = true}) +end + +function M.comment_conf() + require('Comment').setup { + padding = true, -- add a ' ' between comment and the line + sticky = true, -- whether the cursor should stay at its position + ignore = '^$', -- ignore empty lines + mappings = { + basic = true, -- 'gcc', 'gcb', 'gc[count]{motion}', 'gb[count]{motion}' + extra = true, -- 'gco', 'gcO', 'gcA' + extended = false -- 'g>', 'g>[count]{motion}', 'g<[count]{motion}' + }, + toggle = { -- toggle mapping in NORMAL + VISUAL mode + line = 'gcc', + block = 'gbc' + }, + opleader = { -- operator-pending mapping in NORMAL + VISUAL mode + line = 'gc', + block = 'gb' + }, + pre_hook = function(ctx) + require('ts_context_commentstring.internal').update_commentstring() + end, + post_hook = nil + } +end + +function M.range_conf() + require('range-highlight').setup() +end + +function M.neogen_conf() + require('neogen').setup { + enabled = true, + input_after_comment = true, + jump_map = '' + } + + -- Mappings + vim.api.nvim_set_keymap('n', 'eg', ':lua require("neogen").generate()', {noremap = true, silent = true}) +end + +function M.project_conf() + require('project_nvim').setup { + manual_mode = false, + detection_methods = {'lsp', 'pattern'}, + patterns = {'.git', '_darcs', '.hg', '.bzr', '.svn', 'Makefile', 'package.json', '*.pro', 'Dockerfile', '>Code'}, + show_hidden = true, + silent_chdir = true, + datapath = vim.fn.stdpath('data') + } + + -- cd on local window changes with 'lcd' (more eager) + -- see https://github.com/ahmedkhalf/project.nvim/issues/23 + -- _G.set_window_project_dir = function() + -- local root, _ = require('project_nvim.project').get_project_root() + -- if root then + -- vim.api.nvim_command('lcd ' .. root) + -- end + -- end + -- vim.api.nvim_command('autocmd BufEnter * lua set_window_project_dir()') +end + +function M.gitlinker_conf() + require('gitlinker').setup { + opts = { + remote = nil, -- force the use of a specific remote + -- adds current line nr in the url for normal mode + add_current_line_on_normal_mode = true, + -- callback for what to do with the url + action_callback = require('gitlinker.actions').copy_to_clipboard, + -- print the url after performing the action + print_url = true, + }, + callbacks = { + ['git.folliehiyuki.com'] = require('gitlinker.hosts').get_gitea_type_url, + ['git.disroot.org'] = require('gitlinker.hosts').get_gitea_type_url, + ['gitlab.alpinelinux.org'] = require('gitlinker.hosts').get_gitlab_type_url + }, + -- default mapping to call url generation with action_callback + mappings = 'gy' + } + + -- Mapping to get remote url + vim.api.nvim_set_keymap('n', 'gY', ':lua require("gitlinker").get_repo_url()', {noremap = true, silent = true}) +end + +return M diff --git a/roles/nvim/files/lua/modules/lsp.lua b/roles/nvim/files/lua/modules/lsp.lua new file mode 100644 index 0000000..8880f12 --- /dev/null +++ b/roles/nvim/files/lua/modules/lsp.lua @@ -0,0 +1,679 @@ +local M = {} + +function M.signature_conf() + require('lsp_signature').setup { + bind = true, -- This is mandatory, otherwise border config doesn't work + floating_window = true, + fix_pos = true, + hint_enable = false, + hint_prefix = ' ', + hint_scheme = 'String', + hi_parameter = 'Visual', + transpancy = 5, + handler_opts = {border = 'single'}, + zindex = 50, -- set to 200 to make the float window on top of others + toggle_key = '' + } +end + +function M.saga_conf() + require('lspsaga').init_lsp_saga { + debug = false, + use_saga_diagnostic_sign = true, + -- diagnostic sign + error_sign = '', + warn_sign = '', + hint_sign = '', + infor_sign = '', + dianostic_header_icon = '  ', + -- code action title icon + code_action_icon = ' ', + code_action_prompt = { + enable = false, + sign = true, + sign_priority = 40, + virtual_text = true + }, + finder_definition_icon = ' ', + finder_reference_icon = ' ', + max_preview_lines = 10, + finder_action_keys = { + open = 'o', + vsplit = 's', + split = 'i', + quit = 'q', + scroll_down = '', + scroll_up = '' + }, + code_action_keys = { + quit = 'q', + exec = '' + }, + rename_action_keys = { + quit = '', + exec = '' + }, + definition_preview_icon = ' ', + border_style = 'single', + rename_prompt_prefix = '', + server_filetype_map = {} + } +end + +function M.lsp_conf() + local lspconf = require('lspconfig') + + local on_attach = function(client, bufnr) + vim.api.nvim_buf_set_option(bufnr, 'omnifunc', 'v:lua.vim.lsp.omnifunc') + + local function buf_set_keymap(...) + vim.api.nvim_buf_set_keymap(bufnr, ...) + end + + local opts = {noremap = true, silent = true} + buf_set_keymap('n', '', ':lua require("lspsaga.action").smart_scroll_with_saga(1)', opts) + buf_set_keymap('n', '', ':lua require("lspsaga.action").smart_scroll_with_saga(-1)', opts) + + if client.resolved_capabilities.document_formatting then + buf_set_keymap('n', 'lo', ':lua vim.lsp.buf.formatting()', opts) + -- vim.api.nvim_command('autocmd BufWritePre lua vim.lsp.buf.formatting_sync()') + elseif client.resolved_capabilities.document_range_formatting then + buf_set_keymap('n', 'lo', ':lua vim.lsp.buf.range_formatting({},{0,0},{vim.fn.line("$"),0})', opts) + buf_set_keymap('v', 'lo', ':lua vim.lsp.buf.range_formatting()', opts) + -- vim.api.nvim_command('autocmd BufWritePre lua vim.lsp.buf.range_formatting({},{0,0},{vim.fn.line("$"),0})') + end + end + + local capabilities = vim.lsp.protocol.make_client_capabilities() + + -- Add additional capabilities supported by nvim-cmp + local completionItem = capabilities.textDocument.completion.completionItem + completionItem.documentationFormat = {'markdown', 'plaintext'} + completionItem.snippetSupport = true + completionItem.preselectSupport = true + completionItem.insertReplaceSupport = true + completionItem.labelDetailsSupport = true + completionItem.deprecatedSupport = true + completionItem.commitCharactersSupport = true + completionItem.tagSupport = {valueSet = {1}} + completionItem.resolveSupport = { + properties = { + 'documentation', + 'detail', + 'additionalTextEdits', + } + } + + -- Replace the default lsp diagnostic letters with prettier symbols + vim.fn.sign_define('LspDiagnosticsSignError', {text = ''}) + vim.fn.sign_define('LspDiagnosticsSignWarning', {text = ''}) + vim.fn.sign_define('LspDiagnosticsSignInformation', {text = ''}) + vim.fn.sign_define('LspDiagnosticsSignHint', {text = ''}) + + --------------------------- + -- Server configurations -- + --------------------------- + -- https://github.com/neovim/nvim-lspconfig/blob/master/CONFIG.md + local servers_path = vim.fn.stdpath('data') .. '/lsp' + + -- C/C++ + lspconf.clangd.setup { + on_attach = on_attach, + capabilities = capabilities, + filetypes = {'c', 'cpp'}, + init_options = { + usePlaceholders = true, + completeUnimported = true, + clangdFileStatus = true + }, + cmd = { + 'clangd', + '-j=2', + '--background-index', + '--clang-tidy', + '--completion-style=detailed', + '--pch-storage=memory', + '--header-insertion=iwyu', + '--header-insertion=decorators' + } + } + + -- Lua + local lua_lib_path = {} + local lua_runtime_path = {} + + -- lua_lib_path[vim.fn.expand('~/.luarocks/share/lua/5.3')] = true + -- lua_lib_path[vim.fn.expand('/usr/share/lua/5.3')] = true + lua_lib_path[os.getenv('VIMRUNTIME') .. '/lua'] = true + -- local function add(lib) + -- for _, p in pairs(vim.fn.expand(lib .. '/lua', false, true)) do + -- p = vim.loop.fs_realpath(p) + -- if p then lua_lib_path[p] = true end + -- end + -- end + -- for _, site in pairs(vim.split(vim.opt.packpath:get(), ',')) do + -- add(site .. '/pack/*/opt/*') + -- add(site .. '/pack/*/start/*') + -- end + + table.insert(lua_runtime_path, 'lua/?.lua') + table.insert(lua_runtime_path, 'lua/?/init.lua') + -- table.insert(lua_runtime_path, '?.lua') + -- table.insert(lua_runtime_path, '?/?.lua') + -- table.insert(lua_runtime_path, '?/init.lua') + + for lib, _ in pairs(lua_lib_path) do + table.insert(lua_runtime_path, lib .. '/?.lua') + table.insert(lua_runtime_path, lib .. '/?/init.lua') + end + + lspconf.sumneko_lua.setup { + on_attach = on_attach, + capabilities = capabilities, + cmd = { + servers_path .. '/sumneko_lua/bin/Linux/lua-language-server', + '-E', '-e', 'LANG=en', + servers_path .. '/sumneko_lua/main.lua' + }, + settings = { + Lua = { + diagnostics = {globals = {'vim'}}, + runtime = {version = 'LuaJIT', path = lua_runtime_path}, + workspace = { + library = lua_lib_path, + maxPreload = 1000, + preloadFileSize = 150 + }, + completion = {callSnippet = 'Replace'}, + hint = {enable = true}, + telemetry = {enable = false} + } + } + } + + -- Go + lspconf.gopls.setup { + on_attach = on_attach, + capabilities = capabilities, + cmd = {servers_path .. '/gopls/gopls', '--remote=auto'}, + init_options = { + usePlaceholders = true, + completeUnimported = true + } + } + + -- Yaml + lspconf.yamlls.setup { + on_attach = on_attach, + capabilities = capabilities, + cmd = {servers_path .. '/yamlls/node_modules/.bin/yaml-language-server', '--stdio'}, + settings = { + redhat = {telemetry = {enabled = false}}, + yaml = { + format = { + bracketSpacing = true, + printWidth = 80, + -- proseWrap = 'always', -- default is 'preserve' + -- singleQuote = true, + -- editor.formatOnType = true + } + } + } + } + + -- Ansible + lspconf.ansiblels.setup { + on_attach = on_attach, + capabilities = capabilities, + cmd = {'node', servers_path .. '/ansiblels/out/server/src/server.js', '--stdio'}, + filetypes = {'yaml', 'yaml.ansible'}, + settings = { + -- python = {interpreterPath = 'python3'}, + executionEnvironment = {enabled = false} + } + } + + -- Tailwind + -- lspconf.tailwindcss.setup { + -- on_attach = on_attach, + -- capabilities = capabilities, + -- cmd = {servers_path .. '/tailwindcss/node_modules/.bin/tailwindcss-language-server', '--stdio'}, + -- settings = { + -- tailwindCSS = { + -- emmetCompletions = true + -- } + -- } + -- } + + -- Emmet + lspconf.emmet_ls.setup { + cmd = {servers_path .. '/emmet_ls/node_modules/.bin/emmet-ls', '--stdio'}, + filetypes = { + 'html', 'xml', 'css', 'scss', 'sass', + 'javascript', 'javascriptreact' + }, + capabilities = capabilities + } + + -- HTML + lspconf.html.setup { + on_attach = on_attach, + capabilities = capabilities, + cmd = {servers_path .. '/vscode/node_modules/.bin/vscode-html-language-server', '--stdio'}, + filetypes = {'html', 'markdown'} + } + + -- Eslint + lspconf.eslint.setup { + on_attach = on_attach, + capabilities = capabilities, + cmd = {servers_path .. '/vscode/node_modules/.bin/vscode-eslint-language-server', '--stdio'}, + filetypes = {'javascript', 'javascriptreact', 'typescript', 'typescriptreact', 'vue', 'svelte'}, + handlers = { + ['eslint/noConfig'] = function() + vim.notify('Unable to parse ESLint config.', vim.log.levels.WARN) + end + }, + settings = { + codeAction = { + disableRuleComment = { + enable = true, + location = 'separateLine' + }, + showDocumentation = {enable = true} + }, + codeActionOnSave = { + enable = false, -- run ':EslintFixAll' manually + mode = 'all' + }, + format = true, + nodePath = '', + onIgnoredFiles = 'off', + packageManager = 'npm', + quiet = false, + rulesCustomizations = {}, + run = 'onType', + useESLintClass = false, + validate = 'on', + workingDirectory = {mode = 'auto'} + } + } + + -- JSON + lspconf.jsonls.setup { + on_attach = on_attach, + capabilities = capabilities, + cmd = {servers_path .. '/vscode/node_modules/.bin/vscode-json-language-server', '--stdio'}, + settings = { + json = { + -- Schema catalog: https://www.schemastore.org/api/json/catalog.json + schemas = { + { + fileMatch = {'package.json'}, + url = 'https://json.schemastore.org/package.json' + }, { + fileMatch = {'tsconfig*.json'}, + url = 'https://json.schemastore.org/tsconfig.json' + }, { + fileMatch = { + '.prettierrc', '.prettierrc.json', + 'prettier.config.json' + }, + url = 'https://json.schemastore.org/prettierrc.json' + }, { + fileMatch = {'.eslintrc', '.eslintrc.json'}, + url = 'https://json.schemastore.org/eslintrc.json' + }, { + fileMatch = { + '.babelrc', '.babelrc.json', 'babel.config.json' + }, + url = 'https://json.schemastore.org/babelrc.json' + }, + { + fileMatch = {'lerna.json'}, + url = 'https://json.schemastore.org/lerna.json' + }, { + fileMatch = {'now.json', 'vercel.json'}, + url = 'https://json.schemastore.org/now.json' + }, { + fileMatch = { + '.stylelintrc', '.stylelintrc.json', + 'stylelint.config.json' + }, + url = 'http://json.schemastore.org/stylelintrc.json' + } + } + } + } + } + + -- Others + local servers = { + rust_analyzer = {'rust-analyzer'}, + sqls = {servers_path .. '/sqls/sqls'}, + cmake = {servers_path .. '/cmake/venv/bin/cmake-language-server'}, + -- bashls = {servers_path .. '/bashls/node_modules/.bin/bash-language-server', 'start'}, + -- dockerls = {servers_path .. '/dockerls/node_modules/.bin/docker-langserver', '--stdio'}, + cssls = {servers_path .. '/vscode/node_modules/.bin/vscode-css-language-server', '--stdio'}, + pyright = {servers_path .. '/pyright/node_modules/.bin/pyright-langserver', '--stdio'}, + -- vimls = {servers_path .. '/vimls/node_modules/.bin/vim-language-server', '--stdio'}, + tsserver = {servers_path .. '/tsserver/node_modules/.bin/typescript-language-server', '--stdio'} + } + for server, _ in pairs(servers) do + lspconf[server].setup { + on_attach = on_attach, + capabilities = capabilities, + cmd = servers[server] + } + end + + ------------------------ + -- Linters/Formatters -- + ------------------------ + -- TODO: efm-langserver as another option + local null_ls = require('null-ls') + + -- Register sources -- TODO: ansible-lint + null_ls.config { + sources = { + -- Formatters -- + -- null_ls.builtins.formatting.black.with { + -- command = 'black' + -- }, + null_ls.builtins.formatting.clang_format.with { + filetypes = {'c', 'cpp'} + }, + -- null_ls.builtins.formatting.cmake_format.with { + -- command = 'cmake-format' + -- }, + null_ls.builtins.formatting.fish_indent, + -- null_ls.builtins.formatting.fixjson.with { + -- command = 'fixjson' + -- }, + -- null_ls.builtins.formatting.fnlfmt.with { + -- command = 'fnlfmt' + -- }, + -- null_ls.builtins.formatting.goimports.with { + -- command = 'goimports' + -- }, + -- null_ls.builtins.formatting.gofmt.with { + -- command = 'gofmt' + -- }, + -- null_ls.builtins.formatting.isort.with { + -- command = 'isort' + -- }, + -- null_ls.builtins.formatting.nixfmt.with { + -- command = 'nixfmt' + -- }, + -- null_ls.builtins.formatting.prettier.with { + -- command = 'prettier' + -- }, + -- null_ls.builtins.formatting.rustfmt.with { + -- command = 'rustfmt' + -- }, + -- null_ls.builtins.formatting.rustywind.with { + -- command = 'rustywind' + -- }, + -- null_ls.builtins.formatting.shfmt, + -- null_ls.builtins.formatting.stylua.with { + -- condition = function(utils) + -- return utils.root_has_file('stylua.toml') + -- end, + -- command = 'stylua' + -- }, + -- null_ls.builtins.formatting.uncrustify.with { + -- command = 'uncrustify' + -- }, + -- null_ls.builtins.formatting.yapf.with { + -- command = 'yapf' + -- }, + -- null_ls.builtins.formatting.autopep8.with { + -- command = 'autopep8' + -- }, + -- null_ls.builtins.formatting.stylelint.with { + -- command = 'stylelint' + -- }, + -- Linters -- + null_ls.builtins.diagnostics.shellcheck, + -- null_ls.builtins.diagnostics.codespell.with { + -- command = 'codespell' + -- }, + -- null_ls.builtins.diagnostics.flake8.with { + -- command = 'flake8' + -- }, + null_ls.builtins.diagnostics.hadolint.with { + command = vim.fn.stdpath('config') .. '/scripts/hadolint', + args = {'$FILENAME'} + }, + -- null_ls.builtins.diagnostics.luacheck, + -- null_ls.builtins.diagnostics.cppcheck, + -- null_ls.builtins.diagnostics.write_good, + -- null_ls.builtins.diagnostics.proselint, + -- null_ls.builtins.diagnostics.markdownlint, + -- null_ls.builtins.diagnostics.pylint, + -- null_ls.builtins.diagnostics.vale, + -- null_ls.builtins.diagnostics.misspell, + -- null_ls.builtins.diagnostics.vint, + -- null_ls.builtins.diagnostics.stylelint, + -- Special -- + null_ls.builtins.hover.dictionary, -- get word definition from dictionaryapi.dev + -- null_ls.builtins.code_actions.gitsigns + } + } + + lspconf['null-ls'].setup { + on_attach = on_attach + } +end + +function M.sqls_conf() + require('sqls').setup { + picker = 'telescope' + } +end + +function M.lightbulb_conf() + vim.api.nvim_command [[ + autocmd CursorHold * lua require('nvim-lightbulb').update_lightbulb({sign = {enabled = false}, status_text = {enabled = true, text = ' Code action', text_unavailable = ''}}) + ]] +end + +function M.trouble_conf() + require('trouble').setup { + mode = 'lsp_workspace_diagnostics', + fold_open = ' ', + fold_closed = '', + action_keys = { + open_split = {''}, + open_vsplit = {''}, + open_tab = {''} + }, + signs = { + error = '', + warning = '', + information = '', + hint = '', + other = '' + } + } +end + +function M.comments_conf() + require('todo-comments').setup { + signs = false, + -- sign_priority = 8, + keywords = { + FIX = { + icon = ' ', -- icon used for the sign, and in search results + color = 'error', -- can be a hex color, or a named color (see below) + alt = {'FIXME', 'BUG', 'FIXIT', 'ISSUE'}, -- a set of other keywords that all map to this FIX keywords + -- signs = false, -- configure signs for some keywords individually + }, + TODO = {icon = ' ', color = 'info'}, + HACK = {icon = ' ', color = 'warning'}, + WARN = {icon = ' ', color = 'warning', alt = {'WARNING', 'XXX'}}, + PERF = {icon = ' ', alt = {'OPTIM', 'PERFORMANCE', 'OPTIMIZE'}}, + NOTE = {icon = ' ', color = 'hint', alt = {'INFO'}}, + }, + merge_keywords = true, + highlight = { + before = '', -- 'fg' or 'bg' or empty + keyword = 'fg', -- 'fg', 'bg', 'wide' or empty. (wide is the same as bg, but will also highlight surrounding characters) + after = '', -- 'fg' or 'bg' or empty + pattern = [[.*<(KEYWORDS)\s*:]], -- pattern or table of patterns, used for highlightng (vim regex) + comments_only = true, -- uses treesitter to match keywords in comments only + max_line_len = 400, -- ignore lines longer than this + exclude = {'org'}, -- list of file types to exclude highlighting + }, + colors = { + error = {'LspDiagnosticsDefaultError', 'TSDanger', '#bf616a', '#e06c75'}, + warning = {'LspDiagnosticsDefaultWarning', 'TSWarning', '#ebcb8b', '#e5c07b'}, + info = {'LspDiagnosticsDefaultInformation', 'TSNote', '#81a1c1', '#61afef'}, + hint = {'LspDiagnosticsDefaultHint', '#88c0d0', '#56b6c2'}, + default = {'Normal', '#d8dee9', '#abb2bf'} + }, + search = { + command = 'rg', + args = { + '--hidden', + '--color=never', + '--no-heading', + '--with-filename', + '--line-number', + '--column', + }, + -- regex that will be used to match keywords. + -- don't replace the (KEYWORDS) placeholder + pattern = [[\b(KEYWORDS):]] -- ripgrep regex + -- pattern = [[\b(KEYWORDS)\b]] -- match without the extra colon. You'll likely get false positives + } + } +end + +function M.outline_conf() + vim.g.symbols_outline = { + highlight_hovered_item = false, + show_guides = true, + auto_preview = true, + position = 'right', + width = 30, + show_numbers = false, + show_relative_numbers = false, + show_symbol_details = true, + preview_bg_highlight = 'NormalFloat', + keymaps = { -- Can be string or a table + close = {'', 'q'}, + goto_location = '', + focus_location = 'o', + hover_symbol = '', + toggle_preview = 'K', + rename_symbol = 'r', + code_actions = 'a', + }, + lsp_blacklist = {}, + symbol_blacklist = {}, + symbols = { + File = {icon = '', hl = 'TSURI'}, + Module = {icon = '', hl = 'TSNamespace'}, + Namespace = {icon = '', hl = 'TSNamespace'}, + Package = {icon = '', hl = 'TSNamespace'}, + Class = {icon = '𝓒', hl = 'TSType'}, + Method = {icon = 'ƒ', hl = 'TSMethod'}, + Property = {icon = '', hl = 'TSMethod'}, + Field = {icon = '', hl = 'TSField'}, + Constructor = {icon = '', hl = 'TSConstructor'}, + Enum = {icon = 'ℰ', hl = 'TSType'}, + Interface = {icon = 'ﰮ', hl = 'TSType'}, + Function = {icon = '', hl = 'TSFunction'}, + Variable = {icon = '', hl = 'TSConstant'}, + Constant = {icon = '', hl = 'TSConstant'}, + String = {icon = '𝓐', hl = 'TSString'}, + Number = {icon = '#', hl = 'TSNumber'}, + Boolean = {icon = '⊨', hl = 'TSBoolean'}, + Array = {icon = '', hl = 'TSConstant'}, + Object = {icon = '⦿', hl = 'TSType'}, + Key = {icon = '🔐', hl = 'TSType'}, + Null = {icon = 'NULL', hl = 'TSType'}, + EnumMember = {icon = '', hl = 'TSField'}, + Struct = {icon = '𝓢', hl = 'TSType'}, + Event = {icon = '🗲', hl = 'TSType'}, + Operator = {icon = '+', hl = 'TSOperator'}, + TypeParameter = {icon = '𝙏', hl = 'TSParameter'} + } + } +end + +function M.dap_conf() + local dap = require('dap') + vim.fn.sign_define('DapBreakpoint', {text='', texthl='DapSignDefault'}) + vim.fn.sign_define('DapLogPoint', {text='', texthl='DapSignDefault'}) + vim.fn.sign_define('DapStopped', {text='ﱢ', texthl='DapSignDefault'}) + vim.fn.sign_define('DapBreakpointRejected', {text='', texthl='DapSignRejected'}) + + -- Mappings + vim.api.nvim_command('n', 'dn', ':lua require("dap").continue()', {noremap = true, silent = true}) + vim.api.nvim_command('n', 'dd', ':lua require("dap").disconnect()', {noremap = true, silent = true}) + vim.api.nvim_command('n', 'db', ':lua require("dap").toggle_breakpoint()', {noremap = true, silent = true}) + vim.api.nvim_command('n', 'dB', ':lua require("dap").set_breakpoint(vim.fn.input("Breakpoint condition: "))', {noremap = true, silent = true}) + vim.api.nvim_command('n', 'dl', ':lua require("dap").list_breakpoints()', {noremap = true, silent = true}) + vim.api.nvim_command('n', 'dc', ':lua require("dap").run_to_cursor()', {noremap = true, silent = true}) + vim.api.nvim_command('n', 'dz', ':lua require("dap").run_last()', {noremap = true, silent = true}) + vim.api.nvim_command('n', '', ':lua require("dap").step_over()', {noremap = true, silent = true}) + vim.api.nvim_command('n', 'dv', ':lua require("dap").step_over()', {noremap = true, silent = true}) + vim.api.nvim_command('n', '', ':lua require("dap").step_into()', {noremap = true, silent = true}) + vim.api.nvim_command('n', 'di', ':lua require("dap").step_into()', {noremap = true, silent = true}) + vim.api.nvim_command('n', '', ':lua require("dap").step_out()', {noremap = true, silent = true}) + vim.api.nvim_command('n', 'do', ':lua require("dap").step_out()', {noremap = true, silent = true}) + vim.api.nvim_command('n', 'dr', ':lua require("dap").repl.open()', {noremap = true, silent = true}) +end + +function M.dapui_conf() + local dap, dapui = require('dap'), require('dapui') + dap.listeners.after.event_initialized['dapui_config'] = function() dapui.open() end + dap.listeners.before.event_terminated['dapui_config'] = function() dapui.close() end + dap.listeners.before.event_exited['dapui_config'] = function() dapui.close() end + + require('dapui').setup { + icons = {expanded = '', collapsed = ''}, + mappings = { + expand = {'', '<2-LeftMouse>'}, + open = 'o', + remove = 'd', + edit = 'e', + repl = 'r' + }, + sidebar = { + elements = { + -- Provide as ID strings or tables with 'id' and 'size' keys + -- 'size' can be float or integer > 1 + {id = 'scopes', size = 0.25}, + {id = 'breakpoints', size = 0.25}, + {id = 'stacks', size = 0.25}, + {id = 'watches', size = 0.25}, + }, + size = 40, + position = 'left' + }, + tray = { + elements = {'repl'}, + size = 10, + position = 'bottom' + }, + floating = { + max_height = nil, -- These can be integers or a float between 0 and 1. + max_width = nil, -- Floats will be treated as percentage of your screen. + mappings = { + close = {'q', ''} + } + }, + windows = {indent = 1} + } + + -- Mappings + vim.api.nvim_set_keymap('n', 'de', ':lua require("dapui").eval()', {noremap = true, silent = true}) + vim.api.nvim_set_keymap('v', 'de', ':lua require("dapui").eval()', {noremap = true, silent = true}) + vim.api.nvim_set_keymap('n', 'df', ':lua require("dapui").float_element()', {noremap = true, silent = true}) + vim.api.nvim_set_keymap('n', 'dt', ':lua require("dapui").toggle()', {noremap = true, silent = true}) +end + +return M diff --git a/roles/nvim/files/lua/modules/pack.lua b/roles/nvim/files/lua/modules/pack.lua new file mode 100644 index 0000000..d5cf256 --- /dev/null +++ b/roles/nvim/files/lua/modules/pack.lua @@ -0,0 +1,65 @@ +local fn, api = vim.fn, vim.api + +-- Require since we use 'packer' as opt +api.nvim_command('packadd packer.nvim') +local present, packer = pcall(require, 'packer') + +if not present then + local packer_dir = fn.stdpath('data') .. '/site/pack/packer/opt/packer.nvim' + + vim.notify('Cloning packer ...', vim.log.levels.INFO) + -- remove packer_dir before cloning + fn.delete(packer_dir, 'rf') + fn.system {'git', 'clone', 'https://github.com/wbthomason/packer.nvim', packer_dir} + api.nvim_command('packadd packer.nvim') + present, packer = pcall(require, 'packer') + + if present then + vim.notify('Pakcer cloned successfully.', vim.log.levels.INFO) + else + vim.notify('Git clone error for packer!', vim.log.levels.ERROR) + end +end + +local util = require('packer.util') + +packer.init { + compile_path = util.join_paths(fn.stdpath('data'), 'site', 'plugin', 'packer_compiled.lua'), + auto_clean = true, + compile_on_sync = true, + auto_reload_compiled = true, + git = { + -- default_url_format = 'https://github.com/%s', + clone_timeout = 120 + }, + display = { + open_fn = function() + return util.float {border = 'single'} + end, + -- open_cmd = '60vnew \\[packer\\]', + working_sym = '⟳', + error_sym = '✗', + done_sym = '✓', + removed_sym = '-', + moved_sym = '→', + header_sym = '━', + show_all_info = true, + prompt_boder = 'single' + }, + -- profile = {enable = true, threshold = 1}, + luarocks = {python_cmd = 'python3'} +} + +-- Re-compile packer on config changed +_G.packer_compile_on_save = function() + local file = fn.expand('%:p') + local filename = fn.expand('%:p:t') + local config_dir = fn.stdpath('config') .. '/lua/modules' + + if file:match(config_dir) and filename ~= 'pack.lua' then + vim.api.nvim_command('source | PackerCompile') + end +end +api.nvim_command('autocmd BufWritePost *.lua lua packer_compile_on_save()') + +return packer diff --git a/roles/nvim/files/lua/modules/tools.lua b/roles/nvim/files/lua/modules/tools.lua new file mode 100644 index 0000000..15f0991 --- /dev/null +++ b/roles/nvim/files/lua/modules/tools.lua @@ -0,0 +1,370 @@ +local M = {} + +function M.telescope_conf() + local telescope = require('telescope') + + telescope.setup { + defaults = { + prompt_prefix = '  ', + selection_caret = ' ', + set_env = {['COLORTERM'] = 'truecolor'}, + sorting_strategy = 'ascending', + layout_strategy = 'horizontal', + layout_config = { + horizontal = { + prompt_position = 'top', + preview_width = 0.6 + }, + width = 0.8, + height = 0.8 + }, + file_ignore_patterns = {'.git', '.svn', '.hg', 'node_modules'} + }, + pickers = { + find_files = { + hidden = true, + follow = true + }, + grep_string = { + opts = '--hidden' + }, + file_browser = { + hidden = true + } + }, + extensions = { + project = { + base_dirs = {{os.getenv('HOME') .. '/Code', max_depth = 4}}, + hidden_files = true + }, + fzf = { + fuzzy = true, + override_generic_sorter = false, + override_file_sorter = true, + case_mode = 'smart_case' + } + } + } + telescope.load_extension('projects') + telescope.load_extension('project') + telescope.load_extension('fzf') + + -- wrap lines inside preview pane + vim.api.nvim_command('autocmd User TelescopePreviewerLoaded setlocal wrap') +end + +function M.octo_conf() + require('octo').setup() +end + +function M.neogit_conf() + require('neogit').setup { + integrations = { + diffview = true + } + } +end + +function M.diffview_conf() + require('diffview').setup {diff_binaries = true} +end + +function M.asynctasks_conf() + -- vim.g.asyncrun_open = 8 -- when using quickfix window (output=terminal is preferable) + vim.g.asyncrun_rootmarks = {'.git', '.svn', '.root', '.hg', '.projectile'} + + vim.g.asynctasks_term_pos = 'bottom' + vim.g.asynctasks_term_rows = 10 + vim.g.asynctasks_config_name = 'tasks.ini' + vim.g.asynctasks_template = '~/.config/nvim/asynctasks.ini' +end + +function M.markdown_preview_conf() + vim.g.mkdp_refresh_slow = 1 + vim.g.mkdp_filetypes = { + 'markdown', + 'pandoc.markdown', + 'rmd' + } + -- vim.g.mkdp_browser = 'qutebrowser' + -- vim.g.mkdp_page_title = '「${name}」' + -- vim.g.mkdp_echo_preview_url = 1 +end + +function M.rest_conf() + require('rest-nvim').setup { + -- Open request results in a horizontal split + result_split_horizontal = false, + -- Skip SSL verification, useful for unknown certificates + skip_ssl_verification = false, + -- Highlight request on run + highlight = { + enabled = true, + timeout = 150, + }, + -- Jump to request line on run + jump_to_request = false, + } +end + +function M.orgmode_conf() + local c = require('themes.' .. vim.g.colors_name .. '.colors') + + require('orgmode').setup { + -- General settings + org_agenda_files = {'~/Documents/Org/agenda/*'}, + org_default_notes_file = '~/Documents/Org/notes.org', + org_todo_keywords = { + 'TODO', 'PROJ', 'LOOP', 'STRT', 'WAIT', 'HOLD', 'IDEA', 'DONE', 'KILL', + '[ ]', '[-]', '[X]' , '|', 'OKAY', 'YES', 'NO' + }, + org_todo_keyword_faces = { + TODO = ':foreground ' .. c.green .. ' :weight bold', + PROJ = ':foreground ' .. c.grey_bright .. ' :weight bold :slant italic', + LOOP = ':foreground ' .. c.green .. ' :weight bold :underline on', + STRT = ':foreground ' .. c.blue .. ' :weight bold', + WAIT = ':foreground ' .. c.yellow .. ' :weight bold', + HOLD = ':foreground ' .. c.yellow .. ' :weight bold :slant italic', + IDEA = ':foreground ' .. c.green .. ' :weight bold :slant italic', + DONE = ':foreground ' .. c.grey2 .. ' :weight bold', + KILL = ':foreground ' .. c.red .. ' :weight bold', + OKAY = ':foreground ' .. c.grey1 .. ' :weight bold :slant italic', + YES = ':foreground ' .. c.grey1 .. ' :weight bold :underline on', + NO = ':foreground ' .. c.red .. ' :weight bold :underline on' + }, + org_hide_leading_stars = true, + org_highlight_latex_and_related = 'entities', + + -- Agenda settings + org_deadline_warning_days = 7, + org_agenda_span = 'week', + org_agenda_start_on_weekday = 7, -- Start a week in Sunday + org_agenda_min_height = 15, + + -- Tags settings + org_use_tag_inheritance = false + } +end + +function M.bullets_conf() + require('org-bullets').setup { + symbols = {'', '', '', ''} + } +end + +function M.headlines_conf() + require('headlines').setup() +end + +function M.spectre_conf() + require('spectre').setup() + + -- Mappings + vim.api.nvim_set_keymap('n', 'po', ':lua require("spectre").open()', {noremap = true, silent = true}) + vim.api.nvim_set_keymap('n', 'pp', 'viw:lua require("spectre").open_file_search()', {noremap = true, silent = true}) + vim.api.nvim_set_keymap('n', 'pw', ':lua require("spectre").open_visual({select_word = true})', {noremap = true, silent = true}) + vim.api.nvim_set_keymap('v', 'p', ':lua require("spectre").open_visual()', {noremap = true, silent = true}) +end + +function M.translate_conf() + vim.g.trans_join_lines = 1 + vim.g.trans_win_height = 15 + vim.g.trans_default_direction = ':ja' + vim.g.trans_directions_list = { + {'', 'en'}, + {'', 'ja'}, + {'', 'de'}, + {'', 'ru'}, + {'', 'fr'}, + {'', 'nl'}, + {'', 'es'}, + {'', 'zh-CN'}, + {'', 'zh-TW'} + } +end + +function M.undotree_conf() + vim.g.undotree_WindowLayout = 2 + vim.g.undotree_SplitWidth = 30 + vim.g.undotree_DiffpaneHeight = 10 + vim.g.undotree_SetFocusWhenToggle = 1 + vim.g.undotree_RelativeTimestamp = 1 +end + +function M.toggleterm_conf() + require('toggleterm').setup { + shade_terminals = false, + float_opts = { + border = 'curved', + -- width = 80, + -- height = 80, + winblend = 3, + highlights = { + border = 'Normal', + background = 'Normal' + } + } + } +end + +-- function M.wilder_conf() +-- vim.api.nvim_command [[call wilder#setup({'modes': [':', '/', '?']})]] + + -- Doesn't work yet. Bugs in Neovim (see neovim/neovim#14809 and gelguy/wilder.nvim#53) + -- so can't do multi-line config inside vim.cmd [[ ]] with \ +-- vim.api.nvim_command [[ +-- call wilder#set_option('renderer', wilder#renderer_mux({ +-- \ ':': wilder#popupmenu_renderer({ +-- \ 'highlighter': [ +-- \ wilder#pcre2_highlighter(), +-- \ wilder#python_cpsm_highlighter() +-- \ ], +-- \ 'left': [ +-- \ ' ', +-- \ wilder#popupmenu_devicons(), +-- \ wilder#popupmenu_buffer_flags({ +-- \ 'flags': ' a + ', +-- \ 'icons': {'+': '', 'a': '', 'h': ''} +-- \ }) +-- \ ], +-- \ 'right': [' ', wilder#popupmenu_scrollbar()] +-- \ }), +-- \ '/': wilder#wildmenu_renderer({ +-- \ 'highlighter': wilder#basic_highlighter(), +-- \ 'separator': ' · ', +-- \ 'right': [' ', wilder#wildmenu_index()] +-- \ }) +-- \ })) +-- ]] + +-- vim.api.nvim_command [[ +-- call wilder#set_option('pipeline', [ +-- \ wilder#branch( +-- \ wilder#python_file_finder_pipeline({ +-- \ 'file_command': ['fd', '--type', 'f', '--follow', '--hidden', '--exclude', '.git'], +-- \ 'dir_command': ['fd', '--type', 'd', '--follow', '--hidden', '--exclude', '.git'], +-- \ 'filters': ['cpsm_filter', 'fuzzy_filter'] +-- \ }), +-- \ wilder#cmdline_pipeline({'language': 'python', 'fuzzy': 1, 'set_pcre2_patter': v:true}), +-- \ wilder#python_search_pipeline({'pattern': 'fuzzy'}) +-- \ ) +-- \ ]) +-- ]] +-- end + +function M.sniprun_conf() + local c = require('themes.' .. vim.g.colors_name .. '.colors') + + require('sniprun').setup { + display = { + 'Classic', --# display results in the command-line area + 'VirtualTextOk', --# display ok results as virtual text (multiline is shortened) + -- 'VirtualTextErr', --# display error results as virtual text + -- 'TempFloatingWindow', --# display results in a floating window + -- 'LongTempFloatingWindow', --# same as above, but only long results. To use with VirtualText__ + -- 'Terminal', --# display results in a vertical split + -- 'NvimNotify', --# display with the nvim-notify plugin + -- 'Api' --# return output to a programming interface + }, + show_no_output = { + 'Classic', + 'TempFloatingWindow' --# implies LongTempFloatingWindow, which has no effect on its own + }, + snipruncolors = { + SniprunVirtualTextOk = {bg = c.cyan, fg = c.black}, + SniprunFloatingWinOk = {fg = c.cyan}, + SniprunVirtualTextErr = {bg = c.orange, fg = c.black}, + SniprunFloatingWinErr = {fg = c.orange} + }, + inline_messages = 0, --# inline_message (0/1) is a one-line way to display messages + --# to workaround sniprun not being able to display anything + borders = 'single' --# display borders around floating windows + --# possible values are 'none', 'single', 'double', or 'shadow' + } +end + +function M.session_conf() + require('persistence').setup { + dir = vim.fn.expand(vim.fn.stdpath('data') .. '/sessions/'), + options = {'buffers', 'curdir', 'tabpages', 'winsize'} + } + + -- Mappings + vim.api.nvim_set_keymap('n', 'ss', ':lua require("persistence").save()', {noremap = true, silent = true}) + vim.api.nvim_set_keymap('n', 'sd', ':lua require("persistence").stop()', {noremap = true, silent = true}) + vim.api.nvim_set_keymap('n', 'sl', ':lua require("persistence").load({last = true})', {noremap = true, silent = true}) + vim.api.nvim_set_keymap('n', 'sr', ':lua require("persistence").load()', {noremap = true, silent = true}) +end + +function M.filetype_conf() + require('filetype').setup { + overrides = { + extensions = { + md = 'markdown', + mkd = 'markdown', + toml = 'toml', + rasi = 'css', + vifm = 'vim', + log = 'log', + LO = 'log' + }, + literal = { + vifmrc = 'vim' + }, + complex = { + ['*_log'] = 'log', + ['G*_LOG'] = 'log', + ['.*waybar/config'] = 'jsonc', + ['.*lf/lfrc'] = 'sh' + } + } + } +end + +function M.closebuf_conf() + require('close_buffers').setup { + preserve_window_layout = {'this'}, + next_buffer_cmd = function(windows) + require('bufferline').cycle(1) + local bufnr = vim.api.nvim_get_current_buf() + + for _, window in ipairs(windows) do + vim.api.nvim_win_set_buf(window, bufnr) + end + end + } +end + +function M.winshift_conf() + require('winshift').setup { + highlight_moving_win = true, -- Highlight the window being moved + focused_hl_group = 'Visual', -- The highlight group used for the moving window + moving_win_options = { + -- These are local options applied to the moving window while it's + -- being moved. They are unset when you leave Win-Move mode. + wrap = false, + cursorline = false, + cursorcolumn = false, + colorcolumn = '', + } + } +end + +function M.winpicker_conf() + require('window-picker').setup { + keys = 'alskdjfhgwoeiruty', + -- Swap windows by holding shift + letter + swap_shift = true, + exclude = {NvimTree = true, alpha = true}, + -- Flash the cursor line of the newly focused window + flash_duration = 300 + } +end + +function M.distant_conf() + require('distant').setup { + ['*'] = require('distant.settings').chip_default() + } +end + +return M diff --git a/roles/nvim/files/lua/modules/ui.lua b/roles/nvim/files/lua/modules/ui.lua new file mode 100644 index 0000000..ed40d25 --- /dev/null +++ b/roles/nvim/files/lua/modules/ui.lua @@ -0,0 +1,532 @@ +local M = {} + +function M.dashboard_conf() + local dashboard = require('alpha.themes.dashboard') + + dashboard.section.header = { + type = 'text', + val = { + [[<-. (`-')_ (`-') _ (`-') _ <-. (`-') ]], + [[ \( OO) ) ( OO).-/ .-> _(OO ) (_) \(OO )_ ]], + [[,--./ ,--/ (,------.(`-')----. ,--.(_/,-.\ ,-(`-'),--./ ,-.)]], + [[| \ | | | .---'( OO).-. '\ \ / (_/ | ( OO)| `.' |]], + [[| . '| |)(| '--. ( _) | | | \ / / | | )| |'.'| |]], + [[| |\ | | .--' \| |)| |_ \ /_)(| |_/ | | | |]], + [[| | \ | | `---. ' '-' '\-'\ / | |'->| | | |]], + [[`--' `--' `------' `-----' `-' `--' `--' `--']] + }, + opts = { + position = 'center', + -- wrap = 'overflow', + hl = 'DashboardHeader' + } + } + + dashboard.section.footer = { + type = 'text', + val = 'おかえりなさい', + opts = { + position = 'center', + hl = 'DashboardFooter' + } + } + + local button = function(sc, txt, keybind, keybind_opts) + local sc_ = sc:gsub('%s', ''):gsub('SPC', '') + + local opts = { + position = 'center', + shortcut = sc, + cursor = 5, + width = 50, + align_shortcut = 'right', + hl = 'DashboardCenter', + hl_shortcut = 'DashboardShortcut', + } + if keybind then + keybind_opts = vim.F.if_nil(keybind_opts, {noremap = true, silent = true, nowait = true}) + opts.keymap = {'n', sc_, keybind, keybind_opts} + end + + local function on_press() + local key = vim.api.nvim_replace_termcodes(sc_ .. '', true, false, true) + vim.api.nvim_feedkeys(key, 'normal', false) + end + + return { + type = 'button', + val = txt, + on_press = on_press, + opts = opts, + } + end + + dashboard.section.buttons = { + type = 'group', + val = { + button('SPC f g', ' Find word'), + button('SPC f f', ' Find file'), + button('SPC f o', ' Recent files'), + button('SPC f d', 'ﱮ Recent directories'), + button('SPC f m', ' Bookmarks'), + button('SPC f p', ' Projects'), + button('SPC s l', ' Load last session') + }, + opts = {spacing = 1} + } + + require('alpha').setup { + layout = { + {type = 'padding', val = 4}, + dashboard.section.header, + {type = 'padding', val = 2}, + dashboard.section.buttons, + dashboard.section.footer + }, + opts = {margin = 5} + } + + -- Hide tabline in dashboard buffer + vim.api.nvim_command [[ + autocmd FileType alpha set showtabline=0 | autocmd BufUnload set showtabline=2 + ]] +end + +function M.statusline_conf() + local colors = require('themes.' .. vim.g.colors_name .. '.colors') + + local vi_mode_colors = { + NORMAL = colors.green, + OP = colors.green, + INSERT = colors.blue, + VISUAL = colors.yellow, + LINES = colors.yellow, + BLOCK = colors.yellow, + REPLACE = colors.red, + ['V-REPLACE'] = colors.red, + ENTER = colors.cyan, + MORE = colors.cyan, + SELECT = colors.orange, + COMMAND = colors.purple, + SHELL = colors.green, + TERM = colors.green, + NONE = colors.white2 + } + + local function file_osinfo() + local os = vim.bo.fileformat:upper() + local icon + if os == 'UNIX' then + icon = ' ' + elseif os == 'MAC' then + icon = ' ' + else + icon = ' ' + end + return icon .. os + end + + local function buffer_not_empty() + if vim.fn.empty(vim.fn.expand('%:t')) ~= 1 then + return true + end + return false + end + + local vi_mode_utils = require('feline.providers.vi_mode') + + local comps = { + dummy = { + provider = '▊', + hl = {fg = colors.blue}, + right_sep = ' ' + }, + vi_mode = { + provider = ' ', + hl = function() + return { + name = vi_mode_utils.get_mode_highlight_name(), + fg = vi_mode_utils.get_mode_color() + } + end, + right_sep = ' ' + }, + filesize = { + provider = 'file_size', + enabled = buffer_not_empty, + hl = {fg = colors.fg, style = 'bold'}, + right_sep = ' ' + }, + fileinfo = { + provider = { + name = 'file_info', + opts = { + file_modified_icon = ' ', + file_readonly_icon = ' ', + type = 'base-only' -- relative, unique, full-path, short-path, relative-short, unique-short + } + }, + enabled = buffer_not_empty, + hl = {fg = colors.blue, style = 'bold'}, + right_sep = ' ' + }, + lineinfo = { + provider = 'position', + hl = {fg = colors.fg}, + right_sep = ' ' + }, + percent = { + provider = 'line_percentage', + hl = {fg = colors.fg, style = 'bold'}, + right_sep = ' ' + }, + codeact = { + provider = function() + local present, state = pcall(require, 'nvim-lightbulb') + if present then + return state.get_status_text() + else + return '' + end + end, + hl = {fg = colors.green, style = 'bold'} + }, + diagerr = { + provider = 'diagnostic_errors', + icon = ' ', + hl = {fg = colors.red}, + left_sep = ' ' + }, + diagwarn = { + provider = 'diagnostic_warnings', + icon = ' ', + hl = {fg = colors.yellow}, + left_sep = ' ' + }, + diaghint = { + provider = 'diagnostic_hints', + icon = ' ', + hl = {fg = colors.cyan}, + left_sep = ' ' + }, + diaginfo = { + provider = 'diagnostic_info', + icon = ' ', + hl = {fg = colors.blue}, + left_sep = ' ' + }, + lspclient = { + provider = 'lsp_client_names', + icon = ' LSP:', + hl = {fg = colors.purple, style = 'bold'}, + left_sep = ' ' + }, + format = { + provider = file_osinfo, + hl = {fg = colors.cyan}, + left_sep = ' ' + }, + encode = { + provider = 'file_encoding', + hl = {fg = colors.fg}, + left_sep = ' ' + }, + filetype = { + provider = 'file_type', + hl = {fg = colors.blue, style = 'bold'}, + left_sep = ' ' + }, + gitbranch = { + provider = 'git_branch', + icon = ' ', + hl = {fg = colors.green, style = 'bold'}, + left_sep = ' ' + }, + diffadd = { + provider = 'git_diff_added', + icon = ' ', + hl = {fg = colors.green}, + left_sep = ' ' + }, + diffchange = { + provider = 'git_diff_changed', + icon = '柳', + hl = {fg = colors.yellow}, + left_sep = ' ' + }, + diffremove = { + provider = 'git_diff_removed', + icon = ' ', + hl = {fg = colors.red}, + left_sep = ' ' + } + } + + -- Initialize the components table before defining it + local components = { + active = {}, + inactive = {} + } + + table.insert(components.active, {}) + table.insert(components.active, {}) + table.insert(components.active, {}) + table.insert(components.inactive, {}) + table.insert(components.inactive, {}) + + table.insert(components.active[1], comps.dummy) + table.insert(components.active[1], comps.vi_mode) + table.insert(components.active[1], comps.filesize) + table.insert(components.active[1], comps.fileinfo) + table.insert(components.active[1], comps.lineinfo) + table.insert(components.active[1], comps.percent) + table.insert(components.active[3], comps.codeact) + table.insert(components.active[3], comps.diagerr) + table.insert(components.active[3], comps.diagwarn) + table.insert(components.active[3], comps.diaghint) + table.insert(components.active[3], comps.diaginfo) + table.insert(components.active[3], comps.lspclient) + table.insert(components.active[3], comps.format) + table.insert(components.active[3], comps.encode) + table.insert(components.active[3], comps.filetype) + table.insert(components.active[3], comps.gitbranch) + table.insert(components.active[3], comps.diffadd) + table.insert(components.active[3], comps.diffchange) + table.insert(components.active[3], comps.diffremove) + table.insert(components.inactive[1], comps.dummy) + table.insert(components.inactive[1], comps.fileinfo) + table.insert(components.inactive[2], comps.filetype) + + require('feline').setup { + colors = {bg = colors.grey1, fg = colors.fg}, + components = components, + vi_mode_colors = vi_mode_colors, + force_inactive = { + filetypes = { + 'packer', + 'dashboard', + 'alpha', + 'NvimTree', + 'undotree', + 'DIFF', + 'TROUBLE', + 'Outline' + }, + buftypes = {'terminal', 'nofile'}, + bufnames = {} + } + } +end + +function M.bufferline_conf() + require('bufferline').setup { + options = { + numbers = 'none', + max_name_length = 16, + max_prefix_length = 13, + tab_size = 16, + diagnostics = false, -- 'nvim_lsp' + -- diagnostics_update_in_insert = false, + -- diagnostics_indicator = function(count, level, diagnostics_dict, context) + -- local s = '' + -- for e, n in pairs(diagnostics_dict) do + -- local sym = e == 'error' and 'x ' or (e == 'warning' and '! ' or (e == 'info' and 'i ' or '? ')) + -- s = s .. n .. sym + -- end + -- return s + -- end, + show_close_icon = false, + show_buffer_icons = true, + show_tab_indicators = true, + enforce_regular_tabs = false, + show_buffer_close_icons = false, + always_show_bufferline = true, + offsets = { + {filetype = 'NvimTree', text = 'NvimTree', text_align = 'center'}, + {filetype = 'packer', text = 'Packer', text_align = 'center'} + }, + separator_style = 'thin' + }, + highlights = { + fill = {guibg = {attribute = 'bg', highlight = 'TabLineFill'}}, + indicator_selected = {guifg = {attribute = 'fg', highlight = 'TabLineSel'}}, + -- diagnostic_selected = {guifg = {attribute = 'fg', highlight = 'LspDiagnosticsSignHint', gui = 'bold,italic'}}, + -- info_diagnostic_selected = {guifg = {attribute = 'fg', highlight = 'LspDiagnosticsSignInformation', gui = 'bold,italic'}}, + -- info_selected = {guifg = {attribute = 'fg', highlight = 'LspDiagnosticsDefaultInformation', gui = 'bold,italic'}}, + -- warning_diagnostic_selected = {guifg = {attribute = 'fg', highlight = 'LspDiagnosticsSignWarning', gui = 'bold,italic'}}, + -- warning_selected = {guifg = {attribute = 'fg', highlight = 'LspDiagnosticsDefaultWarning', gui = 'bold,italic'}}, + -- error_diagnostic_selected = {guifg = {attribute = 'fg', highlight = 'LspDiagnosticsSignError', gui = 'bold,italic'}}, + -- error_selected = {guifg = {attribute = 'fg', highlight = 'LspDiagnosticsDefaultError', gui = 'bold,italic'}} + } + } +end + +-- FIX: wait for config migration to setup() +function M.nvimtree_conf() + vim.g.nvim_tree_gitignore = 1 + vim.g.nvim_tree_ignore = {'.git', '.hg', '.svn', 'node_modules'} + vim.g.nvim_tree_auto_ignore_ft = {'dashboard', 'alpha'} + vim.g.nvim_tree_indent_markers = 1 + vim.g.nvim_tree_git_hl = 1 + vim.g.nvim_tree_highlight_opened_files = 1 + -- vim.g.nvim_tree_add_trailing = 1 + -- vim.g.nvim_tree_disable_window_picker = 1 + -- vim.g.nvim_tree_symlink_arrow = ' ➛ ' + vim.g.nvim_tree_respect_buf_cwd = 1 + -- vim.g.nvim_tree_create_in_closed_folder = 1 + vim.g.nvim_tree_icons = { + default = '', + symlink = '', + git = { + unstaged = '', + staged = '', + unmerged = '', + renamed = '', + untracked = 'ﱡ', + deleted = '', + ignored = '' + }, + folder = { + arrow_open = '', + arrow_closed = '', + default = '', + open = 'ﱮ', + empty = '', + empty_open = '', + symlink = '', + symlink_open = 'ﱮ' + } + } + + require('nvim-tree').setup { + open_on_setup = false, + ignore_ft_on_setup = {'dashboard', 'alpha'}, + auto_close = true, + open_on_tab = false, + hijack_cursor = true, + update_cwd = true, + update_to_buf_dir = { + enable = false, + auto_open = true + }, + diagnostics = { + enable = true, + icons = { + hint = '', + info = '', + warning = '', + error = '' + } + }, + update_focused_file = { + enable = true, + update_cwd = true, + ignore_list = {} + }, + system_open = { + cmd = 'xdg-open', + args = {} + }, + filters = { + dotfiles = false + }, + view = { + width = 35, + hide_root_folder = false, + side = 'left', + auto_resize = false + } + } +end + +function M.whichkey_conf() + require('which-key').setup { + plugins = { + spelling = { + enabled = true, + suggestions = 30 + } + }, + icons = { + breadcrumb = '»', + separator = 'ﰲ', + group = '+' + }, + layout = { + align = 'center' + } + } +end + +function M.gitsigns_conf() + require('gitsigns').setup { + signs = { + add = {hl = 'DiffAdd' , text = '', numhl='GitSignsAddNr'}, + change = {hl = 'DiffChange', text = '', numhl='GitSignsChangeNr'}, + delete = {hl = 'DiffDelete', text = '', numhl='GitSignsDeleteNr'}, + topdelete = {hl = 'DiffDelete', text = '', numhl='GitSignsDeleteNr'}, + changedelete = {hl = 'DiffChange', text = '', numhl='GitSignsChangeNr'} + }, + signcolumn = false, + numhl = true, + linehl = false, + word_diff = false, + keymaps = { + -- Default keymap options + noremap = true, + + ['n ]g'] = {expr = true, '&diff ? \']g\' : \':lua require"gitsigns.actions".next_hunk()\''}, + ['n [g'] = {expr = true, '&diff ? \'[g\' : \':lua require"gitsigns.actions".prev_hunk()\''}, + + ['n gs'] = ':lua require"gitsigns".stage_hunk()', + ['v gs'] = ':lua require"gitsigns".stage_hunk({vim.fn.line("."), vim.fn.line("v")})', + ['n gu'] = ':lua require"gitsigns".undo_stage_hunk()', + ['n gr'] = ':lua require"gitsigns".reset_hunk()', + ['v gr'] = ':lua require"gitsigns".reset_hunk({vim.fn.line("."), vim.fn.line("v")})', + ['n gR'] = ':lua require"gitsigns".reset_buffer()', + ['n gp'] = ':lua require"gitsigns".preview_hunk()', + ['n gb'] = ':lua require"gitsigns".blame_line(true)', + ['n gS'] = ':lua require"gitsigns".stage_buffer()', + ['n gU'] = ':lua require"gitsigns".reset_buffer_index()', + + -- Text objects + ['o ih'] = ':lua require"gitsigns.actions".select_hunk()', + ['x ih'] = ':lua require"gitsigns.actions".select_hunk()' + }, + watch_gitdir = { + interval = 1000, + follow_files = true + }, + attach_to_untracked = true, + current_line_blame = false, + current_line_blame_opts = { + delay = 1000, + virt_text = true, + virt_text_pos = 'right_align' + }, + current_line_blame_formatter_opts = { + relative_time = false + }, + sign_priority = 6, + update_debounce = 100, + status_formatter = nil, -- Use default + max_file_length = 40000, + preview_config = { + -- Options passed to nvim_open_win + border = 'single', + style = 'minimal', + relative = 'cursor', + row = 0, + col = 1 + }, + yadm = { + enable = false + }, + diff_opts = { + algorithm = 'myers', -- others: 'minimal', 'patience', 'histogram' + internal = true -- If luajit is present + } + } +end + +return M diff --git a/roles/nvim/files/lua/options.lua b/roles/nvim/files/lua/options.lua new file mode 100644 index 0000000..5bdeceb --- /dev/null +++ b/roles/nvim/files/lua/options.lua @@ -0,0 +1,156 @@ +local opt = vim.opt +local M = {} + +function M.disable_default_plugins() + vim.g.loaded_gzip = 1 + vim.g.loaded_tar = 1 + vim.g.loaded_tarPlugin = 1 + vim.g.loaded_zip = 1 + vim.g.loaded_zipPlugin = 1 + vim.g.loaded_getscript = 1 + vim.g.loaded_getscriptPlugin = 1 + vim.g.loaded_vimball = 1 + vim.g.loaded_vimballPlugin = 1 + vim.g.loaded_matchit = 1 + vim.g.loaded_matchparen = 1 + vim.g.loaded_2html_plugin = 1 + vim.g.loaded_logiPat = 1 + vim.g.loaded_rrhelper = 1 + vim.g.loaded_netrw = 1 + vim.g.loaded_netrwPlugin = 1 + vim.g.loaded_netrwSettings = 1 + vim.g.loaded_netrwFileHandlers = 1 + vim.g.did_load_filetypes = 1 -- use filetype.nvim instead +end + +function M.load_options() + -- This is the same as `:colorscheme nord/onedark` + vim.g.colors_name = 'nord' + -- Leader key + vim.g.mapleader = ' ' + -- Python path + vim.g.python3_host_prog = '/usr/bin/python3' + + -- General settings + opt.termguicolors = true + opt.mouse = 'nv' + opt.errorbells = false + opt.visualbell = false + -- opt.hidden = true + opt.fileformats = 'unix' + opt.magic = true + opt.virtualedit = 'block' + opt.encoding = 'utf-8' + opt.fileencoding = 'utf-8' + opt.clipboard = 'unnamedplus' + opt.wildignorecase = true + opt.wildignore = '.git,.hg,.svn,*.pyc,*.o,*.out,*.jpg,*.jpeg,*.png,*.gif,*.zip,**/tmp/**,*.DS_Store,**/node_modules/**' + -- opt.history = 10000 + -- opt.showmode = false + opt.jumpoptions = 'stack' + opt.formatoptions = '1jcroql' + opt.shortmess = 'aoOTIcF' + -- opt.startofline = false + opt.wrap = false + opt.sidescrolloff = 4 + opt.scrolloff = 4 + opt.whichwrap = '<,>,[,],~' + -- opt.ruler = true + -- opt.display = 'lastline' + -- opt.colorcolumn = '80' + -- opt.cursorline = true + -- opt.backspace = 'indent,eol,start' + opt.showcmd = false + opt.inccommand = 'nosplit' + -- opt.cmdheight = 2 + -- opt.cmdwinheight = 6 + opt.showtabline = 2 + -- opt.laststatus = 2 + -- opt.textwidth = 80 + opt.synmaxcol = 2500 + -- opt.shell = 'bash' + opt.grepformat = '%f:%l:%c:%m' + opt.grepprg = 'rg --hidden --vimgrep --smart-case --' + opt.diffopt = 'filler,iwhite,internal,algorithm:patience' + -- opt.spell = true + + -- Transparency + opt.pumblend = 5 + opt.winblend = 5 + + -- Conceal + opt.conceallevel = 2 + opt.concealcursor = 'niv' + -- opt.foldenable = true + opt.foldlevelstart = 99 + + -- Case insensitive + opt.ignorecase = true + opt.smartcase = true + opt.infercase = true + + -- Searching + -- opt.incsearch = true + opt.hlsearch = false + -- opt.wrapscan = true + + -- Update time + -- opt.timeout = true + -- opt.ttimeout = true + opt.timeoutlen = 500 + opt.ttimeoutlen = 25 + opt.updatetime = 150 + opt.redrawtime = 1500 + + -- No swapfile + opt.backup = false + opt.writebackup = false + opt.swapfile = false + + -- Completion menu + -- opt.wildmenu = true + opt.wildmode = 'full' + opt.complete = '.,w,b,k' + opt.completeopt = 'menu,menuone,noselect' + opt.pumheight = 16 + opt.helpheight = 12 + opt.previewheight = 12 + + -- Window rules + opt.splitbelow = true + opt.splitright = true + opt.switchbuf = 'useopen' + opt.winwidth = 30 + opt.winminwidth = 10 + opt.equalalways = false + + -- Left column + opt.signcolumn = 'yes' + opt.number = true + opt.relativenumber = true + -- opt.numberwidth = 6 + + -- 4 spaces = 1 tab + opt.shiftwidth = 4 + opt.tabstop = 4 + opt.softtabstop = -1 -- fallback to 'shiftwidth' + opt.smarttab = true + opt.expandtab = true + opt.smartindent = true + -- opt.autoindent = true + opt.shiftround = true + + -- Trailings, line break + opt.list = true + opt.listchars = 'tab:»·,nbsp:+,trail:·,extends:→,precedes:←' + opt.showbreak = '↳ ' + -- opt.linebreak = true + -- opt.breakat = [[\ \ ;:,!?]] + -- opt.breakindentopt = 'shift:4,min:20' + + -- Undo file path + opt.undofile = true + -- opt.undodir = vim.fn.stdpath('data') .. '/undo' +end + +return M diff --git a/roles/nvim/files/lua/plugins.lua b/roles/nvim/files/lua/plugins.lua new file mode 100644 index 0000000..62c9461 --- /dev/null +++ b/roles/nvim/files/lua/plugins.lua @@ -0,0 +1,461 @@ +local packer = require('modules.pack') + +-- This is recommended when using `luafile ` a lot +-- packer.reset() + +return packer.startup(function(use) + use {'wbthomason/packer.nvim', opt = true} + + --------------------------------- + -- Plugins used by many others -- + --------------------------------- + use {'kyazdani42/nvim-web-devicons', module = 'nvim-web-devicons'} + use {'nvim-lua/plenary.nvim', module = 'plenary'} + use {'nvim-lua/popup.nvim', module = 'popup'} + + -------- + -- UI -- + -------- + local ui = require('modules.ui') + use { + 'goolord/alpha-nvim', + event = 'VimEnter', + config = ui.dashboard_conf + } + use { + 'famiu/feline.nvim', + event = 'VimEnter', + wants = 'nvim-web-devicons', + config = ui.statusline_conf + } + use { + 'akinsho/bufferline.nvim', + event = {'BufRead', 'BufNewFile'}, + config = ui.bufferline_conf + } + use { + 'kyazdani42/nvim-tree.lua', + cmd = 'NvimTreeToggle', + config = ui.nvimtree_conf + } + use { + 'folke/which-key.nvim', + event = 'VimEnter', + config = ui.whichkey_conf + } + use { + 'lewis6991/gitsigns.nvim', + event = {'BufRead', 'BufNewFile'}, + wants = 'plenary.nvim', + config = ui.gitsigns_conf + } + + ------------ + -- Editor -- + ------------ + local editor = require('modules.editor') + use { + 'norcalli/nvim-colorizer.lua', + cmd = 'ColorizerToggle', + config = editor.colorizer_conf + } + use { + 'RRethy/vim-illuminate', + event = 'CursorHold', + setup = editor.illuminate_conf + } + use { -- TODO: config, check out fennel-repl.nvim + 'Olical/conjure', + ft = {'clojure', 'fennel', 'scheme', 'hy', 'janet', 'racket'} + } + use { + 'nvim-treesitter/nvim-treesitter', + run = ':TSUpdate', + event = 'BufRead', + config = editor.treesitter_conf + } + use {'p00f/nvim-ts-rainbow', after = 'nvim-treesitter'} + use {'nvim-treesitter/playground', after = 'nvim-treesitter'} + use {'romgrk/nvim-treesitter-context', after = 'nvim-treesitter'} + use {'nvim-treesitter/nvim-treesitter-textobjects', after = 'nvim-treesitter'} + use {'JoosepAlviste/nvim-ts-context-commentstring', after = 'nvim-treesitter'} + use { + 'lukas-reineke/indent-blankline.nvim', + after = 'nvim-treesitter', + config = editor.blankline_conf + } + use { + 'mizlan/iswap.nvim', + cmd = {'ISwapWith', 'ISwap'}, + wants = 'nvim-treesitter', + config = editor.iswap_conf + } + use { + 'andymass/vim-matchup', + after = 'nvim-treesitter', + config = editor.matchup_conf + } + use {'machakann/vim-sandwich', keys = 's'} -- TODO: check out surround.nvim + use { + 'folke/zen-mode.nvim', + cmd = 'ZenMode', + wants = 'twilight.nvim', + requires = {{ + 'folke/twilight.nvim', + cmd = {'Twilight', 'TwilightEnable'}, + config = editor.twilight_conf, + opt = true + }}, + config = editor.zenmode_conf + } + use { + 'max397574/better-escape.nvim', + event = 'InsertCharPre', + config = editor.betterescape_conf + } + use { -- TODO: check out lightspeed.nvim + 'phaazon/hop.nvim', + cmd = {'HopChar1', 'HopChar2', 'HopWord', 'HopPattern', 'HopLine'}, + config = editor.hop_conf + } + use { + 'hrsh7th/vim-eft', + keys = { + {'n', 'f'}, {'x', 'f'}, {'n', 'F'}, {'x', 'F'}, + {'n', 't'}, {'x', 't'}, {'n', 'T'}, {'x', 'T'}, + {'n', ';'}, {'x', ';'} + }, + config = editor.eft_conf + } + use { + 'monaqa/dial.nvim', + keys = { + {'n', ''}, {'v', ''}, {'v', 'g'}, + {'n', ''}, {'v', ''}, {'v', 'g'} + }, + config = editor.dial_conf + } + use {'junegunn/vim-easy-align', cmd = {'EasyAlign', 'LiveEasyAlign'}} + use { + 'numToStr/Comment.nvim', + keys = {'gc', 'gb'}, + wants = 'nvim-ts-context-commentstring', + config = editor.comment_conf + } + use { + 'winston0410/range-highlight.nvim', + event = 'CmdlineEnter', + wants = 'cmd-parser.nvim', + requires = {{'winston0410/cmd-parser.nvim', opt = true}}, + config = editor.range_conf + } + use { + 'danymat/neogen', + keys = 'eg', + wants = 'nvim-treesitter', + config = editor.neogen_conf + } + use { + 'gpanders/editorconfig.nvim', + event = {'BufRead', 'BufNewFile'} + } + use { -- TODO: move to nvim-parinfer (lua) + 'eraserhd/parinfer-rust', + run = 'cargo build --release', + ft = {'clojure', 'lisp', 'scheme', 'fennel', 'racket', 'hy', 'janet', 'carp', 'wast'} + } + use { + 'ahmedkhalf/project.nvim', + event = 'BufEnter', + config = editor.project_conf + } + use { + 'ruifm/gitlinker.nvim', + wants = 'plenary.nvim', + keys = {'gy', 'gY'}, + config = editor.gitlinker_conf + } + use {'jbyuki/venn.nvim', cmd = 'VBox'} + + --------- + -- LSP -- + --------- + local lsp = require('modules.lsp') + use { + 'neovim/nvim-lspconfig', + event = 'BufReadPre', + wants = {'lsp_signature.nvim', 'lspsaga.nvim', 'null-ls.nvim'}, + requires = { + { + 'ray-x/lsp_signature.nvim', + config = lsp.signature_conf, + opt = true + }, + { + 'tami5/lspsaga.nvim', + branch = 'nvim51', + config = lsp.saga_conf, + opt = true + }, + { -- TODO: scripts to install linters/formatters, config + 'jose-elias-alvarez/null-ls.nvim', + wants = 'plenary.nvim', opt = true + } + }, + config = lsp.lsp_conf + } + use { + 'nanotee/sqls.nvim', + ft = {'sql', 'mysql'}, + wants = 'nvim-lspconfig', + config = lsp.sqls_conf + } + use { + 'kosayoda/nvim-lightbulb', + after = 'nvim-lspconfig', + config = lsp.lightbulb_conf + } + use { + 'folke/trouble.nvim', + cmd = {'Trouble', 'TroubleToggle', 'TroubleRefresh'}, + config = lsp.trouble_conf + } + use { + 'folke/todo-comments.nvim', + wants = 'plenary.nvim', + event = 'BufRead', + config = lsp.comments_conf + } + use { + 'simrat39/symbols-outline.nvim', + cmd = {'SymbolsOutline', 'SymbolsOutlineOpen'}, + setup = lsp.outline_conf + } + use { -- TODO: config, scripts to install/update dap servers + 'rcarriga/nvim-dap-ui', + keys = 'd', + wants = 'nvim-dap', + requires = {{ + 'mfussenegger/nvim-dap', + config = lsp.dap_conf, + opt = true + }}, + config = lsp.dapui_conf + } + + ---------------- + -- Completion -- + ---------------- + local completion = require('modules.completion') + use { + 'hrsh7th/nvim-cmp', + event = {'InsertEnter', 'CmdlineEnter'}, + wants = {'LuaSnip', 'cmp-under-comparator'}, + requires = { + { + 'L3MON4D3/LuaSnip', + wants = 'friendly-snippets', + requires = {{'rafamadriz/friendly-snippets', opt = true}}, + config = completion.snippets_conf, + opt = true + }, + {'lukas-reineke/cmp-under-comparator', opt = true} + }, + config = completion.cmp_conf + } + use {'saadparwaiz1/cmp_luasnip', after = 'nvim-cmp'} + use {'hrsh7th/cmp-path', after = 'nvim-cmp'} + use {'hrsh7th/cmp-buffer', after = 'nvim-cmp'} + use {'hrsh7th/cmp-calc', after = 'nvim-cmp'} + use {'uga-rosa/cmp-dictionary', after = 'nvim-cmp'} -- TODO: scripts to curl dicts from aspell.net + use {'hrsh7th/cmp-nvim-lsp', after = {'nvim-cmp', 'nvim-lspconfig'}} + -- use { + -- 'tzachar/cmp-tabnine', + -- after = 'nvim-cmp', + -- run = './install.sh', + -- config = completion.tabnine_conf + -- } + use {'kdheepak/cmp-latex-symbols', after = 'nvim-cmp'} + use {'PaterJason/cmp-conjure', after = {'conjure', 'nvim-cmp'}} + use { + 'windwp/nvim-autopairs', + after = 'nvim-cmp', + config = completion.autopairs_conf + } + use { + 'windwp/nvim-ts-autotag', + ft = { + 'html', 'javascript', 'javascriptreact', 'typescript', + 'typescriptreact', 'vue', 'svelte' + }, + wants = 'nvim-treesitter', + config = completion.autotag_conf + } + + ----------- + -- Tools -- + ----------- + local tools = require('modules.tools') + use { -- TODO: check out fzf-lua + 'nvim-telescope/telescope.nvim', + cmd = 'Telescope', + wants = { + 'popup.nvim', + 'plenary.nvim', + 'telescope-symbols.nvim', + 'telescope-project.nvim', + 'telescope-fzf-native.nvim' + }, + requires = { + {'nvim-telescope/telescope-symbols.nvim', opt = true}, + {'nvim-telescope/telescope-project.nvim', opt = true}, + {'nvim-telescope/telescope-fzf-native.nvim', run = 'make', opt = true} + }, + config = tools.telescope_conf + } + use { -- TODO: colors + config + 'pwntester/octo.nvim', + cmd = 'Octo', + wants = 'telescope.nvim', + config = tools.octo_conf + } + use { + 'TimUntersberger/neogit', + cmd = 'Neogit', + wants = {'diffview.nvim', 'plenary.nvim'}, + requires = {{ + 'sindrets/diffview.nvim', + cmd = { + 'DiffviewOpen','DiffviewClose', + 'DiffviewToggleFiles', 'DiffviewFocusFiles' + }, + config = tools.diffview_conf, + opt = true + }}, + config = tools.neogit_conf + } + use { -- TODO: replace with code_runner.nvim + 'skywind3000/asynctasks.vim', + cmd = { + 'AsyncTask', + 'AsyncTaskEdit', + 'AsyncTaskList', + 'AsyncTaskMacro' + }, + wants = 'asyncrun.vim', + requires = {{ + 'skywind3000/asyncrun.vim', + setup = tools.asynctasks_conf, + opt = true + }} + } + use { -- TODO: check out kat0h/bufpreview.vim + 'iamcco/markdown-preview.nvim', + run = 'cd app && yarn install', + ft = {'markdown', 'rmd'}, + config = tools.markdown_preview_conf + } + use { + 'turbio/bracey.vim', + run = 'npm install --prefix server', + cmd = 'Bracey' + } + use { -- TODO: check out neorg + 'kristijanhusak/orgmode.nvim', + requires = { + { + 'akinsho/org-bullets.nvim', + after = 'orgmode.nvim', + config = tools.bullets_conf + }, + { + 'lukas-reineke/headlines.nvim', + after = 'orgmode.nvim', + config = tools.headlines_conf + } + }, + ft = 'org', + config = tools.orgmode_conf + } + use { + 'windwp/nvim-spectre', + keys = 'p', + wants = 'plenary.nvim', + config = tools.spectre_conf + } + use { + 'echuraev/translate-shell.vim', + cmd = {'Trans', 'TransSelectDirection'}, + config = tools.translate_conf + } + use { + 'mbbill/undotree', + cmd = 'UndotreeToggle', + setup = tools.undotree_conf + } + use { + 'akinsho/toggleterm.nvim', + cmd = 'ToggleTerm', + config = tools.toggleterm_conf + } + -- use { + -- 'gelguy/wilder.nvim', + -- wants = 'cpsm', + -- requires = {{'nixprime/cpsm', opt = true}}, + -- run = ':UpdateRemotePlugins', + -- event = 'CmdlineEnter', + -- config = tools.wilder_conf + -- } + use { + 'michaelb/sniprun', + run = 'cargo build --release', + cmd = 'SnipRun', + config = tools.sniprun_conf + } + use { + 'NTBBloodbath/rest.nvim', + keys = {'RestNvim', 'RestNvimPreview', 'RestNvimLast'}, + wants = {'plenary.nvim', 'nvim-treesitter'}, + config = tools.rest_conf + } + use { -- TODO: check out auto-session + session-lens + 'folke/persistence.nvim', + event = 'BufReadPre', + keys = 's', + config = tools.session_conf + } + use { + 'nathom/filetype.nvim', + event = {'BufRead', 'BufNewFile'}, + config = tools.filetype_conf + } + use { + 'kazhala/close-buffers.nvim', + cmd = {'BDelete', 'BWipeout'}, + wants = 'bufferline.nvim', + config = tools.closebuf_conf + } + use { + 'sindrets/winshift.nvim', + cmd = 'WinShift', + config = tools.winshift_conf + } + use { + 'FollieHiyuki/window-picker.nvim', + cmd = {'WindowPick', 'WindowSwap', 'WindowSwapStay'}, + config = tools.winpicker_conf + } + use { + 'chipsenkbeil/distant.nvim', + cmd = {'DistantInstall', 'DistantLaunch'}, + config = tools.distant_conf + } + use {'dstein64/vim-startuptime', cmd = 'StartupTime'} -- Just for benchmarking + + -- TODO: rust-tools.nvim, crates.nvim, go.nvim, clojure-vim/*, nvim-bqf, + -- nvim-comment-frame, nvim-revJ.lua, nvim-remote-containers, tex.nvim, + -- telescope-dap.nvim, fcitx.nvim, pandoc.nvim + + -- Install plugins if missing + packer.install() +end) diff --git a/roles/nvim/files/lua/themes/init.lua b/roles/nvim/files/lua/themes/init.lua new file mode 100644 index 0000000..dcc025d --- /dev/null +++ b/roles/nvim/files/lua/themes/init.lua @@ -0,0 +1,23 @@ +local M = {} + +function M.set(theme) + -- Reset everything + vim.api.nvim_command('hi clear') + if vim.fn.exists('syntax_on') then vim.api.nvim_command('syntax reset') end + vim.opt.background = 'dark' + + -- Get theme specs + local t = require('themes.' .. theme) + vim.g.colors_name = theme + + -- Load highlight groups + t.highlight_editor() + t.highlight_syntax() + t.set_vim_termcolors() + t.highlight_plugins() + t.highlight_languages() + t.highlight_treesitter() + t.highlight_lsp() +end + +return M diff --git a/roles/nvim/files/lua/themes/nord/colors.lua b/roles/nvim/files/lua/themes/nord/colors.lua new file mode 100644 index 0000000..66c3840 --- /dev/null +++ b/roles/nvim/files/lua/themes/nord/colors.lua @@ -0,0 +1,22 @@ +local nord = { + black = '#2E3440', + grey1 = '#3B4252', + grey2 = '#434C5E', + grey3 = '#4C566A', + grey_bright = '#616E88', + fg = '#D8DEE9', + white1 = '#E5E9F0', + white2 = '#ECEFF4', + teal = '#8FBCBB', + cyan = '#88C0D0', + blue = '#81A1C1', + dark_blue = '#5E81AC', + red = '#BF616A', + orange = '#D08770', + yellow = '#EBCB8B', + green = '#A3BE8C', + purple = '#B48EAD', + highlight = '#7B88A1' +} + +return nord diff --git a/roles/nvim/files/lua/themes/nord/init.lua b/roles/nvim/files/lua/themes/nord/init.lua new file mode 100644 index 0000000..11df62f --- /dev/null +++ b/roles/nvim/files/lua/themes/nord/init.lua @@ -0,0 +1,435 @@ +local cmd = vim.api.nvim_command +local M = {} + +local c = require('themes.nord.colors') +local hi = require('util').highlight + +-- Set terminal colors +function M.set_vim_termcolors() + vim.g.terminal_color_0 = c.grey1 + vim.g.terminal_color_1 = c.red + vim.g.terminal_color_2 = c.green + vim.g.terminal_color_3 = c.yellow + vim.g.terminal_color_4 = c.blue + vim.g.terminal_color_5 = c.purple + vim.g.terminal_color_6 = c.cyan + vim.g.terminal_color_7 = c.white1 + vim.g.terminal_color_8 = c.grey_bright + vim.g.terminal_color_9 = c.red + vim.g.terminal_color_10 = c.green + vim.g.terminal_color_11 = c.yellow + vim.g.terminal_color_12 = c.blue + vim.g.terminal_color_13 = c.purple + vim.g.terminal_color_14 = c.teal + vim.g.terminal_color_15 = c.white2 +end + +-- Editor related groups +function M.highlight_editor() + -- Editor + hi('NormalFloat', c.fg , c.black, '', '') + hi('FloatBorder', c.fg , '' , '', '') + hi('ColorColumn', '' , c.grey1, '', '') + hi('Cursor' , c.black , c.fg , '', '') + hi('CursorIM' , c.black , c.white1, '', '') + hi('CursorLine' , '' , c.grey1, '', '') + hi('TermCursorNC', '' , c.grey1, '', '') + hi('Underlined' , c.green , '' , 'underline', '') + hi('Ignore' , c.grey1 , '' , '', '') + hi('Error' , c.fg , c.red , '', '') + hi('LineNr' , c.grey3 , '' , '', '') + hi('MatchParen' , c.cyan , c.grey3, '', '') + hi('NonText' , c.highlight, '' , '', '') + hi('EndOfBuffer', c.black , '' , '', '') -- hide filler line ~ completely + hi('Normal' , c.fg , c.black, '', '') + hi('Pmenu' , c.fg , c.grey2, '', '') + hi('PmenuSbar' , c.fg , c.grey2, '', '') + hi('PmenuSel' , c.cyan , c.grey3, '', '') + hi('PmenuThumb' , c.cyan , c.grey3, '', '') + hi('SpecialKey' , c.grey3 , '' , '', '') + hi('SpellBad' , c.red , c.black, 'undercurl', c.red) + hi('SpellCap' , c.yellow, c.black, 'undercurl', c.yellow) + hi('SpellLocal' , c.white1, c.black, 'undercurl', c.white1) + hi('SpellRare' , c.white2, c.black, 'undercurl', c.white2) + hi('Visual' , '' , c.grey2 , '', '') + hi('VisualNOS' , '' , c.grey2 , '', '') + + -- quickfix + hi('QuickFixLine' , '' , c.blue , '', '') + hi('qfLineNr' , c.yellow, '' , '', '') + + -- :checkhealth + hi('healthError' , c.red , c.grey1, '', '') + hi('healthSuccess', c.green , c.grey1, '', '') + hi('healthWarning', c.yellow, c.grey1, '', '') + + -- Gutter + hi('CursorColumn', '' , c.grey1, '', '') + hi('CursorLineNr', c.fg , '' , '', '') + hi('Folded' , c.grey3, c.grey1, '', '') + hi('FoldColumn' , c.grey3, c.black, '', '') + hi('SignColumn' , c.grey1, c.black, '', '') + + -- Navigation + hi('Directory', c.cyan, '', '', '') + + -- Prompt + hi('ErrorMsg' , c.fg , c.red , '', '') + hi('ModeMsg' , c.fg , '' , '', '') + hi('MoreMsg' , c.cyan , '' , '', '') + hi('Question' , c.fg , '' , '', '') + hi('WarningMsg' , c.black, c.yellow, '', '') + hi('WildMenu' , c.cyan , c.grey1 , '', '') + + -- Statusline + hi('StatusLine' , c.cyan, c.grey3, '', '') + hi('StatusLineNC' , c.fg , c.grey3, '', '') + hi('StatusLineTerm' , c.cyan, c.grey3, '', '') + hi('StatusLineTermNC', c.fg , c.grey3, '', '') + + -- Search + hi('IncSearch', c.white2, c.dark_blue, 'underline', '') + hi('Search' , c.grey1 , c.cyan , '' , '') + + -- Tabline + hi('TabLine' , c.fg , c.grey1, '', '') + hi('TabLineFill', c.fg , c.grey1, '', '') + hi('TabLineSel' , c.cyan, c.grey3, '', '') + + -- Window + hi('Title', c.fg, '', '', '') + hi('VertSplit', c.grey_bright, '', '', '') +end + +-- Syntax groups +function M.highlight_syntax() + -- Base syntax + hi('Boolean', c.blue, '', '', '') + hi('Character', c.fg, '', '', '') + hi('Comment', c.grey_bright, '', 'italic', '') + hi('Conceal', '', '', '', '') + hi('Conditional', c.blue, '', '', '') + hi('Constant', c.fg, '', '', '') + hi('Define', c.blue, '', '', '') + hi('Delimiter', c.white2, '', '', '') + hi('Exception', c.blue, '', '', '') + hi('Float', c.purple, '', '', '') + hi('Function', c.cyan, '', '', '') + hi('Identifier', c.fg, '', '', '') + hi('Include', c.blue, '', '', '') + hi('Keyword', c.blue, '', 'bold', '') + hi('Label', c.blue, '', '', '') + hi('Number', c.purple, '', '', '') + hi('Operator', c.blue, '', '', '') + hi('PreProc', c.blue, '', '', '') + hi('Repeat', c.blue, '', '', '') + hi('Special', c.fg, '', '', '') + hi('SpecialChar', c.yellow, '', '', '') + hi('SpecialComment', c.cyan, '', 'italic', '') + hi('Statement', c.blue, '', '', '') + hi('StorageClass', c.blue, '', '', '') + hi('String', c.green, '', '', '') + hi('Structure', c.blue, '', '', '') + hi('Tag', c.fg, '', '', '') + hi('Todo', c.yellow, '', '', '') + hi('Type', c.orange, '', '', '') + hi('Typedef', c.blue, '', '', '') + cmd('hi! link Macro Define') + cmd('hi! link PreCondit PreProc') + cmd('hi! link Variable Identifier') + + -- Diff + hi('DiffAdd' , c.green , c.grey1, '', '') + hi('DiffChange', c.yellow, c.grey1, '', '') + hi('DiffDelete', c.red , c.grey1, '', '') + hi('DiffText' , c.blue , c.grey1, '', '') + -- Legacy diff groups for some plugins + hi('diffOldFile', c.dark_blue, c.grey1, '', '') + hi('diffNewFile', c.blue, c.grey1, '', '') + hi('diffFile', c.cyan, c.grey1, '', '') + hi('diffLine', c.purple, c.grey1, '', '') + hi('diffIndexLine', c.fg, c.grey1, '', '') + cmd('hi! link diffAdded DiffAdd') + cmd('hi! link diffRemoved DiffDelete') + cmd('hi! link diffChanged DiffChange') +end + +-- Things that still don't look right with nvim-treesitter +function M.highlight_languages() + -- sql + cmd('hi! link sqlKeyword Keyword') + cmd('hi! link sqlSpecial Keyword') + + -- markdown + hi('markdownCode', c.fg, '', 'italic', '') + hi('markdownCodeBlock', c.fg, '', 'italic', '') + hi('markdownH1', c.purple, '', 'bold', '') + cmd('hi! link markdownH1Delimiter markdownH1') + hi('markdownH2', c.dark_blue, '', 'bold', '') + cmd('hi! link markdownH2Delimiter markdownH2') + hi('markdownH3', c.blue, '', 'bold', '') + cmd('hi! link markdownH3Delimiter markdownH3') + hi('markdownH4', c.cyan, '', 'bold', '') + cmd('hi! link markdownH4Delimiter markdownH4') + hi('markdownH5', c.teal, '', 'bold', '') + cmd('hi! link markdownH5Delimiter markdownH5') + hi('markdownH6', c.green, '', 'bold', '') + cmd('hi! link markdownH6Delimiter markdownH6') + + -- html + hi('htmlLink', c.green, '', 'underline', '') + cmd('hi! link htmlH1 markdownH1') + cmd('hi! link htmlH2 markdownH2') + cmd('hi! link htmlH3 markdownH3') + cmd('hi! link htmlH4 markdownH4') + cmd('hi! link htmlH5 markdownH5') + cmd('hi! link htmlH6 markdownH6') +end + +-- Treesitter (:h nvim-treesitter-highlights) +function M.highlight_treesitter() + hi('TSAnnotation', c.dark_blue, '', 'italic', '') + hi('TSCharacter', c.green, '', '', '') + hi('TSConstructor', c.blue, '', '', '') + hi('TSConstant', c.yellow, '', '', '') + hi('TSFloat', c.purple, '', '', '') + hi('TSNumber', c.purple, '', '', '') + hi('TSString', c.green, '', '', '') + + hi('TSAttribute', c.purple, '', '', '') + cmd('hi! link TSBoolean Boolean') + hi('TSConstBuiltin', c.teal, '', '', '') + hi('TSConstMacro', c.teal, '', '', '') + hi('TSError', c.red, '', '', '') + hi('TSException', c.purple, '', '', '') + hi('TSField', c.teal, '', '', '') + hi('TSFuncMacro', c.teal, '', '', '') + hi('TSInclude', c.blue, '', '', '') + hi('TSLabel', c.purple, '', '', '') + hi('TSNamespace', c.fg, '', '', '') + hi('TSOperator', c.blue, '', '', '') + hi('TSParameter', c.purple, '', 'italic', '') + hi('TSParameterReference', c.purple, '', 'italic', '') + hi('TSProperty', c.teal, '', '', '') + hi('TSPunctDelimiter', c.fg, '', '', '') + hi('TSPunctBracket', c.cyan, '', '', '') + hi('TSPunctSpecial', c.cyan, '', '', '') + hi('TSStringRegex', c.teal, '', '', '') + hi('TSStringEscape', c.purple, '', '', '') + hi('TSSymbol', c.purple, '', '', '') + hi('TSType', c.orange, '', '', '') + hi('TSTypeBuiltin', c.orange, '', '', '') + hi('TSTag', c.fg, '', '', '') + hi('TSTagDelimiter', c.purple, '', '', '') + hi('TSText', c.fg, '', '', '') + hi('TSTextReference', c.purple, '', '', '') + hi('TSStrong' , c.fg, '', 'bold', '') + hi('TSEmphasis', c.fg, '', 'bold,italic', '') + hi('TSUnderline', '', '', 'underline', '') + hi('TSTitle', c.dark_blue, '', 'bold', '') + hi('TSLiteral', c.fg, '', '', '') + hi('TSURI', c.green, '', 'underline', '') + + cmd('hi! link TSComment Comment') + hi('TSConditional', c.blue, '', 'bold', '') + hi('TSKeyword', c.blue, '', 'bold', '') + hi('TSRepeat', c.blue, '', 'bold', '') + hi('TSKeywordFunction', c.blue, '', 'bold', '') + hi('TSKeywordOperator', c.blue, '', 'bold', '') + cmd('hi! link TSFunction Function') + hi('TSMethod', c.teal, '', '', '') + cmd('hi! link TSFuncBuiltin Function') + cmd('hi! link TSVariable Variable') + cmd('hi! link TSVariableBuiltin Variable') + cmd('hi! link TSStructure Structure') + + hi('TSNote', c.blue, '', 'bold', '') + hi('TSWarning', c.yellow, '', 'bold', '') + hi('TSDanger', c.red, '', 'bold', '') +end + +-- LSP groups +function M.highlight_lsp() + hi('LspDiagnosticsDefaultError', c.red, '', '', '') + hi('LspDiagnosticsSignError', c.red, '', '', '') + hi('LspDiagnosticsFloatingError', c.red, '', '', '') + hi('LspDiagnosticsVirtualTextError', c.red, '', 'italic', '') + hi('LspDiagnosticsUnderlineError', '', '', 'undercurl', c.red) + + hi('LspDiagnosticsDefaultWarning', c.yellow, '', '', '') + hi('LspDiagnosticsSignWarning', c.yellow, '', '', '') + hi('LspDiagnosticsFloatingWarning', c.yellow, '', '', '') + hi('LspDiagnosticsVirtualTextWarning', c.yellow, '', 'italic', '') + hi('LspDiagnosticsUnderlineWarning', '', '', 'undercurl', c.yellow) + + hi('LspDiagnosticsDefaultInformation', c.blue, '', '', '') + hi('LspDiagnosticsSignInformation', c.blue, '', '', '') + hi('LspDiagnosticsFloatingInformation', c.blue, '', '', '') + hi('LspDiagnosticsVirtualTextInformation', c.blue, '', 'italic', '') + hi('LspDiagnosticsUnderlineInformation', '', '', 'undercurl', c.blue) + + hi('LspDiagnosticsDefaultHint', c.cyan, '', '', '') + hi('LspDiagnosticsSignHint', c.cyan, '', '', '') + hi('LspDiagnosticsFloatingHint', c.cyan, '', '', '') + hi('LspDiagnosticsVirtualTextHint', c.cyan, '', 'italic', '') + hi('LspDiagnosticsUnderlineHint', '', '', 'undercurl', c.cyan) + + hi('LspReferenceText', c.fg, c.grey_bright, '', '') + hi('LspReferenceRead', c.fg, c.grey_bright, '', '') + hi('LspReferenceWrite', c.fg, c.grey_bright, '', '') + cmd('hi! link LspCodeLens Comment') +end + +-- Specify groups for plugins +function M.highlight_plugins() + -- nvim-cmp + hi('CmpItemAbbr', c.fg, '', '', '') + hi('CmpItemAbbrMatch', c.yellow, '', '', '') + hi('CmpItemAbbrMatchFuzzy', c.yellow, '', '', '') + hi('CmpItemKind', c.orange, '', '', '') + hi('CmpItemMenu', c.blue, '', '', '') + + -- LuaSnip + hi('LuaSnipChoice', c.orange, '', '', '') + hi('LuaSnipInsert', c.blue, '', '', '') + + -- Gitsigns + hi('GitSignsAddNr' , c.green , '', '', '') + hi('GitSignsChangeNr', c.yellow, '', '', '') + hi('GitSignsDeleteNr', c.red , '', '', '') + hi('GitSignsCurrentLineBlame', c.grey_bright, '', 'italic,bold', '') + + -- dap.nvim + hi('DapSignDefault', c.orange, '', '', '') + hi('DapSignRejected', c.red, '', '', '') + + -- ts-rainbow + hi('rainbowcol1', c.red, '', 'bold', '') + hi('rainbowcol2', c.orange, '', 'bold', '') + hi('rainbowcol3', c.yellow, '', 'bold', '') + hi('rainbowcol4', c.green, '', 'bold', '') + hi('rainbowcol5', c.cyan, '', 'bold', '') + hi('rainbowcol6', c.blue, '', 'bold', '') + hi('rainbowcol7', c.purple, '', 'bold', '') + + -- hop.nvim + hi('HopNextKey', c.red, '', 'bold', '') + hi('HopNextKey1', c.cyan, '', 'bold', '') + hi('HopNextKey2', c.dark_blue, '', '', '') + cmd('hi! link HopUnmatched LineNr') + + -- vim-eft + hi('EftChar', c.orange, '', 'bold,underline', '') + cmd('hi! link EftSubChar LineNr') + + -- dashboard-nvim / alpha-nvim + hi('DashboardHeader' , c.blue , '', 'bold' , '') + hi('DashboardCenter' , c.green , '', 'bold' , '') + hi('DashboardShortcut', c.grey_bright, '', 'bold,italic', '') + hi('DashboardFooter' , c.purple , '', 'bold' , '') + + -- symbols-outline.nvim + hi('FocusedSymbol', c.yellow, '', 'bold', '') + hi('SymbolsOutlineConnector', c.blue, '', '', '') + + -- NvimTree + hi('NvimTreeNormal' , c.fg , '', '', '') + hi('NvimTreeIndentMarker' , c.grey3 , '', '', '') + hi('NvimTreeFolderIcon' , c.fg , '', '', '') + hi('NvimTreeRootFolder' , c.teal , '', 'bold', '') + hi('NvimTreeFolderName' , c.blue , '', '', '') + hi('NvimTreeEmptyFolderName', c.grey_bright, '', '', '') + hi('NvimTreeImageFile' , c.yellow , '', '', '') + hi('NvimTreeExecFile' , c.green , '', '', '') + hi('NvimTreeSpecialFile' , c.dark_blue , '', 'underline', '') + hi('NvimTreeGitDirty' , c.yellow , '', '', '') + hi('NvimTreeGitNew' , c.green , '', '', '') + hi('NvimTreeGitDeleted' , c.red , '', '', '') + + -- WhichKey + hi('WhichKey' , c.green , '', 'bold', '') + hi('WhichKeyGroup' , c.cyan , '', '' , '') + hi('WhichKeyDesc' , c.purple , '', '' , '') + hi('WhichKeySeperator', c.grey_bright, '', '' , '') + cmd('hi! link WhichKeyFloat NormalFloat') + cmd('hi! link WhichKeyValue Comment') + + -- Indent Blankline + hi('IndentBlanklineChar', c.grey1, '', '', '') + hi('IndentBlanklineContextChar', c.grey_bright, '', '', '') + + -- nvim-treesitter-context + cmd('hi! link TreesitterContext Pmenu') + + -- window-picker.nvim + hi('WindowPicker', c.fg, c.blue, 'bold', '') + hi('WindowPickerSwap', c.fg, c.orange, 'bold', '') + + -- vim-illuminate + hi('illuminatedWord', '', '', 'underline', '') + hi('illuminatedCurWord', '', '', 'underline', '') + + -- trouble.nvim + hi('LspTroubleText', c.blue, '', 'bold', '') + + -- lspsaga + hi('LspSagaFinderSelection', c.green, '', 'bold', '') + cmd('hi! link LspFloatWinNormal NormalFloat') + cmd('hi! link LspFloatWinBorder FloatBorder') + hi('LspSagaBorderTitle', c.yellow, '', 'bold', '') + hi('TargetWord', c.blue, '', 'bold', '') + hi('ProviderTruncateLine', c.black, '', '', '') + hi('SagaShadow', '', c.black, '', '') + hi('DiagnosticTruncateLine', c.blue, '', 'bold', '') + cmd('hi! link DiagnosticError LspDiagnosticsDefaultError') + cmd('hi! link DiagnosticWarning LspDiagnosticsDefaultWarning') + cmd('hi! link DiagnosticInformation LspDiagnosticsDefaultInformation') + cmd('hi! link DiagnosticHint LspDiagnosticsDefaultHint') + hi('LspSagaDiagnosticBorder', c.purple, '', '', '') + hi('LspSagaDiagnosticHeader', c.yellow, '', 'bold', '') + hi('LspSagaDiagnosticTruncateLine', c.purple, '', '', '') + cmd('hi! link LspSagaDiagnosticFloatingError LspDiagnosticsDefaultError') + cmd('hi! link LspSagaDiagnosticFloatingWarn LspDiagnosticsDefaultWarning') + cmd('hi! link LspSagaDiagnosticFloatingInfor LspDiagnosticsDefaultInformation') + cmd('hi! link LspSagaDiagnosticFloatingHint LspDiagnosticsDefaultHint') + hi('LspSagaShTruncateLine', c.black, '', '', '') + hi('LspSagaDocTruncateLine', c.black, '', '', '') + hi('LspSagaCodeActionTitle', c.orange, '', 'bold', '') + hi('LspSagaCodeActionTruncateLine', c.black, '', '', '') + hi('LspSagaCodeActionContent', c.green, '', 'bold', '') + hi('LspSagaRenamePromptPrefix', c.green, '', '', '') + hi('LspSagaRenameBorder', c.cyan, '', '', '') + hi('LspSagaHoverBorder', c.blue, '', '', '') + hi('LspSagaSignatureHelpBorder', c.green, '', '', '') + hi('LspSagaLspFinderBorder', c.blue, '', '', '') + hi('LspSagaCodeActionBorder', c.teal, '', '', '') + hi('LspSagaAutoPreview', c.yellow, '', '', '') + hi('LspSagaDefPreviewBorder', c.teal, '', '', '') + -- hi('LspSagaLightBulb', c.green, '', '', '') + + -- Telescope + hi('TelescopePromptBorder', c.cyan, '', 'bold', '') + hi('TelescopeResultsBorder', c.blue, '', 'bold', '') + hi('TelescopePreviewBorder', c.green, '', 'bold', '') + hi('TelescopeSelection', c.fg, c.grey2, '', '') + hi('TelescopeMultiSelection', c.fg, c.grey2, 'bold', '') + hi('TelescopeSelectionCaret', c.red, c.grey2, 'bold', '') + hi('TelescopeMatching', c.yellow, '', 'bold', '') + hi('TelescopePromptTitle', c.black, c.cyan, 'bold', '') + hi('TelescopePreviewTitle', c.black, c.green, 'bold', '') + hi('TelescopeResultsTitle', c.black, c.blue, 'bold', '') + + -- Neogit + hi('NeogitBranch', c.purple, '', '', '') + hi('NeogitRemote', c.blue, '', '', '') + hi('NeogitHunkHeader', c.cyan, c.grey2, 'bold', '') + hi('NeogitHunkHeaderHighlight', c.yellow, c.grey2, 'bold', '') + hi('NeogitDiffContextHighlight', c.fg, c.grey2, '', '') + hi('NeogitDiffDeleteHighlight', c.red, c.grey2, '', '') + hi('NeogitDiffAddHighlight', c.green, c.grey2, '', '') + hi('NeogitNotificationInfo', c.green, '', '', '') + hi('NeogitNotificationWarning', c.yellow, '', '', '') + hi('NeogitNotificationError', c.red, '', '', '') +end + +return M diff --git a/roles/nvim/files/lua/themes/onedark/colors.lua b/roles/nvim/files/lua/themes/onedark/colors.lua new file mode 100644 index 0000000..df98933 --- /dev/null +++ b/roles/nvim/files/lua/themes/onedark/colors.lua @@ -0,0 +1,23 @@ +local onedark = { + black = '#282C34', + grey1 = '#3E4452', + grey2 = '#4B5263', + grey3 = '#5C6470', + grey_bright = '#73797E', + fg = '#ABB2BF', + white1 = '#BBC2CF', + white2 = '#DFDFDF', + teal = '#5699AF', + cyan = '#56B6C2', + blue = '#61AFEF', + dark_blue = '#2257A0', + red = '#E06C75', + dark_red = '#BE5046', + orange = '#D19A66', + yellow = '#E5C07B', + green = '#98C379', + purple = '#C678DD', + highlight = '#9CA0A4' +} + +return onedark diff --git a/roles/nvim/files/lua/themes/onedark/init.lua b/roles/nvim/files/lua/themes/onedark/init.lua new file mode 100644 index 0000000..3b7a6f6 --- /dev/null +++ b/roles/nvim/files/lua/themes/onedark/init.lua @@ -0,0 +1,10 @@ +local M = {} + +local c = require('themes.onedark.colors') +local hi = require('util').highlight + +function M.highlight_editor() + hi('ModeMsg', c.fg, '', '', '') +end + +return M diff --git a/roles/nvim/files/lua/util.lua b/roles/nvim/files/lua/util.lua new file mode 100644 index 0000000..466e7e3 --- /dev/null +++ b/roles/nvim/files/lua/util.lua @@ -0,0 +1,13 @@ +local M = {} + +function M.highlight(group, guifg, guibg, attr, guisp) + local fg = guifg ~= '' and 'guifg=' .. guifg or 'guifg=NONE' + local bg = guibg ~= '' and 'guibg=' .. guibg or 'guibg=NONE' + local style = attr ~= '' and 'gui=' .. attr or 'gui=NONE' + local sp = guisp ~= '' and 'guisp=' .. guisp or '' + + local hl = 'hi ' .. group .. ' ' .. fg .. ' ' .. bg .. ' ' .. style .. ' ' .. sp + vim.api.nvim_command(hl) +end + +return M diff --git a/roles/nvim/files/scripts/hadolint b/roles/nvim/files/scripts/hadolint new file mode 100755 index 0000000..6b44522 --- /dev/null +++ b/roles/nvim/files/scripts/hadolint @@ -0,0 +1,4 @@ +#!/bin/sh + +podman run --rm -i docker.io/hadolint/hadolint \ + hadolint --no-fail --format=json - < "$@" diff --git a/roles/nvim/files/scripts/install b/roles/nvim/files/scripts/install new file mode 100755 index 0000000..48e744a --- /dev/null +++ b/roles/nvim/files/scripts/install @@ -0,0 +1,35 @@ +#!/bin/sh + +if [ "$#" -ne 1 ]; then + echo "Usage:" + printf " - %s [server_name]: install specified server\n" "$0" + printf " - %s -lsp: install all lsp servers\n" "$0" + printf " - %s -dap: install all dap servers\n" "$0" + printf " - %s -lint: install everything\n" "$0" + exit 1 +fi + +nvim_script_dir=${XDG_CONFIG_HOME:-$HOME/.config}/nvim/scripts + +if [ "$1" = "-lsp" ]; then + printf "\033[1;33mInstalling lsp servers...\033[0m\n" + find "${nvim_script_dir}/lsp" -type f -exec printf "\033[1;34mRunning \033[1;32m%s\033[1;34m...\033[0m\n" '{}' \; -and -exec '{}' \; +elif [ "$1" = '-dap' ]; then + printf "\033[1;33mInstalling dap servers...\033[0m\n" + find "${nvim_script_dir}/dap" -type f -exec printf "\033[1;34mRunning \033[1;32m%s\033[1;34m...\033[0m\n" '{}' \; -and -exec '{}' \; +elif [ "$1" = '-lint' ]; then + printf "\033[1;33mInstalling linters and formatters...\033[0m\n" + find "${nvim_script_dir}/lint" -type f -exec printf "\033[1;34mRunning \033[1;32m%s\033[1;34m...\033[0m\n" '{}' \; -and -exec '{}' \; +elif [ "$1" = '-all' ]; then + printf "\033[1;33mInstalling everything...\033[0m\n" + find "${nvim_script_dir}" -mindepth 2 -type f -exec printf "\033[1;34mRunning \033[1;32m%s\033[1;34m...\033[0m\n" '{}' \; -and -exec '{}' \; +else + # Each server should have an unique name + server_path=$(find "${nvim_script_dir}" -mindepth 2 -type f -name "$1" | head -n 1) + if [ -z "${server_path}" ]; then + printf "Incorrect server name \033[1;31m%s\033[0m.\n" "$1" + exit 1 + fi + printf "\033[1;34mInstalling \033[1;32m%s\033[1;34m...\033[0m\n" "$1" + exec ${server_path} +fi diff --git a/roles/nvim/files/scripts/lint/hadolint b/roles/nvim/files/scripts/lint/hadolint new file mode 100755 index 0000000..4236a12 --- /dev/null +++ b/roles/nvim/files/scripts/lint/hadolint @@ -0,0 +1,3 @@ +#!/bin/sh + +podman pull docker.io/hadolint/hadolint:latest diff --git a/roles/nvim/files/scripts/lsp/ansiblels b/roles/nvim/files/scripts/lsp/ansiblels new file mode 100755 index 0000000..dc54860 --- /dev/null +++ b/roles/nvim/files/scripts/lsp/ansiblels @@ -0,0 +1,19 @@ +#!/bin/sh + +current_path="$PWD" +server_path="${XDG_DATA_HOME:-$HOME/.local/share}/nvim/lsp/ansiblels" + +# Clone / Update +if [ -d "${server_path}" ]; then + cd ${server_path} + git pull +else + git clone https://github.com/ansible/ansible-language-server ${server_path} + cd ${server_path} +fi + +# Build +npm ci +npm run compile + +cd ${current_path} diff --git a/roles/nvim/files/scripts/lsp/bashls b/roles/nvim/files/scripts/lsp/bashls new file mode 100755 index 0000000..b84abb7 --- /dev/null +++ b/roles/nvim/files/scripts/lsp/bashls @@ -0,0 +1,12 @@ +#!/bin/sh + +current_path="$PWD" +server_path="${XDG_DATA_HOME:-$HOME/.local/share}/nvim/lsp/bashls" + +[ ! -d "${server_path}" ] && mkdir -p "${server_path}" +cd ${server_path} + +[ ! -f package.json ] && npm init -y --scope=lsp || true +npm install bash-language-server@latest + +cd ${current_path} diff --git a/roles/nvim/files/scripts/lsp/cmake b/roles/nvim/files/scripts/lsp/cmake new file mode 100755 index 0000000..0793dca --- /dev/null +++ b/roles/nvim/files/scripts/lsp/cmake @@ -0,0 +1,8 @@ +#!/bin/sh + +server_path="${XDG_DATA_HOME:-$HOME/.local/share}/nvim/lsp/cmake" +[ ! -d "${server_path}" ] && mkdir -p "${server_path}" + +python3 -m venv ${server_path}/venv +${server_path}/venv/bin/pip3 install -U pip +${server_path}/venv/bin/pip3 install -U cmake-language-server diff --git a/roles/nvim/files/scripts/lsp/dockerls b/roles/nvim/files/scripts/lsp/dockerls new file mode 100755 index 0000000..8b18d7b --- /dev/null +++ b/roles/nvim/files/scripts/lsp/dockerls @@ -0,0 +1,12 @@ +#!/bin/sh + +current_path="$PWD" +server_path="${XDG_DATA_HOME:-$HOME/.local/share}/nvim/lsp/dockerls" + +[ ! -d "${server_path}" ] && mkdir -p "${server_path}" +cd ${server_path} + +[ ! -f package.json ] && npm init -y --scope=lsp || true +npm install dockerfile-language-server-nodejs@latest + +cd ${current_path} diff --git a/roles/nvim/files/scripts/lsp/efm b/roles/nvim/files/scripts/lsp/efm new file mode 100755 index 0000000..64c799e --- /dev/null +++ b/roles/nvim/files/scripts/lsp/efm @@ -0,0 +1,7 @@ +#!/bin/sh + +server_path="${XDG_DATA_HOME:-$HOME/.local/share}/nvim/lsp/efm" +[ ! -d "${server_path}" ] && mkdir -p "${server_path}" + +GOPATH="${server_path}" GOBIN="${server_path}" go install github.com/mattn/efm-langserver@latest +GOPATH="${server_path}" GOBIN="${server_path}" go clean -modcache diff --git a/roles/nvim/files/scripts/lsp/emmet_ls b/roles/nvim/files/scripts/lsp/emmet_ls new file mode 100755 index 0000000..27e4272 --- /dev/null +++ b/roles/nvim/files/scripts/lsp/emmet_ls @@ -0,0 +1,12 @@ +#!/bin/sh + +current_path="$PWD" +server_path="${XDG_DATA_HOME:-$HOME/.local/share}/nvim/lsp/emmet_ls" + +[ ! -d "${server_path}" ] && mkdir -p "${server_path}" +cd ${server_path} + +[ ! -f package.json ] && npm init -y --scope=lsp || true +npm install emmet-ls@latest + +cd ${current_path} diff --git a/roles/nvim/files/scripts/lsp/gopls b/roles/nvim/files/scripts/lsp/gopls new file mode 100755 index 0000000..485b97e --- /dev/null +++ b/roles/nvim/files/scripts/lsp/gopls @@ -0,0 +1,7 @@ +#!/bin/sh + +server_path="${XDG_DATA_HOME:-$HOME/.local/share}/nvim/lsp/gopls" +[ ! -d "${server_path}" ] && mkdir -p "${server_path}" + +GOPATH="${server_path}" GOBIN="${server_path}" go install golang.org/x/tools/gopls@latest +GOPATH="${server_path}" GOBIN="${server_path}" go clean -modcache diff --git a/roles/nvim/files/scripts/lsp/pyright b/roles/nvim/files/scripts/lsp/pyright new file mode 100755 index 0000000..db0e866 --- /dev/null +++ b/roles/nvim/files/scripts/lsp/pyright @@ -0,0 +1,12 @@ +#!/bin/sh + +current_path="$PWD" +server_path="${XDG_DATA_HOME:-$HOME/.local/share}/nvim/lsp/pyright" + +[ ! -d "${server_path}" ] && mkdir -p "${server_path}" +cd ${server_path} + +[ ! -f package.json ] && npm init -y --scope=lsp || true +npm install pyright@latest + +cd ${current_path} diff --git a/roles/nvim/files/scripts/lsp/sqls b/roles/nvim/files/scripts/lsp/sqls new file mode 100755 index 0000000..576ecc8 --- /dev/null +++ b/roles/nvim/files/scripts/lsp/sqls @@ -0,0 +1,7 @@ +#!/bin/sh + +server_path="${XDG_DATA_HOME:-$HOME/.local/share}/nvim/lsp/sqls" +[ ! -d "${server_path}" ] && mkdir -p "${server_path}" + +GOPATH="${server_path}" GOBIN="${server_path}" go install github.com/lighttiger2505/sqls@latest +GOPATH="${server_path}" GOBIN="${server_path}" go clean -modcache diff --git a/roles/nvim/files/scripts/lsp/sumneko_lua b/roles/nvim/files/scripts/lsp/sumneko_lua new file mode 100755 index 0000000..01fa46b --- /dev/null +++ b/roles/nvim/files/scripts/lsp/sumneko_lua @@ -0,0 +1,26 @@ +#!/bin/sh + +current_path="$PWD" +server_path="${XDG_DATA_HOME:-$HOME/.local/share}/nvim/lsp/sumneko_lua" + +# Clone / Update +if [ -d "${server_path}" ]; then + cd ${server_path} + git pull +else + git clone https://github.com/sumneko/lua-language-server.git ${server_path} + cd ${server_path} +fi + +git submodule update --init --recursive + +# Build +cd 3rd/luamake +./compile/install.sh +cd ../.. +./3rd/luamake/luamake rebuild + +# The build process automatically exports path to `~/.profile` +rm -rf ~/.profile + +cd ${current_path} diff --git a/roles/nvim/files/scripts/lsp/tailwindcss b/roles/nvim/files/scripts/lsp/tailwindcss new file mode 100755 index 0000000..728a18c --- /dev/null +++ b/roles/nvim/files/scripts/lsp/tailwindcss @@ -0,0 +1,12 @@ +#!/bin/sh + +current_path="$PWD" +server_path="${XDG_DATA_HOME:-$HOME/.local/share}/nvim/lsp/tailwindcss" + +[ ! -d "${server_path}" ] && mkdir -p "${server_path}" +cd ${server_path} + +[ ! -f package.json ] && npm init -y --scope=lsp || true +npm install @tailwindcss/language-server + +cd ${current_path} diff --git a/roles/nvim/files/scripts/lsp/tsserver b/roles/nvim/files/scripts/lsp/tsserver new file mode 100755 index 0000000..d62efe3 --- /dev/null +++ b/roles/nvim/files/scripts/lsp/tsserver @@ -0,0 +1,12 @@ +#!/bin/sh + +current_path="$PWD" +server_path="${XDG_DATA_HOME:-$HOME/.local/share}/nvim/lsp/tsserver" + +[ ! -d "${server_path}" ] && mkdir -p "${server_path}" +cd ${server_path} + +[ ! -f package.json ] && npm init -y --scope=lsp || true +npm install typescript@latest typescript-language-server@latest + +cd ${current_path} diff --git a/roles/nvim/files/scripts/lsp/vimls b/roles/nvim/files/scripts/lsp/vimls new file mode 100755 index 0000000..48bd20a --- /dev/null +++ b/roles/nvim/files/scripts/lsp/vimls @@ -0,0 +1,12 @@ +#!/bin/sh + +current_path="$PWD" +server_path="${XDG_DATA_HOME:-$HOME/.local/share}/nvim/lsp/vimls" + +[ ! -d "${server_path}" ] && mkdir -p "${server_path}" +cd ${server_path} + +[ ! -f package.json ] && yarn init -y || true +yarn add vim-language-server@latest + +cd ${current_path} diff --git a/roles/nvim/files/scripts/lsp/vscode b/roles/nvim/files/scripts/lsp/vscode new file mode 100755 index 0000000..7d07bc4 --- /dev/null +++ b/roles/nvim/files/scripts/lsp/vscode @@ -0,0 +1,12 @@ +#!/bin/sh + +current_path="$PWD" +server_path="${XDG_DATA_HOME:-$HOME/.local/share}/nvim/lsp/vscode" + +[ ! -d "${server_path}" ] && mkdir -p "${server_path}" +cd ${server_path} + +[ ! -f package.json ] && npm init -y --scope=lsp || true +npm install vscode-langservers-extracted@latest + +cd ${current_path} diff --git a/roles/nvim/files/scripts/lsp/yamlls b/roles/nvim/files/scripts/lsp/yamlls new file mode 100755 index 0000000..6d03f74 --- /dev/null +++ b/roles/nvim/files/scripts/lsp/yamlls @@ -0,0 +1,12 @@ +#!/bin/sh + +current_path="$PWD" +server_path="${XDG_DATA_HOME:-$HOME/.local/share}/nvim/lsp/yamlls" + +[ ! -d "${server_path}" ] && mkdir -p "${server_path}" +cd ${server_path} + +[ ! -f package.json ] && yarn init -y || true +yarn add yaml-language-server@latest + +cd ${current_path} diff --git a/roles/nvim/tasks/main.yml b/roles/nvim/tasks/main.yml new file mode 100644 index 0000000..8840004 --- /dev/null +++ b/roles/nvim/tasks/main.yml @@ -0,0 +1,24 @@ +- name: Create config directory + file: + path: ~/.config/nvim + state: directory + +- name: Copy config + copy: + src: "{{ ansible_env.PWD }}/roles/nvim/files/{{ item }}" + dest: ~/.config/nvim + force: yes + loop: + - after + - colors + - lua + - .luacheckrc + - asynctasks.ini + - init.lua + +- name: Copy helper scripts + copy: + src: "{{ ansible_env.PWD }}/roles/nvim/files/scripts" + dest: ~/.config/nvim + mode: u+x + force: yes