aboutsummaryrefslogtreecommitdiff
path: root/common/config/nvim/lua/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'common/config/nvim/lua/plugins')
-rwxr-xr-xcommon/config/nvim/lua/plugins/auto-session.lua39
-rwxr-xr-x[-rw-r--r--]common/config/nvim/lua/plugins/autopairs.lua22
-rwxr-xr-x[-rw-r--r--]common/config/nvim/lua/plugins/cmp-gh-source.lua0
-rwxr-xr-x[-rw-r--r--]common/config/nvim/lua/plugins/cmp.lua397
-rwxr-xr-xcommon/config/nvim/lua/plugins/colorizer.lua8
-rwxr-xr-x[-rw-r--r--]common/config/nvim/lua/plugins/colorscheme.lua362
-rwxr-xr-xcommon/config/nvim/lua/plugins/comment.lua125
-rwxr-xr-x[-rw-r--r--]common/config/nvim/lua/plugins/dap.lua46
-rwxr-xr-x[-rw-r--r--]common/config/nvim/lua/plugins/dashboard.lua114
-rwxr-xr-x[-rw-r--r--]common/config/nvim/lua/plugins/fidget.lua0
-rwxr-xr-xcommon/config/nvim/lua/plugins/friendly-snippets.lua3
-rwxr-xr-xcommon/config/nvim/lua/plugins/fugitive.lua8
-rwxr-xr-x[-rw-r--r--]common/config/nvim/lua/plugins/fzf.lua103
-rwxr-xr-xcommon/config/nvim/lua/plugins/git.lua8
-rwxr-xr-x[-rw-r--r--]common/config/nvim/lua/plugins/gitsigns.lua40
-rwxr-xr-x[-rw-r--r--]common/config/nvim/lua/plugins/goto-preview.lua19
-rwxr-xr-x[-rw-r--r--]common/config/nvim/lua/plugins/hardtime.lua22
-rwxr-xr-x[-rw-r--r--]common/config/nvim/lua/plugins/harpoon.lua40
-rwxr-xr-x[-rw-r--r--]common/config/nvim/lua/plugins/heirline.lua2631
-rwxr-xr-x[-rw-r--r--]common/config/nvim/lua/plugins/indent-blankline.lua95
-rwxr-xr-xcommon/config/nvim/lua/plugins/interestingwords.lua499
-rwxr-xr-x[-rw-r--r--]common/config/nvim/lua/plugins/leetcode.lua0
-rwxr-xr-x[-rw-r--r--]common/config/nvim/lua/plugins/loclist.lua0
-rwxr-xr-x[-rw-r--r--]common/config/nvim/lua/plugins/lsp.lua1036
-rwxr-xr-xcommon/config/nvim/lua/plugins/lualine.lua22
-rwxr-xr-xcommon/config/nvim/lua/plugins/luasnip.lua13
-rwxr-xr-x[-rw-r--r--]common/config/nvim/lua/plugins/messages.lua0
-rwxr-xr-x[-rw-r--r--]common/config/nvim/lua/plugins/modify-blend.lua0
-rwxr-xr-x[-rw-r--r--]common/config/nvim/lua/plugins/navic.lua97
-rwxr-xr-x[-rw-r--r--]common/config/nvim/lua/plugins/neodev.lua26
-rwxr-xr-x[-rw-r--r--]common/config/nvim/lua/plugins/neoscroll.lua39
-rwxr-xr-x[-rw-r--r--]common/config/nvim/lua/plugins/neotest.lua45
-rwxr-xr-x[-rw-r--r--]common/config/nvim/lua/plugins/notify.lua52
-rwxr-xr-x[-rw-r--r--]common/config/nvim/lua/plugins/nvim-tree.lua690
-rwxr-xr-x[-rw-r--r--]common/config/nvim/lua/plugins/overseer.lua15
-rwxr-xr-xcommon/config/nvim/lua/plugins/plenary.lua3
-rwxr-xr-xcommon/config/nvim/lua/plugins/prettier.lua8
-rwxr-xr-x[-rw-r--r--]common/config/nvim/lua/plugins/quickfix.lua0
-rw-r--r--common/config/nvim/lua/plugins/session.lua5
-rwxr-xr-x[-rw-r--r--]common/config/nvim/lua/plugins/snippets.lua89
-rwxr-xr-x[-rw-r--r--]common/config/nvim/lua/plugins/sniprun.lua0
-rwxr-xr-x[-rw-r--r--]common/config/nvim/lua/plugins/statuscol.lua25
-rwxr-xr-x[-rw-r--r--]common/config/nvim/lua/plugins/surround.lua19
-rwxr-xr-x[-rw-r--r--]common/config/nvim/lua/plugins/telescope.lua944
-rwxr-xr-x[-rw-r--r--]common/config/nvim/lua/plugins/toggleterm.lua217
-rwxr-xr-x[-rw-r--r--]common/config/nvim/lua/plugins/treesitter.lua81
-rwxr-xr-x[-rw-r--r--]common/config/nvim/lua/plugins/trouble.lua114
-rwxr-xr-x[-rw-r--r--]common/config/nvim/lua/plugins/vimtex.lua0
-rwxr-xr-x[-rw-r--r--]common/config/nvim/lua/plugins/web-devicons.lua145
-rwxr-xr-x[-rw-r--r--]common/config/nvim/lua/plugins/which-key.lua109
-rwxr-xr-x[-rw-r--r--]common/config/nvim/lua/plugins/zen-mode.lua0
51 files changed, 4787 insertions, 3588 deletions
diff --git a/common/config/nvim/lua/plugins/auto-session.lua b/common/config/nvim/lua/plugins/auto-session.lua
new file mode 100755
index 0000000..d982e08
--- /dev/null
+++ b/common/config/nvim/lua/plugins/auto-session.lua
@@ -0,0 +1,39 @@
+local M = {}
+
+function M.setup()
+ local auto = pcall(require, 'auto-session') and require('auto-session')
+ if not auto then
+ return false
+ end
+
+ local nvim_version = vim.version()
+ if nvim_version.major == 0 and nvim_version.minor < 5 then
+ return false
+ end
+
+ -- Configure session options
+ vim.opt.sessionoptions:append("localoptions") -- Add localoptions to sessionoptions
+
+ -- Set up auto-session
+ auto.setup({
+ log_level = 'info',
+ auto_session_suppress_dirs = { '~/', '~/Projects', '~/projects', '~/Downloads', '~/downloads' },
+ auto_session_use_git_branch = true,
+ bypass_save_filetypes = { "dashboard" },
+
+ -- Additional configuration to handle session options
+ pre_save_cmds = {
+ -- Ensure local options are saved with the session
+ function() vim.opt.sessionoptions:append("localoptions") end,
+ },
+
+ -- Post restore hook to ensure local options are properly set
+ post_restore = function()
+ vim.opt.sessionoptions:append("localoptions")
+ end,
+ })
+
+ return true
+end
+
+return M
diff --git a/common/config/nvim/lua/plugins/autopairs.lua b/common/config/nvim/lua/plugins/autopairs.lua
index 90b62b1..22dcf27 100644..100755
--- a/common/config/nvim/lua/plugins/autopairs.lua
+++ b/common/config/nvim/lua/plugins/autopairs.lua
@@ -1,9 +1,16 @@
-local status_ok, autopairs = pcall(require, "nvim-autopairs")
-if not status_ok then
- return
-end
+local M = {}
-autopairs.setup({
+--- Setup and configure nvim-autopairs
+-- This function initializes and configures the autopairs plugin
+-- @return boolean True if setup was successful, false otherwise
+function M.setup()
+ local ok, autopairs = pcall(require, "nvim-autopairs")
+ if not ok then
+ return false
+ end
+
+ -- Configure autopairs
+ autopairs.setup({
check_ts = true,
ts_config = {
lua = { "string", "source" },
@@ -85,3 +92,8 @@ cmp.event:on(
-- return
--end
--cmp.event:on("confirm_done", cmp_autopairs.on_confirm_done { map_char = { tex = "" } })
+
+ return true
+end
+
+return M
diff --git a/common/config/nvim/lua/plugins/cmp-gh-source.lua b/common/config/nvim/lua/plugins/cmp-gh-source.lua
index 4990c35..4990c35 100644..100755
--- a/common/config/nvim/lua/plugins/cmp-gh-source.lua
+++ b/common/config/nvim/lua/plugins/cmp-gh-source.lua
diff --git a/common/config/nvim/lua/plugins/cmp.lua b/common/config/nvim/lua/plugins/cmp.lua
index fe212fc..7de04ad 100644..100755
--- a/common/config/nvim/lua/plugins/cmp.lua
+++ b/common/config/nvim/lua/plugins/cmp.lua
@@ -1,354 +1,67 @@
--- Setup nvim-cmp.
-vim.opt.completeopt = "menu,menuone,noselect"
---vim.g.completeopt = "menu,menuone,noselect,noinsert"
-local cmp_status_ok, cmp = pcall(require, "cmp")
-if not cmp_status_ok then
- return
-end
---local WIDE_HEIGHT = 40
-
-local opts = {
- -- whether to highlight the currently hovered symbol
- -- disable if your cpu usage is higher than you want it
- -- or you just hate the highlight
- -- default: true
- highlight_hovered_item = true,
- show_guides = true,
-}
-require("symbols-outline").setup(opts)
-
---local snippets_paths = function()
--- local plugins = { "friendly-snippets" }
--- local paths = {}
--- local path
--- local root_path = vim.env.HOME .. "/.vim/plugged/"
--- for _, plug in ipairs(plugins) do
--- path = root_path .. plug
--- if vim.fn.isdirectory(path) ~= 0 then
--- table.insert(paths, path)
--- end
--- end
--- return paths
---end
---
---require("luasnip.loaders.from_vscode").lazy_load({
--- paths = snippets_paths(),
--- include = nil, -- Load all languages
--- exclude = {},
---})
+local M = {}
---require("luasnip.loaders.from_vscode").lazy_load()
-local lspkind = require("lspkind")
-local kind_icons = {
- Text = "",
- Method = "m", --"",
- Function = "",
- Constructor = "", --"⚙️",
- Field = "",
- Variable = "",
- Class = "ﴯ",
- Interface = "",
- Module = "",
- Property = "",
- Unit = "",
- Value = "",
- Enum = "",
- Keyword = "",
- Snippet = "",
- Color = "",
- File = "",
- Reference = "",
- Folder = "",
- EnumMember = "",
- Constant = "",
- Struct = "",
- Event = "",
- Operator = "",
- TypeParameter = "",
-}
-cmp.setup({
+--- Setup and configure nvim-cmp
+-- This function initializes and configures the completion plugin
+-- @return boolean True if setup was successful, false otherwise
+function M.setup()
+ -- Check Neovim version
+ local nvim_version = vim.version()
+ if nvim_version.major == 0 and nvim_version.minor < 5 then
+ return false
+ end
+
+ -- Try to load required modules
+ local cmp = pcall(require, 'cmp') and require('cmp')
+ if not cmp then
+ return false
+ end
+
+ local luasnip_ok, luasnip = pcall(require, 'luasnip')
+ if not luasnip_ok then
+ vim.notify("luasnip not found, some features may be limited", vim.log.levels.WARN)
+ end
+
+ -- Setup nvim-cmp
+ cmp.setup({
snippet = {
- --expand = function(args)
- -- require("luasnip").lsp_expand(args.body)
- --end,
expand = function(args)
- local luasnip = require("luasnip")
- if not luasnip then
- return
- end
- luasnip.lsp_expand(args.body)
+ if luasnip_ok then luasnip.lsp_expand(args.body) end
end,
},
mapping = cmp.mapping.preset.insert({
- -- ["<CR>"] = cmp.mapping.confirm({
- -- behavior = cmp.ConfirmBehavior.Replace,
- -- select = true,
- -- }),
- --["<C-k>"] = cmp.mapping(cmp.mapping.select_prev_item(), { 'i', 'c' }),
- --["<C-j>"] = cmp.mapping(cmp.mapping.select_next_item(), { 'i', 'c' }),
- ["<C-y>"] = cmp.mapping.confirm({ select = true }),
- --["<C-e>"] = cmp.mapping.close(),
- --['<C-e>'] = cmp.mapping({
- -- i = cmp.mapping.abort(),
- -- c = cmp.mapping.close(),
- --}),
- ["<C-e>"] = cmp.mapping({
- i = function()
- if cmp.visible() then
- cmp.abort()
- require("user.mods").toggle_completion()
- require("notify")("completion off")
- else
- cmp.complete()
- require("user.mods").toggle_completion()
- require("notify")("completion on")
- end
- end,
- }),
- --["<CR>"] = cmp.mapping({
- -- i = function(fallback)
- -- if cmp.visible() then
- -- cmp.confirm({ behavior = cmp.ConfirmBehavior.Replace, select = false })
- -- require("user.mods").toggle_completion()
- -- else
- -- fallback()
- -- end
- -- end,
- --}),
-
- -- ["<C-e>"] = cmp.mapping({
- -- i = function()
- -- if cmp.visible() then
- -- require("notify")("visible")
- -- cmp.abort()
- -- else
- -- require("notify")("not visible")
- -- cmp.complete()
- -- end
- -- end,
- -- c = function()
- -- if cmp.visible() then
- -- require("notify")("visible")
- -- cmp.close()
- -- else
- -- require("notify")("not visible")
- -- cmp.complete()
- -- end
- -- end,
- -- }),
- --['<CR>'] = cmp.config.disable,
- ["<C-u>"] = cmp.mapping.scroll_docs(-4),
- ["<C-d>"] = cmp.mapping.scroll_docs(4),
- ["<C-Space>"] = cmp.mapping.complete(),
- --['<C-o>'] = function(fallback)
- -- if cmp.visible() then
- -- cmp.mapping.confirm({ select = true })(fallback)
- -- else
- -- cmp.mapping.complete()(fallback)
- -- end
- --end
+ ['<C-Space>'] = cmp.mapping.complete(),
+ ['<CR>'] = cmp.mapping.confirm({ select = true }),
+ ['<Tab>'] = cmp.mapping.select_next_item(),
+ ['<S-Tab>'] = cmp.mapping.select_prev_item(),
}),
-
sources = cmp.config.sources({
- --{ name = "nvim_lua" },
- { name = "luasnip" },
- --{ name = 'luasnip', option = { use_show_condition = false } },
- { name = "gh_issues" },
- { name = "nvim_lsp", max_item_count = 6 },
- { name = "nvim_lua" },
- --{ name = "luasnip" },
- --{ name = "luasnip", keyword_length = 4 },
- --{ name = "buffer", keyword_length = 3 },
- { name = "path" },
- { name = "buffer", max_item_count = 6 },
- --{ name = "buffer", option = { get_bufnrs = function()
- -- return vim.api.nvim_list_bufs()
- --end
- --}},
- { name = "cmp_git" },
- { name = "spell" },
- { name = "zsh" },
- { name = "treesitter" },
- { name = "calc" },
- { name = "nvim_lsp_signature_help" },
- --{ name = "cmdline" },
- --{ name = 'treesitter' },
- --{ name = "cmdline", keyword_pattern = [=[[^[:blank:]\!]*]=] }, --exclamation mark hangs a bit without this
- --{name = 'luasnip', keyword_length = 2},
+ { name = 'nvim_lsp' },
+ { name = 'luasnip' },
+ { name = 'buffer' },
}),
- formatting = {
- --formatting = {
- --local icons = kind_icons
- --format = function(entry, vim_item)
- ----vim_item.kind = string.format("%s", kind_icons[vim_item.kind])
- ----vim_item.kind = lspkind.presets.default[vim_item.kind]
- --vim_item.kind = string.format('%s %s', kind_icons[vim_item.kind], vim_item.kind) -- This concatonates the icons with the name of the item kind
- ----vim_item.kind = string.format("%s %s", icons[vim_item.kind], vim_item.kind)
- --vim_item.menu = ({
- ----nvim_lsp = "LSP",
- ----luasnip = "snip",
- ----buffer = "buf",
- ----path = "path",
- ----cmdline = "cmd",
- --buffer = "[buf]",
- --nvim_lsp = "[LSP]",
- --nvim_lua = "[api]",
- --path = "[path]",
- --luasnip = "[snip]",
- --cmdline = "[cmd]",
- --gh_issues = "[issues]",
- --})[entry.source.name]
- --return vim_item
- --end,
- format = lspkind.cmp_format({
- with_text = true,
- menu = {
- nvim_lsp = "[LSP]",
- luasnip = "[snip]",
- buffer = "[buf]",
- nvim_lua = "[api]",
- path = "[path]",
- gh_issues = "[issues]",
- spell = "[spell]",
- zsh = "[zsh]",
- treesitter = "[treesitter]",
- calc = "[calc]",
- nvim_lsp_signature_help = "[signature]",
- cmdline = "[cmd]",
- },
- }),
- --},
-
- --
- --
- --fields = { "abbr", "kind", "menu" },
- -- format = lspkind.cmp_format({
- -- mode = 'symbol_text', -- show only symbol annotations
- -- maxwidth = 50, -- prevent the popup from showing more than provided characters (e.g 50 will not show more than 50 characters)
- -- })
- --format = require('lspkind').cmp_format {
- -- with_text = true,
- -- menu = {
- -- luasnip = "Snip",
- -- buffer = "Buf",
- -- nvim_lsp = "LSP",
- -- path = "Path",
- -- cmdline = "Cmd",
- -- cmp_git = "Git",
- -- },
- --},
- },
- --format = function(entry, vim_item)
- -- -- Kind icons
- -- --vim_item.kind = string.format("%s", kind_icons[vim_item.kind])
- -- vim_item.kind = lspkind.presets.default[vim_item.kind]
- -- -- vim_item.kind = string.format('%s %s', kind_icons[vim_item.kind], vim_item.kind) -- This concatonates the icons with the name of the item kind
- -- vim_item.menu = ({
- -- nvim_lsp = "LSP",
- -- luasnip = "Snip",
- -- buffer = "Buf",
- -- path = "Path",
- -- cmdline = "Cmd",
- -- })[entry.source.name]
- -- return vim_item
- --end,
- confirm_opts = {
- behavior = cmp.ConfirmBehavior.Replace,
- select = false,
- },
-
- event = {},
-
- experimental = {
- ghost_text = true, -- this feature conflicts with copilot.vim's preview.
- hl_group = "Nontext",
- --native_menu = false,
- },
-
- view = {
- entries = { name = "custom", selection_order = "top_down" },
- },
-
- window = {
- --completion = cmp.config.window.bordered(),
- completion = {
- border = { "", "", "", " ", "", "", "", " " },
- --border = { "╭", "─", "╮", "│", "╯", "─", "╰", "│" },
- --border = { '', '', '', '', '', '', '', '' },
- --border = "CmpBorder",
- winhighlight = "Normal:Pmenu,FloatBorder:Pmenu,CursorLine:PmenuSel,Search:None",
- --winhighlight = "Normal:CmpPmenu,CursorLine:PmenuSel,Search:None",
- },
- --documentation = cmp.config.window.bordered(),
- documentation = {
- --max_height = math.floor(WIDE_HEIGHT * (WIDE_HEIGHT / vim.o.lines)),
- --max_width = math.floor((WIDE_HEIGHT * 2) * (vim.o.columns / (WIDE_HEIGHT * 2 * 16 / 9))),
- border = { "", "", "", " ", "", "", "", " " },
- --border = { "╭", "─", "╮", "│", "╯", "─", "╰", "│" },
- winhighlight = "FloatBorder:NormalFloat",
- },
- },
-})
-
-cmp.setup.cmdline({ "/", "?" }, {
- mapping = cmp.mapping.preset.cmdline(),
- sources = {
- { name = "buffer" },
- },
})
-cmp.setup.cmdline(":", {
- mapping = {
- ["<C-p>"] = cmp.mapping(cmp.mapping.select_prev_item(), { "i", "c" }),
- ["<C-n>"] = cmp.mapping(cmp.mapping.select_next_item(), { "i", "c" }),
- ["<C-y>"] = cmp.mapping(cmp.mapping.confirm({ select = true }), { "i", "c" }),
- ["<C-e>"] = cmp.mapping(cmp.mapping.close(), { "i", "c" }),
- ["<C-u>"] = cmp.mapping(cmp.mapping.scroll_docs(-4), { "i", "c" }),
- ["<C-d>"] = cmp.mapping(cmp.mapping.scroll_docs(4), { "i", "c" }),
- ["<C-Space>"] = cmp.mapping(cmp.mapping.complete(), { "i", "c" }),
- --["<C-k>"] = cmp.mapping.select_prev_item(),
- --["<C-j>"] = cmp.mapping.select_next_item(),
- --['<C-y>'] = cmp.mapping.confirm({ select = true }),
- --["<C-e>"] = cmp.mapping.close(),
- ----['<CR>'] = cmp.config.disable,
- --["<C-u>"] = cmp.mapping.scroll_docs(-4),
- --["<C-d>"] = cmp.mapping.scroll_docs(4),
- --["<C-Space>"] = cmp.mapping.complete(),
- },
-
- sources = cmp.config.sources({
- { name = "path" },
- }, {
- --{ name = "cmdline" },
- { name = "cmdline", keyword_pattern = [=[[^[:blank:]\!]*]=], keyword_length = 3 },
- }),
-})
+vim.cmd([[
+ highlight! link CmpItemMenu Comment
+ " gray
+ highlight! CmpItemAbbrDeprecated guibg=NONE gui=strikethrough guifg=#808080
+ " blue
+ highlight! CmpItemAbbrMatch guibg=NONE guifg=#569CD6
+ highlight! CmpItemAbbrMatchFuzzy guibg=NONE guifg=#569CD6
+ " light blue
+ highlight! CmpItemKindVariable guibg=NONE guifg=#9CDCFE
+ highlight! CmpItemKindInterface guibg=NONE guifg=#9CDCFE
+ highlight! CmpItemKindText guibg=NONE guifg=#9CDCFE
+ " pink
+ highlight! CmpItemKindFunction guibg=NONE guifg=#C586C0
+ highlight! CmpItemKindMethod guibg=NONE guifg=#C586C0
+ " front
+ highlight! CmpItemKindKeyword guibg=NONE guifg=#D4D4D4
+ highlight! CmpItemKindProperty guibg=NONE guifg=#D4D4D4
+ highlight! CmpItemKindUnit guibg=NONE guifg=#D4D4D4
+ ]])
+
+ return true
+end
-return {
- "micangl/cmp-vimtex",
- config = function()
- require("cmp_vimtex").setup({
- additional_information = {
- info_in_menu = true,
- info_in_window = true,
- info_max_length = 60,
- match_against_info = true,
- symbols_in_menu = true,
- },
- bibtex_parser = {
- enabled = true,
- },
- search = {
- browser = "xdg-open",
- default = "google_scholar",
- search_engines = {
- google_scholar = {
- name = "Google Scholar",
- get_url = require("cmp_vimtex").url_default_format("https://scholar.google.com/scholar?hl=en&q=%s"),
- },
- -- Other search engines.
- },
- },
- })
- end,
-}
+return M
diff --git a/common/config/nvim/lua/plugins/colorizer.lua b/common/config/nvim/lua/plugins/colorizer.lua
new file mode 100755
index 0000000..6019bc5
--- /dev/null
+++ b/common/config/nvim/lua/plugins/colorizer.lua
@@ -0,0 +1,8 @@
+local M = {}
+
+function M.setup()
+ -- No-op if colorizer is not installed
+ return true
+end
+
+return M
diff --git a/common/config/nvim/lua/plugins/colorscheme.lua b/common/config/nvim/lua/plugins/colorscheme.lua
index be78ac8..7fbabc1 100644..100755
--- a/common/config/nvim/lua/plugins/colorscheme.lua
+++ b/common/config/nvim/lua/plugins/colorscheme.lua
@@ -1,344 +1,24 @@
---local function MyHighlights()
--- vim.cmd('highlight Visual cterm=NONE ctermbg=76 ctermfg=16 gui=NONE guibg=#5fd700 guifg=#000000')
--- vim.cmd('highlight StatusLine cterm=NONE ctermbg=231 ctermfg=160 gui=NONE guibg=#ffffff guifg=#d70000')
--- vim.cmd('highlight Normal cterm=NONE ctermbg=17 gui=NONE guibg=#00005f')
--- vim.cmd('highlight NonText cterm=NONE ctermbg=17 gui=NONE guibg=#00005f')
---end
---
---local function setupMyColors()
--- vim.cmd('augroup MyColors')
--- vim.cmd('autocmd!')
--- vim.cmd('autocmd ColorScheme * call v:lua.MyHighlights()')
--- vim.cmd('augroup END')
---end
---
---setupMyColors()
+local M = {}
---vim.api.nvim_command("highlight FoldColumn guibg=none")
+-- List of preferred colorschemes in order of preference
+local preferred_colorschemes = {
+ 'tokyonight',
+ 'desert',
+ 'default'
+}
---vim.api.nvim_command("highlight SignColumn guifg=none guibg=none cterm=NONE ctermfg=none ctermbg=NONE gui=NONE")
---vim.api.nvim_command("highlight ColorColumn guifg=none guibg=none cterm=NONE ctermfg=none ctermbg=NONE gui=NONE")
---vim.api.nvim_command("highlight TabLineSel guibg=none guifg=none gui=bold")
---vim.api.nvim_command("highlight TabLineNC guibg=none gui=bold")
---vim.api.nvim_command("highlight StatusLine guibg=#333842 gui=bold")
---vim.api.nvim_command("highlight StatusLineNC guibg=none ctermfg=Cyan guifg=#80a0ff gui=bold")
+function M.setup()
+ -- Try each colorscheme in order of preference
+ for _, scheme in ipairs(preferred_colorschemes) do
+ local ok = pcall(vim.cmd, 'colorscheme ' .. scheme)
+ if ok then
+ return true
+ end
+ end
+
+ -- If all else fails, use the built-in default
+ vim.cmd('colorscheme default')
+ return true
+end
--- Custom colorscheme
---vim.cmd([[
--- let g:terminal_color_0 = '#2e3436'
--- let g:terminal_color_1 = '#cc0000'
--- let g:terminal_color_2 = '#4e9a06'
--- let g:terminal_color_3 = '#c4a000'
--- let g:terminal_color_4 = '#3465a4'
--- let g:terminal_color_5 = '#75507b'
--- let g:terminal_color_6 = '#0b939b'
--- let g:terminal_color_7 = '#d3d7cf'
--- let g:terminal_color_8 = '#555753'
--- let g:terminal_color_9 = '#ef2929'
--- let g:terminal_color_10 = '#8ae234'
--- let g:terminal_color_11 = '#fce94f'
--- let g:terminal_color_12 = '#729fcf'
--- let g:terminal_color_13 = '#ad7fa8'
--- let g:terminal_color_14 = '#00f5e9'
--- let g:terminal_color_15 = '#eeeeec'
---
--- set background=dark
--- execute "silent! colorscheme base16-eighties"
--- highlight Comment guifg=#585858
--- highlight Normal guifg=#999999
--- "highlight TabLine guifg=#333333 guibg=#777777
--- "highlight TabLineSel guifg=#FA7F7F
--- highlight MatchParen gui=bold guibg=black guifg=limegreen
---]])
---local colors = {
--- background = '#1c1c1c',
--- foreground = '#cacaca',
--- accent = '#fe5186',
--- blue = '#61afef',
--- cyan = '#3e8fb0',
--- dark_green = '#5faf5f',
--- dark_grey = '#222222',
--- dark_orange = '#ff5d62',
--- dark_red = '#bf1131',
--- dark_yellow = '#ffaf00',
--- green = '#98c379',
--- grey = '#2a2a2a',
--- light_grey = '#727169',
--- light_orange = '#ffa066',
--- light_pink = '#e46876',
--- light_yellow = '#e6db74',
--- magenta = '#c678dd',
--- orange = '#ff8700',
--- purple = '#af87d7',
--- red = '#c4384b',
--- violet = '#a9a1e1',
--- white = '#e3e3e3',
--- yellow = '#d7af5f',
---}
----- Base highlights to override themes to my preferences
---local base = {
--- CursorLine = { bg = 'none', fg = 'none' },
--- -- Avoid changing the foreground color from the main theme
--- MatchParen = { fg = colors.accent, bg = 'none', bold = true },
--- Visual = { bg = colors.grey, fg = 'none' },
--- ActionPreviewBorder = { link = 'XMenuBorder' },
--- ActionPreviewNormal = { link = 'XMenu' },
--- CallHierarchyBorder = { link = 'XMenuBorder' },
--- CallHierarchyNormal = { link = 'XMenu' },
--- CodeActionBorder = { link = 'XMenuBorder' },
--- CodeActionNormal = { link = 'XMenu' },
--- DefinitionBorder = { link = 'XMenuBorder' },
--- DefinitionNormal = { link = 'XMenu' },
--- EndOfBuffer = { fg = colors.background },
--- FinderBorder = { link = 'XMenuBorder' },
--- FinderNormal = { link = 'XMenu' },
--- FloatBorder = { link = 'XMenuBorder' },
--- FloatNormal = { link = 'XMenu' },
--- HoverBorder = { link = 'XMenuBorder' },
--- HoverNormal = { link = 'XMenu' },
--- NormalFloat = { link = 'XMenu' },
--- OutlinePreviewBorder = { link = 'XMenuBorder' },
--- OutlinePreviewNormal = { link = 'XMenu' },
--- Pmenu = { link = 'XMenu' },
--- RenameBorder = { link = 'XMenuBorder' },
--- RenameNormal = { link = 'XMenu' },
--- TerminalBorder = { link = 'XMenuBorder' },
--- TerminalNormal = { link = 'XMenu' },
--- Todo = { fg = colors.orange, bold = true },
--- SagaNormal = { link = 'XMenu' },
--- SagaBorder = { link = 'XMenuBorder' },
--- StatusLine = { bg = colors.background, fg = colors.foreground },
--- TitleString = { link = 'XMenu' },
--- TitleIcon = { link = 'XMenu' },
--- ActionPreviewTitle = { link = 'XMenu' },
--- -- Mason
--- MasonHeader = { link = 'XMenu' },
--- MasonNormal = { link = 'XMenu' },
--- NvimTreeCursorColumn = { bg = 'none', fg = 'none' },
--- --NvimTreeCursorLine = { bg = colors.dark_grey, fg = colors.accent },
--- -- Telescope
--- TelescopeBorder = { link = 'XMenuBorder' },
--- TelescopePromptBorder = { link = 'XMenuBorder' },
--- TelescopePromptNormal = { link = 'XMenu', fg = colors.foreground },
--- TelescopePromptPrefix = { link = 'XMenu', fg = colors.foreground },
--- TelescopeNormal = { bg = colors.background },
--- TelescopePreviewBorder = { link = 'XMenuBorder' },
--- TelescopePreviewNormal = { link = 'XMenu', fg = colors.foreground },
--- TelescopePreviewTitle = { fg = colors.background, bg = colors.light_orange },
--- TelescopePreviewLine = { fg = colors.background, bg = colors.orange },
--- TelescopePromptTitle = { fg = colors.background, bg = colors.light_orange },
--- TelescopeResultsTitle = { fg = colors.background, bg = colors.light_orange },
--- TelescopeResultsBorder = { link = 'XMenuBorder' },
--- TelescopeResultsNormal = { link = 'XMenu' },
---}
---
---local theme = {
--- -- Transparent background
--- Conceal = { bg = 'none', fg = colors.foreground },
--- FoldCoumn = { bg = 'none' },
--- LineNr = { bg = 'none', fg = colors.grey },
--- MsgArea = { bg = 'none', fg = colors.foreground },
--- NonText = { bg = 'none', fg = colors.light_grey },
--- Normal = { bg = 'none', fg = colors.foreground },
--- NormalNC = { bg = 'none', fg = colors.foreground },
--- SignColumn = { bg = 'none' },
--- WinSeparator = { bg = 'none', fg = colors.grey },
--- -- Language Syntax
--- Boolean = { fg = colors.grey },
--- Character = { fg = colors.yellow },
--- Comment = { fg = colors.light_grey },
--- Conditional = { fg = colors.blue },
--- Constant = { fg = colors.grey },
--- Debug = { fg = colors.green },
--- Define = { fg = colors.green },
--- Delimiter = { fg = colors.grey },
--- Error = { fg = colors.red },
--- Exception = { fg = colors.dark_orange },
--- Float = { fg = colors.light_pink },
--- Function = { fg = colors.foreground },
--- Identifier = { fg = colors.foreground },
--- Ignore = { fg = colors.light_grey },
--- Include = { fg = colors.dark_orange },
--- Keyword = { fg = colors.blue },
--- Label = { fg = colors.grey },
--- Macro = { fg = colors.dark_orange },
--- Number = { fg = colors.light_pink },
--- Operator = { fg = colors.purple },
--- PreCondit = { fg = colors.dark_orange },
--- PreProc = { fg = colors.dark_orange },
--- Repeat = { fg = colors.blue },
--- Special = { fg = colors.dark_orange },
--- SpecialChar = { fg = colors.dark_orange },
--- SpecialComment = { fg = colors.orange },
--- Statement = { fg = colors.blue },
--- StorageClass = { fg = colors.light_orange },
--- String = { fg = colors.yellow },
--- Structure = { fg = colors.light_orange },
--- Tag = { fg = colors.orange },
--- Todo = { fg = colors.orange, bold = true },
--- Type = { fg = colors.light_orange },
--- Typedef = { fg = colors.foreground },
--- Underlined = { fg = colors.foreground },
--- -- Rest
--- ColorColumn = { bg = colors.dark_grey },
--- Cursor = { bg = colors.accent },
--- CursorColumn = { bg = 'none', fg = colors.accent },
--- CursorLine = { bg = 'none', fg = 'none' },
--- CursorLineNr = { bg = 'none', fg = colors.light_pink },
--- Directory = { fg = colors.cyan, bold = true },
--- ErrorMsg = { bg = 'none', fg = colors.red },
--- IncSearch = { bg = colors.accent, fg = colors.foreground },
--- MatchParen = { fg = colors.accent, bg = 'none', bold = true },
--- Search = { bg = colors.accent },
--- SpellBad = { bg = 'none', fg = 'none', undercurl = true, ctermbg = 'none', ctermfg = 'none' },
--- SpellLocal = { bg = 'none', fg = 'none', undercurl = true, ctermbg = 'none', ctermfg = 'none' },
--- SpellRare = { bg = 'none', fg = 'none', undercurl = true, ctermbg = 'none', ctermfg = 'none' },
--- StatusLine = { fg = colors.foreground, bg = 'none' },
--- StatusLineNC = { fg = 'none', bg = 'none' },
--- Title = { fg = colors.blue, bg = '', bold = true },
--- VertSplit = { bg = 'none', fg = colors.grey },
--- Visual = { bg = colors.grey, fg = 'none' },
--- -- Diagnostic
--- DiagnosticBorder = { link = 'XMenuBorder' },
--- DiagnosticNormal = { link = 'XMenu' },
--- DiagnosticError = { fg = colors.red },
--- DiagnosticFloatingError = { link = 'XMenu' },
--- DiagnosticFloatingHint = { link = 'XMenu' },
--- DiagnosticFloatingInfo = { link = 'XMenu' },
--- DiagnosticFloatingWarn = { link = 'XMenu' },
--- DiagnosticSignHint = { fg = colors.grey, bold = true, bg = 'none' },
--- DiagnosticUnderlineError = { undercurl = true },
--- DiagnosticVirtualTextHint = { bg = 'none' },
--- DiagnosticWarn = { fg = colors.yellow },
--- -- nvim cmp
--- CmpItemAbbr = { fg = colors.foreground },
--- CmpItemAbbrMatch = { fg = colors.dark_orange },
--- CmpItemAbbrMatchFuzzy = { fg = colors.dark_orange },
--- CmpBorder = { link = 'FloatBorder' },
--- CmpDocBorder = { link = 'FloatBorder' },
--- CmpItemMenuDefault = { link = 'NormalFloat' },
--- CmpMenu = { link = 'NormalFloat' },
--- -- cmp item kinds
--- CmpItemKindConstant = { fg = colors.light_pink },
--- CmpItemKindFunction = { fg = colors.blue },
--- CmpItemKindIdentifier = { fg = colors.purple },
--- CmpItemKindField = { fg = colors.dark_orange },
--- CmpItemKindVariable = { fg = colors.purple },
--- CmpItemKindSnippet = { fg = colors.light_pink },
--- CmpItemKindText = { fg = colors.foreground },
--- CmpItemKindStructure = { fg = colors.blue },
--- CmpItemKindType = { fg = colors.orange },
--- CmpItemKindKeyword = { fg = colors.blue },
--- CmpItemKindMethod = { fg = colors.purple },
--- CmpItemKindConstructor = { fg = colors.blue },
--- CmpItemKindFolder = { fg = colors.blue },
--- CmpItemKindModule = { fg = colors.dark_orange },
--- CmpItemKindProperty = { fg = colors.dark_orange },
--- CmpItemKindEnum = { fg = colors.blue },
--- CmpItemKindUnit = { fg = colors.green },
--- CmpItemKindClass = { fg = colors.blue },
--- CmpItemKindFile = { fg = colors.blue },
--- CmpItemKindInterface = { fg = colors.blue },
--- CmpItemKindColor = { fg = colors.yellow },
--- CmpItemKindReference = { fg = colors.blue },
--- CmpItemKindEnumMember = { fg = colors.green },
--- CmpItemKindStruct = { fg = colors.blue },
--- -- CmpItemKindValue = { fg = "" },
--- -- CmpItemKindEvent = { fg = "" },
--- CmpItemKindOperator = { fg = colors.purple },
--- CmpItemKindTypeParameter = { fg = colors.light_pink },
--- CmpItemKindCopilot = { fg = colors.green },
--- -- LSPSaga
--- OutlinePreviewBorder = { link = 'NormalFloat' },
--- OutlinePreviewNormal = { link = 'FloatBorder' },
--- -- Diffview
--- DiffViewSignColumn = { bg = 'none' },
--- -- Treesitter
--- -- ['@string'] = { fg = colors.yellow, bg = '' },
--- ['@boolean'] = { fg = colors.dark_yellow },
--- ['@character'] = { fg = colors.foreground },
--- ['@character.special'] = { fg = colors.dark_orange },
--- ['@comment'] = { link = 'Comment' },
--- ['@conditional'] = { fg = colors.blue },
--- ['@constant'] = { fg = colors.foreground },
--- ['@constant.builtin'] = { fg = colors.dark_yellow },
--- ['@constant.macro'] = { fg = colors.dark_orange },
--- ['@constructor'] = { fg = colors.blue },
--- ['@debug'] = { link = 'Debug' },
--- ['@define'] = { link = "Define" },
--- ['@exception'] = { fg = colors.dark_orange },
--- ['@field'] = { link = 'Identifier' },
--- ['@field.yaml'] = { fg = colors.light_orange },
--- ['@float'] = { fg = colors.light_pink },
--- ['@function'] = { link = 'Function' },
--- ['@function.builtin'] = { fg = colors.dark_green },
--- ['@function.macro'] = { fg = colors.dark_orange },
--- ['@include'] = { fg = colors.dark_orange },
--- ['@keyword'] = { link = 'Keyword' },
--- ['@keyword.operator'] = { fg = colors.purple },
--- ['@keyword.return'] = { fg = colors.dark_orange },
--- ['@label'] = { fg = colors.blue },
--- ['@macro'] = { fg = colors.dark_orange },
--- ['@method'] = { fg = colors.foreground },
--- ['@namespace'] = { fg = colors.foreground },
--- ['@number'] = { link = 'Number' },
--- ['@operator'] = { link = 'Operator' },
--- ['@parameter'] = { fg = colors.foreground },
--- ['@preproc'] = { link = 'PreProc' },
--- ['@property'] = { fg = colors.foreground },
--- ['@punctuation.Special'] = { fg = colors.purple },
--- ['@punctuation.bracket'] = { fg = colors.purple },
--- ['@punctuation.delimiter'] = { fg = colors.purple },
--- ['@repeat'] = { link = 'Repeat' },
--- ['@storageclass'] = { link = 'StorageClass' },
--- ['@string.escape'] = { fg = colors.dark_orange },
--- ['@string.regex'] = { fg = colors.green },
--- ['@string.special'] = { fg = colors.dark_orange },
--- ['@structure'] = { link = 'Structure' },
--- ['@tag'] = { link = 'Tag' },
--- ['@tag.attribute'] = { fg = colors.foreground },
--- ['@tag.delimiter'] = { fg = colors.purple },
--- ['@text.danger'] = { fg = colors.dark_orange },
--- ['@text.literal'] = { link = 'String' },
--- ['@text.reference'] = { fg = colors.green },
--- ['@text.strong'] = { bold = true },
--- ['@text.title'] = { link = 'Title' },
--- ['@text.todo'] = { link = 'Todo' },
--- ['@text.underline'] = { link = 'Underlined' },
--- ['@text.uri'] = { fg = colors.blue },
--- ['@text.warning'] = { link = 'Todo' },
--- ['@type'] = { link = 'Type' },
--- ['@type.definition'] = { link = 'Typedef' },
--- ['@variable'] = { fg = colors.foreground },
--- ['@variable.builtin'] = { fg = colors.light_orange },
---}
---
---local M = {}
---
---local function _load(config)
--- for group, hl in pairs(config) do
--- if not vim.tbl_isempty(hl) then
--- vim.api.nvim_set_hl(0, group, hl)
--- end
--- end
---end
---
---
---function M.setup()
--- vim.api.nvim_set_hl(0, 'XMenu', { bg = colors.dark_grey, default = true })
--- vim.api.nvim_set_hl(0, 'XMenuBorder', { bg = colors.dark_grey, fg = colors.dark_grey, default = true })
--- vim.g.terminal_color_0 = colors.dark_grey
---end
---
-----function M.load(full)
----- _load(base)
-----
----- if not full then
----- _load_diagnostics()
----- return
----- end
-----
----- _load(theme)
-----end
---
---return M
+return M
diff --git a/common/config/nvim/lua/plugins/comment.lua b/common/config/nvim/lua/plugins/comment.lua
new file mode 100755
index 0000000..392b279
--- /dev/null
+++ b/common/config/nvim/lua/plugins/comment.lua
@@ -0,0 +1,125 @@
+local M = {}
+
+--- Setup and configure comment.nvim
+-- This function initializes and configures the comment plugin
+-- @return boolean True if setup was successful, false otherwise
+function M.setup()
+ local ok, comment = pcall(require, 'Comment')
+ if not ok then
+ vim.notify("Comment.nvim not found", vim.log.levels.WARN)
+ return false
+ end
+
+ -- Configure comment.nvim
+ comment.setup({
+ -- Add a space b/w comment and the line
+ padding = true,
+
+ -- Whether the cursor should stay at its position
+ sticky = true,
+
+ -- Lines to be ignored while (un)commenting
+ ignore = '^$',
+
+ -- LHS of toggle mappings in NORMAL mode
+ toggler = {
+ -- Line-comment toggle keymap
+ line = 'gcc',
+ -- Block-comment toggle keymap
+ block = 'gbc',
+ },
+
+ -- LHS of operator-pending mappings in NORMAL and VISUAL mode
+ opleader = {
+ -- Line-comment keymap
+ line = 'gc',
+ -- Block-comment keymap
+ block = 'gb',
+ },
+
+ -- LHS of extra mappings
+ extra = {
+ -- Add comment on the line above
+ above = 'gcO',
+ -- Add comment on the line below
+ below = 'gco',
+ -- Add comment at the end of line
+ eol = 'gcA',
+ },
+
+ -- Enable keybindings
+ -- NOTE: If given `false` then the plugin won't create any mappings
+ mappings = {
+ -- Operator-pending mapping; `gcc` `gbc` `gc[count]{motion}` `gb[count]{motion}`
+ basic = true,
+ -- Extra mapping; `gco`, `gcO`, `gcA`
+ extra = true,
+ -- Extended mapping; `g>` `g<` `g>[count]{motion}` `g<[count]{motion}`
+ extended = false,
+ },
+
+ -- Function to call before (un)comment
+ pre_hook = nil,
+
+ -- Function to call after (un)comment
+ post_hook = nil,
+ })
+
+ -- Additional keymaps for better UX
+ local keymap = vim.keymap.set
+ local opts = { noremap = true, silent = true }
+
+ -- Toggle comment for current line or visual selection
+ keymap('n', '<leader>cc', '<Plug>(comment_toggle_linewise_current)', opts)
+ keymap('n', '<leader>bc', '<Plug>(comment_toggle_blockwise_current)', opts)
+
+ -- Toggle comment for current line or visual selection and add new line
+ keymap('n', '<leader>cO', '<Plug>(comment_toggle_linewise_above)', opts)
+ keymap('n', '<leader>co', '<Plug>(comment_toggle_linewise_below)', opts)
+
+ -- Toggle comment for visual selection
+ keymap('v', '<leader>cc', '<Plug>(comment_toggle_linewise_visual)', { noremap = false })
+ keymap('v', '<leader>bc', '<Plug>(comment_toggle_blockwise_visual)', { noremap = false })
+
+ -- Filetype specific settings
+ local ft = require('Comment.ft')
+
+ -- Set comment string for specific filetypes
+ ft.set('lua', { '--%s', '--[[%s]]' })
+ ft.set('vim', { '" %s' })
+ ft.set('python', { '# %s', '"""%s"""' })
+ ft.set('javascript', { '// %s', '/*%s*/' })
+ ft.set('typescript', { '// %s', '/*%s*/' })
+ ft.set('css', { '/* %s */' })
+ ft.set('html', { '<!-- %s -->' })
+
+ -- Set up autocommands for specific filetypes
+ local group = vim.api.nvim_create_augroup('CommentCustom', { clear = true })
+
+ -- Disable comment plugin for certain filetypes
+ vim.api.nvim_create_autocmd('FileType', {
+ group = group,
+ pattern = {
+ 'qf', 'help', 'man', 'notify', 'lspinfo', 'packer',
+ 'checkhealth', 'startuptime', 'Trouble', 'alpha', 'dashboard'
+ },
+ callback = function()
+ vim.b.comment_disable = true
+ end,
+ })
+
+ -- Re-enable comment plugin for normal files
+ vim.api.nvim_create_autocmd('FileType', {
+ group = group,
+ pattern = { '*' },
+ callback = function()
+ if vim.bo.buftype == '' then
+ vim.b.comment_disable = nil
+ end
+ end,
+ })
+
+ return true
+end
+
+return M
diff --git a/common/config/nvim/lua/plugins/dap.lua b/common/config/nvim/lua/plugins/dap.lua
index 98ae3fd..7de032c 100644..100755
--- a/common/config/nvim/lua/plugins/dap.lua
+++ b/common/config/nvim/lua/plugins/dap.lua
@@ -1,4 +1,10 @@
-local dap = require("dap")
+local M = {}
+
+function M.setup()
+ local ok, dap = pcall(require, "dap")
+ if not ok or not dap then
+ return false
+ end
-- options
dap.defaults.fallback.switchbuf = "uselast"
@@ -155,11 +161,12 @@ local dapui = require("dapui")
--})
-- Load dapui configuration only if it hasn't been loaded before
-if not vim.g.loaded_dapui then
- require("dapui").setup({
- mappings = {
- expand = "<CR>",
- open = "o",
+ local dapui_ok, dapui = pcall(require, "dapui")
+ if dapui_ok and dapui then
+ dapui.setup({
+ mappings = {
+ expand = "<CR>",
+ open = "o",
remove = "D",
edit = "e",
repl = "r",
@@ -240,14 +247,19 @@ end
require("nvim-dap-virtual-text").setup({
enabled = true,
enabled_commands = true,
- highlight_changed_variables = true,
- highlight_new_as_changed = false,
- show_stop_reason = true,
- commented = true,
- only_first_definition = true,
- all_references = false,
- filter_references_pattern = "<module",
- virt_text_pos = "eol",
- all_frames = false,
- virt_text_win_col = nil,
-})
+ highlight_changed_variables = true,
+ highlight_new_as_changed = false,
+ show_stop_reason = true,
+ commented = true,
+ only_first_definition = true,
+ all_references = false,
+ filter_references_pattern = "<module",
+ virt_text_pos = "eol",
+ all_frames = false,
+ virt_text_win_col = nil,
+ })
+
+ return true
+end
+
+return M
diff --git a/common/config/nvim/lua/plugins/dashboard.lua b/common/config/nvim/lua/plugins/dashboard.lua
index f02242c..43a3461 100644..100755
--- a/common/config/nvim/lua/plugins/dashboard.lua
+++ b/common/config/nvim/lua/plugins/dashboard.lua
@@ -1,11 +1,31 @@
-local db = require('dashboard')
-local messages = require('plugins.messages')
+local M = {}
-function GetRandomMessage()
- -- Get a random index from the messages array
- local randomIndex = math.random(1, #messages)
- return messages[randomIndex]
-end
+--- Setup and configure dashboard.nvim
+-- This function initializes and configures the dashboard plugin
+-- @return boolean True if setup was successful, false otherwise
+function M.setup()
+ local ok, db = pcall(require, 'dashboard')
+ if not ok then
+ return false
+ end
+
+ local messages = {
+ "The only way to do great work is to love what you do. - Steve Jobs",
+ "Code is like humor. When you have to explain it, it's bad. - Cory House",
+ "First, solve the problem. Then, write the code. - John Johnson",
+ "Any fool can write code that a computer can understand. Good programmers write code that humans can understand. - Martin Fowler",
+ "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay",
+ "The most important property of a program is whether it accomplishes the intention of its user. - C.A.R. Hoare",
+ "The best error message is the one that never shows up. - Thomas Fuchs",
+ "The most important skill for a programmer is the ability to effectively communicate ideas. - Gastón Jorquera",
+ "The only way to learn a new programming language is by writing programs in it. - Dennis Ritchie",
+ "The most damaging phrase in the language is 'We've always done it this way!' - Grace Hopper"
+ }
+
+ local function get_random_message()
+ local random_index = math.random(1, #messages)
+ return messages[random_index]
+ end
--vim.api.nvim_create_autocmd("VimEnter", {
-- callback = function()
@@ -16,10 +36,11 @@ end
-- end,
--})
-db.setup({
- theme = 'hyper',
+ -- Configure dashboard
+ db.setup({
+ theme = "hyper",
config = {
- mru = { limit = 10, label = '' },
+ mru = { limit = 20, label = "" },
project = { limit = 10 },
header = {
[[ ███╗ ██╗ ███████╗ ██████╗ ██╗ ██╗ ██╗ ███╗ ███╗]],
@@ -31,46 +52,47 @@ db.setup({
},
disable_move = false,
shortcut = {
- { desc = ' Plugins', group = 'Number', action = 'PackerStatus', key = 'p' },
- --{ desc = " Plugins", group = "@property", action = "PackerStatus", key = "p" },
+ { desc = " Plugins", group = "Number", action = "PackerStatus", key = "p" },
+ {
+ desc = " Files",
+ group = "Number",
+ action = "Telescope find_files",
+ key = "f",
+ },
{
- desc = ' Files',
- group = 'Number',
- --group = "Label",
- action = 'Telescope find_files',
- key = 'f',
+ desc = " TODO",
+ group = "Number",
+ action = ":edit ~/documents/main/inbox/tasks/TODO.md",
+ key = "t",
},
{
- desc = ' Text',
- group = 'Number',
- --group = "Label",
- action = 'enew',
- key = 't',
+ desc = " New",
+ group = "Number",
+ action = "enew",
+ key = "e",
},
{
- desc = ' Grep',
- group = 'Number',
- --group = "Label",
- action = 'Telescope live_grep',
- key = 'g',
+ desc = " Grep",
+ group = "Number",
+ action = "Telescope live_grep",
+ key = "g",
},
{
- desc = ' Scheme',
- group = 'Number',
- --group = "Label",
- action = 'Telescope colorscheme',
- key = 's',
+ desc = " Scheme",
+ group = "Number",
+ action = "Telescope colorscheme",
+ key = "s",
},
{
- desc = ' Config',
- group = 'Number',
- --group = "Label",
- action = ':edit ~/.config/nvim/init.lua',
- key = 'c',
+ desc = " Config",
+ group = "Number",
+ action = ":edit ~/.config/nvim/init.lua",
+ key = "c",
},
},
footer = function()
- return { '', GetRandomMessage() }
+ return { "", "" }
+ --return { "", GetRandomMessage() }
end,
},
hide = {
@@ -80,7 +102,16 @@ db.setup({
},
})
---highlights
+-- Set keymaps only when dashboard is active
+vim.api.nvim_create_autocmd("FileType", {
+ group = vim.api.nvim_create_augroup("DashboardMappings", { clear = true }),
+ pattern = "dashboard",
+ callback = function()
+ vim.keymap.set("n", "e", "<Cmd>DashboardNewFile<CR>", { buffer = true })
+ vim.keymap.set("n", "q", "<Cmd>q!<CR>", { buffer = true })
+ vim.keymap.set("n", "<C-o>", "<C-o><C-o>", { buffer = true }) -- Allow Ctrl + o to act normally
+ end,
+})
---- General
--DashboardHeader DashboardFooter
---- Hyper theme
@@ -88,3 +119,8 @@ db.setup({
--DashboardMruTitle DashboardMruIcon DashboardFiles DashboardShotCutIcon
---- Doome theme
--DashboardDesc DashboardKey DashboardIcon DashboardShotCut
+
+ return true
+end
+
+return M
diff --git a/common/config/nvim/lua/plugins/fidget.lua b/common/config/nvim/lua/plugins/fidget.lua
index d401c5f..d401c5f 100644..100755
--- a/common/config/nvim/lua/plugins/fidget.lua
+++ b/common/config/nvim/lua/plugins/fidget.lua
diff --git a/common/config/nvim/lua/plugins/friendly-snippets.lua b/common/config/nvim/lua/plugins/friendly-snippets.lua
new file mode 100755
index 0000000..2a7695e
--- /dev/null
+++ b/common/config/nvim/lua/plugins/friendly-snippets.lua
@@ -0,0 +1,3 @@
+-- friendly-snippets plugin config (modular, robust)
+local ok, _ = pcall(require, 'friendly-snippets')
+-- No config needed, loaded by LuaSnip \ No newline at end of file
diff --git a/common/config/nvim/lua/plugins/fugitive.lua b/common/config/nvim/lua/plugins/fugitive.lua
new file mode 100755
index 0000000..22620e3
--- /dev/null
+++ b/common/config/nvim/lua/plugins/fugitive.lua
@@ -0,0 +1,8 @@
+local M = {}
+
+function M.setup()
+ -- No-op if fugitive is not installed
+ return true
+end
+
+return M
diff --git a/common/config/nvim/lua/plugins/fzf.lua b/common/config/nvim/lua/plugins/fzf.lua
index 5675e9f..9e62c48 100644..100755
--- a/common/config/nvim/lua/plugins/fzf.lua
+++ b/common/config/nvim/lua/plugins/fzf.lua
@@ -1,60 +1,43 @@
---vim.cmd([[
--- let g:fzf_history_dir = '~/.local/share/fzf-history'
--- map <leader>z :FZF<CR>
--- map <leader>a :Files<CR>
--- map <leader>l :Lines<CR>
--- map <leader>L :BLines<CR>
--- map <leader>B :Buffers<CR>
--- map <leader>h :History:<CR>
--- nnoremap <leader>g :Rg<CR>
--- "nnoremap <leader>t :Tags<CR>
--- nnoremap <leader>m :Marks<CR>
--- " This is the default extra key bindings
--- let g:fzf_action = {
--- \ 'ctrl-t': 'tab split',
--- \ 'ctrl-x': 'split',
--- \ 'ctrl-y': 'vsplit' }
--- let g:fzf_tags_command = 'ctags -R'
--- " Border color
--- let g:fzf_layout = {'up':'~90%', 'window': { 'width': 0.8, 'height': 0.8,'yoffset':0.5,'xoffset': 0.5, 'highlight': 'Todo', 'border': 'sharp' } }
--- let $FZF_DEFAULT_OPTS = '--layout=reverse --info=inline'
--- let $FZF_DEFAULT_COMMAND="rg --files --hidden"
--- " Customize fzf colors to match your color scheme
--- let g:fzf_colors =
--- \ { 'fg': ['fg', 'Normal'],
--- \ 'bg': ['bg', 'Normal'],
--- \ 'hl': ['fg', 'Comment'],
--- \ 'fg+': ['fg', 'CursorLine', 'CursorColumn', 'Normal'],
--- \ 'bg+': ['bg', 'CursorLine', 'CursorColumn'],
--- \ 'hl+': ['fg', 'Statement'],
--- \ 'info': ['fg', 'PreProc'],
--- \ 'border': ['fg', 'Ignore'],
--- \ 'prompt': ['fg', 'Conditional'],
--- \ 'pointer': ['fg', 'Exception'],
--- \ 'marker': ['fg', 'Keyword'],
--- \ 'spinner': ['fg', 'Label'],
--- \ 'header': ['fg', 'Comment'] }
--- " Get Files
--- command! -bang -nargs=? -complete=dir Files
--- \ call fzf#vim#files(<q-args>, fzf#vim#with_preview({'options': ['--layout=reverse', '--info=inline']}), <bang>0)
--- " Get text in files with Rg
--- command! -bang -nargs=* Rg
--- \ call fzf#vim#grep(
--- \ 'rg --column --line-number --no-heading --color=always --smart-case '.shellescape(<q-args>), 1,
--- \ fzf#vim#with_preview(), <bang>0)
--- " Ripgrep advanced
--- function! RipgrepFzf(query, fullscreen)
--- let command_fmt = 'rg --column --line-number --no-heading --color=always --smart-case %s || true'
--- let initial_command = printf(command_fmt, shellescape(a:query))
--- let reload_command = printf(command_fmt, '{q}')
--- let spec = {'options': ['--phony', '--query', a:query, '--bind', 'change:reload:'.reload_command]}
--- call fzf#vim#grep(initial_command, 1, fzf#vim#with_preview(spec), a:fullscreen)
--- endfunction
--- command! -nargs=* -bang RG call RipgrepFzf(<q-args>, <bang>0)
--- " Git grep
--- command! -bang -nargs=* GGrep
--- \ call fzf#vim#grep(
--- \ 'git grep --line-number '.shellescape(<q-args>), 0,
--- \ fzf#vim#with_preview({'dir': systemlist('git rev-parse --show-toplevel')[0]}), <bang>0)
--- command! -bang FM call fzf#run(fzf#wrap({'source': 'cat ~/.fzf-marks | sed "s/.*: \(.*\)$/\1/" | sed "s#~#${HOME}#"', 'sink': 'lcd'}, <bang>0))
---]])
+local M = {}
+
+if not fzfLua then
+ return M
+end
+
+local ok_fzfLua, actions = pcall(require, "fzf-lua")
+if not ok_fzfLua then
+ return
+end
+
+local ok_fzfLua, actions = pcall(require, "fzf-lua.actions")
+if not ok_fzfLua then
+ return
+end
+
+
+local ok, fzfLua = pcall(require, "fzf-lua")
+if not ok then
+ vim.notify("fzf-lua not found", vim.log.levels.WARN)
+ return M
+end
+
+fzfLua.setup({
+ defaults = {
+ file_icons = "mini",
+ },
+ winopts = {
+ row = 0.5,
+ height = 0.7,
+ },
+ files = {
+ previewer = false,
+ },
+})
+
+vim.keymap.set("n", "<leader>fz", "<cmd>FzfLua files<cr>", { desc = "Fuzzy find files" })
+vim.keymap.set("n", "<leader>fzg", "<cmd>FzfLua live_grep<cr>", { desc = "Fuzzy grep files" })
+vim.keymap.set("n", "<leader>fzh", "<cmd>FzfLua helptags<cr>", { desc = "Fuzzy grep tags in help files" })
+vim.keymap.set("n", "<leader>fzt", "<cmd>FzfLua btags<cr>", { desc = "Fuzzy search buffer tags" })
+vim.keymap.set("n", "<leader>fzb", "<cmd>FzfLua buffers<cr>", { desc = "Fuzzy search opened buffers" })
+
+return M
diff --git a/common/config/nvim/lua/plugins/git.lua b/common/config/nvim/lua/plugins/git.lua
new file mode 100755
index 0000000..24a0871
--- /dev/null
+++ b/common/config/nvim/lua/plugins/git.lua
@@ -0,0 +1,8 @@
+local M = {}
+
+function M.setup()
+ -- No-op if git plugin is not installed
+ return true
+end
+
+return M
diff --git a/common/config/nvim/lua/plugins/gitsigns.lua b/common/config/nvim/lua/plugins/gitsigns.lua
index 8fbdae1..7bbe637 100644..100755
--- a/common/config/nvim/lua/plugins/gitsigns.lua
+++ b/common/config/nvim/lua/plugins/gitsigns.lua
@@ -1,4 +1,15 @@
-require("gitsigns").setup({
+local M = {}
+
+--- Setup and configure gitsigns
+-- This function initializes and configures the git signs in the gutter
+-- @return boolean True if setup was successful, false otherwise
+function M.setup()
+ local ok, gitsigns = pcall(require, 'gitsigns')
+ if not ok then
+ return false
+ end
+
+ gitsigns.setup({
signs = {
--add = {
-- hl = "GitSignsAdd",
@@ -45,3 +56,30 @@ hi link GitSignsDelete DiffDelete
hi link GitSignsTopDelete DiffDelete
hi link GitSignsChangedDelete DiffDelete
]])
+ -- Set up highlights
+ vim.cmd([[
+ highlight DiffAdd guibg=none guifg=#21c7a8
+ highlight DiffModified guibg=none guifg=#82aaff
+ highlight DiffDelete guibg=none guifg=#fc514e
+ highlight DiffText guibg=none guifg=#fc514e
+
+ hi link GitSignsAdd DiffAdd
+ hi link GitSignsChange DiffModified
+ hi link GitSignsDelete DiffDelete
+ hi link GitSignsTopDelete DiffDelete
+ hi link GitSignsChangedelete DiffDelete
+ hi link GitSignsChangedeleteLn DiffDelete
+ hi link GitSignsChangedeleteNr DiffDeleteNr
+ ]])
+
+ return true
+end
+
+return M
+--'signs.delete.hl' is now deprecated, please define highlight 'GitSignsDelete'
+--'signs.delete.linehl' is now deprecated, please define highlight 'GitSignsDeleteLn'
+--'signs.delete.numhl' is now deprecated, please define highlight 'GitSignsDeleteNr'
+--'signs.topdelete.hl' is now deprecated, please define highlight 'GitSignsTopdelete'
+--'signs.topdelete.linehl' is now deprecated, please define highlight 'GitSignsTopdeleteLn'
+--'signs.topdelete.numhl' is now deprecated, please define highlight 'GitSignsTopdeleteNr'
+
diff --git a/common/config/nvim/lua/plugins/goto-preview.lua b/common/config/nvim/lua/plugins/goto-preview.lua
index d4d2c67..eb54a8c 100644..100755
--- a/common/config/nvim/lua/plugins/goto-preview.lua
+++ b/common/config/nvim/lua/plugins/goto-preview.lua
@@ -1,4 +1,12 @@
-require('goto-preview').setup {
+local M = {}
+
+function M.setup()
+ local ok, gp = pcall(require, 'goto-preview')
+ if not ok or not gp then
+ return false
+ end
+
+ gp.setup {
width = 120; -- Width of the floating window
height = 15; -- Height of the floating window
border = {"↖", "─" ,"┐", "│", "┘", "─", "└", "│"}; -- Border characters of the floating window
@@ -14,5 +22,10 @@ require('goto-preview').setup {
focus_on_open = true; -- Focus the floating window when opening it.
dismiss_on_move = false; -- Dismiss the floating window when moving the cursor.
force_close = true, -- passed into vim.api.nvim_win_close's second argument. See :h nvim_win_close
- bufhidden = "wipe", -- the bufhidden option to set on the floating window. See :h bufhidden
-}
+ bufhidden = "wipe", -- the bufhidden option to set on the floating window. See :h bufhidden
+ }
+
+ return true
+end
+
+return M
diff --git a/common/config/nvim/lua/plugins/hardtime.lua b/common/config/nvim/lua/plugins/hardtime.lua
index cb03468..b440334 100644..100755
--- a/common/config/nvim/lua/plugins/hardtime.lua
+++ b/common/config/nvim/lua/plugins/hardtime.lua
@@ -1,26 +1,26 @@
-local hardtime = require('hardtime')
+-- Function to toggle the hardtime state and echo a message
+local hardtime_enabled = true
+
+local hardtime = require("hardtime")
hardtime.setup({
-- hardtime config here
enabled = true,
- restriction_mode = 'hint',
- disabled_filetypes = { 'qf', 'netrw', 'NvimTree', 'NvimTree_1', 'lazy', 'mason', 'oil', 'dashboard' },
+ restriction_mode = "hint",
+ disabled_filetypes = { "qf", "netrw", "NvimTree", "NvimTree_1", "lazy", "mason", "oil", "dashboard" },
disable_mouse = false,
disabled_keys = {
- ['<Up>'] = {},
- ['<Down>'] = {},
- ['<Left>'] = {},
- ['<Right>'] = {},
+ ["<Up>"] = {},
+ ["<Down>"] = {},
+ ["<Left>"] = {},
+ ["<Right>"] = {},
},
})
--- Function to toggle the hardtime state and echo a message
-local hardtime_enabled = true
-
function ToggleHardtime()
hardtime.toggle()
hardtime_enabled = not hardtime_enabled
- local message = hardtime_enabled and 'hardtime on' or 'hardtime off'
+ local message = hardtime_enabled and "hardtime on" or "hardtime off"
vim.cmd('echo "' .. message .. '"')
end
diff --git a/common/config/nvim/lua/plugins/harpoon.lua b/common/config/nvim/lua/plugins/harpoon.lua
index 784ee0b..8e842b3 100644..100755
--- a/common/config/nvim/lua/plugins/harpoon.lua
+++ b/common/config/nvim/lua/plugins/harpoon.lua
@@ -1,4 +1,12 @@
-require("harpoon").setup({
+local M = {}
+
+function M.setup()
+ local ok, harpoon = pcall(require, "harpoon")
+ if not ok or not harpoon then
+ return false
+ end
+
+ harpoon.setup({
menu = {
width = vim.api.nvim_win_get_width(0) - 4,
},
@@ -12,18 +20,26 @@ require("harpoon").setup({
-- --{ "<leader>4", function() require("harpoon.term").gotoTerminal(2) end, desc = "Terminal 2" },
-- --{ "<leader>5", function() require("harpoon.term").sendCommand(1,1) end, desc = "Command 1" },
-- --{ "<leader>6", function() require("harpoon.term").sendCommand(1,2) end, desc = "Command 2" },
- --},
-})
-vim.api.nvim_set_keymap("n", "<leader>ma", ":lua require('harpoon.mark').add_file()<CR>", {})
-vim.api.nvim_set_keymap("n", "<leader>mt", ":lua require('harpoon.mark').toggle_file()<CR>", {})
-vim.api.nvim_set_keymap("n", "<leader>mq", ":lua require('harpoon.ui').toggle_quick_menu()<CR>", {})
-vim.api.nvim_set_keymap("n", "<leader>mh", ":lua require('harpoon.ui').nav_file(1)<CR>", {})
-vim.api.nvim_set_keymap("n", "<leader>mj", ":lua require('harpoon.ui').nav_file(2)<CR>", {})
-vim.api.nvim_set_keymap("n", "<leader>mk", ":lua require('harpoon.ui').nav_file(3)<CR>", {})
-vim.api.nvim_set_keymap("n", "<leader>ml", ":lua require('harpoon.ui').nav_file(4)<CR>", {})
+ })
+
+ -- Set up keymaps safely
+ local function safe_keymap(mode, lhs, rhs, opts)
+ local opts_with_noremap = vim.tbl_extend('force', {noremap = true, silent = true}, opts or {})
+ vim.keymap.set(mode, lhs, rhs, opts_with_noremap)
+ end
+
+ safe_keymap("n", "<leader>ma", function() require('harpoon.mark').add_file() end, { desc = "Harpoon: Add file" })
+ safe_keymap("n", "<leader>mt", function() require('harpoon.mark').toggle_file() end, { desc = "Harpoon: Toggle file" })
+ safe_keymap("n", "<leader>mq", function() require('harpoon.ui').toggle_quick_menu() end, { desc = "Harpoon: Toggle quick menu" })
+ safe_keymap("n", "<leader>mh", function() require('harpoon.ui').nav_file(1) end, { desc = "Harpoon: Navigate to file 1" })
+ safe_keymap("n", "<leader>mj", function() require('harpoon.ui').nav_file(2) end, { desc = "Harpoon: Navigate to file 2" })
+ safe_keymap("n", "<leader>mk", function() require('harpoon.ui').nav_file(3) end, { desc = "Harpoon: Navigate to file 3" })
+ safe_keymap("n", "<leader>ml", function() require('harpoon.ui').nav_file(4) end, { desc = "Harpoon: Navigate to file 4" })
+
+ return true
+end
---local mark = require("harpoon.mark")
---local ui = require("harpoon.ui")
+return M
--
--vim.keymap.set("n", "<leader>a", mark.add_file)
--vim.keymap.set("n", "<C-e>", ui.toggle_quick_menu)
diff --git a/common/config/nvim/lua/plugins/heirline.lua b/common/config/nvim/lua/plugins/heirline.lua
index c41aff3..a4c2fc3 100644..100755
--- a/common/config/nvim/lua/plugins/heirline.lua
+++ b/common/config/nvim/lua/plugins/heirline.lua
@@ -1,1290 +1,1497 @@
-local conditions = require('heirline.conditions')
-local utils = require('heirline.utils')
-
-local colors = {
- --bg = "#23232e",
- bg = nil,
- nobg = 'NONE',
- white = '#f8f8f2',
- black = '#000000',
- darkgray = '#23232e',
- gray = '#2d2b3a',
- lightgray = '#d6d3ea',
- pink = '#f92672',
- green = '#50fa7b',
- blue = '#39BAE6',
- yellow = '#f1fa8c',
- orange = '#ffb86c',
- purple = '#BF40BF',
- violet = '#7F00FF',
- red = '#ff5555',
- cyan = '#66d9eC',
- diag = {
- warn = utils.get_highlight('DiagnosticSignWarn').fg,
- error = utils.get_highlight('DiagnosticSignError').fg,
- hint = utils.get_highlight('DiagnosticSignHint').fg,
- info = utils.get_highlight('DiagnosticSignInfo').fg,
- },
- git = {
- active = '#f34f29',
- del = '#ff5555',
- add = '#50fa7b',
- change = '#ae81ff',
- },
-}
-
-require('heirline').load_colors(colors)
-
-local Align = { provider = '%=', hl = { bg = colors.bg } }
-local Space = { provider = ' ', hl = { bg = colors.bg } }
-local Tab = { provider = ' ' }
-local LeftSpace = { provider = '' }
-local RightSpace = { provider = '' }
-
-local ViMode = {
- init = function(self)
- self.mode = vim.fn.mode(1)
- --if not self.once then
- -- vim.cmd("au ModeChanged *:*o redrawstatus")
- --end
- --self.once = true
- end,
- static = {
- mode_names = {
- n = ' NORMAL ',
- no = 'PENDING ',
- nov = ' N? ',
- noV = ' N? ',
- ['no\22'] = ' N? ',
- niI = ' Ni ',
- niR = ' Nr ',
- niV = ' Nv ',
- nt = 'TERMINAL',
- v = ' VISUAL ',
- vs = ' Vs ',
- V = ' V·LINE ',
- ['\22'] = 'V·BLOCK ',
- ['\22s'] = 'V·BLOCK ',
- s = ' SELECT ',
- S = ' S·LINE ',
- ['\19'] = 'S·BLOCK ',
- i = ' INSERT ',
- ix = 'insert x',
- ic = 'insert c',
- R = 'REPLACE ',
- Rc = ' Rc ',
- Rx = ' Rx ',
- Rv = 'V·REPLACE ',
- Rvc = ' Rv ',
- Rvx = ' Rv ',
- c = 'COMMAND ',
- cv = ' VIM EX ',
- ce = ' EX ',
- r = ' PROMPT ',
- rm = ' MORE ',
- ['r?'] = 'CONFIRM ',
- ['!'] = ' SHELL ',
- t = 'TERMINAL',
+local M = {}
+
+-- Safe require function to handle missing dependencies
+local function safe_require(module)
+ local ok, result = pcall(require, module)
+ return ok and result or nil
+end
+
+-- These will be initialized in M.setup()
+local heirline = nil
+local conditions = {}
+local utils = {}
+local colors = {}
+
+function M.setup()
+ heirline = safe_require("heirline")
+ if not heirline then
+ return
+ end
+
+ -- Initialize conditions and utils after heirline is loaded
+ conditions = require("heirline.conditions") or {}
+ utils = require("heirline.utils") or {}
+
+
+ -- Initialize colors after safe_fg is defined
+ colors = {
+ bg = "NONE",
+ nobg = "NONE",
+ white = "#f8f8f2",
+ black = "#000000",
+ darkgray = "#23232e",
+ gray = "#2d2b3a",
+ lightgray = "#d6d3ea",
+ pink = "#f92672",
+ green = "#50fa7b",
+ blue = "#39BAE6",
+ yellow = "#f1fa8c",
+ orange = "#ffb86c",
+ purple = "#BF40BF",
+ violet = "#7F00FF",
+ red = "#ff5555",
+ cyan = "#66d9eC",
+ --diag = {
+ -- warn = safe_fg("DiagnosticSignWarn", "#ffb86c"),
+ -- error = safe_fg("DiagnosticSignError", "#ff5555"),
+ -- hint = safe_fg("DiagnosticSignHint", "#50fa7b"),
+ -- info = safe_fg("DiagnosticSignInfo", "#66d9eC"),
+ --},
+ diag = {
+ warn = utils.get_highlight("DiagnosticSignWarn").fg,
+ error = utils.get_highlight("DiagnosticSignError").fg,
+ hint = utils.get_highlight("DiagnosticSignHint").fg,
+ info = utils.get_highlight("DiagnosticSignInfo").fg,
},
- },
- provider = function(self)
- return ' %2(' .. self.mode_names[self.mode] .. '%) '
- end,
- hl = function(self)
- return { fg = 'colors.black', bg = self.mode_color, bold = true }
- end,
- update = {
- 'ModeChanged',
- 'VimEnter',
- pattern = '*:*',
- callback = vim.schedule_wrap(function()
- vim.cmd('redrawstatus')
- end),
- },
-}
-
--- LSP
-local LSPActive = {
- condition = conditions.lsp_attached,
- update = { 'LspAttach', 'LspDetach' },
- provider = function()
- local buf_clients = vim.lsp.buf_get_clients()
- local buf_client_names = {}
-
- -- add client
- for _, client in pairs(buf_clients) do
- if client.name ~= 'null-ls' then
- table.insert(buf_client_names, client.name)
+ git = {
+ active = "#f34f29",
+ del = "#ff5555",
+ add = "#50fa7b",
+ change = "#ae81ff",
+ },
+ }
+
+ -- Only load colors if heirline is available
+ if heirline.load_colors then
+ local ok, err = pcall(heirline.load_colors, colors)
+ if not ok then
+ vim.notify("Failed to load Heirline colors: " .. tostring(err), vim.log.levels.ERROR)
+ end
+ end
+
+ local function get_icon(icon, fallback)
+ -- Check if we have Nerd Fonts available
+ local has_nerd_fonts = vim.g.statusline_has_nerd_fonts
+ if has_nerd_fonts == nil then
+ -- Cache the result to avoid repeated checks
+ if vim.fn.has('unix') == 1 and vim.fn.executable('fc-list') == 1 then
+ local handle = io.popen('fc-list | grep -i nerd')
+ local result = handle:read('*a')
+ handle:close()
+ has_nerd_fonts = result ~= ""
+ else
+ -- On non-Unix systems or if fc-list isn't available, assume no Nerd Fonts
+ has_nerd_fonts = false
end
+ vim.g.statusline_has_nerd_fonts = has_nerd_fonts
end
- return '⚙️ ' .. table.concat(buf_client_names, '')
- end,
- hl = { fg = colors.lightgray, bold = false },
-}
-local Navic = {
- condition = function()
- return require('nvim-navic').is_available()
- end,
- static = {
- -- create a type highlight map
- type_hl = {
- File = 'Directory',
- Module = '@include',
- Namespace = '@namespace',
- Package = '@include',
- Class = '@structure',
- Method = '@method',
- Property = '@property',
- Field = '@field',
- Constructor = '@constructor',
- Enum = '@field',
- Interface = '@type',
- Function = '@function',
- Variable = '@variable',
- Constant = '@constant',
- String = '@string',
- Number = '@number',
- Boolean = '@boolean',
- Array = '@field',
- Object = '@type',
- Key = '@keyword',
- Null = '@comment',
- EnumMember = '@field',
- Struct = '@structure',
- Event = '@keyword',
- Operator = '@operator',
- TypeParameter = '@type',
+
+ -- Return the appropriate string based on font availability
+ local result = has_nerd_fonts and icon or (fallback or '')
+ -- Trim any whitespace to prevent layout issues
+ return vim.trim(result)
+ end
+
+ -- Define all components after colors and utils are initialized
+
+ --local Signs = {
+ -- Error = "✘",
+ -- Warn = "",
+ -- Hint = "◉",
+ -- Info = "",
+ --}
+ local Icons = {
+ Signs = {
+ Error = "✘",
+ Warn = "",
+ Hint = "◉",
+ Info = "",
+ LSP = get_icon("⚙️", "LSP"),
},
- -- bit operation dark magic, see below...
- enc = function(line, col, winnr)
- return bit.bor(bit.lshift(line, 16), bit.lshift(col, 6), winnr)
+ ---- LSP/Debug
+ Error = get_icon("✘", "E"),
+ Warn = get_icon("", "W"),
+ Hint = get_icon("◉", "H"),--
+ Info = get_icon("ℹ", "I"),
+ --LSP = get_icon("⚙️", "LSP"),
+
+ -- Diagnostic
+ Diagnostic = {
+ error = get_icon("✘", "E"),
+ warn = get_icon("", "W"),
+ hint = get_icon("", "H"),
+ info = get_icon("ℹ", "I"),
+ },
+
+
+--local GitIcons = {
+-- added = "✚", -- plus in diff style
+-- modified = "", -- nf-oct-diff_modified
+-- removed = "", -- nf-oct-diff_removed
+--}
+--added = "", -- nf-oct-diff_added
+--modified = "", -- nf-oct-diff_modified
+--removed = "", -- nf-oct-diff_removed
+--local GitIcons = {
+-- added = "", -- nf-fa-plus_square
+-- modified = "", -- nf-fa-file_text_o
+-- removed = "", -- nf-fa-minus_square
+--}
+ -- Git
+ Git = {
+ branch = get_icon(" ", "⎇ "),
+ added = get_icon("+ ", "+"),
+ removed = get_icon("- ", "-"),
+ modified = get_icon("~ ", "~"),
+ renamed = get_icon("", "r"),
+ untracked = get_icon("", "?"),
+ ignored = get_icon("", "."),
+ },
+
+ -- UI Elements
+ UI = {
+ left_separator = get_icon("", ""),
+ right_separator = get_icon("", ""),
+ thin_separator = get_icon("▏", "|"),
+ ellipsis = get_icon("…", "..."),
+ arrow_left = get_icon("◀", "<"),
+ arrow_right = get_icon("▶", ">"),
+ close = get_icon("✕", "x"),
+ big_close = get_icon(" ", "x "),
+ modified = get_icon(" + ", "*"),
+ readonly = get_icon("", "RO"),
+ lock = get_icon("", "[L]"),
+ clock = get_icon("🕒", "[TIME]"),
+ buffer = get_icon("", "[BUF]"),
+ tab = get_icon("", "[TAB]"),
+ search = get_icon("🔍", "[SEARCH]"),
+ spell = get_icon("暈", "[SPELL]"),
+ whitespace = get_icon("␣", "[WS]"),
+ newline = get_icon("↵", "[NL]"),
+ indent = get_icon("▏", "|"),
+ fold = get_icon("", ">"),
+ fold_open = get_icon("", "v"),
+ fold_closed = get_icon("", ">"),
+ },
+
+ -- File types
+ File = {
+ default = get_icon("", "[F]"),
+ directory = get_icon("", "[D]"),
+ symlink = get_icon("", "[L]"),
+ executable = get_icon("", "[X]"),
+ image = get_icon("", "[IMG]"),
+ archive = get_icon("", "[ARC]"),
+ audio = get_icon("", "[AUD]"),
+ video = get_icon("", "[VID]"),
+ document = get_icon("", "[DOC]"),
+ config = get_icon("", "[CFG]"),
+ code = get_icon("", "[CODE]"),
+ terminal = get_icon("", "[TERM]"),
+ },
+
+ -- File format indicators
+ Format = {
+ unix = get_icon("", "[UNIX]"),
+ dos = get_icon("", "[DOS]"),
+ mac = get_icon("", "[MAC]"),
+ },
+
+ -- Version control
+ VCS = {
+ branch = get_icon("", "[BR]"),
+ git = get_icon("", "[GIT]"),
+ github = get_icon("", "[GH]"),
+ gitlab = get_icon("", "[GL]"),
+ bitbucket = get_icon("", "[BB]"),
+ },
+
+ -- Programming languages
+ Lang = {
+ lua = get_icon("", "[LUA]"),
+ python = get_icon("", "[PY]"),
+ javascript = get_icon("", "[JS]"),
+ typescript = get_icon("", "[TS]"),
+ html = get_icon("", "[HTML]"),
+ css = get_icon("", "[CSS]"),
+ json = get_icon("", "[JSON]"),
+ markdown = get_icon("", "[MD]"),
+ docker = get_icon("", "[DKR]"),
+ rust = get_icon("", "[RS]"),
+ go = get_icon("", "[GO]"),
+ java = get_icon("", "[JAVA]"),
+ c = get_icon("", "[C]"),
+ cpp = get_icon("", "[C++]"),
+ ruby = get_icon("", "[RB]"),
+ php = get_icon("", "[PHP]"),
+ haskell = get_icon("", "[HS]"),
+ scala = get_icon("", "[SCALA]"),
+ elixir = get_icon("", "[EXS]"),
+ clojure = get_icon("", "[CLJ]"),
+ },
+
+ -- UI Indicators
+ Indicator = {
+ error = get_icon("✘", "[E]"),
+ warning = get_icon("⚠", "[W]"),
+ info = get_icon("ℹ", "[I]"),
+ hint = get_icon("", "[H]"),
+ success = get_icon("✓", "[OK]"),
+ question = get_icon("?", "[?]"),
+ star = get_icon("★", "[*]"),
+ heart = get_icon("❤", "<3"),
+ lightning = get_icon("⚡", "[!]"),
+ check = get_icon("✓", "[√]"),
+ cross = get_icon("✗", "[x]"),
+ plus = get_icon("+", "[+]"),
+ recording = get_icon(" ", "q")
+ },
+
+ -- File operations
+ FileOp = {
+ new = get_icon("", "[NEW]"),
+ save = get_icon("💾", "[SAVE]"),
+ open = get_icon("📂", "[OPEN]"),
+ close = get_icon("✕", "[X]"),
+ undo = get_icon("↩", "[UNDO]"),
+ redo = get_icon("↪", "[REDO]"),
+ cut = get_icon("✂", "[CUT]"),
+ copy = get_icon("⎘", "[COPY]"),
+ paste = get_icon("📋", "[PASTE]"),
+ search = get_icon("🔍", "[FIND]"),
+ replace = get_icon("🔄", "[REPLACE]"),
+ },
+
+ -- Navigation
+ Nav = {
+ left = get_icon("←", "[<]"),
+ right = get_icon("→", "[>]"),
+ up = get_icon("↑", "[^]"),
+ down = get_icon("↓", "[v]"),
+ first = get_icon("⏮", "[<<]"),
+ last = get_icon("⏭", "[>>]"),
+ prev = get_icon("◀", "[<]"),
+ next = get_icon("▶", "[>]"),
+ back = get_icon("↩", "[B]"),
+ forward = get_icon("↪", "[F]"),
+ },
+
+ -- Editor states
+ State = {
+ insert = get_icon("", "[INS]"),
+ normal = get_icon("🚀", "[NOR]"),
+ visual = get_icon("👁", "[VIS]"),
+ replace = get_icon("🔄", "[REP]"),
+ command = get_icon("", "[CMD]"),
+ terminal = get_icon("", "[TERM]"),
+ select = get_icon("🔍", "[SEL]"),
+ },
+
+ -- Common symbols
+ Symbol = {
+ dot = get_icon("•", "•"),
+ bullet = get_icon("•", "•"),
+ middle_dot = get_icon("·", "·"),
+ ellipsis = get_icon("…", "..."),
+ check = get_icon("✓", "[OK]"),
+ cross = get_icon("✗", "[X]"),
+ arrow_right = get_icon(" ", "->"),
+ arrow_left = get_icon(" ", "<-"),
+ double_arrow_right = get_icon("»", ">>"),
+ double_arrow_left = get_icon("«", "<<"),
+ chevron_right = get_icon("›", ">"),
+ chevron_left = get_icon("‹", "<"),
+ },
+
+ -- Document symbols
+ DocSymbol = {
+ class = get_icon("", "[C]"),
+ function_icon = get_icon("", "[F]"),
+ method = get_icon("", "[M]"),
+ property = get_icon("", "[P]"),
+ field = get_icon("ﰠ", "[F]"),
+ constructor = get_icon("", "[C]"),
+ enum = get_icon("", "[E]"),
+ interface = get_icon("", "[I]"),
+ variable = get_icon("", "[V]"),
+ constant = get_icon("", "[C]"),
+ string = get_icon("", "[S]"),
+ number = get_icon("", "[N]"),
+ boolean = get_icon("◩", "[B]"),
+ array = get_icon("", "[A]"),
+ object = get_icon("⦿", "[O]"),
+ key = get_icon("🔑", "[K]"),
+ null = get_icon("NULL", "Ø"),
+ enum_member = get_icon("", "[E]"),
+ struct = get_icon("פּ", "[S]"),
+ event = get_icon("", "[E]"),
+ operator = get_icon("", "[O]"),
+ type_parameter = get_icon("", "[T]"),
+ },
+ }
+ local Align = { provider = "%=", hl = { bg = colors.bg } }
+ local Space = { provider = " ", hl = { bg = colors.bg } }
+ local Tab = { provider = " " }
+ local LeftSpace = { provider = "" }
+ local RightSpace = { provider = "" }
+
+ local ViMode = {
+ init = function(self)
+ self.mode = vim.fn.mode(1)
+ -- Store the initial mode
+ self.prev_mode = self.mode
+
+ -- Set up autocommand to force redraw on mode change
+ vim.api.nvim_create_autocmd("ModeChanged", {
+ pattern = "*:*",
+ callback = function()
+ -- Only redraw if the mode actually changed
+ local current_mode = vim.fn.mode(1)
+ if current_mode ~= self.prev_mode then
+ self.prev_mode = current_mode
+ vim.schedule(function()
+ vim.cmd("redrawstatus")
+ end)
+ end
+ end,
+ })
end,
- -- line: 16 bit (65535); col: 10 bit (1023); winnr: 6 bit (63)
- dec = function(c)
- local line = bit.rshift(c, 16)
- local col = bit.band(bit.rshift(c, 6), 1023)
- local winnr = bit.band(c, 63)
- return line, col, winnr
+ static = {
+ mode_names = {
+ n = " NORMAL ",
+ no = "PENDING ",
+ nov = " N? ",
+ noV = " N? ",
+ ["no\22"] = " N? ",
+ niI = " Ni ",
+ niR = " Nr ",
+ niV = " Nv ",
+ nt = "TERMINAL",
+ v = " VISUAL ",
+ vs = " Vs ",
+ V = " V·LINE ",
+ ["\22"] = "V·BLOCK ",
+ ["\22s"] = "V·BLOCK ",
+ s = " SELECT ",
+ S = " S·LINE ",
+ ["\19"] = "S·BLOCK ",
+ i = " INSERT ",
+ ix = "insert x",
+ ic = "insert c",
+ R = "REPLACE ",
+ Rc = " Rc ",
+ Rx = " Rx ",
+ Rv = "V·REPLACE ",
+ Rvc = " Rv ",
+ Rvx = " Rv ",
+ c = "COMMAND ",
+ cv = " VIM EX ",
+ ce = " EX ",
+ r = " PROMPT ",
+ rm = " MORE ",
+ ["r?"] = "CONFIRM ",
+ ["!"] = " SHELL ",
+ t = "TERMINAL",
+ },
+ },
+ provider = function(self)
+ return " %2(" .. self.mode_names[self.mode] .. "%) "
end,
- },
- init = function(self)
- local data = require('nvim-navic').get_data() or {}
- local children = {}
- -- create a child for each level
- for i, d in ipairs(data) do
- -- encode line and column numbers into a single integer
- local pos = self.enc(d.scope.start.line, d.scope.start.character, self.winnr)
- local child = {
- {
- provider = d.icon,
- hl = self.type_hl[d.type],
- },
- {
- -- escape `%`s (elixir) and buggy default separators
- provider = d.name:gsub('%%', '%%%%'):gsub('%s*->%s*', ''),
- -- highlight icon only or location name as well
- -- hl = self.type_hl[d.type],
-
- on_click = {
- -- pass the encoded position through minwid
- minwid = pos,
- callback = function(_, minwid)
- -- decode
- local line, col, winnr = self.dec(minwid)
- vim.api.nvim_win_set_cursor(vim.fn.win_getid(winnr), { line, col })
- end,
- name = 'heirline_navic',
- },
- },
- }
- -- add a separator only if needed
- if #data > 1 and i < #data then
- table.insert(child, {
- provider = ' > ',
- hl = { fg = 'bright_fg' },
- })
+ hl = function(self)
+ return { fg = "colors.black", bg = self.mode_color, bold = true }
+ end,
+ update = {
+ "ModeChanged",
+ "VimEnter",
+ "BufEnter",
+ "WinEnter",
+ "TabEnter",
+ pattern = "*:*",
+ callback = vim.schedule_wrap(function()
+ vim.cmd("redrawstatus")
+ end),
+ },
+ }
+
+ -- LSP
+ local LSPActive = {
+ condition = function()
+ local ok, _ = pcall(function()
+ local buf = vim.api.nvim_get_current_buf()
+ return #vim.lsp.get_clients({ bufnr = buf }) > 0
+ end)
+ return ok or false
+ end,
+ update = { "LspAttach", "LspDetach", "BufEnter" },
+ provider = function()
+ local ok, result = pcall(function()
+ local buf = vim.api.nvim_get_current_buf()
+ if not vim.api.nvim_buf_is_valid(buf) then return "" end
+
+ local clients = vim.lsp.get_clients({ bufnr = buf })
+ if not clients or #clients == 0 then return "" end
+
+ local client_names = {}
+ for _, client in ipairs(clients) do
+ if client and client.name and client.name ~= "null-ls" then
+ table.insert(client_names, client.name)
+ end
+ end
+
+ if #client_names > 0 then
+ return Icons.Signs.LSP .. " " .. table.concat(client_names, "/") .. " "
+ end
+
+ return ""
+ end)
+
+ if not ok then
+ vim.schedule(function()
+ vim.notify_once("Error in LSPActive provider: " .. tostring(result), vim.log.levels.DEBUG)
+ end)
+ return ""
end
- table.insert(children, child)
- end
- -- instantiate the new child, overwriting the previous one
- self.child = self:new(children, 1)
- end,
- -- evaluate the children containing navic components
- provider = function(self)
- return self.child:eval()
- end,
- hl = { fg = 'gray' },
- update = 'CursorMoved',
-}
-
--- Diagnostics
-local Diagnostics = {
- condition = conditions.has_diagnostics,
- static = {
- error_icon = vim.fn.sign_getdefined('DiagnosticSignError')[1].text,
- warn_icon = vim.fn.sign_getdefined('DiagnosticSignWarn')[1].text,
- info_icon = vim.fn.sign_getdefined('DiagnosticSignInfo')[1].text,
- hint_icon = vim.fn.sign_getdefined('DiagnosticSignHint')[1].text,
- },
- init = function(self)
- self.errors = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.ERROR })
- self.warnings = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.WARN })
- self.hints = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.HINT })
- self.info = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.INFO })
- end,
- update = { 'DiagnosticChanged', 'BufEnter' },
- {
- provider = function(self)
- -- 0 is just another output, we can decide to print it or not!
- return self.errors > 0 and (self.error_icon .. self.errors .. ' ')
+
+ return result or ""
end,
- hl = { fg = colors.diag.error, bg = colors.bg },
- },
- {
- provider = function(self)
- return self.warnings > 0 and (self.warn_icon .. self.warnings .. ' ')
+ hl = { fg = "lightgray", bold = false },
+ }
+
+ local Navic = {
+ condition = function()
+ local ok, navic = pcall(require, "nvim-navic")
+ return ok and navic.is_available()
end,
- hl = { fg = colors.diag.warn, bg = colors.bg },
- },
- {
- provider = function(self)
- return self.info > 0 and (self.info_icon .. self.info .. ' ')
+ static = {
+ type_hl = {
+ File = "Directory",
+ Module = "@include",
+ Namespace = "@namespace",
+ Package = "@include",
+ Class = "@structure",
+ Method = "@method",
+ Property = "@property",
+ Field = "@field",
+ Constructor = "@constructor",
+ Enum = "@field",
+ Interface = "@type",
+ Function = "@function",
+ Variable = "@variable",
+ Constant = "@constant",
+ String = "@string",
+ Number = "@number",
+ Boolean = "@boolean",
+ Array = "@field",
+ Object = "@type",
+ Key = "@keyword",
+ Null = "@comment",
+ EnumMember = "@field",
+ Struct = "@structure",
+ Event = "@keyword",
+ Operator = "@operator",
+ TypeParameter = "@type",
+ },
+ enc = function(line, col, winnr)
+ return bit.bor(bit.lshift(line, 16), bit.lshift(col, 6), winnr)
+ end,
+ dec = function(c)
+ local line = bit.rshift(c, 16)
+ local col = bit.band(bit.rshift(c, 6), 1023)
+ local winnr = bit.band(c, 63)
+ return line, col, winnr
+ end,
+ },
+ init = function(self)
+ local data = require("nvim-navic").get_data() or {}
+ local children = {}
+ for i, d in ipairs(data) do
+ local pos = self.enc(d.scope.start.line, d.scope.start.character, self.winnr)
+ local child = {
+ {
+ provider = d.icon,
+ hl = self.type_hl[d.type],
+ },
+ {
+ provider = d.name:gsub("%%", "%%%%"):gsub("%s*->%s*", ""),
+ on_click = {
+ minwid = pos,
+ callback = function(_, minwid)
+ local line, col, winnr = self.dec(minwid)
+ vim.api.nvim_win_set_cursor(vim.fn.win_getid(winnr), { line, col })
+ end,
+ name = "heirline_navic",
+ },
+ },
+ }
+ if #data > 1 and i < #data then
+ table.insert(child, {
+ provider = " > ",
+ hl = { fg = "bright_fg" },
+ })
+ end
+ table.insert(children, child)
+ end
+ self.child = self:new(children, 1)
end,
- hl = { fg = colors.diag.info, bg = colors.bg },
- },
- {
provider = function(self)
- return self.hints > 0 and (self.hint_icon .. self.hints)
+ return self.child:eval()
end,
- hl = { fg = colors.diag.hint, bg = colors.bg },
- },
- on_click = {
- callback = function()
- require('trouble').toggle({ mode = 'document_diagnostics' })
- -- or
- -- vim.diagnostic.setqflist()
+ hl = { fg = "gray" },
+ update = "CursorMoved",
+ }
+
+ -- Diagnostics
+ local Diagnostics = {
+ condition = conditions.has_diagnostics,
+ static = {
+ error_icon = Icons.Error,
+ warn_icon = Icons.Warn,
+ info_icon = Icons.Info,
+ hint_icon = Icons.Hint,
+ },
+ init = function(self)
+ self.errors = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.ERROR })
+ self.warnings = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.WARN })
+ self.hints = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.HINT })
+ self.info = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.INFO })
end,
- name = 'heirline_diagnostics',
- },
-}
-
--- Git
--- For the ones who're not (too) afraid of changes! Uses gitsigns.
-local Git = {
- condition = conditions.is_git_repo,
- init = function(self)
- self.status_dict = vim.b.gitsigns_status_dict
- self.has_changes = self.status_dict.added ~= 0 or self.status_dict.removed ~= 0 or self.status_dict.changed ~= 0
- end,
- --{
- -- -- git branch name
- -- provider = function(self)
- -- --return ' ' .. self.status_dict.head
- -- return '  ' .. self.status_dict.head
- -- end,
- -- --hl = { bold = true },
- -- hl = { fg = colors.git.active, bold = true, bg = colors.bg },
- --},
- -- You could handle delimiters, icons and counts similar to Diagnostics
- {
- -- git branch icon
- provider = function()
- return '  '
+ update = { "DiagnosticChanged", "BufEnter" },
+ {
+ provider = function(self)
+ return self.errors > 0 and (self.error_icon .. " " .. self.errors .. " ")
+ end,
+ hl = { fg = colors.diag.error, bg = colors.bg },
+ },
+ {
+ provider = function(self)
+ return self.warnings > 0 and (self.warn_icon .. " " .. self.warnings .. " ")
+ end,
+ hl = { fg = colors.diag.warn, bg = colors.bg },
+ },
+ {
+ provider = function(self)
+ return self.info > 0 and (self.info_icon .. " " .. self.info .. " ")
+ end,
+ hl = { fg = colors.diag.info, bg = colors.bg },
+ },
+ {
+ provider = function(self)
+ return self.hints > 0 and (self.hint_icon .. " " .. self.hints .. " ")
+ end,
+ hl = { fg = colors.diag.hint, bg = colors.bg },
+ },
+ on_click = {
+ callback = function()
+ local ok, _ = pcall(require, "trouble")
+ if ok then
+ require("trouble").toggle({ mode = "document_diagnostics" })
+ else
+ vim.diagnostic.setqflist()
+ end
+ end,
+ name = "heirline_diagnostics",
+ },
+ }
+
+ -- Git
+ local Git = {
+ condition = conditions.is_git_repo,
+ init = function(self)
+ self.status_dict = vim.b.gitsigns_status_dict or {}
+ self.has_changes = (self.status_dict.added or 0) ~= 0 or
+ (self.status_dict.removed or 0) ~= 0 or
+ (self.status_dict.changed or 0) ~= 0
end,
- hl = { fg = colors.git.active, bg = colors.bg },
- },
+ {
+ provider = function()
+ return " " .. Icons.Git.branch .. " "
+ end,
+ hl = { fg = colors.git.active, bg = colors.bg },
+ },
+ {
+ provider = function(self)
+ return self.status_dict.head or ""
+ end,
+ hl = { fg = colors.white, bg = colors.bg },
+ },
+ {
+ condition = function(self)
+ return self.has_changes
+ end,
+ provider = "",
+ },
+ {
+ provider = function(self)
+ local count = self.status_dict.added or 0
+ return count > 0 and (" " .. Icons.Git.added .. count) or ""
+ end,
+ hl = { fg = colors.git.add, bg = colors.bg },
+ },
+ {
+ provider = function(self)
+ local count = self.status_dict.removed or 0
+ return count > 0 and (" " .. Icons.Git.removed .. count) or ""
+ end,
+ hl = { fg = colors.git.del, bg = colors.bg },
+ },
+ {
+ provider = function(self)
+ local count = self.status_dict.changed or 0
+ return count > 0 and (" " .. Icons.Git.modified .. count) or ""
+ end,
+ hl = { fg = colors.git.change, bg = colors.bg },
+ },
+ on_click = {
+ callback = function()
+ vim.defer_fn(function()
+ vim.cmd("Lazygit")
+ end, 100)
+ end,
+ name = "heirline_git",
+ },
+ }
- {
- -- git branch name
- provider = function(self)
- return self.status_dict.head
+ -- FileNameBlock: FileIcon, FileName and friends
+ local FileNameBlock = {
+ init = function(self)
+ self.filename = vim.api.nvim_buf_get_name(0)
end,
- hl = { fg = colors.white, bg = colors.bg },
- },
+ hl = { bg = colors.bg },
+ }
+
+ local FileIcon = {
+ init = function(self)
+ local filename = self.filename or vim.api.nvim_buf_get_name(0)
+ local extension = vim.fn.fnamemodify(filename, ":e")
+
+ local has_nerd_fonts = vim.g.statusline_has_nerd_fonts
+ if has_nerd_fonts == nil then
+ if vim.fn.has('unix') == 1 and vim.fn.executable('fc-list') == 1 then
+ local handle = io.popen('fc-list | grep -i nerd')
+ local result = handle:read('*a')
+ handle:close()
+ has_nerd_fonts = result ~= ""
+ else
+ has_nerd_fonts = false
+ end
+ vim.g.statusline_has_nerd_fonts = has_nerd_fonts
+ end
- {
- condition = function(self)
- return self.has_changes
+ local icon, icon_color
+ if has_nerd_fonts then
+ icon, icon_color = require("nvim-web-devicons").get_icon_color(filename, extension, { default = true })
+ end
+
+ if vim.fn.isdirectory(filename) == 1 then
+ self.icon = has_nerd_fonts and Icons.File.directory or "[DIR]"
+ self.icon_color = colors.blue
+ else
+ if has_nerd_fonts and icon then
+ self.icon = icon .. " "
+ self.icon_color = icon_color or colors.blue
+ else
+ if extension == "" then
+ self.icon = Icons.File.default
+ else
+ local file_icon = Icons.File[extension:lower()] or Icons.File.default
+ if type(file_icon) == "table" then
+ self.icon = file_icon[1] or Icons.File.default
+ else
+ self.icon = file_icon
+ end
+ end
+ self.icon_color = colors.blue
+ end
+ end
end,
- --provider = "("
- provider = '',
- },
- {
provider = function(self)
- local count = self.status_dict.added or 0
- --return count > 0 and ("+" .. count)
- return count > 0 and ('  ' .. count)
+ return self.icon
end,
- --hl = { fg = "git_add" },
- hl = { fg = colors.git.add, bg = colors.bg },
- },
- {
- provider = function(self)
- local count = self.status_dict.removed or 0
- --return count > 0 and ("-" .. count)
- return count > 0 and ('  ' .. count)
+ hl = function(self)
+ return { fg = self.icon_color, bold = true }
end,
- --hl = { fg = "git_del" },
- hl = { fg = colors.git.del, bg = colors.bg },
- },
- {
+ }
+
+ local FileName = {
provider = function(self)
- local count = self.status_dict.changed or 0
- --return count > 0 and ("~" .. count)
- return count > 0 and ('  ' .. count)
+ local filename = vim.fn.fnamemodify(self.filename, ":.")
+ if filename == "" then
+ return "No Name"
+ end
+ if not conditions.width_percent_below(#filename, 0.25) then
+ filename = vim.fn.pathshorten(filename)
+ end
+ return filename
end,
- --hl = { fg = "git_change" },
- hl = { fg = colors.git.change, bg = colors.bg },
- },
- --{
- -- condition = function(self)
- -- return self.has_changes
- -- end,
- -- provider = ")",
- --},
- on_click = {
- callback = function()
- -- If you want to use Fugitive:
- -- vim.cmd("G")
-
- -- If you prefer Lazygit
- -- use vim.defer_fn() if the callback requires
- -- opening of a floating window
- -- (this also applies to telescope)
- vim.defer_fn(function()
- vim.cmd('Lazygit')
- end, 100)
+ hl = { fg = colors.white, bold = false, bg = colors.bg },
+ }
+
+ local FileFlags = {
+ {
+ provider = function()
+ if vim.bo.modified then
+ return " +"
+ end
+ end,
+ hl = { fg = colors.green, bg = colors.bg },
+ },
+ {
+ provider = function()
+ if not vim.bo.modifiable or vim.bo.readonly then
+ return " " .. Icons.UI.lock
+ end
+ end,
+ hl = { fg = colors.orange, bold = true, bg = colors.bg },
+ },
+ }
+
+ local FileNameModifier = {
+ hl = function()
+ if vim.bo.modified then
+ return { fg = colors.green, bold = false, force = true }
+ end
end,
- name = 'heirline_git',
- },
-}
-
--- Debugger
--- Display informations from nvim-dap!
--- Note that we add spaces separately, so that only the icon characters will be clickable
---local DAPMessages = {
--- condition = function()
--- local session = require("dap").session()
--- return session ~= nil
--- end,
--- provider = function()
--- return " " .. require("dap").status() .. " "
--- end,
--- hl = "Debug",
--- {
--- provider = "",
--- on_click = {
--- callback = function()
--- require("dap").step_into()
--- end,
--- name = "heirline_dap_step_into",
--- },
--- },
--- { provider = " " },
--- {
--- provider = "",
--- on_click = {
--- callback = function()
--- require("dap").step_out()
--- end,
--- name = "heirline_dap_step_out",
--- },
--- },
--- { provider = " " },
--- {
--- provider = " ",
--- on_click = {
--- callback = function()
--- require("dap").step_over()
--- end,
--- name = "heirline_dap_step_over",
--- },
--- },
--- { provider = " " },
--- {
--- provider = "ﰇ",
--- on_click = {
--- callback = function()
--- require("dap").run_last()
--- end,
--- name = "heirline_dap_run_last",
--- },
--- },
--- { provider = " " },
--- {
--- provider = "",
--- on_click = {
--- callback = function()
--- require("dap").terminate()
--- require("dapui").close({})
--- end,
--- name = "heirline_dap_close",
--- },
--- },
--- { provider = " " },
--- -- icons:       ﰇ  
---}
+ }
--- Tests
--- This requires the great ultest.
---local UltTest = {
--- condition = function()
--- return vim .api.nvim_call_function("ultest#is_test_file", {}) ~= 0
--- end,
--- static = {
--- passed_icon = vim.fn.sign_getdefined("test_pass")[1].text,
--- failed_icon = vim.fn.sign_getdefined("test_fail")[1].text,
--- passed_hl = { fg = utils.get_highlight("UltestPass").fg },
--- failed_hl = { fg = utils.get_highlight("UltestFail").fg },
--- },
--- init = function(self)
--- self.status = vim.api.nvim_call_function("ultest#status", {})
--- end,
---
--- -- again, if you'd like icons and numbers to be colored differently,
--- -- just split the component in two
--- {
--- provider = function(self)
--- return self.passed_icon .. self.status.passed .. " "
--- end,
--- hl = function(self)
--- return self.passed_hl
--- end,
--- },
--- {
--- provider = function(self)
--- return self.failed_icon .. self.status.failed .. " "
--- end,
--- hl = function(self)
--- return self.failed_hl
--- end,
--- },
--- {
--- provider = function(self)
--- return "of " .. self.status.tests - 1
--- end,
--- },
---}
+ -- FileType, FileEncoding and FileFormat
+ local FileType = {
+ provider = function()
+ return vim.bo.filetype
+ end,
+ hl = { fg = colors.white, bold = false, bg = colors.bg },
+ }
--- FileNameBlock: FileIcon, FileName and friends
-local FileNameBlock = {
- -- let's first set up some attributes needed by this component and it's children
- init = function(self)
- self.filename = vim.api.nvim_buf_get_name(0)
- end,
- --hl = { fg = utils.get_highlight("Statusline").fg, bold = true, bg = colors.bg },
- hl = { bg = colors.bg },
-}
-
--- FileIcon, FileName, FileFlags and FileNameModifier
-local FileIcon = {
- init = function(self)
- local filename = self.filename
- local extension = vim.fn.fnamemodify(filename, ':e')
- self.icon, self.icon_color = require('nvim-web-devicons').get_icon_color(filename, extension, { default = true })
- end,
- provider = function(self)
- return self.icon and (self.icon .. ' ')
- end,
- hl = function(self)
- return { fg = self.icon_color, bg = colors.bg }
- end,
-}
-
-local FileName = {
- provider = function(self)
- -- first, trim the pattern relative to the current directory. For other
- -- options, see :h filename-modifers
- local filename = vim.fn.fnamemodify(self.filename, ':.')
- if filename == '' then
- return 'No Name'
- end
- -- now, if the filename would occupy more than 1/4th of the available
- -- space, we trim the file path to its initials
- -- See Flexible Components section below for dynamic truncation
- if not conditions.width_percent_below(#filename, 0.25) then
- filename = vim.fn.pathshorten(filename)
- end
- return filename
- end,
- --hl = { fg = utils.get_highlight("Statusline").fg, bold = false, bg = colors.bg },
- hl = { fg = colors.white, bold = false, bg = colors.bg },
-}
-
-local FileFlags = {
- {
+ local FileEncoding = {
+ Space,
provider = function()
- if vim.bo.modified then
- return ' [+]' -- ±[+]
- end
+ local enc = (vim.bo.fenc ~= "" and vim.bo.fenc) or vim.o.enc
+ return enc:lower()
+ end,
+ hl = { bg = colors.bg, bold = false },
+ }
+
+ local FileFormat = {
+ provider = function()
+ local fmt = vim.bo.fileformat
+ return fmt ~= "unix" and fmt:lower() or ""
end,
- hl = { fg = colors.green, bg = colors.bg },
- },
- {
+ hl = { fg = utils.get_highlight("Statusline").fg, bold = true, bg = colors.bg },
+ }
+
+ local FileSize = {
provider = function()
- if not vim.bo.modifiable or vim.bo.readonly then
- return ' '
+ local suffix = { "b", "k", "M", "G", "T", "P", "E" }
+ local filename = vim.api.nvim_buf_get_name(0)
+ local fsize = vim.fn.getfsize(filename)
+ fsize = (fsize < 0 and 0) or fsize
+ if fsize < 1024 then
+ return fsize .. suffix[1]
end
+ local i = math.floor((math.log(fsize) / math.log(1024)))
+ return string.format("%.2g%s", fsize / math.pow(1024, i), suffix[i + 1])
end,
- --hl = { fg = colors.orange },
- hl = { fg = colors.orange, bold = true, bg = colors.bg },
- },
-}
-
-local FileNameModifier = {
- hl = function()
- if vim.bo.modified then
- return { fg = colors.green, bold = false, force = true }
- end
- end,
-}
-
--- FileType, FileEncoding and FileFormat
-local FileType = {
- provider = function()
- return vim.bo.filetype
- end,
- hl = { fg = colors.white, bold = false, bg = colors.bg },
-}
-
-local FileEncoding = {
- Space,
- provider = function()
- local enc = (vim.bo.fenc ~= '' and vim.bo.fenc) or vim.o.enc -- :h 'enc'
- return enc:lower()
- end,
- --hl = { fg = utils.get_highlight("Statusline").fg, bold = true, bg = colors.bg },
- hl = { bg = colors.bg, bold = false },
-}
-
-local FileFormat = {
- provider = function()
- local fmt = vim.bo.fileformat
- --return fmt ~= "unix" and fmt:upper()
- return fmt ~= 'unix' and fmt:lower()
- end,
- hl = { fg = utils.get_highlight('Statusline').fg, bold = true, bg = colors.bg },
-}
-
--- FileSize and FileLastModified
-local FileSize = {
- provider = function()
- -- stackoverflow, compute human readable file size
- local suffix = { 'b', 'k', 'M', 'G', 'T', 'P', 'E' }
- local fsize = vim.fn.getfsize(vim.api.nvim_buf_get_name(0))
- fsize = (fsize < 0 and 0) or fsize
- if fsize < 1024 then
- return fsize .. suffix[1]
- end
- local i = math.floor((math.log(fsize) / math.log(1024)))
- return string.format('%.2g%s', fsize / math.pow(1024, i), suffix[i + 1])
- end,
- hl = { fg = utils.get_highlight('Statusline').fg, bold = true, bg = colors.bg },
-}
-
-local FileLastModified = {
- -- did you know? Vim is full of functions!
- provider = function()
- local ftime = vim.fn.getftime(vim.api.nvim_buf_get_name(0))
- return (ftime > 0) and os.date('%c', ftime)
- end,
- hl = { fg = utils.get_highlight('Statusline').fg, bold = true, bg = colors.bg },
-}
-
--- Spell
--- Add indicator when spell is set!
-local Spell = {
- condition = function()
- return vim.wo.spell
- end,
- provider = ' 暈',
- hl = { bold = true, fg = colors.yellow },
-}
-
-local HelpFileName = {
- condition = function()
- return vim.bo.filetype == 'help'
- end,
- provider = function()
- local filename = vim.api.nvim_buf_get_name(0)
- return vim.fn.fnamemodify(filename, ':t')
- end,
- hl = { fg = colors.blue },
-}
-
-local SearchCount = {
- condition = function()
- return vim.v.hlsearch ~= 0 and vim.o.cmdheight == 0
- end,
- init = function(self)
- local ok, search = pcall(vim.fn.searchcount)
- if ok and search.total then
- self.search = search
- end
- end,
- provider = function(self)
- local search = self.search
- return string.format('[%d/%d]', search.current, math.min(search.total, search.maxcount))
- end,
-}
-
-local MacroRec = {
- condition = function()
- return vim.fn.reg_recording() ~= '' and vim.o.cmdheight == 0
- end,
- provider = ' ',
- hl = { fg = 'orange', bold = true },
- utils.surround({ '[', ']' }, nil, {
+ hl = { fg = utils.get_highlight("Statusline").fg, bold = true, bg = colors.bg },
+ }
+
+ local FileLastModified = {
provider = function()
- return vim.fn.reg_recording()
+ local filename = vim.api.nvim_buf_get_name(0)
+ local ftime = vim.fn.getftime(filename)
+ return (ftime > 0) and os.date("%c", ftime) or ""
end,
- hl = { fg = 'green', bold = true },
- }),
- update = {
- 'RecordingEnter',
- 'RecordingLeave',
- },
-}
-
-local ShowCmd = {
- condition = function()
- return vim.o.cmdheight == 0
- end,
- provider = ':%3.5(%S%)',
-}
-
-local cursor_location = {
- { provider = '%1(%4l:%-3(%c%)%) %*', hl = { fg = colors.black, bold = true } },
-}
-
-local Ruler = { cursor_location }
-
---utils.make_flexible_component(
--- 3,
--- { Ruler, hl = { fg = utils.get_highlight("statusline").bg, force = true } },
--- { provider = "%<" }
---),
---local cursor_location = {
--- { provider = "%7(%l:%c%) ", hl = { bold = true } },
--- {
--- provider = " ",
--- hl = function(self)
--- local color = self:mode_color()
--- return { fg = color, bold = true }
--- end,
--- },
---}
+ hl = { fg = utils.get_highlight("Statusline").fg, bold = true, bg = colors.bg },
+ }
-local WordCount = {
- condition = function()
- return conditions.buffer_matches({
- filetype = {
- 'markdown',
- 'txt',
- 'vimwiki',
- },
- })
- end,
- Space,
- {
+ local Spell = {
+ condition = function()
+ return vim.wo.spell
+ end,
provider = function()
- return 'W:' .. vim.fn.wordcount().words
+ return " " .. Icons.Indicator.spell .. " "
end,
- },
-}
-
--- Working Directory
-local WorkDir = {
- init = function(self)
- self.icon = (vim.fn.haslocaldir(0) == 1 and 'l' or 'g') .. ' ' .. ' '
- local cwd = vim.fn.getcwd(0)
- self.cwd = vim.fn.fnamemodify(cwd, ':~')
- end,
- hl = { fg = 'colors.blue', bold = true },
- flexible = 1,
- {
- -- evaluates to the full-lenth path
- provider = function(self)
- local trail = self.cwd:sub(-1) == '/' and '' or '/'
- return self.icon .. self.cwd .. trail .. ' '
+ hl = { bold = true, fg = colors.yellow },
+ }
+
+ local HelpFileName = {
+ condition = function()
+ return vim.bo.filetype == "help"
+ end,
+ provider = function()
+ local filename = vim.api.nvim_buf_get_name(0)
+ return vim.fn.fnamemodify(filename, ":t")
+ end,
+ hl = { fg = colors.blue },
+ }
+
+ local SearchCount = {
+ condition = function()
+ return vim.v.hlsearch ~= 0 and vim.o.cmdheight == 0
+ end,
+ init = function(self)
+ local ok, search = pcall(vim.fn.searchcount, { recompute = 1, maxcount = -1 })
+ if ok and search.total then
+ self.search = search
+ end
end,
- },
- {
- -- evaluates to the shortened path
provider = function(self)
- local cwd = vim.fn.pathshorten(self.cwd)
- local trail = self.cwd:sub(-1) == '/' and '' or '/'
- return self.icon .. cwd .. trail .. ' '
+ local search = self.search or { current = 0, total = 0, maxcount = 0 }
+ return string.format("[%d/%d]", search.current, math.min(search.total, search.maxcount))
end,
- },
- {
- -- evaluates to "", hiding the component
- provider = '',
- },
-}
-
--- Snippets Indicator
--- This requires ultisnips
---local Snippets = {
--- -- check that we are in insert or select mode
--- condition = function()
--- return vim.tbl_contains({'s', 'i'}, vim.fn.mode())
--- end,
--- provider = function()
--- local forward = (vim.fn["UltiSnips#CanJumpForwards"]() == 1) and "" or ""
--- local backward = (vim.fn["UltiSnips#CanJumpBackwards"]() == 1) and " " or ""
--- return backward .. forward
--- end,
--- hl = { fg = "red", bold = true },
---}
+ update = { "CursorMoved", "CursorMovedI", "SearchWrapped" },
+ }
--- let's add the children to our FileNameBlock component
-FileNameBlock = utils.insert(
- FileNameBlock,
- FileIcon,
- utils.insert(FileNameModifier, FileName), -- a new table where FileName is a child of FileNameModifier
- unpack(FileFlags), -- A small optimisation, since their parent does nothing
- { provider = '%<' } -- this means that the statusline is cut here when there's not enough space
-)
-
-local FileInfoBlock = {
- -- let's first set up some attributes needed by this component and it's children
- init = function(self)
- self.filename = vim.api.nvim_buf_get_name(0)
- end,
-}
-
-FileInfoBlock = utils.insert(
- FileInfoBlock,
- Space,
- FileIcon,
- FileType,
- { provider = '%<' } -- this means that the statusline is cut here when there's not enough space
-)
-
-LeftSpace = utils.surround({ '', '' }, function(self)
- return self:mode_color()
-end, { LeftSpace, hl = { fg = utils.get_highlight('statusline').bg, force = true } })
-
-RightSpace = utils.surround({ '', '' }, function(self)
- return self:mode_color()
-end, { RightSpace, hl = { fg = utils.get_highlight('statusline').bg, force = true } })
-
-LSPActive = utils.surround({ '', '' }, function(self)
- return self:mode_color()
-end, { Space, LSPActive, hl = { bg = colors.darkgray, force = true } })
-
-FileInfoBlock = utils.surround({ '', '' }, function(self)
- return self:mode_color()
-end, { FileInfoBlock, Space, hl = { bg = colors.black, force = true } })
-
-ViMode = utils.surround({ '', '' }, function(self)
- return self:mode_color()
-end, { ViMode, hl = { fg = colors.black, force = true } })
-
-Ruler = utils.surround({ '', '' }, function(self)
- return self:mode_color()
-end, { Ruler, hl = { fg = colors.black, force = true } })
-
-local left = {
- { RightSpace, hl = { bg = colors.nobg, force = true } },
- { ViMode, hl = { bg = utils.get_highlight('statusline').bg, bold = false } },
- { LeftSpace, hl = { bg = colors.nobg, force = true } },
- { Space, hl = { bg = colors.nobg, force = true } },
- { FileNameBlock, hl = { bg = colors.nobg, force = true } },
- { Space, hl = { bg = colors.nobg, force = true } },
- { Git, hl = { bg = colors.nobg, force = true } },
-}
-
-local middle = {
- { Align, hl = { bg = colors.nobg, force = true } },
- --{ Navic, hl = { bg = colors.nobg, force = true } },
- --{ DAPMessages, hl = { bg = colors.nobg, force = true } },
- { Align, hl = { bg = colors.nobg, force = true } },
-}
-
-local right = {
- --{ Space, hl = { bg = colors.nobg, force = true } },
- { Diagnostics, hl = { bg = colors.nobg, force = true } },
- { Space, hl = { bg = colors.nobg, force = true } },
- { LSPActive, hl = { bg = colors.nobg, force = true } },
- { Space, hl = { bg = colors.nobg, force = true } },
- { FileInfoBlock, hl = { bg = colors.nobg, force = true } },
- { RightSpace, hl = { bg = colors.nobg, force = true } },
- { Ruler, hl = { fg = utils.get_highlight('statusline').bg, bold = false } },
- { LeftSpace, hl = { bg = colors.nobg, force = true } },
-}
-
-local sections = { left, middle, right }
-local DefaultStatusline = { sections }
-
-local specialleft = {
- { RightSpace, hl = { bg = colors.nobg, force = true } },
- { ViMode, hl = { bg = utils.get_highlight('statusline').bg, bold = false } },
- { LeftSpace, hl = { bg = colors.nobg, force = true } },
-}
-
-local specialmiddle = {
- { Align, hl = { bg = colors.nobg, force = true } },
- --{ DAPMessages, hl = { bg = colors.nobg, force = true } },
- { Align, hl = { bg = colors.nobg, force = true } },
-}
-
-local specialright = {
- { RightSpace, hl = { bg = colors.nobg, force = true } },
- { Ruler, hl = { fg = utils.get_highlight('statusline').bg, bold = false } },
- { LeftSpace, hl = { bg = colors.nobg, force = true } },
-}
-
-local specialsections = { specialleft, specialmiddle, specialright }
-
-local InactiveStatusline = {
- condition = conditions.is_not_active,
- --{ FileNameBlock, hl = { bg = colors.nobg, force = true } },
- --{ Align, hl = { bg = colors.nobg, force = true } },
- specialsections,
-}
-
-local SpecialStatusline = {
- condition = function()
- return conditions.buffer_matches({
- buftype = { 'nofile', 'prompt', 'help', 'quickfix' },
- filetype = { '^git.*', 'fugitive', 'dashboard' },
- })
- end,
- specialsections,
-}
-
---local InactiveStatusline = SpecialStatusline
-
-local TerminalStatusline = {
- condition = function()
- return conditions.buffer_matches({ buftype = { 'terminal' } })
- end,
- specialsections,
-}
-
-local StatusLine = {
- static = {
- --mode_colors = {
- -- n = colors.blue,
- -- i = colors.green,
- -- v = colors.purple,
- -- V = colors.purple,
- -- ["\22"] = colors.purple,
- -- c = colors.orange,
- -- s = colors.purple,
- -- S = colors.purple,
- -- ["\19"] = colors.purple,
- -- R = colors.red,
- -- r = colors.red,
- -- ["!"] = colors.orange,
- -- t = colors.orange,
- --},
- mode_colors = {
- n = colors.blue,
- no = colors.blue,
- nov = colors.blue,
- noV = colors.blue,
- ['no\22'] = colors.blue,
- niI = colors.blue,
- niR = colors.blue,
- niV = colors.blue,
- nt = colors.blue,
- v = colors.purple,
- vs = colors.purple,
- V = colors.purple,
- ['\22'] = colors.purple,
- ['\22s'] = colors.purple,
- s = colors.purple,
- S = colors.purple,
- ['\19'] = colors.purple,
- i = colors.green,
- ix = colors.green,
- ic = colors.green,
- R = colors.red,
- Rc = colors.red,
- Rx = colors.red,
- Rv = colors.red,
- Rvc = colors.red,
- Rvx = colors.red,
- c = colors.orange,
- cv = colors.orange,
- ce = colors.orange,
- r = colors.red,
- rm = colors.red,
- ['r?'] = colors.red,
- ['!'] = colors.orange,
- t = colors.orange,
- },
- mode_color = function(self)
- local mode = conditions.is_active() and vim.fn.mode() or 'n'
- return self.mode_colors[mode]
+ local MacroRec = {
+ condition = function()
+ return vim.fn.reg_recording() ~= "" and vim.o.cmdheight == 0
end,
- hl = function(self)
- local color = self:mode_color() -- here!
- return { bg = color }
+ provider = function()
+ return Icons.Indicator.recording .. " "
end,
- },
- fallthrough = false,
- SpecialStatusline,
- TerminalStatusline,
- InactiveStatusline,
- DefaultStatusline,
-}
-
---
---- WinBar
---
-local WinbarFileNameBlock = {
- -- let's first set up some attributes needed by this component and it's children
- init = function(self)
- self.filename = vim.api.nvim_buf_get_name(0)
- end,
- hl = { bg = colors.bg },
-}
-
-local WinbarFileName = {
- provider = function(self)
- -- first, trim the pattern relative to the current directory. For other
- -- options, see :h filename-modifers
- local filename = vim.fn.fnamemodify(self.filename, ':.')
- if filename == '' then
- return 'No Name'
- end
- -- now, if the filename would occupy more than 1/4th of the available
- -- space, we trim the file path to its initials
- -- See Flexible Components section below for dynamic truncation
- if not conditions.width_percent_below(#filename, 0.25) then
- filename = vim.fn.pathshorten(filename)
- end
- return filename
- end,
- --hl = { fg = utils.get_highlight("Statusline").fg, bold = false, bg = colors.bg },
- hl = { fg = colors.gray, bold = false, bg = colors.bg },
-}
-
-WinbarFileNameBlock = utils.insert(
- WinbarFileNameBlock,
- FileIcon,
- utils.insert(WinbarFileName), -- a new table where FileName is a child of FileNameModifier
- unpack(FileFlags), -- A small optimisation, since their parent does nothing
- { provider = '%<' } -- this means that the statusline is cut here when there's not enough space
-)
-
-vim.api.nvim_create_autocmd('User', {
- pattern = 'HeirlineInitWinbar',
- callback = function(args)
- local buf = args.buf
- local buftype = vim.tbl_contains({ 'prompt', 'nofile', 'help', 'quickfix' }, vim.bo[buf].buftype)
- local filetype = vim.tbl_contains({ 'gitcommit', 'fugitive' }, vim.bo[buf].filetype)
- if buftype or filetype then
- vim.opt_local.winbar = nil
- end
- end,
-})
-
-On_click = {
- -- get the window id of the window in which the component was evaluated
- minwid = function()
- return vim.api.nvim_get_current_win()
- end,
- callback = function(_, minwid)
- -- winid is the window id of the window the component was clicked from
- local winid = minwid
- -- do something with the window id, e.g.:
- local buf = vim.api.nvim_win_get_buf(winid)
- -- ...
- end,
-}
-
-local CloseButton = {
- condition = function(self)
- return not vim.bo.modified
- end,
- -- a small performance improvement:
- -- re register the component callback only on layout/buffer changes.
- update = { 'WinNew', 'WinClosed', 'BufEnter' },
- { provider = ' ' },
- {
- provider = '',
- hl = { fg = 'gray' },
- On_click = {
- minwid = function()
- return vim.api.nvim_get_current_win()
- end,
- callback = function(_, minwid)
- vim.api.nvim_win_close(minwid, true)
+ hl = { fg = "orange", bold = true },
+ utils.surround({ "[", "]" }, nil, {
+ provider = function()
+ return vim.fn.reg_recording()
end,
- name = 'heirline_winbar_close_button',
+ hl = { fg = "green", bold = true },
+ }),
+ update = {
+ "RecordingEnter",
+ "RecordingLeave",
+ callback = vim.schedule_wrap(function()
+ vim.cmd("redrawstatus")
+ end),
},
- },
-}
+ }
-local Center = {
- fallthrough = false,
- {
- -- Hide the winbar for special buffers
+ local ShowCmd = {
+ condition = function()
+ return vim.o.cmdheight == 0
+ end,
+ provider = ":%3.5(%S%)",
+ update = { "CmdlineChanged" },
+ }
+
+ local cursor_location = {
+ { provider = "%1(%4l:%-3(%c%)%) %*", hl = { fg = colors.black, bold = true } },
+ }
+
+ local Ruler = { cursor_location }
+
+ local WordCount = {
condition = function()
return conditions.buffer_matches({
- buftype = { 'terminal', 'nofile', 'prompt', 'help', 'quickfix' },
- filetype = { 'dap-ui', 'NvimTree', '^git.*', 'fugitive', 'dashboard' },
+ filetype = {
+ "markdown",
+ "txt",
+ "vimwiki",
+ },
})
end,
- init = function()
- vim.opt_local.winbar = nil
+ Space,
+ {
+ provider = function()
+ local ok, wordcount = pcall(vim.fn.wordcount)
+ return ok and wordcount.words and ("W:%d"):format(wordcount.words) or ""
+ end,
+ update = { "CursorMoved", "CursorMovedI", "InsertEnter", "TextChanged", "TextChangedI" },
+ },
+ }
+
+ local WorkDir = {
+ init = function(self)
+ local is_local = vim.fn.haslocaldir(0) == 1
+ self.icon = (is_local and "l" or "g") .. " " .. Icons.File.directory
+ local cwd = vim.fn.getcwd(0)
+ self.cwd = vim.fn.fnamemodify(cwd, ":~")
end,
- },
- {
- -- A special winbar for terminals
- condition = function()
- return conditions.buffer_matches({ buftype = { 'terminal' } })
+ hl = { fg = colors.blue, bold = true },
+ on_click = {
+ callback = function()
+ vim.cmd("Telescope find_files cwd=" .. vim.fn.getcwd(0))
+ end,
+ name = "heirline_workdir",
+ },
+ flexible = 1,
+ {
+ provider = function(self)
+ local trail = self.cwd:sub(-1) == "/" and "" or "/"
+ return self.icon .. " " .. self.cwd .. trail .. " "
+ end,
+ },
+ {
+ provider = function(self)
+ local cwd = vim.fn.pathshorten(self.cwd)
+ local trail = self.cwd:sub(-1) == "/" and "" or "/"
+ return self.icon .. " " .. cwd .. trail .. " "
+ end,
+ },
+ {
+ provider = function(self)
+ return self.icon .. " "
+ end,
+ },
+ }
+
+ -- Build FileNameBlock
+ FileNameBlock = utils.insert(
+ FileNameBlock,
+ FileIcon,
+ utils.insert(FileNameModifier, FileName),
+ unpack(FileFlags),
+ { provider = "%<" }
+ )
+
+ local FileInfoBlock = {
+ init = function(self)
+ self.filename = vim.api.nvim_buf_get_name(0)
end,
- FileType,
+ }
+
+ FileInfoBlock = utils.insert(
+ FileInfoBlock,
Space,
- --TerminalName,
- },
- {
- -- An inactive winbar for regular files
+ FileIcon,
+ FileType,
+ { provider = "%<" }
+ )
+
+ -- Create surrounded components with proper mode color functions
+ LeftSpace = utils.surround({ "", Icons.UI.right_separator }, function(self)
+ return self:mode_color()
+ end, { LeftSpace, hl = { fg = utils.get_highlight("statusline").bg, force = true } })
+
+ RightSpace = utils.surround({ Icons.UI.left_separator, "" }, function(self)
+ return self:mode_color()
+ end, { RightSpace, hl = { fg = utils.get_highlight("statusline").bg, force = true } })
+
+ LSPActive = utils.surround({ "", "" }, function(self)
+ return self:mode_color()
+ end, { Space, LSPActive, hl = { bg = colors.darkgray, force = true } })
+
+ FileInfoBlock = utils.surround({ "", "" }, function(self)
+ return self:mode_color()
+ end, { FileInfoBlock, Space, hl = { bg = colors.black, force = true } })
+
+ ViMode = utils.surround({ "", "" }, function(self)
+ return self:mode_color()
+ end, { ViMode, hl = { fg = colors.black, force = true } })
+
+ Ruler = utils.surround({ "", "" }, function(self)
+ return self:mode_color()
+ end, { Ruler, hl = { fg = colors.black, force = true } })
+
+ -- Statusline sections - FIXED: Removed duplicate LeftSpace from right section
+ local left = {
+ { RightSpace, hl = { bg = colors.nobg, force = true } },
+ { ViMode, hl = { bg = utils.get_highlight("statusline").bg, bold = false } },
+ { LeftSpace, hl = { bg = colors.nobg, force = true } },
+ { Space, hl = { bg = colors.nobg, force = true } },
+ { FileNameBlock, hl = { bg = colors.nobg, force = true } },
+ { Space, hl = { bg = colors.nobg, force = true } },
+ { Git, hl = { bg = colors.nobg, force = true } },
+ }
+
+ local middle = {
+ { Align, hl = { bg = colors.nobg, force = true } },
+ { Align, hl = { bg = colors.nobg, force = true } },
+ }
+
+ -- FIXED: Right section now has proper sequence without duplicate LeftSpace
+ local right = {
+ { Diagnostics, hl = { bg = colors.nobg, force = true } },
+ { Space, hl = { bg = colors.nobg, force = true } },
+ { LSPActive, hl = { bg = colors.nobg, force = true } },
+ { Space, hl = { bg = colors.nobg, force = true } },
+ { FileInfoBlock, hl = { bg = colors.nobg, force = true } },
+ { RightSpace, hl = { bg = colors.nobg, force = true } },
+ { Ruler, hl = { fg = utils.get_highlight("statusline").bg, bold = false } },
+ { LeftSpace, hl = { bg = colors.nobg, force = true } },
+ }
+
+ local sections = { left, middle, right }
+ local DefaultStatusline = { sections }
+
+ -- Special statuslines for inactive/special buffers
+ local specialleft = {
+ { RightSpace, hl = { bg = colors.nobg, force = true } },
+ { ViMode, hl = { bg = utils.get_highlight("statusline").bg, bold = false } },
+ { LeftSpace, hl = { bg = colors.nobg, force = true } },
+ }
+
+ local specialmiddle = {
+ { Align, hl = { bg = colors.nobg, force = true } },
+ { Align, hl = { bg = colors.nobg, force = true } },
+ }
+
+ local specialright = {
+ { RightSpace, hl = { bg = colors.nobg, force = true } },
+ { Ruler, hl = { fg = utils.get_highlight("statusline").bg, bold = false } },
+ { LeftSpace, hl = { bg = colors.nobg, force = true } },
+ }
+
+ local specialsections = { specialleft, specialmiddle, specialright }
+
+ local InactiveStatusline = {
+ condition = conditions.is_not_active,
+ specialsections,
+ }
+
+ local SpecialStatusline = {
condition = function()
- return not conditions.is_active()
+ return conditions.buffer_matches({
+ buftype = { "nofile", "prompt", "help", "quickfix" },
+ filetype = { "^git.*", "fugitive", "dashboard" },
+ })
end,
- --utils.surround({ "", "" }, colors.nobg, { FileIcon, { WinbarFileName, hl = { fg = colors.gray } }, FileFlags } ),
- utils.surround({ '', '' }, colors.nobg, { WinbarFileNameBlock }),
- },
- -- A winbar for regular files
- utils.surround({ '', '' }, colors.nobg, { FileNameBlock }),
-}
-
---local WinBar = { Align, Center, Align }
-local WinBar = { Space, Center }
-
--- TabLine
---local TablineBufnr = {
--- provider = function(self)
--- return tostring(self.bufnr) .. "."
--- end,
--- hl = { fg = colors.white, bold = false },
----- hl = "Comment",
---}
+ specialsections,
+ }
+
+ local TerminalStatusline = {
+ condition = function()
+ return conditions.buffer_matches({ buftype = { "terminal" } })
+ end,
+ specialsections,
+ }
+
+ -- FIXED: Main StatusLine with better mode handling
+ local StatusLine = {
+ static = {
+ mode_colors = {
+ n = colors.blue,
+ no = colors.blue,
+ nov = colors.blue,
+ noV = colors.blue,
+ ["no\22"] = colors.blue,
+ niI = colors.blue,
+ niR = colors.blue,
+ niV = colors.blue,
+ nt = colors.blue,
+ v = colors.purple,
+ vs = colors.purple,
+ V = colors.purple,
+ ["\22"] = colors.purple,
+ ["\22s"] = colors.purple,
+ s = colors.purple,
+ S = colors.purple,
+ ["\19"] = colors.purple,
+ i = colors.green,
+ ix = colors.green,
+ ic = colors.green,
+ R = colors.red,
+ Rc = colors.red,
+ Rx = colors.red,
+ Rv = colors.red,
+ Rvc = colors.red,
+ Rvx = colors.red,
+ c = colors.orange,
+ cv = colors.orange,
+ ce = colors.orange,
+ r = colors.red,
+ rm = colors.red,
+ ["r?"] = colors.red,
+ ["!"] = colors.orange,
+ t = colors.orange,
+ },
+ mode_color = function(self)
+ -- FIXED: Always get current mode to ensure updates
+ local mode = vim.fn.mode()
+ return self.mode_colors[mode] or colors.blue
+ end,
+ },
+ -- FIXED: Add update triggers to ensure statusline refreshes properly
+ update = {
+ "ModeChanged",
+ "BufEnter",
+ "WinEnter",
+ "WinLeave",
+ "BufWinEnter",
+ "CmdlineLeave",
+ callback = vim.schedule_wrap(function()
+ vim.cmd("redrawstatus")
+ end),
+ },
+ fallthrough = false,
+ SpecialStatusline,
+ TerminalStatusline,
+ InactiveStatusline,
+ DefaultStatusline,
+ }
+
+ -- WinBar components
+ local WinbarFileNameBlock = {
+ init = function(self)
+ self.filename = vim.api.nvim_buf_get_name(0)
+ end,
+ hl = { bg = colors.bg },
+ }
--- we redefine the filename component, as we probably only want the tail and not the relative path
-local TablineFileName = {
- provider = function(self)
- -- self.filename will be defined later, just keep looking at the example!
- local filename = self.filename
- filename = filename == '' and 'No Name' or vim.fn.fnamemodify(filename, ':t')
- return filename
- end,
- hl = function(self)
- return { fg = colors.white, bold = self.is_active or self.is_visible, italic = true }
- end,
-}
-
-local TablineFileFlags = {
- {
+ local WinbarFileName = {
provider = function(self)
- if vim.bo[self.bufnr].modified then
- return ' [+] '
+ local filename = vim.fn.fnamemodify(self.filename, ":.")
+ if filename == "" then
+ return "No Name"
+ end
+ if not conditions.width_percent_below(#filename, 0.25) then
+ filename = vim.fn.pathshorten(filename)
end
+ return filename
end,
- hl = { fg = colors.green },
- },
- {
- provider = function(self)
- if not vim.bo[self.bufnr].modifiable or vim.bo[self.bufnr].readonly then
- return '  '
+ hl = { fg = colors.gray, bold = false, bg = colors.bg },
+ }
+
+ WinbarFileNameBlock = utils.insert(
+ WinbarFileNameBlock,
+ FileIcon,
+ utils.insert(WinbarFileName),
+ unpack(FileFlags),
+ { provider = "%<" }
+ )
+
+ vim.api.nvim_create_autocmd("User", {
+ pattern = "HeirlineInitWinbar",
+ callback = function(args)
+ local buf = args.buf
+ local buftype = vim.tbl_contains({ "prompt", "nofile", "help", "quickfix" }, vim.bo[buf].buftype)
+ local filetype = vim.tbl_contains({ "gitcommit", "fugitive" }, vim.bo[buf].filetype)
+ if buftype or filetype then
+ vim.opt_local.winbar = nil
end
end,
- hl = { fg = 'orange' },
- },
-}
-
-local TablineFileIcon = {
- init = function(self)
- local filename = self.filename
- local extension = vim.fn.fnamemodify(filename, ':e')
- self.icon, self.icon_color = require('nvim-web-devicons').get_icon_color(filename, extension, { default = true })
- end,
- provider = function(self)
- return self.icon and (' ' .. self.icon .. ' ')
- end,
- hl = function(self)
- return { fg = self.icon_color }
- end,
-}
-
--- Here the filename block finally comes together
-local TablineFileNameBlock = {
- init = function(self)
- self.filename = vim.api.nvim_buf_get_name(self.bufnr)
- end,
- hl = function(self)
- if self.is_active then
- return 'TabLineSel'
- -- why not?
- --elseif not vim.api.nvim_buf_is_loaded(self.bufnr) then
- --return { fg = "gray", bg = colors.bg }
- else
- return 'TabLineFill'
- end
- end,
- on_click = {
- callback = function(_, minwid, _, button)
- if button == 'm' then -- close on mouse middle click
- vim.api.nvim_buf_delete(minwid, { force = false })
+ })
+
+ local On_click = {
+ minwid = function()
+ return vim.api.nvim_get_current_win()
+ end,
+ callback = function(_, minwid)
+ local winid = minwid
+ local buf = vim.api.nvim_win_get_buf(winid)
+ end,
+ }
+
+ local CloseButton = {
+ condition = function(self)
+ return not vim.bo.modified
+ end,
+ update = { "WinNew", "WinClosed", "BufEnter" },
+ { provider = " " },
+ {
+ provider = Icons.UI.close,
+ hl = { fg = "gray" },
+ On_click = {
+ minwid = function()
+ return vim.api.nvim_get_current_win()
+ end,
+ callback = function(_, minwid)
+ vim.api.nvim_win_close(minwid, true)
+ end,
+ name = "heirline_winbar_close_button",
+ },
+ },
+ }
+
+ local Center = {
+ fallthrough = false,
+ {
+ condition = function()
+ return conditions.buffer_matches({
+ buftype = { "terminal", "nofile", "prompt", "help", "quickfix" },
+ filetype = { "dap-ui", "NvimTree", "^git.*", "fugitive", "dashboard" },
+ })
+ end,
+ init = function()
+ vim.opt_local.winbar = nil
+ end,
+ },
+ {
+ condition = function()
+ return conditions.buffer_matches({ buftype = { "terminal" } })
+ end,
+ FileType,
+ Space,
+ },
+ {
+ condition = function()
+ return not conditions.is_active()
+ end,
+ utils.surround({ "", "" }, colors.nobg, { WinbarFileNameBlock }),
+ },
+ utils.surround({ "", "" }, colors.nobg, { FileNameBlock }),
+ }
+
+ local WinBar = { Space, Center }
+
+ -- Tabline components
+ local TablineFileIcon = {
+ init = function(self)
+ local filename = self.filename
+ local extension = vim.fn.fnamemodify(filename, ":e")
+
+ local has_nerd_fonts = vim.g.statusline_has_nerd_fonts
+ if has_nerd_fonts == nil then
+ if vim.fn.has('unix') == 1 and vim.fn.executable('fc-list') == 1 then
+ local handle = io.popen('fc-list | grep -i nerd')
+ local result = handle:read('*a')
+ handle:close()
+ has_nerd_fonts = result ~= ""
+ else
+ has_nerd_fonts = false
+ end
+ vim.g.statusline_has_nerd_fonts = has_nerd_fonts
+ end
+
+ if has_nerd_fonts then
+ self.icon, self.icon_color = require("nvim-web-devicons").get_icon_color(filename, extension, { default = true })
else
- vim.api.nvim_win_set_buf(0, minwid)
+ self.icon = ""
+ self.icon_color = colors.blue
+
+ if vim.fn.isdirectory(filename) == 1 then
+ self.icon = "[DIR]"
+ else
+ local file_icon = Icons.File[extension:lower()] or Icons.File.default
+ if type(file_icon) == "table" then
+ self.icon = file_icon[1] or Icons.File.default
+ else
+ self.icon = file_icon
+ end
+ end
+ end
+
+ if self.icon ~= "" then
+ self.icon = self.icon .. " "
end
end,
- minwid = function(self)
- return self.bufnr
+ provider = function(self)
+ return self.icon or ""
+ end,
+ hl = function(self)
+ return { fg = self.icon_color or colors.blue }
+ end,
+ }
+
+ local TablineFileName = {
+ provider = function(self)
+ local filename = vim.fn.fnamemodify(self.filename, ":t")
+ if filename == "" then
+ return "[No Name]"
+ end
+ return filename
+ end,
+ }
+
+ local TablineFileFlags = {
+ {
+ condition = function(self)
+ return vim.api.nvim_buf_get_option(self.bufnr, "modified")
+ end,
+ provider = "%X " .. Icons.Indicator.plus .. " %X",
+ hl = { fg = "green" },
+ },
+ {
+ condition = function(self)
+ return not vim.api.nvim_buf_get_option(self.bufnr, "modifiable") or vim.api.nvim_buf_get_option(self.bufnr, "readonly")
+ end,
+ provider = function()
+ if vim.bo.readonly then
+ return " " .. Icons.UI.lock
+ end
+ return ""
+ end,
+ hl = { fg = "orange" },
+ },
+ }
+
+ local TablineFileNameBlock = {
+ init = function(self)
+ self.filename = vim.api.nvim_buf_get_name(self.bufnr)
+ end,
+ hl = function(self)
+ if self.is_active then
+ return "TabLineSel"
+ else
+ return "TabLineFill"
+ end
end,
- name = 'heirline_tabline_buffer_callback',
- },
- --TablineBufnr,
- TablineFileIcon,
- TablineFileName,
- TablineFileFlags,
-}
-
--- a nice "x" button to close the buffer
-local TablineCloseButton = {
- condition = function(self)
- return not vim.api.nvim_buf_get_option(self.bufnr, 'modified')
- end,
- { provider = ' ' },
- {
- provider = ' ',
- --hl = { fg = "red", bg = colors.bg },
- hl = { fg = colors.red },
on_click = {
- callback = function(_, minwid)
- vim.api.nvim_buf_delete(minwid, { force = false })
+ callback = function(_, minwid, _, button)
+ if button == "m" then
+ vim.api.nvim_buf_delete(minwid, { force = false })
+ else
+ vim.api.nvim_win_set_buf(0, minwid)
+ end
end,
minwid = function(self)
return self.bufnr
end,
- name = 'heirline_tabline_close_buffer_callback',
+ name = "heirline_tabline_buffer_callback",
},
- },
-}
-
--- The final touch!
-local TablineBufferBlock = utils.surround({ '', '' }, function(self)
- --local TablineBufferBlock = utils.surround({ "█", "█" }, function(self)
- if self.is_active then
- return utils.get_highlight('TabLineSel').bg
- else
- return utils.get_highlight('TabLineFill').bg
- end
-end, { Tab, TablineFileNameBlock, TablineCloseButton })
-
-local BufferLine = utils.make_buflist(
- TablineBufferBlock,
- { provider = ' ', hl = { fg = colors.white } }, -- left truncation, optional (defaults to "<")
- { provider = ' ', hl = { fg = colors.white } } -- right trunctation, also optional (defaults to ...... yep, ">")
--- by the way, open a lot of buffers and try clicking them ;)
-)
--- TabList
-local Tabpage = {
- provider = function(self)
- return '%' .. self.tabnr .. 'T ' .. self.tabnr .. ' %T'
- end,
- hl = function(self)
- if not self.is_active then
- return 'TabLineFill'
+ TablineFileIcon,
+ TablineFileName,
+ TablineFileFlags,
+ }
+
+ local TablineCloseButton = {
+ condition = function(self)
+ return not vim.api.nvim_buf_get_option(self.bufnr, "modified")
+ end,
+ { provider = " " },
+ {
+ provider = "" .. Icons.UI.close .. " %X",
+ hl = { fg = colors.red },
+ on_click = {
+ callback = function(_, minwid)
+ vim.api.nvim_buf_delete(minwid, { force = false })
+ end,
+ minwid = function(self)
+ return self.bufnr
+ end,
+ name = "heirline_tabline_close_buffer_callback",
+ },
+ },
+ }
+
+ local TablineBufferBlock = utils.surround({ "", "" }, function(self)
+ if self.is_active then
+ return utils.get_highlight("TabLineSel").bg
else
- return 'TabLineSel'
+ return utils.get_highlight("TabLineFill").bg
end
- end,
-}
-
-local TabpageClose = {
- provider = '%999X  %X',
- --hl = "TabLine",
- hl = { fg = colors.red, bg = colors.bg },
-}
-
-local TabPages = {
- -- only show this component if there's 2 or more tabpages
- condition = function()
- return #vim.api.nvim_list_tabpages() >= 2
- end,
- {
- provider = '%=',
- },
- utils.make_tablist(Tabpage),
- TabpageClose,
-}
-
--- TabLineOffset
-local TabLineOffset = {
- condition = function(self)
- local win = vim.api.nvim_tabpage_list_wins(0)[1]
- local bufnr = vim.api.nvim_win_get_buf(win)
- self.winid = win
-
- if vim.api.nvim_buf_get_option(bufnr, 'filetype') == 'NvimTree' then
- self.title = 'NvimTree'
- return true
+ end, { Tab, TablineFileNameBlock, TablineCloseButton })
+
+ local BufferLine = utils.make_buflist(
+ TablineBufferBlock,
+ { provider = Icons.Symbol.arrow_left, hl = { fg = colors.gray } },
+ { provider = Icons.Symbol.arrow_right, hl = { fg = colors.gray } }
+ )
+
+ local Tabpage = {
+ provider = function(self)
+ return "%" .. self.tabnr .. "T " .. self.tabnr .. " %T"
+ end,
+ hl = function(self)
+ return self.is_active and "TabLineSel" or "TabLineFill"
+ end,
+ }
+
+ local TabpageClose = {
+ provider = "%999X " .. Icons.UI.close .. " %X",
+ hl = { fg = colors.red, bg = colors.bg },
+ }
+
+ local TabPages = {
+ condition = function()
+ return #vim.api.nvim_list_tabpages() >= 2
+ end,
+ { provider = "%=" },
+ utils.make_tablist(Tabpage),
+ TabpageClose,
+ }
+
+ local TabLineOffset = {
+ condition = function(self)
+ local win = vim.api.nvim_tabpage_list_wins(0)[1]
+ local bufnr = vim.api.nvim_win_get_buf(win)
+ self.winid = win
+
+ if vim.api.nvim_buf_get_option(bufnr, "filetype") == "NvimTree" then
+ self.title = "NvimTree"
+ return true
+ end
+ end,
+ provider = function(self)
+ local title = self.title
+ local width = vim.api.nvim_win_get_width(self.winid)
+ local pad = math.ceil((width - #title) / 2)
+ return string.rep(" ", pad) .. title .. string.rep(" ", pad)
+ end,
+ hl = { fg = colors.white, bg = "#333842", bold = true },
+ }
+
+ local TabLine = {
+ TabLineOffset,
+ BufferLine,
+ TabPages,
+ }
+
+ -- Buffer navigation functions
+ local function get_bufs()
+ return vim.tbl_filter(function(bufnr)
+ return vim.api.nvim_buf_is_loaded(bufnr) and vim.bo[bufnr].buflisted
+ end, vim.api.nvim_list_bufs())
+ end
+
+ local function goto_buf(index)
+ local bufs = get_bufs()
+ if index > #bufs then
+ index = #bufs
end
- end,
- provider = function(self)
- local title = self.title
- local width = vim.api.nvim_win_get_width(self.winid)
- local pad = math.ceil((width - #title) / 2)
- return string.rep(' ', pad) .. title .. string.rep(' ', pad)
- end,
- hl = { fg = colors.white, bg = '#333842', bold = true },
-
- --hl = function(self)
- -- if vim.api.nvim_get_current_win() == self.winid then
- -- return 'TablineSel'
- -- else
- -- return 'TablineFill'
- -- end
- --end,
-}
-
-local TabLine = {
- TabLineOffset,
- BufferLine,
- TabPages,
-}
-
-require('heirline').setup({
- statusline = StatusLine,
- winbar = WinBar,
- tabline = TabLine,
- --statuscolumn = StatusColumn
-})
-
--- Yep, with heirline we're driving manual!
-vim.o.showtabline = 2
-vim.cmd([[au FileType * if index(['wipe', 'delete', 'unload'], &bufhidden) >= 0 | set nobuflisted | endif]])
-
-local function get_bufs()
- return vim.tbl_filter(function(bufnr)
- return vim.api.nvim_buf_is_loaded(bufnr) and vim.bo[bufnr].buflisted
- end, vim.api.nvim_list_bufs())
-end
+ vim.api.nvim_win_set_buf(0, bufs[index])
+ end
-local function goto_buf(index)
- local bufs = get_bufs()
- if index > #bufs then
- index = #bufs
+ local function add_key(key, index)
+ vim.keymap.set("n", "<A-" .. key .. ">", function()
+ goto_buf(index)
+ end, { noremap = true, silent = true })
end
- vim.api.nvim_win_set_buf(0, bufs[index])
-end
-local function addKey(key, index)
- vim.keymap.set('', '<A-' .. key .. '>', function()
- goto_buf(index)
- end, { noremap = true, silent = true })
-end
+ for i = 1, 9 do
+ add_key(i, i)
+ end
+ add_key("0", 10)
+
+ vim.o.showtabline = 2
+ vim.cmd([[au FileType * if index(['wipe', 'delete', 'unload'], &bufhidden) >= 0 | set nobuflisted | endif]])
+
+ -- FIXED: Add proper autocmds for better statusline updates
+ local augroup = vim.api.nvim_create_augroup("HeirlineStatusline", { clear = true })
+
+ -- Force statusline refresh on mode changes and buffer events
+ vim.api.nvim_create_autocmd({
+ "ModeChanged",
+ "BufEnter",
+ "BufWinEnter",
+ "WinEnter",
+ "WinLeave",
+ "CmdlineLeave",
+ "TermEnter",
+ "TermLeave"
+ }, {
+ group = augroup,
+ callback = function()
+ vim.schedule(function()
+ if vim.o.laststatus > 0 then
+ vim.cmd("redrawstatus!")
+ end
+ end)
+ end,
+ })
+
+ -- Final heirline setup
+ heirline.setup({
+ statusline = StatusLine,
+ winbar = WinBar,
+ tabline = TabLine,
+ opts = {
+ disable_winbar_cb = function(args)
+ local buf = args.buf
+ if not vim.api.nvim_buf_is_valid(buf) then
+ return true
+ end
+
+ local buftype = vim.tbl_contains(
+ { "prompt", "nofile", "help", "quickfix" },
+ vim.bo[buf].buftype
+ )
+ local filetype = vim.tbl_contains(
+ { "gitcommit", "fugitive" },
+ vim.bo[buf].filetype
+ )
+ return buftype or filetype
+ end,
+ }
+ })
-for i = 1, 9 do
- addKey(i, i)
end
-addKey('0', 10)
+
+return M
diff --git a/common/config/nvim/lua/plugins/indent-blankline.lua b/common/config/nvim/lua/plugins/indent-blankline.lua
index 25a2da0..cbbcf27 100644..100755
--- a/common/config/nvim/lua/plugins/indent-blankline.lua
+++ b/common/config/nvim/lua/plugins/indent-blankline.lua
@@ -1,24 +1,73 @@
---local highlight = {
--- "RainbowRed",
--- "RainbowYellow",
--- "RainbowBlue",
--- "RainbowOrange",
--- "RainbowGreen",
--- "RainbowViolet",
--- "RainbowCyan",
---}
---
---local hooks = require("ibl.hooks")
----- create the highlight groups in the highlight setup hook, so they are reset
----- every time the colorscheme changes
---hooks.register(hooks.type.HIGHLIGHT_SETUP, function()
--- vim.api.nvim_set_hl(0, "RainbowRed", { fg = "#E06C75" })
--- vim.api.nvim_set_hl(0, "RainbowYellow", { fg = "#E5C07B" })
--- vim.api.nvim_set_hl(0, "RainbowBlue", { fg = "#61AFEF" })
--- vim.api.nvim_set_hl(0, "RainbowOrange", { fg = "#D19A66" })
--- vim.api.nvim_set_hl(0, "RainbowGreen", { fg = "#98C379" })
--- vim.api.nvim_set_hl(0, "RainbowViolet", { fg = "#C678DD" })
--- vim.api.nvim_set_hl(0, "RainbowCyan", { fg = "#56B6C2" })
---end)
+local M = {}
-require("ibl").setup({ indent = { highlight = highlight } })
+--- Setup and configure indent-blankline.nvim
+-- This function initializes and configures the indent guides
+-- @return boolean True if setup was successful, false otherwise
+function M.setup()
+ local ok, ibl = pcall(require, 'ibl')
+ if not ok then
+ return false
+ end
+
+ local highlight = {
+ "RainbowRed",
+ "RainbowYellow",
+ "RainbowBlue",
+ "RainbowOrange",
+ "RainbowGreen",
+ "RainbowViolet",
+ "RainbowCyan",
+ }
+
+ local hooks = require("ibl.hooks")
+ -- create the highlight groups in the highlight setup hook, so they are reset
+ -- every time the colorscheme changes
+ hooks.register(hooks.type.HIGHLIGHT_SETUP, function()
+ vim.api.nvim_set_hl(0, "RainbowRed", { fg = "#E06C75" })
+ vim.api.nvim_set_hl(0, "RainbowYellow", { fg = "#E5C07B" })
+ vim.api.nvim_set_hl(0, "RainbowBlue", { fg = "#61AFEF" })
+ vim.api.nvim_set_hl(0, "RainbowOrange", { fg = "#D19A66" })
+ vim.api.nvim_set_hl(0, "RainbowGreen", { fg = "#98C379" })
+ vim.api.nvim_set_hl(0, "RainbowViolet", { fg = "#C678DD" })
+ vim.api.nvim_set_hl(0, "RainbowCyan", { fg = "#56B6C2" })
+ end)
+
+ ibl.setup({
+ indent = { highlight = highlight },
+ exclude = {
+ filetypes = {
+ "", -- for all buffers without a file type
+ "NvimTree",
+ "Trouble",
+ "TelescopePrompt",
+ "TelescopeResults",
+ "mason",
+ "help",
+ "dashboard",
+ "packer",
+ "neogitstatus",
+ "Trouble",
+ "text",
+ "terminal",
+ "lazy",
+ },
+ buftypes = {
+ "terminal",
+ "nofile",
+ "quickfix",
+ "prompt",
+ },
+ },
+ })
+
+ -- Toggle indent blankline with <leader>ti
+ vim.keymap.set('n', '<leader>ti', '<cmd>IBLToggle<CR>', {
+ noremap = true,
+ silent = true,
+ desc = 'Toggle indent guides'
+ })
+
+ return true
+end
+
+return M
diff --git a/common/config/nvim/lua/plugins/interestingwords.lua b/common/config/nvim/lua/plugins/interestingwords.lua
new file mode 100755
index 0000000..655ed42
--- /dev/null
+++ b/common/config/nvim/lua/plugins/interestingwords.lua
@@ -0,0 +1,499 @@
+local interestingwords = (function()
+ local api = vim.api
+ local fn = vim.fn
+ local uv = vim.loop
+
+ local m = {}
+
+ m.words = {}
+ m.colors = {}
+ m.limits = {}
+ m.capcity = 0
+ m.next = 1
+
+ local get_default_config = function()
+ return {
+ colors = { "#aeee00", "#ff0000", "#0000ff", "#b88823", "#ffa724", "#ff2c4b" },
+ search_count = true,
+ navigation = true,
+ scroll_center = true,
+ search_key = "<leader>hl",
+ cancel_search_key = "<leader>lh",
+ color_key = "<leader>ih",
+ cancel_color_key = "<leader>hi",
+ select_mode = "random", -- random or loop
+ }
+ end
+
+ local init_colors = function()
+ for i, v in pairs(m.config.colors) do
+ local color = "InterestingWord" .. i
+
+ api.nvim_set_hl(0, color, { bg = v, fg = "Black" })
+ m.colors[color] = 595129 + i
+ m.capcity = m.capcity + 1
+ end
+ m.limits.min = 595129 + 1
+ m.limits.max = 595129 + #m.config.colors
+ end
+
+ local get_reg_ex = function(word)
+ if vim.o.ignorecase and (not vim.o.smartcase or fn.match(word, "\\u") == -1) then
+ return "\\c\\V" .. word
+ else
+ return "\\C\\V" .. word
+ end
+ end
+
+ local get_visual_selection = function()
+ local lines
+ local start_row, start_col = fn.getpos("v")[2], fn.getpos("v")[3]
+ local end_row, end_col = fn.getpos(".")[2], fn.getpos(".")[3]
+ if end_row < start_row then
+ start_row, end_row = end_row, start_row
+ start_col, end_col = end_col, start_col
+ elseif end_row == start_row and end_col < start_col then
+ start_col, end_col = end_col, start_col
+ end
+ start_row = start_row - 1
+ start_col = start_col - 1
+ end_row = end_row - 1
+ if api.nvim_get_mode().mode == "V" then
+ lines = api.nvim_buf_get_text(0, start_row, 0, end_row, -1, {})
+ elseif api.nvim_get_mode().mode == "v" then
+ lines = api.nvim_buf_get_text(0, start_row, start_col, end_row, end_col, {})
+ end
+ vim.cmd("normal! ")
+ if lines == nil then
+ return ""
+ end
+
+ local line = ""
+ for i, v in ipairs(lines) do
+ if i == 1 then
+ line = line .. fn.escape(v, "\\")
+ else
+ line = line .. "\\n" .. fn.escape(v, "\\")
+ end
+ end
+
+ return line
+ end
+
+ local uncolor = function(word)
+ if m.words[word] then
+ local windows = api.nvim_list_wins()
+ for _, i in ipairs(windows) do
+ pcall(function()
+ fn.matchdelete(m.words[word].mid, i)
+ end)
+ end
+ m.colors[m.words[word].color] = m.words[word].mid
+ m.words[word] = nil
+ end
+ end
+
+ local get_rest_color_random = function()
+ local res = {}
+ for k, v in pairs(m.colors) do
+ if v ~= 0 then
+ table.insert(res, { color = k, mid = v })
+ end
+ end
+ if #res == 0 then
+ return nil
+ end
+
+ return res[math.random(#res)]
+ end
+
+ local find_who_use_this = function(target_color)
+ for word, color in pairs(m.words) do
+ if color.color == target_color then
+ return word
+ end
+ end
+ return nil
+ end
+
+ local get_rest_color_loop = function()
+ if m.next > m.capcity then
+ m.next = 1
+ end
+ local color = "InterestingWord" .. m.next
+ if m.colors[color] == 0 then
+ local word = find_who_use_this(color)
+ if word ~= nil then
+ uncolor(word)
+ else
+ return nil
+ end
+ end
+ m.next = m.next + 1
+ return { color = color, mid = m.colors[color] }
+ end
+
+ local get_rest_color = function()
+ local selector = {
+ ["random"] = get_rest_color_random,
+ ["loop"] = get_rest_color_loop,
+ }
+ return selector[m.config.select_mode]()
+ end
+
+ local color = function(word)
+ local color = get_rest_color()
+ if not color then
+ vim.notify("InterestingWords: max number of highlight groups reached")
+ return
+ end
+
+ m.words[word] = {}
+ m.words[word].color = color.color
+ m.words[word].mid = color.mid
+ m.colors[color.color] = 0
+
+ local windows = api.nvim_list_wins()
+ for _, i in ipairs(windows) do
+ pcall(function()
+ fn.matchadd(m.words[word].color, word, 1, m.words[word].mid, { window = i })
+ end)
+ end
+ end
+
+ local recolorAllWords = function()
+ for k, v in pairs(m.words) do
+ pcall(function()
+ fn.matchadd(v.color, k, 1, v.mid, { window = 0 })
+ end)
+ end
+ end
+
+ local nearest_word_at_cursor = function()
+ for _, match_item in pairs(fn.getmatches()) do
+ if match_item.id >= m.limits.min or match_item.id <= m.limits.max then
+ local buf_content = fn.join(api.nvim_buf_get_lines(0, 0, -1, {}), "\n")
+ local cur_pos = #fn.join(api.nvim_buf_get_lines(0, 0, fn.line(".") - 1, {}), "\n") +
+ ((fn.line(".") == 1) and 0 or 1) + fn.col(".") - 1
+ local lst_pos = 0
+ while true do
+ local mat_pos = fn.matchstrpos(buf_content, match_item.pattern, lst_pos, 1)
+ if mat_pos[1] == "" then
+ break
+ end
+ if cur_pos >= mat_pos[2] and cur_pos < mat_pos[3] then
+ return match_item.pattern
+ end
+ lst_pos = mat_pos[3]
+ end
+ end
+ end
+ end
+
+ local filter = function(word)
+ if #word <= 4 or (string.sub(word, 1, 4) ~= "\\c\\V" and string.sub(word, 1, 4) ~= "\\C\\V") then
+ return word
+ else
+ return string.sub(word, 5, -1)
+ end
+ end
+
+ local display_search_count = function(word, count)
+ local icon = ""
+ m.search_count_extmark_id = api.nvim_buf_set_extmark(0, m.search_count_namespace, fn.line(".") - 1, 0, {
+ virt_text_pos = "eol",
+ virt_text = {
+ { icon .. count, "NonText" },
+ },
+ hl_mode = "combine",
+ })
+ m.search_count_cache = icon .. " " .. filter(word) .. count
+ m.search_count_timer:again()
+ end
+
+ local hide_search_count = function(bufnr)
+ if m.search_count_namespace then
+ api.nvim_buf_del_extmark(bufnr, m.search_count_namespace, m.search_count_extmark_id)
+ end
+ end
+
+ local scroll_timer = vim.loop.new_timer()
+ local function scroll_up(cnt)
+ return vim.cmd("normal! " .. cnt .. "")
+ end
+
+ local function scroll_down(cnt)
+ return vim.cmd("normal! " .. cnt .. "")
+ end
+
+ local function stop_scrolling()
+ scroll_timer:stop()
+ end
+
+ local scroll_to_center = function()
+ local window_height = api.nvim_win_get_height(0)
+ local lines = fn.winline() - math.floor(window_height / 2)
+ if lines == 0 then
+ return
+ end
+ local up = lines > 0
+ lines = math.abs(lines)
+
+ local move_lines = function(n)
+ return math.floor(n / 5) + 1
+ end
+
+ local each_time = function()
+ local lines_bak = lines
+ local circles = 0
+ while lines_bak ~= 0 do
+ lines_bak = lines_bak - move_lines(lines_bak)
+ circles = circles + 1
+ end
+ local pseudo_total_time = 300 + 15 * math.min((lines - 11), 10) + lines
+ return math.floor(pseudo_total_time / circles)
+ end
+ local t = each_time()
+ local time_total = 0
+
+ local scroll_callback = function()
+ local cnt = move_lines(lines)
+ if lines == 0 then
+ stop_scrolling()
+ return
+ else
+ lines = lines - cnt
+ end
+
+ if up then
+ scroll_up(cnt)
+ else
+ scroll_down(cnt)
+ end
+ time_total = time_total + t
+ end
+
+ scroll_timer:start(t, t, vim.schedule_wrap(scroll_callback))
+ end
+
+ m.lualine_get = function()
+ return m.search_count_cache
+ end
+
+ m.lualine_has = function()
+ return m.search_count_cache ~= ""
+ end
+
+ m.init_search_count = function()
+ m.search_count_extmark_id = 0
+ m.search_count_namespace = api.nvim_create_namespace("custom/search_count")
+ m.search_count_timer = vim.loop.new_timer()
+ m.search_count_timer:start(0, 5000, function()
+ m.search_count_cache = ""
+ vim.defer_fn(function()
+ hide_search_count(0)
+ end, 100)
+ m.search_count_timer:stop()
+ end)
+
+ vim.api.nvim_create_autocmd({ "CmdlineLeave" }, {
+ pattern = { "*" },
+ callback = function(event)
+ if vim.v.event.abort then
+ return
+ end
+ if event.match == "/" or event.match == "?" then
+ vim.defer_fn(function()
+ local searched = m.search_count(fn.getreg("/"))
+ if searched and m.config.scroll_center then
+ scroll_to_center()
+ end
+ end, 100)
+ end
+ end,
+ })
+ end
+
+ m.search_count = function(word)
+ hide_search_count(0)
+ if word == "" then
+ return false
+ end
+
+ local cur_cnt = 0
+ local total_cnt = 0
+ local buf_content = fn.join(api.nvim_buf_get_lines(0, 0, -1, {}), "\n")
+ local cur_pos = #fn.join(api.nvim_buf_get_lines(0, 0, fn.line(".") - 1, {}), "\n") + ((fn.line(".") == 1) and 0 or 1) +
+ fn.col(".") - 1
+ local lst_pos = 0
+ while true do
+ local mat_pos = fn.matchstrpos(buf_content, word, lst_pos, 1)
+ if mat_pos[1] == "" then
+ break
+ end
+ total_cnt = total_cnt + 1
+ if cur_pos >= mat_pos[2] and cur_pos < mat_pos[3] then
+ cur_cnt = total_cnt
+ end
+ lst_pos = mat_pos[3]
+ end
+
+ if total_cnt == 0 or cur_cnt == 0 then
+ return false
+ end
+
+ local count = " [" .. cur_cnt .. "/" .. total_cnt .. "]"
+ display_search_count(word, count)
+
+ return true
+ end
+
+ m.NavigateToWord = function(forward)
+ local word = nearest_word_at_cursor()
+ if not word then
+ word = fn.getreg("/")
+ end
+ if word == "" then
+ return
+ end
+
+ local search_flag = ""
+ if not forward then
+ search_flag = "b"
+ end
+ local n = fn.search(word, search_flag)
+ if n ~= 0 then
+ if m.config.scroll_center then
+ scroll_to_center()
+ end
+ else
+ vim.notify("Pattern not found: " .. filter(word))
+ return
+ end
+
+ if m.config.search_count then
+ m.search_count(word)
+ end
+ end
+
+ m.InterestingWord = function(mode, search)
+ local word = ""
+ if mode == "v" then
+ word = get_visual_selection()
+ else
+ word = "\\<" .. fn.expand("<cword>") .. "\\>"
+ end
+ if #word == 0 then
+ return
+ end
+ word = get_reg_ex(word)
+
+ if search then
+ if word == fn.getreg("/") then
+ fn.setreg("/", "")
+ word = ""
+ else
+ fn.setreg("/", word)
+ vim.cmd("set hls")
+ end
+ else
+ if m.words[word] then
+ uncolor(word)
+ word = ""
+ else
+ color(word)
+ end
+ end
+
+ if m.config.search_count then
+ m.search_count(word)
+ end
+ end
+
+ m.UncolorAllWords = function(search)
+ m.search_count("")
+ if search then
+ fn.setreg("/", "")
+ else
+ local windows = api.nvim_list_wins()
+ for _, v in pairs(m.words) do
+ for _, i in ipairs(windows) do
+ pcall(function()
+ fn.matchdelete(v.mid, i)
+ end)
+ end
+ m.colors[v.color] = v.mid
+ end
+
+ m.words = {}
+ end
+ end
+
+ m.setup = function(opt)
+ opt = opt or {}
+ m.config = vim.tbl_deep_extend("force", get_default_config(), opt)
+
+ init_colors()
+ math.randomseed(uv.now())
+
+ local group = api.nvim_create_augroup("InterestingWordsGroup", { clear = true })
+ api.nvim_create_autocmd({ "WinEnter" }, {
+ callback = function()
+ recolorAllWords()
+ local windows = api.nvim_list_wins()
+ for _, i in ipairs(windows) do
+ hide_search_count(api.nvim_win_get_buf(fn.win_getid(i)))
+ end
+ end,
+ group = group,
+ })
+
+ if m.config.navigation then
+ vim.keymap.set("n", "n", function()
+ m.NavigateToWord(true)
+ end, { noremap = true, silent = true, desc = "InterestingWord Navigation Forward" })
+ vim.keymap.set("n", "N", m.NavigateToWord,
+ { noremap = true, silent = true, desc = "InterestingWord Navigation Backword" })
+ end
+
+ if m.config.search_key then
+ vim.keymap.set("n", m.config.search_key, function()
+ m.InterestingWord("n", true)
+ end, { noremap = true, silent = true, desc = "InterestingWord Toggle Search" })
+ vim.keymap.set("x", m.config.search_key, function()
+ m.InterestingWord("v", true)
+ end, { noremap = true, silent = true, desc = "InterestingWord Toggle Search" })
+ vim.keymap.set("n", m.config.cancel_search_key, function()
+ m.UncolorAllWords(true)
+ end, { noremap = true, silent = true, desc = "InterestingWord Unsearch" })
+ end
+
+ if m.config.color_key then
+ vim.keymap.set("n", m.config.color_key, function()
+ m.InterestingWord("n", false)
+ end, { noremap = true, silent = true, desc = "InterestingWord Toggle Color" })
+ vim.keymap.set("x", m.config.color_key, function()
+ m.InterestingWord("v", false)
+ end, { noremap = true, silent = true, desc = "InterestingWord Toggle Color" })
+ vim.keymap.set("n", m.config.cancel_color_key, function()
+ m.UncolorAllWords()
+ end, { noremap = true, silent = true, desc = "InterestingWord Uncolor" })
+ end
+
+ if m.config.search_count then
+ m.init_search_count()
+ end
+ end
+
+ return m
+end)()
+
+interestingwords.setup({
+ select_mode = "loop", -- or "random"
+ scroll_center = false,
+ search_key = "<leader>S",
+ cancel_search_key = "<leader>C",
+ color_key = "<leader>H",
+ cancel_color_key = "<leader>C",
+ colors = { "#ff5f5f", "#5fafff", "#afff5f", "#ffd75f" },
+})
diff --git a/common/config/nvim/lua/plugins/leetcode.lua b/common/config/nvim/lua/plugins/leetcode.lua
index 50369e1..50369e1 100644..100755
--- a/common/config/nvim/lua/plugins/leetcode.lua
+++ b/common/config/nvim/lua/plugins/leetcode.lua
diff --git a/common/config/nvim/lua/plugins/loclist.lua b/common/config/nvim/lua/plugins/loclist.lua
index 9b72a94..9b72a94 100644..100755
--- a/common/config/nvim/lua/plugins/loclist.lua
+++ b/common/config/nvim/lua/plugins/loclist.lua
diff --git a/common/config/nvim/lua/plugins/lsp.lua b/common/config/nvim/lua/plugins/lsp.lua
index 286e0d2..5ed1152 100644..100755
--- a/common/config/nvim/lua/plugins/lsp.lua
+++ b/common/config/nvim/lua/plugins/lsp.lua
@@ -1,448 +1,674 @@
-local lspconfig = require("lspconfig")
-local mason_lspconfig = require("mason-lspconfig")
-local null_ls = require("null-ls")
--- local lsp_lines = require('lsp_lines')
-require("mason").setup()
-require("mason-null-ls").setup({ handlers = {}, ensure_installed = nil, automatic_installation = true,
- automatic_setup = true })
-
-local keymap = vim.keymap
-local cmd = vim.cmd
-
-local border = { { "┌", "FloatBorder" }, { "─", "FloatBorder" }, { "┐", "FloatBorder" }, { "│", "FloatBorder" },
- { "┘", "FloatBorder" }, { "─", "FloatBorder" }, { "└", "FloatBorder" }, { "│", "FloatBorder" } }
-
--- Set up LSP servers if not done before
-if not vim.g.lsp_setup_done then
- -- Clear existing LSP clients
- for _, bufnr in ipairs(vim.api.nvim_list_bufs()) do
- local clients = require("user.mods").get_lsp_clients(bufnr)
-
- for _, client in ipairs(clients) do
- client.stop()
- end
+local M = {}
+
+-- Safe require helper
+local function safe_require(name)
+ local ok, mod = pcall(require, name)
+ return ok and mod or nil
+end
+
+-- Autocmd groups for managing event listeners
+local augroup_format = vim.api.nvim_create_augroup("LspFormattingOnSave", { clear = true })
+local augroup_diag_float = vim.api.nvim_create_augroup("ShowLineDiagnostics", { clear = true })
+local augroup_diag_load = vim.api.nvim_create_augroup("OpenDiagnosticsOnLoad", { clear = true })
+local augroup_highlight = vim.api.nvim_create_augroup("LspDocumentHighlight", { clear = true })
+
+-- Border for floating windows
+local border = {
+ { "┌", "FloatBorder" }, { "─", "FloatBorder" }, { "┐", "FloatBorder" },
+ { "│", "FloatBorder" }, { "┘", "FloatBorder" }, { "─", "FloatBorder" },
+ { "└", "FloatBorder" }, { "│", "FloatBorder" }
+}
+
+-- Initialize LSP modules
+local function init_modules()
+ -- Silently try to load each module
+ M.lspconfig = safe_require("lspconfig")
+ M.mason = safe_require("mason")
+ M.mason_lspconfig = safe_require("mason-lspconfig")
+ M.mason_tool_installer = safe_require("mason-tool-installer")
+ M.null_ls = safe_require("null-ls")
+
+ if M.null_ls then
+ M.builtins = M.null_ls.builtins
end
- local signs = { Error = " ", Warn = "▲", Info = "􀅳", Hint = "⚑" }
- -- 
- for type, icon in pairs(signs) do
- local hl = "DiagnosticSign" .. type
- vim.fn.sign_define(hl, { text = icon, texthl = hl, numhl = hl })
+ return true
+end
+
+-- Check Neovim version compatibility and feature availability
+local function has_feature(feature)
+ if feature == "diagnostic_api" then
+ return vim.fn.has("nvim-0.6") == 1
+ elseif feature == "native_lsp_config" then
+ -- Check for both vim.lsp.enable AND vim.lsp.config
+ return vim.fn.has("nvim-0.11") == 1 and vim.lsp.enable ~= nil
+ elseif feature == "lsp_get_client_by_id" then
+ return vim.fn.has("nvim-0.10") == 1
+ elseif feature == "cmp_nvim_lsp" then
+ return pcall(require, "cmp_nvim_lsp")
+ elseif feature == "virtual_text_disabled_by_default" then
+ return vim.fn.has("nvim-0.11") == 1
+ elseif feature == "deprecated_lsp_handlers" then
+ -- vim.lsp.handlers.hover and signature_help deprecated in 0.12, removed in 0.13
+ return vim.fn.has("nvim-0.12") == 0
+ elseif feature == "new_lsp_config_api" then
+ -- New LSP config API available from 0.12+
+ return vim.fn.has("nvim-0.12") == 1 and vim.lsp.config ~= nil
end
+ return false
+end
- -- lsp_lines.setup()
-
- -- vim.keymap.set("n", "g?", function()
- -- local lines_enabled = not vim.diagnostic.config().virtual_lines
- -- vim.diagnostic.config(
- -- {
- -- virtual_lines = lines_enabled,
- -- virtual_text = not lines_enabled
- -- }
- -- )
- -- end, { noremap = true, silent = true })
-
- vim.diagnostic.config({
- underline = false,
- signs = true,
- virtual_text = true, -- virtual_lines = { only_current_line = true },
- virtual_lines = false,
- float = {
- show_header = true,
- source = "if_many", -- border = 'rounded',
- border = border,
- focusable = true,
- },
- update_in_insert = false, -- default to false
- severity_sort = true, -- default to false
- })
+-- Backwards compatible capabilities setup
+local function setup_capabilities()
+ local capabilities
- vim.lsp.handlers["textDocument/publishDiagnostics"] = vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics,
- { underline = false, virtual_text = false, signs = true, update_in_insert = false })
-
- vim.lsp.handlers["textDocument/hover"] = vim.lsp.with(vim.lsp.handlers.hover, { border = "rounded" })
- vim.lsp.handlers["textDocument/signatureHelp"] = vim.lsp.with(vim.lsp.handlers.signature_help, { border = "rounded" })
-
- -- Use an on_attach function to only map the following keys after the language server attaches to the current buffer
- local on_attach = function(client, bufnr)
- -- Enable completion triggered by <c-x><c-o>
- vim.api.nvim_buf_set_option(bufnr, "omnifunc", "v:lua.vim.lsp.omnifunc")
- local map = function(mode, l, r, opts)
- opts = opts or {}
- opts.silent = true
- opts.noremap = true
- opts.buffer = bufnr
- keymap.set(mode, l, r, opts)
- end
- -- Mappings
- map("n", "K", "<Cmd>lua vim.lsp.buf.hover()<CR>")
- -- map("n", "gd", "<Cmd>lua vim.lsp.buf.definition()<CR>")
- map("n", "gd", "<cmd>lua require('goto-preview').goto_preview_definition()<CR>")
- -- map("n", "gi", "<Cmd>lua vim.lsp.buf.implementation()<CR>")
- map("n", "gi", "<cmd>lua require('goto-preview').goto_preview_implementation()<CR>")
- -- map("n", "gr", "<Cmd>lua vim.lsp.buf.references()<CR>")
- map("n", "gr", "<cmd>lua require('goto-preview').goto_preview_references()<CR>")
- map("n", "gD", "<Cmd>lua vim.lsp.buf.declaration()<CR>") -- most lsp servers don't implement textDocument/Declaration, so gD is useless for now.
- map("n", "<leader>k", "<Cmd>lua vim.lsp.buf.signature_help()<CR>")
- -- map("n", "gt", "<Cmd>lua vim.lsp.buf.type_definition()<CR>")
- map("n", "gt", "<cmd>lua require('goto-preview').goto_preview_type_definition()<CR>")
- map("n", "gn", "<Cmd>lua vim.lsp.buf.rename()<CR>")
- map("n", "ga", "<Cmd>lua vim.lsp.buf.code_action()<CR>")
- map("n", "gf", "<Cmd>lua vim.lsp.buf.format()<CR>")
- map("n", "go", "<Cmd>lua vim.diagnostic.open_float()<CR>")
- map("n", "<leader>go",
- ":call utils#ToggleDiagnosticsOpenFloat()<CR> | :echom ('Toggle Diagnostics Float open/close...')<CR> | :sl! | echo ('')<CR>")
- map("n", "gq", "<Cmd>lua vim.diagnostic.setloclist()<CR>")
- map("n", "[d", "<Cmd>lua vim.diagnostic.goto_prev()<CR>")
- map("n", "]d", "<Cmd>lua vim.diagnostic.goto_next()<CR>")
- map("n", "gs", "<Cmd>lua vim.lsp.buf.document_symbol()<CR>")
- map("n", "gw", "<Cmd>lua vim.lsp.buf.workspace_symbol()<CR>")
- map("n", "<leader>wa", "<Cmd>lua vim.lsp.buf.add_workspace_folder()<CR>")
- map("n", "<leader>wr", "<Cmd>lua vim.lsp.buf.remove_workspace_folder()<CR>")
- map("n", "<leader>wl", function()
- print(vim.inspect(vim.lsp.buf.list_workspace_folders()))
- end)
-
- -- TODO: Use the nicer new API for autocommands
- cmd("augroup lsp_aucmds")
- if client.server_capabilities.documentHighlightProvider then
- cmd("au CursorHold <buffer> lua vim.lsp.buf.document_highlight()")
- cmd("au CursorMoved <buffer> lua vim.lsp.buf.clear_references()")
- end
- cmd("augroup END")
+ if has_feature("cmp_nvim_lsp") then
+ capabilities = require('cmp_nvim_lsp').default_capabilities()
+ elseif vim.lsp.protocol and vim.lsp.protocol.make_client_capabilities then
+ capabilities = vim.lsp.protocol.make_client_capabilities()
+ else
+ capabilities = {}
end
- -- Toggle diagnostics visibility
- vim.g.diagnostics_visible = true
- function _G.toggle_diagnostics()
- if vim.g.diagnostics_visible then
- vim.g.diagnostics_visible = false
- vim.diagnostic.disable()
- else
- vim.g.diagnostics_visible = true
- vim.diagnostic.enable()
- end
+ -- Add snippet support if available
+ if capabilities.textDocument then
+ capabilities.textDocument.completion = capabilities.textDocument.completion or {}
+ capabilities.textDocument.completion.completionItem =
+ capabilities.textDocument.completion.completionItem or {}
+ capabilities.textDocument.completion.completionItem.snippetSupport = true
end
- -- Open float for diagnostics automatically
- vim.cmd([[
- augroup OpenFloat
- " autocmd CursorHold,CursorHoldI * lua vim.diagnostic.open_float(nil, {focusable = false,})
- autocmd CursorHold * lua vim.diagnostic.open_float(nil, {focusable = false,})
-
- augroup END
- ]])
-
- -- Suppress error messages from lang servers
- vim.lsp.set_log_level("debug")
- local capabilities = vim.lsp.protocol.make_client_capabilities()
- capabilities = require("cmp_nvim_lsp").default_capabilities()
- capabilities.textDocument.completion.completionItem.snippetSupport = true
- capabilities.offsetEncoding = { "utf-8", "utf-16" }
-
- local function prefer_null_ls_fmt(client)
- client.server_capabilities.documentHighlightProvider = true
- client.server_capabilities.documentFormattingProvider = true
- on_attach(client)
+ -- Set offset encoding for newer versions (0.11+ supports utf-8 and utf-32)
+ if vim.fn.has("nvim-0.11") == 1 then
+ capabilities.offsetEncoding = { "utf-8", "utf-32", "utf-16" }
+ elseif vim.fn.has("nvim-0.9") == 1 then
+ capabilities.offsetEncoding = { "utf-8", "utf-16" }
end
- --local cmp_nvim_lsp = require('cmp_nvim_lsp')
- local servers = {
- asm_lsp = {},
- bashls = {},
- clangd = {
- on_attach = on_attach,
- capabilites = capabilities,
- cmd = { "clangd", "--offset-encoding=utf-16", "--cross-file-rename", "--header-insertion=never",
- "--suggest-missing-includes" },
- init_options = {
- clangdFileStatus = true,
- },
- root_files = {
- ".clangd",
- ".clang-tidy",
- ".clang-format",
- "compile_commands.json",
- "compile_flags.txt",
- "configure.ac", -- AutoTools
+ return capabilities
+end
+
+-- Default LSP keymaps (fallback if external not available)
+local function setup_fallback_keymaps(bufnr)
+ -- Only set up minimal fallbacks, prefer external setup
+ local opts = { buffer = bufnr, silent = true, noremap = true }
+ vim.keymap.set('n', 'gd', vim.lsp.buf.definition, opts)
+ vim.keymap.set('n', 'K', vim.lsp.buf.hover, opts)
+ vim.keymap.set('n', '[d', vim.diagnostic.goto_prev, opts)
+ vim.keymap.set('n', ']d', vim.diagnostic.goto_next, opts)
+end
+
+-- Create LSP directory and config files for native LSP
+local function setup_native_lsp_configs()
+ local config_path = vim.fn.stdpath("config")
+ local lsp_dir = config_path .. "/lsp"
+
+ -- Create lsp directory if it doesn't exist
+ vim.fn.mkdir(lsp_dir, "p")
+
+ -- LSP server configurations for native config
+ local server_configs = {
+ lua_ls = {
+ cmd = { "lua-language-server" },
+ filetypes = { "lua" },
+ root_markers = { ".luarc.json", ".luarc.jsonc", ".luacheckrc", ".stylua.toml", "stylua.toml", "selene.toml", "selene.yml" },
+ settings = {
+ Lua = {
+ diagnostics = {
+ globals = { "vim", "use", "_G", "packer_plugins", "P" },
+ disable = {
+ "undefined-global",
+ "lowercase-global",
+ "unused-local",
+ "unused-vararg",
+ "trailing-space"
+ },
+ },
+ workspace = {
+ library = {
+ vim.env.VIMRUNTIME,
+ "${3rd}/luv/library",
+ "${3rd}/busted/library",
+ },
+ checkThirdParty = false,
+ },
+ telemetry = {
+ enable = false,
+ },
+ },
},
},
- cssls = { filetypes = { "css", "scss", "less", "sass" },
- root_dir = lspconfig.util.root_pattern("package.json", ".git") }, -- ghcide = {},
- html = {},
- jsonls = { prefer_null_ls = true, cmd = { "--stdio" } },
- intelephense = {},
- julials = {
- on_new_config = function(new_config, _)
- local julia = vim.fn.expand("~/.julia/environments/nvim-lspconfig/bin/julia")
- if lspconfig.util.path.is_file(julia) then
- new_config.cmd[1] = julia
- end
- end,
- settings = { julia = { format = { indent = 2 } } },
- },
- pyright = { settings = { python = { formatting = { provider = "yapf" }, linting = { pytypeEnabled = true } } } },
- rust_analyzer = {
+
+ pyright = {
+ cmd = { "pyright-langserver", "--stdio" },
+ filetypes = { "python" },
+ root_markers = { "pyproject.toml", "setup.py", "setup.cfg", "requirements.txt", "Pipfile", "pyrightconfig.json" },
settings = {
- ["rust-analyzer"] = { cargo = { allFeatures = true }, checkOnSave = { command = "clippy",
- extraArgs = { "--no-deps" } } },
- },
+ python = {
+ formatting = {
+ provider = "none"
+ }
+ }
+ }
},
- dartls = {
- cmd = { "dart", "language-server", "--protocol=lsp" },
- filetypes = { "dart" },
+
+ ts_ls = {
+ cmd = { "typescript-language-server", "--stdio" },
+ filetypes = { "javascript", "javascriptreact", "javascript.jsx", "typescript", "typescriptreact", "typescript.tsx" },
+ root_markers = { "tsconfig.json", "jsconfig.json", "package.json" },
init_options = {
- closingLabels = true,
- flutterOutline = true,
- onlyAnalyzeProjectsWithOpenFiles = true,
- outline = true,
- suggestFromUnimportedLibraries = true,
- }, -- root_dir = root_pattern("pubspec.yaml"),
- settings = { dart = { completeFunctionCalls = true, showTodos = true } },
- on_attach = function(client, bufnr) end,
+ disableAutomaticTypeAcquisition = true
+ },
},
- lua_ls = {
- on_attach = on_attach,
- capabilities = capabilities,
- debounce_text_changes = 500,
+
+ rust_analyzer = {
+ cmd = { "rust-analyzer" },
+ filetypes = { "rust" },
+ root_markers = { "Cargo.toml", "rust-project.json" },
+ },
+
+ clangd = {
+ cmd = { "clangd", "--background-index", "--clang-tidy", "--header-insertion=iwyu" },
+ filetypes = { "c", "cpp", "objc", "objcpp", "cuda", "proto" },
+ root_markers = { ".clangd", ".clang-tidy", ".clang-format", "compile_commands.json", "compile_flags.txt", "configure.ac" },
+ },
+
+ gopls = {
+ cmd = { "gopls" },
+ filetypes = { "go", "gomod", "gowork", "gotmpl" },
+ root_markers = { "go.work", "go.mod" },
settings = {
- Lua = {
- runtime = { version = "LuaJIT", path = vim.split(package.path, ";") },
- diagnostics = { enable = true, globals = { "vim" } },
- workspace = { maxPreload = 2000, preloadFileSize = 50000, checkThirdParty = false },
+ gopls = {
+ gofumpt = 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,
+ },
+ analyses = {
+ fieldalignment = true,
+ nilness = true,
+ unusedparams = true,
+ unusedwrite = true,
+ useany = true,
+ },
+ usePlaceholders = true,
+ completeUnimported = true,
+ staticcheck = true,
+ directoryFilters = { "-.git", "-.vscode", "-.idea", "-.vscode-test", "-node_modules" },
+ semanticTokens = true,
},
},
},
- sqlls = {},
- tsserver = {
- capabilities = require("cmp_nvim_lsp").default_capabilities(vim.lsp.protocol.make_client_capabilities()),
- on_attach = function(client)
- client.server_capabilities.document_formatting = false
- client.server_capabilities.document_range_formatting = false
- end,
- filetypes = { "javascript", "javascriptreact", "javascript.jsx", "typescript", "typescriptreact", "typescript.tsx" },
+
+ -- Add more basic configs
+ bashls = {
+ cmd = { "bash-language-server", "start" },
+ filetypes = { "sh", "bash" },
},
- vimls = {},
- yamlls = {},
- }
- mason_lspconfig.setup({
- ensure_installed = servers, -- will be installed by mason
- automatic_installation = true,
- })
+ --html = {
+ -- cmd = { "vscode-html-language-server", "--stdio" },
+ -- filetypes = { "html" },
+ --},
- -- Your other configurations ...
- -- require("lspconfig").dartls.setup({ capabilities = capabilities })
- -- local installed_lsp = mason_lspconfig.ensure_installed
- -- local mason_lspconfig = require("mason-lspconfig").ensure_installed
-
- -- require("lspconfig").setup({
- -- function()
- -- for _, lsp in ipairs(installed_lsp) do
- -- if
- -- lsp ~= "sqls"
- -- --and lsp ~= "sumneko_lua"
- -- --and lsp ~= "stylelint_lsp"
- -- --and lsp ~= "rust_analyzer"
- -- --and lsp ~= "sourcekit"
- -- and lsp ~= "dartls"
- -- then
- -- lspconfig[lsp].setup({
- -- on_attach = on_attach,
- -- capabilities = capabilities,
- -- })
- -- end
- -- end
- -- end,
- -- })
-
- for server, config in pairs(servers) do
- if config.prefer_null_ls then
- if config.on_attach then
- local old_on_attach = config.on_attach
- config.on_attach = function(client, bufnr)
- old_on_attach(client, bufnr)
- prefer_null_ls_fmt(client)
- end
- else
- config.on_attach = prefer_null_ls_fmt
+ --cssls = {
+ -- cmd = { "vscode-css-language-server", "--stdio" },
+ -- filetypes = { "css", "scss", "less" },
+ --},
+
+ --jsonls = {
+ -- cmd = { "vscode-json-language-server", "--stdio" },
+ -- filetypes = { "json", "jsonc" },
+ --},
+
+ yamlls = {
+ cmd = { "yaml-language-server", "--stdio" },
+ filetypes = { "yaml", "yml" },
+ },
+ }
+
+ -- Write config files to lsp directory
+ for server_name, config in pairs(server_configs) do
+ local file_path = lsp_dir .. "/" .. server_name .. ".lua"
+ local file_content = "return " .. vim.inspect(config)
+
+ -- Only write if file doesn't exist to avoid overwriting user customizations
+ if vim.fn.filereadable(file_path) == 0 then
+ local file = io.open(file_path, "w")
+ if file then
+ file:write(file_content)
+ file:close()
+ vim.notify("Created LSP config: " .. file_path, vim.log.levels.DEBUG)
end
- elseif not config.on_attach then
- config.on_attach = on_attach
end
+ end
+
+ return vim.tbl_keys(server_configs)
+end
+
+-- Set up LSP on_attach function
+local function create_on_attach()
+ return function(client, bufnr)
+ -- Your existing keymap setup function from keys.lua
+ if _G.setup_lsp_keymaps then
+ _G.setup_lsp_keymaps(bufnr)
+ else
+ setup_fallback_keymaps(bufnr)
+ end
+
+ -- Disable LSP formatting in favor of null-ls (if null-ls is available)
+ if M.null_ls then
+ client.server_capabilities.documentFormattingProvider = false
+ client.server_capabilities.documentRangeFormattingProvider = false
+ end
+
+ -- Disable specific LSP capabilities to avoid conflicts
+ if client.name == "ruff" then
+ -- Disable ruff hover in favor of Pyright
+ client.server_capabilities.hoverProvider = false
+ elseif client.name == "ts_ls" then
+ -- Disable ts_ls formatting in favor of prettier via null-ls
+ client.server_capabilities.documentFormattingProvider = false
+ client.server_capabilities.documentRangeFormattingProvider = false
+ elseif client.name == "pyright" and M.null_ls then
+ -- Disable pyright formatting in favor of black/isort via null-ls
+ client.server_capabilities.documentFormattingProvider = false
+ client.server_capabilities.documentRangeFormattingProvider = false
+ end
+
+ -- Set log level (backwards compatible)
+ if vim.lsp.set_log_level then
+ vim.lsp.set_log_level("warn")
+ end
+
+ -- Document highlight on cursor hold
+ if client.server_capabilities and client.server_capabilities.documentHighlightProvider then
+ vim.api.nvim_create_autocmd("CursorHold", {
+ group = augroup_highlight,
+ buffer = bufnr,
+ callback = function()
+ if vim.lsp.buf.document_highlight then
+ vim.lsp.buf.document_highlight()
+ end
+ end,
+ })
+ vim.api.nvim_create_autocmd("CursorMoved", {
+ group = augroup_highlight,
+ buffer = bufnr,
+ callback = function()
+ if vim.lsp.buf.clear_references then
+ vim.lsp.buf.clear_references()
+ end
+ end,
+ })
+ end
+ end
+end
- lspconfig[server].setup(config)
+-- Set up basic LSP configuration
+function M.setup()
+ -- Initialize all required modules
+ init_modules()
+
+ -- Enable virtual_text diagnostics by default for 0.11+ (since it's disabled by default)
+ if has_feature("virtual_text_disabled_by_default") then
+ vim.diagnostic.config({ virtual_text = true })
+ end
+
+ -- Set up Mason if available (useful for tool management)
+ if M.mason then
+ M.mason.setup({
+ ui = {
+ border = 'rounded',
+ icons = {
+ package_installed = '✓',
+ package_pending = '➜',
+ package_uninstalled = '✗'
+ }
+ }
+ })
end
- -- null_ls setup
- local builtins = null_ls.builtins
- local augroup = vim.api.nvim_create_augroup("LspFormatting", {})
-
- -- local eslint_opts = {
- -- -- condition = function(utils)
- -- -- return utils.root_has_file ".eslintrc.js" or utils.root_has_file ".eslintrc" or utils.root_has_file ".eslintrc.json"
- -- -- end,
- -- -- diagnostics_format = "#{m} [#{c}]",
- -- prefer_local = true,
- -- }
-
- -- null_ls.setup({
- local sources = {
- -- Diagnostics
- builtins.diagnostics.chktex,
- -- null_ls.builtins.code_actions.eslint_d,
- -- null_ls.builtins.diagnostics.eslint_d,
- -- null_ls.builtins.formatting.eslint_d,
- -- null_ls.builtins.diagnostics.cppcheck,
- -- null_ls.builtins.diagnostics.proselint,
- -- null_ls.builtins.diagnostics.pylint,
- -- builtins.diagnostics.selene,
- builtins.diagnostics.dotenv_linter,
- builtins.diagnostics.shellcheck.with({ -- shell script diagnostics
- diagnostic_config = { -- see :help vim.diagnostic.config()
- underline = true,
- virtual_text = false,
- signs = true,
- update_in_insert = false,
- severity_sort = true,
+ -- Set up mason-tool-installer if available
+ if M.mason_tool_installer then
+ M.mason_tool_installer.setup({
+ ensure_installed = {
+ -- Language servers
+ "lua-language-server", "pyright", "typescript-language-server", "rust-analyzer",
+ "clangd", "bash-language-server", "yaml-language-server",
+ -- Formatters
+ "stylua", "clang-format", "prettier", "shfmt", "black", "isort", "goimports",
+ "sql-formatter", "shellharden",
+ -- Linters/Diagnostics
+ "eslint_d", "selene", "flake8", "dotenv-linter", "phpcs",
+ -- Utilities
+ "jq"
},
- diagnostics_format = "[#{c}] #{m} (#{s})", -- this will run every time the source runs,
- -- so you should prefer caching results if possible
- }),
- builtins.diagnostics.zsh.with({ filetypes = "zsh", "sh" }),
- builtins.diagnostics.todo_comments,
- builtins.diagnostics.teal,
- -- null_ls.builtins.diagnostics.vale,
- builtins.diagnostics.vint,
- builtins.diagnostics.tidy,
- builtins.diagnostics.php,
- builtins.diagnostics.phpcs,
- builtins.diagnostics.flake8,
- builtins.diagnostics.eslint_d.with({
- condition = function(utils)
- return utils.root_has_file(".eslintrc.json")
+ auto_update = false,
+ run_on_start = true,
+ start_delay = 3000,
+ })
+ end
+
+ -- Set up null-ls if available
+ if M.null_ls and M.builtins then
+ local sources = {
+ M.builtins.diagnostics.selene.with({
+ condition = function(utils)
+ return utils.root_has_file({"selene.toml"})
+ end,
+ }),
+ M.builtins.diagnostics.dotenv_linter,
+ M.builtins.diagnostics.tidy,
+ M.builtins.diagnostics.phpcs.with({
+ condition = function(utils)
+ return utils.root_has_file({"phpcs.xml", "phpcs.xml.dist", ".phpcs.xml", ".phpcs.xml.dist"})
+ end,
+ }),
+
+ -- Formatters (prioritized over LSP formatting)
+ M.builtins.formatting.stylua.with({
+ extra_args = { "--quote-style", "AutoPreferSingle", "--indent-width", "2", "--column-width", "160" },
+ condition = function(utils)
+ return utils.root_has_file({"stylua.toml", ".stylua.toml"})
+ end,
+ }),
+ M.builtins.formatting.prettier.with({
+ extra_args = { "--single-quote", "--tab-width", "4", "--print-width", "100" },
+ filetypes = { "javascript", "javascriptreact", "typescript", "typescriptreact", "vue", "css", "scss", "less", "html", "json", "jsonc", "yaml", "markdown", "graphql", "handlebars" },
+ prefer_local = "node_modules/.bin",
+ }),
+ M.builtins.formatting.black.with({
+ extra_args = { "--fast" },
+ prefer_local = ".venv/bin",
+ }),
+ M.builtins.formatting.isort.with({
+ extra_args = { "--profile", "black" },
+ prefer_local = ".venv/bin",
+ }),
+ M.builtins.formatting.goimports,
+ M.builtins.formatting.clang_format.with({
+ extra_args = { "--style", "{BasedOnStyle: Google, IndentWidth: 4}" }
+ }),
+ M.builtins.formatting.shfmt.with({
+ extra_args = { "-i", "2", "-ci" }
+ }),
+ M.builtins.formatting.shellharden,
+ M.builtins.formatting.sql_formatter,
+ M.builtins.formatting.dart_format,
+
+ -- Code actions
+ M.builtins.code_actions.gitsigns,
+ M.builtins.code_actions.gitrebase,
+ }
+
+ M.null_ls.setup({
+ sources = sources,
+ update_in_insert = false,
+ on_attach = function(client, bufnr)
+ -- Disable LSP formatting in favor of null-ls
+ client.server_capabilities.documentFormattingProvider = false
+ client.server_capabilities.documentRangeFormattingProvider = false
+
+ local function lsp_supports_method(client, method)
+ if client.supports_method then
+ return client:supports_method(method)
+ elseif client.server_capabilities then
+ local capability_map = {
+ ["textDocument/formatting"] = "documentFormattingProvider",
+ ["textDocument/rangeFormatting"] = "documentRangeFormattingProvider",
+ ["textDocument/hover"] = "hoverProvider",
+ ["textDocument/signatureHelp"] = "signatureHelpProvider",
+ ["textDocument/documentHighlight"] = "documentHighlightProvider",
+ }
+ local cap = capability_map[method]
+ return cap and client.server_capabilities[cap]
+ end
+ return false
+ end
+
+ if lsp_supports_method(client, "textDocument/formatting") then
+ vim.api.nvim_create_autocmd("BufWritePre", {
+ group = augroup_format,
+ buffer = bufnr,
+ callback = function()
+ if vim.fn.has("nvim-0.8") == 1 then
+ vim.lsp.buf.format({
+ async = false,
+ bufnr = bufnr,
+ filter = function(formatting_client)
+ return formatting_client.name == "null-ls"
+ end,
+ })
+ else
+ vim.lsp.buf.formatting_sync()
+ end
+ end,
+ })
+ end
end,
- }),
- builtins.formatting.eslint_d,
- -- null_ls.builtins.diagnostics.write_good.with { filetypes = { 'markdown', 'tex' } },
-
- -- Formatting
- builtins.formatting.shfmt.with({ filetypes = { "bash", "zsh", "sh" }, extra_args = { "-i", "2", "-ci" } }),
- builtins.formatting.shellharden,
- builtins.formatting.trim_whitespace.with({ filetypes = { "tmux", "teal", "zsh" } }), -- builtins.formatting.beautysh,
- builtins.formatting.beautysh.with({ filetypes = "zsh" }),
- builtins.formatting.clang_format.with({
- filetypes = { "c", "cpp", "cs", "java", "cuda", "proto" },
- extra_args = {
- "--style",
- "{BasedOnStyle: Google, IndentWidth: 4, BreakBeforeBinaryOperators: NonAssignment, AllowShortFunctionsOnASingleLine: None}",
- },
- }),
- --builtins.formatting.rustfmt,
- builtins.formatting.sql_formatter,
- -- null_ls.builtins.formatting.cmake_format,
- builtins.formatting.isort,
- builtins.formatting.htmlbeautifier, -- null_ls.builtins.formatting.prettier,
- builtins.formatting.prettierd,
- builtins.formatting.prettier.with({
- filetypes = { "javascript", "javascriptreact", "typescript", "typescriptreact", "json", "yaml", "markdown", "html",
- "css", "scss", "less", "graphql", "vue", "svelte" },
- extra_args = { "--single-quote", "--tab-width 4", "--print-width 200" },
- }),
- -- builtins.formatting.stylua,
- -- builtins.formatting.lua_format,
- builtins.formatting.stylua.with({
- filetypes = { "lua" },
- command = "stylua",
- args = { "--quote_style", "AutoPreferSingle", "--indent-width", "2", "--column-width", "160", "--indent-type",
- "Spaces", "-" },
- }),
- -- builtins.formatting.dart_format,
- builtins.formatting.dart_format.with({ filetypes = { "dart" } }),
- builtins.formatting.trim_whitespace,
- builtins.formatting.yapf,
- -- null_ls.builtins.formatting.black
-
- -- Code Actions
- builtins.code_actions.shellcheck, -- shell script code actions
- -- builtins.code_actions.eslint_d.with(eslint_opts),
- -- null_ls.builtins.code_actions.refactoring.with { filetypes = { 'javascript', 'typescript', 'lua', 'python', 'c', 'cpp' } },
- builtins.code_actions.gitsigns,
- builtins.code_actions.gitrebase, -- Hover
- builtins.hover.dictionary,
- builtins.hover.printenv,
- }
- -- })
- -- Linters/Formatters ensure installed
- -- for _, pkg_name in ipairs({
- -- "dart-debug-Adaptor",
- -- "stylua",
- -- "prettier",
- -- "prettierd",
- -- }) do
-
- -- Import the builtins table from the null-ls module and store it in the null_ls_sources variable
- null_ls.setup({
- sources = sources,
- update_in_insert = true,
- on_attach = function(client, bufnr)
- if client.supports_method("textDocument/formatting") then
- vim.api.nvim_clear_autocmds({ group = augroup, buffer = bufnr })
- vim.api.nvim_create_autocmd("BufWritePre", {
- group = augroup,
- buffer = bufnr,
- callback = function()
- vim.lsp.buf.format()
- end,
- })
- end
- end,
- })
+ })
+ end
- -- Install all the null-ls sources using Mason
- local registry = require("mason-registry")
- for _, source_name in ipairs(sources) do
- local ok, pkg = pcall(registry.get_package, source_name)
- if ok then
- if not pkg:is_installed() then
- pkg:install()
- end
+ -- Set up LSP capabilities
+ local capabilities = setup_capabilities()
+ local on_attach = create_on_attach()
+
+ -- Set up LSP handlers with version compatibility (avoid deprecated APIs)
+ if has_feature("deprecated_lsp_handlers") then
+ -- Use old handler setup for versions before 0.12
+ if vim.lsp.handlers then
+ vim.lsp.handlers['textDocument/hover'] = vim.lsp.with(
+ vim.lsp.handlers.hover, { border = 'rounded' }
+ )
+
+ vim.lsp.handlers['textDocument/signatureHelp'] = vim.lsp.with(
+ vim.lsp.handlers.signature_help, { border = 'rounded' }
+ )
+ end
+ else
+ -- Use new handler setup for 0.12+ (when old handlers are deprecated/removed)
+ if vim.lsp.handlers then
+ vim.lsp.handlers['textDocument/hover'] = vim.lsp.with(
+ vim.lsp.handlers['textDocument/hover'], { border = 'rounded' }
+ )
+
+ vim.lsp.handlers['textDocument/signatureHelp'] = vim.lsp.with(
+ vim.lsp.handlers['textDocument/signatureHelp'], { border = 'rounded' }
+ )
end
end
- -- Loop through the null_ls_sources table and install the packages
- -- Install all sources for null-ls
- -- local null_ls_sources = require("null-ls").builtins
-
- -- for _, source_name in ipairs(null_ls_sources) do
- -- local ok, pkg = pcall(mason.get_package, source_name)
- -- if ok then
- -- if not pkg:is_installed() then
- -- pkg:install()
- -- end
- -- end
- -- end
- vim.api.nvim_create_user_command("NullLsToggle", function()
- -- you can also create commands to disable or enable sources
- require("null-ls").toggle({})
- end, {})
- local null_ls_stop = function()
- local null_ls_client
- local clients = require("user.mods").get_lsp_clients(bufnr)
+ -- Choose configuration method based on Neovim version and available features
+ if has_feature("native_lsp_config") then
+ -- Set up native LSP configuration
+ local servers = setup_native_lsp_configs()
- for _, client in ipairs(clients) do
- if client.name == "null-ls" then
- null_ls_client = client
- end
+ -- Set default on_attach and capabilities for all LSP servers
+ vim.lsp.config('*', {
+ on_attach = on_attach,
+ capabilities = capabilities,
+ })
+
+ -- Enable the LSP servers
+ vim.lsp.enable(servers)
+
+ elseif M.mason_lspconfig and M.lspconfig then
+ -- Set up mason-lspconfig if available
+ if M.mason_lspconfig then
+ M.mason_lspconfig.setup({
+ ensure_installed = {
+ "lua_ls", "pyright", "ts_ls", "rust_analyzer", "clangd", "gopls",
+ "bashls", "html", "cssls", "jsonls", "yamlls"
+ },
+ automatic_installation = true,
+ })
end
- if not null_ls_client then
- return
+
+ -- Use traditional lspconfig with mason
+ local enabled_servers = {}
+
+ local server_configs = {
+ lua_ls = {
+ settings = {
+ Lua = {
+ diagnostics = {
+ globals = { "vim", "use", "_G", "packer_plugins", "P" },
+ },
+ workspace = {
+ library = {
+ vim.env.VIMRUNTIME,
+ "${3rd}/luv/library",
+ "${3rd}/busted/library",
+ },
+ checkThirdParty = false,
+ },
+ telemetry = { enable = false },
+ },
+ },
+ },
+ pyright = {
+ settings = {
+ python = {
+ formatting = { provider = "none" }
+ }
+ }
+ },
+ ts_ls = {
+ init_options = {
+ disableAutomaticTypeAcquisition = true
+ },
+ },
+ clangd = {
+ cmd = { "clangd", "--background-index", "--clang-tidy", "--header-insertion=iwyu" },
+ },
+ gopls = {
+ settings = {
+ gopls = {
+ gofumpt = true,
+ usePlaceholders = true,
+ completeUnimported = true,
+ staticcheck = true,
+ },
+ },
+ },
+ }
+
+ M.mason_lspconfig.setup_handlers({
+ function(server_name)
+ if not enabled_servers[server_name] then
+ local config = server_configs[server_name] or {}
+ config.on_attach = on_attach
+ config.capabilities = capabilities
+ M.lspconfig[server_name].setup(config)
+ enabled_servers[server_name] = true
+ end
+ end,
+ })
+
+ elseif M.lspconfig then
+ -- Fallback: Set up servers manually if mason-lspconfig is not available
+ local servers = { 'lua_ls', 'pyright', 'ts_ls', 'rust_analyzer', 'clangd', 'gopls', 'bashls', 'html', 'cssls', 'jsonls', 'yamlls' }
+ local enabled_servers = {}
+
+ for _, server in ipairs(servers) do
+ if not enabled_servers[server] and M.lspconfig[server] then
+ local config = {
+ on_attach = on_attach,
+ capabilities = capabilities,
+ }
+ M.lspconfig[server].setup(config)
+ enabled_servers[server] = true
+ end
end
+ end
- null_ls_client.stop()
+ return true
+end
+
+-- Global toggle for diagnostics (backwards compatible)
+vim.g.diagnostics_visible = true
+function _G.toggle_diagnostics()
+ if has_feature("diagnostic_api") then
+ if vim.g.diagnostics_visible then
+ vim.g.diagnostics_visible = false
+ vim.diagnostic.disable()
+ else
+ vim.g.diagnostics_visible = true
+ vim.diagnostic.enable()
+ end
+ else
+ -- Fallback for older versions
+ if vim.g.diagnostics_visible then
+ vim.g.diagnostics_visible = false
+ vim.lsp.handlers["textDocument/publishDiagnostics"] = function() end
+ else
+ vim.g.diagnostics_visible = true
+ vim.lsp.handlers["textDocument/publishDiagnostics"] = vim.lsp.with(
+ vim.lsp.diagnostic.on_publish_diagnostics, {}
+ )
+ end
end
+end
- vim.api.nvim_create_user_command("NullLsStop", null_ls_stop, {})
+-- Create Mason command if Mason is available
+if M.mason then
+ vim.api.nvim_create_user_command("Mason", function()
+ require("mason.ui").open()
+ end, {})
+end
- vim.g.lsp_setup_done = true
+-- Automatically show diagnostics in a float window for the current line
+if has_feature("diagnostic_api") then
+ vim.api.nvim_create_autocmd("CursorHold", {
+ group = augroup_diag_float,
+ pattern = "*",
+ callback = function()
+ local opts = {
+ focusable = false,
+ close_events = { "BufLeave", "CursorMoved", "InsertEnter", "FocusLost" },
+ border = border,
+ source = "always",
+ prefix = " ",
+ scope = "cursor",
+ }
+ vim.diagnostic.open_float(nil, opts)
+ end,
+ })
+
+ -- Autocmd to open the diagnostic window when a file with errors is opened
+ vim.api.nvim_create_autocmd({ "LspAttach", "BufReadPost" }, {
+ group = augroup_diag_load,
+ callback = function()
+ local has_errors = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.ERROR }) > 0
+ if has_errors then
+ vim.diagnostic.setqflist({
+ open = true,
+ title = "Diagnostics",
+ })
+ end
+ end,
+ })
end
+
+-- Create Toggle Diagnostic command
+vim.api.nvim_create_user_command("ToggleDiagnostics", _G.toggle_diagnostics, {
+ desc = "Toggle global diagnostics visibility"
+})
+
+return M
diff --git a/common/config/nvim/lua/plugins/lualine.lua b/common/config/nvim/lua/plugins/lualine.lua
new file mode 100755
index 0000000..9c1cc43
--- /dev/null
+++ b/common/config/nvim/lua/plugins/lualine.lua
@@ -0,0 +1,22 @@
+-- lualine.nvim plugin config (modular, robust)
+local ok, lualine = pcall(require, 'lualine')
+if not ok then return end
+local nvim_version = vim.version()
+if nvim_version.major == 0 and nvim_version.minor < 5 then return end
+lualine.setup({
+ options = {
+ theme = 'auto',
+ icons_enabled = true,
+ section_separators = '',
+ component_separators = '',
+ disabled_filetypes = {},
+ },
+ sections = {
+ lualine_a = {'mode'},
+ lualine_b = {'branch', 'diff', 'diagnostics'},
+ lualine_c = {'filename'},
+ lualine_x = {'encoding', 'fileformat', 'filetype'},
+ lualine_y = {'progress'},
+ lualine_z = {'location'},
+ },
+}) \ No newline at end of file
diff --git a/common/config/nvim/lua/plugins/luasnip.lua b/common/config/nvim/lua/plugins/luasnip.lua
new file mode 100755
index 0000000..75f4c28
--- /dev/null
+++ b/common/config/nvim/lua/plugins/luasnip.lua
@@ -0,0 +1,13 @@
+-- LuaSnip plugin config (modular, robust)
+local ok, luasnip = pcall(require, 'luasnip')
+if not ok then return end
+local nvim_version = vim.version()
+if nvim_version.major == 0 and nvim_version.minor < 5 then return end
+-- Load friendly-snippets if available
+pcall(function()
+ require('luasnip.loaders.from_vscode').lazy_load()
+end)
+luasnip.config.set_config({
+ history = true,
+ updateevents = "TextChanged,TextChangedI",
+}) \ No newline at end of file
diff --git a/common/config/nvim/lua/plugins/messages.lua b/common/config/nvim/lua/plugins/messages.lua
index 8e46c09..8e46c09 100644..100755
--- a/common/config/nvim/lua/plugins/messages.lua
+++ b/common/config/nvim/lua/plugins/messages.lua
diff --git a/common/config/nvim/lua/plugins/modify-blend.lua b/common/config/nvim/lua/plugins/modify-blend.lua
index 1b2c6d5..1b2c6d5 100644..100755
--- a/common/config/nvim/lua/plugins/modify-blend.lua
+++ b/common/config/nvim/lua/plugins/modify-blend.lua
diff --git a/common/config/nvim/lua/plugins/navic.lua b/common/config/nvim/lua/plugins/navic.lua
index a95485d..a574d5c 100644..100755
--- a/common/config/nvim/lua/plugins/navic.lua
+++ b/common/config/nvim/lua/plugins/navic.lua
@@ -1,50 +1,51 @@
-local navic = require("nvim-navic")
---local on_attach = function(client, bufnr)
--- if client.server_capabilities.documentSymbolProvider then
--- navic.attach(client, bufnr)
--- end
---end
+local M = {}
---require("lspconfig").clangd.setup {
--- on_attach = on_attach
---}
+function M.setup()
+ local ok, navic = pcall(require, "nvim-navic")
+ if not ok or not navic then
+ return false
+ end
-navic.setup {
- icons = {
- File = " ",
- Module = " ",
- Namespace = " ",
- Package = " ",
- Class = " ",
- Method = " ",
- Property = " ",
- Field = " ",
- Constructor = " ",
- Enum = "練",
- Interface = "練",
- Function = " ",
- Variable = " ",
- Constant = " ",
- String = " ",
- Number = " ",
- Boolean = "◩ ",
- Array = " ",
- Object = " ",
- Key = " ",
- Null = "ﳠ ",
- EnumMember = " ",
- Struct = " ",
- Event = " ",
- Operator = " ",
- TypeParameter = " ",
- },
- lsp = {
- auto_attach = true,
- --preference = nil,
- },
- highlight = false,
- separator = " > ",
- depth_limit = 0,
- depth_limit_indicator = "..",
- safe_output = true
-}
+ navic.setup({
+ icons = {
+ File = " ",
+ Module = " ",
+ Namespace = " ",
+ Package = " ",
+ Class = " ",
+ Method = " ",
+ Property = " ",
+ Field = " ",
+ Constructor = " ",
+ Enum = "練",
+ Interface = "練",
+ Function = " ",
+ Variable = " ",
+ Constant = " ",
+ String = " ",
+ Number = " ",
+ Boolean = "◩ ",
+ Array = " ",
+ Object = " ",
+ Key = " ",
+ Null = "ﳠ ",
+ EnumMember = " ",
+ Struct = " ",
+ Event = " ",
+ Operator = " ",
+ TypeParameter = " "
+ },
+ highlight = false,
+ separator = " > ",
+ depth_limit = 0,
+ depth_limit_indicator = "..",
+ safe_output = true,
+ lsp = {
+ auto_attach = true
+ }
+ })
+
+ return true
+end
+
+return M
diff --git a/common/config/nvim/lua/plugins/neodev.lua b/common/config/nvim/lua/plugins/neodev.lua
index f820422..07843e1 100644..100755
--- a/common/config/nvim/lua/plugins/neodev.lua
+++ b/common/config/nvim/lua/plugins/neodev.lua
@@ -1,4 +1,15 @@
-require("neodev").setup({
+local M = {}
+
+--- Setup and configure neodev
+-- This function initializes neodev with configurations for better Lua development experience
+-- @return boolean True if setup was successful, false otherwise
+function M.setup()
+ local ok, neodev = pcall(require, 'neodev')
+ if not ok then
+ return false
+ end
+
+ neodev.setup({
--library = { plugins = { "nvim-dap-ui" }, types = true },
--library = { plugins = { "neotest" }, types = true },
library = {
@@ -23,7 +34,12 @@ require("neodev").setup({
-- If you disable this, then you have to set {before_init=require("neodev.lsp").before_init}
-- in your lsp start options
lspconfig = true,
- -- much faster, but needs a recent built of lua-language-server
- -- needs lua-language-server >= 3.6.0
- pathStrict = true,
-})
+ -- much faster, but needs a recent built of lua-language-server
+ -- needs lua-language-server >= 3.6.0
+ pathStrict = true,
+ })
+
+ return true
+end
+
+return M
diff --git a/common/config/nvim/lua/plugins/neoscroll.lua b/common/config/nvim/lua/plugins/neoscroll.lua
index d122584..f2ecb04 100644..100755
--- a/common/config/nvim/lua/plugins/neoscroll.lua
+++ b/common/config/nvim/lua/plugins/neoscroll.lua
@@ -1,21 +1,22 @@
-require("neoscroll").setup({
- easing_function = "quadratic",
-})
+local M = {}
-local t = {}
--- Syntax: t[keys] = {function, {function arguments}}
--- Use the "sine" easing function
-t["<C-u>"] = { "scroll", { "-vim.wo.scroll", "true", "20", [['cubic']] } }
-t["<C-d>"] = { "scroll", { "vim.wo.scroll", "true", "20", [['cubic']] } }
--- Use the "circular" easing function
-t["<C-b>"] = { "scroll", { "-vim.api.nvim_win_get_height(0)", "true", "50", [['cubic']] } }
-t["<C-f>"] = { "scroll", { "vim.api.nvim_win_get_height(0)", "true", "50", [['cubic']] } }
--- Pass "nil" to disable the easing animation (constant scrolling speed)
-t["<C-y>"] = { "scroll", { "-0.10", "false", "100", nil } }
-t["<C-e>"] = { "scroll", { "0.10", "false", "100", nil } }
--- When no easing function is provided the default easing function (in this case "quadratic") will be used
-t["zt"] = { "zt", { "10" } }
-t["zz"] = { "zz", { "10" } }
-t["zb"] = { "zb", { "10" } }
+function M.setup()
+ local ok, neoscroll = pcall(require, 'neoscroll')
+ if not ok then
+ return false
+ end
+
+ -- Basic configuration
+ neoscroll.setup({
+ mappings = {'<C-u>', '<C-d>', '<C-b>', '<C-f>', '<C-y>', '<C-e>', 'zt', 'zz', 'zb'},
+ hide_cursor = true,
+ stop_eof = true,
+ respect_scrolloff = false,
+ cursor_scrolls_alone = true,
+ easing_function = 'quadratic',
+ })
+
+ return true
+end
-require("neoscroll.config").set_mappings(t)
+return M
diff --git a/common/config/nvim/lua/plugins/neotest.lua b/common/config/nvim/lua/plugins/neotest.lua
index aa73899..1034d33 100644..100755
--- a/common/config/nvim/lua/plugins/neotest.lua
+++ b/common/config/nvim/lua/plugins/neotest.lua
@@ -1,11 +1,38 @@
-require("neotest").setup({
- adapters = {
- require("neotest-python")({
+local M = {}
+
+function M.setup()
+ local ok, neotest = pcall(require, "neotest")
+ if not ok or not neotest then
+ return false
+ end
+
+ -- Safely require adapters
+ local python_ok, python_adapter = pcall(require, "neotest-python")
+ local plenary_ok, plenary_adapter = pcall(require, "neotest-plenary")
+ local vim_test_ok, vim_test_adapter = pcall(require, "neotest-vim-test")
+
+ local adapters = {}
+ if python_ok and python_adapter then
+ table.insert(adapters, python_adapter({
dap = { justMyCode = false },
- }),
- require("neotest-plenary"),
- require("neotest-vim-test")({
+ }))
+ end
+
+ if plenary_ok and plenary_adapter then
+ table.insert(adapters, plenary_adapter)
+ end
+
+ if vim_test_ok and vim_test_adapter then
+ table.insert(adapters, vim_test_adapter({
ignore_file_types = { "python", "vim", "lua" },
- }),
- },
-})
+ }))
+ end
+
+ neotest.setup({
+ adapters = adapters,
+ })
+
+ return true
+end
+
+return M
diff --git a/common/config/nvim/lua/plugins/notify.lua b/common/config/nvim/lua/plugins/notify.lua
index dcb496a..62a8f47 100644..100755
--- a/common/config/nvim/lua/plugins/notify.lua
+++ b/common/config/nvim/lua/plugins/notify.lua
@@ -1,18 +1,36 @@
-require('notify').setup({
- background_colour = '#000000',
- icons = {
- ERROR = '',
- WARN = '',
- INFO = '',
- DEBUG = '',
- TRACE = '✎',
- },
-})
+local M = {}
-vim.api.nvim_command('hi default link NotifyERRORBody Normal')
-vim.api.nvim_command('hi default link NotifyWARNBody Normal')
-vim.api.nvim_command('hi default link NotifyINFOBody Normal')
-vim.api.nvim_command('hi default link NotifyDEBUGBody Normal')
-vim.api.nvim_command('hi default link NotifyTRACEBody Normal')
-vim.api.nvim_command('hi default link NotifyLogTime Comment')
-vim.api.nvim_command('hi default link NotifyLogTitle Special')
+function M.setup()
+ local ok, notify = pcall(require, 'notify')
+ if not ok or not notify then
+ return false
+ end
+
+ notify.setup({
+ background_colour = '#000000',
+ icons = {
+ ERROR = '',
+ WARN = '',
+ INFO = '',
+ DEBUG = '',
+ TRACE = '✎',
+ }
+ })
+
+ -- Set highlight groups safely
+ local function set_hl(group, link)
+ vim.cmd(('hi default link %s %s'):format(group, link))
+ end
+
+ set_hl('NotifyERRORBody', 'Normal')
+ set_hl('NotifyWARNBody', 'Normal')
+ set_hl('NotifyINFOBody', 'Normal')
+ set_hl('NotifyDEBUGBody', 'Normal')
+ set_hl('NotifyTRACEBody', 'Normal')
+ set_hl('NotifyLogTime', 'Comment')
+ set_hl('NotifyLogTitle', 'Special')
+
+ return true
+end
+
+return M
diff --git a/common/config/nvim/lua/plugins/nvim-tree.lua b/common/config/nvim/lua/plugins/nvim-tree.lua
index e817c04..a212eab 100644..100755
--- a/common/config/nvim/lua/plugins/nvim-tree.lua
+++ b/common/config/nvim/lua/plugins/nvim-tree.lua
@@ -1,13 +1,126 @@
------------------------------------------------------------
--- Neovim File Tree Configuration
------------------------------------------------------------
+local M = {}
---- To see mappings `g?` on nvim-tree
---- To see default mappings `:nvim-tree-default-mappings`
+-- Safe require helper
+local function safe_require(name)
+ local ok, mod = pcall(require, name)
+ return ok and mod or nil
+end
+
+
+local ok, api = pcall(require, 'nvim-tree.api')
+if not ok then return end
+local function on_attach(bufnr)
+ local function opts(desc)
+ return { desc = "nvim-tree: " .. desc, buffer = bufnr, noremap = true, silent = true, nowait = true }
+ end
+
+ local mappings = {
+ ["<C-]>"] = { api.tree.change_root_to_node, "CD" },
+ ["<C-e>"] = { api.node.open.replace_tree_buffer, "Open: In Place" },
+ ["<C-k>"] = { api.node.show_info_popup, "Info" },
+ ["<C-r>"] = { api.fs.rename_sub, "Rename: Omit Filename" },
+ ["<C-t>"] = { api.node.open.tab, "Open: New Tab" },
+ ["<C-v>"] = { api.node.open.vertical, "Open: Vertical Split" },
+ ["<C-x>"] = { api.node.open.horizontal, "Open: Horizontal Split" },
+ ["<BS>"] = { api.node.navigate.parent_close, "Close Directory" },
+ -- ["<CR>"] = { api.node.open.edit, "Open" },
+ ["<Tab>"] = { api.node.open.preview, "Open Preview" },
+ [">"] = { api.node.navigate.sibling.next, "Next Sibling" },
+ ["<"] = { api.node.navigate.sibling.prev, "Previous Sibling" },
+ ["."] = { api.node.run.cmd, "Run Command" },
+ ["-"] = { api.tree.change_root_to_parent, "Up" },
+ ["a"] = { api.fs.create, "Create" },
+ ["bmv"] = { api.marks.bulk.move, "Move Bookmarked" },
+ ["B"] = { api.tree.toggle_no_buffer_filter, "Toggle No Buffer" },
+ ["c"] = { api.fs.copy.node, "Copy" },
+ -- ["C"] = { api.tree.toggle_git_clean_filter, "Toggle Git Clean" },
+ ["[c"] = { api.node.navigate.git.prev, "Prev Git" },
+ ["]c"] = { api.node.navigate.git.next, "Next Git" },
+ ["d"] = { api.fs.remove, "Delete" },
+ ["D"] = { api.fs.trash, "Trash" },
+ ["E"] = { api.tree.expand_all, "Expand All" },
+ ["e"] = { api.fs.rename_basename, "Rename: Basename" },
+ ["]e"] = { api.node.navigate.diagnostics.next, "Next Diagnostic" },
+ ["[e"] = { api.node.navigate.diagnostics.prev, "Prev Diagnostic" },
+ ["F"] = { api.live_filter.clear, "Clean Filter" },
+ ["f"] = { api.live_filter.start, "Filter" },
+ ["g?"] = { api.tree.toggle_help, "Help" },
+ ["gy"] = { api.fs.copy.absolute_path, "Copy Absolute Path" },
+ ["H"] = { api.tree.toggle_hidden_filter, "Toggle Dotfiles" },
+ ["I"] = { api.tree.toggle_gitignore_filter, "Toggle Git Ignore" },
+ ["J"] = { api.node.navigate.sibling.last, "Last Sibling" },
+ ["K"] = { api.node.navigate.sibling.first, "First Sibling" },
+ ["m"] = { api.marks.toggle, "Toggle Bookmark" },
+ -- ["o"] = { api.node.open.edit, "Open" },
+ ["O"] = { api.node.open.no_window_picker, "Open: No Window Picker" },
+ ["p"] = { api.fs.paste, "Paste" },
+ ["P"] = { api.node.navigate.parent, "Parent Directory" },
+ ["q"] = { api.tree.close, "Close" },
+ ["r"] = { api.fs.rename, "Rename" },
+ ["R"] = { api.tree.reload, "Refresh" },
+ ["s"] = { api.node.run.system, "Run System" },
+ ["S"] = { api.tree.search_node, "Search" },
+ ["U"] = { api.tree.toggle_custom_filter, "Toggle Hidden" },
+ ["W"] = { api.tree.collapse_all, "Collapse" },
+ ["x"] = { api.fs.cut, "Cut" },
+ ["y"] = { api.fs.copy.filename, "Copy Name" },
+ ["Y"] = { api.fs.copy.relative_path, "Copy Relative Path" },
+ ["<2-LeftMouse>"] = { api.node.open.edit, "Open" },
+ ["<2-RightMouse>"] = { api.tree.change_root_to_node, "CD" },
--- Nvim-Tree.lua advises to do this at the start.
-vim.g.loaded_netrw = 1
-vim.g.loaded_netrwPlugin = 1
+ -- Mappings migrated from view.mappings.list
+ ["l"] = { api.node.open.edit, "Open" },
+ ["<CR>"] = { api.node.open.edit, "Open" },
+ ["o"] = { api.node.open.edit, "Open" },
+ ["h"] = { api.node.navigate.parent_close, "Close Directory" },
+ ["v"] = { api.node.open.vertical, "Open: Vertical Split" },
+ ["C"] = { api.tree.change_root_to_node, "CD" },
+ }
+ for keys, mapping in pairs(mappings) do
+ vim.keymap.set("n", keys, mapping[1], opts(mapping[2]))
+ end
+end
+
+---- Icons configuration for nvim-tree
+--local icons = {
+-- webdev_colors = true,
+-- git_placement = "before",
+-- modified_placement = "after",
+-- padding = " ",
+-- symlink_arrow = " ➛ ",
+-- show = {
+-- file = true,
+-- folder = true,
+-- folder_arrow = true,
+-- git = true,
+-- modified = true,
+-- },
+-- glyphs = {
+-- default = "",
+-- symlink = "",
+-- bookmark = "",
+-- modified = "●",
+-- folder = {
+-- arrow_closed = "",
+-- arrow_open = "",
+-- default = "",
+-- open = "",
+-- empty = "",
+-- empty_open = "",
+-- symlink = "",
+-- symlink_open = "",
+-- },
+-- git = {
+-- unstaged = "✗",
+-- staged = "✓",
+-- unmerged = "",
+-- renamed = "➜",
+-- untracked = "★",
+-- deleted = "",
+-- ignored = "◌",
+-- },
+-- },
+--}
local icons = {
webdev_colors = true,
@@ -39,7 +152,7 @@ local icons = {
git = {
deleted = "",
unmerged = "",
- untracked = "",
+ untracked = "",
unstaged = "",
staged = "",
renamed = "➜",
@@ -54,6 +167,28 @@ local icons = {
},
}
+local float = {
+ enable = false,
+ open_win_config = function()
+ local screen_w = vim.o.columns
+ local screen_h = vim.o.lines - vim.o.cmdheight
+ local window_w = screen_w * WIDTH_RATIO
+ local window_h = screen_h * HEIGHT_RATIO
+ local window_w_int = math.floor(window_w)
+ local window_h_int = math.floor(window_h)
+ local center_x = (screen_w - window_w) / 2
+ local center_y = ((vim.o.lines - window_h) / 2) - vim.o.cmdheight
+ return {
+ border = "rounded",
+ relative = "editor",
+ row = center_y,
+ col = center_x,
+ width = window_w_int,
+ height = window_h_int,
+ }
+ end,
+}
+
local renderer = {
group_empty = true, -- default: true. Compact folders that only contain a single folder into one node in the file tree.
highlight_git = false,
@@ -75,33 +210,11 @@ local renderer = {
},
icons = icons,
}
+
local system_open = { cmd = "zathura" }
local HEIGHT_RATIO = 0.8
local WIDTH_RATIO = 0.15
-
-local float = {
- enable = false,
- open_win_config = function()
- local screen_w = vim.opt.columns:get()
- local screen_h = vim.opt.lines:get() - vim.opt.cmdheight:get()
- local window_w = screen_w * WIDTH_RATIO
- local window_h = screen_h * HEIGHT_RATIO
- local window_w_int = math.floor(window_w)
- local window_h_int = math.floor(window_h)
- local center_x = (screen_w - window_w) / 2
- local center_y = ((vim.opt.lines:get() - window_h) / 2) - vim.opt.cmdheight:get()
- return {
- border = "rounded",
- relative = "editor",
- row = center_y,
- col = center_x,
- width = window_w_int,
- height = window_h_int,
- }
- end,
-}
-
local view = {
cursorline = true,
float = float,
@@ -113,311 +226,254 @@ local view = {
side = "left",
}
-local api = require("nvim-tree.api")
-local function on_attach(bufnr)
- local function opts(desc)
- return { desc = "nvim-tree: " .. desc, buffer = bufnr, noremap = true, silent = true, nowait = true }
+-- Open nvim-tree when opening a directory
+local function open_nvim_tree(data)
+ -- buffer is a directory
+ local directory = vim.fn.isdirectory(data.file) == 1
+
+ if not directory then
+ return
end
- local mappings = {
- ["<C-]>"] = { api.tree.change_root_to_node, "CD" },
- ["<C-e>"] = { api.node.open.replace_tree_buffer, "Open: In Place" },
- ["<C-k>"] = { api.node.show_info_popup, "Info" },
- ["<C-r>"] = { api.fs.rename_sub, "Rename: Omit Filename" },
- ["<C-t>"] = { api.node.open.tab, "Open: New Tab" },
- ["<C-v>"] = { api.node.open.vertical, "Open: Vertical Split" },
- ["<C-x>"] = { api.node.open.horizontal, "Open: Horizontal Split" },
- ["<BS>"] = { api.node.navigate.parent_close, "Close Directory" },
- -- ["<CR>"] = { api.node.open.edit, "Open" },
- ["<Tab>"] = { api.node.open.preview, "Open Preview" },
- [">"] = { api.node.navigate.sibling.next, "Next Sibling" },
- ["<"] = { api.node.navigate.sibling.prev, "Previous Sibling" },
- ["."] = { api.node.run.cmd, "Run Command" },
- ["-"] = { api.tree.change_root_to_parent, "Up" },
- ["a"] = { api.fs.create, "Create" },
- ["bmv"] = { api.marks.bulk.move, "Move Bookmarked" },
- ["B"] = { api.tree.toggle_no_buffer_filter, "Toggle No Buffer" },
- ["c"] = { api.fs.copy.node, "Copy" },
- -- ["C"] = { api.tree.toggle_git_clean_filter, "Toggle Git Clean" },
- ["[c"] = { api.node.navigate.git.prev, "Prev Git" },
- ["]c"] = { api.node.navigate.git.next, "Next Git" },
- ["d"] = { api.fs.remove, "Delete" },
- ["D"] = { api.fs.trash, "Trash" },
- ["E"] = { api.tree.expand_all, "Expand All" },
- ["e"] = { api.fs.rename_basename, "Rename: Basename" },
- ["]e"] = { api.node.navigate.diagnostics.next, "Next Diagnostic" },
- ["[e"] = { api.node.navigate.diagnostics.prev, "Prev Diagnostic" },
- ["F"] = { api.live_filter.clear, "Clean Filter" },
- ["f"] = { api.live_filter.start, "Filter" },
- ["g?"] = { api.tree.toggle_help, "Help" },
- ["gy"] = { api.fs.copy.absolute_path, "Copy Absolute Path" },
- ["H"] = { api.tree.toggle_hidden_filter, "Toggle Dotfiles" },
- ["I"] = { api.tree.toggle_gitignore_filter, "Toggle Git Ignore" },
- ["J"] = { api.node.navigate.sibling.last, "Last Sibling" },
- ["K"] = { api.node.navigate.sibling.first, "First Sibling" },
- ["m"] = { api.marks.toggle, "Toggle Bookmark" },
- -- ["o"] = { api.node.open.edit, "Open" },
- ["O"] = { api.node.open.no_window_picker, "Open: No Window Picker" },
- ["p"] = { api.fs.paste, "Paste" },
- ["P"] = { api.node.navigate.parent, "Parent Directory" },
- ["q"] = { api.tree.close, "Close" },
- ["r"] = { api.fs.rename, "Rename" },
- ["R"] = { api.tree.reload, "Refresh" },
- ["s"] = { api.node.run.system, "Run System" },
- ["S"] = { api.tree.search_node, "Search" },
- ["U"] = { api.tree.toggle_custom_filter, "Toggle Hidden" },
- ["W"] = { api.tree.collapse_all, "Collapse" },
- ["x"] = { api.fs.cut, "Cut" },
- ["y"] = { api.fs.copy.filename, "Copy Name" },
- ["Y"] = { api.fs.copy.relative_path, "Copy Relative Path" },
- ["<2-LeftMouse>"] = { api.node.open.edit, "Open" },
- ["<2-RightMouse>"] = { api.tree.change_root_to_node, "CD" },
+ -- change to the directory
+ vim.cmd.cd(data.file)
- -- Mappings migrated from view.mappings.list
- ["l"] = { api.node.open.edit, "Open" },
- ["<CR>"] = { api.node.open.edit, "Open" },
- ["o"] = { api.node.open.edit, "Open" },
- ["h"] = { api.node.navigate.parent_close, "Close Directory" },
- ["v"] = { api.node.open.vertical, "Open: Vertical Split" },
- ["C"] = { api.tree.change_root_to_node, "CD" },
- }
- for keys, mapping in pairs(mappings) do
- vim.keymap.set("n", keys, mapping[1], opts(mapping[2]))
- end
+ -- open the tree
+ require("nvim-tree.api").tree.open()
end
---api.events.subscribe(api.events.Event.FileCreated, function(file)
--- vim.cmd('edit' .. file.fname)
---end)
-
-require("nvim-tree").setup({
- --auto_reload_on_write = true,
- --create_in_closed_folder = false,
- --hijack_cursor = true,
- --disable_netrw = true,
- --hijack_netrw = true,
- --hijack_unnamed_buffer_when_opening = false,
- --ignore_buffer_on_setup = false,
- update_focused_file = {
- enable = true,
+
+
+-- Setup function
+function M.setup()
+ -- Check if nvim-tree is installed
+ --local nvim_tree = safe_require('nvim-tree')
+ --if not nvim_tree then
+ -- return false
+ --end
+
+ local nvim_tree = safe_require('nvim-tree')
+ if type(nvim_tree) ~= "table" or not nvim_tree.setup then
+ --vim.notify("[nvim-tree] Plugin did not load correctly", vim.log.levels.ERROR)
+ return false
+ end
+
+ -- Setup nvim-tree
+ nvim_tree.setup({
+ sync_root_with_cwd = true,
+ respect_buf_cwd = true,
+ disable_netrw = true,
+ hijack_netrw = true,
+ open_on_tab = false,
+ hijack_cursor = false,
update_cwd = true,
- update_root = true,
- ignore_list = {},
- },
- root_dirs = {},
- --prefer_startup_root = true,
- --hijack_directories = {
- -- enable = false,
- --},
- --respect_buf_cwd = false,
- sync_root_with_cwd = true,
- --reload_on_bufenter = false,
- filesystem_watchers = {
- enable = true,
- debounce_delay = 50,
- ignore_dirs = { "node_modules", ".config/nvm" },
- },
- view = view,
- system_open = system_open,
- renderer = renderer,
- on_attach = on_attach,
- notify = {
- threshold = vim.log.levels.ERROR,
- },
- log = {
- enable = true,
- truncate = true,
- types = {
- diagnostics = true,
- git = true,
- profile = true,
- watcher = true,
+ hijack_directories = {
+ enable = true,
+ auto_open = true,
},
- },
- git = { ignore = false },
- diagnostics = {
- enable = true,
- show_on_dirs = true,
- icons = {
- hint = "⚑",
- info = "􀅳",
- warning = "▲",
- error = "",
+ diagnostics = {
+ enable = true,
+ icons = {
+ error = "✘",
+ warning = "",
+ hint = "◉",
+ info = "",
+ },
},
- },
- trash = {
- cmd = "gio trash",
- require_confirm = true,
- },
- modified = {
- enable = true,
- show_on_dirs = true,
- show_on_open_dirs = true,
- },
- --filters = {
- -- dotfiles = false,
- -- git_clean = false,
- -- no_buffer = false,
- -- custom = {},
- -- exclude = {},
- --},
- actions = {
- use_system_clipboard = true,
- change_dir = {
+ filesystem_watchers = {
+ enable = true,
+ debounce_delay = 50,
+ ignore_dirs = { "node_modules", ".config/nvm" },
+ },
+ update_focused_file = {
enable = true,
- global = false,
- restrict_above_cwd = false,
+ update_cwd = true,
+ --update_root = true,
+ ignore_list = {},
+ },
+ --root_dirs = {},
+ --system_open = {
+ -- --cmd = nil,
+ -- --args = {},
+ --},
+ system_open = system_open,
+ filters = {
+ dotfiles = false,
+ custom = {},
},
- remove_file = {
- close_window = true,
+ --git = {
+ -- enable = true,
+ -- ignore = true,
+ -- timeout = 500,
+ --},
+ git = { ignore = false },
+ view = view,
+ renderer = renderer,
+ --renderer = {
+ -- indent_markers = {
+ -- enable = false,
+ -- icons = {
+ -- corner = "└ ",
+ -- edge = "│ ",
+ -- none = " ",
+ -- },
+ -- },
+ -- icons = icons,
+ --},
+ on_attach = on_attach,
+ notify = {
+ threshold = vim.log.levels.ERROR,
+ },
+ log = {
+ enable = true,
+ truncate = true,
+ types = {
+ diagnostics = true,
+ git = true,
+ profile = true,
+ watcher = true,
+ },
},
- open_file = {
- quit_on_open = true,
- --eject = true,
- resize_window = false,
- window_picker = {
+ trash = {
+ cmd = "gio trash",
+ require_confirm = true,
+ },
+ modified = {
+ enable = true,
+ show_on_dirs = true,
+ show_on_open_dirs = true,
+ },
+ actions = {
+ use_system_clipboard = true,
+ change_dir = {
enable = true,
- chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890",
- exclude = {
- filetype = { "notify", "packer", "qf", "diff", "fugitive", "fugitiveblame" },
- buftype = { "nofile", "terminal", "help" },
+ global = false,
+ restrict_above_cwd = false,
+ },
+ remove_file = {
+ close_window = true,
+ },
+ open_file = {
+ quit_on_open = false,
+ resize_window = true,
+ window_picker = {
+ enable = true,
+ chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890",
+ exclude = {
+ filetype = { "notify", "packer", "qf", "diff", "fugitive", "fugitiveblame" },
+ buftype = { "nofile", "terminal", "help" },
+ },
},
},
},
- },
-})
-
-local api = require("nvim-tree.api")
-local event = api.events.Event
---api.events.subscribe(event.TreeOpen, function(_)
--- vim.cmd([[setlocal statuscolumn=\ ]])
--- vim.cmd([[setlocal cursorlineopt=number]])
--- vim.cmd([[setlocal fillchars+=vert:🮇]])
--- vim.cmd([[setlocal fillchars+=horizup:🮇]])
--- vim.cmd([[setlocal fillchars+=vertright:🮇]])
---end)
+ })
-local function open_nvim_tree(data)
- vim.cmd.cd(data.file:match("(.+)/[^/]*$"))
- local directory = vim.fn.isdirectory(data.file) == 1
- if not directory then
- return
- end
- require("nvim-tree.api").tree.open()
-end
-vim.api.nvim_create_autocmd({ "VimEnter" }, { callback = open_nvim_tree })
--- Change Root To Global Current Working Directory
-local function change_root_to_global_cwd()
local api = require("nvim-tree.api")
- local global_cwd = vim.fn.getcwd(-1, -1)
- api.tree.change_root(global_cwd)
-end
+ --local event = api.events.Event
+ --api.events.subscribe(event.TreeOpen, function(_)
+ -- vim.cmd([[setlocal statuscolumn=\ ]])
+ -- vim.cmd([[setlocal cursorlineopt=number]])
+ -- vim.cmd([[setlocal fillchars+=vert:🮇]])
+ -- vim.cmd([[setlocal fillchars+=horizup:🮇]])
+ -- vim.cmd([[setlocal fillchars+=vertright:🮇]])
+ --end)
-local function copy_file_to(node)
- local file_src = node["absolute_path"]
- -- The args of input are {prompt}, {default}, {completion}
- -- Read in the new file path using the existing file's path as the baseline.
- local file_out = vim.fn.input("COPY TO: ", file_src, "file")
- -- Create any parent dirs as required
- local dir = vim.fn.fnamemodify(file_out, ":h")
- vim.fn.system({ "mkdir", "-p", dir })
- -- Copy the file
- vim.fn.system({ "cp", "-R", file_src, file_out })
-end
+ local function open_nvim_tree(data)
+ vim.cmd.cd(data.file:match("(.+)/[^/]*$"))
+ local directory = vim.fn.isdirectory(data.file) == 1
+ if not directory then
+ return
+ end
+ require("nvim-tree.api").tree.open()
+ end
+
+ -- Auto open nvim-tree when opening a directory
+ vim.api.nvim_create_autocmd({ "VimEnter" }, { pattern = { "*" }, callback = open_nvim_tree })
+
+ -- Change Root To Global Current Working Directory
+ local function change_root_to_global_cwd()
+ local api = require("nvim-tree.api")
+ local global_cwd = vim.fn.getcwd(-1, -1)
+ api.tree.change_root(global_cwd)
+ end
+
+ local function copy_file_to(node)
+ local file_src = node["absolute_path"]
+ -- The args of input are {prompt}, {default}, {completion}
+ -- Read in the new file path using the existing file's path as the baseline.
+ local file_out = vim.fn.input("COPY TO: ", file_src, "file")
+ -- Create any parent dirs as required
+ local dir = vim.fn.fnamemodify(file_out, ":h")
+ vim.fn.system({ "mkdir", "-p", dir })
+ -- Copy the file
+ vim.fn.system({ "cp", "-R", file_src, file_out })
+ end
+
+ local function edit_and_close(node)
+ api.node.open.edit(node, {})
+ api.tree.close()
+ end
-local function edit_and_close(node)
- api.node.open.edit(node, {})
- api.tree.close()
+ --vim.api.nvim_create_augroup('NvimTreeRefresh', {})
+ --vim.api.nvim_create_autocmd('BufEnter', {
+ -- pattern = 'NvimTree_1',
+ -- command = 'NvimTreeRefresh',
+ -- group = 'NvimTreeRefresh',
+ --})
+
+ vim.api.nvim_create_autocmd({ "CursorHold" }, {
+ pattern = "NvimTree*",
+ callback = function()
+ local def = vim.api.nvim_get_hl_by_name("Cursor", true)
+ vim.api.nvim_set_hl(
+ 0,
+ "Cursor",
+ vim.tbl_extend("force", def, {
+ blend = 100,
+ })
+ )
+ vim.opt.guicursor = "n-v-c-sm:block,i-ci-ve:ver25,r-cr-o:hor20,a:Cursor/lCursor"
+ end,
+ })
+
+ vim.api.nvim_create_autocmd({ "BufLeave", "WinClosed", "WinLeave" }, {
+ pattern = "NvimTree*",
+ callback = function()
+ local def = vim.api.nvim_get_hl_by_name("Cursor", true)
+ vim.api.nvim_set_hl(
+ 0,
+ "Cursor",
+ vim.tbl_extend("force", def, {
+ blend = 0,
+ })
+ )
+ vim.opt.guicursor = "n-v-c-sm:block,i-ci-ve:ver25,r-cr-o:hor20"
+ end,
+ })
+
+ vim.api.nvim_command("highlight NvimTreeNormal guibg=NONE ctermbg=NONE")
+ vim.api.nvim_command("highlight NvimTreeNormalNC guibg=NONE ctermbg=NONE guifg=NONE")
+ vim.api.nvim_command("highlight NvimTreeNormalFloat guibg=NONE ctermbg=NONE")
+ vim.api.nvim_command("highlight NvimTreeEndOfBuffer guibg=NONE ctermbg=NONE") --(NonText)
+ vim.api.nvim_command("highlight NvimTreeCursorLine guibg=#50fa7b guifg=#000000")
+ vim.api.nvim_command("highlight NvimTreeSymlinkFolderName guifg=#f8f8f2 guibg=NONE ctermbg=NONE")
+ vim.api.nvim_command("highlight NvimTreeFolderName guifg=#f8f8f2 guibg=NONE ctermbg=NONE")
+ vim.api.nvim_command("highlight NvimTreeRootFolder guifg=#f8f8f2 guibg=NONE ctermbg=NONE")
+ vim.api.nvim_command("highlight NvimTreeEmptyFolderName guifg=#f8f8f2 guibg=NONE ctermbg=NONE") --(Directory)
+ vim.api.nvim_command("highlight NvimTreeOpenedFolderName guifg=#f8f8f2 guibg=NONE ctermbg=NONE") --(Directory)
+ vim.api.nvim_command("highlight NvimTreeOpenedFile guifg=#50fa7b guibg=NONE ctermbg=NONE")
+ vim.api.nvim_command("highlight NvimTreeExecFile guifg=#ff882a guibg=none gui=NONE")
+
+ return true
end
---vim.api.nvim_create_augroup('NvimTreeRefresh', {})
---vim.api.nvim_create_autocmd('BufEnter', {
--- pattern = 'NvimTree_1',
--- command = 'NvimTreeRefresh',
--- group = 'NvimTreeRefresh',
---})
-
-vim.api.nvim_create_autocmd({ "CursorHold" }, {
- pattern = "NvimTree*",
- callback = function()
- local def = vim.api.nvim_get_hl_by_name("Cursor", true)
- vim.api.nvim_set_hl(
- 0,
- "Cursor",
- vim.tbl_extend("force", def, {
- blend = 100,
- })
- )
- vim.opt.guicursor:append("a:Cursor/lCursor")
- end,
-})
-
-vim.api.nvim_create_autocmd({ "BufLeave", "WinClosed", "WinLeave" }, {
- pattern = "NvimTree*",
- callback = function()
- local def = vim.api.nvim_get_hl_by_name("Cursor", true)
- vim.api.nvim_set_hl(
- 0,
- "Cursor",
- vim.tbl_extend("force", def, {
- blend = 0,
- })
- )
- vim.opt.guicursor = "n-v-c-sm:block,i-ci-ve:ver25,r-cr-o:hor20"
- end,
-})
+---- Set highlights
+--vim.cmd([[highlight NvimTreeNormal guibg=NONE ctermbg=NONE]])
+--vim.cmd([[highlight NvimTreeNormalNC guibg=NONE ctermbg=NONE guifg=NONE]])
+--vim.cmd([[highlight NvimTreeNormalFloat guibg=NONE ctermbg=NONE]])
+--vim.cmd([[highlight NvimTreeEndOfBuffer guibg=NONE ctermbg=NONE]])
+--vim.cmd([[highlight NvimTreeCursorLine guibg=#50fa7b guifg=#000000]])
-- Highlight Groups
-vim.api.nvim_command("highlight NvimTreeNormal guibg=NONE ctermbg=NONE")
-vim.api.nvim_command("highlight NvimTreeNormalNC guibg=NONE ctermbg=NONE guifg=NONE")
-vim.api.nvim_command("highlight NvimTreeNormalFloat guibg=NONE ctermbg=NONE")
-vim.api.nvim_command("highlight NvimTreeEndOfBuffer guibg=NONE ctermbg=NONE") --(NonText)
-vim.api.nvim_command("highlight NvimTreeCursorLine guibg=#50fa7b guifg=#000000")
-vim.api.nvim_command("highlight NvimTreeSymlinkFolderName guifg=#f8f8f2 guibg=NONE ctermbg=NONE")
-vim.api.nvim_command("highlight NvimTreeFolderName guifg=#f8f8f2 guibg=NONE ctermbg=NONE")
-vim.api.nvim_command("highlight NvimTreeRootFolder guifg=#f8f8f2 guibg=NONE ctermbg=NONE")
-vim.api.nvim_command("highlight NvimTreeEmptyFolderName guifg=#f8f8f2 guibg=NONE ctermbg=NONE") --(Directory)
-vim.api.nvim_command("highlight NvimTreeOpenedFolderName guifg=#f8f8f2 guibg=NONE ctermbg=NONE") --(Directory)
-vim.api.nvim_command("highlight NvimTreeOpenedFile guifg=#50fa7b guibg=NONE ctermbg=NONE")
-
---vim.api.nvim_command("highlight NvimTreeSymlink ")
---vim.api.nvim_command("highlight NvimTreeSymlinkFolderName ") --(Directory)
---vim.api.nvim_command("highlight NvimTreeFolderName ") --(Directory)
---vim.api.nvim_command("highlight NvimTreeRootFolder ")
---vim.api.nvim_command("highlight NvimTreeFolderIcon ")
---vim.api.nvim_command("highlight NvimTreeOpenedFolderIcon ") --(NvimTreeFolderIcon)
---vim.api.nvim_command("highlight NvimTreeClosedFolderIcon ") --(NvimTreeFolderIcon)
---vim.api.nvim_command("highlight NvimTreeFileIcon ")
---vim.api.nvim_command("highlight NvimTreeEmptyFolderName ") --(Directory)
---vim.api.nvim_command("highlight NvimTreeOpenedFolderName ") --(Directory)
---vim.api.nvim_command("highlight NvimTreeExecFile ")
-vim.api.nvim_command("highlight NvimTreeExecFile guifg=#ff882a guibg=none gui=NONE")
---vim.api.nvim_command("highlight NvimTreeOpenedFile ")
---vim.api.nvim_command("highlight NvimTreeModifiedFile ")
---vim.api.nvim_command("highlight NvimTreeSpecialFile ")
---vim.api.nvim_command("highlight NvimTreeImageFile ")
---vim.api.nvim_command("highlight NvimTreeIndentMarker ")
---vim.api.nvim_command("highlight NvimTreeLspDiagnosticsError ") --(DiagnosticError)
---vim.api.nvim_command("highlight NvimTreeLspDiagnosticsWarning ") --(DiagnosticWarn)
---vim.api.nvim_command("highlight NvimTreeLspDiagnosticsInformation ") --(DiagnosticInfo)
---vim.api.nvim_command("highlight NvimTreeLspDiagnosticsHint ") --(DiagnosticHint)
---vim.api.nvim_command("highlight NvimTreeGitDirty ")
---vim.api.nvim_command("highlight NvimTreeGitStaged ")
---vim.api.nvim_command("highlight NvimTreeGitMerge ")
---vim.api.nvim_command("highlight NvimTreeGitRenamed ")
---vim.api.nvim_command("highlight NvimTreeGitNew ")
---vim.api.nvim_command("highlight NvimTreeGitDeleted ")
---vim.api.nvim_command("highlight NvimTreeGitIgnored ") --(Comment)
---vim.api.nvim_command("highlight NvimTreeNormal ")
---vim.api.nvim_command("highlight NvimTreeEndOfBuffer ") --(NonText)
---vim.api.nvim_command("highlight NvimTreeCursorColumn ") --(CursorColumn)
---vim.api.nvim_command("highlight NvimTreeFileDirty ") --(NvimTreeGitDirty)
---vim.api.nvim_command("highlight NvimTreeFileStaged ") --(NvimTreeGitStaged)
---vim.api.nvim_command("highlight NvimTreeFileMerge ") --(NvimTreeGitMerge)
---vim.api.nvim_command("highlight NvimTreeFileRenamed ") --(NvimTreeGitRenamed)
---vim.api.nvim_command("highlight NvimTreeFileNew ") --(NvimTreeGitNew)
---vim.api.nvim_command("highlight NvimTreeFileDeleted ") --(NvimTreeGitDeleted)
---vim.api.nvim_command("highlight NvimTreeFileIgnored ") --(NvimTreeGitIgnored)
---vim.api.nvim_command("highlight NvimTreeLiveFilterPrefix ")
---vim.api.nvim_command("highlight NvimTreeLiveFilterValue ")
---vim.api.nvim_command("highlight NvimTreeBookmark ")
+
+return M
diff --git a/common/config/nvim/lua/plugins/overseer.lua b/common/config/nvim/lua/plugins/overseer.lua
index 6319d36..593d094 100644..100755
--- a/common/config/nvim/lua/plugins/overseer.lua
+++ b/common/config/nvim/lua/plugins/overseer.lua
@@ -1 +1,14 @@
-require('overseer').setup()
+local M = {}
+
+function M.setup()
+ local ok, overseer = pcall(require, 'overseer')
+ if not ok or not overseer then
+ return false
+ end
+
+ overseer.setup({})
+
+ return true
+end
+
+return M
diff --git a/common/config/nvim/lua/plugins/plenary.lua b/common/config/nvim/lua/plugins/plenary.lua
new file mode 100755
index 0000000..f572244
--- /dev/null
+++ b/common/config/nvim/lua/plugins/plenary.lua
@@ -0,0 +1,3 @@
+-- plenary.nvim plugin config (modular, robust)
+local ok, _ = pcall(require, 'plenary')
+-- No config needed \ No newline at end of file
diff --git a/common/config/nvim/lua/plugins/prettier.lua b/common/config/nvim/lua/plugins/prettier.lua
new file mode 100755
index 0000000..ca57ea9
--- /dev/null
+++ b/common/config/nvim/lua/plugins/prettier.lua
@@ -0,0 +1,8 @@
+local M = {}
+
+function M.setup()
+ -- No-op if prettier is not installed
+ return true
+end
+
+return M
diff --git a/common/config/nvim/lua/plugins/quickfix.lua b/common/config/nvim/lua/plugins/quickfix.lua
index 4a76da0..4a76da0 100644..100755
--- a/common/config/nvim/lua/plugins/quickfix.lua
+++ b/common/config/nvim/lua/plugins/quickfix.lua
diff --git a/common/config/nvim/lua/plugins/session.lua b/common/config/nvim/lua/plugins/session.lua
deleted file mode 100644
index 0c84625..0000000
--- a/common/config/nvim/lua/plugins/session.lua
+++ /dev/null
@@ -1,5 +0,0 @@
-require('auto-session').setup({
- log_level = 'error',
- auto_session_suppress_dirs = { '~/', '~/projects', '~/downloads', '/' },
-})
-require('session-lens').setup({})
diff --git a/common/config/nvim/lua/plugins/snippets.lua b/common/config/nvim/lua/plugins/snippets.lua
index 7df6b2f..989ad8a 100644..100755
--- a/common/config/nvim/lua/plugins/snippets.lua
+++ b/common/config/nvim/lua/plugins/snippets.lua
@@ -1,68 +1,33 @@
-local ls = require "luasnip" --
+local M = {}
-require("luasnip.loaders.from_lua").load({ paths = "~/.config/nvim/snippets/" })
---local options = {
-ls.config.set_config {
- history = true,
- updateevents = "TextChanged,TextChangedI",
- -- Autosnippets:
- enable_autosnippets = true, --
- region_check_events = "InsertEnter",
- delete_check_events = "TextChanged",
- update_events = "TextChanged,TextChangedI",
- store_selection_keys = "<Tab>",
- ext_opts = { --
- [require("luasnip.util.types").choiceNode] = {
- active = {
- virt_text = { { "«", "GruvboxOrange" } },
- },
- },
- },
-}
-
---local keymap = vim.keymap
---local keymap = vim.api.nvim_set_keymap
-local keymap = vim.keymap.set
---keymap('i', '<c-f>', 'luasnip#expand_or_jumpable() ? "<Plug>luasnip-expand-or-jump" : "<Tab>"', {expr = true, silent = true})
-keymap({ "i", "s"}, "<c-f>", function()
- if ls.expand_or_jumpable() then
- ls.expand()
- end
-end)
-
-keymap({ "i", "s"}, "<c-j>", function()
- if ls.jumpable(1) then
- ls.jump(1)
+function M.setup()
+ local ok, ls = pcall(require, "luasnip")
+ if not ok or not ls then
+ return false
end
-end)
-keymap({ "i", "s"}, "<c-k>", function()
- if ls.jumpable(-1) then
- ls.jump(-1)
- end
-end)
+ -- Safely load snippets
+ pcall(function() require("luasnip.loaders.from_lua").load({ paths = "~/.config/nvim/snippets/" }) end)
+ pcall(function() require("luasnip.loaders.from_vscode").lazy_load() end)
+ pcall(function() require("luasnip.loaders.from_snipmate").lazy_load() end)
-keymap({ "i", "s"}, "<c-c>", function()
- if ls.choice_active() then
- ls.change_choice(1)
- end
-end)
+ ls.config.set_config {
+ history = true,
+ updateevents = "TextChanged,TextChangedI",
+ enable_autosnippets = true,
+ region_check_events = "InsertEnter",
+ delete_check_events = "TextChanged",
+ store_selection_keys = "<Tab>",
+ ext_opts = {
+ [require("luasnip.util.types").choiceNode] = {
+ active = {
+ virt_text = { { "«", "GruvboxOrange" } },
+ },
+ },
+ },
+ }
-keymap({ "i", "s"}, "<a-c>", function()
- if ls.choice_active() then
- ls.change_choice(-1)
- end
-end)
+ return true
+end
--- Character class Matching
--- %a letters (A-Z, a-z)
--- %c control characters (\n, \t, \r, ...)
--- %d digits (0-9)
--- %l lower-case letter (a-z)
--- %p punctuation characters (!, ?, &, ...)
--- %s space characters
--- %u upper-case letters
--- %w alphanumeric characters (A-Z, a-z, 0-9)
--- %x hexadecimal digits (\3, \4, ...)
--- %z the character with representation 0
--- . Matches any character
+return M
diff --git a/common/config/nvim/lua/plugins/sniprun.lua b/common/config/nvim/lua/plugins/sniprun.lua
index 418e8cc..418e8cc 100644..100755
--- a/common/config/nvim/lua/plugins/sniprun.lua
+++ b/common/config/nvim/lua/plugins/sniprun.lua
diff --git a/common/config/nvim/lua/plugins/statuscol.lua b/common/config/nvim/lua/plugins/statuscol.lua
index 24a2308..c538790 100644..100755
--- a/common/config/nvim/lua/plugins/statuscol.lua
+++ b/common/config/nvim/lua/plugins/statuscol.lua
@@ -1,13 +1,17 @@
-local status, statuscol = pcall(require, "statuscol")
+local M = {}
-if not status then
- vim.notify("statuscol not found")
- return
-end
+function M.setup()
+ local ok, statuscol = pcall(require, "statuscol")
+ if not ok or not statuscol then
+ return false
+ end
-local builtin = require("statuscol.builtin")
+ local builtin_ok, builtin = pcall(require, "statuscol.builtin")
+ if not builtin_ok or not builtin then
+ return false
+ end
-statuscol.setup({
+ statuscol.setup({
segments = {
{ text = { builtin.lnumfunc }, click = "v:lua.ScLa" },
{ text = { "%s" }, click = "v:lua.ScSa" },
@@ -25,4 +29,9 @@ statuscol.setup({
"dapui_console",
"dapui_repl",
},
-})
+ })
+
+ return true
+end
+
+return M
diff --git a/common/config/nvim/lua/plugins/surround.lua b/common/config/nvim/lua/plugins/surround.lua
index 04def1b..71023c7 100644..100755
--- a/common/config/nvim/lua/plugins/surround.lua
+++ b/common/config/nvim/lua/plugins/surround.lua
@@ -1,4 +1,12 @@
-require("nvim-surround").setup({
+local M = {}
+
+function M.setup()
+ local ok, surround = pcall(require, 'nvim-surround')
+ if not ok or not surround then
+ return false
+ end
+
+ surround.setup({
keymaps = {
insert = false,
insert_line = false,
@@ -18,5 +26,10 @@ require("nvim-surround").setup({
["r"] = false,
["q"] = false,
["s"] = false,
- },
-})
+ },
+ })
+
+ return true
+end
+
+return M
diff --git a/common/config/nvim/lua/plugins/telescope.lua b/common/config/nvim/lua/plugins/telescope.lua
index 506be8b..5aca8ac 100644..100755
--- a/common/config/nvim/lua/plugins/telescope.lua
+++ b/common/config/nvim/lua/plugins/telescope.lua
@@ -1,372 +1,384 @@
local M = {}
--- Shorten function names
-local actions = require('telescope.actions')
-local fb_actions = require('telescope').extensions.file_browser.actions
---local builtin = require("telescope.builtin")
---local utils = require("telescope.utils")
---local layout_actions = require("telescope.actions.layout")
---local themes = require('telescope.themes')
-local actions_set = require('telescope.actions.set')
-local actions_state = require('telescope.actions.state')
-local finders = require('telescope.finders')
-local pickers = require('telescope.pickers')
-local config = require('telescope.config').values
-
-require('telescope').setup({
- defaults = {
- vimgrep_arguments = {
- 'rg',
- '--color=never',
- '--no-heading',
- '--with-filename',
- '--line-number',
- '--column',
- '--smart-case',
- '--hidden',
- '--fixed-strings',
- '--trim',
+-- Safely require a module
+-- @param name string The module name to require
+-- @return table|nil The loaded module or nil if failed
+local function safe_require(name)
+ local ok, mod = pcall(require, name)
+ return ok and mod or nil
+end
+
+--- Setup and configure Telescope
+-- This function initializes Telescope with default configurations and extensions
+-- @return boolean True if setup was successful, false otherwise
+function M.setup()
+ -- Check if Telescope is installed
+ local telescope = safe_require("telescope")
+ if not telescope then
+ return false
+ end
+ -- Require Telescope and fail early if missing
+ local telescope = safe_require("telescope")
+ if not telescope then
+ return false
+ end
+
+ local actions = safe_require("telescope.actions")
+ local actions_set = safe_require("telescope.actions.set")
+ local actions_state = safe_require("telescope.actions.state")
+ local finders = safe_require("telescope.finders")
+ local pickers = safe_require("telescope.pickers")
+ local config_mod = safe_require("telescope.config")
+ local utils = safe_require("telescope.utils")
+ local previewers = require("telescope.previewers")
+
+ local config = config_mod and config_mod.values or {}
+
+ -- 🛡 Safe previewer to avoid nil path error
+ local safe_previewer = function()
+ return require("telescope.previewers").new_buffer_previewer({
+ define_preview = function(self, entry)
+ if not entry or type(entry) ~= "table" then return end
+
+ local path = entry.path or entry.filename or entry.value
+ if type(path) ~= "string" or path == "" then return end
+
+ -- Avoid expanding things like " Recent Books" which aren't valid files
+ if path:match("^%s") then return end
+
+ -- Resolve tilde if present
+ path = path:gsub("^~", vim.env.HOME)
+
+ if vim.fn.filereadable(path) ~= 1 and vim.fn.isdirectory(path) ~= 1 then
+ return
+ end
+
+ -- Protect against nil path being passed further
+ if not self.state or not self.state.bufnr or not self.state.bufname then return end
+
+ local preview_utils = require("telescope.previewers.utils")
+ preview_utils.buffer_previewer_maker(path, self.state.bufnr, {
+ bufname = self.state.bufname,
+ callback = function(bufnr, success)
+ if not success then
+ vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, { "Failed to preview file." })
+ end
+ end,
+ })
+ end,
+ })
+ end
+
+ local function get_extension_actions(ext)
+ local ok, telescope_ext = pcall(require, "telescope._extensions." .. ext)
+ if not ok then return {} end
+ return telescope_ext.actions or {}
+ end
+
+ telescope.setup({
+ defaults = {
+ vimgrep_arguments = {
+ "rg",
+ "--color=never",
+ "--no-heading",
+ "--with-filename",
+ "--line-number",
+ "--column",
+ "--smart-case",
+ "--hidden",
+ "--fixed-strings",
+ "--trim",
+ },
+ previewer = safe_previewer(),
+ prompt_prefix = " ",
+ selection_caret = " ",
+ entry_prefix = " ",
+ path_display = { "tail" },
+ file_ignore_patterns = {
+ "packer_compiled.lua",
+ "~/.config/zsh/plugins",
+ "zcompdump",
+ "%.DS_Store",
+ "%.git/",
+ "%.spl",
+ "%[No Name%]",
+ "/$",
+ "node_modules",
+ "%.png",
+ "%.zip",
+ "%.pxd",
+ "^.local/",
+ "^.cache/",
+ "^downloads/",
+ "^music/",
+ },
+ mappings = {
+ i = {
+ ["<C-n>"] = actions.cycle_history_next,
+ ["<C-p>"] = actions.cycle_history_prev,
+ ["<C-j>"] = actions.move_selection_next,
+ ["<C-k>"] = actions.move_selection_previous,
+ ["<Esc>"] = actions.close,
+ ["<?>"] = actions.which_key,
+ ["<Down>"] = actions.move_selection_next,
+ ["<Up>"] = actions.move_selection_previous,
+ ["<CR>"] = actions.select_default,
+ ["<C-x>"] = actions.select_horizontal,
+ ["<C-y>"] = actions.select_vertical,
+ ["<C-t>"] = actions.select_tab,
+ ["<C-c>"] = actions.delete_buffer,
+ ["<C-u>"] = actions.preview_scrolling_up,
+ ["<C-d>"] = actions.preview_scrolling_down,
+ ["<PageUp>"] = actions.results_scrolling_up,
+ ["<PageDown>"] = actions.results_scrolling_down,
+ ["<Tab>"] = actions.toggle_selection + actions.move_selection_worse,
+ ["<S-Tab>"] = actions.toggle_selection + actions.move_selection_better,
+ ["<C-q>"] = actions.send_to_qflist + actions.open_qflist,
+ ["<M-q>"] = actions.send_selected_to_qflist + actions.open_qflist,
+ ["<C-l>"] = actions.complete_tag,
+ ["<C-_>"] = actions.which_key,
+ },
+ n = {
+ ["<esc>"] = actions.close,
+ ["<q>"] = actions.close,
+ ["<CR>"] = actions.select_default,
+ ["<C-x>"] = actions.select_horizontal,
+ ["<C-y>"] = actions.select_vertical,
+ ["<C-t>"] = actions.select_tab,
+ ["<C-c>"] = actions.delete_buffer,
+ ["<Tab>"] = actions.toggle_selection + actions.move_selection_worse,
+ ["<S-Tab>"] = actions.toggle_selection + actions.move_selection_better,
+ ["<C-q>"] = actions.send_to_qflist + actions.open_qflist,
+ ["<M-q>"] = actions.send_selected_to_qflist + actions.open_qflist,
+ ["j"] = actions.move_selection_next,
+ ["k"] = actions.move_selection_previous,
+ ["H"] = actions.move_to_top,
+ ["M"] = actions.move_to_middle,
+ ["L"] = actions.move_to_bottom,
+ ["<Down>"] = actions.move_selection_next,
+ ["<Up>"] = actions.move_selection_previous,
+ ["gg"] = actions.move_to_top,
+ ["G"] = actions.move_to_bottom,
+ ["<C-u>"] = actions.preview_scrolling_up,
+ ["<C-d>"] = actions.preview_scrolling_down,
+ ["<PageUp>"] = actions.results_scrolling_up,
+ ["<PageDown>"] = actions.results_scrolling_down,
+ ["cd"] = function(prompt_bufnr)
+ local selection = actions_state.get_selected_entry()
+ local dir = vim.fn.fnamemodify(selection.path, ":p:h")
+ actions.close(prompt_bufnr)
+ vim.cmd("silent lcd " .. dir)
+ end,
+ ["?"] = actions.which_key,
+ },
+ },
},
- prompt_prefix = ' ',
- selection_caret = ' ',
- entry_prefix = ' ',
- path_display = { 'tail' },
- --path_display = { "truncate" },
- --path_display = { "smart" },
- file_ignore_patterns = {
- 'packer_compiled.lua',
- '~/.config/zsh/plugins',
- 'zcompdump',
- '%.DS_Store',
- '%.git/',
- '%.spl',
- --"%.log",
- '%[No Name%]', -- new files / sometimes folders (netrw)
- '/$', -- ignore folders (netrw)
- 'node_modules',
- '%.png',
- '%.zip',
- '%.pxd',
- --"^.vim/",
- '^.local/',
- '^.cache/',
- '^downloads/',
- '^music/',
- --"^node_modules/",
- --"^undodir/",
+ preview = {
+ filesize_limit = 3,
+ timeout = 250,
},
- mappings = {
- i = {
- ['<C-n>'] = actions.cycle_history_next,
- ['<C-p>'] = actions.cycle_history_prev,
-
- ['<C-j>'] = actions.move_selection_next,
- ['<C-k>'] = actions.move_selection_previous,
-
- --["<C-c>"] = actions.close,
- ['<Esc>'] = actions.close, -- close w/ one esc
- --["<Esc>"] = "close", -- close w/ one esc
- ['<?>'] = actions.which_key, -- keys from pressing <C-/>
-
- ['<Down>'] = actions.move_selection_next,
- ['<Up>'] = actions.move_selection_previous,
-
- ['<CR>'] = actions.select_default,
- ['<C-x>'] = actions.select_horizontal,
- ['<C-y>'] = actions.select_vertical,
- ['<C-t>'] = actions.select_tab,
- ['<C-c>'] = actions.delete_buffer,
-
- ['<C-u>'] = actions.preview_scrolling_up,
- ['<C-d>'] = actions.preview_scrolling_down,
-
- ['<PageUp>'] = actions.results_scrolling_up,
- ['<PageDown>'] = actions.results_scrolling_down,
-
- ['<Tab>'] = actions.toggle_selection + actions.move_selection_worse,
- ['<S-Tab>'] = actions.toggle_selection + actions.move_selection_better,
- ['<C-q>'] = actions.send_to_qflist + actions.open_qflist,
- ['<M-q>'] = actions.send_selected_to_qflist + actions.open_qflist,
- ['<C-l>'] = actions.complete_tag,
- ['<C-_>'] = actions.which_key, -- keys from pressing <C-/>
- --["<C-o>"] = function(prompt_bufnr)
- -- local selection = require("telescope.actions.state").get_selected_entry()
- -- local dir = vim.fn.fnamemodify(selection.path, ":p:h")
- -- require("telescope.actions").close(prompt_bufnr)
- -- -- Depending on what you want put `cd`, `lcd`, `tcd`
- -- vim.cmd(string.format("silent lcd %s", dir))
- --end,
+ selection_strategy = "reset",
+ sorting_strategy = "ascending",
+ scroll_strategy = "limit",
+ color_devicons = true,
+ layout_strategy = "horizontal",
+ layout_config = {
+ horizontal = {
+ height = 0.95,
+ preview_cutoff = 70,
+ width = 0.92,
+ preview_width = { 0.55, max = 50 },
},
- n = {
- --["cd"] = function(prompt_bufnr)
- -- local selection = require("telescope.actions.state").get_selected_entry()
- -- local dir = vim.fn.fnamemodify(selection.path, ":p:h")
- -- require("telescope.actions").close(prompt_bufnr)
- -- -- Depending on what you want put `cd`, `lcd`, `tcd`
- -- vim.cmd(string.format("silent lcd %s", dir))
- --end,
- ['<esc>'] = actions.close,
- ['<q>'] = actions.close,
- ['<CR>'] = actions.select_default,
- ['<C-x>'] = actions.select_horizontal,
- ['<C-y>'] = actions.select_vertical,
- ['<C-t>'] = actions.select_tab,
- ['<C-c>'] = actions.delete_buffer,
-
- ['<Tab>'] = actions.toggle_selection + actions.move_selection_worse,
- ['<S-Tab>'] = actions.toggle_selection + actions.move_selection_better,
- ['<C-q>'] = actions.send_to_qflist + actions.open_qflist,
- ['<M-q>'] = actions.send_selected_to_qflist + actions.open_qflist,
-
- ['j'] = actions.move_selection_next,
- ['k'] = actions.move_selection_previous,
- ['H'] = actions.move_to_top,
- ['M'] = actions.move_to_middle,
- ['L'] = actions.move_to_bottom,
-
- ['<Down>'] = actions.move_selection_next,
- ['<Up>'] = actions.move_selection_previous,
- ['gg'] = actions.move_to_top,
- ['G'] = actions.move_to_bottom,
-
- ['<C-u>'] = actions.preview_scrolling_up,
- ['<C-d>'] = actions.preview_scrolling_down,
-
- ['<PageUp>'] = actions.results_scrolling_up,
- ['<PageDown>'] = actions.results_scrolling_down,
- ['cd'] = function(prompt_bufnr)
- local selection = require('telescope.actions.state').get_selected_entry()
- local dir = vim.fn.fnamemodify(selection.path, ':p:h')
- require('telescope.actions').close(prompt_bufnr)
- -- Depending on what you want put `cd`, `lcd`, `tcd`
- vim.cmd(string.format('silent lcd %s', dir))
- end,
- ['?'] = actions.which_key,
- --["<C-o>"] = function(prompt_bufnr)
- -- local selection = require("telescope.actions.state").get_selected_entry()
- -- local dir = vim.fn.fnamemodify(selection.path, ":p:h")
- -- require("telescope.actions").close(prompt_bufnr)
- -- -- Depending on what you want put `cd`, `lcd`, `tcd`
- -- vim.cmd(string.format("silent lcd %s", dir))
- --end,
+ bottom_pane = {
+ height = 12,
+ preview_cutoff = 70,
+ prompt_position = "bottom",
},
},
- },
- preview = {
- filesize_limit = 3,
- timeout = 250,
- },
- selection_strategy = 'reset',
- sorting_strategy = 'ascending',
- scroll_strategy = 'limit',
- color_devicons = true,
- layout_strategy = 'horizontal',
- layout_config = {
- horizontal = {
- height = 0.95,
- preview_cutoff = 70,
- width = 0.92,
- preview_width = { 0.55, max = 50 },
- },
- bottom_pane = {
- height = 12,
- preview_cutoff = 70,
- prompt_position = 'bottom',
+ find_files = {
+ cwd = vim.fn.getcwd(),
+ prompt_prefix = " ",
+ follow = true,
},
- },
- find_files = {
- --cwd = '%:p:h',
- cwd = vim.fn.getcwd(),
- prompt_prefix = ' ',
- --hidden = true,
- --no_ignore = false,
- follow = true,
- },
- --pickers = {
- -- live_grep = {
- -- disable_coordinates = true,
- -- layout_config = {
- -- horizontal = {
- -- preview_width = 0.55,
- -- },
- -- },
- -- },
- --},
- --pickers = {
- -- live_grep = {
- -- mappings = {
- -- i = {
- -- ["<C-f>"] = ts_select_dir_for_grep,
- -- },
- -- n = {
- -- ["<C-f>"] = ts_select_dir_for_grep,
- -- },
- -- },
- -- },
- --},
- --pickers = {
- --lsp_references = {
- -- prompt_prefix='⬅️',
- -- show_line=false,
- -- trim_text=true,
- -- include_declaration=false,
- -- initial_mode = "normal",
- --},
- --lsp_definitions = {
- -- prompt_prefix='➡️',
- -- show_line=false,
- -- trim_text=true,
- -- initial_mode = "normal",
- --},
- --lsp_document_symbols = {
- -- prompt_prefix='* ',
- -- show_line = false,
- --},
- --treesitter = {
- -- prompt_prefix=' ',
- -- show_line = false,
- --},
- --keymaps = { prompt_prefix='? ' },
- --oldfiles = { prompt_prefix=' ' },
- --highlights = { prompt_prefix=' ' },
- --git_files = {
- -- prompt_prefix=' ',
- -- show_untracked = true,
- -- path_display = { "tail" },
- --},
- --buffers = {
- -- prompt_prefix=' ',
- -- ignore_current_buffer = true,
- -- initial_mode = "normal",
- -- sort_mru = true,
- --},
- --live_grep = {
- -- cwd='%:p:h',
- -- disable_coordinates=true,
- -- prompt_title='Search in Folder',
- -- prompt_prefix=' ',
- --},
- --spell_suggest = {
- -- initial_mode = "normal",
- -- prompt_prefix = "暈",
- -- theme = "cursor",
- -- layout_config = { cursor = { width = 0.3 } }
- --},
- --colorscheme = {
- -- enable_preview = true,
- -- prompt_prefix = '',
- -- results_title = '',
- -- layout_strategy = "bottom_pane",
- --},
- --},
-
- extensions = {
- file_browser = {
- theme = 'dropdown',
- -- disables netrw and use telescope-file-browser in its place
- hijack_netrw = false,
- mappings = {
- -- your custom insert mode mappings
- ['i'] = {
- ['<C-w>'] = function()
- vim.cmd('normal vbd')
- end,
- ['<C-h>'] = fb_actions.goto_parent_dir,
- },
- ['n'] = {
- -- your custom normal mode mappings
- ['N'] = fb_actions.create,
- ['<C-h>'] = fb_actions.goto_parent_dir,
- --["/"] = function()
- -- vim.cmd("startinsert")
- --end,
+ extensions = {
+ file_browser = {
+ theme = "dropdown",
+ hijack_netrw = false,
+ mappings = {
+ i = {
+ ["<C-w>"] = function() vim.cmd("normal vbd") end,
+ ["<C-h>"] = function()
+ local fb_actions = get_extension_actions("file_browser")
+ if fb_actions.goto_parent_dir then
+ fb_actions.goto_parent_dir()
+ end
+ end,
+ },
+ n = {
+ ["N"] = function()
+ local fb_actions = get_extension_actions("file_browser")
+ if fb_actions.create then
+ fb_actions.create()
+ end
+ end,
+ ["<C-h>"] = function()
+ local fb_actions = get_extension_actions("file_browser")
+ if fb_actions.goto_parent_dir then
+ fb_actions.goto_parent_dir()
+ end
+ end,
+ },
},
},
},
- },
-})
-
---------------------------------------------------------------------------------
-
--- Load extensions:
--- have to be loaded after telescope setup/config
-require('telescope').load_extension('fzf')
-require('telescope').load_extension('ui-select')
-require('telescope').load_extension('file_browser')
-require('telescope').load_extension('changed_files')
-require('telescope').load_extension('media_files')
-require('telescope').load_extension('notify')
-require('telescope').load_extension('dap')
-require('telescope').load_extension('session-lens')
-require('telescope').load_extension('flutter')
-require('telescope').load_extension('recent_files')
---require('telescope').load_extension('projects')
-
---M.curbuf = function(opts)
--- opts = opts
--- or themes.get_dropdown({
--- previewer = false,
--- shorten_path = false,
--- border = true,
--- })
--- require("telescope.builtin").current_buffer_fuzzy_find(opts)
---end
+ })
-function M.find_configs()
- -- Track dotfiles (bare git repository)
- -- Inside shell config file:
- -- alias config='git --git-dir=$HOME/.cfg --work-tree=$HOME'
- -- cfg_files=$(config ls-tree --name-only -r HEAD)
- -- export CFG_FILES="$cfg_files"
- local tracked_files = {}
-
- for file in string.gmatch(os.getenv('CFG_FILES'), '[^\n]+') do
- table.insert(tracked_files, os.getenv('HOME') .. '/' .. file)
+ -- Load extensions
+ for _, ext in ipairs({
+ "fzf", "ui-select", "file_browser", "changed_files",
+ "media_files", "notify", "dap", "session-lens", "recent_files"
+ }) do
+ pcall(telescope.load_extension, ext)
end
- local history = os.getenv('HOME') .. '/.config/zsh/.zhistory'
- table.insert(tracked_files, history)
+ -- Define the custom command findhere/startup
+ vim.cmd('command! Findhere lua require("plugins.telescope").findhere()')
- require('telescope.builtin').find_files({
- hidden = true,
- no_ignore = false,
- prompt_title = ' Find Configs',
- results_title = 'Config Files',
- path_display = { 'smart' },
- search_dirs = tracked_files,
- layout_strategy = 'horizontal',
- layout_config = { preview_width = 0.65, width = 0.75 },
- })
+ return true
+end
+
+-- Find config files
+local function _sys_path(repo_path)
+ local home = os.getenv("HOME") or vim.fn.expand("~")
+
+ -- Case 1: Files in the OS-specific home folder (e.g., linux/home/.bashrc)
+ if repo_path:find("/home/", 1, true) then
+ local file = repo_path:match(".*/home/(.*)")
+ return home .. "/" .. file
+ -- Case 2: Files in the common folder (e.g., common/README.md)
+ elseif repo_path:find("common/", 1, true) then
+ local file = repo_path:match("common/(.*)")
+ return home .. "/" .. file
+ -- Case 3: Root-level files (e.g., profile/profile_script or README.md)
+ elseif repo_path:find("profile/", 1, true) or repo_path:find("README.md", 1, true) then
+ return home .. "/" .. repo_path
+ -- Case 4: System-level files (e.g., linux/etc/issue)
+ elseif repo_path:find("/etc/", 1, true) then
+ local file = repo_path:match(".*/etc/(.*)")
+ return "/etc/" .. file
+ -- Return nil for paths that don't match any known pattern
+ else
+ return nil
+ end
+end
+
+function M.find_configs()
+ local telescope_builtin = require("telescope.builtin")
+ local tracked_files = {}
+ local home = os.getenv("HOME") or "~"
+ local original_dir = vim.fn.getcwd()
+ vim.fn.chdir(home)
+
+ vim.api.nvim_create_autocmd("VimLeave", {
+ callback = function()
+ vim.fn.chdir(original_dir)
+ end,
+ })
+
+ -- Check if the bare repository exists
+ if vim.fn.isdirectory(home .. "/.cfg") == 1 then
+ -- Repository exists, use git to find tracked files
+ local handle = io.popen("git --git-dir=" .. home .. "/.cfg --work-tree=" .. home .. " ls-tree --name-only -r HEAD")
+ local cfg_files = ""
+ if handle then
+ cfg_files = handle:read("*a") or ""
+ handle:close()
+ end
+
+ -- Process the list of files
+ for file in string.gmatch(cfg_files, "[^\n]+") do
+ file = vim.trim(file)
+ if file ~= "" then
+ local fullpath = _sys_path(file)
+ if fullpath and (vim.fn.filereadable(fullpath) == 1 or vim.fn.isdirectory(fullpath) == 1) then
+ table.insert(tracked_files, fullpath)
+ end
+ end
+ end
+ end
+
+ -- If no files were found (either no repo or no tracked files), use fallback paths
+ if #tracked_files == 0 then
+ local fallback_dirs = {
+ home .. "/.config/nvim",
+ home .. "/.config/zsh",
+ home .. "/.config/tmux",
+ home .. "/.bashrc",
+ home .. "/.zshrc",
+ home .. "/.tmux.conf",
+ }
+ for _, path in ipairs(fallback_dirs) do
+ if vim.fn.filereadable(path) == 1 or vim.fn.isdirectory(path) == 1 then
+ table.insert(tracked_files, path)
+ end
+ end
+ end
+
+ if #tracked_files == 0 then
+ vim.notify("[find_configs] No configuration files found to search.", vim.log.levels.WARN)
+ return
+ end
+
+ -- Launch Telescope
+ telescope_builtin.find_files({
+ hidden = true,
+ no_ignore = false,
+ prompt_title = " Find Configs",
+ results_title = "Config Files",
+ path_display = { "smart" },
+ search_dirs = tracked_files,
+ layout_strategy = "horizontal",
+ layout_config = { preview_width = 0.65, width = 0.75 },
+ previewer = true,
+ })
end
function M.find_scripts()
- require('telescope.builtin').find_files({
+ require("telescope.builtin").find_files({
hidden = true,
no_ignore = true,
- prompt_title = ' Find Scripts',
- path_display = { 'smart' },
+ prompt_title = " Find Scripts",
+ path_display = { "smart" },
search_dirs = {
- '~/.scripts',
+ "~/.scripts",
},
- layout_strategy = 'horizontal',
+ layout_strategy = "horizontal",
layout_config = { preview_width = 0.65, width = 0.75 },
})
end
function M.find_projects()
- local search_dir = '~/projects'
+ local search_dir = "~/projects"
+ local actions = safe_require("telescope.actions")
+ local actions_set = safe_require("telescope.actions.set")
+ local actions_state = safe_require("telescope.actions.state")
+ local finders = safe_require("telescope.finders")
+ local pickers = safe_require("telescope.pickers")
+ local config_mod = safe_require("telescope.config")
+ local config = config_mod and config_mod.values or {}
+
pickers
.new({}, {
- prompt_title = 'Find Projects',
+ prompt_title = "Find Projects",
finder = finders.new_oneshot_job({
- 'find',
+ "find",
vim.fn.expand(search_dir),
- '-type',
- 'd',
- '-maxdepth',
- '1',
+ "-type",
+ "d",
+ "-maxdepth",
+ "1",
}),
- previewer = require('telescope.previewers').vim_buffer_cat.new({}),
+ previewer = require("telescope.previewers").vim_buffer_cat.new({}),
sorter = config.generic_sorter({}),
attach_mappings = function(prompt_bufnr, map)
actions_set.select:replace(function()
@@ -375,9 +387,9 @@ function M.find_projects()
local dir = entry.value
actions.close(prompt_bufnr, false)
vim.fn.chdir(dir)
- vim.cmd('e .')
+ vim.cmd("e .")
vim.cmd("echon ''")
- print('cwd: ' .. vim.fn.getcwd())
+ print("cwd: " .. vim.fn.getcwd())
end
end)
return true
@@ -390,50 +402,64 @@ function M.grep_notes()
local opts = {}
opts.hidden = false
opts.search_dirs = {
- '~/documents/notes/',
+ "~/documents/main/",
}
- opts.prompt_prefix = '  '
- opts.prompt_title = ' Grep Notes'
- opts.path_display = { 'smart' }
- require('telescope.builtin').live_grep(opts)
+ opts.prompt_prefix = " "
+ opts.prompt_title = " Grep Notes"
+ opts.path_display = { "smart" }
+ require("telescope.builtin").live_grep(opts)
end
function M.find_notes()
- require('telescope.builtin').find_files({
+ require("telescope.builtin").find_files({
hidden = true,
no_ignore = false,
- prompt_title = ' Find Notes',
- path_display = { 'smart' },
+ prompt_title = " Find Notes",
+ path_display = { "smart" },
search_dirs = {
- '~/documents/notes/private/',
- '~/documents/notes',
+ "~/documents/main",
},
- layout_strategy = 'horizontal',
+ layout_strategy = "horizontal",
layout_config = { preview_width = 0.65, width = 0.75 },
})
end
function M.find_private()
- require('telescope.builtin').find_files({
+ require("telescope.builtin").find_files({
hidden = true,
no_ignore = false,
- prompt_title = ' Find Notes',
- path_display = { 'smart' },
+ prompt_title = " Find Notes",
+ path_display = { "smart" },
search_dirs = {
- '~/notes/private',
- '~/notes',
+ "~/notes/private",
+ "~/notes",
},
- layout_strategy = 'horizontal',
+ layout_strategy = "horizontal",
layout_config = { preview_width = 0.65, width = 0.75 },
})
end
function M.find_books()
- local search_dir = '~/documents/books'
- vim.fn.jobstart('$HOME/.scripts/track-books.sh')
- local recent_books_directory = vim.fn.stdpath('config') .. '/tmp/'
- local recent_books_file = recent_books_directory .. 'recent_books.txt'
- local search_cmd = 'find ' .. vim.fn.expand(search_dir) .. ' -type d -o -type f -maxdepth 1'
+ local search_dir = "~/documents/books"
+ local actions = safe_require("telescope.actions")
+ local actions_set = safe_require("telescope.actions.set")
+ local actions_state = safe_require("telescope.actions.state")
+ local finders = safe_require("telescope.finders")
+ local pickers = safe_require("telescope.pickers")
+ local config_mod = safe_require("telescope.config")
+ local config = config_mod and config_mod.values or {}
+
+ vim.fn.jobstart("$HOME/.scripts/track-books.sh")
+ local recent_books_directory = vim.fn.stdpath("config") .. "/tmp/"
+ local recent_books_file = recent_books_directory .. "recent_books.txt"
+
+ -- Check if recent_books.txt exists, create it if not
+ if vim.fn.filereadable(recent_books_file) == 0 then
+ vim.fn.mkdir(recent_books_directory, "p") -- Ensure the directory exists
+ vim.fn.writefile({}, recent_books_file) -- Create an empty file
+ end
+
+ local search_cmd = "find " .. vim.fn.expand(search_dir) .. " -type d -o -type f -maxdepth 1"
local recent_books = vim.fn.readfile(recent_books_file)
local search_results = vim.fn.systemlist(search_cmd)
@@ -441,14 +467,14 @@ function M.find_books()
local results = {}
-- Section for Recent Books
- table.insert(results, ' Recent Books')
+ table.insert(results, " Recent Books")
for _, recent_book_path in ipairs(recent_books) do
local formatted_path = vim.fn.fnameescape(recent_book_path)
table.insert(results, formatted_path)
end
-- Section for All Books
- table.insert(results, ' All Books')
+ table.insert(results, " All Books")
local directories = {}
local files = {}
@@ -472,14 +498,14 @@ function M.find_books()
end
local picker = pickers.new({}, {
- prompt_title = 'Find Books',
+ prompt_title = "Find Books",
finder = finders.new_table({
results = results,
}),
file_ignore_patterns = {
- '%.git',
+ "%.git",
},
- previewer = require('telescope.previewers').vim_buffer_cat.new({}),
+ previewer = require("telescope.previewers").vim_buffer_cat.new({}),
sorter = config.generic_sorter({}),
attach_mappings = function(prompt_bufnr, map)
actions_set.select:replace(function()
@@ -490,17 +516,18 @@ function M.find_books()
actions.close(prompt_bufnr, false)
-- Check if it's under "Recent Books"
- if path == ' Recent Books' or path == ' All Books' then
- vim.notify("Cannot select 'All Books'/'Recent Books', please select a book or directory.", vim.log.levels.WARN, { title = 'Find Books' })
+ if path == " Recent Books" or path == " All Books" then
+ vim.notify("Cannot select 'All Books'/'Recent Books', please select a book or directory.",
+ vim.log.levels.WARN, { title = "Find Books" })
else
-- Determine whether it's a directory or a file
local is_directory = vim.fn.isdirectory(path)
if is_directory then
-- It's a directory, navigate to it in the current buffer
- vim.cmd('e ' .. path)
+ vim.cmd("e " .. path)
else
-- It's a file, open it
- vim.cmd('e ' .. path)
+ vim.cmd("e " .. path)
end
end
end
@@ -513,48 +540,43 @@ function M.find_books()
end
function M.grep_current_dir()
- local buffer_dir = require('telescope.utils').buffer_dir()
+ local buffer_dir = require("telescope.utils").buffer_dir()
local opts = {
- prompt_title = 'Live Grep in ' .. buffer_dir,
+ prompt_title = "Live Grep in " .. buffer_dir,
cwd = buffer_dir,
}
- require('telescope.builtin').live_grep(opts)
+ require("telescope.builtin").live_grep(opts)
end
---------------------------------------------------------------------------------
-
-local dropdown = require('telescope.themes').get_dropdown({
- hidden = true,
- no_ignore = true,
- previewer = false,
- prompt_title = '',
- preview_title = '',
- results_title = '',
- layout_config = {
- --anchor = "S",
- prompt_position = 'top',
- },
-})
-
--- File browser always relative to buffer
---local opts_file_browser = vim.tbl_extend('force', dropdown, {
--- path_display = { '%:p:h' },
---})
+-- Helper functions that depend on telescope availability
+local function get_dropdown_theme()
+ return require("telescope.themes").get_dropdown({
+ hidden = true,
+ no_ignore = true,
+ previewer = false,
+ prompt_title = "",
+ preview_title = "",
+ results_title = "",
+ layout_config = {
+ prompt_position = "top",
+ },
+ })
+end
-- Set current folder as prompt title
-local with_title = function(opts, extra)
+local function with_title(opts, extra)
extra = extra or {}
local path = opts.cwd or opts.path or extra.cwd or extra.path or nil
- local title = ''
- local buf_path = vim.fn.expand('%:p:h')
+ local title = ""
+ local buf_path = vim.fn.expand("%:p:h")
local cwd = vim.fn.getcwd()
if path ~= nil and buf_path ~= cwd then
- title = require('plenary.path'):new(buf_path):make_relative(cwd)
+ title = require("plenary.path"):new(buf_path):make_relative(cwd)
else
- title = vim.fn.fnamemodify(cwd, ':t')
+ title = vim.fn.fnamemodify(cwd, ":t")
end
- return vim.tbl_extend('force', opts, {
+ return vim.tbl_extend("force", opts, {
prompt_title = title,
}, extra or {})
end
@@ -562,31 +584,21 @@ end
-- Find here
function M.findhere()
-- Open file browser if argument is a folder
- local arg = vim.api.nvim_eval('argv(0)')
- if arg and (vim.fn.isdirectory(arg) ~= 0 or arg == '') then
+ local arg = vim.api.nvim_eval("argv(0)")
+ if arg and (vim.fn.isdirectory(arg) ~= 0 or arg == "") then
vim.defer_fn(function()
- require('telescope.builtin').find_files(with_title(dropdown))
- -- require'telescope.builtin'.find_files(require('telescope.themes').get_dropdown({
- -- hidden = true,
- -- results_title = '',
- -- layout_config = { prompt_position = 'top' },
- -- }))
+ require("telescope.builtin").find_files(with_title(get_dropdown_theme()))
end, 10)
end
end
--- Define the custom command findhere/startup
-vim.cmd('command! Findhere lua require("plugins.telescope").findhere()')
---vim.cmd('command! Startup lua require("plugins.telescope").findhere()')
---vim.api.nvim_command('autocmd VimEnter * lua require("plugins/telescope").findhere()')
-
-- Find dirs
function M.find_dirs()
- local root_dir = vim.fn.input('Enter the root directory: ')
+ local root_dir = vim.fn.input("Enter the root directory: ")
-- Check if root_dir is empty
- if root_dir == '' then
- print('No directory entered. Aborting.')
+ if root_dir == "" then
+ print("No directory entered. Aborting.")
return
end
@@ -598,14 +610,22 @@ function M.find_dirs()
local subentries = vim.fn.readdir(root_path)
if subentries then
for _, subentry in ipairs(subentries) do
- local absolute_path = root_path .. '/' .. subentry
+ local absolute_path = root_path .. "/" .. subentry
table.insert(entries, subentry)
end
end
+ local actions = safe_require("telescope.actions")
+ local actions_set = safe_require("telescope.actions.set")
+ local actions_state = safe_require("telescope.actions.state")
+ local finders = safe_require("telescope.finders")
+ local pickers = safe_require("telescope.pickers")
+ local config_mod = safe_require("telescope.config")
+ local config = config_mod and config_mod.values or {}
+
pickers
.new({}, {
- prompt_title = 'Change Directory or Open File',
+ prompt_title = "Change Directory or Open File",
finder = finders.new_table({
results = entries,
}),
@@ -617,13 +637,13 @@ function M.find_dirs()
if entry ~= nil then
local selected_entry = entry.value
actions.close(prompt_bufnr, false)
- local selected_path = root_path .. '/' .. selected_entry
+ local selected_path = root_path .. "/" .. selected_entry
if vim.fn.isdirectory(selected_path) == 1 then
vim.fn.chdir(selected_path)
- vim.cmd('e .')
- print('cwd: ' .. vim.fn.getcwd())
+ vim.cmd("e .")
+ print("cwd: " .. vim.fn.getcwd())
else
- vim.cmd('e ' .. selected_path)
+ vim.cmd("e " .. selected_path)
end
end
end)
@@ -633,4 +653,88 @@ function M.find_dirs()
:find()
end
+-- Safe telescope function wrapper for keymaps
+local function safe_telescope_call(module_path, func_name, fallback_msg)
+ return function()
+ local ok, module = pcall(require, module_path)
+ if ok and module[func_name] then
+ module[func_name]()
+ else
+ vim.notify(fallback_msg or ("Telescope plugin not available for " .. func_name), vim.log.levels.WARN)
+ end
+ end
+end
+
+local function safe_telescope_builtin(func_name, fallback_msg)
+ return function(opts)
+ local ok, telescope_builtin = pcall(require, "telescope.builtin")
+ if not ok then
+ vim.notify(fallback_msg or ("Telescope builtin module (telescope.builtin) not found!"), vim.log.levels.ERROR)
+ vim.notify("Error details: " .. tostring(telescope_builtin), vim.log.levels.DEBUG) -- telescope_builtin will contain the error message here
+ return
+ end
+
+ if not telescope_builtin[func_name] then
+ vim.notify(fallback_msg or ("Telescope builtin function '" .. func_name .. "' not found!"), vim.log.levels.ERROR)
+ vim.notify("Available builtin functions: " .. vim.inspect(vim.tbl_keys(telescope_builtin)), vim.log.levels.DEBUG)
+ return
+ end
+
+ -- If both are ok, proceed
+ telescope_builtin[func_name](opts or {})
+ end
+end
+
+-- Safe builtin telescope functions
+local function safe_telescope_builtin(func_name, fallback_msg)
+ return function(opts)
+ local ok, telescope_builtin = pcall(require, "telescope.builtin")
+ if ok and telescope_builtin[func_name] then
+ telescope_builtin[func_name](opts or {})
+ else
+ vim.notify(fallback_msg or ("Telescope builtin not available: " .. func_name), vim.log.levels.WARN)
+ end
+ end
+end
+
+-- Safe extension calls with better checking
+local function safe_telescope_extension(ext_name, func_name, fallback_msg)
+ return function(opts)
+ local telescope_mod = package.loaded.telescope or require("telescope")
+ if not telescope_mod then
+ return
+ end
+
+ -- Check if extension is loaded
+ if not telescope_mod.extensions or not telescope_mod.extensions[ext_name] then
+ vim.notify(fallback_msg or ("Telescope extension '" .. ext_name .. "' not available (plugin may not be installed)"), vim.log.levels.WARN)
+ return
+ end
+
+ local ext_func = telescope_mod.extensions[ext_name][func_name]
+ if not ext_func then
+ vim.notify(fallback_msg or ("Function '" .. func_name .. "' not found in extension '" .. ext_name .. "'"), vim.log.levels.WARN)
+ return
+ end
+
+ ext_func(opts or {})
+ end
+end
+
+-- Fallback-safe `find_files`
+M.safe_find_files = function()
+ local builtin = safe_require("telescope.builtin")
+ if builtin and builtin.find_files then
+ builtin.find_files()
+ else
+ local file = vim.fn.input("Open file: ", "", "file")
+ if file ~= "" then vim.cmd("edit " .. file) end
+ end
+end
+
+-- Export safe wrapper functions for external use
+M.safe_telescope_call = safe_telescope_call
+M.safe_telescope_builtin = safe_telescope_builtin
+M.safe_telescope_extension = safe_telescope_extension
+
return M
diff --git a/common/config/nvim/lua/plugins/toggleterm.lua b/common/config/nvim/lua/plugins/toggleterm.lua
index e67bdec..6b7aad5 100644..100755
--- a/common/config/nvim/lua/plugins/toggleterm.lua
+++ b/common/config/nvim/lua/plugins/toggleterm.lua
@@ -1,8 +1,15 @@
-local status_ok, toggleterm = pcall(require, 'toggleterm')
-if not status_ok then
- return
-end
-toggleterm.setup({
+local M = {}
+
+--- Setup and configure toggleterm.nvim
+-- This function initializes and configures the toggleterm plugin for terminal management
+-- @return boolean True if setup was successful, false otherwise
+function M.setup()
+ local ok, toggleterm = pcall(require, 'toggleterm')
+ if not ok or not toggleterm then
+ return false
+ end
+
+ toggleterm.setup({
--open_mapping = [[<leader>tt]],
autochdir = true,
hide_numbers = true,
@@ -47,9 +54,67 @@ toggleterm.setup({
--background = 'Normal',
},
--winblend = 0,
- },
-})
-local mods = require('user.mods')
+ },
+ })
+
+ -- Set up keymaps for toggleterm
+ local Terminal = require('toggleterm.terminal').Terminal
+
+ -- Custom terminal commands
+ local lazygit
+ if not Terminal then return end
+ local term = Terminal:new({
+ cmd = 'lazygit',
+ dir = 'git_dir',
+ direction = 'float',
+ float_opts = {
+ border = 'curved',
+ },
+ on_open = function(term)
+ vim.cmd('startinsert!')
+ vim.api.nvim_buf_set_keymap(term.bufnr, 'n', 'q', '<cmd>close<CR>', {noremap = true, silent = true})
+ end,
+ })
+ if term then
+ lazygit = term
+ end
+
+ -- Toggle functions
+ local function _lazygit_toggle()
+ if not Terminal then return end
+ if not lazygit then
+ init_lazygit()
+ end
+ if lazygit then
+ pcall(lazygit.toggle, lazygit)
+ end
+ end
+
+ -- Set up keymaps
+ vim.keymap.set('n', '<leader>tt', '<cmd>ToggleTerm<CR>', {noremap = true, silent = true, desc = 'Toggle Terminal'})
+ vim.keymap.set('n', '<leader>tf', '<cmd>ToggleTerm direction=float<CR>', {noremap = true, silent = true, desc = 'Toggle Float Terminal'})
+ vim.keymap.set('n', '<leader>th', '<cmd>ToggleTerm size=10 direction=horizontal<CR>', {noremap = true, silent = true, desc = 'Toggle Horizontal Terminal'})
+ vim.keymap.set('n', '<leader>tv', '<cmd>ToggleTerm size=80 direction=vertical<CR>', {noremap = true, silent = true, desc = 'Toggle Vertical Terminal'})
+ vim.keymap.set('n', '<leader>tl', _lazygit_toggle, {noremap = true, silent = true, desc = 'Toggle Lazygit'})
+
+ -- Terminal mode mappings
+ vim.keymap.set('t', '<esc>', [[<C-\><C-n>]], {noremap = true, silent = true})
+ vim.keymap.set('t', 'jk', [[<C-\><C-n>]], {noremap = true, silent = true})
+ vim.keymap.set('t', '<C-h>', [[<Cmd>wincmd h<CR>]], {noremap = true, silent = true})
+ vim.keymap.set('t', '<C-j>', [[<Cmd>wincmd j<CR>]], {noremap = true, silent = true})
+ vim.keymap.set('t', '<C-k>', [[<Cmd>wincmd k<CR>]], {noremap = true, silent = true})
+ vim.keymap.set('t', '<C-l>', [[<Cmd>wincmd l<CR>]], {noremap = true, silent = true})
+
+ return true
+end
+
+-- Terminal utility functions
+local mods = {}
+
+-- Simple empty check function if mods.empty is not available
+function mods.empty(v)
+ return v == nil or v == ''
+end
local float_handler = function(term)
if not mods.empty(vim.fn.mapcheck('jk', 't')) then
vim.keymap.del('t', 'jk', { buffer = term.bufnr })
@@ -72,54 +137,77 @@ end
-- if you only want these mappings for toggle term use term://*toggleterm#* instead
vim.cmd('autocmd! TermOpen term://* lua set_terminal_keymaps()')
-local Terminal = require('toggleterm.terminal').Terminal
+local Terminal
+local horizontal_term, vertical_term
-local horizontal_term = Terminal:new({ hidden = true, direction = 'horizontal' })
-local vertical_term = Terminal:new({ hidden = true, direction = 'vertical' })
+-- Safely require toggleterm.terminal
+local toggleterm_ok, toggleterm = pcall(require, 'toggleterm.terminal')
+if toggleterm_ok and toggleterm and toggleterm.Terminal then
+ Terminal = toggleterm.Terminal
+ -- Initialize terminals only if Terminal is available
+ if Terminal then
+ local ok1, hterm = pcall(Terminal.new, Terminal, { hidden = true, direction = 'horizontal' })
+ local ok2, vterm = pcall(Terminal.new, Terminal, { hidden = true, direction = 'vertical' })
+ if ok1 then horizontal_term = hterm end
+ if ok2 then vertical_term = vterm end
+ end
+end
function Horizontal_term_toggle()
- horizontal_term:toggle(8, 'horizontal')
+ if horizontal_term then
+ pcall(horizontal_term.toggle, horizontal_term, 8, 'horizontal')
+ end
end
function Vertical_term_toggle()
- horizontal_term:toggle(math.floor(vim.o.columns * 0.5), 'vertical')
+ if vertical_term then
+ pcall(vertical_term.toggle, vertical_term, math.floor(vim.o.columns * 0.5), 'vertical')
+ end
end
-local lazygit = Terminal:new({
- cmd = 'lazygit',
- count = 5,
- id = 1000,
- dir = 'git_dir',
- direction = 'float',
- on_open = float_handler,
- hidden = true,
- float_opts = {
- border = { '╒', '═', '╕', '│', '╛', '═', '╘', '│' },
- width = 150,
- height = 40,
- },
+-- Initialize lazygit terminal instance
+local lazygit = nil
+local Cur_cwd = vim.fn.getcwd()
- ---- Function to run on opening the terminal
- --on_open = function(term)
- -- vim.api.nvim_buf_set_keymap(term.bufnr, 'n', 'q', '<cmd>close<CR>',
- -- {noremap = true, silent = true})
- -- vim.api.nvim_buf_set_keymap(term.bufnr, 'n', '<esc>', '<cmd>close<CR>',
- -- {noremap = true, silent = true})
- -- vim.api.nvim_buf_set_keymap(term.bufnr, 'n', '<C-\\>', '<cmd>close<CR>',
- -- {noremap = true, silent = true})
- --end,
- ---- Function to run on closing the terminal
- --on_close = function(term)
- -- vim.cmd("startinsert!")
- --end
-})
+-- Function to initialize lazygit terminal
+local function init_lazygit()
+ if not Terminal then return nil end
+ if not lazygit then
+ local ok, term = pcall(function()
+ return Terminal:new({
+ cmd = 'lazygit',
+ count = 5,
+ id = 1000,
+ dir = 'git_dir',
+ direction = 'float',
+ on_open = float_handler,
+ hidden = true,
+ float_opts = {
+ border = { '╒', '═', '╕', '│', '╛', '═', '╘', '│' },
+ width = 150,
+ height = 40,
+ },
+ })
+ end)
+ if ok and term then
+ lazygit = term
+ end
+ end
+ return lazygit
+end
+-- Initialize lazygit on first use
function Lazygit_toggle()
+ -- Initialize lazygit if not already done
+ if not init_lazygit() then return end
+
-- cwd is the root of project. if cwd is changed, change the git.
local cwd = vim.fn.getcwd()
if cwd ~= Cur_cwd then
Cur_cwd = cwd
- lazygit:close()
+ if lazygit then
+ lazygit:close()
+ end
lazygit = Terminal:new({
cmd = "zsh --login -c 'lazygit'",
dir = 'git_dir',
@@ -133,31 +221,58 @@ function Lazygit_toggle()
},
})
end
- lazygit:toggle()
+ if lazygit then
+ lazygit:toggle()
+ else
+ vim.notify("Failed to initialize lazygit terminal", vim.log.levels.ERROR)
+ end
end
-local node = Terminal:new({ cmd = 'node', hidden = true })
+local node = nil
+local ncdu = nil
-function _NODE_TOGGLE()
- node:toggle()
+-- Initialize node terminal if Terminal is available
+if Terminal then
+ local ok1, nterm = pcall(function() return Terminal:new({ cmd = 'node', hidden = true }) end)
+ local ok2, ncduterm = pcall(function() return Terminal:new({ cmd = 'ncdu', hidden = true }) end)
+ if ok1 then node = nterm end
+ if ok2 then ncdu = ncduterm end
end
-local ncdu = Terminal:new({ cmd = 'ncdu', hidden = true })
+function _NODE_TOGGLE()
+ if not node then return end
+ pcall(node.toggle, node)
+end
function _NCDU_TOGGLE()
- ncdu:toggle()
+ if not ncdu then return end
+ pcall(ncdu.toggle, ncdu)
end
-local htop = Terminal:new({ cmd = 'htop', hidden = true })
+local htop = nil
function _HTOP_TOGGLE()
- htop:toggle()
+ if not Terminal then return end
+ if not htop then
+ local ok, term = pcall(function() return Terminal:new({ cmd = 'htop', hidden = true }) end)
+ if ok then htop = term end
+ end
+ if htop then
+ pcall(htop.toggle, htop)
+ end
end
-local python = Terminal:new({ cmd = 'python', hidden = true })
+local python = nil
function _PYTHON_TOGGLE()
- python:toggle()
+ if not Terminal then return end
+ if not python then
+ local ok, term = pcall(function() return Terminal:new({ cmd = 'python', hidden = true }) end)
+ if ok then python = term end
+ end
+ if python then
+ pcall(python.toggle, python)
+ end
end
function Gh_dash()
diff --git a/common/config/nvim/lua/plugins/treesitter.lua b/common/config/nvim/lua/plugins/treesitter.lua
index 7f481d3..9df99b8 100644..100755
--- a/common/config/nvim/lua/plugins/treesitter.lua
+++ b/common/config/nvim/lua/plugins/treesitter.lua
@@ -1,31 +1,54 @@
-require'nvim-treesitter.configs'.setup {
- -- A list of parser names, or "all" (the four listed parsers should always be installed)
+local M = {}
- ensure_installed = {
- "c",
- "bash",
- "lua",
- "rust",
- },
- --ensure_installed = "all", -- one of "all" or a list of languages
- --ignore_install = { "" }, -- List of parsers to ignore installing
- sync_install = false,
- auto_install = true,
- highlight = {
- enable = false,
- disable = {},
- },
- indent = {
- enable = true,
- disable = {},
- --disable = { "python", "css" }
- },
- autotag = {
- enable = true,
- },
-}
---vim.opt.foldmethod = "expr"
---vim.opt.foldexpr = "nvim_treesitter#foldexpr()"
+function M.setup()
+ local ok, treesitter = pcall(require, "nvim-treesitter.configs")
+ if not ok or not treesitter then
+ return false
+ end
---local parser_config = require "nvim-treesitter.parsers".get_parser_configs()
---parser_config.tsx.filetype_to_parsername = { "javascript", "typescript.tsx" }
+ -- Add custom parser directory to runtime path
+ vim.opt.runtimepath:append("$HOME/.local/share/treesitter")
+
+ -- Configure treesitter
+ treesitter.setup({
+ -- Install parsers in custom directory
+ parser_install_dir = "$HOME/.local/share/treesitter",
+
+ -- Enable syntax highlighting
+ highlight = {
+ enable = true,
+ -- Disable additional regex-based highlighting to improve performance
+ additional_vim_regex_highlighting = false,
+ },
+
+ -- Enable indentation
+ indent = {
+ enable = true,
+ },
+
+ -- Additional modules to enable
+ incremental_selection = {
+ enable = true,
+ keymaps = {
+ init_selection = "gnn",
+ node_incremental = "grn",
+ scope_incremental = "grc",
+ node_decremental = "grm",
+ },
+ },
+
+ -- Ensure parsers are installed automatically
+ ensure_installed = {
+ "bash", "c", "cpp", "css", "dockerfile", "go", "html",
+ "javascript", "json", "lua", "markdown", "python", "rust",
+ "toml", "typescript", "vim", "yaml"
+ },
+
+ -- Auto-install parsers
+ auto_install = true,
+ })
+
+ return true
+end
+
+return M
diff --git a/common/config/nvim/lua/plugins/trouble.lua b/common/config/nvim/lua/plugins/trouble.lua
index 7d74730..4a07e3b 100644..100755
--- a/common/config/nvim/lua/plugins/trouble.lua
+++ b/common/config/nvim/lua/plugins/trouble.lua
@@ -1,47 +1,73 @@
-require('trouble').setup({
- position = 'bottom', -- position of the list can be: bottom, top, left, right
- height = 10, -- height of the trouble list when position is top or bottom
- width = 50, -- width of the list when position is left or right
- icons = true, -- use devicons for filenames
- mode = 'document_diagnostics', -- "workspace_diagnostics", "document_diagnostics", "quickfix", "lsp_references", "loclist"
- fold_open = '', -- icon used for open folds
- fold_closed = '', -- icon used for closed folds
- group = true, -- group results by file
- padding = true, -- add an extra new line on top of the list
- action_keys = { -- key mappings for actions in the trouble list
- -- map to {} to remove a mapping, for example:
- -- close = {},
- close = 'q', -- close the list
- cancel = '<esc>', -- cancel the preview and get back to your last window / buffer / cursor
- refresh = 'r', -- manually refresh
- jump = { '<cr>', '<tab>' }, -- jump to the diagnostic or open / close folds
- open_split = { '<c-x>' }, -- open buffer in new split
- open_vsplit = { '<c-v>' }, -- open buffer in new vsplit
- open_tab = { '<c-t>' }, -- open buffer in new tab
- jump_close = { 'o' }, -- jump to the diagnostic and close the list
- toggle_mode = 'm', -- toggle between "workspace" and "document" diagnostics mode
- toggle_preview = 'P', -- toggle auto_preview
- hover = 'K', -- opens a small popup with the full multiline message
- preview = 'p', -- preview the diagnostic location
- close_folds = { 'zM', 'zm' }, -- close all folds
- open_folds = { 'zR', 'zr' }, -- open all folds
- toggle_fold = { 'zA', 'za' }, -- toggle fold of current file
- previous = 'k', -- previous item
- next = 'j', -- next item
+local M = {}
+
+--- Setup and configure trouble.nvim
+-- This function initializes and configures the trouble plugin for diagnostics and references
+-- @return boolean True if setup was successful, false otherwise
+function M.setup()
+ local ok, trouble = pcall(require, 'trouble')
+ if not ok then
+ return false
+ end
+
+ trouble.setup({
+ position = "bottom", -- bottom, top, left, right
+ height = 10,
+ width = 50,
+ icons = {
+ indent = {
+ fold = {
+ open = "",
+ closed = "",
+ },
+ },
+ kinds = {
+ -- you can use LSP kind symbols or devicons here
+ -- remove if you want default
+ },
},
- indent_lines = true, -- add an indent guide below the fold icons
- auto_open = false, -- automatically open the list when you have diagnostics
- auto_close = false, -- automatically close the list when you have no diagnostics
- auto_preview = true, -- automatically preview the location of the diagnostic. <esc> to close preview and go back to last window
- auto_fold = false, -- automatically fold a file trouble list at creation
- auto_jump = { 'lsp_definitions' }, -- for the given modes, automatically jump if there is only a single result
+ modes = {
+ diagnostics = {
+ groups = { "filename", "kind" },
+ },
+ symbols = {
+ format = "{kind_icon} {symbol.name} {symbol.kind} [{symbol.scope}]",
+ },
+ },
+ action_keys = {
+ close = "q",
+ cancel = "<esc>",
+ refresh = "r",
+ jump = { "<cr>", "<tab>" },
+ open_split = { "<c-x>" },
+ open_vsplit = { "<c-v>" },
+ open_tab = { "<c-t>" },
+ jump_close = { "o" },
+ toggle_preview = "P",
+ hover = "K",
+ preview = "p",
+ close_folds = { "zM", "zm" },
+ open_folds = { "zR", "zr" },
+ toggle_fold = { "zA", "za" },
+ previous = "k",
+ next = "j",
+ },
+ indent_lines = true,
+ auto_open = false,
+ auto_close = false,
+ auto_preview = true,
+ auto_fold = false,
+ auto_jump = { "lsp_definitions" },
signs = {
- -- icons / text used for a diagnostic
- error = '',
- warning = '▲',
- information = '􀅳',
- hint = '⚑',
- other = '',
+ error = "",
+ warning = "▲",
+ info = "󰋼",
+ hint = "⚑",
+ other = "•",
},
- use_diagnostic_signs = true, -- enabling this will use the signs defined in your lsp client
-})
+ use_diagnostic_signs = true,
+ })
+
+ return true
+end
+
+return M
diff --git a/common/config/nvim/lua/plugins/vimtex.lua b/common/config/nvim/lua/plugins/vimtex.lua
index 732e6ed..732e6ed 100644..100755
--- a/common/config/nvim/lua/plugins/vimtex.lua
+++ b/common/config/nvim/lua/plugins/vimtex.lua
diff --git a/common/config/nvim/lua/plugins/web-devicons.lua b/common/config/nvim/lua/plugins/web-devicons.lua
index 06f2d1c..a565a31 100644..100755
--- a/common/config/nvim/lua/plugins/web-devicons.lua
+++ b/common/config/nvim/lua/plugins/web-devicons.lua
@@ -1,22 +1,125 @@
-local devicons = require('nvim-web-devicons')
-
--- Set devicons overrides early.
-devicons.setup({
- override = {
- js = { icon = '󰌞', color = '#f5c06f', name = 'Js' },
- jsx = { icon = '', color = '#689fb6', name = 'Jsx' },
- ts = { icon = '󰛦', color = '#4377c1', name = 'Ts' },
- tsx = { icon = '', color = '#4377c1', name = 'Tsx' },
- png = { icon = '󰋩', color = '#d4843e', name = 'Png' },
- webp = { icon = '󰋩', color = '#3498db', name = 'Webp' },
- jpg = { icon = '󰋩', color = '#16a085', name = 'Jpg' },
- svg = { icon = '󰋩', color = '#3affdb', name = 'Svg' },
- zsh = {
- icon = '',
- color = '#428850',
- cterm_color = '65',
- name = 'Zsh',
+local M = {}
+
+-- Cache the nerd fonts check with better error handling
+local function get_nerd_fonts_available()
+ if vim.g.nerd_fonts_available ~= nil then
+ return vim.g.nerd_fonts_available
+ end
+
+ local has_nerd_fonts = false
+ local ok, result = pcall(function()
+ if vim.fn.has('unix') == 1 and vim.fn.executable('fc-list') == 1 then
+ local handle = io.popen('fc-list | grep -i nerd 2>/dev/null')
+ if handle then
+ local result = handle:read('*a')
+ handle:close()
+ return result ~= ""
+ end
+ end
+ return false
+ end)
+
+ has_nerd_fonts = ok and result or false
+ vim.g.nerd_fonts_available = has_nerd_fonts
+ return has_nerd_fonts
+end
+
+-- Helper function to get icon with fallback and validation
+local function get_icon(nerd_icon, fallback, color, cterm_color, name)
+ local has_nerd = get_nerd_fonts_available()
+
+ -- Validate colors
+ if not color or color == '' then
+ color = '#6d8086' -- Default gray color
+ end
+ if not cterm_color or cterm_color == '' then
+ cterm_color = '102' -- Default gray for terminal
+ end
+
+ -- Pick icon
+ local icon = has_nerd and nerd_icon or fallback
+ if not icon or icon == '' then
+ icon = has_nerd and '󰈔' or '[F]'
+ end
+
+ return {
+ icon = icon,
+ color = color,
+ cterm_color = cterm_color,
+ name = name or 'File',
+ }
+end
+
+function M.setup()
+ local ok, devicons = pcall(require, 'nvim-web-devicons')
+ if not ok or not devicons then
+ return false
+ end
+
+ devicons.setup({
+ color_icons = true,
+ override = {
+ -- Languages
+ js = get_icon('󰌞', '[JS]', '#f5c06f', '179', 'Js'),
+ jsx = get_icon('', '[JSX]', '#689fb6', '67', 'Jsx'),
+ ts = get_icon('󰛦', '[TS]', '#4377c1', '67', 'Ts'),
+ tsx = get_icon('', '[TSX]', '#4377c1', '67', 'Tsx'),
+ lua = get_icon('', '[LUA]', '#51a0cf', '74', 'Lua'),
+ py = get_icon('', '[PY]', '#3572A5', '67', 'Python'),
+ rb = get_icon('', '[RB]', '#701516', '124', 'Ruby'),
+ go = get_icon('', '[GO]', '#519aba', '74', 'Go'),
+ rs = get_icon('', '[RS]', '#dea584', '173', 'Rust'),
+
+ -- Images
+ png = get_icon('󰋩', '[PNG]', '#d4843e', '173', 'Png'),
+ jpg = get_icon('󰋩', '[JPG]', '#16a085', '36', 'Jpg'),
+ jpeg = get_icon('󰋩', '[JPG]', '#16a085', '36', 'Jpeg'),
+ webp = get_icon('󰋩', '[WEBP]', '#3498db', '32', 'Webp'),
+ svg = get_icon('󰋩', '[SVG]', '#3affdb', '80', 'Svg'),
+
+ -- Archives
+ zip = get_icon('', '[ZIP]', '#e6b422', '178', 'Zip'),
+ rar = get_icon('', '[RAR]', '#e6b422', '178', 'Rar'),
+ ['7z'] = get_icon('', '[7Z]', '#e6b422', '178', '7z'),
+ tar = get_icon('', '[TAR]', '#e6b422', '178', 'Tar'),
+ gz = get_icon('', '[GZ]', '#e6b422', '178', 'GZip'),
+ bz2 = get_icon('', '[BZ2]', '#e6b422', '178', 'BZip2'),
+
+ -- Docs
+ md = get_icon('', '[MD]', '#519aba', '67', 'Markdown'),
+ txt = get_icon('', '[TXT]', '#6d8086', '102', 'Text'),
+ pdf = get_icon('', '[PDF]', '#e74c3c', '160', 'PDF'),
+ doc = get_icon('', '[DOC]', '#2c6ecb', '27', 'Word'),
+ docx = get_icon('', '[DOC]', '#2c6ecb', '27', 'Word'),
+ xls = get_icon('', '[XLS]', '#1d6f42', '29', 'Excel'),
+ xlsx = get_icon('', '[XLS]', '#1d6f42', '29', 'Excel'),
+
+ -- Config
+ json = get_icon('', '[JSON]', '#f5c06f', '179', 'Json'),
+ yaml = get_icon('', '[YAML]', '#6d8086', '102', 'Yaml'),
+ toml = get_icon('', '[TOML]', '#6d8086', '102', 'Toml'),
+ conf = get_icon('', '[CFG]', '#6d8086', '102', 'Config'),
+ ini = get_icon('', '[INI]', '#6d8086', '102', 'Ini'),
+
+ -- Shell
+ sh = get_icon('', '[SH]', '#4d5a5e', '59', 'Shell'),
+ zsh = get_icon('', '[ZSH]', '#89e051', '113', 'Zsh'),
+ bash = get_icon('', '[BASH]', '#89e051', '113', 'Bash'),
+
+ -- Git
+ ['.gitignore'] = get_icon('', '[GIT]', '#e24329', '166', 'GitIgnore'),
+ ['.gitattributes'] = get_icon('', '[GIT]', '#e24329', '166', 'GitAttributes'),
+ ['.gitconfig'] = get_icon('', '[GIT]', '#e24329', '166', 'GitConfig'),
+ },
+ default = {
+ icon = get_nerd_fonts_available() and '󰈔' or '[F]',
+ name = 'File',
+ color = '#6d8086',
+ cterm_color = '102',
},
- },
- color_icons = true,
-})
+ })
+
+ return true
+end
+
+return M
diff --git a/common/config/nvim/lua/plugins/which-key.lua b/common/config/nvim/lua/plugins/which-key.lua
index 10c0c41..10015aa 100644..100755
--- a/common/config/nvim/lua/plugins/which-key.lua
+++ b/common/config/nvim/lua/plugins/which-key.lua
@@ -1,60 +1,53 @@
-require("which-key").setup {
- plugins = {
- marks = true, -- shows a list of your marks on ' and `
- registers = true, -- shows your registers on " in NORMAL or <C-r> in INSERT mode
- spelling = {
- enabled = true, -- enabling this will show WhichKey when pressing z= to select spelling suggestions
- suggestions = 9, -- how many suggestions should be shown in the list?
- },
- -- the presets plugin, adds help for a bunch of default keybindings in Neovim
- -- No actual key bindings are created
- presets = {
- operators = true, -- adds help for operators like d, y, ... and registers them for motion / text object completion
- motions = true, -- adds help for motions
- text_objects = true, -- help for text objects triggered after entering an operator
- windows = true, -- default bindings on <c-w>
- nav = true, -- misc bindings to work with windows
- z = true, -- bindings for folds, spelling and others prefixed with z
- g = true, -- bindings for prefixed with g
+local M = {}
+
+function M.setup()
+ local ok, wk = pcall(require, 'which-key')
+ if not ok then
+ return false
+ end
+
+ -- Basic configuration
+ wk.setup({
+ plugins = {
+ marks = true,
+ registers = true,
+ spelling = { enabled = true, suggestions = 20 },
+ presets = {
+ operators = true,
+ motions = true,
+ text_objects = true,
+ windows = true,
+ nav = true,
+ z = true,
+ g = true,
+ },
},
- },
- -- add operators that will trigger motion and text object completion
- -- to enable all native operators, set the preset / operators plugin above
- operators = { gc = "Comments" },
- key_labels = {
- -- override the label used to display some keys. It doesn't effect WK in any other way.
- -- For example:
- -- ["<space>"] = "SPC",
- -- ["<cr>"] = "RET",
- -- ["<tab>"] = "TAB",
- },
- icons = {
- breadcrumb = "»", -- symbol used in the command line area that shows your active key combo
- separator = "➜", -- symbol used between a key and it's label
- group = "+", -- symbol prepended to a group
- },
- window = {
- border = "none", -- none, single, double, shadow
- position = "bottom", -- bottom, top
- margin = { 0, 0, 0, 0 }, -- extra window margin [top, right, bottom, left]
- padding = { 1, 0, 1, 0 }, -- extra window padding [top, right, bottom, left]
- },
- layout = {
- height = { min = 1, max = 25 }, -- min and max height of the columns
- width = { min = 20, max = 50 }, -- min and max width of the columns
- spacing = 1, -- spacing between columns
- align = "center", -- align columns left, center or right
- },
- ignore_missing = false, -- enable this to hide mappings for which you didn't specify a label
- hidden = { "<silent>", "<cmd>", "<Cmd>", "<CR>", "call", "lua", "^:", "^ " }, -- hide mapping boilerplate
- show_help = true, -- show help message on the command line when the popup is visible
- triggers = "auto", -- automatically setup triggers
- -- triggers = {"<leader>"} -- or specify a list manually
+ --window = {
+ -- border = "none",
+ -- position = "bottom",
+ -- margin = { 1, 0, 1, 0 },
+ -- padding = { 2, 2, 2, 2 },
+ -- winblend = 0
+ --},
+ --layout = {
+ -- height = { min = 4, max = 25 },
+ -- width = { min = 20, max = 50 },
+ -- spacing = 3,
+ -- align = "left"
+ --},
+ --ignore_missing = false,
+ --hidden = { "<silent>", "<cmd>", "<Cmd>", "<CR>", "call", "lua", "^:", "^ " },
+ --show_help = true,
+ --triggers = "<leader>",
+ --triggers_blacklist = {
+ -- i = { "j", "k" },
+ -- v = { "j", "k" },
+ --}
+ })
+
+
+
+ return true
+end
- triggers_blacklist = {
- -- list of mode / prefixes that should never be hooked by WhichKey
- -- this is mostly relevant for key maps that start with a native binding
- -- most people should not need to change this
- n = { "o", "O" },
- },
-}
+return M
diff --git a/common/config/nvim/lua/plugins/zen-mode.lua b/common/config/nvim/lua/plugins/zen-mode.lua
index 7e52854..7e52854 100644..100755
--- a/common/config/nvim/lua/plugins/zen-mode.lua
+++ b/common/config/nvim/lua/plugins/zen-mode.lua