mirror of
https://github.com/hyzendust/KickestEnd.nvim.git
synced 2026-02-15 03:41:14 +01:00
added modularity: separated files for keymaps, telescope. added undotree plugin. small features like relative line numbers.
This commit is contained in:
527
init.lua
527
init.lua
@@ -86,6 +86,10 @@ require('lazy').setup({
|
|||||||
lsp_format = 'fallback',
|
lsp_format = 'fallback',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
-- format without saving
|
||||||
|
vim.keymap.set('n', '<leader>f', function()
|
||||||
|
require('conform').format { async = true }
|
||||||
|
end, { desc = 'Format buffer' }),
|
||||||
},
|
},
|
||||||
|
|
||||||
-- Install formatters automatically
|
-- Install formatters automatically
|
||||||
@@ -125,7 +129,7 @@ require('lazy').setup({
|
|||||||
},
|
},
|
||||||
|
|
||||||
-- Useful plugin to show you pending keybinds.
|
-- Useful plugin to show you pending keybinds.
|
||||||
{ 'folke/which-key.nvim', opts = {} },
|
{ 'folke/which-key.nvim', opts = {} },
|
||||||
{
|
{
|
||||||
-- Adds git related signs to the gutter, as well as utilities for managing changes
|
-- Adds git related signs to the gutter, as well as utilities for managing changes
|
||||||
'lewis6991/gitsigns.nvim',
|
'lewis6991/gitsigns.nvim',
|
||||||
@@ -227,31 +231,8 @@ require('lazy').setup({
|
|||||||
main = 'ibl',
|
main = 'ibl',
|
||||||
opts = {},
|
opts = {},
|
||||||
},
|
},
|
||||||
|
|
||||||
-- "gc" to comment visual regions/lines
|
-- "gc" to comment visual regions/lines
|
||||||
{ 'numToStr/Comment.nvim', opts = {} },
|
{ 'numToStr/Comment.nvim', opts = {} },
|
||||||
|
|
||||||
-- Fuzzy Finder (files, lsp, etc)
|
|
||||||
{
|
|
||||||
'nvim-telescope/telescope.nvim',
|
|
||||||
branch = '0.1.x',
|
|
||||||
dependencies = {
|
|
||||||
'nvim-lua/plenary.nvim',
|
|
||||||
-- Fuzzy Finder Algorithm which requires local dependencies to be built.
|
|
||||||
-- Only load if `make` is available. Make sure you have the system
|
|
||||||
-- requirements installed.
|
|
||||||
{
|
|
||||||
'nvim-telescope/telescope-fzf-native.nvim',
|
|
||||||
-- NOTE: If you are having trouble with this installation,
|
|
||||||
-- refer to the README for telescope-fzf-native for more instructions.
|
|
||||||
build = 'make',
|
|
||||||
cond = function()
|
|
||||||
return vim.fn.executable 'make' == 1
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
{
|
||||||
-- Highlight, edit, and navigate code
|
-- Highlight, edit, and navigate code
|
||||||
'nvim-treesitter/nvim-treesitter',
|
'nvim-treesitter/nvim-treesitter',
|
||||||
@@ -282,21 +263,28 @@ require('lazy').setup({
|
|||||||
{ import = 'custom.plugins' },
|
{ import = 'custom.plugins' },
|
||||||
}, {})
|
}, {})
|
||||||
|
|
||||||
|
-- custom/keymaps.lua file
|
||||||
|
require 'keymaps'
|
||||||
|
|
||||||
-- [[ Setting options ]]
|
-- [[ Setting options ]]
|
||||||
-- See `:help vim.o`
|
-- See `:help vim.o`
|
||||||
-- NOTE: You can change these options as you wish!
|
|
||||||
|
|
||||||
-- Set highlight on search
|
-- Set highlight on search
|
||||||
vim.o.hlsearch = false
|
vim.o.hlsearch = false
|
||||||
|
|
||||||
-- Make line numbers default
|
-- Make line numbers default
|
||||||
vim.wo.number = true
|
vim.opt.number = true
|
||||||
|
|
||||||
|
-- Relative line number
|
||||||
|
vim.opt.relativenumber = true
|
||||||
|
|
||||||
-- Enable mouse mode
|
-- Enable mouse mode
|
||||||
vim.o.mouse = ''
|
vim.o.mouse = ''
|
||||||
|
|
||||||
|
-- Always keep a distance of the cursor to the top and bottom of the screen
|
||||||
|
vim.opt.scrolloff = 8
|
||||||
|
|
||||||
-- Sync clipboard between OS and Neovim.
|
-- Sync clipboard between OS and Neovim.
|
||||||
-- Remove this option if you want your OS clipboard to remain independent.
|
|
||||||
-- See `:help 'clipboard'`
|
-- See `:help 'clipboard'`
|
||||||
-- vim.o.clipboard = 'unnamedplus'
|
-- vim.o.clipboard = 'unnamedplus'
|
||||||
|
|
||||||
@@ -324,246 +312,12 @@ vim.o.completeopt = 'menuone,noselect'
|
|||||||
vim.o.termguicolors = true
|
vim.o.termguicolors = true
|
||||||
|
|
||||||
-- Tabs and indentation
|
-- Tabs and indentation
|
||||||
vim.o.expandtab = false -- use spaces instead of tabs
|
vim.o.expandtab = false -- use spaces instead of tabs
|
||||||
vim.o.shiftwidth = 4 -- number of spaces for autoindent
|
vim.o.shiftwidth = 4 -- number of spaces for autoindent
|
||||||
vim.o.softtabstop = 0 -- number of spaces per Tab in insert mode
|
vim.o.softtabstop = 0 -- number of spaces per Tab in insert mode
|
||||||
vim.o.tabstop = 4 -- number of spaces a Tab counts for
|
vim.o.tabstop = 4 -- number of spaces a Tab counts for
|
||||||
vim.o.smartindent = true -- auto-indent new lines
|
vim.o.smartindent = true -- auto-indent new lines
|
||||||
|
|
||||||
-- [[ Basic Keymaps ]]
|
|
||||||
|
|
||||||
-- Keymaps for better default experience
|
|
||||||
-- See `:help vim.keymap.set()`
|
|
||||||
vim.keymap.set({ 'n', 'v' }, '<Space>', '<Nop>', { silent = true })
|
|
||||||
|
|
||||||
-- Remap for dealing with word wrap
|
|
||||||
vim.keymap.set('n', 'k', "v:count == 0 ? 'gk' : 'k'", { expr = true, silent = true })
|
|
||||||
vim.keymap.set('n', 'j', "v:count == 0 ? 'gj' : 'j'", { expr = true, silent = true })
|
|
||||||
|
|
||||||
-- Diagnostic keymaps
|
|
||||||
vim.keymap.set('n', '[d', vim.diagnostic.goto_prev, { desc = 'Go to previous diagnostic message' })
|
|
||||||
vim.keymap.set('n', ']d', vim.diagnostic.goto_next, { desc = 'Go to next diagnostic message' })
|
|
||||||
vim.keymap.set('n', '<leader>de', vim.diagnostic.open_float, { desc = 'Diagnostics: floating message' })
|
|
||||||
vim.keymap.set('n', '<leader>dq', vim.diagnostic.setloclist, { desc = 'Diagnostics: location list' })
|
|
||||||
|
|
||||||
-- [[ Custom keymaps ]]
|
|
||||||
|
|
||||||
-- Neo-tree sync to current directory & toggle
|
|
||||||
vim.keymap.set('n', '<leader>n', '<Cmd>cd %:p:h | Neotree toggle float<CR>')
|
|
||||||
|
|
||||||
-- Terminal open in new tab
|
|
||||||
vim.keymap.set('n', '<leader>t', '<Cmd>tabnew +term<CR>i')
|
|
||||||
|
|
||||||
-- Create an empty buffer in a new tab
|
|
||||||
vim.keymap.set('n', '<Leader>e', function()
|
|
||||||
vim.cmd 'tabnew' -- create a new tab
|
|
||||||
vim.cmd 'enew' -- create a new empty buffer in it
|
|
||||||
end, { noremap = true, silent = true })
|
|
||||||
|
|
||||||
-- Horizontal split with new empty buffer below
|
|
||||||
vim.keymap.set('n', '<leader>sv', function()
|
|
||||||
vim.cmd 'split' -- create horizontal split (above by default)
|
|
||||||
vim.cmd 'wincmd j' -- move to the new split below
|
|
||||||
vim.cmd 'enew' -- open new empty buffer
|
|
||||||
end, { desc = 'New buffer in horizontal split (below)' })
|
|
||||||
|
|
||||||
-- Vertical split with new empty buffer to the right
|
|
||||||
vim.keymap.set('n', '<leader>sh', function()
|
|
||||||
vim.cmd 'vsplit' -- create vertical split (left by default)
|
|
||||||
vim.cmd 'wincmd l' -- move to the new split to the right
|
|
||||||
vim.cmd 'enew' -- open new empty buffer
|
|
||||||
end, { desc = 'New buffer in vertical split (right)' })
|
|
||||||
|
|
||||||
-- Save current buffer (asks for filename if new/unsaved)
|
|
||||||
vim.keymap.set('n', '<leader>w', function()
|
|
||||||
if vim.api.nvim_buf_get_name(0) == '' then
|
|
||||||
-- Ask user for a filename
|
|
||||||
local filename = vim.fn.input('Save as: ', '', 'file')
|
|
||||||
if filename ~= '' then
|
|
||||||
vim.cmd('saveas ' .. vim.fn.fnameescape(filename))
|
|
||||||
else
|
|
||||||
print 'Save cancelled'
|
|
||||||
end
|
|
||||||
else
|
|
||||||
vim.cmd 'w'
|
|
||||||
end
|
|
||||||
end, { desc = 'Save buffer (prompt if new file)' })
|
|
||||||
|
|
||||||
-- Close current window (asks if buffer is unsaved)
|
|
||||||
vim.keymap.set('n', '<leader>q', function()
|
|
||||||
if vim.bo.modified then
|
|
||||||
local choice = vim.fn.input 'Buffer modified! Save (y), Discard (n), Cancel (any other key)? '
|
|
||||||
if choice:lower() == 'y' then
|
|
||||||
if vim.api.nvim_buf_get_name(0) == '' then
|
|
||||||
local filename = vim.fn.input('Save as: ', '', 'file')
|
|
||||||
if filename ~= '' then
|
|
||||||
vim.cmd('saveas ' .. vim.fn.fnameescape(filename))
|
|
||||||
vim.cmd 'q'
|
|
||||||
else
|
|
||||||
print 'Save cancelled'
|
|
||||||
end
|
|
||||||
else
|
|
||||||
vim.cmd 'wq'
|
|
||||||
end
|
|
||||||
elseif choice:lower() == 'n' then
|
|
||||||
vim.cmd 'q!'
|
|
||||||
else
|
|
||||||
print 'Quit cancelled'
|
|
||||||
end
|
|
||||||
else
|
|
||||||
vim.cmd 'q'
|
|
||||||
end
|
|
||||||
end, { desc = 'Close buffer (prompt if modified)' })
|
|
||||||
|
|
||||||
-- Save changes and close current window (asks for filename if new/unsaved)
|
|
||||||
vim.keymap.set('n', '<leader>qy', function()
|
|
||||||
if vim.api.nvim_buf_get_name(0) == '' then
|
|
||||||
-- Ask user for a filename
|
|
||||||
local filename = vim.fn.input('Save as: ', '', 'file')
|
|
||||||
if filename ~= '' then
|
|
||||||
vim.cmd('saveas ' .. vim.fn.fnameescape(filename))
|
|
||||||
vim.cmd 'q'
|
|
||||||
else
|
|
||||||
print 'Save cancelled'
|
|
||||||
end
|
|
||||||
else
|
|
||||||
vim.cmd 'wq'
|
|
||||||
end
|
|
||||||
end, { desc = 'Save & quit (prompt if new file)' })
|
|
||||||
|
|
||||||
-- Discard changes and Close current window
|
|
||||||
vim.keymap.set('n', '<leader>qn', '<Cmd>q!<CR>')
|
|
||||||
|
|
||||||
-- Switch below/right split windows
|
|
||||||
vim.keymap.set('n', '<leader><Tab>', '<C-W><C-W>')
|
|
||||||
|
|
||||||
-- Switch above/left split windows
|
|
||||||
vim.keymap.set('n', '<Tab>', '<C-W>W')
|
|
||||||
|
|
||||||
-- Select all
|
|
||||||
vim.keymap.set('n', '<leader>ll', 'ggVG')
|
|
||||||
|
|
||||||
-- Select all and copy to clipboard
|
|
||||||
vim.keymap.set('n', '<leader>lY', 'ggVG"+y')
|
|
||||||
|
|
||||||
-- Copy to clipboard a single line
|
|
||||||
vim.keymap.set('n', 'Y', '"+yy')
|
|
||||||
|
|
||||||
-- Copy to clipboard selected text in Visual mode
|
|
||||||
vim.keymap.set('v', 'Y', '"+y')
|
|
||||||
|
|
||||||
-- Paste from clipboard
|
|
||||||
vim.keymap.set('n', '<leader>p', '"+p')
|
|
||||||
|
|
||||||
-- Redo
|
|
||||||
vim.keymap.set('n', 'U', '<C-r>')
|
|
||||||
|
|
||||||
-- Smart Open current buffers for Telescope (switch to already open buffer)
|
|
||||||
local actions = require 'telescope.actions'
|
|
||||||
local action_state = require 'telescope.actions.state'
|
|
||||||
local builtin = require 'telescope.builtin'
|
|
||||||
|
|
||||||
local function smart_open_buffer()
|
|
||||||
builtin.buffers {
|
|
||||||
attach_mappings = function(_, map)
|
|
||||||
local function open_selected(prompt_bufnr)
|
|
||||||
local entry = action_state.get_selected_entry()
|
|
||||||
if not entry then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
actions.close(prompt_bufnr)
|
|
||||||
|
|
||||||
local bufname = vim.api.nvim_buf_get_name(entry.bufnr)
|
|
||||||
if bufname == '' then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Check all windows in current tab
|
|
||||||
local current_tab = vim.api.nvim_get_current_tabpage()
|
|
||||||
for _, win in ipairs(vim.api.nvim_tabpage_list_wins(current_tab)) do
|
|
||||||
local buf = vim.api.nvim_win_get_buf(win)
|
|
||||||
if vim.api.nvim_buf_get_name(buf) == bufname then
|
|
||||||
vim.api.nvim_set_current_win(win)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Check other tabs
|
|
||||||
for _, tab in ipairs(vim.api.nvim_list_tabpages()) do
|
|
||||||
if tab ~= current_tab then
|
|
||||||
for _, win in ipairs(vim.api.nvim_tabpage_list_wins(tab)) do
|
|
||||||
local buf = vim.api.nvim_win_get_buf(win)
|
|
||||||
if vim.api.nvim_buf_get_name(buf) == bufname then
|
|
||||||
-- Switch tab first, then window
|
|
||||||
vim.api.nvim_set_current_tabpage(tab)
|
|
||||||
vim.api.nvim_set_current_win(win)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Not open anywhere → open in current window
|
|
||||||
vim.cmd('buffer ' .. entry.bufnr)
|
|
||||||
end
|
|
||||||
|
|
||||||
map('i', '<CR>', open_selected)
|
|
||||||
map('n', '<CR>', open_selected)
|
|
||||||
return true
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Map to <leader><leader>
|
|
||||||
vim.keymap.set('n', '<leader><leader>', smart_open_buffer, { desc = 'Switch to Open Buffers' })
|
|
||||||
|
|
||||||
-- which-key, register it to show a description
|
|
||||||
require('which-key').register {
|
|
||||||
['<leader><leader>'] = { smart_open_buffer, 'Switch to Open Buffers' },
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Smart open a file path, reusing empty buffers or tabs if possible
|
|
||||||
local function smart_open_file(path)
|
|
||||||
if not path or path == '' then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
path = vim.fn.fnamemodify(path, ':p') -- make absolute
|
|
||||||
|
|
||||||
-- 1. If file is already open → jump to it
|
|
||||||
for _, tab in ipairs(vim.api.nvim_list_tabpages()) do
|
|
||||||
for _, win in ipairs(vim.api.nvim_tabpage_list_wins(tab)) do
|
|
||||||
local buf = vim.api.nvim_win_get_buf(win)
|
|
||||||
if vim.api.nvim_buf_get_name(buf) == path then
|
|
||||||
vim.api.nvim_set_current_tabpage(tab)
|
|
||||||
vim.api.nvim_set_current_win(win)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- 2. If current tab has an empty "No Name" buffer → reuse it
|
|
||||||
for _, win in ipairs(vim.api.nvim_tabpage_list_wins(0)) do
|
|
||||||
local buf = vim.api.nvim_win_get_buf(win)
|
|
||||||
local name = vim.api.nvim_buf_get_name(buf)
|
|
||||||
local buftype = vim.api.nvim_buf_get_option(buf, 'buftype')
|
|
||||||
local modified = vim.api.nvim_buf_get_option(buf, 'modified')
|
|
||||||
if name == '' and buftype == '' and not modified then
|
|
||||||
vim.api.nvim_set_current_win(win)
|
|
||||||
vim.cmd('edit ' .. vim.fn.fnameescape(path))
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- 3. Otherwise → open in a new tab
|
|
||||||
vim.cmd('tabedit ' .. vim.fn.fnameescape(path))
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Remap gf to use smart_open_file
|
|
||||||
vim.keymap.set('n', 'gf', function()
|
|
||||||
local path = vim.fn.expand '<cfile>' -- get file under cursor
|
|
||||||
smart_open_file(path)
|
|
||||||
end, { desc = 'Smart gf: open file under cursor in new tab or reuse buffer' })
|
|
||||||
|
|
||||||
-- [[ Highlight on yank ]]
|
-- [[ Highlight on yank ]]
|
||||||
-- See `:help vim.highlight.on_yank()`
|
-- See `:help vim.highlight.on_yank()`
|
||||||
local highlight_group = vim.api.nvim_create_augroup('YankHighlight', { clear = true })
|
local highlight_group = vim.api.nvim_create_augroup('YankHighlight', { clear = true })
|
||||||
@@ -575,240 +329,6 @@ vim.api.nvim_create_autocmd('TextYankPost', {
|
|||||||
pattern = '*',
|
pattern = '*',
|
||||||
})
|
})
|
||||||
|
|
||||||
-- [[ Configure Telescope ]]
|
|
||||||
-- See `:help telescope` and `:help telescope.setup()`
|
|
||||||
require('telescope').setup {
|
|
||||||
defaults = {
|
|
||||||
mappings = {
|
|
||||||
i = {
|
|
||||||
['<C-u>'] = false,
|
|
||||||
['<C-d>'] = false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Enable telescope fzf native, if installed
|
|
||||||
pcall(require('telescope').load_extension, 'fzf')
|
|
||||||
|
|
||||||
-- smart_open function for Telescope to check if the current tab has an empty "No Name" buffer. If it has, it replaces the empty buffer and open a file in the same tab
|
|
||||||
local actions = require 'telescope.actions'
|
|
||||||
local action_state = require 'telescope.actions.state'
|
|
||||||
|
|
||||||
local function smart_open(prompt_bufnr)
|
|
||||||
local entry = action_state.get_selected_entry()
|
|
||||||
if not entry then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local path = entry.path or entry.filename
|
|
||||||
if not path then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if prompt_bufnr and vim.api.nvim_buf_is_valid(prompt_bufnr) then
|
|
||||||
pcall(actions.close, prompt_bufnr)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- 1. If file is already open → jump to it
|
|
||||||
local tabpages = vim.api.nvim_list_tabpages()
|
|
||||||
for _, tab in ipairs(tabpages) do
|
|
||||||
for _, win in ipairs(vim.api.nvim_tabpage_list_wins(tab)) do
|
|
||||||
local buf = vim.api.nvim_win_get_buf(win)
|
|
||||||
if vim.api.nvim_buf_get_name(buf) == path then
|
|
||||||
vim.api.nvim_set_current_tabpage(tab) -- jump to tab
|
|
||||||
vim.api.nvim_set_current_win(win) -- jump to window
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- 2. If current tab has an empty "No Name" buffer → reuse it
|
|
||||||
local wins = vim.api.nvim_tabpage_list_wins(0)
|
|
||||||
for _, win in ipairs(wins) do
|
|
||||||
local buf = vim.api.nvim_win_get_buf(win)
|
|
||||||
local name = vim.api.nvim_buf_get_name(buf)
|
|
||||||
local buftype = vim.api.nvim_buf_get_option(buf, 'buftype')
|
|
||||||
local modified = vim.api.nvim_buf_get_option(buf, 'modified')
|
|
||||||
if name == '' and buftype == '' and not modified then
|
|
||||||
vim.api.nvim_set_current_win(win)
|
|
||||||
vim.cmd('edit ' .. vim.fn.fnameescape(path))
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- 3. Otherwise → open in a new tab
|
|
||||||
vim.cmd('tabnew ' .. vim.fn.fnameescape(path))
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Split option in Telescope file picker with smart_open
|
|
||||||
local actions = require 'telescope.actions'
|
|
||||||
local action_state = require 'telescope.actions.state'
|
|
||||||
|
|
||||||
local function smart_open_split(prompt_bufnr, split_type)
|
|
||||||
local entry = action_state.get_selected_entry()
|
|
||||||
if not entry then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local path = entry.path or entry.filename
|
|
||||||
if not path then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if prompt_bufnr and vim.api.nvim_buf_is_valid(prompt_bufnr) then
|
|
||||||
pcall(actions.close, prompt_bufnr)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Check if file is already open
|
|
||||||
local open_tab, open_win
|
|
||||||
for _, tab in ipairs(vim.api.nvim_list_tabpages()) do
|
|
||||||
for _, win in ipairs(vim.api.nvim_tabpage_list_wins(tab)) do
|
|
||||||
local buf = vim.api.nvim_win_get_buf(win)
|
|
||||||
if vim.api.nvim_buf_get_name(buf) == path then
|
|
||||||
open_tab = tab
|
|
||||||
open_win = win
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if open_tab then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if open_tab then
|
|
||||||
local choice = vim.fn.confirm('File is already open in a tab. Open split here anyway?', '&Yes\n&No', 2)
|
|
||||||
if choice ~= 1 then
|
|
||||||
-- User chose No → jump to the tab where file is open
|
|
||||||
vim.api.nvim_set_current_tabpage(open_tab)
|
|
||||||
vim.api.nvim_set_current_win(open_win)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
-- Else user chose Yes → continue to open split in current tab
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Open in split
|
|
||||||
if split_type == 'v' then
|
|
||||||
-- horizontal → always below
|
|
||||||
vim.cmd('belowright split ' .. vim.fn.fnameescape(path))
|
|
||||||
elseif split_type == 'h' then
|
|
||||||
-- vertical → always right
|
|
||||||
vim.cmd('vertical rightbelow split ' .. vim.fn.fnameescape(path))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Telescope keymap using Smart Open
|
|
||||||
vim.keymap.set('n', '<leader>sf', function()
|
|
||||||
require('telescope.builtin').find_files {
|
|
||||||
attach_mappings = function(_, map)
|
|
||||||
map('i', '<CR>', function(prompt_bufnr)
|
|
||||||
smart_open(prompt_bufnr)
|
|
||||||
end)
|
|
||||||
map('n', '<CR>', function(prompt_bufnr)
|
|
||||||
smart_open(prompt_bufnr)
|
|
||||||
end)
|
|
||||||
-- Horizontal split with 'h'
|
|
||||||
map('n', 'h', function(prompt_bufnr)
|
|
||||||
smart_open_split(prompt_bufnr, 'h')
|
|
||||||
end)
|
|
||||||
-- Vertical split with 'v'
|
|
||||||
map('n', 'v', function(prompt_bufnr)
|
|
||||||
smart_open_split(prompt_bufnr, 'v')
|
|
||||||
end)
|
|
||||||
return true
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
end, { desc = '[S]earch [F]iles (Smart Open)' })
|
|
||||||
|
|
||||||
-- Telescope live_grep in git root
|
|
||||||
-- Function to find the git root directory based on the current buffer's path
|
|
||||||
local function find_git_root()
|
|
||||||
-- Use the current buffer's path as the starting point for the git search
|
|
||||||
local current_file = vim.api.nvim_buf_get_name(0)
|
|
||||||
local current_dir
|
|
||||||
local cwd = vim.fn.getcwd()
|
|
||||||
-- If the buffer is not associated with a file, return nil
|
|
||||||
if current_file == '' then
|
|
||||||
current_dir = cwd
|
|
||||||
else
|
|
||||||
-- Extract the directory from the current file's path
|
|
||||||
current_dir = vim.fn.fnamemodify(current_file, ':h')
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Find the Git root directory from the current file's path
|
|
||||||
local git_root = vim.fn.systemlist('git -C ' .. vim.fn.escape(current_dir, ' ') .. ' rev-parse --show-toplevel')[1]
|
|
||||||
if vim.v.shell_error ~= 0 then
|
|
||||||
print 'Not a git repository. Searching on current working directory'
|
|
||||||
return cwd
|
|
||||||
end
|
|
||||||
return git_root
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Custom live_grep function to search in git root
|
|
||||||
local function live_grep_git_root()
|
|
||||||
local git_root = find_git_root()
|
|
||||||
if git_root then
|
|
||||||
require('telescope.builtin').live_grep {
|
|
||||||
search_dirs = { git_root },
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
vim.api.nvim_create_user_command('LiveGrepGitRoot', live_grep_git_root, {})
|
|
||||||
|
|
||||||
-- See `:help telescope.builtin`
|
|
||||||
vim.keymap.set('n', '<leader>?', require('telescope.builtin').oldfiles, { desc = '[?] Find recently opened files' })
|
|
||||||
vim.keymap.set('n', '<leader><space>', require('telescope.builtin').buffers, { desc = '[ ] Find existing buffers' })
|
|
||||||
vim.keymap.set('n', '<leader>/', function()
|
|
||||||
-- You can pass additional configuration to telescope to change theme, layout, etc.
|
|
||||||
require('telescope.builtin').current_buffer_fuzzy_find(require('telescope.themes').get_dropdown {
|
|
||||||
winblend = 10,
|
|
||||||
previewer = false,
|
|
||||||
})
|
|
||||||
end, { desc = '[/] Fuzzily search in current buffer' })
|
|
||||||
|
|
||||||
local function telescope_live_grep_open_files()
|
|
||||||
require('telescope.builtin').live_grep {
|
|
||||||
grep_open_files = true,
|
|
||||||
prompt_title = 'Live Grep in Open Files',
|
|
||||||
}
|
|
||||||
end
|
|
||||||
vim.keymap.set('n', '<leader>s/', telescope_live_grep_open_files, { desc = '[S]earch [/] in Open Files' })
|
|
||||||
vim.keymap.set('n', '<leader>ss', require('telescope.builtin').builtin, { desc = '[S]earch [S]elect Telescope' })
|
|
||||||
vim.keymap.set('n', '<leader>gf', function()
|
|
||||||
local is_git_dir = vim.fn.system('git rev-parse --is-inside-work-tree'):gsub('%s+', '') == 'true'
|
|
||||||
if not is_git_dir then
|
|
||||||
vim.notify('Not a git repository', vim.log.levels.WARN, { title = 'Telescope Git Files' })
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
require('telescope.builtin').git_files {
|
|
||||||
attach_mappings = function(_, map)
|
|
||||||
local actions = require 'telescope.actions'
|
|
||||||
local action_state = require 'telescope.actions.state'
|
|
||||||
|
|
||||||
local function open_smart(prompt_bufnr)
|
|
||||||
local entry = action_state.get_selected_entry()
|
|
||||||
if not entry then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
pcall(actions.close, prompt_bufnr)
|
|
||||||
smart_open(prompt_bufnr)
|
|
||||||
end
|
|
||||||
|
|
||||||
map('i', '<CR>', open_smart)
|
|
||||||
map('n', '<CR>', open_smart)
|
|
||||||
return true
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
end, { desc = 'Search [G]it [F]iles (Smart Open)' })
|
|
||||||
vim.keymap.set('n', '<leader>si', require('telescope.builtin').help_tags, { desc = '[S]earch [I]nfo' })
|
|
||||||
vim.keymap.set('n', '<leader>sw', require('telescope.builtin').grep_string, { desc = '[S]earch current [W]ord' })
|
|
||||||
vim.keymap.set('n', '<leader>sg', require('telescope.builtin').live_grep, { desc = '[S]earch by [G]rep' })
|
|
||||||
vim.keymap.set('n', '<leader>sG', ':LiveGrepGitRoot<cr>', { desc = '[S]earch by [G]rep on Git Root' })
|
|
||||||
vim.keymap.set('n', '<leader>sd', require('telescope.builtin').diagnostics, { desc = '[S]earch [D]iagnostics' })
|
|
||||||
vim.keymap.set('n', '<leader>sr', require('telescope.builtin').resume, { desc = '[S]earch [R]esume' })
|
|
||||||
|
|
||||||
-- [[ Configure Treesitter ]]
|
-- [[ Configure Treesitter ]]
|
||||||
-- See `:help nvim-treesitter`
|
-- See `:help nvim-treesitter`
|
||||||
-- Defer Treesitter setup after first render to improve startup time of 'nvim {filename}'
|
-- Defer Treesitter setup after first render to improve startup time of 'nvim {filename}'
|
||||||
@@ -948,10 +468,8 @@ require('mason-lspconfig').setup()
|
|||||||
|
|
||||||
-- Enable the following language servers
|
-- Enable the following language servers
|
||||||
-- Feel free to add/remove any LSPs that you want here. They will automatically be installed.
|
-- Feel free to add/remove any LSPs that you want here. They will automatically be installed.
|
||||||
--
|
|
||||||
-- Add any additional override configuration in the following tables. They will be passed to
|
-- Add any additional override configuration in the following tables. They will be passed to
|
||||||
-- the `settings` field of the server config. You must look up that documentation yourself.
|
-- the `settings` field of the server config. You must look up that documentation yourself.
|
||||||
--
|
|
||||||
-- If you want to override the default filetypes that your language server will attach to you can
|
-- If you want to override the default filetypes that your language server will attach to you can
|
||||||
-- define the property 'filetypes' to the map in question.
|
-- define the property 'filetypes' to the map in question.
|
||||||
local servers = {
|
local servers = {
|
||||||
@@ -982,10 +500,6 @@ capabilities = require('cmp_nvim_lsp').default_capabilities(capabilities)
|
|||||||
-- Ensure the servers above are installed
|
-- Ensure the servers above are installed
|
||||||
local mason_lspconfig = require 'mason-lspconfig'
|
local mason_lspconfig = require 'mason-lspconfig'
|
||||||
|
|
||||||
mason_lspconfig.setup {
|
|
||||||
ensure_installed = vim.tbl_keys(servers),
|
|
||||||
}
|
|
||||||
|
|
||||||
mason_lspconfig.setup {
|
mason_lspconfig.setup {
|
||||||
ensure_installed = vim.tbl_keys(servers),
|
ensure_installed = vim.tbl_keys(servers),
|
||||||
handlers = {
|
handlers = {
|
||||||
@@ -1213,8 +727,7 @@ end
|
|||||||
-- Auto-clear messages on most user actions
|
-- Auto-clear messages on most user actions
|
||||||
local clear_msg_grp = vim.api.nvim_create_augroup('AutoClearMessages', { clear = true })
|
local clear_msg_grp = vim.api.nvim_create_augroup('AutoClearMessages', { clear = true })
|
||||||
|
|
||||||
vim.api.nvim_create_autocmd(
|
vim.api.nvim_create_autocmd({ 'CursorMoved', 'CursorMovedI', 'InsertEnter', 'InsertLeave', 'TextChanged', 'TextChangedI' }, {
|
||||||
{ 'CursorMoved', 'CursorMovedI', 'InsertEnter', 'InsertLeave', 'TextChanged', 'TextChangedI' }, {
|
|
||||||
group = clear_msg_grp,
|
group = clear_msg_grp,
|
||||||
callback = function()
|
callback = function()
|
||||||
vim.cmd 'echo ""' -- Clear the message/command line
|
vim.cmd 'echo ""' -- Clear the message/command line
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
"plenary.nvim": { "branch": "master", "commit": "b9fd5226c2f76c951fc8ed5923d85e4de065e509" },
|
"plenary.nvim": { "branch": "master", "commit": "b9fd5226c2f76c951fc8ed5923d85e4de065e509" },
|
||||||
"telescope-fzf-native.nvim": { "branch": "main", "commit": "1f08ed60cafc8f6168b72b80be2b2ea149813e55" },
|
"telescope-fzf-native.nvim": { "branch": "main", "commit": "1f08ed60cafc8f6168b72b80be2b2ea149813e55" },
|
||||||
"telescope.nvim": { "branch": "0.1.x", "commit": "a0bbec21143c7bc5f8bb02e0005fa0b982edc026" },
|
"telescope.nvim": { "branch": "0.1.x", "commit": "a0bbec21143c7bc5f8bb02e0005fa0b982edc026" },
|
||||||
|
"undotree": { "branch": "master", "commit": "0f1c9816975b5d7f87d5003a19c53c6fd2ff6f7f" },
|
||||||
"vim-fugitive": { "branch": "master", "commit": "61b51c09b7c9ce04e821f6cf76ea4f6f903e3cf4" },
|
"vim-fugitive": { "branch": "master", "commit": "61b51c09b7c9ce04e821f6cf76ea4f6f903e3cf4" },
|
||||||
"vim-rhubarb": { "branch": "master", "commit": "5496d7c94581c4c9ad7430357449bb57fc59f501" },
|
"vim-rhubarb": { "branch": "master", "commit": "5496d7c94581c4c9ad7430357449bb57fc59f501" },
|
||||||
"which-key.nvim": { "branch": "main", "commit": "904308e6885bbb7b60714c80ab3daf0c071c1492" }
|
"which-key.nvim": { "branch": "main", "commit": "904308e6885bbb7b60714c80ab3daf0c071c1492" }
|
||||||
|
|||||||
@@ -2,181 +2,181 @@
|
|||||||
vim.cmd [[ let g:neo_tree_remove_legacy_commands = 1 ]]
|
vim.cmd [[ let g:neo_tree_remove_legacy_commands = 1 ]]
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'nvim-neo-tree/neo-tree.nvim',
|
'nvim-neo-tree/neo-tree.nvim',
|
||||||
version = '*',
|
version = '*',
|
||||||
dependencies = {
|
dependencies = {
|
||||||
'nvim-lua/plenary.nvim',
|
'nvim-lua/plenary.nvim',
|
||||||
'nvim-tree/nvim-web-devicons',
|
'nvim-tree/nvim-web-devicons',
|
||||||
'MunifTanjim/nui.nvim',
|
'MunifTanjim/nui.nvim',
|
||||||
},
|
},
|
||||||
config = function()
|
config = function()
|
||||||
local function smart_open(state)
|
local function smart_open(state)
|
||||||
local node = state.tree:get_node()
|
local node = state.tree:get_node()
|
||||||
if not node then
|
if not node then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local path = node:get_id()
|
local path = node:get_id()
|
||||||
|
|
||||||
-- If the node is a directory, just toggle expand/collapse
|
-- If the node is a directory, just toggle expand/collapse
|
||||||
if node.type == 'directory' then
|
if node.type == 'directory' then
|
||||||
state.commands.toggle_node(state, node)
|
state.commands.toggle_node(state, node)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- --- File handling starts here ---
|
-- --- File handling starts here ---
|
||||||
-- Reuse already open buffer in any tab safely
|
-- Reuse already open buffer in any tab safely
|
||||||
for _, tab in ipairs(vim.api.nvim_list_tabpages()) do
|
for _, tab in ipairs(vim.api.nvim_list_tabpages()) do
|
||||||
if vim.api.nvim_tabpage_is_valid(tab) then
|
if vim.api.nvim_tabpage_is_valid(tab) then
|
||||||
for _, win in ipairs(vim.api.nvim_tabpage_list_wins(tab)) do
|
for _, win in ipairs(vim.api.nvim_tabpage_list_wins(tab)) do
|
||||||
if vim.api.nvim_win_is_valid(win) then
|
if vim.api.nvim_win_is_valid(win) then
|
||||||
local buf = vim.api.nvim_win_get_buf(win)
|
local buf = vim.api.nvim_win_get_buf(win)
|
||||||
if vim.api.nvim_buf_is_valid(buf) and vim.api.nvim_buf_get_name(buf) == path then
|
if vim.api.nvim_buf_is_valid(buf) and vim.api.nvim_buf_get_name(buf) == path then
|
||||||
vim.api.nvim_set_current_tabpage(tab)
|
vim.api.nvim_set_current_tabpage(tab)
|
||||||
vim.api.nvim_set_current_win(win)
|
vim.api.nvim_set_current_win(win)
|
||||||
-- close Neo-tree if open
|
-- close Neo-tree if open
|
||||||
for _, w in ipairs(vim.api.nvim_list_wins()) do
|
for _, w in ipairs(vim.api.nvim_list_wins()) do
|
||||||
if vim.api.nvim_win_is_valid(w) then
|
if vim.api.nvim_win_is_valid(w) then
|
||||||
local b = vim.api.nvim_win_get_buf(w)
|
local b = vim.api.nvim_win_get_buf(w)
|
||||||
if vim.api.nvim_buf_is_valid(b) and vim.api.nvim_buf_get_option(b, 'filetype') == 'neo-tree' then
|
if vim.api.nvim_buf_is_valid(b) and vim.api.nvim_buf_get_option(b, 'filetype') == 'neo-tree' then
|
||||||
vim.api.nvim_win_close(w, true)
|
vim.api.nvim_win_close(w, true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Reuse empty buffer in current tab
|
-- Reuse empty buffer in current tab
|
||||||
local wins = vim.api.nvim_tabpage_list_wins(0)
|
local wins = vim.api.nvim_tabpage_list_wins(0)
|
||||||
local empty_buf = nil
|
local empty_buf = nil
|
||||||
for _, win in ipairs(wins) do
|
for _, win in ipairs(wins) do
|
||||||
if vim.api.nvim_win_is_valid(win) then
|
if vim.api.nvim_win_is_valid(win) then
|
||||||
local buf = vim.api.nvim_win_get_buf(win)
|
local buf = vim.api.nvim_win_get_buf(win)
|
||||||
if vim.api.nvim_buf_is_valid(buf) then
|
if vim.api.nvim_buf_is_valid(buf) then
|
||||||
local bufname = vim.api.nvim_buf_get_name(buf)
|
local bufname = vim.api.nvim_buf_get_name(buf)
|
||||||
local buftype = vim.api.nvim_buf_get_option(buf, 'buftype')
|
local buftype = vim.api.nvim_buf_get_option(buf, 'buftype')
|
||||||
local modified = vim.api.nvim_buf_get_option(buf, 'modified')
|
local modified = vim.api.nvim_buf_get_option(buf, 'modified')
|
||||||
if bufname == '' and buftype == '' and not modified then
|
if bufname == '' and buftype == '' and not modified then
|
||||||
empty_buf = buf
|
empty_buf = buf
|
||||||
vim.api.nvim_set_current_win(win)
|
vim.api.nvim_set_current_win(win)
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if empty_buf then
|
if empty_buf then
|
||||||
vim.cmd('edit ' .. vim.fn.fnameescape(path))
|
vim.cmd('edit ' .. vim.fn.fnameescape(path))
|
||||||
else
|
else
|
||||||
vim.cmd('tabnew ' .. vim.fn.fnameescape(path))
|
vim.cmd('tabnew ' .. vim.fn.fnameescape(path))
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Always close Neo-tree window if open
|
-- Always close Neo-tree window if open
|
||||||
for _, win in ipairs(vim.api.nvim_list_wins()) do
|
for _, win in ipairs(vim.api.nvim_list_wins()) do
|
||||||
if vim.api.nvim_win_is_valid(win) then
|
if vim.api.nvim_win_is_valid(win) then
|
||||||
local buf = vim.api.nvim_win_get_buf(win)
|
local buf = vim.api.nvim_win_get_buf(win)
|
||||||
if vim.api.nvim_buf_is_valid(buf) and vim.api.nvim_buf_get_option(buf, 'filetype') == 'neo-tree' then
|
if vim.api.nvim_buf_is_valid(buf) and vim.api.nvim_buf_get_option(buf, 'filetype') == 'neo-tree' then
|
||||||
vim.api.nvim_win_close(win, true)
|
vim.api.nvim_win_close(win, true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Smart_open_split for split windows
|
-- Smart_open_split for split windows
|
||||||
local function smart_open_split(state, direction)
|
local function smart_open_split(state, direction)
|
||||||
local node = state.tree:get_node()
|
local node = state.tree:get_node()
|
||||||
if not node then
|
if not node then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local path = node:get_id()
|
local path = node:get_id()
|
||||||
|
|
||||||
if node.type == 'directory' then
|
if node.type == 'directory' then
|
||||||
state.commands.toggle_node(state, node)
|
state.commands.toggle_node(state, node)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Check if file is open in another tab
|
-- Check if file is open in another tab
|
||||||
local open_tab, open_win
|
local open_tab, open_win
|
||||||
for _, tab in ipairs(vim.api.nvim_list_tabpages()) do
|
for _, tab in ipairs(vim.api.nvim_list_tabpages()) do
|
||||||
for _, win in ipairs(vim.api.nvim_tabpage_list_wins(tab)) do
|
for _, win in ipairs(vim.api.nvim_tabpage_list_wins(tab)) do
|
||||||
local buf = vim.api.nvim_win_get_buf(win)
|
local buf = vim.api.nvim_win_get_buf(win)
|
||||||
if vim.api.nvim_buf_is_valid(buf) and vim.api.nvim_buf_get_name(buf) == path then
|
if vim.api.nvim_buf_is_valid(buf) and vim.api.nvim_buf_get_name(buf) == path then
|
||||||
open_tab = tab
|
open_tab = tab
|
||||||
open_win = win
|
open_win = win
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if open_tab then
|
if open_tab then
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if open_tab then
|
if open_tab then
|
||||||
local choice = vim.fn.confirm('File is already open in a tab. Open split here anyway?', '&Yes\n&No', 2)
|
local choice = vim.fn.confirm('File is already open in a tab. Open split here anyway?', '&Yes\n&No', 2)
|
||||||
if choice ~= 1 then
|
if choice ~= 1 then
|
||||||
-- User chose No → jump to the tab where file is open
|
-- User chose No → jump to the tab where file is open
|
||||||
vim.api.nvim_set_current_tabpage(open_tab)
|
vim.api.nvim_set_current_tabpage(open_tab)
|
||||||
vim.api.nvim_set_current_win(open_win)
|
vim.api.nvim_set_current_win(open_win)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
-- Else user chose Yes → continue to open split in current tab
|
-- Else user chose Yes → continue to open split in current tab
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Open split in current tab
|
-- Open split in current tab
|
||||||
if direction == 'v' then
|
if direction == 'v' then
|
||||||
state.commands.open_vsplit(state)
|
state.commands.open_vsplit(state)
|
||||||
vim.schedule(function()
|
vim.schedule(function()
|
||||||
vim.cmd 'wincmd L'
|
vim.cmd 'wincmd L'
|
||||||
end)
|
end)
|
||||||
else
|
else
|
||||||
state.commands.open_split(state)
|
state.commands.open_split(state)
|
||||||
vim.schedule(function()
|
vim.schedule(function()
|
||||||
vim.cmd 'wincmd J'
|
vim.cmd 'wincmd J'
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
vim.cmd('edit ' .. vim.fn.fnameescape(path))
|
vim.cmd('edit ' .. vim.fn.fnameescape(path))
|
||||||
end
|
end
|
||||||
|
|
||||||
require('neo-tree').setup {
|
require('neo-tree').setup {
|
||||||
close_if_last_window = true,
|
close_if_last_window = true,
|
||||||
popup_border_style = 'rounded',
|
popup_border_style = 'rounded',
|
||||||
enable_git_status = true,
|
enable_git_status = true,
|
||||||
enable_diagnostics = true,
|
enable_diagnostics = true,
|
||||||
default_component_configs = {
|
default_component_configs = {
|
||||||
indent = { padding = 1, indent_size = 2 },
|
indent = { padding = 1, indent_size = 2 },
|
||||||
icon = { folder_closed = '', folder_open = '', folder_empty = 'ﰊ' },
|
icon = { folder_closed = '', folder_open = '', folder_empty = 'ﰊ' },
|
||||||
},
|
},
|
||||||
window = {
|
window = {
|
||||||
position = 'float',
|
position = 'float',
|
||||||
width = 40,
|
width = 40,
|
||||||
mapping_options = { noremap = true, nowait = true },
|
mapping_options = { noremap = true, nowait = true },
|
||||||
mappings = {
|
mappings = {
|
||||||
['<cr>'] = smart_open,
|
['<cr>'] = smart_open,
|
||||||
['v'] = function(state)
|
['v'] = function(state)
|
||||||
smart_open_split(state, 'h')
|
smart_open_split(state, 'h')
|
||||||
end,
|
end,
|
||||||
['h'] = function(state)
|
['h'] = function(state)
|
||||||
smart_open_split(state, 'v')
|
smart_open_split(state, 'v')
|
||||||
end,
|
end,
|
||||||
['t'] = 'noop',
|
['t'] = 'noop',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
filesystem = {
|
filesystem = {
|
||||||
follow_current_file = {
|
follow_current_file = {
|
||||||
enabled = true, -- updated to table format
|
enabled = true, -- updated to table format
|
||||||
},
|
},
|
||||||
use_libuv_file_watcher = true,
|
use_libuv_file_watcher = true,
|
||||||
hijack_netrw_behavior = 'open_default',
|
hijack_netrw_behavior = 'open_default',
|
||||||
filtered_items = {
|
filtered_items = {
|
||||||
visible = true,
|
visible = true,
|
||||||
hide_dotfiles = false,
|
hide_dotfiles = false,
|
||||||
hide_gitignored = true,
|
hide_gitignored = true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
-- You can add your own plugins here or in other files in this directory!
|
|
||||||
-- I promise not to create any merge conflicts in this directory :)
|
|
||||||
--
|
|
||||||
-- See the kickstart.nvim README for more information
|
|
||||||
|
|
||||||
return {
|
|
||||||
}
|
|
||||||
255
lua/custom/plugins/telescope.lua
Normal file
255
lua/custom/plugins/telescope.lua
Normal file
@@ -0,0 +1,255 @@
|
|||||||
|
return {
|
||||||
|
-- Fuzzy Finder (files, lsp, etc)
|
||||||
|
'nvim-telescope/telescope.nvim',
|
||||||
|
branch = '0.1.x',
|
||||||
|
dependencies = {
|
||||||
|
'nvim-lua/plenary.nvim',
|
||||||
|
-- Fuzzy Finder Algorithm which requires local dependencies to be built.
|
||||||
|
-- Only load if `make` is available. Make sure you have the system
|
||||||
|
-- requirements installed.
|
||||||
|
{
|
||||||
|
'nvim-telescope/telescope-fzf-native.nvim',
|
||||||
|
-- NOTE: If you are having trouble with this installation,
|
||||||
|
-- refer to the README for telescope-fzf-native for more instructions.
|
||||||
|
build = 'make',
|
||||||
|
cond = function()
|
||||||
|
return vim.fn.executable 'make' == 1
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
config = function()
|
||||||
|
-- [[ Configure Telescope ]]
|
||||||
|
-- See `:help telescope` and `:help telescope.setup()`
|
||||||
|
require('telescope').setup {
|
||||||
|
defaults = {
|
||||||
|
mappings = {
|
||||||
|
i = {
|
||||||
|
['<C-u>'] = false,
|
||||||
|
['<C-d>'] = false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Enable telescope fzf native, if installed
|
||||||
|
pcall(require('telescope').load_extension, 'fzf')
|
||||||
|
|
||||||
|
-- smart_open function for Telescope to check if the current tab has an empty "No Name" buffer. If it has, it replaces the empty buffer and open a file in the same tab
|
||||||
|
local actions = require 'telescope.actions'
|
||||||
|
local action_state = require 'telescope.actions.state'
|
||||||
|
|
||||||
|
local function smart_open(prompt_bufnr)
|
||||||
|
local entry = action_state.get_selected_entry()
|
||||||
|
if not entry then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local path = entry.path or entry.filename
|
||||||
|
if not path then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if prompt_bufnr and vim.api.nvim_buf_is_valid(prompt_bufnr) then
|
||||||
|
pcall(actions.close, prompt_bufnr)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 1. If file is already open → jump to it
|
||||||
|
local tabpages = vim.api.nvim_list_tabpages()
|
||||||
|
for _, tab in ipairs(tabpages) do
|
||||||
|
for _, win in ipairs(vim.api.nvim_tabpage_list_wins(tab)) do
|
||||||
|
local buf = vim.api.nvim_win_get_buf(win)
|
||||||
|
if vim.api.nvim_buf_get_name(buf) == path then
|
||||||
|
vim.api.nvim_set_current_tabpage(tab) -- jump to tab
|
||||||
|
vim.api.nvim_set_current_win(win) -- jump to window
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 2. If current tab has an empty "No Name" buffer → reuse it
|
||||||
|
local wins = vim.api.nvim_tabpage_list_wins(0)
|
||||||
|
for _, win in ipairs(wins) do
|
||||||
|
local buf = vim.api.nvim_win_get_buf(win)
|
||||||
|
local name = vim.api.nvim_buf_get_name(buf)
|
||||||
|
local buftype = vim.api.nvim_buf_get_option(buf, 'buftype')
|
||||||
|
local modified = vim.api.nvim_buf_get_option(buf, 'modified')
|
||||||
|
if name == '' and buftype == '' and not modified then
|
||||||
|
vim.api.nvim_set_current_win(win)
|
||||||
|
vim.cmd('edit ' .. vim.fn.fnameescape(path))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 3. Otherwise → open in a new tab
|
||||||
|
vim.cmd('tabnew ' .. vim.fn.fnameescape(path))
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Split option in Telescope file picker with smart_open
|
||||||
|
local actions = require 'telescope.actions'
|
||||||
|
local action_state = require 'telescope.actions.state'
|
||||||
|
|
||||||
|
local function smart_open_split(prompt_bufnr, split_type)
|
||||||
|
local entry = action_state.get_selected_entry()
|
||||||
|
if not entry then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local path = entry.path or entry.filename
|
||||||
|
if not path then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if prompt_bufnr and vim.api.nvim_buf_is_valid(prompt_bufnr) then
|
||||||
|
pcall(actions.close, prompt_bufnr)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check if file is already open
|
||||||
|
local open_tab, open_win
|
||||||
|
for _, tab in ipairs(vim.api.nvim_list_tabpages()) do
|
||||||
|
for _, win in ipairs(vim.api.nvim_tabpage_list_wins(tab)) do
|
||||||
|
local buf = vim.api.nvim_win_get_buf(win)
|
||||||
|
if vim.api.nvim_buf_get_name(buf) == path then
|
||||||
|
open_tab = tab
|
||||||
|
open_win = win
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if open_tab then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if open_tab then
|
||||||
|
local choice = vim.fn.confirm('File is already open in a tab. Open split here anyway?', '&Yes\n&No', 2)
|
||||||
|
if choice ~= 1 then
|
||||||
|
-- User chose No → jump to the tab where file is open
|
||||||
|
vim.api.nvim_set_current_tabpage(open_tab)
|
||||||
|
vim.api.nvim_set_current_win(open_win)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
-- Else user chose Yes → continue to open split in current tab
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Open in split
|
||||||
|
if split_type == 'v' then
|
||||||
|
-- horizontal → always below
|
||||||
|
vim.cmd('belowright split ' .. vim.fn.fnameescape(path))
|
||||||
|
elseif split_type == 'h' then
|
||||||
|
-- vertical → always right
|
||||||
|
vim.cmd('vertical rightbelow split ' .. vim.fn.fnameescape(path))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Telescope keymap using Smart Open
|
||||||
|
vim.keymap.set('n', '<leader>sf', function()
|
||||||
|
require('telescope.builtin').find_files {
|
||||||
|
attach_mappings = function(_, map)
|
||||||
|
map('i', '<CR>', function(prompt_bufnr)
|
||||||
|
smart_open(prompt_bufnr)
|
||||||
|
end)
|
||||||
|
map('n', '<CR>', function(prompt_bufnr)
|
||||||
|
smart_open(prompt_bufnr)
|
||||||
|
end)
|
||||||
|
-- Horizontal split with 'h'
|
||||||
|
map('n', 'h', function(prompt_bufnr)
|
||||||
|
smart_open_split(prompt_bufnr, 'h')
|
||||||
|
end)
|
||||||
|
-- Vertical split with 'v'
|
||||||
|
map('n', 'v', function(prompt_bufnr)
|
||||||
|
smart_open_split(prompt_bufnr, 'v')
|
||||||
|
end)
|
||||||
|
return true
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
end, { desc = '[S]earch [F]iles (Smart Open)' })
|
||||||
|
|
||||||
|
-- Telescope live_grep in git root
|
||||||
|
-- Function to find the git root directory based on the current buffer's path
|
||||||
|
local function find_git_root()
|
||||||
|
-- Use the current buffer's path as the starting point for the git search
|
||||||
|
local current_file = vim.api.nvim_buf_get_name(0)
|
||||||
|
local current_dir
|
||||||
|
local cwd = vim.fn.getcwd()
|
||||||
|
-- If the buffer is not associated with a file, return nil
|
||||||
|
if current_file == '' then
|
||||||
|
current_dir = cwd
|
||||||
|
else
|
||||||
|
-- Extract the directory from the current file's path
|
||||||
|
current_dir = vim.fn.fnamemodify(current_file, ':h')
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Find the Git root directory from the current file's path
|
||||||
|
local git_root = vim.fn.systemlist('git -C ' .. vim.fn.escape(current_dir, ' ') .. ' rev-parse --show-toplevel')[1]
|
||||||
|
if vim.v.shell_error ~= 0 then
|
||||||
|
print 'Not a git repository. Searching on current working directory'
|
||||||
|
return cwd
|
||||||
|
end
|
||||||
|
return git_root
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Custom live_grep function to search in git root
|
||||||
|
local function live_grep_git_root()
|
||||||
|
local git_root = find_git_root()
|
||||||
|
if git_root then
|
||||||
|
require('telescope.builtin').live_grep {
|
||||||
|
search_dirs = { git_root },
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
vim.api.nvim_create_user_command('LiveGrepGitRoot', live_grep_git_root, {})
|
||||||
|
|
||||||
|
-- See `:help telescope.builtin`
|
||||||
|
vim.keymap.set('n', '<leader>?', require('telescope.builtin').oldfiles, { desc = '[?] Find recently opened files' })
|
||||||
|
vim.keymap.set('n', '<leader><space>', require('telescope.builtin').buffers, { desc = '[ ] Find existing buffers' })
|
||||||
|
vim.keymap.set('n', '<leader>/', function()
|
||||||
|
-- You can pass additional configuration to telescope to change theme, layout, etc.
|
||||||
|
require('telescope.builtin').current_buffer_fuzzy_find(require('telescope.themes').get_dropdown {
|
||||||
|
winblend = 10,
|
||||||
|
previewer = false,
|
||||||
|
})
|
||||||
|
end, { desc = '[/] Fuzzily search in current buffer' })
|
||||||
|
|
||||||
|
local function telescope_live_grep_open_files()
|
||||||
|
require('telescope.builtin').live_grep {
|
||||||
|
grep_open_files = true,
|
||||||
|
prompt_title = 'Live Grep in Open Files',
|
||||||
|
}
|
||||||
|
end
|
||||||
|
vim.keymap.set('n', '<leader>s/', telescope_live_grep_open_files, { desc = '[S]earch [/] in Open Files' })
|
||||||
|
vim.keymap.set('n', '<leader>ss', require('telescope.builtin').builtin, { desc = '[S]earch [S]elect Telescope' })
|
||||||
|
vim.keymap.set('n', '<leader>gf', function()
|
||||||
|
local is_git_dir = vim.fn.system('git rev-parse --is-inside-work-tree'):gsub('%s+', '') == 'true'
|
||||||
|
if not is_git_dir then
|
||||||
|
vim.notify('Not a git repository', vim.log.levels.WARN, { title = 'Telescope Git Files' })
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
require('telescope.builtin').git_files {
|
||||||
|
attach_mappings = function(_, map)
|
||||||
|
local actions = require 'telescope.actions'
|
||||||
|
local action_state = require 'telescope.actions.state'
|
||||||
|
|
||||||
|
local function open_smart(prompt_bufnr)
|
||||||
|
local entry = action_state.get_selected_entry()
|
||||||
|
if not entry then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
pcall(actions.close, prompt_bufnr)
|
||||||
|
smart_open(prompt_bufnr)
|
||||||
|
end
|
||||||
|
|
||||||
|
map('i', '<CR>', open_smart)
|
||||||
|
map('n', '<CR>', open_smart)
|
||||||
|
return true
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
end, { desc = 'Search [G]it [F]iles (Smart Open)' })
|
||||||
|
vim.keymap.set('n', '<leader>si', require('telescope.builtin').help_tags, { desc = '[S]earch [I]nfo' })
|
||||||
|
vim.keymap.set('n', '<leader>sw', require('telescope.builtin').grep_string, { desc = '[S]earch current [W]ord' })
|
||||||
|
vim.keymap.set('n', '<leader>sg', require('telescope.builtin').live_grep, { desc = '[S]earch by [G]rep' })
|
||||||
|
vim.keymap.set('n', '<leader>sG', ':LiveGrepGitRoot<cr>', { desc = '[S]earch by [G]rep on Git Root' })
|
||||||
|
vim.keymap.set('n', '<leader>sd', require('telescope.builtin').diagnostics, { desc = '[S]earch [D]iagnostics' })
|
||||||
|
vim.keymap.set('n', '<leader>sr', require('telescope.builtin').resume, { desc = '[S]earch [R]esume' })
|
||||||
|
end,
|
||||||
|
}
|
||||||
14
lua/custom/plugins/undotree.lua
Normal file
14
lua/custom/plugins/undotree.lua
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
-- lua/custom/plugins/undotree.lua
|
||||||
|
return {
|
||||||
|
'mbbill/undotree',
|
||||||
|
keys = {
|
||||||
|
{ '<leader>u', vim.cmd.UndotreeToggle, desc = 'Toggle UndoTree' },
|
||||||
|
},
|
||||||
|
config = function()
|
||||||
|
-- Optional settings
|
||||||
|
vim.g.undotree_WindowLayout = 2 -- vertical split
|
||||||
|
vim.g.undotree_SplitWidth = 30 -- width of undo tree window
|
||||||
|
vim.g.undotree_SetFocusWhenToggle = 1
|
||||||
|
vim.g.undotree_EnableDiff = 1
|
||||||
|
end,
|
||||||
|
}
|
||||||
259
lua/keymaps.lua
Normal file
259
lua/keymaps.lua
Normal file
@@ -0,0 +1,259 @@
|
|||||||
|
-- [[ Few useful keymaps]]
|
||||||
|
vim.keymap.set('v', 'J', ":m '<+1<CR>gv=gv")
|
||||||
|
vim.keymap.set('v', 'K', ":m '<-2<CR>gv=gv")
|
||||||
|
vim.keymap.set('n', 'J', 'mzJ`z')
|
||||||
|
vim.keymap.set('n', 'J', 'mzJ`z')
|
||||||
|
vim.keymap.set('n', '<leader>j', '<C-d>zz', { desc = 'Scroll down and center cursor' })
|
||||||
|
vim.keymap.set('n', '<leader>k', '<C-u>zz', { desc = 'Scroll up and center cursor' })
|
||||||
|
vim.keymap.set('n', 'n', 'nzzzv')
|
||||||
|
vim.keymap.set('n', 'N', 'Nzzzv')
|
||||||
|
vim.keymap.set('x', '<leader>p', '"_dP', { desc = 'Paste over selection without yanking' })
|
||||||
|
|
||||||
|
-- Replace all occurrences of the word under cursor
|
||||||
|
vim.keymap.set('n', '<leader>F', function()
|
||||||
|
-- Save current cursor position
|
||||||
|
local pos = vim.api.nvim_win_get_cursor(0)
|
||||||
|
-- Get the word under the cursor
|
||||||
|
local word = vim.fn.expand '<cword>'
|
||||||
|
-- Ask user for the replacement
|
||||||
|
local replacement = vim.fn.input("Replace '" .. word .. "' with: ")
|
||||||
|
-- If user typed something, do the substitution
|
||||||
|
if replacement ~= '' then
|
||||||
|
-- %%s/.../.../gI = substitute globally, case-insensitive
|
||||||
|
vim.cmd(string.format('%%s/\\<%s\\>/%s/gI', word, replacement))
|
||||||
|
end
|
||||||
|
-- Restore cursor position
|
||||||
|
vim.api.nvim_win_set_cursor(0, pos)
|
||||||
|
end, { desc = 'Replace all occurrences of word under cursor' })
|
||||||
|
|
||||||
|
-- [[ Basic Keymaps ]]
|
||||||
|
|
||||||
|
-- Keymaps for better default experience
|
||||||
|
-- See `:help vim.keymap.set()`
|
||||||
|
vim.keymap.set({ 'n', 'v' }, '<Space>', '<Nop>', { silent = true })
|
||||||
|
|
||||||
|
-- Remap for dealing with word wrap
|
||||||
|
vim.keymap.set('n', 'k', "v:count == 0 ? 'gk' : 'k'", { expr = true, silent = true })
|
||||||
|
vim.keymap.set('n', 'j', "v:count == 0 ? 'gj' : 'j'", { expr = true, silent = true })
|
||||||
|
|
||||||
|
-- Diagnostic keymaps
|
||||||
|
vim.keymap.set('n', '[d', vim.diagnostic.goto_prev, { desc = 'Go to previous diagnostic message' })
|
||||||
|
vim.keymap.set('n', ']d', vim.diagnostic.goto_next, { desc = 'Go to next diagnostic message' })
|
||||||
|
vim.keymap.set('n', '<leader>de', vim.diagnostic.open_float, { desc = 'Diagnostics: floating message' })
|
||||||
|
vim.keymap.set('n', '<leader>dq', vim.diagnostic.setloclist, { desc = 'Diagnostics: location list' })
|
||||||
|
|
||||||
|
-- [[ Custom keymaps ]]
|
||||||
|
|
||||||
|
-- Neo-tree sync to current directory & toggle
|
||||||
|
vim.keymap.set('n', '<leader>n', '<Cmd>cd %:p:h | Neotree toggle float<CR>')
|
||||||
|
|
||||||
|
-- Terminal open in new tab
|
||||||
|
vim.keymap.set('n', '<leader>t', '<Cmd>tabnew +term<CR>i')
|
||||||
|
|
||||||
|
-- Create an empty buffer in a new tab
|
||||||
|
vim.keymap.set('n', '<Leader>e', function()
|
||||||
|
vim.cmd 'tabnew' -- create a new tab
|
||||||
|
vim.cmd 'enew' -- create a new empty buffer in it
|
||||||
|
end, { noremap = true, silent = true })
|
||||||
|
|
||||||
|
-- Horizontal split with new empty buffer below
|
||||||
|
vim.keymap.set('n', '<leader>sv', function()
|
||||||
|
vim.cmd 'split' -- create horizontal split (above by default)
|
||||||
|
vim.cmd 'wincmd j' -- move to the new split below
|
||||||
|
vim.cmd 'enew' -- open new empty buffer
|
||||||
|
end, { desc = 'New buffer in horizontal split (below)' })
|
||||||
|
|
||||||
|
-- Vertical split with new empty buffer to the right
|
||||||
|
vim.keymap.set('n', '<leader>sh', function()
|
||||||
|
vim.cmd 'vsplit' -- create vertical split (left by default)
|
||||||
|
vim.cmd 'wincmd l' -- move to the new split to the right
|
||||||
|
vim.cmd 'enew' -- open new empty buffer
|
||||||
|
end, { desc = 'New buffer in vertical split (right)' })
|
||||||
|
|
||||||
|
-- Save current buffer (asks for filename if new/unsaved)
|
||||||
|
vim.keymap.set('n', '<leader>w', function()
|
||||||
|
if vim.api.nvim_buf_get_name(0) == '' then
|
||||||
|
-- Ask user for a filename
|
||||||
|
local filename = vim.fn.input('Save as: ', '', 'file')
|
||||||
|
if filename ~= '' then
|
||||||
|
vim.cmd('saveas ' .. vim.fn.fnameescape(filename))
|
||||||
|
else
|
||||||
|
print 'Save cancelled'
|
||||||
|
end
|
||||||
|
else
|
||||||
|
vim.cmd 'w'
|
||||||
|
end
|
||||||
|
end, { desc = 'Save buffer (prompt if new file)' })
|
||||||
|
|
||||||
|
-- Close current window (asks if buffer is unsaved)
|
||||||
|
vim.keymap.set('n', '<leader>q', function()
|
||||||
|
if vim.bo.modified then
|
||||||
|
local choice = vim.fn.input 'Buffer modified! Save (y), Discard (n), Cancel (any other key)? '
|
||||||
|
if choice:lower() == 'y' then
|
||||||
|
if vim.api.nvim_buf_get_name(0) == '' then
|
||||||
|
local filename = vim.fn.input('Save as: ', '', 'file')
|
||||||
|
if filename ~= '' then
|
||||||
|
vim.cmd('saveas ' .. vim.fn.fnameescape(filename))
|
||||||
|
vim.cmd 'q'
|
||||||
|
else
|
||||||
|
print 'Save cancelled'
|
||||||
|
end
|
||||||
|
else
|
||||||
|
vim.cmd 'wq'
|
||||||
|
end
|
||||||
|
elseif choice:lower() == 'n' then
|
||||||
|
vim.cmd 'q!'
|
||||||
|
else
|
||||||
|
print 'Quit cancelled'
|
||||||
|
end
|
||||||
|
else
|
||||||
|
vim.cmd 'q'
|
||||||
|
end
|
||||||
|
end, { desc = 'Close buffer (prompt if modified)' })
|
||||||
|
|
||||||
|
-- Save changes and close current window (asks for filename if new/unsaved)
|
||||||
|
vim.keymap.set('n', '<leader>qy', function()
|
||||||
|
if vim.api.nvim_buf_get_name(0) == '' then
|
||||||
|
-- Ask user for a filename
|
||||||
|
local filename = vim.fn.input('Save as: ', '', 'file')
|
||||||
|
if filename ~= '' then
|
||||||
|
vim.cmd('saveas ' .. vim.fn.fnameescape(filename))
|
||||||
|
vim.cmd 'q'
|
||||||
|
else
|
||||||
|
print 'Save cancelled'
|
||||||
|
end
|
||||||
|
else
|
||||||
|
vim.cmd 'wq'
|
||||||
|
end
|
||||||
|
end, { desc = 'Save & quit (prompt if new file)' })
|
||||||
|
|
||||||
|
-- Discard changes and Close current window
|
||||||
|
vim.keymap.set('n', '<leader>qn', '<Cmd>q!<CR>')
|
||||||
|
|
||||||
|
-- Switch below/right split windows
|
||||||
|
vim.keymap.set('n', '<leader><Tab>', '<C-W><C-W>')
|
||||||
|
|
||||||
|
-- Switch above/left split windows
|
||||||
|
vim.keymap.set('n', '<Tab>', '<C-W>W')
|
||||||
|
|
||||||
|
-- Select all
|
||||||
|
vim.keymap.set('n', '<leader>ll', 'ggVG')
|
||||||
|
|
||||||
|
-- Select all and copy to clipboard
|
||||||
|
vim.keymap.set('n', '<leader>lY', 'ggVG"+y')
|
||||||
|
|
||||||
|
-- Copy to clipboard a single line
|
||||||
|
vim.keymap.set('n', 'Y', '"+yy')
|
||||||
|
|
||||||
|
-- Copy to clipboard selected text in Visual mode
|
||||||
|
vim.keymap.set('v', 'Y', '"+y')
|
||||||
|
|
||||||
|
-- Paste from clipboard
|
||||||
|
vim.keymap.set('n', '<leader>P', '"+p')
|
||||||
|
|
||||||
|
-- Redo
|
||||||
|
vim.keymap.set('n', 'U', '<C-r>')
|
||||||
|
|
||||||
|
-- Smart Open current buffers for Telescope (switch to already open buffer)
|
||||||
|
local actions = require 'telescope.actions'
|
||||||
|
local action_state = require 'telescope.actions.state'
|
||||||
|
local builtin = require 'telescope.builtin'
|
||||||
|
|
||||||
|
local function smart_open_buffer()
|
||||||
|
builtin.buffers {
|
||||||
|
attach_mappings = function(_, map)
|
||||||
|
local function open_selected(prompt_bufnr)
|
||||||
|
local entry = action_state.get_selected_entry()
|
||||||
|
if not entry then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
actions.close(prompt_bufnr)
|
||||||
|
|
||||||
|
local bufname = vim.api.nvim_buf_get_name(entry.bufnr)
|
||||||
|
if bufname == '' then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check all windows in current tab
|
||||||
|
local current_tab = vim.api.nvim_get_current_tabpage()
|
||||||
|
for _, win in ipairs(vim.api.nvim_tabpage_list_wins(current_tab)) do
|
||||||
|
local buf = vim.api.nvim_win_get_buf(win)
|
||||||
|
if vim.api.nvim_buf_get_name(buf) == bufname then
|
||||||
|
vim.api.nvim_set_current_win(win)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check other tabs
|
||||||
|
for _, tab in ipairs(vim.api.nvim_list_tabpages()) do
|
||||||
|
if tab ~= current_tab then
|
||||||
|
for _, win in ipairs(vim.api.nvim_tabpage_list_wins(tab)) do
|
||||||
|
local buf = vim.api.nvim_win_get_buf(win)
|
||||||
|
if vim.api.nvim_buf_get_name(buf) == bufname then
|
||||||
|
-- Switch tab first, then window
|
||||||
|
vim.api.nvim_set_current_tabpage(tab)
|
||||||
|
vim.api.nvim_set_current_win(win)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Not open anywhere → open in current window
|
||||||
|
vim.cmd('buffer ' .. entry.bufnr)
|
||||||
|
end
|
||||||
|
|
||||||
|
map('i', '<CR>', open_selected)
|
||||||
|
map('n', '<CR>', open_selected)
|
||||||
|
return true
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
-- Map it to <leader><leader>
|
||||||
|
vim.keymap.set('n', '<leader><leader>', smart_open_buffer, { desc = 'Switch to Open Buffers' })
|
||||||
|
-- which-key, register it to show a description
|
||||||
|
require('which-key').register {
|
||||||
|
['<leader><leader>'] = { smart_open_buffer, 'Switch to Open Buffers' },
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Smart open a file path, reusing empty buffers or tabs if possible
|
||||||
|
local function smart_open_file(path)
|
||||||
|
if not path or path == '' then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
path = vim.fn.fnamemodify(path, ':p') -- make absolute
|
||||||
|
|
||||||
|
-- 1. If file is already open → jump to it
|
||||||
|
for _, tab in ipairs(vim.api.nvim_list_tabpages()) do
|
||||||
|
for _, win in ipairs(vim.api.nvim_tabpage_list_wins(tab)) do
|
||||||
|
local buf = vim.api.nvim_win_get_buf(win)
|
||||||
|
if vim.api.nvim_buf_get_name(buf) == path then
|
||||||
|
vim.api.nvim_set_current_tabpage(tab)
|
||||||
|
vim.api.nvim_set_current_win(win)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 2. If current tab has an empty "No Name" buffer → reuse it
|
||||||
|
for _, win in ipairs(vim.api.nvim_tabpage_list_wins(0)) do
|
||||||
|
local buf = vim.api.nvim_win_get_buf(win)
|
||||||
|
local name = vim.api.nvim_buf_get_name(buf)
|
||||||
|
local buftype = vim.api.nvim_buf_get_option(buf, 'buftype')
|
||||||
|
local modified = vim.api.nvim_buf_get_option(buf, 'modified')
|
||||||
|
if name == '' and buftype == '' and not modified then
|
||||||
|
vim.api.nvim_set_current_win(win)
|
||||||
|
vim.cmd('edit ' .. vim.fn.fnameescape(path))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 3. Otherwise → open in a new tab
|
||||||
|
vim.cmd('tabedit ' .. vim.fn.fnameescape(path))
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Remap gf to use smart_open_file
|
||||||
|
vim.keymap.set('n', 'gf', function()
|
||||||
|
local path = vim.fn.expand '<cfile>' -- get file under cursor
|
||||||
|
smart_open_file(path)
|
||||||
|
end, { desc = 'Smart gf: open file under cursor in new tab or reuse buffer' })
|
||||||
@@ -6,6 +6,11 @@
|
|||||||
return {
|
return {
|
||||||
'neovim/nvim-lspconfig',
|
'neovim/nvim-lspconfig',
|
||||||
config = function()
|
config = function()
|
||||||
|
-- Skip setting up LSP autoformatting if conform.nvim is being used
|
||||||
|
if package.loaded['conform'] then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
-- Switch for controlling whether you want autoformatting.
|
-- Switch for controlling whether you want autoformatting.
|
||||||
-- Use :KickstartFormatToggle to toggle autoformatting on or off
|
-- Use :KickstartFormatToggle to toggle autoformatting on or off
|
||||||
local format_is_enabled = true
|
local format_is_enabled = true
|
||||||
|
|||||||
Reference in New Issue
Block a user