Neovim: WIP on navigation workflow
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
require("core.leader-key")
|
||||
require("core.config")
|
||||
require("core.buffers")
|
||||
require("core.autocommands")
|
||||
require("core.globals")
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
local F = require("core.functions")
|
||||
|
||||
--------------------------------------------
|
||||
--- Commands ---
|
||||
|
||||
@@ -13,10 +15,9 @@ vim.cmd [[
|
||||
--- Autocommands ---
|
||||
|
||||
-- Cut off trailing whitespace and trailing blank lines
|
||||
local core = require("core.functions")
|
||||
vim.api.nvim_create_autocmd({ "BufWritePre" }, {
|
||||
pattern = "*",
|
||||
callback = core.trim_buffer,
|
||||
callback = F.trim_buffer,
|
||||
})
|
||||
|
||||
-- Highlight on yank
|
||||
@@ -29,14 +30,24 @@ vim.api.nvim_create_autocmd("TextYankPost", {
|
||||
})
|
||||
|
||||
-- Show message when autosaving
|
||||
local group = vim.api.nvim_create_augroup('autosave', {})
|
||||
vim.api.nvim_create_autocmd('User', {
|
||||
pattern = 'AutoSaveWritePost',
|
||||
group = group,
|
||||
callback = function(opts)
|
||||
if opts.data.saved_buffer ~= nil then
|
||||
local filename = vim.api.nvim_buf_get_name(opts.data.saved_buffer)
|
||||
vim.notify("Wrote " .. filename, vim.log.levels.INFO)
|
||||
end
|
||||
end,
|
||||
local autosave_group = vim.api.nvim_create_augroup("autosave", {})
|
||||
vim.api.nvim_create_autocmd("User", {
|
||||
pattern = "AutoSaveWritePost",
|
||||
group = autosave_group,
|
||||
callback = function(opts)
|
||||
if opts.data.saved_buffer ~= nil then
|
||||
local filename = vim.api.nvim_buf_get_name(opts.data.saved_buffer)
|
||||
vim.notify("Wrote " .. filename, vim.log.levels.INFO)
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
-- Create an autocommand for full window buffers
|
||||
vim.api.nvim_create_autocmd("BufWinEnter", {
|
||||
-- callback = require("core.buffers").add_buffer
|
||||
callback = function()
|
||||
require("core.buffers").add_buffer()
|
||||
LOG(require("core.buffers").buffers)
|
||||
end,
|
||||
desc = "Track all full window buffers visited",
|
||||
})
|
||||
|
||||
@@ -0,0 +1,213 @@
|
||||
local F = require("core.functions")
|
||||
|
||||
-- Module for managing buffers, these are used for navigation
|
||||
|
||||
local M = {}
|
||||
|
||||
-- Buffer table structure:
|
||||
-- {
|
||||
-- "Group" = { "buffer1", "buffer2", active_index = 1 }
|
||||
-- }
|
||||
M.buffers = {}
|
||||
|
||||
M.buffer_default_group = "Other"
|
||||
|
||||
M.buffer_matcher = {
|
||||
-- match = truthy, function() -> thruthy, or string matching buffer filename
|
||||
-- group = string, function() -> string
|
||||
{ match = F.find_project_root, group = F.find_project_root },
|
||||
{ match = true, group = "Other" }, -- default
|
||||
}
|
||||
|
||||
--------------------------------------------
|
||||
|
||||
local get_buffer_name = function()
|
||||
local buf = vim.api.nvim_get_current_buf()
|
||||
local buffer_name = vim.api.nvim_buf_get_name(buf)
|
||||
if not buffer_name or buffer_name == "" then return nil end
|
||||
return buffer_name
|
||||
end
|
||||
|
||||
M.add_buffer = function()
|
||||
local buffer_name = get_buffer_name()
|
||||
if not buffer_name then return end
|
||||
|
||||
-- Evaluate group
|
||||
local eval_group = function(config_group)
|
||||
if not config_group then return M.buffer_default_group end
|
||||
if type(config_group) == "function" then return config_group() end
|
||||
return config_group
|
||||
end
|
||||
|
||||
-- Add if buffer does not exist yet
|
||||
local add = function(config_group)
|
||||
local group = eval_group(config_group)
|
||||
if not M.buffers[group] then M.buffers[group] = {} end
|
||||
for i, buffer in ipairs(M.buffers[group]) do
|
||||
if buffer == buffer_name then
|
||||
M.buffers[group]["active_index"] = i
|
||||
return group, i
|
||||
end
|
||||
end
|
||||
|
||||
table.insert(M.buffers[group], buffer_name)
|
||||
local count = #M.buffers[group]
|
||||
M.buffers[group]["active_index"] = count
|
||||
|
||||
return group, count
|
||||
end
|
||||
|
||||
-- Walk matcher configuration
|
||||
local matcher = M.buffer_matcher or {}
|
||||
if matcher and type(matcher) == "function" then
|
||||
matcher = matcher()
|
||||
end
|
||||
if #matcher == 0 then add(M.buffer_default_group) end
|
||||
for _, config in ipairs(M.buffer_matcher) do
|
||||
if type(config.match) == "function" and config.match() then
|
||||
return add(config.group)
|
||||
end
|
||||
|
||||
-- Match path's filename
|
||||
if type(config.match) == "string" and config.match == buffer_name:match("([^/]+)$") then
|
||||
return add(config.group)
|
||||
end
|
||||
|
||||
if type(config.match) == "boolean" and config.match then
|
||||
return add(config.group)
|
||||
end
|
||||
end
|
||||
|
||||
return add(M.buffer_default_group)
|
||||
end
|
||||
|
||||
local get_group_from_buffer = function(buffer_name)
|
||||
for group, buffers in pairs(M.buffers) do
|
||||
for i, buffer in ipairs(buffers) do
|
||||
if buffer == buffer_name then return group, i end
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
local buffer_action_in_active_group = function(action, direction)
|
||||
local buffer_name = get_buffer_name()
|
||||
if not buffer_name then return end
|
||||
|
||||
local group, index = get_group_from_buffer(buffer_name)
|
||||
if not group then group, index = M.add_buffer() end
|
||||
|
||||
local buffers = M.buffers[group]
|
||||
if #buffers < 2 then return end
|
||||
|
||||
-- Determine the other index
|
||||
local other_index = index + direction
|
||||
if index == 1 and direction == -1 then
|
||||
other_index = #buffers
|
||||
elseif index == #buffers and direction == 1 then
|
||||
other_index = 1
|
||||
end
|
||||
|
||||
if action == "move" then
|
||||
for _, buffer in ipairs(vim.api.nvim_list_bufs()) do
|
||||
-- Remove inactive buffers
|
||||
if not vim.api.nvim_buf_is_loaded(buffer) then
|
||||
for i, group_buffer in ipairs(buffers) do
|
||||
if buffer == group_buffer then
|
||||
table.remove(buffers, i)
|
||||
if i > 1 and i <= other_index then
|
||||
other_index = other_index - 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
goto continue
|
||||
end
|
||||
|
||||
-- Make buffer active
|
||||
if vim.api.nvim_buf_get_name(buffer) == buffers[other_index] then
|
||||
vim.api.nvim_set_current_buf(buffer)
|
||||
buffers.active_index = other_index
|
||||
break
|
||||
end
|
||||
|
||||
::continue::
|
||||
end
|
||||
elseif action == "swap" then
|
||||
local tmp = buffers[other_index]
|
||||
buffers[other_index] = buffers[index]
|
||||
buffers[index] = tmp
|
||||
end
|
||||
|
||||
M.buffers[group] = buffers
|
||||
end
|
||||
|
||||
M.buffer_move_left = function()
|
||||
buffer_action_in_active_group("move", -1)
|
||||
end
|
||||
|
||||
M.buffer_move_right = function()
|
||||
buffer_action_in_active_group("move", 1)
|
||||
end
|
||||
|
||||
M.buffer_swap_left = function()
|
||||
buffer_action_in_active_group("swap", -1)
|
||||
end
|
||||
|
||||
M.buffer_swap_right = function()
|
||||
buffer_action_in_active_group("swap", 1)
|
||||
end
|
||||
|
||||
--------------------------------------------
|
||||
-- Group move
|
||||
|
||||
local buffer_group_move = function(direction)
|
||||
local buffer_name = get_buffer_name()
|
||||
if not buffer_name then return end
|
||||
|
||||
-- TODO: How to get groups deterministically?
|
||||
|
||||
-- Get active group from the current buffer
|
||||
|
||||
-- Check groups bounds
|
||||
|
||||
-- Change active group
|
||||
end
|
||||
|
||||
M.buffer_group_move_up = function()
|
||||
buffer_group_move(-1)
|
||||
end
|
||||
|
||||
M.buffer_group_move_down = function()
|
||||
buffer_group_move(1)
|
||||
end
|
||||
|
||||
-- TODO: functions that can
|
||||
-- v Navigate buffer left
|
||||
-- v Navigate buffer right
|
||||
-- - Navigate group up (use active_index when swapping)
|
||||
-- - Navigate group down
|
||||
-- v Move buffer left
|
||||
-- v Move buffer right
|
||||
-- - Remove buffer from currently active group (decrease active_index)
|
||||
|
||||
return M
|
||||
|
||||
|
||||
-- (cond
|
||||
-- ((string-equal "*" (substring (buffer-name) 0 1)) "Emacs")
|
||||
-- ((or (memq major-mode '(magit-process-mode
|
||||
-- magit-status-mode
|
||||
-- magit-diff-mode
|
||||
-- magit-log-mode
|
||||
-- magit-file-mode
|
||||
-- magit-blob-mode
|
||||
-- magit-blame-mode))
|
||||
-- (string= (buffer-name) "COMMIT_EDITMSG")) "Magit")
|
||||
-- ((project-current) (dot/project-project-name))
|
||||
-- ((memq major-mode '(org-mode
|
||||
-- emacs-lisp-mode)) "Org Mode")
|
||||
-- ((derived-mode-p 'dired-mode) "Dired")
|
||||
-- ((derived-mode-p 'prog-mode
|
||||
-- 'text-mode) "Editing")
|
||||
-- (t "Other")))))
|
||||
@@ -32,11 +32,14 @@ M.find_project_root = function()
|
||||
|
||||
local directory = current_directory
|
||||
while directory ~= "/" do
|
||||
local git_directory = directory .. "/.git"
|
||||
local project_file = directory .. "/.project"
|
||||
local git_path = vim.loop.fs_stat(directory .. "/.git")
|
||||
if git_path then
|
||||
return directory:gsub("/$", "") -- remove trailing slash
|
||||
end
|
||||
|
||||
if vim.fn.isdirectory(git_directory) == 1 or vim.fn.filereadable(project_file) == 1 then
|
||||
return directory
|
||||
local project_file = vim.loop.fs_stat(directory .. "/.project")
|
||||
if project_file and project_file.type == "file" then
|
||||
return directory:gsub("/$", "") -- remove trailing slash
|
||||
end
|
||||
|
||||
directory = vim.fn.fnamemodify(directory, ":h")
|
||||
|
||||
@@ -66,6 +66,8 @@ return {
|
||||
{ -- https://github.com/neovim/nvim-lspconfig
|
||||
"neovim/nvim-lspconfig",
|
||||
dependencies = {
|
||||
-- Improve the built-in LSP UI
|
||||
"nvimdev/lspsaga.nvim",
|
||||
-- Additional lua configuration, makes Nvim stuff amazing!
|
||||
"folke/neodev.nvim",
|
||||
-- C# "Goto Definition" with decompilation support
|
||||
@@ -73,6 +75,7 @@ return {
|
||||
},
|
||||
config = function()
|
||||
-- Setup neovim Lua configuration
|
||||
require("lspsaga").setup() -- ?? does this do anything with doc hover
|
||||
require("neodev").setup()
|
||||
|
||||
-- Vim process
|
||||
@@ -103,6 +106,39 @@ return {
|
||||
["textDocument/definition"] = require('omnisharp_extended').handler,
|
||||
},
|
||||
},
|
||||
ts_ls = {
|
||||
init_options = {
|
||||
plugins = {
|
||||
{
|
||||
name = '@vue/typescript-plugin',
|
||||
location = '/home/rick/.cache/.bun/install/global/node_modules/@vue/language-server',
|
||||
languages = { 'vue' },
|
||||
},
|
||||
},
|
||||
},
|
||||
filetypes = { 'javascript', 'javascriptreact', 'javascript.jsx', 'typescript', 'typescriptreact', 'typescript.tsx', 'vue', },
|
||||
-- filetypes = { 'typescript', 'javascript', 'javascriptreact', 'typescriptreact', 'vue' },
|
||||
-- requires: bun install -g typescript-language-server
|
||||
-- TODO: Update which-key config, maybe other packages
|
||||
-- Sources:
|
||||
-- https://github.com/vuejs/language-tools?tab=readme-ov-file#hybrid-mode-configuration-requires-vuelanguage-server-version-200
|
||||
-- https://github.com/neovim/nvim-lspconfig/blob/master/lua/lspconfig/configs/ts_ls.lua#L4
|
||||
},
|
||||
volar = {
|
||||
-- init_options = {
|
||||
-- vue = {
|
||||
-- hybridMode = false,
|
||||
-- },
|
||||
-- },
|
||||
},
|
||||
-- volar = {
|
||||
-- -- init_options = {
|
||||
-- -- typescript = {
|
||||
-- -- serverPath = '/home/rick/.cache/.bun/install/global/node_modules/typescript/lib//tsserverlibrary.js'
|
||||
-- -- }
|
||||
-- -- },
|
||||
-- -- filetypes = {'typescript', 'javascript', 'javascriptreact', 'typescriptreact', 'vue', 'json'}
|
||||
-- },
|
||||
}
|
||||
|
||||
-- nvim-cmp supports additional completion capabilities, so broadcast that to servers
|
||||
@@ -114,6 +150,8 @@ return {
|
||||
capabilities = capabilities,
|
||||
on_attach = require("keybinds").lspconfig_on_attach,
|
||||
})
|
||||
-- P(server)
|
||||
-- P(opts)
|
||||
require("lspconfig")[server].setup(opts)
|
||||
end
|
||||
end,
|
||||
|
||||
@@ -297,8 +297,13 @@ M.vc_select_repo = function()
|
||||
end
|
||||
|
||||
M.vc_status = function()
|
||||
-- Open the repository of the current file
|
||||
require("neogit").open({ cwd = "%:p:h" })
|
||||
if F.find_project_root() then
|
||||
-- Open the repository of the current file
|
||||
require("neogit").open({ cwd = "%:p:h" })
|
||||
else
|
||||
-- Pick a project to open
|
||||
M.vc_select_repo()
|
||||
end
|
||||
end
|
||||
|
||||
return M
|
||||
|
||||
@@ -160,6 +160,9 @@ M.lspconfig_on_attach = function(_, bufnr)
|
||||
nnoremap("<leader>lf", F.lsp_format_buffer, "Format buffer")
|
||||
nnoremap("<leader>lr", vim.lsp.buf.rename, "Rename")
|
||||
|
||||
nnoremap("<leader>ld", "<cmd>Lspsaga hover_doc<CR>", "Show documentation")
|
||||
-- vim.keymap.set("n", "<leader>ld", "<cmd>Lspsaga hover_doc<CR>", { desc = "Show documentation" })
|
||||
|
||||
F.wk("<leader>lg", "goto", bufnr)
|
||||
nnoremap("<leader>lga", builtin.lsp_dynamic_workspace_symbols, "Workspace symbols")
|
||||
nnoremap("<leader>lgd", vim.lsp.buf.declaration, "Declaration")
|
||||
|
||||
+18
-11
@@ -64,8 +64,21 @@ return {
|
||||
globalstatus = true,
|
||||
},
|
||||
sections = {
|
||||
lualine_b = { "branch" },
|
||||
lualine_x = { "diagnostics", "encoding", "fileformat", "filetype" },
|
||||
lualine_a = { "mode" },
|
||||
lualine_b = { "encoding", "filename" },
|
||||
lualine_c = {
|
||||
{
|
||||
-- TODO: nvim alternate file stuff and closing files is busted
|
||||
"project",
|
||||
fmt = function()
|
||||
local path = require("core.functions").find_project_root() or ""
|
||||
return path:match("([^/]+)$")
|
||||
end,
|
||||
},
|
||||
},
|
||||
lualine_x = { "diagnostics", "fileformat" },
|
||||
lualine_y = { "filetype" },
|
||||
lualine_z = { "progress", "location" },
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -80,14 +93,6 @@ return {
|
||||
opts = {
|
||||
config = {
|
||||
header = {
|
||||
-- " ",
|
||||
-- " ███╗ ██╗███████╗ ██████╗ ██╗ ██╗██╗███╗ ███╗ ",
|
||||
-- " ████╗ ██║██╔════╝██╔═══██╗██║ ██║██║████╗ ████║ ",
|
||||
-- " ██╔██╗ ██║█████╗ ██║ ██║██║ ██║██║██╔████╔██║ ",
|
||||
-- " ██║╚██╗██║██╔══╝ ██║ ██║╚██╗ ██╔╝██║██║╚██╔╝██║ ",
|
||||
-- " ██║ ╚████║███████╗╚██████╔╝ ╚████╔╝ ██║██║ ╚═╝ ██║ ",
|
||||
-- " ╚═╝ ╚═══╝╚══════╝ ╚═════╝ ╚═══╝ ╚═╝╚═╝ ╚═╝ ",
|
||||
-- "____________________________________________________",
|
||||
" . . ",
|
||||
" ';;,. ::' ",
|
||||
" ,:::;,, :ccc, ",
|
||||
@@ -101,7 +106,9 @@ return {
|
||||
" .;ooo: ;cclooo:. ",
|
||||
" .;oc 'coo;. ",
|
||||
" .' .,. ",
|
||||
"____________________________________________________",
|
||||
"",
|
||||
" _______________________________________________________",
|
||||
"",
|
||||
"",
|
||||
},
|
||||
shortcut = {
|
||||
|
||||
Reference in New Issue
Block a user