shameless steal

This commit is contained in:
Christoph J. Scherr 2023-09-06 00:26:45 +02:00
commit 3213bbc114
66 changed files with 7102 additions and 0 deletions

46
init.lua Normal file
View File

@ -0,0 +1,46 @@
-- plex Neovim entry-point
-- https://git.cscherr.de/PlexSheep/neovim-conf
local config = require('plex.config')
config.ensure_lazy()
-- Start lazy.nvim plugin manager.
require('lazy').setup(vim.tbl_extend('keep', config.user_lazy_opts(), {
spec = {
{ import = 'plex.plugins' },
-- { import = 'plex.plugins.extras.lang.go' },
-- { import = 'plex.plugins.extras.lang.json' },
-- { import = 'plex.plugins.extras.lang.python' },
-- { import = 'plex.plugins.extras.lang.yaml' },
-- This will load a custom user lua/plugins.lua or lua/plugins/*
config.has_user_plugins() and { import = 'plugins' } or nil,
},
concurrency = vim.loop.available_parallelism() * 2,
defaults = { lazy = true, version = false },
dev = { path = config.path_join(vim.fn.stdpath('config'), 'dev') },
install = { missing = true, colorscheme = {} },
checker = { enabled = true, notify = false },
change_detection = { notify = false },
ui = { border = 'rounded' },
diff = { cmd = 'terminal_git' },
performance = {
rtp = {
disabled_plugins = {
'gzip',
'vimballPlugin',
'matchit',
'matchparen',
'2html_plugin',
'tarPlugin',
'netrwPlugin',
'tutor',
'zipPlugin',
'vim-lsp',
'lua-ls',
},
},
},
}))
config.setup()

View File

@ -0,0 +1,159 @@
-- Rafi's Neovim autocmds
-- github.com/plex/vim-config
-- ===
-- This file is automatically loaded by plex.config.init
local function augroup(name)
return vim.api.nvim_create_augroup('plex_' .. name, {})
end
-- Check if we need to reload the file when it changed
vim.api.nvim_create_autocmd({ 'FocusGained', 'TermClose', 'TermLeave' }, {
group = augroup('checktime'),
command = 'checktime',
})
-- Go to last loc when opening a buffer, see ':h last-position-jump'
vim.api.nvim_create_autocmd('BufReadPost', {
group = augroup('last_loc'),
callback = function()
local exclude = { 'gitcommit', 'commit', 'gitrebase' }
local buf = vim.api.nvim_get_current_buf()
if vim.tbl_contains(exclude, vim.bo[buf].filetype) then
return
end
local mark = vim.api.nvim_buf_get_mark(buf, '"')
local lcount = vim.api.nvim_buf_line_count(buf)
if mark[1] > 0 and mark[1] <= lcount then
pcall(vim.api.nvim_win_set_cursor, 0, mark)
end
end,
})
-- Show cursor line only in active window
vim.api.nvim_create_autocmd({ 'InsertLeave', 'WinEnter' }, {
group = augroup('auto_cursorline_show'),
callback = function(event)
if vim.bo[event.buf].buftype == '' then
vim.opt_local.cursorline = true
end
end,
})
vim.api.nvim_create_autocmd({ 'InsertEnter', 'WinLeave' }, {
group = augroup('auto_cursorline_hide'),
callback = function(_)
vim.opt_local.cursorline = false
end,
})
-- Highlight on yank
vim.api.nvim_create_autocmd('TextYankPost', {
group = augroup('highlight_yank'),
callback = function()
vim.highlight.on_yank()
end,
})
-- Automatically set read-only for files being edited elsewhere
vim.api.nvim_create_autocmd('SwapExists', {
group = augroup('open_swap'),
nested = true,
callback = function()
vim.v.swapchoice = 'o'
end,
})
-- Create directories when needed, when saving a file (except for URIs "://").
vim.api.nvim_create_autocmd('BufWritePre', {
group = augroup('auto_create_dir'),
callback = function(event)
if event.match:match('^%w%w+://') then
return
end
local file = vim.loop.fs_realpath(event.match) or event.match
vim.fn.mkdir(vim.fn.fnamemodify(file, ':p:h'), 'p')
end,
})
-- Disable conceallevel for specific file-types.
vim.api.nvim_create_autocmd('FileType', {
group = augroup('fix_conceallevel'),
pattern = { 'markdown' },
callback = function()
vim.opt_local.conceallevel = 0
end,
})
-- Resize splits if window got resized
vim.api.nvim_create_autocmd('VimResized', {
group = augroup('resize_splits'),
callback = function()
vim.cmd('wincmd =')
end,
})
-- Wrap and enable spell-checker in text filetypes
vim.api.nvim_create_autocmd('FileType', {
group = augroup('spell_conceal'),
pattern = { 'gitcommit', 'markdown' },
callback = function()
vim.opt_local.spell = true
vim.opt_local.conceallevel = 0
end,
})
-- Close some filetypes with <q>
vim.api.nvim_create_autocmd('FileType', {
group = augroup('close_with_q'),
pattern = {
'blame',
'checkhealth',
'fugitive',
'fugitiveblame',
'help',
'httpResult',
'lspinfo',
'notify',
'PlenaryTestPopup',
'qf',
'spectre_panel',
'startuptime',
'tsplayground',
},
callback = function(event)
vim.bo[event.buf].buflisted = false
-- stylua: ignore
vim.keymap.set('n', 'q', '<cmd>close<CR>', { buffer = event.buf, silent = true })
end,
})
vim.api.nvim_create_autocmd('BufWritePre', {
group = augroup('undo_disable'),
pattern = { '/tmp/*', '*.tmp', '*.bak', 'COMMIT_EDITMSG', 'MERGE_MSG' },
callback = function(event)
vim.opt_local.undofile = false
if event.file == 'COMMIT_EDITMSG' or event.file == 'MERGE_MSG' then
vim.opt_local.swapfile = false
end
end,
})
-- Disable swap/undo/backup files in temp directories or shm
vim.api.nvim_create_autocmd({ 'BufNewFile', 'BufReadPre' }, {
group = augroup('secure'),
pattern = {
'/tmp/*',
'$TMPDIR/*',
'$TMP/*',
'$TEMP/*',
'*/shm/*',
'/private/var/*',
},
callback = function()
vim.opt_local.undofile = false
vim.opt_local.swapfile = false
vim.opt_global.backup = false
vim.opt_global.writebackup = false
end,
})

318
lua/plex/config/init.lua Normal file
View File

@ -0,0 +1,318 @@
-- Rafi's Neovim config loader
-- https://github.com/plex/vim-config
-- This is part of LazyVim's code, with my modifications.
-- See: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/init.lua
---@type RafiConfig
local M = {}
M.lazy_version = '>=9.1.0'
---@class RafiConfig
local defaults = {
-- Load the default settings
-- stylua: ignore
defaults = {
autocmds = true, -- plex.config.autocmds
keymaps = true, -- plex.config.keymaps
-- plex.config.options can't be configured here since it's loaded
-- prematurely. You can disable loading options with the following line at
-- the top of your lua/config/setup.lua or init.lua:
-- `package.loaded['plex.config.options'] = true`
},
-- String like `habamax` or a function that will load the colorscheme.
-- Disabled by default to allow theme-loader.nvim to manage the colorscheme.
---@type string|fun()
colorscheme = '',
features = {
elite_mode = false,
window_q_mapping = true,
},
-- stylua: ignore
icons = {
git = '',
diagnostics = {
Error = '', --   ✘
Warn = '󰀪', -- 󰀪 󰳤 󱦄 󱗓 
Info = '', --    ⁱ 󰋼 󰋽
Hint = '', --  󰌶 
},
status = {
git = {
added = '', --  ₊
modified = '', -- 
removed = '', --  ₋
},
diagnostics = {
error = '',
warn = '',
info = '',
hint = '󰌶 ',
},
filename = {
modified = '+',
readonly = '🔒',
zoomed = '🔎',
},
},
-- Default completion kind symbols.
kinds = {
Array = '󰅪 ', --  󰅪 󰅨 󱃶
Boolean = '', --  ◩ 󰔡 󱃙 󰟡 󰨙
Class = '󰌗 ', --  󰌗 󰠱 𝓒
Color = '󰏘 ', -- 󰸌 󰏘
Constant = '󰏿 ', --   󰏿
Constructor = '󰆧 ', --  󰆧   
Copilot = '', -- 
Enum = '󰕘 ', --  󰕘
EnumMember = '', --  
Event = '', --  
Field = '', -- 󰄶  󰆨  󰀻 󰃒
File = '', --    󰈔 󰈙
Folder = '', --   󰉋
Function = '󰊕 ', --  󰊕 
Interface = '', --    
Key = '', -- 
Keyword = '', --   󰌋 
Method = '󰆧 ', --  󰆧 ƒ
Module = '', --   󰅩 󰆧 󰏗
Namespace = '', --   󰅩
Null = '', --  󰟢
Number = '󰎠 ', --  󰎠 
Object = '', --   󰅩
Operator = '󰃬 ', --  󰃬 󰆕 +
Package = '', --   󰏖 󰏗
Property = '󰖷 ', --  󰜢  
Reference = '󰈝 ', --  󰈝 󰈇
Snippet = '', --  󰘌 ⮡   
String = '󰅳 ', --  󰅳
Struct = '', --   𝓢 󰙅 󱏒
Text = '', --   󰉿 𝓐
TypeParameter = '', --  󰊄 𝙏
Unit = '', --   󰑭 
Value = '', --   󰀬 󰎠
Variable = '', --   󰀫 
},
},
}
M.renames = {}
M.did_init = false
function M.init()
if not M.did_init then
M.did_init = true
-- delay notifications till vim.notify was replaced or after 500ms
require('plex.config').lazy_notify()
-- load options here, before lazy init while sourcing plugin modules
-- this is needed to make sure options will be correctly applied
-- after installing missing plugins
require('plex.config').load('options')
-- carry over plugin options that their name has been changed.
local Plugin = require('lazy.core.plugin')
local add = Plugin.Spec.add
---@diagnostic disable-next-line: duplicate-set-field
Plugin.Spec.add = function(self, plugin, ...)
if type(plugin) == 'table' and M.renames[plugin[1]] then
plugin[1] = M.renames[plugin[1]]
end
return add(self, plugin, ...)
end
end
end
---@type RafiConfig
local options
-- Load plex and user config files.
---@param user_opts table|nil
function M.setup(user_opts)
if not M.did_init then
M.init()
end
options = vim.tbl_deep_extend('force', defaults, user_opts or {})
if not M.has_version() then
require('lazy.core.util').error(
string.format(
'**lazy.nvim** version %s is required.\n Please upgrade **lazy.nvim**',
M.lazy_version
)
)
error('Exiting')
end
-- Override config with user config at lua/config/setup.lua
local ok, user_setup = pcall(require, 'config.setup')
if ok and user_setup.override then
options = vim.tbl_deep_extend('force', options, user_setup.override())
end
for feat_name, feat_val in pairs(options.features) do
vim.g['plex_' .. feat_name] = feat_val
end
M.load('autocmds')
M.load('keymaps')
-- Set colorscheme
require('lazy.core.util').try(function()
if type(M.colorscheme) == 'function' then
M.colorscheme()
elseif #M.colorscheme > 0 then
vim.cmd.colorscheme(M.colorscheme)
end
end, {
msg = 'Could not load your colorscheme',
on_error = function(msg)
require('lazy.core.util').error(msg)
vim.cmd.colorscheme('habamax')
end,
})
end
---@return table
function M.user_lazy_opts()
local ok, user_setup = pcall(require, 'config.setup')
if ok and user_setup.lazy_opts then
return user_setup.lazy_opts()
end
return {}
end
---@param range? string
---@return boolean
function M.has_version(range)
local Semver = require('lazy.manage.semver')
return Semver.range(range or M.lazy_version)
:matches(require('lazy.core.config').version or '0.0.0')
end
---@param name "autocmds" | "options" | "keymaps"
function M.load(name)
local Util = require('lazy.core.util')
local function _load(mod)
Util.try(function()
require(mod)
end, {
msg = 'Failed loading ' .. mod,
on_error = function(msg)
local info = require('lazy.core.cache').find(mod)
if info == nil or (type(info) == 'table' and #info == 0) then
return
end
Util.error(msg)
end,
})
end
-- always load plex's file, then user file
if M.defaults[name] or name == 'options' then
_load('plex.config.' .. name)
end
_load('config.' .. name)
if vim.bo.filetype == 'lazy' then
vim.cmd([[do VimResized]])
end
end
-- Ensure package manager (lazy.nvim) exists.
function M.ensure_lazy()
local lazypath = M.path_join(vim.fn.stdpath('data'), 'lazy', 'lazy.nvim')
if not vim.loop.fs_stat(lazypath) then
print('Installing lazy.nvim…')
vim.fn.system({
'git',
'clone',
'--filter=blob:none',
'--branch=stable',
'https://github.com/folke/lazy.nvim.git',
lazypath,
})
end
vim.opt.rtp:prepend(lazypath)
end
-- Validate if lua/plugins/ or lua/plugins.lua exist.
---@return boolean
function M.has_user_plugins()
local user_path = M.path_join(vim.fn.stdpath('config'), 'lua')
return vim.loop.fs_stat(M.path_join(user_path, 'plugins')) ~= nil
or vim.loop.fs_stat(M.path_join(user_path, 'plugins.lua')) ~= nil
end
-- Delay notifications till vim.notify was replaced or after 500ms.
function M.lazy_notify()
local notifs = {}
local function temp(...)
table.insert(notifs, vim.F.pack_len(...))
end
local orig = vim.notify
vim.notify = temp
local timer = vim.loop.new_timer()
local check = vim.loop.new_check()
if timer == nil or check == nil then
return
end
local replay = function()
timer:stop()
check:stop()
if vim.notify == temp then
vim.notify = orig -- put back the original notify if needed
end
vim.schedule(function()
---@diagnostic disable-next-line: no-unknown
for _, notif in ipairs(notifs) do
vim.notify(vim.F.unpack_len(notif))
end
end)
end
-- wait till vim.notify has been replaced
check:start(function()
if vim.notify ~= temp then
replay()
end
end)
-- or if it took more than 500ms, then something went wrong
timer:start(500, 0, replay)
end
-- Join paths.
---@private
M.path_join = function(...)
return table.concat({ ... }, M.path_sep)
end
-- Variable holds OS directory separator.
---@private
M.path_sep = (function()
if jit then
local os = string.lower(jit.os)
if os ~= 'windows' then
return '/'
else
return '\\'
end
else
return package.config:sub(1, 1)
end
end)()
setmetatable(M, {
__index = function(_, key)
if options == nil then
return vim.deepcopy(defaults)[key]
end
---@cast options RafiConfig
return options[key]
end,
})
return M

359
lua/plex/config/keymaps.lua Normal file
View File

@ -0,0 +1,359 @@
-- Rafi's Neovim keymaps
-- github.com/plex/vim-config
-- ===
-- This file is automatically loaded by plex.config.init
local Util = require('plex.lib.utils')
local map = vim.keymap.set
local function augroup(name)
return vim.api.nvim_create_augroup('plex_' .. name, {})
end
-- Elite-mode: Arrow-keys resize window
if vim.g.plex_elite_mode then
map('n', '<Up>', '<cmd>resize +1<cr>', { desc = 'Resize Window' })
map('n', '<Down>', '<cmd>resize -1<cr>', { desc = 'Resize Window' })
map('n', '<Left>', '<cmd>vertical resize +1<cr>', { desc = 'Resize Window' })
map('n', '<Right>', '<cmd>vertical resize -1<cr>', { desc = 'Resize Window' })
end
-- Package-manager
map('n', '<leader>l', '<cmd>Lazy<cr>', { desc = 'Open Lazy UI' })
-- stylua: ignore start
-- Navigation
-- ===
-- Moves through display-lines, unless count is provided
map({ 'n', 'x' }, 'j', "v:count == 0 ? 'gj' : 'j'", { expr = true, silent = true })
map({ 'n', 'x' }, 'k', "v:count == 0 ? 'gk' : 'k'", { expr = true, silent = true })
-- Easier line-wise movement
map('n', 'gh', 'g^')
map('n', 'gl', 'g$')
map('n', '<Leader><Leader>', 'V', { desc = 'Visual Mode' })
map('x', '<Leader><Leader>', '<Esc>', { desc = 'Exit Visual Mode' })
-- Toggle fold or select option from popup menu
---@return string
map('n', '<CR>', function()
return vim.fn.pumvisible() == 1 and '<CR>' or 'za'
end, { expr = true, desc = 'Toggle Fold' })
-- Focus the current fold by closing all others
map('n', '<S-Return>', 'zMzv', { remap = true, desc = 'Focus Fold' })
-- Location/quickfix list movement
if not Util.has('mini.bracketed') and not Util.has('trouble.nvim') then
map('n', ']q', '<cmd>cnext<CR>', { desc = 'Next Quickfix Item' })
map('n', '[q', '<cmd>cprev<CR>', { desc = 'Previous Quickfix Item' })
end
map('n', ']a', '<cmd>lnext<CR>', { desc = 'Next Loclist Item' })
map('n', '[a', '<cmd>lprev<CR>', { desc = 'Previous Loclist Item' })
-- Whitespace jump (see plugin/whitespace.vim)
map('n', ']s', function()
require('plex.lib.edit').whitespace_jump(1)
end, { desc = 'Next Whitespace' })
map('n', '[s', function()
require('plex.lib.edit').whitespace_jump(-1)
end, { desc = 'Previous Whitespace' })
-- Navigation in command line
map('c', '<C-h>', '<Home>')
map('c', '<C-l>', '<End>')
map('c', '<C-f>', '<Right>')
map('c', '<C-b>', '<Left>')
-- Scroll step sideways
map('n', 'zl', 'z4l')
map('n', 'zh', 'z4h')
-- Clipboard
-- ===
-- Yank buffer's relative path to clipboard
map('n', '<Leader>y', function()
local path = vim.fn.fnamemodify(vim.api.nvim_buf_get_name(0), ':~:.')
vim.fn.setreg('+', path)
vim.notify(path, vim.log.levels.INFO, { title = 'Yanked relative path' })
end, { silent = true, desc = 'Yank relative path' })
-- Yank absolute path
map('n', '<Leader>Y', function()
local path = vim.fn.fnamemodify(vim.api.nvim_buf_get_name(0), ':p')
vim.fn.setreg('+', path)
vim.notify(path, vim.log.levels.INFO, { title = 'Yanked absolute path' })
end, { silent = true, desc = 'Yank absolute path' })
-- Paste in visual-mode without pushing to register
map('x', 'p', 'p:let @+=@0<CR>:let @"=@0<CR>', { silent = true, desc = 'Paste' })
map('x', 'P', 'P:let @+=@0<CR>:let @"=@0<CR>', { silent = true, desc = 'Paste In-place' })
-- Edit
-- ===
-- Macros
map('n', '<C-q>', 'q', { desc = 'Macro Prefix' })
-- Start new line from any cursor position in insert-mode
map('i', '<S-Return>', '<C-o>o', { desc = 'Start Newline' })
-- Re-select blocks after indenting in visual/select mode
map('x', '<', '<gv', { desc = 'Indent Right and Re-select' })
map('x', '>', '>gv|', { desc = 'Indent Left and Re-select' })
-- Use tab for indenting in visual/select mode
map('x', '<Tab>', '>gv|', { desc = 'Indent Left' })
map('x', '<S-Tab>', '<gv', { desc = 'Indent Right' })
-- Drag current line/s vertically and auto-indent
map('n', '<Leader>k', '<cmd>move-2<CR>==', { desc = 'Move line up' })
map('n', '<Leader>j', '<cmd>move+<CR>==', { desc = 'Move line down' })
map('x', '<Leader>k', ":move'<-2<CR>gv=gv", { desc = 'Move selection up' })
map('x', '<Leader>j', ":move'>+<CR>gv=gv", { desc = 'Move selection down' })
-- Duplicate lines without affecting PRIMARY and CLIPBOARD selections.
map('n', '<Leader>d', 'm`""Y""P``', { desc = 'Duplicate line' })
map('x', '<Leader>d', '""Y""Pgv', { desc = 'Duplicate selection' })
-- Duplicate paragraph
map('n', '<Leader>cp', 'yap<S-}>p', { desc = 'Duplicate Paragraph' })
-- Remove spaces at the end of lines
map('n', '<Leader>cw', '<cmd>lua MiniTrailspace.trim()<CR>', { desc = 'Erase Whitespace' })
-- Search & Replace
-- ===
-- Switch */g* and #/g#
map('n', '*', 'g*')
map('n', 'g*', '*')
map('n', '#', 'g#')
map('n', 'g#', '#')
-- Clear search with <Esc>
map('n', '<Esc>', '<cmd>noh<CR>', { desc = 'Clear Search Highlight' })
-- Clear search, diff update and redraw taken from runtime/lua/_editor.lua
map(
'n',
'<leader>ur',
'<cmd>nohlsearch<bar>diffupdate<bar>normal! <C-L><CR>',
{ desc = 'Redraw / clear hlsearch / diff update' }
)
-- Use backspace key for matching parens
map({ 'n', 'x' }, '<BS>', '%', { remap = true, desc = 'Jump to Paren' })
-- Select last paste
map('n', 'gpp', "'`['.strpart(getregtype(), 0, 1).'`]'", { expr = true, desc = 'Select Paste' })
-- Quick substitute within selected area
map('x', 'sg', ':s//gc<Left><Left><Left>', { desc = 'Substitute Within Selection' })
-- C-r: Easier search and replace visual/select mode
map(
'x',
'<C-r>',
":<C-u>%s/\\V<C-R>=v:lua.require'plex.lib.edit'.get_visual_selection()<CR>"
.. '//gc<Left><Left><Left>',
{ desc = 'Replace Selection' }
)
-- Command & History
-- ===
-- Start an external command with a single bang
map('n', '!', ':!', { desc = 'Execute Shell Command' })
-- Put vim command output into buffer
map('n', 'g!', ":put=execute('')<Left><Left>", { desc = 'Paste Command' })
-- Switch history search pairs, matching my bash shell
---@return string
map('c', '<C-p>', function()
return vim.fn.pumvisible() == 1 and '<C-p>' or '<Up>'
end, { expr = true })
map('c', '<C-n>', function()
return vim.fn.pumvisible() == 1 and '<C-n>' or '<Down>'
end, { expr = true })
map('c', '<Up>', '<C-p>')
map('c', '<Down>', '<C-n>')
-- Allow misspellings
vim.cmd.cnoreabbrev('qw', 'wq')
vim.cmd.cnoreabbrev('Wq', 'wq')
vim.cmd.cnoreabbrev('WQ', 'wq')
vim.cmd.cnoreabbrev('Qa', 'qa')
vim.cmd.cnoreabbrev('Bd', 'bd')
vim.cmd.cnoreabbrev('bD', 'bd')
-- File operations
-- ===
-- Switch (window) to the directory of the current opened buffer
map('n', '<Leader>cd', function()
local bufdir = vim.fn.fnamemodify(vim.api.nvim_buf_get_name(0), ':p:h')
if bufdir ~= nil and vim.loop.fs_stat(bufdir) then
vim.cmd.tcd(bufdir)
vim.notify(bufdir)
end
end, { desc = 'Change Local Directory' })
-- Fast saving from all modes
map('n', '<Leader>w', '<cmd>write<CR>', { desc = 'Save' })
map({ 'n', 'i', 'v' }, '<C-s>', '<cmd>write<CR>', { desc = 'Save' })
-- Editor UI
-- ===
-- Toggle editor's visual effects
map('n', '<leader>uf', require('plex.plugins.lsp.format').toggle, { desc = 'Toggle format on Save' })
map('n', '<Leader>us', '<cmd>setlocal spell!<CR>', { desc = 'Toggle Spellcheck' })
map('n', '<Leader>ul', '<cmd>setlocal nonumber!<CR>', { desc = 'Toggle Line Numbers' })
map('n', '<Leader>uo', '<cmd>setlocal nolist!<CR>', { desc = 'Toggle Whitespace Symbols' })
map('n', '<Leader>uu', '<cmd>nohlsearch<CR>', { desc = 'Hide Search Highlight' })
if vim.lsp.inlay_hint then
map('n', '<leader>uh', function() vim.lsp.inlay_hint(0, nil) end, { desc = 'Toggle Inlay Hints' })
end
-- Smart wrap toggle (breakindent and colorcolumn toggle as-well)
map('n', '<Leader>uw', function()
vim.opt_local.wrap = not vim.wo.wrap
vim.opt_local.breakindent = not vim.wo.breakindent
if vim.wo.colorcolumn == '' then
vim.opt_local.colorcolumn = tostring(vim.bo.textwidth)
else
vim.opt_local.colorcolumn = ''
end
end, { desc = 'Toggle Wrap' })
-- Tabs: Many ways to navigate them
map('n', '<A-j>', '<cmd>tabnext<CR>', { desc = 'Next Tab' })
map('n', '<A-k>', '<cmd>tabprevious<CR>', { desc = 'Previous Tab' })
map('n', '<A-[>', '<cmd>tabprevious<CR>', { desc = 'Previous Tab' })
map('n', '<A-]>', '<cmd>tabnext<CR>', { desc = 'Next Tab' })
map('n', '<C-Tab>', '<cmd>tabnext<CR>', { desc = 'Next Tab' })
map('n', '<C-S-Tab>', '<cmd>tabprevious<CR>', { desc = 'Previous Tab' })
-- Moving tabs
map('n', '<A-{>', '<cmd>-tabmove<CR>', { desc = 'Tab Move Backwards' })
map('n', '<A-}>', '<cmd>+tabmove<CR>', { desc = 'Tab Move Forwards' })
-- Show treesitter nodes under cursor
-- highlights under cursor
if vim.fn.has('nvim-0.9') == 1 then
map('n', '<Leader>ui', vim.show_pos, { desc = 'Show Treesitter Node' })
end
-- Custom Tools
-- ===
-- Append mode-line to current buffer
map('n', '<Leader>ml', function()
require('plex.lib.edit').append_modeline()
end, { desc = 'Append Modeline' })
-- Jump entire buffers throughout jumplist
map('n', 'g<C-i>', function()
require('plex.lib.edit').jump_buffer(1)
end, { desc = 'Jump to newer buffer' })
map('n', 'g<C-o>', function()
require('plex.lib.edit').jump_buffer(-1)
end, { desc = 'Jump to older buffer' })
-- Context aware menu. See lua/lib/contextmenu.lua
map('n', '<LocalLeader>c', function()
require('plex.lib.contextmenu').show()
end, { desc = 'Content-aware menu' })
-- Lazygit
map('n', '<leader>tg', function() Util.float_term({ 'lazygit' }, { cwd = Util.get_root(), esc_esc = false }) end, { desc = 'Lazygit (root dir)' })
map('n', '<leader>tG', function() Util.float_term({ 'lazygit' }, { esc_esc = false }) end, { desc = 'Lazygit (cwd)' })
-- Floating terminal
map('t', '<Esc><Esc>', '<C-\\><C-n>', { desc = 'Enter Normal Mode' })
map('n', '<Leader>tt', function() Util.float_term(nil, { cwd = Util.get_root() }) end, { desc = 'Terminal (root dir)' })
map('n', '<Leader>tT', function() Util.float_term() end, { desc = 'Terminal (cwd)' })
if vim.fn.has('mac') then
-- Open the macOS dictionary on current word
map('n', '<Leader>?', '<cmd>silent !open dict://<cword><CR>', { desc = 'Dictionary' })
-- Use Marked for real-time Markdown preview
-- See: https://marked2app.com/
if vim.fn.executable('/Applications/Marked 2.app') then
vim.api.nvim_create_autocmd('FileType', {
group = augroup('marked_preview'),
pattern = 'markdown',
callback = function()
local cmd = "<cmd>silent !open -a Marked\\ 2.app '%:p'<CR>"
map('n', '<Leader>P', cmd, { desc = 'Markdown Preview' })
end,
})
end
end
-- Windows, buffers and tabs
-- ===
-- Ultimatus Quitos
if vim.F.if_nil(vim.g.plex_window_q_mapping, true) then
vim.api.nvim_create_autocmd({ 'BufWinEnter', 'VimEnter' }, {
group = augroup('quit_mapping'),
callback = function(event)
if vim.bo.buftype == '' and vim.fn.maparg('q', 'n') == '' then
local args = { buffer = event.buf, desc = 'Quit' }
map('n', 'q', '<cmd>quit<CR>', args)
end
end,
})
end
-- Toggle quickfix window
map('n', '<Leader>q', function()
require('plex.lib.edit').toggle_list('quickfix')
end, { desc = 'Open Quickfix' })
-- Set locations with diagnostics and open the list.
map('n', '<Leader>a', function()
if vim.bo.filetype ~= 'qf' then
vim.diagnostic.setloclist({ open = false })
end
require('plex.lib.edit').toggle_list('loclist')
end, { desc = 'Open Location List' })
-- Switch with adjacent window
map('n', '<C-x>', '<C-w>x', { remap = true, desc = 'Swap windows' })
map('n', 'sb', '<cmd>buffer#<CR>', { desc = 'Alternate buffer' })
map('n', 'sc', '<cmd>close<CR>', { desc = 'Close window' })
map('n', 'sd', '<cmd>bdelete<CR>', { desc = 'Buffer delete' })
map('n', 'sv', '<cmd>split<CR>', { desc = 'Split window horizontally' })
map('n', 'sg', '<cmd>vsplit<CR>', { desc = 'Split window vertically' })
map('n', 'st', '<cmd>tabnew<CR>', { desc = 'New tab' })
map('n', 'so', '<cmd>only<CR>', { desc = 'Close other windows' })
map('n', 'sq', '<cmd>quit<CR>', { desc = 'Quit' })
map('n', 'sz', '<cmd>vertical resize | resize | normal! ze<CR>', { desc = 'Maximize' })
map('n', 'sx', function()
require('mini.bufremove').delete(0, false)
vim.cmd.enew()
end, { desc = 'Delete buffer and open new' })
-- Background dark/light toggle
map('n', 'sh', function()
if vim.o.background == 'dark' then
vim.o.background = 'light'
else
vim.o.background = 'dark'
end
end, { desc = 'Toggle background dark/light' })

253
lua/plex/config/options.lua Normal file
View File

@ -0,0 +1,253 @@
-- Rafi's Neovim options
-- github.com/plex/vim-config
-- ===
-- This file is automatically loaded by config.init or plugins.core
-- stylua: ignore start
-- Keyboard leaders
vim.g.mapleader = ' '
vim.g.maplocalleader = ';'
-- General
-- ===
local opt = vim.opt
opt.mouse = 'nv' -- Disable mouse in command-line mode
opt.errorbells = true -- Trigger bell on error
opt.virtualedit = 'block' -- Position cursor anywhere in visual blockd
opt.confirm = true -- Confirm to save changes before exiting modified bufferd
-- number
opt.number = true -- show line number
opt.relativenumber = false --
-- History and persistence
opt.history = 5000
opt.shada = { "'1000", "<50", "s10", "h" }
opt.conceallevel = 3
opt.signcolumn = 'yes'
opt.spelloptions:append('camel')
-- What to save for views and sessions
opt.viewoptions:remove('folds')
opt.sessionoptions:remove({ 'buffers', 'folds' })
-- Sync with system clipboard
opt.clipboard = 'unnamedplus'
-- Undo
opt.undofile = true
opt.undolevels = 10000
opt.writebackup = false
-- If sudo, disable vim swap/backup/undo/shada writing
local USER = vim.env.USER or ''
local SUDO_USER = vim.env.SUDO_USER or ''
if
SUDO_USER ~= '' and USER ~= SUDO_USER
and vim.env.HOME ~= vim.fn.expand('~' .. USER, true)
and vim.env.HOME == vim.fn.expand('~' .. SUDO_USER, true)
then
vim.opt_global.modeline = false
vim.opt_global.undofile = false
vim.opt_global.swapfile = false
vim.opt_global.backup = false
vim.opt_global.writebackup = false
vim.opt_global.shadafile = 'NONE'
end
-- Tabs and Indents
-- ===
opt.textwidth = 80 -- Text width maximum chars before wrapping
opt.tabstop = 2 -- The number of spaces a tab is
opt.shiftwidth = 2 -- Number of spaces to use in auto(indent)
opt.smarttab = true -- Tab insert blanks according to 'shiftwidth'
opt.autoindent = true -- Use same indenting on new lines
opt.smartindent = true -- Smart autoindenting on new lines
opt.shiftround = true -- Round indent to multiple of 'shiftwidth'
-- Timing
-- ===
opt.ttimeout = true
opt.timeoutlen = 500 -- Time out on mappings
opt.ttimeoutlen = 10 -- Time out on key codes
opt.updatetime = 500 -- Idle time to write swap and trigger CursorHold
-- Searching
-- ===
opt.ignorecase = true -- Search ignoring case
opt.smartcase = true -- Keep case when searching with *
opt.infercase = true -- Adjust case in insert completion mode
opt.incsearch = true -- Incremental search
opt.inccommand = 'nosplit'
opt.grepformat = '%f:%l:%c:%m'
opt.path:append('**') -- Find recursively
if vim.fn.executable('rg') then
opt.grepprg = 'rg --vimgrep --no-heading'
.. (opt.smartcase and ' --smart-case' or '') .. ' --'
elseif vim.fn.executable('ag') then
opt.grepprg = 'ag --vimgrep'
.. (opt.smartcase and ' --smart-case' or '') .. ' --'
end
-- Formatting
-- ===
opt.wrap = false -- No wrap by default
opt.linebreak = true -- Break long lines at 'breakat'
opt.breakat = '\\ \\ ;:,!?' -- Long lines break chars
opt.startofline = false -- Cursor in same column for few commands
opt.splitbelow = true -- Splits open bottom right
opt.splitright = true
opt.breakindentopt = { shift = 2, min = 20 }
opt.formatoptions = opt.formatoptions
- 'a' -- Auto formatting is BAD.
- 't' -- Don't auto format my code. I got linters for that.
+ 'c' -- In general, I like it when comments respect textwidth
+ 'q' -- Allow formatting comments w/ gq
- 'o' -- O and o, don't continue comments
+ 'r' -- But do continue when pressing enter.
+ 'n' -- Indent past the formatlistpat, not underneath it.
+ 'j' -- Auto-remove comments if possible.
- '2' -- I'm not in gradeschool anymore
-- Completion and Diff
-- ===
-- C-n completion
opt.complete:append('k')
opt.complete:remove('u')
opt.complete:remove('t')
opt.completeopt = 'menu,menuone,noselect'
opt.diffopt:append({ 'iwhite', 'indent-heuristic', 'algorithm:patience' })
opt.wildmode = 'longest:full,full' -- Command-line completion mode
-- Editor UI
-- ===
opt.termguicolors = true
opt.shortmess:append({ W = true, I = true, c = true })
opt.showmode = false -- Don't show mode in cmd window
opt.scrolloff = 2 -- Keep at least 2 lines above/below
opt.sidescrolloff = 5 -- Keep at least 5 lines left/right
opt.numberwidth = 2 -- Minimum number of columns to use for the line number
opt.number = false -- Don't show line numbers
opt.ruler = false -- Disable default status ruler
opt.list = true -- Show hidden characters
opt.showtabline = 2 -- Always show the tabs line
opt.helpheight = 0 -- Disable help window resizing
opt.winwidth = 30 -- Minimum width for active window
opt.winminwidth = 1 -- Minimum width for inactive windows
opt.winheight = 1 -- Minimum height for active window
opt.winminheight = 1 -- Minimum height for inactive window
opt.showcmd = false -- Don't show command in status line
opt.cmdheight = 0
opt.cmdwinheight = 5 -- Command-line lines
opt.equalalways = true -- Resize windows on split or close
opt.colorcolumn = '+0' -- Column highlight at textwidth's max character-limit
opt.cursorline = true
opt.cursorlineopt = { 'number', 'screenline' }
opt.pumheight = 10 -- Maximum number of items to show in the popup menu
opt.pumwidth = 10 -- Minimum width for the popup menu
opt.pumblend = 10 -- Popup blend
if vim.fn.has('nvim-0.9') == 1 then
opt.splitkeep = 'screen'
opt.shortmess:append({ C = true })
end
-- UI Symbols
-- ===
-- icons: ▏│ ¦ ╎ ┆ ⋮ ⦙ ┊ 
opt.showbreak = ''
opt.listchars = {
tab = ' ',
extends = '',
precedes = '',
nbsp = '',
trail = '·'
}
opt.fillchars = {
foldopen = '󰅀', -- 󰅀 
foldclose = '󰅂', -- 󰅂 
fold = ' ',
foldsep = ' ',
diff = '',
eob = ' ',
horiz = '',
horizup = '',
horizdown = '',
vert = '',
vertleft = '',
vertright = '',
verthoriz = '',
}
-- Folds
-- ===
opt.foldlevel = 99
opt.foldlevelstart = 99
opt.foldcolumn = '0'
opt.foldenable = true
-- Misc
-- ===
-- Disable python/perl/ruby/node providers
vim.g.loaded_python3_provider = 0
vim.g.loaded_perl_provider = 0
vim.g.loaded_ruby_provider = 0
vim.g.loaded_node_provider = 0
vim.g.no_gitrebase_maps = 1 -- See share/nvim/runtime/ftplugin/gitrebase.vim
vim.g.no_man_maps = 1 -- See share/nvim/runtime/ftplugin/man.vim
-- Filetype detection
-- ===
---@diagnostic disable-next-line: missing-fields
vim.filetype.add({
filename = {
Brewfile = 'ruby',
justfile = 'just',
Justfile = 'just',
Tmuxfile = 'tmux',
['yarn.lock'] = 'yaml',
['.buckconfig'] = 'toml',
['.flowconfig'] = 'ini',
['.jsbeautifyrc'] = 'json',
['.jscsrc'] = 'json',
['.watchmanconfig'] = 'json',
['dev-requirements.txt'] = 'requirements',
},
pattern = {
['.*%.js%.map'] = 'json',
['.*%.postman_collection'] = 'json',
['Jenkinsfile.*'] = 'groovy',
['%.kube/config'] = 'yaml',
['%.config/git/users/.*'] = 'gitconfig',
['requirements-.*%.txt'] = 'requirements',
['.*/templates/.*%.ya?ml'] = 'helm',
['.*/templates/.*%.tpl'] = 'helm',
['.*/playbooks/.*%.ya?ml'] = 'yaml.ansible',
['.*/roles/.*/tasks/.*%.ya?ml'] = 'yaml.ansible',
['.*/roles/.*/handlers/.*%.ya?ml'] = 'yaml.ansible',
['.*/inventory/.*%.ini'] = 'ansible_hosts',
},
})
-- vim: set ts=2 sw=0 tw=80 noet :

8
lua/plex/init.lua Normal file
View File

@ -0,0 +1,8 @@
local M = {}
---@param opts? RafiConfig
function M.setup(opts)
require('plex.config').setup(opts)
end
return M

210
lua/plex/lib/badge.lua Normal file
View File

@ -0,0 +1,210 @@
-- Badge utilities
-- https://github.com/plex/vim-config
local plugin_icons = {
DiffviewFiles = { '' },
fugitive = { '' },
fugitiveblame = { '󰊢', 'Blame' },
lazy = { '󰒲 ', 'Lazy.nvim' },
loclist = { '󰂖', 'Location List' },
mason = { '󰈏 ', 'Mason' },
NeogitStatus = { '󰉺' },
['neo-tree'] = { '', 'Neo-tree' },
['neo-tree-popup'] = { '󰋱', 'Neo-tree' },
Outline = { '' },
quickfix = { '', 'Quickfix List' }, -- 󰎟 
spectre_panel = { '󰥩 ', 'Spectre' },
TelescopePrompt = { '󰋱', 'Telescope' },
terminal = { '' },
toggleterm = { '', 'Terminal' },
Trouble = { '' }, --  
undotree = { '󰃢' },
}
local cache_keys = {
'badge_cache_filepath',
'badge_cache_filepath_tab',
'badge_cache_icon',
}
local augroup = vim.api.nvim_create_augroup('plex_badge', {})
-- Clear cached values that relate to buffer filename.
vim.api.nvim_create_autocmd(
{ 'BufReadPost', 'BufFilePost', 'BufNewFile', 'BufWritePost' },
{
group = augroup,
callback = function()
if vim.bo.buftype ~= '' then
return
end
for _, cache_key in ipairs(cache_keys) do
pcall(vim.api.nvim_buf_del_var, 0, cache_key)
end
end,
}
)
-- Clear cached values that relate to buffer content.
vim.api.nvim_create_autocmd(
{ 'BufWritePre', 'FileChangedShellPost', 'TextChanged', 'InsertLeave' },
{
group = augroup,
callback = function()
pcall(vim.api.nvim_buf_del_var, 0, 'badge_cache_trails')
end,
}
)
local M = {}
-- Try to guess the project's name
---@return string
function M.project()
return vim.fn.fnamemodify(require('plex.lib.utils').get_root(), ':t') or ''
end
-- Provides relative path with limited characters in each directory name, and
-- limits number of total directories. Caches the result for current buffer.
---@param bufnr integer buffer number
---@param max_dirs integer max dirs to show
---@param dir_max_chars integer max chars in dir
---@param cache_suffix string? cache suffix
---@return string
function M.filepath(bufnr, max_dirs, dir_max_chars, cache_suffix)
local msg = ''
local cache_key = 'badge_cache_filepath' -- _'..ft
if cache_suffix then
cache_key = cache_key .. cache_suffix
end
local cache_ok, cache = pcall(vim.api.nvim_buf_get_var, bufnr, cache_key)
if cache_ok then
return cache
end
local bufname = vim.api.nvim_buf_get_name(bufnr)
local buftype = vim.bo[bufnr].buftype
local filetype = vim.bo[bufnr].filetype
-- Normalize bufname
if bufname:len() < 1 and buftype:len() < 1 then
return 'N/A'
end
bufname = vim.fn.fnamemodify(bufname, ':~:.') or ''
-- Reduce directory count according to 'max_dirs' setting.
local formatter = string.format('([^%s]+)', M.path_sep)
local parts = {}
for str in string.gmatch(bufname, formatter) do
table.insert(parts, str)
end
local short_parts = {}
for i = #parts, 1, -1 do
if #short_parts <= max_dirs then
table.insert(short_parts, 1, parts[i])
end
end
bufname = table.concat(short_parts, M.path_sep)
-- Reduce each directory character count according to setting.
bufname = vim.fn.pathshorten(bufname, dir_max_chars + 1)
-- Override with plugin names.
local plugin_type = filetype == 'qf' and vim.fn.win_gettype() or filetype
if plugin_icons[plugin_type] ~= nil and #plugin_icons[plugin_type] > 1 then
msg = msg .. plugin_icons[plugin_type][2]
else
msg = msg .. bufname
end
vim.api.nvim_buf_set_var(bufnr, cache_key, msg)
return msg
end
function M.filemedia(separator)
local parts = {}
if vim.bo.fileformat ~= '' and vim.bo.fileformat ~= 'unix' then
table.insert(parts, vim.bo.fileformat)
end
if vim.bo.fileencoding ~= '' and vim.bo.fileencoding ~= 'utf-8' then
table.insert(parts, vim.bo.fileencoding)
end
if vim.bo.filetype ~= '' then
table.insert(parts, vim.bo.filetype)
end
return table.concat(parts, separator)
end
function M.icon(bufnr)
bufnr = bufnr or 0
local cache_key = 'badge_cache_icon'
local cache_ok, cache = pcall(vim.api.nvim_buf_get_var, bufnr, cache_key)
if cache_ok then
return cache
end
local icon = ''
local ft = vim.bo[bufnr].filetype
local buftype = vim.bo[bufnr].buftype
local bufname = vim.api.nvim_buf_get_name(bufnr)
local plugin_type = ft == 'qf' and vim.fn.win_gettype() or ft
if buftype ~= '' and plugin_icons[plugin_type] ~= nil then
icon = plugin_icons[plugin_type][1]
else
-- Try nvim-tree/nvim-web-devicons
local ok, devicons = pcall(require, 'nvim-web-devicons')
if ok then
if buftype == '' and bufname == '' then
return devicons.get_default_icon().icon
end
local f_name = vim.fn.fnamemodify(bufname, ':t')
local f_extension = vim.fn.fnamemodify(bufname, ':e')
icon, _ = devicons.get_icon(f_name, f_extension)
if icon == '' or icon == nil then
icon = devicons.get_default_icon().icon
end
end
end
vim.api.nvim_buf_set_var(bufnr, cache_key, icon)
return icon
end
-- Detect trailing whitespace and cache result per buffer
---@param symbol string
---@return string
function M.trails(symbol)
local cache_key = 'badge_cache_trails'
local cache_ok, cache = pcall(vim.api.nvim_buf_get_var, 0, cache_key)
if cache_ok then
return cache
end
local msg = ''
if not vim.bo.readonly and vim.bo.modifiable and vim.fn.line('$') < 9000 then
local trailing = vim.fn.search('\\s$', 'nw')
if trailing > 0 then
local label = symbol or 'WS:'
msg = msg .. label .. trailing
end
end
vim.api.nvim_buf_set_var(0, cache_key, msg)
return msg
end
-- Variable holds OS directory separator.
M.path_sep = (function()
if jit then
local os = string.lower(jit.os)
if os ~= 'windows' then
return '/'
else
return '\\'
end
else
return package.config:sub(1, 1)
end
end)()
return M

140
lua/plex/lib/color.lua Normal file
View File

@ -0,0 +1,140 @@
-- Source: https://github.com/nvim-lualine/lualine.nvim/blob/master/lua/lualine/themes/auto.lua
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
local M = {}
-- Turns #rrggbb -> { red, green, blue }
function M.rgb_str2num(rgb_color_str)
if rgb_color_str:find('#') == 1 then
rgb_color_str = rgb_color_str:sub(2, #rgb_color_str)
end
local red = tonumber(rgb_color_str:sub(1, 2), 16)
local green = tonumber(rgb_color_str:sub(3, 4), 16)
local blue = tonumber(rgb_color_str:sub(5, 6), 16)
return { red = red, green = green, blue = blue }
end
-- Turns { red, green, blue } -> #rrggbb
function M.rgb_num2str(rgb_color_num)
local rgb_color_str = string.format(
'#%02x%02x%02x',
rgb_color_num.red,
rgb_color_num.green,
rgb_color_num.blue
)
return rgb_color_str
end
-- Returns brightness level of color in range 0 to 1
-- arbitrary value it's basically an weighted average
function M.get_color_brightness(rgb_color)
local color = M.rgb_str2num(rgb_color)
local brightness = (color.red * 2 + color.green * 3 + color.blue) / 6
return brightness / 256
end
-- returns average of colors in range 0 to 1
-- used to determine contrast level
function M.get_color_avg(rgb_color)
local color = M.rgb_str2num(rgb_color)
return (color.red + color.green + color.blue) / 3 / 256
end
-- Clamps the val between left and right
function M.clamp(val, left, right)
if val > right then
return right
end
if val < left then
return left
end
return val
end
-- Changes brightness of rgb_color by percentage
function M.brightness_modifier(rgb_color, parcentage)
local color = M.rgb_str2num(rgb_color)
color.red = M.clamp(color.red + (color.red * parcentage / 100), 0, 255)
color.green = M.clamp(color.green + (color.green * parcentage / 100), 0, 255)
color.blue = M.clamp(color.blue + (color.blue * parcentage / 100), 0, 255)
return M.rgb_num2str(color)
end
-- Changes contrast of rgb_color by amount
function M.contrast_modifier(rgb_color, amount)
local color = M.rgb_str2num(rgb_color)
color.red = M.clamp(color.red + amount, 0, 255)
color.green = M.clamp(color.green + amount, 0, 255)
color.blue = M.clamp(color.blue + amount, 0, 255)
return M.rgb_num2str(color)
end
-- Changes brightness of foreground color to achieve contrast
-- without changing the color
function M.apply_contrast(highlight, threshold)
local hightlight_bg_avg = M.get_color_avg(highlight.bg)
local contrast_threshold_config = M.clamp(threshold, 0, 0.5)
local contranst_change_step = 5
if hightlight_bg_avg > 0.5 then
contranst_change_step = -contranst_change_step
end
-- Don't waste too much time here max 25 iteration should be more than enough
local iteration_count = 1
while
math.abs(M.get_color_avg(highlight.fg) - hightlight_bg_avg)
< contrast_threshold_config
and iteration_count < 25
do
highlight.fg = M.contrast_modifier(highlight.fg, contranst_change_step)
iteration_count = iteration_count + 1
end
end
-- Change brightness of colors
-- Darken if light theme (or) Lighten if dark theme
function M.apply_brightness(color, base_color, brightness_modifier_parameter)
if base_color ~= nil then
if M.get_color_brightness(base_color) > 0.5 then
brightness_modifier_parameter = -brightness_modifier_parameter
end
return M.brightness_modifier(color, brightness_modifier_parameter)
end
end
-- Assorted highlight helpers
--
local has_nvim9 = vim.fn.has('nvim-0.9') == 1
-- Retrieves color value from highlight group names.
-- First present highlight is returned
---@param scope string
---@param highlights table
---@param default string?
---@return string|nil
function M.get_color(scope, highlights, default)
for _, hl_name in ipairs(highlights) do
local hl
if has_nvim9 then
hl = vim.api.nvim_get_hl(0, { name = hl_name })
else
---@diagnostic disable-next-line: deprecated
hl = vim.api.nvim_get_hl_by_name(hl_name, true)
hl.fg, hl.bg, hl.sp = hl.foreground, hl.background, hl.special
end
if hl.reverse then
if scope == 'bg' then
scope = 'fg'
elseif scope == 'fg' then
scope = 'bg'
end
end
if hl[scope] then
return string.format('#%06x', hl[scope])
end
end
return default
end
return M

View File

@ -0,0 +1,94 @@
-- Context-aware menu
-- https://github.com/plex/vim-config
local M = {}
---@param method string
---@param clients lsp.Client[]
---@return boolean
local function supports_method(method, clients)
for _, client in pairs(clients) do
if client.supports_method(method) then
return true
end
end
return false
end
M.show = function()
if vim.fn.has('nvim-0.8') ~= 1 then
vim.notify(
'You must be running Neovim ≥8.0',
vim.log.levels.WARN,
{ title = 'Contextmenu' }
)
return
end
local cword = vim.fn.expand('<cword>')
local bufnr = vim.api.nvim_get_current_buf()
local clients
if vim.lsp.get_clients ~= nil then
clients = vim.lsp.get_clients({ bufnr = bufnr })
else
---@diagnostic disable-next-line: deprecated
clients = vim.lsp.get_active_clients({ bufnr = bufnr })
end
-- Remove all menu options
pcall(vim.cmd.aunmenu, 'Context')
if cword == '' then
-- Cursor is on blank character.
vim.cmd([[
nmenu Context.Select\ All ggVG
nmenu Context.-1- <Nop>
]])
else
-- Add LSP methods, only if one of the servers support it.
if supports_method('textDocument/declaration', clients) then
vim.cmd(
'nmenu Context.Declaration <cmd>lua vim.lsp.buf.declaration()<CR>'
)
end
if supports_method('textDocument/definition', clients) then
vim.cmd('nmenu Context.&Definition <cmd>lua vim.lsp.buf.definition()<CR>')
end
if supports_method('textDocument/references', clients) then
vim.cmd(
'nmenu Context.&References… <cmd>lua vim.lsp.buf.references()<CR>'
)
end
if supports_method('textDocument/implementation', clients) then
vim.cmd(
'nmenu Context.Implementation <cmd>lua vim.lsp.buf.implementation()<CR>'
)
end
if #clients > 0 then
vim.cmd([[
nmenu Context.-1- <Nop>
nmenu Context.Find\ symbol <cmd>lua vim.schedule(function() require'telescope.builtin'.lsp_workspace_symbols({default_text = vim.fn.expand('<cword>')}) end)<CR>
]])
end
vim.cmd([[
nmenu Context.Grep <cmd>lua vim.schedule(function() require'telescope.builtin'.live_grep({default_text = vim.fn.expand('<cword>')}) end)<CR>
nmenu Context.-2- <Nop>
]])
end
vim.cmd([[
nmenu Context.Diagnostics <cmd>Trouble<CR>
nmenu Context.Bookmark m;
nmenu Context.TODOs <cmd>TodoTrouble<CR>
nmenu Context.Git\ diff <cmd>Gdiffsplit<CR>
nmenu Context.Unsaved\ diff <cmd>DiffOrig<CR>
nmenu Context.Open\ in\ browser <cmd>lua require('gitlinker').get_buf_range_url('n')<CR>
]])
pcall(vim.cmd.popup, 'Context')
end
return M

141
lua/plex/lib/edit.lua Normal file
View File

@ -0,0 +1,141 @@
-- Edit utilities
-- https://github.com/plex/vim-config
local M = {}
-- Get visually selected lines.
-- Source: https://github.com/ibhagwan/fzf-lua/blob/main/lua/fzf-lua/utils.lua
---@return string
function M.get_visual_selection()
-- this will exit visual mode
-- use 'gv' to reselect the text
local _, csrow, cscol, cerow, cecol
local mode = vim.fn.mode()
if mode == 'v' or mode == 'V' or mode == '' then
-- if we are in visual mode use the live position
_, csrow, cscol, _ = unpack(vim.fn.getpos('.'))
_, cerow, cecol, _ = unpack(vim.fn.getpos('v'))
if mode == 'V' then
-- visual line doesn't provide columns
cscol, cecol = 0, 999
end
-- exit visual mode
vim.api.nvim_feedkeys(
vim.api.nvim_replace_termcodes('<Esc>', true, false, true),
'n',
true
)
else
-- otherwise, use the last known visual position
_, csrow, cscol, _ = unpack(vim.fn.getpos("'<"))
_, cerow, cecol, _ = unpack(vim.fn.getpos("'>"))
end
-- swap vars if needed
if cerow < csrow then
csrow, cerow = cerow, csrow
end
if cecol < cscol then
cscol, cecol = cecol, cscol
end
local lines = vim.fn.getline(csrow, cerow)
-- local n = cerow-csrow+1
local n = #lines
if n <= 0 or type(lines) ~= 'table' then
return ''
end
lines[n] = string.sub(lines[n], 1, cecol)
lines[1] = string.sub(lines[1], cscol)
return table.concat(lines, '\n')
end
-- Append modeline at end of file.
function M.append_modeline()
local modeline = string.format(
'vim: set ts=%d sw=%d tw=%d %set :',
vim.bo.tabstop,
vim.bo.shiftwidth,
vim.bo.textwidth,
vim.bo.expandtab and '' or 'no'
)
modeline = string.gsub(vim.bo.commentstring, '%%s', modeline)
vim.api.nvim_buf_set_lines(0, -1, -1, false, { modeline })
end
-- Go to newer/older buffer through jumplist.
---@param direction 1 | -1
function M.jump_buffer(direction)
local jumplist, curjump = unpack(vim.fn.getjumplist())
if #jumplist == 0 then
return
end
local cur_buf = vim.api.nvim_get_current_buf()
local jumpcmd = direction > 0 and '<C-i>' or '<C-o>'
local searchrange = {}
curjump = curjump + 1
if direction > 0 then
searchrange = vim.fn.range(curjump + 1, #jumplist)
else
searchrange = vim.fn.range(curjump - 1, 1, -1)
end
for _, i in ipairs(searchrange) do
local nr = jumplist[i]['bufnr']
if nr ~= cur_buf and vim.fn.bufname(nr):find('^%w+://') == nil then
local n = tostring(math.abs(i - curjump))
vim.notify('Executing ' .. jumpcmd .. ' ' .. n .. ' times')
jumpcmd = vim.api.nvim_replace_termcodes(jumpcmd, true, true, true)
vim.cmd.normal({ n .. jumpcmd, bang = true })
break
end
end
end
-- Jump to next/previous whitespace error.
---@param direction 1 | -1
function M.whitespace_jump(direction)
local opts = 'wz'
if direction < 1 then
opts = opts .. 'b'
end
-- Whitespace pattern: Trailing whitespace or mixed tabs/spaces.
local pat = '\\s\\+$\\| \\+\\ze\\t'
vim.fn.search(pat, opts)
end
-- Toggle list window
---@param name "quickfix" | "loclist"
M.toggle_list = function(name)
local win_bufs = M.get_tabpage_win_bufs(0)
for win, buf in pairs(win_bufs) do
if vim.bo[buf].filetype == 'qf' and vim.fn.win_gettype(win) == name then
vim.api.nvim_win_close(win, false)
return
end
end
if name == 'loclist' then
vim.cmd([[ botright lopen ]])
else
vim.cmd([[ botright copen ]])
end
end
-- Return a table with all window buffers from a tabpage.
---@private
---@param tabpage integer
---@return table
M.get_tabpage_win_bufs = function(tabpage)
local bufs = {}
for _, win in pairs(vim.api.nvim_tabpage_list_wins(tabpage)) do
if win ~= nil and vim.api.nvim_win_is_valid(win) then
local buf = vim.api.nvim_win_get_buf(win)
if buf ~= nil and vim.api.nvim_buf_is_valid(buf) then
bufs[win] = buf
end
end
end
return bufs
end
return M

108
lua/plex/lib/preview.lua Normal file
View File

@ -0,0 +1,108 @@
-- plex preview functions
-- https://github.com/plex/vim-config
-- requires telescope
local M = {}
local opts = {}
local default_opts = {
popup = {
enter = false,
-- moved = 'any', -- doesn't work.
focusable = true,
noautocmd = true,
relative = 'cursor',
line = 'cursor-3',
col = 'cursor+27',
minwidth = math.ceil(vim.o.columns / 2),
minheight = math.ceil(vim.o.lines / 1.5),
border = true,
borderchars = { '', '', '', '', '', '', '', '' },
highlight = 'Normal',
borderhighlight = 'FloatBorder',
titlehighlight = 'Title',
zindex = 100,
},
}
opts = vim.deepcopy(default_opts)
---@param popup_state table
---@param augroup integer
local function close(popup_state, augroup)
vim.schedule(function()
local utils = require('telescope.utils')
pcall(vim.api.nvim_del_augroup_by_id, augroup)
utils.win_delete('preview_border_win', popup_state.win_id, true, true)
if popup_state.border and popup_state.border.win_id then
utils.win_delete(
'preview_border_win',
popup_state.border.win_id,
true,
true
)
end
end)
end
---@param user_opts table
function M.setup(user_opts)
user_opts = vim.F.if_nil(user_opts, {})
opts = vim.tbl_deep_extend('keep', user_opts, default_opts)
end
---@param path string
function M.open(path)
local bufnr = vim.api.nvim_get_current_buf()
local popup = require('plenary.popup')
opts.popup.title = path
local winid, popup_state = popup.create('', opts.popup)
local popup_bufnr = vim.api.nvim_win_get_buf(winid)
-- Ensure best viewing options are toggled.
local scope = { scope = 'local', win = winid }
vim.api.nvim_set_option_value('number', true, scope)
vim.api.nvim_set_option_value('relativenumber', false, scope)
vim.api.nvim_set_option_value('wrap', false, scope)
vim.api.nvim_set_option_value('spell', false, scope)
vim.api.nvim_set_option_value('list', false, scope)
vim.api.nvim_set_option_value('foldenable', false, scope)
vim.api.nvim_set_option_value('cursorline', false, scope)
vim.api.nvim_set_option_value('signcolumn', 'no', scope)
vim.api.nvim_set_option_value('colorcolumn', '', scope)
vim.api.nvim_set_option_value('winhighlight', 'Normal:NormalFloat', scope)
-- Run telescope preview.
local previewer = require('telescope.config').values.buffer_previewer_maker
previewer(path, popup_bufnr, {})
-- Setup close events
local augroup = vim.api.nvim_create_augroup('preview_window_' .. winid, {})
-- Close the preview window when entered a buffer that is not
-- the floating window buffer or the buffer that spawned it.
vim.api.nvim_create_autocmd('BufEnter', {
group = augroup,
callback = function()
-- close preview unless we're in original window or popup window
local bufnrs = { popup_bufnr, bufnr }
if not vim.tbl_contains(bufnrs, vim.api.nvim_get_current_buf()) then
close(popup_state, augroup)
end
end,
})
-- Create autocommands to close a preview window when events happen.
local events = { 'CursorMoved', 'BufUnload', 'InsertCharPre', 'ModeChanged' }
vim.api.nvim_create_autocmd(events, {
group = augroup,
buffer = bufnr,
once = true,
callback = function()
close(popup_state, augroup)
end,
})
end
return M

122
lua/plex/lib/utils.lua Normal file
View File

@ -0,0 +1,122 @@
-- General utilities
-- https://github.com/plex/vim-config
local root_patterns = { '.git', '_darcs', '.hg', '.bzr', '.svn' }
local M = {}
local augroup_lsp_attach = vim.api.nvim_create_augroup('plex_lsp_attach', {})
---@param on_attach fun(client:lsp.Client, buffer:integer)
function M.on_attach(on_attach)
vim.api.nvim_create_autocmd('LspAttach', {
group = augroup_lsp_attach,
callback = function(args)
local buffer = args.buf
local client = vim.lsp.get_client_by_id(args.data.client_id)
if client ~= nil then
on_attach(client, buffer)
end
end,
})
end
---@param plugin string
---@return boolean
function M.has(plugin)
-- return require('lazy.core.config').plugins[plugin] ~= nil
return require('lazy.core.config').spec.plugins[plugin] ~= nil
end
---@param fn fun()
function M.on_very_lazy(fn)
vim.api.nvim_create_autocmd('User', {
pattern = 'VeryLazy',
callback = function()
fn()
end,
})
end
---@param name string
---@return table
function M.opts(name)
local plugin = require('lazy.core.config').plugins[name]
if not plugin then
return {}
end
local Plugin = require('lazy.core.plugin')
return Plugin.values(plugin, 'opts', false)
end
-- Find the root directory by searching for the version-control dir
---@return string
function M.get_root()
local cwd = vim.loop.cwd()
if cwd == '' or cwd == nil then
return ''
end
local ok, cache = pcall(vim.api.nvim_buf_get_var, 0, 'project_dir')
if ok and cache then
local _, last_cwd =
pcall(vim.api.nvim_buf_get_var, 0, 'project_dir_last_cwd')
if cwd == last_cwd then
return cache
end
end
local root = vim.fs.find(root_patterns, { path = cwd, upward = true })[1]
root = root and vim.fs.dirname(root) or vim.loop.cwd() or ''
vim.api.nvim_buf_set_var(0, 'project_dir', root)
vim.api.nvim_buf_set_var(0, 'project_dir_last_cwd', cwd)
return root
end
---@type table<string,LazyFloat>
local terminals = {}
-- Opens a floating terminal (interactive by default)
---@param cmd? string[]|string
---@param opts? LazyCmdOptions|{interactive?:boolean, esc_esc?:false, ctrl_hjkl?:false}
function M.float_term(cmd, opts)
opts = vim.tbl_deep_extend('force', {
ft = 'lazyterm',
size = { width = 0.9, height = 0.9 },
}, opts or {}, { persistent = true })
---@cast opts LazyCmdOptions|{interactive?:boolean, esc_esc?:false, ctrl_hjkl?:false}
local termkey = vim.inspect({
cmd = cmd or 'shell',
cwd = opts.cwd,
env = opts.env,
count = vim.v.count1,
})
if terminals[termkey] and terminals[termkey]:buf_valid() then
terminals[termkey]:toggle()
else
terminals[termkey] = require('lazy.util').float_term(cmd, opts)
local buf = terminals[termkey].buf
vim.b[buf].lazyterm_cmd = cmd
if opts.esc_esc == false then
vim.keymap.set('t', '<esc>', '<esc>', { buffer = buf, nowait = true })
end
if opts.ctrl_hjkl == false then
vim.keymap.set('t', '<c-h>', '<c-h>', { buffer = buf, nowait = true })
vim.keymap.set('t', '<c-j>', '<c-j>', { buffer = buf, nowait = true })
vim.keymap.set('t', '<c-k>', '<c-k>', { buffer = buf, nowait = true })
vim.keymap.set('t', '<c-l>', '<c-l>', { buffer = buf, nowait = true })
end
vim.api.nvim_create_autocmd('BufEnter', {
buffer = buf,
callback = function()
vim.cmd.startinsert()
end,
})
end
return terminals[termkey]
end
return M

325
lua/plex/plugins/coding.lua Normal file
View File

@ -0,0 +1,325 @@
-- Plugins: Coding
-- https://github.com/plex/vim-config
return {
-----------------------------------------------------------------------------
{
'hrsh7th/nvim-cmp',
event = 'InsertEnter',
dependencies = {
'hrsh7th/cmp-nvim-lsp',
'hrsh7th/cmp-buffer',
'hrsh7th/cmp-path',
'hrsh7th/cmp-emoji',
{ 'saadparwaiz1/cmp_luasnip', dependencies = 'L3MON4D3/LuaSnip' },
'andersevenrud/cmp-tmux',
},
opts = function()
local cmp = require('cmp')
local defaults = require('cmp.config.default')()
local luasnip = require('luasnip')
local function has_words_before()
if vim.bo.buftype == 'prompt' then
return false
end
local line, col = unpack(vim.api.nvim_win_get_cursor(0))
-- stylua: ignore
return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match('%s') == nil
end
return {
preselect = cmp.PreselectMode.None,
sorting = defaults.sorting,
experimental = {
ghost_text = {
hl_group = 'Comment',
},
},
snippet = {
expand = function(args)
require('luasnip').lsp_expand(args.body)
end,
},
sources = cmp.config.sources({
{ name = 'nvim_lsp', priority = 50 },
{ name = 'path', priority = 40 },
{ name = 'luasnip', priority = 30 },
}, {
{ name = 'buffer', priority = 50, keyword_length = 3 },
{ name = 'emoji', insert = true, priority = 20 },
{
name = 'tmux',
priority = 10,
keyword_length = 3,
option = { all_panes = true, label = 'tmux' },
},
}),
mapping = cmp.mapping.preset.insert({
-- <CR> accepts currently selected item.
-- Set `select` to `false` to only confirm explicitly selected items.
['<CR>'] = cmp.mapping({
i = function(fallback)
if cmp.visible() and cmp.get_active_entry() then
cmp.confirm({ select = false })
else
fallback()
end
end,
s = cmp.mapping.confirm({
select = true,
behavior = cmp.ConfirmBehavior.Replace,
}),
-- Do not set command mode, it will interfere with noice popmenu.
}),
['<S-CR>'] = cmp.mapping.confirm({
behavior = cmp.ConfirmBehavior.Replace,
select = true,
}),
['<C-Space>'] = cmp.mapping.complete(),
['<C-n>'] = cmp.mapping.select_next_item(),
['<C-p>'] = cmp.mapping.select_prev_item(),
['<C-d>'] = cmp.mapping.select_next_item({ count = 5 }),
['<C-u>'] = cmp.mapping.select_prev_item({ count = 5 }),
['<C-f>'] = cmp.mapping.scroll_docs(4),
['<C-b>'] = cmp.mapping.scroll_docs(-4),
['<C-c>'] = function(fallback)
cmp.close()
fallback()
end,
['<Tab>'] = cmp.mapping(function(fallback)
if cmp.visible() then
cmp.select_next_item()
elseif luasnip.jumpable(1) then
luasnip.jump(1)
elseif has_words_before() then
cmp.complete()
else
fallback()
end
end, { 'i', 's' }),
['<S-Tab>'] = 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' }),
}),
formatting = {
format = function(entry, vim_item)
-- Prepend with a fancy icon from config lua/plex/config/init.lua
local icons = require('plex.config').icons
if entry.source.name == 'git' then
vim_item.kind = icons.git
else
local symbol = icons.kinds[vim_item.kind]
if symbol ~= nil then
vim_item.kind = symbol .. ' ' .. vim_item.kind
end
end
return vim_item
end,
},
}
end,
},
-----------------------------------------------------------------------------
{
'L3MON4D3/LuaSnip',
event = 'InsertEnter',
dependencies = { 'rafamadriz/friendly-snippets' },
build = (not jit.os:find('Windows'))
and "echo 'NOTE: jsregexp is optional, so not a big deal if it fails to build'; make install_jsregexp"
or nil,
-- stylua: ignore
keys = {
{
'<C-l>',
function() require('luasnip').expand_or_jump() end,
mode = { 'i', 's' },
},
},
opts = {
-- Don't store snippet history for less overhead
history = false,
-- Event on which to check for exiting a snippet's region
region_check_events = 'InsertEnter',
delete_check_events = 'InsertLeave',
ft_func = function()
return vim.split(vim.bo.filetype, '.', { plain = true })
end,
},
config = function(_, opts)
require('luasnip').setup(opts)
require('luasnip.loaders.from_vscode').lazy_load()
require('luasnip.loaders.from_lua').load({ paths = './snippets' })
vim.api.nvim_create_user_command('LuaSnipEdit', function()
require('luasnip.loaders.from_lua').edit_snippet_files()
end, {})
end,
},
-----------------------------------------------------------------------------
{
'ziontee113/SnippetGenie',
event = 'InsertEnter',
dependencies = 'L3MON4D3/LuaSnip',
opts = {
snippets_directory = vim.fn.stdpath('config') .. '/snippets',
},
},
-----------------------------------------------------------------------------
{
'danymat/neogen',
-- stylua: ignore
keys = {
{
'<leader>cc',
function() require('neogen').generate({}) end,
desc = 'Neogen Comment',
},
},
opts = { snippet_engine = 'luasnip' },
},
-----------------------------------------------------------------------------
{
'echasnovski/mini.pairs',
event = 'VeryLazy',
opts = {},
},
-----------------------------------------------------------------------------
{
'echasnovski/mini.surround',
-- stylua: ignore
keys = function(_, keys)
-- Populate the keys based on the user's options
local plugin = require('lazy.core.config').spec.plugins['mini.surround']
local opts = require('lazy.core.plugin').values(plugin, 'opts', false)
local mappings = {
{ opts.mappings.add, desc = 'Add surrounding', mode = { 'n', 'x' } },
{ opts.mappings.delete, desc = 'Delete surrounding' },
{ opts.mappings.find, desc = 'Find right surrounding' },
{ opts.mappings.find_left, desc = 'Find left surrounding' },
{ opts.mappings.highlight, desc = 'Highlight surrounding' },
{ opts.mappings.replace, desc = 'Replace surrounding' },
{ opts.mappings.update_n_lines, desc = 'Update `MiniSurround.config.n_lines`' },
}
mappings = vim.tbl_filter(function(m)
return m[1] and #m[1] > 0
end, mappings)
return vim.list_extend(mappings, keys)
end,
opts = {
mappings = {
add = 'sa', -- Add surrounding in Normal and Visual modes
delete = 'ds', -- Delete surrounding
find = 'gzf', -- Find surrounding (to the right)
find_left = 'gzF', -- Find surrounding (to the left)
highlight = 'gzh', -- Highlight surrounding
replace = 'cs', -- Replace surrounding
update_n_lines = 'gzn', -- Update `n_lines`
},
},
},
-----------------------------------------------------------------------------
{
'echasnovski/mini.comment',
event = 'VeryLazy',
dependencies = { 'JoosepAlviste/nvim-ts-context-commentstring' },
keys = {
{ '<Leader>v', 'gcc', remap = true, silent = true, mode = 'n' },
{ '<Leader>v', 'gc', remap = true, silent = true, mode = 'x' },
},
opts = {
options = {
custom_commentstring = function()
return require('ts_context_commentstring.internal').calculate_commentstring()
or vim.bo.commentstring
end,
},
},
},
-----------------------------------------------------------------------------
{
'echasnovski/mini.trailspace',
event = { 'BufReadPost', 'BufNewFile' },
opts = {},
},
-----------------------------------------------------------------------------
{
'echasnovski/mini.ai',
event = 'VeryLazy',
dependencies = { 'nvim-treesitter/nvim-treesitter-textobjects' },
opts = function()
local ai = require('mini.ai')
return {
n_lines = 500,
-- stylua: ignore
custom_textobjects = {
o = ai.gen_spec.treesitter({
a = { '@block.outer', '@conditional.outer', '@loop.outer' },
i = { '@block.inner', '@conditional.inner', '@loop.inner' },
}, {}),
},
}
end,
},
-----------------------------------------------------------------------------
{
'echasnovski/mini.splitjoin',
keys = {
{
'sj',
'<cmd>lua MiniSplitjoin.join()<CR>',
mode = { 'n', 'x' },
desc = 'Join arguments',
},
{
'sk',
'<cmd>lua MiniSplitjoin.split()<CR>',
mode = { 'n', 'x' },
desc = 'Split arguments',
},
},
opts = {
mappings = { toggle = '' },
},
},
-----------------------------------------------------------------------------
{
'AndrewRadev/linediff.vim',
cmd = { 'Linediff', 'LinediffAdd' },
keys = {
{ '<Leader>mdf', ':Linediff<CR>', mode = 'x', desc = 'Line diff' },
{ '<Leader>mda', ':LinediffAdd<CR>', mode = 'x', desc = 'Line diff add' },
{ '<Leader>mds', '<cmd>LinediffShow<CR>', desc = 'Line diff show' },
{ '<Leader>mdr', '<cmd>LinediffReset<CR>', desc = 'Line diff reset' },
},
},
-----------------------------------------------------------------------------
{
'AndrewRadev/dsf.vim',
-- stylua: ignore
keys = {
{ 'dsf', '<Plug>DsfDelete', noremap = true, desc = 'Delete Surrounding Function' },
{ 'csf', '<Plug>DsfChange', noremap = true, desc = 'Change Surrounding Function' },
},
init = function()
vim.g.dsf_no_mappings = 1
end,
},
}

View File

@ -0,0 +1,73 @@
-- Plugins: Colorschemes
-- https://github.com/plex/vim-config
return {
{
'plex/theme-loader.nvim',
lazy = false,
priority = 99,
opts = { initial_colorscheme = 'neohybrid' },
},
{ 'plex/neo-hybrid.vim', priority = 100, lazy = false },
{ 'plex/awesome-vim-colorschemes', lazy = false },
{ 'AlexvZyl/nordic.nvim' },
{ 'folke/tokyonight.nvim', opts = { style = 'night' } },
{ 'rebelot/kanagawa.nvim' },
{ 'olimorris/onedarkpro.nvim' },
{ 'EdenEast/nightfox.nvim' },
{ 'nyoom-engineering/oxocarbon.nvim' },
{
'catppuccin/nvim',
lazy = true,
name = 'catppuccin',
opts = {
flavour = 'mocha', -- latte, frappe, macchiato, mocha
dim_inactive = { enabled = false },
integrations = {
alpha = true,
cmp = true,
flash = true,
gitsigns = true,
illuminate = true,
indent_blankline = { enabled = true },
lsp_trouble = true,
markdown = true,
mason = true,
mini = true,
native_lsp = {
enabled = true,
virtual_text = {
errors = { 'italic' },
hints = { 'italic' },
warnings = { 'italic' },
information = { 'italic' },
},
underlines = {
errors = { 'undercurl' },
hints = { 'undercurl' },
warnings = { 'undercurl' },
information = { 'undercurl' },
},
inlay_hints = {
background = true,
},
},
navic = { enabled = true },
neogit = true,
neotest = true,
neotree = true,
noice = true,
notify = true,
semantic_tokens = true,
symbols_outline = true,
treesitter_context = true,
telescope = { enabled = true },
treesitter = true,
which_key = true,
},
},
},
}

View File

@ -0,0 +1,6 @@
require('plex.config').init()
return {
{ 'folke/lazy.nvim', version = '*' },
{ 'nvim-lua/plenary.nvim', lazy = false },
}

514
lua/plex/plugins/editor.lua Normal file
View File

@ -0,0 +1,514 @@
-- Plugins: Editor
-- https://github.com/plex/vim-config
local is_windows = vim.loop.os_uname().sysname == 'Windows_NT'
return {
-----------------------------------------------------------------------------
{ 'nmac427/guess-indent.nvim', lazy = false, priority = 50, config = true },
{ 'tweekmonster/helpful.vim', cmd = 'HelpfulVersion' },
{ 'lambdalisue/suda.vim', event = 'BufRead' },
-----------------------------------------------------------------------------
{
'christoomey/vim-tmux-navigator',
lazy = false,
cond = not is_windows,
-- stylua: ignore
keys = {
{ '<C-h>', '<cmd>TmuxNavigateLeft<CR>', mode = { 'n', 't' }, silent = true, desc = 'Jump to left pane' },
{ '<C-j>', '<cmd>TmuxNavigateDown<CR>', mode = { 'n', 't' }, silent = true, desc = 'Jump to lower pane' },
{ '<C-k>', '<cmd>TmuxNavigateUp<CR>', mode = { 'n', 't' }, silent = true, desc = 'Jump to upper pane' },
{ '<C-l>', '<cmd>TmuxNavigateRight<CR>', mode = { 'n', 't' }, silent = true, desc = 'Jump to right pane' },
},
init = function()
vim.g.tmux_navigator_no_mappings = true
end,
},
-----------------------------------------------------------------------------
{
'olimorris/persisted.nvim',
event = 'VimEnter',
priority = 1000,
opts = {
autoload = true,
follow_cwd = false,
ignored_dirs = { '/usr', '/opt', '~/.cache', vim.env.TMPDIR or '/tmp' },
},
config = function(_, opts)
if vim.g.in_pager_mode or vim.env.GIT_EXEC_PATH ~= nil then
-- Do not autoload if stdin has been provided, or git commit session.
opts.autoload = false
opts.autosave = false
end
require('persisted').setup(opts)
end,
init = function()
-- Detect if stdin has been provided.
vim.g.in_pager_mode = false
vim.api.nvim_create_autocmd('StdinReadPre', {
group = vim.api.nvim_create_augroup('plex_persisted', {}),
callback = function()
vim.g.in_pager_mode = true
end,
})
-- Close all floats before loading a session. (e.g. Lazy.nvim)
vim.api.nvim_create_autocmd('User', {
group = 'plex_persisted',
pattern = 'PersistedLoadPre',
callback = function()
for _, win in pairs(vim.api.nvim_tabpage_list_wins(0)) do
if vim.api.nvim_win_get_config(win).zindex then
vim.api.nvim_win_close(win, false)
end
end
end,
})
-- Close all plugin owned buffers before saving a session.
vim.api.nvim_create_autocmd('User', {
pattern = 'PersistedSavePre',
group = 'plex_persisted',
callback = function()
-- Detect if window is owned by plugin by checking buftype.
local current_buffer = vim.api.nvim_get_current_buf()
for _, win in ipairs(vim.fn.getwininfo()) do
local buftype = vim.bo[win.bufnr].buftype
if buftype ~= '' and buftype ~= 'help' then
-- Delete plugin owned window buffers.
if win.bufnr == current_buffer then
-- Jump to previous window if current window is not a real file
vim.cmd.wincmd('p')
end
vim.api.nvim_buf_delete(win.bufnr, {})
end
end
end,
})
-- Before switching to a different session using Telescope, save and stop
-- current session to avoid previous session to be overwritten.
vim.api.nvim_create_autocmd('User', {
pattern = 'PersistedTelescopeLoadPre',
group = 'plex_persisted',
callback = function()
require('persisted').save()
require('persisted').stop()
end,
})
-- After switching to a different session using Telescope, start it so it
-- will be auto-saved.
vim.api.nvim_create_autocmd('User', {
pattern = 'PersistedTelescopeLoadPost',
group = 'plex_persisted',
callback = function(session)
require('persisted').start()
print('Started session ' .. session.data.name)
end,
})
end,
},
-----------------------------------------------------------------------------
{
'RRethy/vim-illuminate',
event = { 'BufReadPost', 'BufNewFile' },
opts = {
delay = 200,
under_cursor = false,
modes_allowlist = { 'n', 'no', 'nt' },
filetypes_denylist = {
'DiffviewFileHistory',
'DiffviewFiles',
'SidebarNvim',
'fugitive',
'git',
'minifiles',
'neo-tree',
},
},
keys = {
{ ']]', desc = 'Next Reference' },
{ '[[', desc = 'Prev Reference' },
},
config = function(_, opts)
require('illuminate').configure(opts)
local function map(key, dir, buffer)
vim.keymap.set('n', key, function()
require('illuminate')['goto_' .. dir .. '_reference'](false)
end, {
desc = dir:sub(1, 1):upper() .. dir:sub(2) .. ' Reference',
buffer = buffer,
})
end
map(']]', 'next')
map('[[', 'prev')
-- also set it after loading ftplugins, since a lot overwrite [[ and ]]
vim.api.nvim_create_autocmd('FileType', {
group = vim.api.nvim_create_augroup('plex_illuminate', {}),
callback = function()
local buffer = vim.api.nvim_get_current_buf()
map(']]', 'next', buffer)
map('[[', 'prev', buffer)
end,
})
end,
},
-----------------------------------------------------------------------------
{
'mbbill/undotree',
cmd = 'UndotreeToggle',
keys = {
{ '<Leader>gu', '<cmd>UndotreeToggle<CR>', desc = 'Undo Tree' },
},
},
-----------------------------------------------------------------------------
{
'ggandor/flit.nvim',
keys = function()
---@type LazyKeys[]
local ret = {}
for _, key in ipairs({ 'f', 'F', 't', 'T' }) do
ret[#ret + 1] = { key, mode = { 'n', 'x', 'o' }, desc = key }
end
return ret
end,
opts = { labeled_modes = 'nx' },
},
-----------------------------------------------------------------------------
{
'ggandor/leap.nvim',
-- stylua: ignore
keys = {
{ 'ss', '<Plug>(leap-forward-to)', mode = { 'n', 'x', 'o' }, desc = 'Leap forward to' },
{ 'sS', '<Plug>(leap-backward-to)', mode = { 'n', 'x', 'o' }, desc = 'Leap backward to' },
{ 'SS', '<Plug>(leap-from-window)', mode = { 'n', 'x', 'o' }, desc = 'Leap from windows' },
},
config = true,
},
-----------------------------------------------------------------------------
{
'kana/vim-niceblock',
-- stylua: ignore
keys = {
{ 'I', '<Plug>(niceblock-I)', silent = true, mode = 'x', desc = 'Blockwise Insert' },
{ 'gI', '<Plug>(niceblock-gI)', silent = true, mode = 'x', desc = 'Blockwise Insert' },
{ 'A', '<Plug>(niceblock-A)', silent = true, mode = 'x', desc = 'Blockwise Append' },
},
init = function()
vim.g.niceblock_no_default_key_mappings = 0
end,
},
-----------------------------------------------------------------------------
{
'haya14busa/vim-edgemotion',
-- stylua: ignore
keys = {
{ 'gj', '<Plug>(edgemotion-j)', mode = { 'n', 'x' }, desc = 'Move to bottom edge' },
{ 'gk', '<Plug>(edgemotion-k)', mode = { 'n', 'x' }, desc = 'Move to top edge' },
},
},
-----------------------------------------------------------------------------
{
'folke/zen-mode.nvim',
cmd = 'ZenMode',
keys = {
{ '<Leader>zz', '<cmd>ZenMode<CR>', noremap = true, desc = 'Zen Mode' },
},
opts = {
plugins = {
gitsigns = { enabled = true },
tmux = { enabled = vim.env.TMUX ~= nil },
},
},
},
-----------------------------------------------------------------------------
{
'folke/which-key.nvim',
event = 'VeryLazy',
opts = {
icons = { separator = ' 󰁔 ' },
window = { winblend = 0 },
defaults = {
mode = { 'n', 'v' },
[';'] = { name = '+telescope' },
[';d'] = { name = '+lsp/todo' },
['g'] = { name = '+goto' },
['gz'] = { name = '+surround' },
[']'] = { name = '+next' },
['['] = { name = '+prev' },
['<leader>b'] = { name = '+buffer' },
['<leader>c'] = { name = '+code' },
['<leader>g'] = { name = '+git' },
['<leader>h'] = { name = '+hunks' },
['<leader>s'] = { name = '+search' },
['<leader>t'] = { name = '+toggle/tools' },
['<leader>u'] = { name = '+ui' },
['<leader>x'] = { name = '+diagnostics/quickfix' },
['<leader>z'] = { name = '+notes' },
},
},
config = function(_, opts)
local wk = require('which-key')
wk.setup(opts)
wk.register(opts.defaults)
end,
},
-----------------------------------------------------------------------------
{
'folke/todo-comments.nvim',
dependencies = 'nvim-telescope/telescope.nvim',
-- stylua: ignore
keys = {
{ ']t', function() require('todo-comments').jump_next() end, desc = 'Next todo comment' },
{ '[t', function() require('todo-comments').jump_prev() end, desc = 'Previous todo comment' },
{ '<LocalLeader>dt', '<cmd>TodoTelescope<CR>', desc = 'todo' },
{ '<leader>xt', '<cmd>TodoTrouble<CR>', desc = 'Todo (Trouble)' },
{ '<leader>xT', '<cmd>TodoTrouble keywords=TODO,FIX,FIXME<cr>', desc = 'Todo/Fix/Fixme (Trouble)' },
{ '<leader>st', '<cmd>TodoTelescope<cr>', desc = 'Todo' },
{ '<leader>sT', '<cmd>TodoTelescope keywords=TODO,FIX,FIXME<cr>', desc = 'Todo/Fix/Fixme' },
},
opts = { signs = false },
},
-----------------------------------------------------------------------------
{
'folke/trouble.nvim',
cmd = { 'Trouble', 'TroubleToggle' },
opts = { use_diagnostic_signs = true },
-- stylua: ignore
keys = {
{ '<leader>e', '<cmd>TroubleToggle document_diagnostics<CR>', noremap = true, desc = 'Document Diagnostics' },
{ '<leader>r', '<cmd>TroubleToggle workspace_diagnostics<CR>', noremap = true, desc = 'Workspace Diagnostics' },
{ '<leader>xx', '<cmd>TroubleToggle document_diagnostics<cr>', desc = 'Document Diagnostics (Trouble)' },
{ '<leader>xX', '<cmd>TroubleToggle workspace_diagnostics<cr>', desc = 'Workspace Diagnostics (Trouble)' },
{ '<leader>xQ', '<cmd>TroubleToggle quickfix<cr>', desc = 'Quickfix List (Trouble)' },
{ '<leader>xL', '<cmd>TroubleToggle loclist<cr>', desc = 'Location List (Trouble)' },
{
'[q',
function()
if require('trouble').is_open() then
require('trouble').previous({ skip_groups = true, jump = true })
else
vim.cmd.cprev()
end
end,
desc = 'Previous trouble/quickfix item',
},
{
']q',
function()
if require('trouble').is_open() then
require('trouble').next({ skip_groups = true, jump = true })
else
vim.cmd.cnext()
end
end,
desc = 'Next trouble/quickfix item',
},
},
},
-----------------------------------------------------------------------------
{
'akinsho/toggleterm.nvim',
cmd = 'ToggleTerm',
keys = {
{
'<C-_>',
mode = { 'n', 't' },
silent = true,
function()
local venv = vim.b['virtual_env']
local term = require('toggleterm.terminal').Terminal:new({
env = venv and { VIRTUAL_ENV = venv } or nil,
count = vim.v.count > 0 and vim.v.count or 1,
})
term:toggle()
end,
desc = 'Toggle terminal',
},
},
opts = {
open_mapping = false,
float_opts = {
border = 'curved',
},
},
},
-----------------------------------------------------------------------------
{
'simrat39/symbols-outline.nvim',
cmd = { 'SymbolsOutline', 'SymbolsOutlineOpen' },
keys = {
{ '<Leader>o', '<cmd>SymbolsOutline<CR>', desc = 'Symbols Outline' },
},
opts = {
width = 30,
autofold_depth = 0,
keymaps = {
hover_symbol = 'K',
toggle_preview = 'p',
},
},
init = function()
vim.api.nvim_create_autocmd('FileType', {
group = vim.api.nvim_create_augroup('plex_outline', {}),
pattern = 'Outline',
callback = function()
vim.opt_local.winhighlight = 'CursorLine:WildMenu'
vim.opt_local.signcolumn = 'auto'
end,
})
end,
},
-----------------------------------------------------------------------------
{
's1n7ax/nvim-window-picker',
event = 'VeryLazy',
keys = function(_, keys)
local pick_window = function()
local picked_window_id = require('window-picker').pick_window()
if picked_window_id ~= nil then
vim.api.nvim_set_current_win(picked_window_id)
end
end
local swap_window = function()
local picked_window_id = require('window-picker').pick_window()
if picked_window_id ~= nil then
local current_winnr = vim.api.nvim_get_current_win()
local current_bufnr = vim.api.nvim_get_current_buf()
local other_bufnr = vim.api.nvim_win_get_buf(picked_window_id)
vim.api.nvim_win_set_buf(current_winnr, other_bufnr)
vim.api.nvim_win_set_buf(picked_window_id, current_bufnr)
end
end
local mappings = {
{ '-', pick_window, desc = 'Pick window' },
{ 'sp', pick_window, desc = 'Pick window' },
{ 'sw', swap_window, desc = 'Swap picked window' },
}
return vim.list_extend(mappings, keys)
end,
opts = {
hint = 'floating-big-letter',
show_prompt = false,
filter_rules = {
include_current_win = true,
bo = {
filetype = { 'notify', 'noice' },
buftype = {},
},
},
},
},
-----------------------------------------------------------------------------
{
'rest-nvim/rest.nvim',
ft = 'http',
keys = {
{ '<Leader>mh', '<Plug>RestNvim', desc = 'Execute HTTP request' },
},
opts = { skip_ssl_verification = true },
},
-----------------------------------------------------------------------------
{
'mickael-menu/zk-nvim',
name = 'zk',
ft = 'markdown',
cmd = { 'ZkNew', 'ZkNotes', 'ZkTags', 'ZkMatch' },
-- stylua: ignore
keys = {
{ '<leader>zn', "<Cmd>ZkNew { title = vim.fn.input('Title: ') }<CR>", desc = 'Zk New' },
{ '<leader>zo', "<Cmd>ZkNotes { sort = { 'modified' } }<CR>", desc = 'Zk Notes' },
{ '<leader>zt', '<Cmd>ZkTags<CR>', desc = 'Zk Tags' },
{ '<leader>zf', "<Cmd>ZkNotes { sort = { 'modified' }, match = vim.fn.input('Search: ') }<CR>", desc = 'Zk Search' },
{ '<leader>zf', ":'<,'>ZkMatch<CR>", mode = 'x', desc = 'Zk Match' },
{ '<leader>zb', '<Cmd>ZkBacklinks<CR>', desc = 'Zk Backlinks' },
{ '<leader>zl', '<Cmd>ZkLinks<CR>', desc = 'Zk Links' },
},
opts = { picker = 'telescope' },
},
-----------------------------------------------------------------------------
{
'nvim-pack/nvim-spectre',
-- stylua: ignore
keys = {
{ '<Leader>sp', function() require('spectre').toggle() end, desc = 'Spectre', },
{ '<Leader>sp', function() require('spectre').open_visual({ select_word = true }) end, mode = 'x', desc = 'Spectre Word' },
},
opts = {
mapping = {
['toggle_gitignore'] = {
map = 'tg',
cmd = "<cmd>lua require('spectre').change_options('gitignore')<CR>",
desc = 'toggle gitignore',
},
},
find_engine = {
['rg'] = {
cmd = 'rg',
args = {
'--color=never',
'--no-heading',
'--with-filename',
'--line-number',
'--column',
'--ignore',
},
options = {
['gitignore'] = {
value = '--no-ignore',
icon = '[G]',
desc = 'gitignore',
},
},
},
},
default = {
find = {
cmd = 'rg',
options = { 'ignore-case', 'hidden', 'gitignore' },
},
},
},
},
-----------------------------------------------------------------------------
{
'echasnovski/mini.bufremove',
opts = {},
-- stylua: ignore
keys = {
{ '<leader>bd', function() require('mini.bufremove').delete(0, false) end, desc = 'Delete Buffer', },
},
},
-----------------------------------------------------------------------------
{
'mzlogin/vim-markdown-toc',
cmd = { 'GenTocGFM', 'GenTocRedcarpet', 'GenTocGitLab', 'UpdateToc' },
ft = 'markdown',
init = function()
vim.g.vmt_auto_update_on_save = 0
end,
},
}

View File

@ -0,0 +1,18 @@
return {
{
'windwp/nvim-autopairs',
dependencies = 'hrsh7th/nvim-cmp',
config = function()
local autopairs = require('nvim-autopairs')
autopairs.setup()
-- Disable [ rule, it interferes with zk-nvim link completion.
local cond = require('nvim-autopairs.conds')
autopairs.get_rule('['):with_pair(cond.not_filetypes({ 'markdown' }))
-- Insert `(` after function or method item selection.
local cmp_autopairs = require('nvim-autopairs.completion.cmp')
require('cmp').event:on('confirm_done', cmp_autopairs.on_confirm_done())
end,
},
}

View File

@ -0,0 +1,26 @@
return {
{
'hrsh7th/nvim-cmp',
optional = true,
dependencies = { 'petertriho/cmp-git' },
},
{
'petertriho/cmp-git',
opts = {},
config = function()
local cmp = require('cmp')
---@diagnostic disable-next-line: missing-fields
cmp.setup.filetype('gitcommit', {
sources = cmp.config.sources({
{ name = 'git', priority = 50 },
{ name = 'path', priority = 40 },
}, {
{ name = 'buffer', priority = 50 },
{ name = 'emoji', insert = true, priority = 20 },
}),
})
end,
},
}

View File

@ -0,0 +1,107 @@
-- This is part of LazyVim's code, with my modifications.
-- See: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/plugins/extras/coding/copilot.lua
return {
-----------------------------------------------------------------------------
{
'zbirenbaum/copilot.lua',
cmd = 'Copilot',
build = ':Copilot auth',
opts = {
suggestion = { enabled = false },
panel = { enabled = false },
filetypes = {
markdown = true,
help = true,
},
},
},
-----------------------------------------------------------------------------
{
'nvim-lualine/lualine.nvim',
optional = true,
event = 'VeryLazy',
opts = function(_, opts)
local get_color = require('plex.lib.color').get_color
local fg = function(...)
return { fg = get_color('fg', ...) }
end
local colors = {
[''] = fg({ 'Comment' }),
['Normal'] = fg({ 'Comment' }),
['Warning'] = fg({ 'DiagnosticError' }),
['InProgress'] = fg({ 'DiagnosticWarn' }),
}
-- Add copilot icon to lualine statusline
table.insert(opts.sections.lualine_x, {
function()
local icon = require('plex.config').icons.kinds.Copilot
local status = require('copilot.api').status.data
return icon .. (status.message or '')
end,
cond = function()
local clients
if vim.lsp.get_clients ~= nil then
clients = vim.lsp.get_clients({ name = 'copilot', bufnr = 0 })
else
---@diagnostic disable-next-line: deprecated
clients = vim.lsp.get_active_clients({
name = 'copilot',
bufnr = 0,
})
end
return #clients > 0
end,
color = function()
if not package.loaded["copilot"] then
return
end
local status = require('copilot.api').status.data
return colors[status.status] or colors['']
end,
})
end,
},
-----------------------------------------------------------------------------
{
'nvim-cmp',
dependencies = {
{
'zbirenbaum/copilot-cmp',
dependencies = 'zbirenbaum/copilot.lua',
opts = {},
config = function(_, opts)
local copilot_cmp = require('copilot_cmp')
copilot_cmp.setup(opts)
-- attach cmp source whenever copilot attaches
-- fixes lazy-loading issues with the copilot cmp source
---@param client lsp.Client
require('plex.lib.utils').on_attach(function(client)
if client.name == 'copilot' then
copilot_cmp._on_insert_enter({})
end
end)
end,
},
},
---@param opts cmp.ConfigSchema|{sources: table[]}
opts = function(_, opts)
-- Add copilot nvim-cmp source.
table.insert(opts.sources, 1, {
name = 'copilot',
group_index = 2,
priority = 60,
})
opts.sorting = opts.sorting or require('cmp.config.default')().sorting
table.insert(
opts.sorting.comparators,
1,
require('copilot_cmp.comparators').prioritize
)
end,
},
}

View File

@ -0,0 +1,20 @@
return {
{
'sgur/vim-editorconfig',
lazy = false,
init = function()
vim.g.editorconfig_verbose = 1
vim.g.editorconfig_blacklist = {
filetype = {
'git.*',
'fugitive',
'help',
'lsp-.*',
'any-jump',
'gina-.*',
},
pattern = { '\\.un~$' },
}
end,
},
}

View File

@ -0,0 +1,31 @@
return {
{
'mattn/emmet-vim',
ft = { 'html', 'css', 'vue', 'javascript', 'javascriptreact', 'svelte' },
init = function()
vim.g.user_emmet_mode = 'i'
vim.g.user_emmet_install_global = 0
vim.g.user_emmet_install_command = 0
vim.g.user_emmet_complete_tag = 0
end,
config = function()
vim.api.nvim_create_autocmd('FileType', {
group = vim.api.nvim_create_augroup('plex_emmet', {}),
pattern = {
'css',
'html',
'javascript',
'javascriptreact',
'svelte',
'vue',
},
callback = function()
vim.cmd([[
EmmetInstall
imap <silent><buffer> <C-y> <Plug>(emmet-expand-abbr)
]])
end,
})
end,
},
}

View File

@ -0,0 +1,19 @@
return {
{
'machakann/vim-sandwich',
-- stylua: ignore
keys = {
-- See https://github.com/machakann/vim-sandwich/blob/master/macros/sandwich/keymap/surround.vim
{ 'ds', '<Plug>(operator-sandwich-delete)<Plug>(operator-sandwich-release-count)<Plug>(textobj-sandwich-query-a)', silent = true },
{ 'dss', '<Plug>(operator-sandwich-delete)<Plug>(operator-sandwich-release-count)<Plug>(textobj-sandwich-auto-a)', silent = true },
{ 'cs', '<Plug>(operator-sandwich-replace)<Plug>(operator-sandwich-release-count)<Plug>(textobj-sandwich-query-a)', silent = true },
{ 'css', '<Plug>(operator-sandwich-replace)<Plug>(operator-sandwich-release-count)<Plug>(textobj-sandwich-auto-a)', silent = true },
{ 'sa', '<Plug>(operator-sandwich-add)', silent = true, mode = { 'n', 'x', 'o' }},
{ 'ir', '<Plug>(textobj-sandwich-auto-i)', silent = true, mode = { 'x', 'o' }},
{ 'ab', '<Plug>(textobj-sandwich-auto-a)', silent = true, mode = { 'x', 'o' }},
},
init = function()
vim.g.sandwich_no_default_key_mappings = 1
end,
},
}

View File

@ -0,0 +1,22 @@
return {
{
'williamboman/mason.nvim',
opts = function(_, opts)
table.insert(opts.ensure_installed, 'proselint')
end,
},
{
'jose-elias-alvarez/null-ls.nvim',
optional = true,
opts = function(_, opts)
local nls = require('null-ls')
local source = nls.builtins.diagnostics.proselint.with({
diagnostics_postprocess = function(diagnostic)
diagnostic.severity = vim.diagnostic.severity.HINT
end,
})
table.insert(opts.sources, source)
end,
},
}

View File

@ -0,0 +1,22 @@
return {
{
'williamboman/mason.nvim',
opts = function(_, opts)
table.insert(opts.ensure_installed, 'write-good')
end,
},
{
'jose-elias-alvarez/null-ls.nvim',
optional = true,
opts = function(_, opts)
local nls = require('null-ls')
local source = nls.builtins.diagnostics.write_good.with({
diagnostics_postprocess = function(diagnostic)
diagnostic.severity = vim.diagnostic.severity.HINT
end,
})
table.insert(opts.sources, source)
end,
},
}

View File

@ -0,0 +1,22 @@
return {
{
'pechorin/any-jump.vim',
cmd = { 'AnyJump', 'AnyJumpVisual' },
keys = {
{ '<leader>ii', '<cmd>AnyJump<CR>', desc = 'Any Jump' },
{ '<leader>ii', '<cmd>AnyJumpVisual<CR>', mode = 'x', desc = 'Any Jump' },
{ '<leader>ib', '<cmd>AnyJumpBack<CR>', desc = 'Any Jump Back' },
{ '<leader>il', '<cmd>AnyJumpLastResults<CR>', desc = 'Any Jump Resume' },
},
init = function()
vim.g.any_jump_disable_default_keybindings = 1
vim.api.nvim_create_autocmd('FileType', {
group = vim.api.nvim_create_augroup('plex_any-jump', {}),
pattern = 'any-jump',
callback = function()
vim.opt.cursorline = true
end,
})
end,
},
}

View File

@ -0,0 +1,11 @@
return {
{
'glepnir/flybuf.nvim',
cmd = 'FlyBuf',
keys = {
-- stylua: ignore
{ '<Leader><Tab>', function() require('flybuf').toggle() end, desc = 'Flybuf' },
},
opts = {},
},
}

View File

@ -0,0 +1,14 @@
return {
{
'sidebar-nvim/sidebar.nvim',
main = 'sidebar-nvim',
cmd = { 'SidebarNvimToggle', 'SidebarNvimOpen' },
opts = {
open = true,
bindings = {
-- stylua: ignore
['q'] = function() require('sidebar-nvim').close() end,
},
},
},
}

View File

@ -0,0 +1,112 @@
return {
{
'neovim/nvim-lspconfig',
opts = {
capabilities = {
textDocument = {
foldingRange = {
dynamicRegistration = false,
lineFoldingOnly = true,
},
},
},
},
},
{
'kevinhwang91/nvim-ufo',
event = { 'BufReadPost', 'BufNewFile' },
-- stylua: ignore
keys = {
{ 'zR', function() require('ufo').openAllFolds() end },
{ 'zM', function() require('ufo').closeAllFolds() end },
-- { 'zr', function() require('ufo').openFoldsExceptKinds() end },
-- { 'zm', function() require('ufo').closeFoldsWith() end },
},
dependencies = {
'kevinhwang91/promise-async',
'nvim-treesitter/nvim-treesitter',
'neovim/nvim-lspconfig',
},
opts = function()
-- lsp->treesitter->indent
---@param bufnr number
---@return table
local function customizeSelector(bufnr)
local function handleFallbackException(err, providerName)
if type(err) == 'string' and err:match('UfoFallbackException') then
return require('ufo').getFolds(bufnr, providerName)
else
return require('promise').reject(err)
end
end
return require('ufo')
.getFolds(bufnr, 'lsp')
:catch(function(err)
return handleFallbackException(err, 'treesitter')
end)
:catch(function(err)
return handleFallbackException(err, 'indent')
end)
end
local ft_providers = {
vim = 'indent',
python = { 'indent' },
git = '',
help = '',
qf = '',
fugitive = '',
fugitiveblame = '',
['neo-tree'] = '',
}
return {
open_fold_hl_timeout = 0,
preview = {
win_config = {
border = { '', '', '', '', '', '', '', '' },
winhighlight = 'Normal:Folded',
winblend = 10,
},
mappings = {
scrollU = '<C-u>',
scrollD = '<C-d>',
jumpTop = '[',
jumpBot = ']',
},
},
-- Select the fold provider.
provider_selector = function(_, filetype, _)
return ft_providers[filetype] or customizeSelector
end,
-- Display text for folded lines.
---@param text table
---@param lnum integer
---@param endLnum integer
---@param width integer
---@return table
fold_virt_text_handler = function(text, lnum, endLnum, width)
local suffix = ' 󰇘 '
local lines = (' 󰁂 %d '):format(endLnum - lnum)
local cur_width = 0
for _, section in ipairs(text) do
cur_width = cur_width + vim.fn.strdisplaywidth(section[1])
end
suffix = suffix
.. (' '):rep(width - cur_width - vim.fn.strdisplaywidth(lines) - 3)
table.insert(text, { suffix, 'UfoFoldedEllipsis' })
table.insert(text, { lines, 'Folded' })
return text
end,
}
end,
},
}

View File

@ -0,0 +1,36 @@
-- This is part of LazyVim's code, with my modifications.
-- See: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/plugins/extras/formatting/prettier.lua
return {
{
'williamboman/mason.nvim',
opts = function(_, opts)
if type(opts.ensure_installed) == 'table' then
table.insert(opts.ensure_installed, 'prettierd')
end
end,
},
{
'mhartington/formatter.nvim',
optional = true,
opts = function(_, opts)
opts = opts or {}
local filetypes = {
-- FIXME:add more filetypes
json = { require('formatter.defaults.prettierd') },
}
opts.filetype = vim.tbl_extend('keep', opts.filetype or {}, filetypes)
end,
},
{
'jose-elias-alvarez/null-ls.nvim',
optional = true,
opts = function(_, opts)
local nls = require('null-ls')
table.insert(opts.sources, nls.builtins.formatting.prettierd)
end,
},
}

View File

@ -0,0 +1,31 @@
return {
-----------------------------------------------------------------------------
{
'tpope/vim-fugitive',
cmd = { 'G', 'Git', 'Gfetch', 'Gpush', 'Gclog', 'Gdiffsplit' },
keys = {
{ '<leader>gd', '<cmd>Gdiffsplit<CR>', desc = 'Git diff' },
{ '<leader>gb', '<cmd>Git blame<CR>', desc = 'Git blame' },
},
config = function()
vim.api.nvim_create_autocmd('FileType', {
group = vim.api.nvim_create_augroup('plex_fugitive', {}),
pattern = 'fugitiveblame',
callback = function()
vim.schedule(function()
vim.cmd.normal('A')
end)
end,
})
end,
},
-----------------------------------------------------------------------------
{
'junegunn/gv.vim',
dependencies = { 'tpope/vim-fugitive' },
cmd = 'GV',
},
}

View File

@ -0,0 +1,72 @@
-- plex.plugins.extras.lang.ansible
--
return {
{
'nvim-treesitter/nvim-treesitter',
dependencies = {
'pearofducks/ansible-vim',
ft = { 'ansible', 'ansible_hosts', 'jinja2' },
},
opts = function(_, opts)
if type(opts.ensure_installed) == 'table' then
vim.list_extend(opts.ensure_installed, { 'yaml' })
end
vim.g.ansible_extra_keywords_highlight = 1
vim.g.ansible_template_syntaxes = {
['*.json.j2'] = 'json',
['*.(ba)?sh.j2'] = 'sh',
['*.ya?ml.j2'] = 'yaml',
['*.xml.j2'] = 'xml',
['*.conf.j2'] = 'conf',
['*.ini.j2'] = 'ini',
}
-- Setup filetype settings
vim.api.nvim_create_autocmd('FileType', {
group = vim.api.nvim_create_augroup('plex_ftplugin_ansible', {}),
pattern = 'ansible',
callback = function()
-- Add '.' to iskeyword for ansible modules, e.g. ansible.builtin.copy
vim.opt_local.iskeyword:append('.')
vim.b.undo_ftplugin = (vim.b.undo_ftplugin or '')
.. (vim.b.undo_ftplugin ~= nil and ' | ' or '')
.. 'setlocal iskeyword<'
if vim.fn.executable('ansible-doc') then
vim.b.undo_ftplugin = vim.b.undo_ftplugin
.. '| sil! nunmap <buffer> gK'
vim.keymap.set('n', 'gK', function()
-- Open ansible-doc in a vertical split with word under cursor.
vim.cmd([[
vertical split
| execute('terminal PAGER=cat ansible-doc ' .. shellescape(expand('<cword>')))
| setf man
| wincmd p
]])
end, { buffer = 0 })
end
end,
})
end,
},
{
'neovim/nvim-lspconfig',
opts = {
servers = {
ansiblels = {},
},
},
},
{
'mason.nvim',
opts = function(_, opts)
opts.ensure_installed = opts.ensure_installed or {}
vim.list_extend(opts.ensure_installed, { 'ansible-lint' })
end,
},
}

View File

@ -0,0 +1,50 @@
-- This is part of LazyVim's code, with my modifications.
-- See: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/plugins/extras/lang/docker.lua
return {
{
'nvim-treesitter/nvim-treesitter',
opts = function(_, opts)
if type(opts.ensure_installed) == 'table' then
vim.list_extend(opts.ensure_installed, { 'dockerfile' })
end
end,
},
{
'neovim/nvim-lspconfig',
opts = {
servers = {
dockerls = {},
-- docker_compose_language_service = {},
},
},
},
{
'mason.nvim',
opts = function(_, opts)
opts.ensure_installed = opts.ensure_installed or {}
vim.list_extend(opts.ensure_installed, { 'hadolint' })
end,
},
{
'jose-elias-alvarez/null-ls.nvim',
optional = true,
opts = function(_, opts)
local nls = require('null-ls')
opts.sources = opts.sources or {}
vim.list_extend(opts.sources, {
nls.builtins.diagnostics.hadolint,
})
end,
dependencies = {
'mason.nvim',
opts = function(_, opts)
opts.ensure_installed = opts.ensure_installed or {}
vim.list_extend(opts.ensure_installed, { 'hadolint' })
end,
},
},
}

View File

@ -0,0 +1,199 @@
-- This is part of LazyVim's code, with my modifications.
-- See: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/plugins/extras/lang/go.lua
return {
{
'nvim-treesitter/nvim-treesitter',
opts = function(_, opts)
if type(opts.ensure_installed) == 'table' then
vim.list_extend(opts.ensure_installed, {
'go',
'gomod',
'gosum',
'gowork',
})
end
-- Convert a JSON string to a Go struct.
vim.api.nvim_buf_create_user_command(
0,
'JsonToStruct',
---@param args table
function(args)
local range = args.line1 .. ',' .. args.line2
local fname = vim.api.nvim_buf_get_name(0)
local cmd = { '!json-to-struct' }
table.insert(cmd, '-name ' .. vim.fn.fnamemodify(fname, ':t:r'))
table.insert(cmd, '-pkg ' .. vim.fn.fnamemodify(fname, ':h:t:r'))
vim.cmd(range .. ' ' .. table.concat(cmd, ' '))
end,
{ bar = true, nargs = 0, range = true }
)
end,
},
{
'neovim/nvim-lspconfig',
opts = {
servers = {
gopls = {
settings = {
-- https://github.com/golang/tools/blob/master/gopls/doc/settings.md
gopls = {
gofumpt = true,
usePlaceholders = true,
completeUnimported = true,
staticcheck = true,
directoryFilters = {
'-.git',
'-.vscode',
'-.idea',
'-.vscode-test',
'-node_modules',
},
semanticTokens = true,
codelenses = {
gc_details = false,
generate = true,
regenerate_cgo = true,
run_govulncheck = true,
test = true,
tidy = true,
upgrade_dependency = true,
vendor = true,
},
hints = {
assignVariableTypes = true,
compositeLiteralFields = true,
compositeLiteralTypes = true,
constantValues = true,
functionTypeParameters = true,
parameterNames = true,
rangeVariableTypes = true,
},
-- https://github.com/golang/tools/blob/master/gopls/doc/analyzers.md
analyses = {
fieldalignment = true,
nilness = true,
unusedparams = true,
unusedwrite = true,
useany = true,
-- fillreturns = true,
-- nonewvars = true,
-- shadow = true,
-- undeclaredname = true,
-- unusedvariable = true,
-- ST1000 = false,
-- ST1005 = false,
},
},
},
},
},
setup = {
gopls = function(_, _)
-- workaround for gopls not supporting semanticTokensProvider
-- https://github.com/golang/go/issues/54531#issuecomment-1464982242
require('plex.lib.utils').on_attach(function(client, _)
if client.name == 'gopls' then
if not client.server_capabilities.semanticTokensProvider then
local semantic =
client.config.capabilities.textDocument.semanticTokens
if semantic ~= nil then
client.server_capabilities.semanticTokensProvider = {
full = true,
legend = {
tokenTypes = semantic.tokenTypes,
tokenModifiers = semantic.tokenModifiers,
},
range = true,
}
end
end
end
end)
-- end workaround
end,
},
},
},
{
'mason.nvim',
opts = function(_, opts)
opts.ensure_installed = opts.ensure_installed or {}
vim.list_extend(opts.ensure_installed, {
'gofumpt',
'goimports-reviser',
'gomodifytags',
'impl',
'json-to-struct',
})
end,
},
{
'mhartington/formatter.nvim',
optional = true,
opts = function(_, opts)
opts = opts or {}
local filetypes = {
go = {
require('formatter.filetypes.go').gofumpt,
},
}
opts.filetype = vim.tbl_extend('keep', opts.filetype or {}, filetypes)
end,
},
{
'jose-elias-alvarez/null-ls.nvim',
optional = true,
opts = function(_, opts)
local nls = require('null-ls')
local sources = {
nls.builtins.code_actions.gomodifytags,
nls.builtins.code_actions.impl,
nls.builtins.formatting.gofumpt,
-- nls.builtins.formatting.goimports_reviser,
}
opts.sources = opts.sources or {}
for _, source in ipairs(sources) do
table.insert(opts.sources, source)
end
end,
},
{
'mfussenegger/nvim-dap',
optional = true,
dependencies = {
{
'mason.nvim',
opts = function(_, opts)
opts.ensure_installed = opts.ensure_installed or {}
vim.list_extend(opts.ensure_installed, { 'delve' })
end,
},
{
'leoluz/nvim-dap-go',
config = true,
},
},
},
{
'nvim-neotest/neotest',
optional = true,
dependencies = { 'nvim-neotest/neotest-go' },
opts = {
adapters = {
['neotest-go'] = {
-- Here we can set options for neotest-go, e.g.
-- args = { '-tags=integration' }
},
},
},
},
}

View File

@ -0,0 +1,24 @@
-- plex.plugins.extras.lang.helm
--
return {
{ 'towolf/vim-helm', ft = 'helm' },
{
'nvim-treesitter/nvim-treesitter',
opts = function(_, opts)
if type(opts.ensure_installed) == 'table' then
vim.list_extend(opts.ensure_installed, { 'yaml' })
end
end,
},
{
'mason.nvim',
opts = function(_, opts)
opts.ensure_installed = opts.ensure_installed or {}
vim.list_extend(opts.ensure_installed, { 'helm-ls' })
end,
},
}

View File

@ -0,0 +1,40 @@
-- This is part of LazyVim's code, with my modifications.
-- See: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/plugins/extras/lang/json.lua
return {
{
'nvim-treesitter/nvim-treesitter',
opts = function(_, opts)
if type(opts.ensure_installed) == 'table' then
vim.list_extend(opts.ensure_installed, { 'json', 'json5', 'jsonc' })
end
end,
},
{
'neovim/nvim-lspconfig',
dependencies = { 'b0o/SchemaStore.nvim', version = false },
opts = {
servers = {
jsonls = {
-- lazy-load schemastore when needed
on_new_config = function(new_config)
new_config.settings.json.schemas = new_config.settings.json.schemas
or {}
vim.list_extend(
new_config.settings.json.schemas,
require('schemastore').json.schemas()
)
end,
settings = {
json = {
format = { enable = true },
validate = { enable = true },
},
},
},
},
},
},
}

View File

@ -0,0 +1,72 @@
-- plex.plugins.extras.lang.python
--
-- This is part of LazyVim's code, with my modifications.
-- See: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/plugins/extras/lang/python.lua
return {
{
'nvim-treesitter/nvim-treesitter',
opts = function(_, opts)
if type(opts.ensure_installed) == 'table' then
vim.list_extend(
opts.ensure_installed,
{ 'ninja', 'python', 'requirements', 'rst', 'toml' }
)
end
end,
},
{
'neovim/nvim-lspconfig',
dependencies = 'plex/neoconf-venom.nvim',
opts = {
servers = {
pyright = {},
},
},
},
{
'plex/neoconf-venom.nvim',
main = 'venom',
opts = {},
-- stylua: ignore
keys = {
{ '<leader>cv', '<cmd>Telescope venom virtualenvs<cr>', desc = 'Select VirtualEnv' },
},
},
{
'nvim-neotest/neotest',
optional = true,
dependencies = { 'nvim-neotest/neotest-python' },
opts = {
adapters = {
['neotest-python'] = {
-- Here you can specify the settings for the adapter, i.e.
-- runner = "pytest",
-- python = '.venv/bin/python',
},
},
},
},
{
'mfussenegger/nvim-dap',
optional = true,
dependencies = {
'mfussenegger/nvim-dap-python',
-- stylua: ignore
keys = {
{ '<leader>dPt', function() require('dap-python').test_method() end, desc = 'Debug Method' },
{ '<leader>dPc', function() require('dap-python').test_class() end, desc = 'Debug Class' },
},
config = function()
local path =
require('mason-registry').get_package('debugpy'):get_install_path()
require('dap-python').setup(path .. '/venv/bin/python')
end,
},
},
}

View File

@ -0,0 +1,38 @@
-- This is part of LazyVim's code, with my modifications.
-- See: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/plugins/extras/lang/terraform.lua
return {
{
'nvim-treesitter/nvim-treesitter',
opts = function(_, opts)
if type(opts.ensure_installed) == 'table' then
vim.list_extend(opts.ensure_installed, {
'terraform',
'hcl',
})
end
end,
},
{
'neovim/nvim-lspconfig',
opts = {
servers = {
terraformls = {},
},
},
},
{
'jose-elias-alvarez/null-ls.nvim',
optional = true,
opts = function(_, opts)
if type(opts.sources) == 'table' then
local builtins = require('null-ls.builtins')
table.insert(opts.sources, builtins.formatting.terraform_fmt)
table.insert(opts.sources, builtins.diagnostics.terraform_validate)
end
end,
},
}

View File

@ -0,0 +1,125 @@
-- This is part of LazyVim's code, with my modifications.
-- See: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/plugins/extras/lang/typescript.lua
return {
-- add typescript to treesitter
{
'nvim-treesitter/nvim-treesitter',
opts = function(_, opts)
if type(opts.ensure_installed) == 'table' then
vim.list_extend(opts.ensure_installed, { 'typescript', 'tsx' })
end
end,
},
-- correctly setup lspconfig
{
'neovim/nvim-lspconfig',
dependencies = { 'jose-elias-alvarez/typescript.nvim' },
opts = {
-- make sure mason installs the server
servers = {
---@type lspconfig.options.tsserver
tsserver = {
-- stylua: ignore
keys = {
{ '<leader>co', '<cmd>TypescriptOrganizeImports<CR>', desc = 'Organize Imports' },
{ '<leader>cR', '<cmd>TypescriptRenameFile<CR>', desc = 'Rename File' },
},
settings = {
---@diagnostic disable: missing-fields
typescript = {
format = {
indentSize = vim.o.shiftwidth,
convertTabsToSpaces = vim.o.expandtab,
tabSize = vim.o.tabstop,
},
},
javascript = {
format = {
indentSize = vim.o.shiftwidth,
convertTabsToSpaces = vim.o.expandtab,
tabSize = vim.o.tabstop,
},
},
completions = {
completeFunctionCalls = true,
},
},
},
},
setup = {
tsserver = function(_, opts)
require('typescript').setup({ server = opts })
return true
end,
},
},
},
{
'jose-elias-alvarez/null-ls.nvim',
optional = true,
opts = function(_, opts)
table.insert(
opts.sources,
require('typescript.extensions.null-ls.code-actions')
)
end,
},
{
'mfussenegger/nvim-dap',
optional = true,
dependencies = {
{
'williamboman/mason.nvim',
opts = function(_, opts)
opts.ensure_installed = opts.ensure_installed or {}
table.insert(opts.ensure_installed, 'js-debug-adapter')
end,
},
},
opts = function()
local dap = require('dap')
if not dap.adapters['pwa-node'] then
require('dap').adapters['pwa-node'] = {
type = 'server',
host = 'localhost',
port = '${port}',
executable = {
command = 'node',
-- 💀 Make sure to update this path to point to your installation
args = {
require('mason-registry')
.get_package('js-debug-adapter')
:get_install_path() .. '/js-debug/src/dapDebugServer.js',
'${port}',
},
},
}
end
for _, language in ipairs({ 'typescript', 'javascript' }) do
if not dap.configurations[language] then
dap.configurations[language] = {
{
type = 'pwa-node',
request = 'launch',
name = 'Launch file',
program = '${file}',
cwd = '${workspaceFolder}',
},
{
type = 'pwa-node',
request = 'attach',
name = 'Attach',
processId = require('dap.utils').pick_process,
cwd = '${workspaceFolder}',
},
}
end
end
end,
},
}

View File

@ -0,0 +1,63 @@
-- This is part of LazyVim's code, with my modifications.
-- See: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/plugins/extras/lang/yaml.lua
return {
{
'nvim-treesitter/nvim-treesitter',
opts = function(_, opts)
if type(opts.ensure_installed) == 'table' then
vim.list_extend(opts.ensure_installed, { 'yaml' })
end
end,
},
{
'neovim/nvim-lspconfig',
dependencies = { 'b0o/SchemaStore.nvim', version = false },
opts = {
servers = {
yamlls = {
-- Have to add this for yamlls to understand that we support line folding
capabilities = {
textDocument = {
foldingRange = {
dynamicRegistration = false,
lineFoldingOnly = true,
},
},
},
-- Lazy-load schemastore when needed
on_new_config = function(new_config)
new_config.settings.yaml.schemas = vim.tbl_extend(
'force',
require('schemastore').yaml.schemas(),
new_config.settings.yaml.schemas or {}
)
end,
settings = {
redhat = { telemetry = { enabled = false } },
yaml = {
completion = true,
hover = true,
validate = true,
format = {
enable = true,
},
schemaStore = {
-- Must disable built-in schemaStore support to use
-- schemas from SchemaStore.nvim plugin
enable = false,
-- Avoid TypeError: Cannot read properties of undefined (reading 'length')
url = '',
},
schemas = {
kubernetes = { 'k8s**.yaml', 'kube*/*.yaml' },
},
},
},
},
},
},
},
}

View File

@ -0,0 +1,50 @@
return {
{
'neovim/nvim-lspconfig',
opts = {
servers = {
ruff_lsp = {},
},
setup = {
ruff_lsp = function(_, opts)
local root_files = {
'.python-version',
'pyproject.toml',
'ruff.toml',
}
local util = require('lspconfig.util')
opts.root_dir = util.root_pattern(unpack(root_files))
or util.find_git_ancestor()
require('plex.lib.utils').on_attach(function(client, _)
if client.name == 'ruff_lsp' then
client.server_capabilities.hoverProvider = false
end
end)
end,
},
},
},
{
'williamboman/mason.nvim',
opts = function(_, opts)
vim.list_extend(opts.ensure_installed, {
'ruff',
'ruff-lsp',
})
end,
},
{
'jose-elias-alvarez/null-ls.nvim',
optional = true,
opts = function(_, opts)
if type(opts.sources) == 'table' then
local nls = require('null-ls')
table.insert(opts.sources, nls.builtins.formatting.ruff)
end
end,
},
}

View File

@ -0,0 +1,33 @@
return {
{
'hrsh7th/nvim-gtd',
event = { 'BufReadPre', 'BufNewFile' },
dependencies = 'neovim/nvim-lspconfig',
-- stylua: ignore
keys = {
{
'gf',
function() require('gtd').exec({ command = 'split' }) end,
desc = 'Go to definition or file',
},
},
---@type gtd.kit.App.Config.Schema
opts = {
sources = {
{ name = 'findup' },
{
name = 'walk',
root_markers = {
'.git',
'.neoconf.json',
'Makefile',
'package.json',
'tsconfig.json',
},
ignore_patterns = { '/node_modules', '/.git' },
},
{ name = 'lsp' },
},
},
},
}

View File

@ -0,0 +1,22 @@
return {
-- Not needed anymore with nvim-0.10.0
{
'lvimuser/lsp-inlayhints.nvim',
branch = 'anticonceal',
event = 'LspAttach',
opts = {},
config = function(_, opts)
require('lsp-inlayhints').setup(opts)
vim.api.nvim_create_autocmd('LspAttach', {
group = vim.api.nvim_create_augroup('LspAttach_inlayhints', {}),
callback = function(args)
if not (args.data and args.data.client_id) then
return
end
local client = vim.lsp.get_client_by_id(args.data.client_id)
require('lsp-inlayhints').on_attach(client, args.buf)
end,
})
end,
},
}

View File

@ -0,0 +1,20 @@
return {
{
'kosayoda/nvim-lightbulb',
event = { 'BufReadPre', 'BufNewFile' },
opts = {
ignore = {
clients = { 'null-ls' },
},
},
config = function(_, opts)
require('nvim-lightbulb').setup(opts)
vim.api.nvim_create_autocmd('CursorHold', {
group = vim.api.nvim_create_augroup('plex_lightbulb', {}),
callback = function()
require('nvim-lightbulb').update_lightbulb()
end,
})
end,
},
}

View File

@ -0,0 +1,62 @@
return {
{
'jose-elias-alvarez/null-ls.nvim',
event = { 'BufReadPre', 'BufNewFile' },
dependencies = { 'williamboman/mason.nvim' },
opts = function(_, opts)
-- https://github.com/jose-elias-alvarez/null-ls.nvim/blob/main/doc/BUILTINS.md
local builtins = require('null-ls').builtins
local sources = {
builtins.formatting.stylua,
builtins.formatting.shfmt,
}
for _, source in ipairs(sources) do
table.insert(opts.sources, source)
end
opts.fallback_severity = vim.diagnostic.severity.INFO
opts.should_attach = function(bufnr)
return not vim.api.nvim_buf_get_name(bufnr):match('^[a-z]+://')
end
opts.root_dir = require('null-ls.utils').root_pattern(
'.git',
'_darcs',
'.hg',
'.bzr',
'.svn',
'.null-ls-root',
'.neoconf.json',
'.python-version',
'Makefile'
)
end,
},
-- You can add your own sources. Here's an example:
-- {
-- 'jose-elias-alvarez/null-ls.nvim',
-- optional = true,
-- opts = function(_, opts)
-- local builtins = require('null-ls.builtins')
-- local sources = {
-- builtins.formatting.black,
-- builtins.formatting.fixjson,
-- builtins.formatting.golines,
-- builtins.formatting.markdownlint,
-- builtins.formatting.shellharden,
-- builtins.formatting.sql_formatter,
-- builtins.formatting.taplo,
-- builtins.diagnostics.markdownlint,
-- builtins.diagnostics.mypy,
-- builtins.diagnostics.vint,
-- builtins.diagnostics.yamllint,
-- builtins.code_actions.shellcheck,
-- }
-- opts.sources = opts.sources or {}
-- for _, source in ipairs(sources) do
-- table.insert(opts.sources, source)
-- end
-- end,
-- },
}

View File

@ -0,0 +1,33 @@
return {
{
'neovim/nvim-lspconfig',
opts = {
setup = {
yamlls = function(_, _)
local yamlls_opts = require('yaml-companion').setup(
require('plex.lib.utils').opts('yaml-companion.nvim')
)
require('lspconfig')['yamlls'].setup(yamlls_opts)
return true
end,
},
},
},
{
'someone-stole-my-name/yaml-companion.nvim',
dependencies = {
'neovim/nvim-lspconfig',
'nvim-telescope/telescope.nvim',
},
keys = {
-- stylua: ignore
{ '<localleader>y', '<cmd>Telescope yaml_schema<CR>', desc = 'YAML Schema' },
},
opts = {},
config = function(_, _)
require('telescope').load_extension('yaml_schema')
end,
},
}

View File

@ -0,0 +1,44 @@
return {
{
'vimwiki/vimwiki',
cmd = { 'VimwikiIndex', 'VimwikiUISelect' },
keys = {
{ '<Leader>W', '<cmd>VimwikiIndex<CR>', { noremap = true } },
},
init = function()
vim.g.vimwiki_global_ext = 0
vim.g.vimwiki_use_calendar = 1
vim.g.vimwiki_hl_headers = 1
vim.g.vimwiki_hl_cb_checked = 1
vim.g.vimwiki_autowriteall = 0
vim.g.vimwiki_listsym_rejected = ''
vim.g.vimwiki_listsyms = '✗○◐●✓'
end,
config = function()
vim.g.vimwiki_key_mappings = {
all_maps = 1,
global = 1,
headers = 1,
text_objs = 1,
table_format = 1,
table_mappings = 1,
lists = 1,
links = 1,
html = 1,
mouse = 0,
}
vim.g.vimwiki_list = {
{
diary_header = 'Diary',
diary_link_fmt = '%Y-%m/%d',
auto_toc = 1,
path = '~/docs/wiki/',
syntax = 'markdown',
ext = '.md',
},
{ path = '~/docs/books/', syntax = 'markdown', ext = '.md' },
{ path = '~/notes/', syntax = 'markdown', ext = '.md' },
}
end,
},
}

View File

@ -0,0 +1,10 @@
return {
{
'Wansmer/treesj',
cmd = { 'TSJJoin', 'TSJSplit' },
keys = {
{ 'sj', '<cmd>TSJJoin<CR>' },
{ 'sk', '<cmd>TSJSplit<CR>' },
},
},
}

View File

@ -0,0 +1,28 @@
return {
{
'utilyre/barbecue.nvim',
dependencies = { 'SmiteshP/nvim-navic', 'nvim-tree/nvim-web-devicons' },
keys = {
{
'<Leader>ub',
function()
local off = vim.b['barbecue_entries'] == nil
require('barbecue.ui').toggle(off and true or nil)
end,
desc = 'Breadcrumbs toggle',
},
},
opts = function()
local kind_icons = vim.tbl_map(function(icon)
return vim.trim(icon)
end, require('plex.config').icons.kinds)
return {
attach_navic = false,
show_dirname = false,
show_modified = true,
kinds = kind_icons,
symbols = { separator = '' },
}
end,
},
}

View File

@ -0,0 +1,45 @@
return {
{
'akinsho/bufferline.nvim',
event = 'VeryLazy',
opts = {
options = {
mode = 'tabs',
separator_style = 'slant',
show_close_icon = false,
show_buffer_close_icons = false,
diagnostics = false,
always_show_bufferline = true,
diagnostics_indicator = function(_, _, diag)
local icons = require('plex.config').icons.diagnostics
local ret = (diag.error and icons.Error .. diag.error .. ' ' or '')
.. (diag.warning and icons.Warn .. diag.warning or '')
return vim.trim(ret)
end,
custom_areas = {
right = function()
local project_root = require('plex.lib.badge').project()
local result = {}
local part = {}
part.text = '%#BufferLineTab# ' .. project_root
table.insert(result, part)
-- Session indicator
if vim.v['this_session'] ~= '' then
table.insert(result, { text = '%#BufferLineTab#  ' })
end
return result
end,
},
offsets = {
{
filetype = 'neo-tree',
text = 'Neo-tree',
highlight = 'Directory',
text_align = 'center',
},
},
},
},
},
}

View File

@ -0,0 +1,47 @@
return {
{
'itchyny/vim-cursorword',
event = 'FileType',
init = function()
vim.g.cursorword = 0
end,
config = function()
local augroup = vim.api.nvim_create_augroup('plex_cursorword', {})
vim.api.nvim_create_autocmd('FileType', {
group = augroup,
pattern = {
'conf',
'dosini',
'json',
'markdown',
'nginx',
'text',
'yaml',
},
callback = function()
if vim.wo.diff or vim.wo.previewwindow then
vim.b.cursorword = 0
else
vim.b.cursorword = 1
end
end,
})
vim.api.nvim_create_autocmd('InsertEnter', {
group = augroup,
callback = function()
if vim.b['cursorword'] == 1 then
vim.b['cursorword'] = 0
end
end,
})
vim.api.nvim_create_autocmd('InsertLeave', {
group = augroup,
callback = function()
if vim.b['cursorword'] == 0 then
vim.b['cursorword'] = 1
end
end,
})
end,
},
}

View File

@ -0,0 +1,21 @@
return {
{
'ghillb/cybu.nvim',
dependencies = { 'nvim-tree/nvim-web-devicons', 'nvim-lua/plenary.nvim' },
keys = {
{ '[b', '<Plug>(CybuPrev)' },
{ ']b', '<Plug>(CybuNext)' },
{ '<C-S-Tab>', '<Plug>(CybuLastusedPrev)' },
{ '<C-Tab>', '<Plug>(CybuLastusedNext)' },
},
config = true,
},
{
'echasnovski/mini.bracketed',
optional = true,
opts = function(_, opts)
opts.buffer = { suffix = '' }
return opts
end,
},
}

View File

@ -0,0 +1,9 @@
return {
{
'Bekaboo/deadcolumn.nvim',
event = { 'BufReadPre', 'BufNewFile' },
opts = {
scope = 'visible',
},
},
}

View File

@ -0,0 +1,51 @@
return {
{
'rmagatti/goto-preview',
dependencies = 'nvim-telescope/telescope.nvim',
keys = {
{
'gpd',
function()
require('goto-preview').goto_preview_definition({})
end,
{ noremap = true },
},
{
'gpi',
function()
require('goto-preview').goto_preview_implementation({})
end,
{ noremap = true },
},
{
'gpc',
function()
require('goto-preview').close_all_win()
end,
{ noremap = true },
},
{
'gpr',
function()
require('goto-preview').goto_preview_references({})
end,
{ noremap = true },
},
},
opts = {
width = 78,
height = 15,
default_mappings = false,
opacity = 10,
post_open_hook = function(_, win)
vim.api.nvim_win_set_config(win, {
border = { '', '', '', '', '', '', '', '' },
})
local scope = { scope = 'local', win = win }
vim.api.nvim_set_option_value('spell', false, scope)
vim.api.nvim_set_option_value('signcolumn', 'no', scope)
vim.keymap.set('n', '<Esc>', '<cmd>quit<CR>')
end,
},
},
}

View File

@ -0,0 +1,7 @@
return {
{
'b0o/incline.nvim',
event = 'FileType',
opts = {},
},
}

View File

@ -0,0 +1,19 @@
return {
{
'echasnovski/mini.map',
keys = {
{ '<Leader>mn', '<cmd>lua MiniMap.toggle()<CR>', desc = 'Mini map' },
},
opts = function()
local minimap = require('mini.map')
return {
integrations = {
minimap.gen_integration.diagnostic(),
minimap.gen_integration.builtin_search(),
minimap.gen_integration.gitsigns(),
},
window = { winblend = 50 },
}
end,
},
}

View File

@ -0,0 +1,24 @@
return {
{
'luukvbaal/statuscol.nvim',
event = 'BufReadPost',
init = function()
vim.opt_global.foldcolumn = '1'
end,
opts = function()
local builtin = require('statuscol.builtin')
return {
setopt = true,
relculright = true,
segments = {
{
sign = { name = { '.*' }, maxwidth = 2, colwidth = 1, auto = true },
click = 'v:lua.ScSa',
},
{ text = { builtin.lnumfunc }, click = 'v:lua.ScLa' },
{ text = { builtin.foldfunc }, click = 'v:lua.ScFa' },
},
}
end,
},
}

246
lua/plex/plugins/git.lua Normal file
View File

@ -0,0 +1,246 @@
-- Plugins: Git
-- https://github.com/rafi/vim-config
return {
-----------------------------------------------------------------------------
{
'lewis6991/gitsigns.nvim',
event = { 'BufReadPre', 'BufNewFile' },
-- See: https://github.com/lewis6991/gitsigns.nvim#usage
-- stylua: ignore
opts = {
signcolumn = true, -- Toggle with `:Gitsigns toggle_signs`
numhl = false, -- Toggle with `:Gitsigns toggle_numhl`
linehl = false, -- Toggle with `:Gitsigns toggle_linehl`
word_diff = false, -- Toggle with `:Gitsigns toggle_word_diff`
current_line_blame = false, -- Toggle with `:Gitsigns toggle_current_line_blame`
attach_to_untracked = true,
watch_gitdir = {
interval = 1000,
follow_files = true,
},
preview_config = {
border = 'rounded',
},
on_attach = function(bufnr)
local gs = package.loaded.gitsigns
local function map(mode, l, r, opts)
opts = opts or {}
opts.buffer = bufnr
vim.keymap.set(mode, l, r, opts)
end
-- Navigation
---@return string
map('n', ']g', function()
if vim.wo.diff then return ']c' end
vim.schedule(function() gs.next_hunk() end)
return '<Ignore>'
end, { expr = true, desc = 'Git hunk forward' })
map('n', '[g', function()
if vim.wo.diff then return '[c' end
vim.schedule(function() gs.prev_hunk() end)
return '<Ignore>'
end, { expr = true, desc = 'Git hunk last' })
-- Actions
--
map('n', '<leader>hs', gs.stage_hunk, { silent = true, desc = 'Stage hunk' })
map('n', '<leader>hr', gs.reset_hunk, { silent = true, desc = 'Reset hunk' })
map('x', '<leader>hs', function() gs.stage_hunk({vim.fn.line('.'), vim.fn.line('v')}) end)
map('x', '<leader>hr', function() gs.reset_hunk({vim.fn.line('.'), vim.fn.line('v')}) end)
map('n', '<leader>hS', gs.stage_buffer, { silent = true, desc = 'Stage buffer' })
map('n', '<leader>hu', gs.undo_stage_hunk, { desc = 'Undo staged hunk' })
map('n', '<leader>hR', gs.reset_buffer, { desc = 'Reset buffer' })
map('n', 'gs', gs.preview_hunk, { desc = 'Preview hunk' })
map('n', '<leader>hp', gs.preview_hunk_inline, { desc = 'Preview hunk inline' })
map('n', '<leader>hb', function() gs.blame_line({ full=true }) end, { desc = 'Show blame commit' })
map('n', '<leader>tb', gs.toggle_current_line_blame, { desc = 'Toggle Git line blame' })
-- map('n', '<leader>tw', gs.toggle_word_diff)
map('n', '<leader>hd', gs.diffthis, { desc = 'Diff against the index' })
map('n', '<leader>hD', function() gs.diffthis('~') end, { desc = 'Diff against the last commit' })
map('n', '<leader>td', gs.toggle_deleted, { desc = 'Toggle Git deleted' })
map('n', '<leader>hl', function()
if vim.bo.filetype ~= 'qf' then
require('gitsigns').setqflist(0, { use_location_list = true })
end
end, { desc = 'Send to location list' })
-- Text object
map({'o', 'x'}, 'ih', ':<C-U>Gitsigns select_hunk<CR>', { silent = true, desc = 'Select hunk'})
end,
},
},
-----------------------------------------------------------------------------
{
'sindrets/diffview.nvim',
cmd = { 'DiffviewOpen', 'DiffviewFileHistory' },
keys = {
{ '<Leader>gd', '<cmd>DiffviewFileHistory<CR>', desc = 'Diff File' },
{ '<Leader>gv', '<cmd>DiffviewOpen<CR>', desc = 'Diff View' },
},
opts = function()
local actions = require('diffview.actions')
vim.api.nvim_create_autocmd({ 'WinEnter', 'BufEnter' }, {
group = vim.api.nvim_create_augroup('rafi_diffview', {}),
pattern = 'diffview:///panels/*',
callback = function()
vim.opt_local.cursorline = true
vim.opt_local.winhighlight = 'CursorLine:WildMenu'
end,
})
return {
enhanced_diff_hl = true, -- See ':h diffview-config-enhanced_diff_hl'
keymaps = {
view = {
{ 'n', 'q', '<cmd>DiffviewClose<CR>' },
{ 'n', '<Tab>', actions.select_next_entry },
{ 'n', '<S-Tab>', actions.select_prev_entry },
{ 'n', '<LocalLeader>a', actions.focus_files },
{ 'n', '<LocalLeader>e', actions.toggle_files },
},
file_panel = {
{ 'n', 'q', '<cmd>DiffviewClose<CR>' },
{ 'n', 'h', actions.prev_entry },
{ 'n', 'o', actions.focus_entry },
{ 'n', 'gf', actions.goto_file },
{ 'n', 'sg', actions.goto_file_split },
{ 'n', 'st', actions.goto_file_tab },
{ 'n', '<C-r>', actions.refresh_files },
{ 'n', ';e', actions.toggle_files },
},
file_history_panel = {
{ 'n', 'q', '<cmd>DiffviewClose<CR>' },
{ 'n', 'o', actions.focus_entry },
{ 'n', 'O', actions.options },
},
},
}
end,
},
-----------------------------------------------------------------------------
{
'NeogitOrg/neogit',
dependencies = {
'sindrets/diffview.nvim',
'nvim-telescope/telescope.nvim'
},
cmd = 'Neogit',
keys = {
{ '<Leader>mg', '<cmd>Neogit<CR>', desc = 'Neogit' },
},
-- See: https://github.com/TimUntersberger/neogit#configuration
opts = {
disable_signs = false,
disable_context_highlighting = false,
disable_commit_confirmation = false,
signs = {
section = { '>', 'v' },
item = { '>', 'v' },
hunk = { '', '' },
},
integrations = {
diffview = true,
},
},
},
-----------------------------------------------------------------------------
{
'FabijanZulj/blame.nvim',
cmd = 'ToggleBlame',
-- stylua: ignore
keys = {
{ '<leader>gb', '<cmd>ToggleBlame virtual<CR>', desc = 'Git blame' },
{ '<leader>gB', '<cmd>ToggleBlame window<CR>', desc = 'Git blame (window)' },
},
opts = {
date_format = '%Y-%m-%d %H:%M',
},
},
-----------------------------------------------------------------------------
{
'rhysd/git-messenger.vim',
cmd = 'GitMessenger',
keys = {
{ '<Leader>gm', '<Plug>(git-messenger)', desc = 'Git messenger'}
},
init = function()
vim.g.git_messenger_include_diff = 'current'
vim.g.git_messenger_no_default_mappings = false
vim.g.git_messenger_floating_win_opts = { border = 'rounded' }
end,
},
-----------------------------------------------------------------------------
{
'ruifm/gitlinker.nvim',
keys = {
{
'<leader>go',
function()
require('gitlinker').get_buf_range_url('n')
end,
silent = true,
desc = 'Git open in browser',
},
{
'<leader>go',
function()
require('gitlinker').get_buf_range_url('v')
end,
mode = 'x',
desc = 'Git open in browser',
},
},
opts = {
mappings = nil,
opts = {
add_current_line_on_normal_mode = true,
print_url = false,
action_callback = function(...)
return require('gitlinker.actions').open_in_browser(...)
end,
},
},
},
-----------------------------------------------------------------------------
{
'rhysd/committia.vim',
event = 'BufReadPre COMMIT_EDITMSG',
init = function()
-- See: https://github.com/rhysd/committia.vim#variables
vim.g.committia_min_window_width = 30
vim.g.committia_edit_window_width = 75
end,
config = function()
vim.g.committia_hooks = {
edit_open = function()
vim.cmd.resize(10)
local opts = {
buffer = vim.api.nvim_get_current_buf(),
silent = true,
}
local function imap(lhs, rhs)
vim.keymap.set('i', lhs, rhs, opts)
end
imap('<C-d>', '<Plug>(committia-scroll-diff-down-half)')
imap('<C-u>', '<Plug>(committia-scroll-diff-up-half)')
imap('<C-f>', '<Plug>(committia-scroll-diff-down-page)')
imap('<C-b>', '<Plug>(committia-scroll-diff-up-page)')
imap('<C-j>', '<Plug>(committia-scroll-diff-down)')
imap('<C-k>', '<Plug>(committia-scroll-diff-up)')
end,
}
end,
},
}

View File

@ -0,0 +1,166 @@
-- LSP: Auto-format on save
-- https://github.com/plex/vim-config
-- This is part of LazyVim's code, with my modifications.
-- See: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/plugins/lsp/format.lua
local M = {}
---@type PluginLspOpts
M.opts = nil
function M.enabled()
return M.opts.autoformat
end
function M.toggle()
if vim.b.autoformat == false then
vim.b.autoformat = nil
M.opts.autoformat = true
else
M.opts.autoformat = not M.opts.autoformat
end
local msg = M.opts.autoformat and 'Enabled' or 'Disabled'
vim.notify(
msg .. ' format on save',
vim.log.levels.INFO,
{ title = 'Format' }
)
end
---@param opts? {force?:boolean}
function M.format(opts)
local buf = vim.api.nvim_get_current_buf()
if vim.b.autoformat == false and not (opts and opts.force) then
return
end
local formatters = M.get_formatters(buf)
local client_ids = vim.tbl_map(function(client)
return client.id
end, formatters.active)
if #client_ids == 0 then
return
end
if M.opts.format_notify then
M.notify(formatters)
end
vim.lsp.buf.format(vim.tbl_deep_extend('force', {
bufnr = buf,
filter = function(client)
return vim.tbl_contains(client_ids, client.id)
end,
}, require('plex.lib.utils').opts('nvim-lspconfig').format or {}))
end
---@param formatters LazyVimFormatters
function M.notify(formatters)
local lines = { '# Active:' }
for _, client in ipairs(formatters.active) do
local line = '- **' .. client.name .. '**'
if client.name == 'null-ls' then
line = line
.. ' ('
.. table.concat(
vim.tbl_map(function(f)
return '`' .. f.name .. '`'
end, formatters.null_ls),
', '
)
.. ')'
end
table.insert(lines, line)
end
if #formatters.available > 0 then
table.insert(lines, '')
table.insert(lines, '# Disabled:')
for _, client in ipairs(formatters.available) do
table.insert(lines, '- **' .. client.name .. '**')
end
end
vim.notify(table.concat(lines, '\n'), vim.log.levels.INFO, {
title = 'Formatting',
on_open = function(win)
local scope = { scope = 'local', win = win }
vim.api.nvim_set_option_value('conceallevel', 3, scope)
vim.api.nvim_set_option_value('spell', false, scope)
local buf = vim.api.nvim_win_get_buf(win)
vim.treesitter.start(buf, 'markdown')
end,
})
end
-- Gets all lsp clients that support formatting.
-- When a null-ls formatter is available for the current filetype,
-- only null-ls formatters are returned.
function M.get_formatters(bufnr)
local ft = vim.bo[bufnr].filetype
-- check if we have any null-ls formatters for the current filetype
local null_ls = package.loaded['null-ls']
and require('null-ls.sources').get_available(ft, 'NULL_LS_FORMATTING')
or {}
---@class LazyVimFormatters
local ret = {
---@type lsp.Client[]
active = {},
---@type lsp.Client[]
available = {},
null_ls = null_ls,
}
local clients
if vim.lsp.get_clients ~= nil then
clients = vim.lsp.get_clients({ bufnr = bufnr })
else
---@diagnostic disable-next-line: deprecated
clients = vim.lsp.get_active_clients({ bufnr = bufnr })
end
for _, client in ipairs(clients) do
if M.supports_format(client) then
if (#null_ls > 0 and client.name == 'null-ls') or #null_ls == 0 then
table.insert(ret.active, client)
else
table.insert(ret.available, client)
end
end
end
return ret
end
-- Gets all lsp clients that support formatting
-- and have not disabled it in their client config
---@param client lsp.Client
function M.supports_format(client)
if
client.config
and client.config.capabilities
and client.config.capabilities['documentFormattingProvider'] == false
then
return false
end
return client.supports_method('textDocument/formatting')
or client.supports_method('textDocument/rangeFormatting')
end
---@param opts PluginLspOpts
function M.setup(opts)
M.opts = opts
vim.api.nvim_create_autocmd('BufWritePre', {
group = vim.api.nvim_create_augroup('plex_format', {}),
callback = function()
if M.opts.autoformat then
M.format()
end
end,
})
end
return M

View File

@ -0,0 +1,47 @@
-- LSP: Highlights
-- https://github.com/plex/vim-config
-- This is part of LunarVim's code, with my modifications.
-- Reference: https://github.com/LunarVim/LunarVim
local M = {}
---@param client lsp.Client
---@param bufnr integer
function M.on_attach(client, bufnr)
if require('plex.lib.utils').has('vim-illuminate') then
-- Skipped setup for document_highlight, illuminate is installed.
return
end
local status_ok, highlight_supported = pcall(function()
return client.supports_method('textDocument/documentHighlight')
end)
if not status_ok or not highlight_supported then
return
end
local group_name = 'lsp_document_highlight'
local ok, hl_autocmds = pcall(vim.api.nvim_get_autocmds, {
group = group_name,
buffer = bufnr,
event = 'CursorHold',
})
if ok and #hl_autocmds > 0 then
return
end
vim.api.nvim_create_augroup(group_name, { clear = false })
vim.api.nvim_create_autocmd('CursorHold', {
group = group_name,
buffer = bufnr,
callback = vim.lsp.buf.document_highlight,
})
vim.api.nvim_create_autocmd('CursorMoved', {
group = group_name,
buffer = bufnr,
callback = vim.lsp.buf.clear_references,
})
end
return M

View File

@ -0,0 +1,326 @@
-- LSP: Plugins
-- https://github.com/plex/vim-config
-- This is part of LazyVim's code, with my modifications.
-- See: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/plugins/lsp/init.lua
return {
-----------------------------------------------------------------------------
{
'neovim/nvim-lspconfig',
event = { 'BufReadPre', 'BufNewFile' },
dependencies = {
{ 'folke/neoconf.nvim', cmd = 'Neoconf', config = false, dependencies = { 'nvim-lspconfig' } },
{ 'folke/neodev.nvim', opts = {} },
'williamboman/mason.nvim',
'williamboman/mason-lspconfig.nvim',
{
'hrsh7th/cmp-nvim-lsp',
cond = function()
return require('plex.lib.utils').has('nvim-cmp')
end,
},
},
---@class PluginLspOpts
opts = {
-- Options for vim.diagnostic.config()
diagnostics = {
signs = true,
underline = true,
update_in_insert = false,
virtual_text = {
spacing = 4,
source = 'if_many',
prefix = '',
},
severity_sort = true,
float = {
show_header = true,
border = 'rounded',
source = 'always',
},
},
-- Enable this to enable the builtin LSP inlay hints on Neovim >= 0.10.0
-- Be aware that you also will need to properly configure your LSP server to
-- provide the inlay hints.
inlay_hints = {
enabled = false,
},
-- Add any global capabilities here
capabilities = {},
-- Automatically format on save
autoformat = false,
-- Options for vim.lsp.buf.format
-- `bufnr` and `filter` is handled by the formatter,
-- but can be also overridden when specified
format = {
formatting_options = nil,
timeout_ms = nil,
},
-- Enable this to show formatters used in a notification
-- Useful for debugging formatter issues
format_notify = false,
-- LSP Server Settings
---@type lspconfig.options
---@diagnostic disable: missing-fields
servers = {
-- jsonls = {},
lua_ls = {
settings = {
Lua = {
workspace = { checkThirdParty = false },
completion = { callSnippet = 'Replace' },
},
},
},
},
-- you can do any additional lsp server setup here
-- return true if you don't want this server to be setup with lspconfig
---@type table<string, fun(server:string, opts:_.lspconfig.options):boolean?>
setup = {
-- example to setup with typescript.nvim
-- tsserver = function(_, opts)
-- require('typescript').setup({ server = opts })
-- return true
-- end,
-- Specify * to use this function as a fallback for any server
-- ['*'] = function(server, opts) end,
},
},
---@param opts PluginLspOpts
config = function(_, opts)
if require('plex.lib.utils').has('neoconf.nvim') then
local plugin = require('lazy.core.config').spec.plugins['neoconf.nvim']
require('neoconf').setup(require('lazy.core.plugin').values(plugin, 'opts', false))
end
-- Setup autoformat
require('plex.plugins.lsp.format').setup(opts)
-- Setup formatting, keymaps and highlights.
local lsp_on_attach = require('plex.lib.utils').on_attach
---@param client lsp.Client
---@param buffer integer
lsp_on_attach(function(client, buffer)
require('plex.plugins.lsp.keymaps').on_attach(client, buffer)
require('plex.plugins.lsp.highlight').on_attach(client, buffer)
if vim.diagnostic.is_disabled() or vim.bo[buffer].buftype ~= '' then
vim.diagnostic.disable(buffer)
return
end
end)
local register_capability = vim.lsp.handlers['client/registerCapability']
---@diagnostic disable-next-line: duplicate-set-field
vim.lsp.handlers['client/registerCapability'] = function(err, res, ctx)
local ret = register_capability(err, res, ctx)
local client_id = ctx.client_id
---@type lsp.Client|nil
local client = vim.lsp.get_client_by_id(client_id)
local buffer = vim.api.nvim_get_current_buf()
if client ~= nil then
require('plex.plugins.lsp.keymaps').on_attach(client, buffer)
end
return ret
end
-- Diagnostics signs and highlights
for type, icon in pairs(require('plex.config').icons.diagnostics) do
local hl = 'DiagnosticSign' .. type
vim.fn.sign_define(hl, { text = icon, texthl = hl, numhl = '' })
end
-- Setup inlay-hints
local inlay_hint = vim.lsp.buf.inlay_hint or vim.lsp.inlay_hint
if opts.inlay_hints.enabled and inlay_hint then
lsp_on_attach(function(client, buffer)
if client.supports_method('textDocument/inlayHint') then
inlay_hint(buffer, true)
end
end)
end
if
type(opts.diagnostics.virtual_text) == 'table'
and opts.diagnostics.virtual_text.prefix == 'icons'
then
opts.diagnostics.virtual_text.prefix = vim.fn.has('nvim-0.10') == 0
and ''
or function(diagnostic)
local icons = require('plex.config').icons.diagnostics
for d, icon in pairs(icons) do
if diagnostic.severity == vim.diagnostic.severity[d:upper()] then
return icon
end
end
end
end
vim.diagnostic.config(vim.deepcopy(opts.diagnostics))
-- Initialize LSP servers and ensure Mason packages
-- Setup base config for all servers.
local servers = opts.servers
local has_cmp, cmp_nvim_lsp = pcall(require, 'cmp_nvim_lsp')
local capabilities = vim.tbl_deep_extend(
'force',
{},
vim.lsp.protocol.make_client_capabilities(),
has_cmp and cmp_nvim_lsp.default_capabilities() or {},
opts.capabilities or {}
)
-- Combine base config for each server and merge user-defined settings.
-- These can be overridden locally by lua/lsp/<server_name>.lua
---@param server_name string
local function make_config(server_name)
local server_opts = vim.tbl_deep_extend('force', {
capabilities = vim.deepcopy(capabilities),
}, servers[server_name] or {})
if opts.setup[server_name] then
if opts.setup[server_name](server_name, server_opts) then
return
end
elseif opts.setup['*'] then
if opts.setup['*'](server_name, server_opts) then
return
end
end
local exists, module = pcall(require, 'lsp.' .. server_name)
if exists and module ~= nil then
local user_config = module.config(server_opts) or {}
server_opts = vim.tbl_deep_extend('force', server_opts, user_config)
end
require('lspconfig')[server_name].setup(server_opts)
end
-- Get all the servers that are available thourgh mason-lspconfig
local have_mason, mlsp = pcall(require, 'mason-lspconfig')
local all_mslp_servers = {}
if have_mason then
all_mslp_servers = vim.tbl_keys(
require('mason-lspconfig.mappings.server').lspconfig_to_package
)
end
local ensure_installed = {} ---@type string[]
for server, server_opts in pairs(servers) do
if server_opts then
server_opts = server_opts == true and {} or server_opts
-- run manual setup if mason=false or if this is a server that cannot
-- be installed with mason-lspconfig
if
server_opts.mason == false
or not vim.tbl_contains(all_mslp_servers, server)
then
make_config(server)
else
ensure_installed[#ensure_installed + 1] = server
end
end
end
if have_mason then
mlsp.setup({
ensure_installed = ensure_installed,
handlers = { make_config },
})
end
-- Enable rounded borders in :LspInfo window.
require('lspconfig.ui.windows').default_options.border = 'rounded'
end,
},
-----------------------------------------------------------------------------
{
'williamboman/mason.nvim',
cmd = 'Mason',
build = ':MasonUpdate',
keys = { { '<leader>mm', '<cmd>Mason<cr>', desc = 'Mason' } },
opts = {
ensure_installed = {},
ui = {
border = 'rounded',
},
},
---@param opts MasonSettings | {ensure_installed: string[]}
config = function(_, opts)
require('mason').setup(opts)
local mr = require('mason-registry')
local function ensure_installed()
for _, tool in ipairs(opts.ensure_installed) do
local p = mr.get_package(tool)
if not p:is_installed() then
p:install()
end
end
end
if mr.refresh then
mr.refresh(ensure_installed)
else
ensure_installed()
end
end,
},
-----------------------------------------------------------------------------
{
'mhartington/formatter.nvim',
event = { 'BufReadPre', 'BufNewFile' },
dependencies = { 'williamboman/mason.nvim', 'neovim/nvim-lspconfig' },
opts = function(_, opts)
opts = opts or {}
local defaults = {
logging = true,
log_level = vim.log.levels.WARN,
filetype = {
lua = { require('formatter.filetypes.lua').stylua },
},
}
opts = vim.tbl_extend('keep', opts, defaults)
return opts
end,
config = true,
},
-----------------------------------------------------------------------------
{
'dnlhc/glance.nvim',
cmd = 'Glance',
keys = {
{ 'gpd', '<cmd>Glance definitions<CR>' },
{ 'gpr', '<cmd>Glance references<CR>' },
{ 'gpy', '<cmd>Glance type_definitions<CR>' },
{ 'gpi', '<cmd>Glance implementations<CR>' },
},
opts = function()
local actions = require('glance').actions
return {
folds = {
fold_closed = '󰅂', -- 󰅂 
fold_open = '󰅀', -- 󰅀 
folded = true,
},
mappings = {
list = {
['<C-u>'] = actions.preview_scroll_win(5),
['<C-d>'] = actions.preview_scroll_win(-5),
['sg'] = actions.jump_vsplit,
['sv'] = actions.jump_split,
['st'] = actions.jump_tab,
['p'] = actions.enter_win('preview'),
},
preview = {
['q'] = actions.close,
['p'] = actions.enter_win('list'),
},
},
}
end,
},
}

View File

@ -0,0 +1,178 @@
-- LSP: Key-maps
-- https://github.com/plex/vim-config
local M = {}
---@type PluginLspKeys
M._keys = nil
---@return (LazyKeys|{has?:string})[]
function M.get()
if M._keys then
return M._keys
end
local format = function()
require('plex.plugins.lsp.format').format({ force = true })
end
---@class PluginLspKeys
-- stylua: ignore
M._keys = {
{ 'gD', vim.lsp.buf.declaration, desc = 'Goto Declaration', has = 'declaration' },
{ 'gd', vim.lsp.buf.definition, desc = 'Goto Definition', has = 'definition' },
{ 'gr', vim.lsp.buf.references, desc = 'References', has = 'references' },
{ 'gy', vim.lsp.buf.type_definition, desc = 'Goto Type Definition', has = 'typeDefinition' },
{ 'gi', vim.lsp.buf.implementation, desc = 'Goto Implementation', has = 'implementation' },
{ 'gK', vim.lsp.buf.signature_help, desc = 'Signature Help', has = 'signatureHelp' },
{ '<C-g>h', vim.lsp.buf.signature_help, mode = 'i', desc = 'Signature Help', has = 'signatureHelp' },
{ ']d', M.diagnostic_goto(true), desc = 'Next Diagnostic' },
{ '[d', M.diagnostic_goto(false), desc = 'Prev Diagnostic' },
{ ']e', M.diagnostic_goto(true, 'ERROR'), desc = 'Next Error' },
{ '[e', M.diagnostic_goto(false, 'ERROR'), desc = 'Prev Error' },
{ ',wa', vim.lsp.buf.add_workspace_folder, desc = 'Show Workspace Folders' },
{ ',wr', vim.lsp.buf.remove_workspace_folder, desc = 'Remove Workspace Folder' },
{ ',wl', '<cmd>lua =vim.lsp.buf.list_workspace_folders()<CR>', desc = 'List Workspace Folders' },
{ 'K', function()
-- Show hover documentation or folded lines.
local winid = require('plex.lib.utils').has('nvim-ufo')
and require('ufo').peekFoldedLinesUnderCursor() or nil
if not winid then
vim.lsp.buf.hover()
end
end },
{ '<Leader>ud', function() M.diagnostic_toggle(false) end, desc = 'Disable Diagnostics' },
{ '<Leader>uD', function() M.diagnostic_toggle(true) end, desc = 'Disable All Diagnostics' },
{ '<leader>cl', '<cmd>LspInfo<cr>' },
{ '<leader>cf', format, desc = 'Format Document', has = 'formatting' },
{ '<leader>cf', format, mode = 'x', desc = 'Format Range' }, -- , has = 'rangeFormatting'
{ '<Leader>cr', vim.lsp.buf.rename, desc = 'Rename', has = 'rename' },
{ '<Leader>ce', vim.diagnostic.open_float, desc = 'Open diagnostics' },
{ '<Leader>ca', vim.lsp.buf.code_action, mode = { 'n', 'x' }, has = 'codeAction', desc = 'Code Action' },
{ '<Leader>cA', function()
vim.lsp.buf.code_action({
context = {
only = { 'source' },
diagnostics = {},
},
})
end, desc = 'Source Action', has = 'codeAction' },
}
return M._keys
end
---@param method string
function M.has(buffer, method)
method = method:find('/') and method or 'textDocument/' .. method
local clients
if vim.lsp.get_clients ~= nil then
clients = vim.lsp.get_clients({ bufnr = buffer })
else
---@diagnostic disable-next-line: deprecated
clients = vim.lsp.get_active_clients({ bufnr = buffer })
end
for _, client in ipairs(clients) do
if client.supports_method(method) then
return true
end
end
return false
end
---@param buffer integer
function M.resolve(buffer)
local Keys = require('lazy.core.handler.keys')
local keymaps = {} ---@type table<string,LazyKeys|{has?:string}>
local function add(keymap)
local keys = Keys.parse(keymap)
if keys[2] == false then
keymaps[keys.id] = nil
else
keymaps[keys.id] = keys
end
end
for _, keymap in ipairs(M.get()) do
add(keymap)
end
local opts = require('plex.lib.utils').opts('nvim-lspconfig')
local clients
if vim.lsp.get_clients ~= nil then
clients = vim.lsp.get_clients({ bufnr = buffer })
else
---@diagnostic disable-next-line: deprecated
clients = vim.lsp.get_active_clients({ bufnr = buffer })
end
for _, client in ipairs(clients) do
local maps = opts.servers[client.name] and opts.servers[client.name].keys
or {}
for _, keymap in ipairs(maps) do
add(keymap)
end
end
return keymaps
end
---@param client lsp.Client
---@param buffer integer
function M.on_attach(client, buffer)
local Keys = require('lazy.core.handler.keys')
local keymaps = M.resolve(buffer)
for _, keys in pairs(keymaps) do
if not keys.has or M.has(buffer, keys.has) then
local opts = Keys.opts(keys)
---@diagnostic disable-next-line: no-unknown
opts.has = nil
opts.silent = opts.silent ~= false
opts.buffer = buffer
vim.keymap.set(keys.mode or 'n', keys[1], keys[2], opts)
end
end
end
-- Toggle diagnostics locally (false) or globally (true).
---@param global boolean
function M.diagnostic_toggle(global)
local bufnr, cmd, msg, state
if global then
bufnr = nil
state = vim.g.diagnostics_disabled
vim.g.diagnostics_disabled = not state
else
bufnr = 0
if vim.fn.has('nvim-0.9') == 1 then
state = vim.diagnostic.is_disabled(bufnr)
else
state = vim.b.diagnostics_disabled
vim.b.diagnostics_disabled = not state
end
end
cmd = state and 'enable' or 'disable'
msg = cmd:gsub('^%l', string.upper) .. 'd diagnostics'
if global then
msg = msg .. ' globally'
end
vim.notify(msg)
vim.schedule(function()
vim.diagnostic[cmd](bufnr)
end)
end
---@param next boolean
---@param severity string|nil
---@return fun()
function M.diagnostic_goto(next, severity)
local go = next and vim.diagnostic.goto_next or vim.diagnostic.goto_prev
local severity_int = severity and vim.diagnostic.severity[severity] or nil
return function()
go({ severity = severity_int })
end
end
return M

View File

@ -0,0 +1,285 @@
-- Plugin: Lualine
-- https://github.com/plex/vim-config
return {
-----------------------------------------------------------------------------
{
'nvim-lualine/lualine.nvim',
dependencies = {
'nvim-lua/plenary.nvim',
'nvim-tree/nvim-web-devicons',
},
event = 'VeryLazy',
init = function()
vim.g.qf_disable_statusline = true
end,
opts = function()
local icons = require('plex.config').icons
local get_color = require('plex.lib.color').get_color
local fg = function(...) return { fg = get_color('fg', ...) } end
local function filepath()
local fpath = require('plex.lib.badge').filepath(0, 3, 5)
-- % char must be escaped in statusline.
return fpath:gsub('%%', '%%%%')
end
local function is_file_window()
return vim.bo.buftype == ''
end
local function is_min_width(min)
if vim.o.laststatus > 2 then
return vim.o.columns > min
end
return vim.fn.winwidth(0) > min
end
local active = {
fg = get_color('fg', { 'StatusLine' }, '#000000'),
bg = get_color('bg', { 'StatusLine' }, '#000000'),
}
local inactive = {
fg = get_color('fg', { 'StatusLineNC' }, '#666656'),
bg = get_color('bg', { 'StatusLineNC' }, '#000000'),
}
local theme = {
normal = {
a = active,
b = active,
c = active,
x = active,
y = {
fg = active.fg,
bg = require('plex.lib.color').brightness_modifier(active.bg, -20),
},
z = {
fg = active.fg,
bg = require('plex.lib.color').brightness_modifier(active.bg, 63),
},
},
inactive = {
a = inactive, b = inactive, c = inactive,
x = inactive, y = inactive, z = inactive,
},
}
return {
options = {
theme = theme,
globalstatus = true,
always_divide_middle = false,
disabled_filetypes = { statusline = { 'dashboard', 'alpha' } },
component_separators = '',
section_separators = '',
},
extensions = {
'man',
},
sections = {
lualine_a = {
-- Left edge block.
{
function() return '' end,
color = fg({'Directory'}, '#51afef'),
padding = 0,
},
-- Readonly/zoomed/hash symbol.
{
padding = { left = 1, right = 0 },
cond = is_file_window,
function()
if vim.bo.buftype == '' and vim.bo.readonly then
return icons.status.filename.readonly
elseif vim.t['zoomed'] then
return icons.status.filename.zoomed
end
return '%*#'
end,
},
-- Buffer number.
{ function() return '%n' end, cond = is_file_window, padding = 0 },
-- Modified symbol.
{
function()
return vim.bo.modified and icons.status.filename.modified or ''
end,
cond = is_file_window,
padding = 0,
color = { fg = get_color('bg', {'DiffDelete'}, '#ec5f67') },
},
},
lualine_b = {
{
function() return require('plex.lib.badge').icon() end,
padding = { left = 1, right = 0 },
},
{
filepath,
padding = 1,
color = { fg = '#D7D7BC' },
separator = '',
},
{
'branch',
cond = is_file_window,
icon = '',
padding = 1,
},
{
function() return '#' .. vim.b['toggle_number'] end,
cond = function() return vim.bo.buftype == 'terminal' end,
},
{
function()
if vim.fn.win_gettype() == 'loclist' then
return vim.fn.getloclist(0, { title = 0 }).title
end
return vim.fn.getqflist({ title = 0 }).title
end,
cond = function() return vim.bo.filetype == 'qf' end,
padding = { left = 1, right = 0 },
},
},
lualine_c = {
{
'diagnostics',
padding = { left = 1, right = 0 },
symbols = {
error = icons.status.diagnostics.error,
warn = icons.status.diagnostics.warn,
info = icons.status.diagnostics.info,
hint = icons.status.diagnostics.hint,
},
},
-- Whitespace trails
{
function() return require('plex.lib.badge').trails('') end,
cond = is_file_window,
padding = { left = 1, right = 0 },
color = { fg = get_color('bg', {'Identifier'}, '#b294bb') },
},
-- Start truncating here
{ function() return '%<' end, padding = 0 },
{
'diff',
symbols = {
added = icons.status.git.added,
modified = icons.status.git.modified,
removed = icons.status.git.removed,
},
padding = { left = 1, right = 0 },
cond = function()
return is_file_window() and is_min_width(70)
end,
},
-- {
-- function() return require('nvim-navic').get_location() end,
-- padding = { left = 1, right = 0 },
-- cond = function()
-- return is_min_width(100)
-- and package.loaded['nvim-navic']
-- and require('nvim-navic').is_available()
-- end,
-- },
},
lualine_x = {
-- showcmd
{
function() return require('noice').api.status.command.get() end,
cond = function()
return package.loaded['noice']
and require('noice').api.status.command.has()
end,
color = fg({'Statement'}),
},
-- showmode
{
function() return require('noice').api.status.mode.get() end,
cond = function()
return package.loaded['noice']
and require('noice').api.status.mode.has()
end,
color = fg({'Constant'}),
},
-- search count
{
function() require('noice').api.status.search.get() end,
cond = function()
return package.loaded['noice']
and require('noice').api.status.search.has()
end,
color = { fg = "#ff9e64" },
},
-- lazy.nvim updates
{
require('lazy.status').updates,
cond = require('lazy.status').has_updates,
color = fg({'Comment'}),
separator = { left = '' },
},
},
lualine_y = {
{
function() return require('plex.lib.badge').filemedia('') end,
cond = function() return is_min_width(70) end,
separator = { left = '' },
padding = 1,
},
},
lualine_z = {
{
function()
if is_file_window() then
return '%l/%2c%4p%%'
end
return '%l/%L'
end,
cond = function()
return vim.bo.filetype ~= 'TelescopePrompt'
end,
separator = { left = '' },
padding = 1,
},
},
},
inactive_sections = {
lualine_a = {
{
function() return require('plex.lib.badge').icon() end,
padding = 1,
},
{ filepath, padding = { left = 1, right = 0 } },
{
function()
return vim.bo.modified
and vim.bo.buftype == ''
and icons.status.filename.modified
or ''
end,
cond = is_file_window,
padding = 1,
color = { fg = get_color('bg', {'DiffDelete'}, '#ec5f67') },
},
},
lualine_b = {},
lualine_c = {},
lualine_x = {},
lualine_y = {},
lualine_z = {
{ function() return vim.bo.filetype end, cond = is_file_window },
}
},
}
end,
},
}

View File

@ -0,0 +1,234 @@
-- Plugin: Neo-tree
-- https://github.com/rafi/vim-config
local winwidth = 30
-- Toggle width.
local toggle_width = function()
local max = winwidth * 2
local cur_width = vim.fn.winwidth(0)
local half = math.floor((winwidth + (max - winwidth) / 2) + 0.4)
local new_width = winwidth
if cur_width == winwidth then
new_width = half
elseif cur_width == half then
new_width = max
else
new_width = winwidth
end
vim.cmd(new_width .. ' wincmd |')
end
-- Get current opened directory from state.
---@param state table
---@return string
local function get_current_directory(state)
local node = state.tree:get_node()
local path = node.path
if node.type ~= 'directory' or not node:is_expanded() then
local path_separator = package.config:sub(1, 1)
path = path:match('(.*)' .. path_separator)
end
return path
end
return {
-----------------------------------------------------------------------------
'nvim-neo-tree/neo-tree.nvim',
dependencies = {
'MunifTanjim/nui.nvim',
's1n7ax/nvim-window-picker',
},
cmd = 'Neotree',
keys = {
{
'<LocalLeader>e',
'<cmd>Neotree filesystem left toggle dir=./<CR>',
desc = 'Explorer NeoTree Toggle',
},
},
deactivate = function()
vim.cmd([[Neotree close]])
end,
init = function()
vim.g.neo_tree_remove_legacy_commands = 1
if vim.fn.argc() == 1 then
local stat = vim.loop.fs_stat(tostring(vim.fn.argv(0)))
if stat and stat.type == 'directory' then
require('neo-tree')
end
end
end,
-- See: https://github.com/nvim-neo-tree/neo-tree.nvim
opts = {
close_if_last_window = true,
source_selector = {
winbar = false,
show_scrolled_off_parent_node = true,
padding = { left = 1, right = 0 },
sources = {
{ source = 'filesystem', display_name = '  Files' }, --       
{ source = 'buffers', display_name = '  Buffers' }, --        
{ source = 'git_status', display_name = ' 󰊢 Git' }, -- 󰊢      
},
},
-- event_handlers = {
-- -- Close neo-tree when opening a file.
-- {
-- event = 'file_opened',
-- handler = function()
-- require('neo-tree').close_all()
-- end,
-- },
-- },
default_component_configs = {
indent = {
padding = 0,
},
icon = {
folder_closed = '',
folder_open = '',
folder_empty = '',
folder_empty_open = '',
default = '',
},
modified = {
symbol = '',
},
name = {
trailing_slash = true,
highlight_opened_files = true, -- NeoTreeFileNameOpened
use_git_status_colors = false,
},
git_status = {
symbols = {
-- Change type
added = 'A',
deleted = 'D',
modified = 'M',
renamed = 'R',
-- Status type
untracked = 'U',
ignored = 'I',
unstaged = '',
staged = 'S',
conflict = 'C',
},
},
},
window = {
width = winwidth,
mappings = {
['q'] = 'close_window',
['?'] = 'show_help',
['<Space>'] = 'noop',
['g?'] = 'show_help',
['<2-LeftMouse>'] = 'open',
['<CR>'] = 'open_with_window_picker',
['l'] = 'open_drop',
['h'] = 'change_root_to_node',
['C'] = 'cd',
['z'] = 'close_all_nodes',
['<C-r>'] = 'refresh',
['s'] = 'noop',
['sv'] = 'open_split',
['sg'] = 'open_vsplit',
['st'] = 'open_tabnew',
['c'] = { 'copy', config = { show_path = 'relative' } },
['m'] = { 'move', config = { show_path = 'relative' } },
['a'] = { 'add', nowait = true, config = { show_path = 'relative' } },
['N'] = { 'add_directory', config = { show_path = 'relative' } },
['d'] = 'noop',
['dd'] = 'delete',
['r'] = 'rename',
['y'] = 'copy_to_clipboard',
['x'] = 'cut_to_clipboard',
['P'] = 'paste_from_clipboard',
['<S-Tab>'] = 'prev_source',
['<Tab>'] = 'next_source',
['p'] = {
'toggle_preview',
nowait = true,
config = { use_float = true },
},
['w'] = toggle_width,
},
},
filesystem = {
window = {
mappings = {
['H'] = 'toggle_hidden',
['/'] = 'noop',
['f'] = 'fuzzy_finder',
['F'] = 'filter_on_submit',
['<C-x>'] = 'clear_filter',
['<C-c>'] = 'clear_filter',
['<BS>'] = 'navigate_up',
['.'] = 'set_root',
['[g'] = 'prev_git_modified',
[']g'] = 'next_git_modified',
['gf'] = function(state)
require('telescope.builtin').find_files({
cwd = get_current_directory(state),
})
end,
['gr'] = function(state)
require('telescope.builtin').live_grep({
cwd = get_current_directory(state),
})
end,
},
},
group_empty_dirs = true,
use_libuv_file_watcher = true,
bind_to_cwd = false,
cwd_target = {
sidebar = 'window',
current = 'window',
},
filtered_items = {
visible = false,
show_hidden_count = true,
hide_dotfiles = false,
hide_gitignored = false,
hide_by_name = {
'.git',
'.hg',
'.svc',
'.DS_Store',
'thumbs.db',
'.sass-cache',
'node_modules',
'.pytest_cache',
'.mypy_cache',
'__pycache__',
'.stfolder',
'.stversions',
},
never_show = {},
},
},
buffers = {
bind_to_cwd = false,
window = {
mappings = {
['<BS>'] = 'navigate_up',
['.'] = 'set_root',
['dd'] = 'buffer_delete',
},
},
},
},
}

View File

@ -0,0 +1,512 @@
-- Plugin: telescope.nvim
-- https://github.com/rafi/vim-config
-- Helpers
-- Custom actions
local myactions = {}
function myactions.send_to_qflist(prompt_bufnr)
require('telescope.actions').send_to_qflist(prompt_bufnr)
vim.api.nvim_command([[ botright copen ]])
end
function myactions.smart_send_to_qflist(prompt_bufnr)
require('telescope.actions').smart_send_to_qflist(prompt_bufnr)
vim.api.nvim_command([[ botright copen ]])
end
--- Scroll the results window up
---@param prompt_bufnr number: The prompt bufnr
function myactions.results_scrolling_up(prompt_bufnr)
myactions.scroll_results(prompt_bufnr, -1)
end
--- Scroll the results window down
---@param prompt_bufnr number: The prompt bufnr
function myactions.results_scrolling_down(prompt_bufnr)
myactions.scroll_results(prompt_bufnr, 1)
end
---@param prompt_bufnr number: The prompt bufnr
---@param direction number: 1|-1
function myactions.scroll_results(prompt_bufnr, direction)
local status = require('telescope.state').get_status(prompt_bufnr)
local default_speed = vim.api.nvim_win_get_height(status.results_win) / 2
local speed = status.picker.layout_config.scroll_speed or default_speed
require('telescope.actions.set').shift_selection(
prompt_bufnr,
math.floor(speed) * direction
)
end
-- Custom pickers
local plugin_directories = function(opts)
local actions = require('telescope.actions')
local utils = require('telescope.utils')
local dir = vim.fn.stdpath('data') .. '/lazy'
opts = opts or {}
opts.cmd = vim.F.if_nil(opts.cmd, {
vim.o.shell,
'-c',
'find ' .. vim.fn.shellescape(dir) .. ' -mindepth 1 -maxdepth 1 -type d',
})
local dir_len = dir:len()
opts.entry_maker = function(line)
return {
value = line,
ordinal = line,
display = line:sub(dir_len + 2),
}
end
require('telescope.pickers')
.new(opts, {
layout_config = {
width = 0.65,
height = 0.7,
},
prompt_title = '[ Plugin directories ]',
finder = require('telescope.finders').new_table({
results = utils.get_os_command_output(opts.cmd),
entry_maker = opts.entry_maker,
}),
sorter = require('telescope.sorters').get_fuzzy_file(),
previewer = require('telescope.previewers.term_previewer').cat.new(opts),
attach_mappings = function(prompt_bufnr)
actions.select_default:replace(function()
local entry = require('telescope.actions.state').get_selected_entry()
actions.close(prompt_bufnr)
vim.cmd.tcd(entry.value)
end)
return true
end,
})
:find()
end
-- Custom window-sizes
---@param dimensions table
---@param size integer
---@return float
local function get_matched_ratio(dimensions, size)
for min_cols, scale in pairs(dimensions) do
if min_cols == 'lower' or size >= min_cols then
return math.floor(size * scale)
end
end
return dimensions.lower
end
local function width_tiny(_, cols, _)
return get_matched_ratio({ [180] = 0.27, lower = 0.37 }, cols)
end
local function width_small(_, cols, _)
return get_matched_ratio({ [180] = 0.4, lower = 0.5 }, cols)
end
local function width_medium(_, cols, _)
return get_matched_ratio({ [180] = 0.5, [110] = 0.6, lower = 0.75 }, cols)
end
local function width_large(_, cols, _)
return get_matched_ratio({ [180] = 0.7, [110] = 0.8, lower = 0.85 }, cols)
end
-- Enable indent-guides in telescope preview
vim.api.nvim_create_autocmd('User', {
pattern = 'TelescopePreviewerLoaded',
group = vim.api.nvim_create_augroup('rafi_telescope', {}),
callback = function(args)
if args.buf ~= vim.api.nvim_win_get_buf(0) then
return
end
vim.opt_local.listchars = vim.wo.listchars .. ',tab:▏\\ '
vim.opt_local.conceallevel = 0
vim.opt_local.wrap = true
vim.opt_local.list = true
vim.opt_local.number = true
end,
})
-- Setup Telescope
-- See telescope.nvim/lua/telescope/config.lua for defaults.
return {
-----------------------------------------------------------------------------
{
'nvim-telescope/telescope.nvim',
cmd = 'Telescope',
commit = vim.fn.has('nvim-0.9') == 0 and '057ee0f8783' or nil,
dependencies = {
'nvim-lua/plenary.nvim',
'jvgrootveld/telescope-zoxide',
'folke/todo-comments.nvim',
'rafi/telescope-thesaurus.nvim',
},
config = function(_, opts)
require('telescope').setup(opts)
require('telescope').load_extension('persisted')
end,
-- stylua: ignore
keys = {
-- General pickers
{ '<localleader>r', '<cmd>Telescope resume initial_mode=normal<CR>', desc = 'Resume last' },
{ '<localleader>R', '<cmd>Telescope pickers<CR>', desc = 'Pickers' },
{ '<localleader>f', '<cmd>Telescope find_files<CR>', desc = 'Find files' },
{ '<localleader>g', '<cmd>Telescope live_grep<CR>', desc = 'Grep' },
{ '<localleader>b', '<cmd>Telescope buffers show_all_buffers=true<CR>', desc = 'Buffers' },
{ '<localleader>h', '<cmd>Telescope highlights<CR>', desc = 'Highlights' },
{ '<localleader>j', '<cmd>Telescope jumplist<CR>', desc = 'Jump list' },
{ '<localleader>m', '<cmd>Telescope marks<CR>', desc = 'Marks' },
{ '<localleader>o', '<cmd>Telescope vim_options<CR>', desc = 'Neovim options' },
{ '<localleader>t', '<cmd>Telescope lsp_dynamic_workspace_symbols<CR>', desc = 'Workspace symbols' },
{ '<localleader>v', '<cmd>Telescope registers<CR>', desc = 'Registers' },
{ '<localleader>u', '<cmd>Telescope spell_suggest<CR>', desc = 'Spell suggest' },
{ '<localleader>s', '<cmd>Telescope persisted<CR>', desc = 'Sessions' },
{ '<localleader>x', '<cmd>Telescope oldfiles<CR>', desc = 'Old files' },
{ '<localleader>;', '<cmd>Telescope command_history<CR>', desc = 'Command history' },
{ '<localleader>:', '<cmd>Telescope commands<CR>', desc = 'Commands' },
{ '<localleader>/', '<cmd>Telescope search_history<CR>', desc = 'Search history' },
{ '<leader>/', '<cmd>Telescope current_buffer_fuzzy_find<CR>', desc = 'Buffer find' },
{ '<leader>sd', '<cmd>Telescope diagnostics bufnr=0<CR>', desc = 'Document diagnostics' },
{ '<leader>sD', '<cmd>Telescope diagnostics<CR>', desc = 'Workspace diagnostics' },
{ '<leader>sh', '<cmd>Telescope help_tags<CR>', desc = 'Help Pages' },
{ '<leader>sk', '<cmd>Telescope keymaps<CR>', desc = 'Key Maps' },
{ '<leader>sm', '<cmd>Telescope man_pages<CR>', desc = 'Man Pages' },
{ '<leader>sw', '<cmd>Telescope grep_string<CR>', desc = 'Word' },
{ '<leader>sc', '<cmd>Telescope colorscheme<CR>', desc = 'Colorscheme' },
{ '<leader>uC', '<cmd>Telescope colorscheme<CR>', desc = 'Colorscheme' },
-- LSP related
{ '<localleader>dd', '<cmd>Telescope lsp_definitions<CR>', desc = 'Definitions' },
{ '<localleader>di', '<cmd>Telescope lsp_implementations<CR>', desc = 'Implementations' },
{ '<localleader>dr', '<cmd>Telescope lsp_references<CR>', desc = 'References' },
{ '<localleader>da', '<cmd>Telescope lsp_code_actions<CR>', desc = 'Code actions' },
{ '<localleader>da', ':Telescope lsp_range_code_actions<CR>', mode = 'x', desc = 'Code actions' },
{
'<leader>ss',
function()
require('telescope.builtin').lsp_document_symbols({
symbols = {
'Class',
'Function',
'Method',
'Constructor',
'Interface',
'Module',
'Struct',
'Trait',
'Field',
'Property',
},
})
end,
desc = 'Goto Symbol',
},
{
'<leader>sS',
function()
require('telescope.builtin').lsp_dynamic_workspace_symbols({
symbols = {
'Class',
'Function',
'Method',
'Constructor',
'Interface',
'Module',
'Struct',
'Trait',
'Field',
'Property',
},
})
end,
desc = 'Goto Symbol (Workspace)',
},
-- Git
{ '<leader>gs', '<cmd>Telescope git_status<CR>', desc = 'Git status' },
{ '<leader>gr', '<cmd>Telescope git_branches<CR>', desc = 'Git branches' },
{ '<leader>gl', '<cmd>Telescope git_commits<CR>', desc = 'Git commits' },
{ '<leader>gL', '<cmd>Telescope git_bcommits<CR>', desc = 'Git buffer commits' },
{ '<leader>gh', '<cmd>Telescope git_stash<CR>', desc = 'Git stashes' },
{ '<leader>gc', '<cmd>Telescope git_bcommits_range<CR>', mode = { 'x', 'n' }, desc = 'Git bcommits range' },
-- Plugins
{ '<localleader>n', plugin_directories, desc = 'Plugins' },
{ '<localleader>k', '<cmd>Telescope thesaurus lookup<CR>', desc = 'Thesaurus' },
{ '<localleader>w', '<cmd>ZkNotes<CR>', desc = 'Zk notes' },
{
'<localleader>z',
function()
require('telescope').extensions.zoxide.list({
layout_config = { width = 0.5, height = 0.6 },
})
end,
desc = 'Zoxide (MRU)',
},
-- Find by...
{
'<leader>gt',
function()
require('telescope.builtin').lsp_workspace_symbols({
default_text = vim.fn.expand('<cword>'),
})
end,
desc = 'Find symbol',
},
{
'<leader>gf',
function()
require('telescope.builtin').find_files({
default_text = vim.fn.expand('<cword>'),
})
end,
desc = 'Find file',
},
{
'<leader>gg', function()
require('telescope.builtin').live_grep({
default_text = vim.fn.expand('<cword>'),
})
end,
desc = 'Grep cursor word',
},
{
'<leader>gg',
function()
require('telescope.builtin').live_grep({
default_text = require('rafi.lib.edit').get_visual_selection(),
})
end,
mode = 'x',
desc = 'Grep cursor word',
},
},
opts = function()
local transform_mod = require('telescope.actions.mt').transform_mod
local actions = require('telescope.actions')
-- Transform to Telescope proper actions.
myactions = transform_mod(myactions)
-- Clone the default Telescope configuration and enable hidden files.
local has_ripgrep = vim.fn.executable('rg') == 1
local vimgrep_args = {
unpack(require('telescope.config').values.vimgrep_arguments),
}
table.insert(vimgrep_args, '--hidden')
table.insert(vimgrep_args, '--follow')
table.insert(vimgrep_args, '--no-ignore-vcs')
table.insert(vimgrep_args, '--glob')
table.insert(vimgrep_args, '!**/.git/*')
local find_args = {
'rg',
'--vimgrep',
'--files',
'--follow',
'--hidden',
'--no-ignore-vcs',
'--smart-case',
'--glob',
'!**/.git/*',
}
return {
defaults = {
sorting_strategy = 'ascending',
cache_picker = { num_pickers = 3 },
prompt_prefix = '', --  
selection_caret = '',
multi_icon = '',
path_display = { 'truncate' },
file_ignore_patterns = { 'node_modules' },
set_env = { COLORTERM = 'truecolor' },
vimgrep_arguments = has_ripgrep and vimgrep_args or nil,
layout_strategy = 'horizontal',
layout_config = {
prompt_position = 'top',
horizontal = {
height = 0.85,
},
},
-- stylua: ignore
mappings = {
i = {
['jj'] = { '<Esc>', type = 'command' },
['<Tab>'] = actions.move_selection_worse,
['<S-Tab>'] = actions.move_selection_better,
['<C-u>'] = actions.results_scrolling_up,
['<C-d>'] = actions.results_scrolling_down,
['<C-q>'] = myactions.smart_send_to_qflist,
['<C-n>'] = actions.cycle_history_next,
['<C-p>'] = actions.cycle_history_prev,
['<C-b>'] = actions.preview_scrolling_up,
['<C-f>'] = actions.preview_scrolling_down,
},
n = {
['q'] = actions.close,
['<Esc>'] = actions.close,
['<Tab>'] = actions.move_selection_worse,
['<S-Tab>'] = actions.move_selection_better,
['<C-u>'] = myactions.results_scrolling_up,
['<C-d>'] = myactions.results_scrolling_down,
['<C-b>'] = actions.preview_scrolling_up,
['<C-f>'] = actions.preview_scrolling_down,
['<C-n>'] = actions.cycle_history_next,
['<C-p>'] = actions.cycle_history_prev,
['*'] = actions.toggle_all,
['u'] = actions.drop_all,
['J'] = actions.toggle_selection + actions.move_selection_next,
['K'] = actions.toggle_selection + actions.move_selection_previous,
[' '] = {
actions.toggle_selection + actions.move_selection_next,
type = 'action',
opts = { nowait = true },
},
['sv'] = actions.select_horizontal,
['sg'] = actions.select_vertical,
['st'] = actions.select_tab,
['w'] = myactions.smart_send_to_qflist,
['e'] = myactions.send_to_qflist,
['!'] = actions.edit_command_line,
['t'] = function(...)
return require('trouble.providers.telescope').open_with_trouble(...)
end,
['p'] = function()
local entry = require('telescope.actions.state').get_selected_entry()
require('rafi.lib.preview').open(entry.path)
end,
},
},
},
pickers = {
buffers = {
sort_lastused = true,
sort_mru = true,
show_all_buffers = true,
ignore_current_buffer = true,
layout_config = { width = width_large, height = 0.7 },
mappings = {
n = {
['dd'] = actions.delete_buffer,
},
},
},
find_files = {
find_command = has_ripgrep and find_args or nil,
},
live_grep = {
dynamic_preview_title = true,
},
colorscheme = {
enable_preview = true,
layout_config = { preview_width = 0.7 },
},
highlights = {
layout_config = { preview_width = 0.7 },
},
vim_options = {
theme = 'dropdown',
layout_config = { width = width_medium, height = 0.7 },
},
command_history = {
theme = 'dropdown',
layout_config = { width = width_medium, height = 0.7 },
},
search_history = {
theme = 'dropdown',
layout_config = { width = width_small, height = 0.6 },
},
spell_suggest = {
theme = 'cursor',
layout_config = { width = width_tiny, height = 0.45 },
},
registers = {
theme = 'cursor',
layout_config = { width = 0.35, height = 0.4 },
},
oldfiles = {
theme = 'dropdown',
previewer = false,
layout_config = { width = width_medium, height = 0.7 },
},
lsp_definitions = {
layout_config = { width = width_large, preview_width = 0.55 },
},
lsp_implementations = {
layout_config = { width = width_large, preview_width = 0.55 },
},
lsp_references = {
layout_config = { width = width_large, preview_width = 0.55 },
},
lsp_code_actions = {
theme = 'cursor',
previewer = false,
layout_config = { width = 0.3, height = 0.4 },
},
lsp_range_code_actions = {
theme = 'cursor',
previewer = false,
layout_config = { width = 0.3, height = 0.4 },
},
},
extensions = {
persisted = {
layout_config = { width = 0.55, height = 0.55 },
},
zoxide = {
prompt_title = '[ Zoxide directories ]',
mappings = {
default = {
action = function(selection)
vim.cmd.tcd(selection.path)
end,
after_action = function(selection)
vim.notify(
"Current working directory set to '"
.. selection.path
.. "'",
vim.log.levels.INFO
)
end,
},
},
},
},
}
end,
},
}

View File

@ -0,0 +1,190 @@
-- Plugins: Tree-sitter and Syntax
-- https://github.com/rafi/vim-config
return {
-----------------------------------------------------------------------------
-- Vimscript syntax/indent plugins
{ 'iloginow/vim-stylus', ft = 'stylus' },
{ 'chrisbra/csv.vim', ft = 'csv' },
{ 'mustache/vim-mustache-handlebars', ft = { 'mustache', 'handlebars' } },
{ 'lifepillar/pgsql.vim', ft = 'pgsql' },
{ 'MTDL9/vim-log-highlighting', ft = 'log' },
{ 'reasonml-editor/vim-reason-plus', ft = { 'reason', 'merlin' } },
{ 'vmchale/just-vim', ft = 'just' },
-----------------------------------------------------------------------------
{
'andymass/vim-matchup',
init = function()
vim.g.matchup_matchparen_offscreen = {}
end,
},
-----------------------------------------------------------------------------
{
'nvim-treesitter/nvim-treesitter',
event = { 'BufReadPost', 'BufNewFile' },
main = 'nvim-treesitter.configs',
build = ':TSUpdate',
dependencies = {
'nvim-treesitter/nvim-treesitter-textobjects',
{ 'nvim-treesitter/nvim-treesitter-context', opts = { enable = false } },
'JoosepAlviste/nvim-ts-context-commentstring',
'RRethy/nvim-treesitter-endwise',
'windwp/nvim-ts-autotag',
'andymass/vim-matchup',
},
cmd = {
'TSUpdate',
'TSInstall',
'TSInstallInfo',
'TSModuleInfo',
'TSConfigInfo',
'TSUpdateSync',
},
keys = {
{ 'v', desc = 'Increment selection', mode = 'x' },
{ 'V', desc = 'Shrink selection', mode = 'x' },
},
---@type TSConfig
---@diagnostic disable-next-line: missing-fields
opts = {
highlight = { enable = true },
indent = { enable = true },
refactor = {
highlight_definitions = { enable = true },
highlight_current_scope = { enable = true },
},
-- See: https://github.com/RRethy/nvim-treesitter-endwise
endwise = { enable = true },
-- See: https://github.com/andymass/vim-matchup
matchup = {
enable = true,
include_match_words = true,
},
-- See: https://github.com/windwp/nvim-ts-autotag
autotag = {
enable = true,
-- Removed markdown due to errors
filetypes = {
'glimmer',
'handlebars',
'hbs',
'html',
'javascript',
'javascriptreact',
'jsx',
'rescript',
'svelte',
'tsx',
'typescript',
'typescriptreact',
'vue',
'xml',
},
},
-- See: https://github.com/JoosepAlviste/nvim-ts-context-commentstring
context_commentstring = { enable = true, enable_autocmd = false },
incremental_selection = {
enable = true,
keymaps = {
init_selection = false,
node_incremental = 'v',
scope_incremental = false,
node_decremental = 'V',
},
},
-- See: https://github.com/nvim-treesitter/nvim-treesitter-textobjects
textobjects = {
select = {
enable = true,
lookahead = true,
keymaps = {
['af'] = '@function.outer',
['if'] = '@function.inner',
['ac'] = '@class.outer',
['ic'] = '@class.inner',
['a,'] = '@parameter.outer',
['i,'] = '@parameter.inner',
},
},
move = {
enable = true,
set_jumps = true,
goto_next_start = {
['],'] = '@parameter.inner',
},
goto_previous_start = {
['[,'] = '@parameter.inner',
},
},
swap = {
enable = true,
swap_next = {
['>,'] = '@parameter.inner',
},
swap_previous = {
['<,'] = '@parameter.inner',
},
},
},
-- https://github.com/nvim-treesitter/nvim-treesitter#supported-languages
ensure_installed = {
'bash',
'comment',
'css',
'cue',
'diff',
'fish',
'fennel',
'git_config',
'git_rebase',
'gitcommit',
'gitignore',
'gitattributes',
'graphql',
'hcl',
'html',
'http',
'java',
'javascript',
'jsdoc',
'kotlin',
'lua',
'luadoc',
'luap',
'make',
'markdown',
'markdown_inline',
'nix',
'perl',
'php',
'pug',
'regex',
'ruby',
'rust',
'scala',
'scss',
'sql',
'svelte',
'terraform',
'todotxt',
'toml',
'tsx',
'typescript',
'vim',
'vimdoc',
'vue',
'zig',
},
},
},
}

343
lua/plex/plugins/ui.lua Normal file
View File

@ -0,0 +1,343 @@
-- Plugins: UI
-- https://github.com/plex/vim-config
return {
-----------------------------------------------------------------------------
{ 'nvim-tree/nvim-web-devicons', lazy = false },
{ 'MunifTanjim/nui.nvim', lazy = false },
{ 'plex/tabstrip.nvim', lazy = false, priority = 98, opts = true },
-----------------------------------------------------------------------------
{
'folke/noice.nvim',
event = 'VeryLazy',
dependencies = {
'MunifTanjim/nui.nvim',
'rcarriga/nvim-notify',
'nvim-treesitter/nvim-treesitter',
},
-- stylua: ignore
keys = {
{ '<S-Enter>', function() require('noice').redirect(tostring(vim.fn.getcmdline())) end, mode = 'c', desc = 'Redirect Cmdline' },
{ '<leader>snl', function() require('noice').cmd('last') end, desc = 'Noice Last Message' },
{ '<leader>snh', function() require('noice').cmd('history') end, desc = 'Noice History' },
{ '<leader>sna', function() require('noice').cmd('all') end, desc = 'Noice All' },
{ '<c-f>', function() if not require('noice.lsp').scroll(4) then return '<c-f>' end end, silent = true, expr = true, desc = 'Scroll forward', mode = {'i', 'n', 's'} },
{ '<c-b>', function() if not require('noice.lsp').scroll(-4) then return '<c-b>' end end, silent = true, expr = true, desc = 'Scroll backward', mode = {'i', 'n', 's'}},
},
---@type NoiceConfig
opts = {
lsp = {
override = {
['vim.lsp.util.convert_input_to_markdown_lines'] = true,
['vim.lsp.util.stylize_markdown'] = true,
['cmp.entry.get_documentation'] = true,
},
},
messages = {
view_search = false,
},
routes = {
-- See :h ui-messages
{
filter = { event = 'msg_show', find = '%d+L, %d+B$' },
view = 'mini',
},
{
filter = { event = 'msg_show', find = '^Hunk %d+ of %d+$' },
view = 'mini',
},
{
filter = { event = 'notify', find = '^No code actions available$' },
view = 'mini',
},
{
filter = { event = 'notify', find = '^No information available$' },
opts = { skip = true },
},
{
filter = { event = 'msg_show', find = '^%d+ change;' },
opts = { skip = true },
},
{
filter = { event = 'msg_show', find = '^%d+ %a+ lines' },
opts = { skip = true },
},
{
filter = { event = 'msg_show', find = '^%d+ lines yanked$' },
opts = { skip = true },
},
{
filter = { event = 'msg_show', kind = 'emsg', find = 'E490' },
opts = { skip = true },
},
{
filter = { event = 'msg_show', kind = 'quickfix' },
view = 'mini',
},
{
filter = { event = 'msg_show', kind = 'search_count' },
view = 'mini',
},
{
filter = { event = 'msg_show', kind = 'wmsg' },
view = 'mini',
},
},
presets = {
bottom_search = true,
command_palette = true,
long_message_to_split = true,
lsp_doc_border = true,
},
commands = {
all = {
view = 'split',
opts = { enter = true, format = 'details' },
filter = {},
},
},
---@type NoiceConfigViews
views = {
mini = {
zindex = 100,
win_options = { winblend = 0 },
},
},
},
},
-----------------------------------------------------------------------------
{
'stevearc/dressing.nvim',
init = function()
---@diagnostic disable-next-line: duplicate-set-field
vim.ui.select = function(...)
require('lazy').load({ plugins = { 'dressing.nvim' } })
return vim.ui.select(...)
end
---@diagnostic disable-next-line: duplicate-set-field
vim.ui.input = function(...)
require('lazy').load({ plugins = { 'dressing.nvim' } })
return vim.ui.input(...)
end
end,
},
-----------------------------------------------------------------------------
{
'SmiteshP/nvim-navic',
keys = {
{
'<Leader>tf',
function()
if vim.b.navic_winbar then
vim.b.navic_winbar = false
vim.opt_local.winbar = ''
else
vim.b.navic_winbar = true
vim.opt_local.winbar = '%#NavicIconsFile# %t %* '
.. "%{%v:lua.require'nvim-navic'.get_location()%}"
end
end,
desc = 'Toggle structure panel',
},
},
init = function()
vim.g.navic_silence = true
---@param client lsp.Client
---@param buffer integer
require('plex.lib.utils').on_attach(function(client, buffer)
if client.server_capabilities.documentSymbolProvider then
require('nvim-navic').attach(client, buffer)
end
end)
end,
opts = function()
return {
separator = '',
highlight = true,
icons = require('plex.config').icons.kinds,
}
end,
},
-----------------------------------------------------------------------------
{
'rcarriga/nvim-notify',
event = 'VeryLazy',
keys = {
{
'<leader>un',
function()
require('notify').dismiss({ silent = true, pending = true })
end,
desc = 'Dismiss all Notifications',
},
},
opts = {
timeout = 3000,
max_height = function()
return math.floor(vim.o.lines * 0.75)
end,
max_width = function()
return math.floor(vim.o.columns * 0.75)
end,
},
init = function()
-- When noice is not enabled, install notify on VeryLazy
local Util = require('plex.lib.utils')
if not Util.has('noice.nvim') then
Util.on_very_lazy(function()
vim.notify = require('notify')
end)
end
end,
},
-----------------------------------------------------------------------------
{
'chentoast/marks.nvim',
dependencies = 'lewis6991/gitsigns.nvim',
event = 'FileType',
keys = {
{ 'm/', '<cmd>MarksListAll<CR>', desc = 'Marks from all opened buffers' },
},
opts = {
sign_priority = { lower = 10, upper = 15, builtin = 8, bookmark = 20 },
bookmark_1 = { sign = '󰈼' }, -- ⚐ ⚑ 󰈻 󰈼 󰈽 󰈾 󰈿 󰉀
mappings = {
annotate = 'm<Space>',
},
},
},
-----------------------------------------------------------------------------
{
'lukas-reineke/indent-blankline.nvim',
event = 'FileType',
keys = {
{ '<Leader>ue', '<cmd>IndentBlanklineToggle<CR>' },
},
opts = {
show_trailing_blankline_indent = false,
disable_with_nolist = true,
show_foldtext = false,
char_priority = 100,
show_current_context = true,
show_current_context_start = false,
filetype_exclude = {
'lspinfo',
'checkhealth',
'git',
'gitcommit',
'help',
'man',
'lazy',
'alpha',
'dashboard',
'terminal',
'TelescopePrompt',
'TelescopeResults',
'neo-tree',
'Outline',
'mason',
'Trouble',
},
},
},
-----------------------------------------------------------------------------
{
'tenxsoydev/tabs-vs-spaces.nvim',
event = { 'BufReadPost', 'BufNewFile' },
config = true,
},
-----------------------------------------------------------------------------
{
't9md/vim-quickhl',
keys = {
{
'<Leader>mt',
'<Plug>(quickhl-manual-this)',
mode = { 'n', 'x' },
desc = 'Highlight word',
},
},
},
-----------------------------------------------------------------------------
{
'kevinhwang91/nvim-bqf',
ft = 'qf',
cmd = 'BqfAutoToggle',
event = 'QuickFixCmdPost',
opts = {
auto_resize_height = false,
func_map = {
tab = 'st',
split = 'sv',
vsplit = 'sg',
stoggleup = 'K',
stoggledown = 'J',
stogglevm = '<Space>',
ptoggleitem = 'p',
ptoggleauto = 'P',
ptogglemode = 'zp',
pscrollup = '<C-b>',
pscrolldown = '<C-f>',
prevfile = 'gk',
nextfile = 'gj',
prevhist = '<S-Tab>',
nexthist = '<Tab>',
},
preview = {
auto_preview = true,
should_preview_cb = function(bufnr)
-- file size greater than 100kb can't be previewed automatically
local filename = vim.api.nvim_buf_get_name(bufnr)
local fsize = vim.fn.getfsize(filename)
if fsize > 100 * 1024 then
return false
end
return true
end,
},
},
},
-----------------------------------------------------------------------------
{
'uga-rosa/ccc.nvim',
event = 'FileType',
keys = {
{ '<Leader>cp', '<cmd>CccPick<CR>', desc = 'Color-picker' },
},
opts = {
highlighter = {
auto_enable = true,
lsp = true,
excludes = { 'lazy', 'mason', 'help', 'neo-tree' },
},
},
},
-----------------------------------------------------------------------------
{
'itchyny/calendar.vim',
cmd = 'Calendar',
init = function()
vim.g.calendar_google_calendar = 1
vim.g.calendar_google_task = 1
vim.g.calendar_cache_directory = vim.fn.stdpath('data') .. '/calendar'
end,
},
}