feat: phase 2 migration
This commit is contained in:
parent
fc1fcc0c8c
commit
c0c1148fde
20 changed files with 663 additions and 2645 deletions
64
lua/plugins/core/completion.lua
Normal file
64
lua/plugins/core/completion.lua
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
-- ========================================================================
|
||||
-- COMPLETION PLUGIN
|
||||
-- ========================================================================
|
||||
-- Autocompletion engine with LSP integration
|
||||
-- - Blink.cmp: Fast completion engine
|
||||
-- - LuaSnip: Snippet engine
|
||||
-- - Lazydev: Lua LSP for Neovim config
|
||||
-- ========================================================================
|
||||
|
||||
return {
|
||||
-- Autocompletion
|
||||
{
|
||||
'saghen/blink.cmp',
|
||||
event = 'VimEnter',
|
||||
version = '1.*',
|
||||
dependencies = {
|
||||
{
|
||||
'L3MON4D3/LuaSnip',
|
||||
version = '2.*',
|
||||
build = (function()
|
||||
if vim.fn.has 'win32' == 1 or vim.fn.executable 'make' == 0 then
|
||||
return
|
||||
end
|
||||
return 'make install_jsregexp'
|
||||
end)(),
|
||||
opts = {},
|
||||
},
|
||||
'folke/lazydev.nvim',
|
||||
},
|
||||
---@module 'blink.cmp'
|
||||
---@type blink.cmp.Config
|
||||
opts = {
|
||||
keymap = {
|
||||
preset = 'enter',
|
||||
},
|
||||
appearance = {
|
||||
nerd_font_variant = 'mono',
|
||||
},
|
||||
completion = {
|
||||
documentation = { auto_show = false, auto_show_delay_ms = 500 },
|
||||
},
|
||||
sources = {
|
||||
default = { 'lsp', 'path', 'snippets', 'lazydev' },
|
||||
providers = {
|
||||
lazydev = { module = 'lazydev.integrations.blink', score_offset = 100 },
|
||||
},
|
||||
},
|
||||
snippets = { preset = 'luasnip' },
|
||||
fuzzy = { implementation = 'lua' },
|
||||
signature = { enabled = true },
|
||||
},
|
||||
},
|
||||
|
||||
-- Lazydev: Lua LSP for Neovim config
|
||||
{
|
||||
'folke/lazydev.nvim',
|
||||
ft = 'lua',
|
||||
opts = {
|
||||
library = {
|
||||
{ path = '${3rd}/luv/library', words = { 'vim%.uv' } },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
138
lua/plugins/core/editor.lua
Normal file
138
lua/plugins/core/editor.lua
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
-- ========================================================================
|
||||
-- CORE EDITOR PLUGINS
|
||||
-- ========================================================================
|
||||
-- Essential editing tools that are always loaded
|
||||
-- - Telescope: Fuzzy finder
|
||||
-- - Which-key: Keybinding helper
|
||||
-- - Neo-tree: File explorer
|
||||
-- - guess-indent: Auto-detect indentation
|
||||
-- ========================================================================
|
||||
|
||||
return {
|
||||
-- Detect tabstop and shiftwidth automatically
|
||||
'NMAC427/guess-indent.nvim',
|
||||
|
||||
-- Telescope: Fuzzy finder (files, LSP, etc)
|
||||
{
|
||||
'nvim-telescope/telescope.nvim',
|
||||
event = 'VimEnter',
|
||||
dependencies = {
|
||||
'nvim-lua/plenary.nvim',
|
||||
{
|
||||
'nvim-telescope/telescope-fzf-native.nvim',
|
||||
build = 'make',
|
||||
cond = function()
|
||||
return vim.fn.executable 'make' == 1
|
||||
end,
|
||||
},
|
||||
{ 'nvim-telescope/telescope-ui-select.nvim' },
|
||||
{ 'nvim-tree/nvim-web-devicons', enabled = vim.g.have_nerd_font },
|
||||
},
|
||||
config = function()
|
||||
require('telescope').setup {
|
||||
defaults = {
|
||||
mappings = {
|
||||
i = {
|
||||
['<C-j>'] = require('telescope.actions').move_selection_next,
|
||||
['<C-k>'] = require('telescope.actions').move_selection_previous,
|
||||
['<C-d>'] = require('telescope.actions').preview_scrolling_down,
|
||||
['<C-u>'] = require('telescope.actions').preview_scrolling_up,
|
||||
},
|
||||
},
|
||||
},
|
||||
extensions = {
|
||||
['ui-select'] = {
|
||||
require('telescope.themes').get_dropdown(),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
pcall(require('telescope').load_extension, 'fzf')
|
||||
pcall(require('telescope').load_extension, 'ui-select')
|
||||
|
||||
local builtin = require 'telescope.builtin'
|
||||
vim.keymap.set('n', '<leader>sh', builtin.help_tags, { desc = '[S]earch [H]elp' })
|
||||
vim.keymap.set('n', '<leader>sk', builtin.keymaps, { desc = '[S]earch [K]eymaps' })
|
||||
vim.keymap.set('n', '<leader>sf', builtin.find_files, { desc = '[S]earch [F]iles' })
|
||||
vim.keymap.set('n', '<leader>ss', builtin.builtin, { desc = '[S]earch [S]elect Telescope' })
|
||||
vim.keymap.set('n', '<leader>sw', builtin.grep_string, { desc = '[S]earch current [W]ord' })
|
||||
vim.keymap.set('n', '<leader>sg', builtin.live_grep, { desc = '[S]earch by [G]rep' })
|
||||
vim.keymap.set('n', '<leader>sd', builtin.diagnostics, { desc = '[S]earch [D]iagnostics' })
|
||||
vim.keymap.set('n', '<leader>sr', builtin.resume, { desc = '[S]earch [R]esume' })
|
||||
vim.keymap.set('n', '<leader>s.', builtin.oldfiles, { desc = '[S]earch Recent Files ("." for repeat)' })
|
||||
vim.keymap.set('n', '<leader><leader>', builtin.buffers, { desc = '[ ] Find existing buffers' })
|
||||
|
||||
vim.keymap.set('n', '<leader>/', function()
|
||||
builtin.current_buffer_fuzzy_find(require('telescope.themes').get_dropdown {
|
||||
winblend = 10,
|
||||
previewer = false,
|
||||
})
|
||||
end, { desc = '[/] Fuzzily search in current buffer' })
|
||||
|
||||
vim.keymap.set('n', '<leader>s/', function()
|
||||
builtin.live_grep {
|
||||
grep_open_files = true,
|
||||
prompt_title = 'Live Grep in Open Files',
|
||||
}
|
||||
end, { desc = '[S]earch [/] in Open Files' })
|
||||
|
||||
vim.keymap.set('n', '<leader>sn', function()
|
||||
builtin.find_files { cwd = vim.fn.stdpath 'config' }
|
||||
end, { desc = '[S]earch [N]eovim files' })
|
||||
end,
|
||||
},
|
||||
|
||||
-- Which-key: Shows pending keybinds
|
||||
{
|
||||
'folke/which-key.nvim',
|
||||
event = 'VimEnter',
|
||||
opts = {
|
||||
delay = 0,
|
||||
icons = {
|
||||
mappings = vim.g.have_nerd_font,
|
||||
keys = vim.g.have_nerd_font and {} or {
|
||||
Up = '<Up> ',
|
||||
Down = '<Down> ',
|
||||
Left = '<Left> ',
|
||||
Right = '<Right> ',
|
||||
C = '<C-…> ',
|
||||
M = '<M-…> ',
|
||||
D = '<D-…> ',
|
||||
S = '<S-…> ',
|
||||
CR = '<CR> ',
|
||||
Esc = '<Esc> ',
|
||||
ScrollWheelDown = '<ScrollWheelDown> ',
|
||||
ScrollWheelUp = '<ScrollWheelUp> ',
|
||||
NL = '<NL> ',
|
||||
BS = '<BS> ',
|
||||
Space = '<Space> ',
|
||||
Tab = '<Tab> ',
|
||||
F1 = '<F1>',
|
||||
F2 = '<F2>',
|
||||
F3 = '<F3>',
|
||||
F4 = '<F4>',
|
||||
F5 = '<F5>',
|
||||
F6 = '<F6>',
|
||||
F7 = '<F7>',
|
||||
F8 = '<F8>',
|
||||
F9 = '<F9>',
|
||||
F10 = '<F10>',
|
||||
F11 = '<F11>',
|
||||
F12 = '<F12>',
|
||||
},
|
||||
},
|
||||
spec = {
|
||||
{ '<leader>Q', group = '[Q]uit' },
|
||||
{ '<leader>c', group = '[c]ode' },
|
||||
{ '<leader>s', group = '[s]earch' },
|
||||
{ '<leader>S', group = '[S]ession' },
|
||||
{ '<leader>t', group = '[T]oggle' },
|
||||
{ '<leader>x', group = 'diagnostics/quickfi[x]' },
|
||||
{ '<leader>h', group = 'Git [H]unk', mode = { 'n', 'v' } },
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
-- Neo-tree: File explorer
|
||||
-- Imported from kickstart/plugins/neo-tree.lua
|
||||
}
|
||||
406
lua/plugins/core/extras.lua
Normal file
406
lua/plugins/core/extras.lua
Normal file
|
|
@ -0,0 +1,406 @@
|
|||
-- ========================================================================
|
||||
-- COMMON PLUGINS - Loaded for all filetypes/profiles
|
||||
-- ========================================================================
|
||||
--
|
||||
-- This file contains plugins that are always loaded regardless of what
|
||||
-- file type you're working with. These are your "core" plugins that
|
||||
-- provide functionality across all your language profiles.
|
||||
--
|
||||
-- Examples: file explorers, git tools, common UI elements, copilot, etc.
|
||||
--
|
||||
-- See the kickstart.nvim README for more information
|
||||
-- ========================================================================
|
||||
|
||||
return {
|
||||
-- ========================================================================
|
||||
-- FILE EXPLORER - Neo-tree
|
||||
-- ========================================================================
|
||||
-- Neo-tree provides a modern file explorer sidebar similar to VS Code.
|
||||
-- It's loaded for all profiles so you can browse files regardless of
|
||||
-- what language you're working with.
|
||||
--
|
||||
-- Keybindings:
|
||||
-- \ (backslash) - Toggle Neo-tree file explorer
|
||||
-- Within Neo-tree:
|
||||
-- a - Add file/folder
|
||||
-- d - Delete
|
||||
-- r - Rename
|
||||
-- x - Cut
|
||||
-- c - Copy
|
||||
-- p - Paste
|
||||
-- ? - Show help (see all keybindings)
|
||||
--
|
||||
-- Note: This references the existing neo-tree configuration from
|
||||
-- kickstart/plugins/neo-tree.lua. We're just ensuring it's loaded.
|
||||
-- ========================================================================
|
||||
-- {
|
||||
-- 'nvim-neo-tree/neo-tree.nvim',
|
||||
-- version = '*',
|
||||
-- dependencies = {
|
||||
-- 'nvim-lua/plenary.nvim',
|
||||
-- 'nvim-tree/nvim-web-devicons', -- not strictly required, but recommended
|
||||
-- 'MunifTanjim/nui.nvim',
|
||||
-- },
|
||||
-- cmd = 'Neotree', -- Lazy load on command
|
||||
-- keys = {
|
||||
-- { '\\', ':Neotree reveal<CR>', desc = 'NeoTree reveal', silent = true },
|
||||
-- },
|
||||
-- opts = {
|
||||
-- filesystem = {
|
||||
-- window = {
|
||||
-- mappings = {
|
||||
-- ['\\'] = 'close_window',
|
||||
-- },
|
||||
-- },
|
||||
-- follow_current_file = {
|
||||
-- enabled = true, -- Focus on the current file when opening
|
||||
-- },
|
||||
-- hijack_netrw_behavior = 'open_current', -- Use neo-tree instead of netrw
|
||||
-- },
|
||||
-- },
|
||||
-- },
|
||||
|
||||
-- ========================================================================
|
||||
-- GITHUB COPILOT - AI pair programming assistant
|
||||
-- ========================================================================
|
||||
-- GitHub Copilot provides AI-powered code completions and suggestions.
|
||||
-- Works across all file types and integrates with your completion engine.
|
||||
--
|
||||
-- Setup:
|
||||
-- 1. After installing, run :Copilot setup
|
||||
-- 2. Follow the authentication flow
|
||||
-- 3. You'll need an active GitHub Copilot subscription
|
||||
--
|
||||
-- Usage:
|
||||
-- - Copilot suggestions appear automatically as you type
|
||||
-- - Press Tab to accept a suggestion
|
||||
-- - Press Ctrl+] to see next suggestion
|
||||
-- - Press Ctrl+[ to see previous suggestion
|
||||
-- - :Copilot panel - Open completion panel with multiple suggestions
|
||||
--
|
||||
-- Commands:
|
||||
-- :Copilot setup - Authenticate with GitHub
|
||||
-- :Copilot status - Check authentication status
|
||||
-- :Copilot enable - Enable Copilot
|
||||
-- :Copilot disable - Disable Copilot
|
||||
-- ========================================================================
|
||||
{
|
||||
'github/copilot.vim',
|
||||
lazy = false, -- Load immediately on startup (not lazy-loaded)
|
||||
config = function()
|
||||
-- Copilot keybindings (optional customization)
|
||||
-- By default, Tab accepts suggestions, but this might conflict with completion
|
||||
-- Uncomment below to use Ctrl+J to accept instead:
|
||||
-- vim.keymap.set('i', '<C-J>', 'copilot#Accept("\\<CR>")', {
|
||||
-- expr = true,
|
||||
-- replace_keycodes = false,
|
||||
-- })
|
||||
-- vim.g.copilot_no_tab_map = true
|
||||
|
||||
-- Optional: Disable Copilot for certain filetypes
|
||||
-- vim.g.copilot_filetypes = {
|
||||
-- ['*'] = true,
|
||||
-- ['markdown'] = false,
|
||||
-- ['text'] = false,
|
||||
-- }
|
||||
end,
|
||||
},
|
||||
|
||||
-- ========================================================================
|
||||
-- SMOOTH SCROLLING & ANIMATIONS - mini.animate
|
||||
-- ========================================================================
|
||||
-- Provides smooth scrolling and cursor animations for a better visual experience.
|
||||
--
|
||||
-- Features:
|
||||
-- - Smooth scrolling (when using Ctrl+D, Ctrl+U, etc.)
|
||||
-- - Cursor path animation when jumping
|
||||
-- - Window resize animations
|
||||
-- - Window open/close animations
|
||||
--
|
||||
-- All animations are non-blocking and can be customized or disabled independently.
|
||||
-- ========================================================================
|
||||
{
|
||||
'echasnovski/mini.animate',
|
||||
event = 'VeryLazy', -- Load after UI is ready
|
||||
opts = function()
|
||||
-- Don't use animate when scrolling with the mouse
|
||||
local mouse_scrolled = false
|
||||
for _, scroll in ipairs({ 'Up', 'Down' }) do
|
||||
local key = '<ScrollWheel' .. scroll .. '>'
|
||||
vim.keymap.set({ '', 'i' }, key, function()
|
||||
mouse_scrolled = true
|
||||
return key
|
||||
end, { expr = true })
|
||||
end
|
||||
|
||||
local animate = require('mini.animate')
|
||||
return {
|
||||
-- Cursor path animation - shows path when cursor jumps
|
||||
cursor = {
|
||||
enable = true,
|
||||
timing = animate.gen_timing.linear({ duration = 100, unit = 'total' }),
|
||||
},
|
||||
|
||||
-- Smooth scrolling
|
||||
scroll = {
|
||||
enable = true,
|
||||
timing = animate.gen_timing.linear({ duration = 150, unit = 'total' }),
|
||||
subscroll = animate.gen_subscroll.equal({
|
||||
predicate = function(total_scroll)
|
||||
if mouse_scrolled then
|
||||
mouse_scrolled = false
|
||||
return false
|
||||
end
|
||||
return total_scroll > 1
|
||||
end,
|
||||
}),
|
||||
},
|
||||
|
||||
-- Window resize animation
|
||||
resize = {
|
||||
enable = true,
|
||||
timing = animate.gen_timing.linear({ duration = 50, unit = 'total' }),
|
||||
},
|
||||
|
||||
-- Window open/close animation
|
||||
open = {
|
||||
enable = false, -- Disabled by default as it can be distracting
|
||||
timing = animate.gen_timing.linear({ duration = 150, unit = 'total' }),
|
||||
},
|
||||
|
||||
close = {
|
||||
enable = false, -- Disabled by default
|
||||
timing = animate.gen_timing.linear({ duration = 150, unit = 'total' }),
|
||||
},
|
||||
}
|
||||
end,
|
||||
},
|
||||
|
||||
-- ========================================================================
|
||||
-- TROUBLE.NVIM - Beautiful diagnostics list (LazyVim-style)
|
||||
-- ========================================================================
|
||||
-- Provides a nice list view of diagnostics, quickfix, LSP references, etc.
|
||||
-- Shows errors inline in a dedicated panel like LazyVim/VS Code.
|
||||
-- Auto-opens when diagnostics are present to show errors in editor area.
|
||||
--
|
||||
-- Keymaps:
|
||||
-- <leader>xx - Toggle diagnostics list
|
||||
-- <leader>xX - Buffer diagnostics
|
||||
-- <leader>cs - Symbols list
|
||||
-- <leader>cl - LSP references
|
||||
-- <leader>xL - Location list
|
||||
-- <leader>xQ - Quickfix list
|
||||
-- [q / ]q - Previous/next item in trouble list
|
||||
-- ========================================================================
|
||||
{
|
||||
'folke/trouble.nvim',
|
||||
cmd = 'Trouble', -- Lazy load on command
|
||||
opts = {
|
||||
focus = false, -- Don't focus the window when opened (LazyVim behavior)
|
||||
auto_close = true, -- Auto close when no items
|
||||
auto_open = false, -- Don't auto open (we'll handle this with autocmd)
|
||||
warn_no_results = false,
|
||||
open_no_results = false,
|
||||
modes = {
|
||||
-- Configure the diagnostics mode to show in editor area
|
||||
diagnostics = {
|
||||
mode = 'diagnostics',
|
||||
preview = {
|
||||
type = 'split',
|
||||
relative = 'win',
|
||||
position = 'right',
|
||||
size = 0.3,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
keys = {
|
||||
{
|
||||
'<leader>xx',
|
||||
'<cmd>Trouble diagnostics toggle<cr>',
|
||||
desc = 'Diagnostics (Trouble)',
|
||||
},
|
||||
{
|
||||
'<leader>xX',
|
||||
'<cmd>Trouble diagnostics toggle filter.buf=0<cr>',
|
||||
desc = 'Buffer Diagnostics (Trouble)',
|
||||
},
|
||||
{
|
||||
'<leader>cs',
|
||||
'<cmd>Trouble symbols toggle focus=false<cr>',
|
||||
desc = 'Symbols (Trouble)',
|
||||
},
|
||||
{
|
||||
'<leader>cl',
|
||||
'<cmd>Trouble lsp toggle focus=false win.position=right<cr>',
|
||||
desc = 'LSP Definitions / references / ... (Trouble)',
|
||||
},
|
||||
{
|
||||
'<leader>xL',
|
||||
'<cmd>Trouble loclist toggle<cr>',
|
||||
desc = 'Location List (Trouble)',
|
||||
},
|
||||
{
|
||||
'<leader>xQ',
|
||||
'<cmd>Trouble qflist toggle<cr>',
|
||||
desc = 'Quickfix List (Trouble)',
|
||||
},
|
||||
{
|
||||
'[q',
|
||||
function()
|
||||
if require('trouble').is_open() then
|
||||
require('trouble').prev({ skip_groups = true, jump = true })
|
||||
else
|
||||
local ok, err = pcall(vim.cmd.cprev)
|
||||
if not ok then
|
||||
vim.notify(err, vim.log.levels.ERROR)
|
||||
end
|
||||
end
|
||||
end,
|
||||
desc = 'Previous Trouble/Quickfix Item',
|
||||
},
|
||||
{
|
||||
']q',
|
||||
function()
|
||||
if require('trouble').is_open() then
|
||||
require('trouble').next({ skip_groups = true, jump = true })
|
||||
else
|
||||
local ok, err = pcall(vim.cmd.cnext)
|
||||
if not ok then
|
||||
vim.notify(err, vim.log.levels.ERROR)
|
||||
end
|
||||
end
|
||||
end,
|
||||
desc = 'Next Trouble/Quickfix Item',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
-- ========================================================================
|
||||
-- NOICE.NVIM - Better UI for messages, cmdline, and notifications
|
||||
-- ========================================================================
|
||||
-- Provides a modern UI for command line, messages, and notifications (LazyVim-style).
|
||||
-- Makes the editor feel more polished with popup notifications and floating cmdline.
|
||||
--
|
||||
-- Features:
|
||||
-- - Floating command line
|
||||
-- - Modern notification system
|
||||
-- - Better message display
|
||||
-- - Signature help while typing
|
||||
--
|
||||
-- Note: This can be disabled if you prefer the classic Vim UI
|
||||
-- ========================================================================
|
||||
{
|
||||
'folke/noice.nvim',
|
||||
event = 'VeryLazy',
|
||||
dependencies = {
|
||||
'MunifTanjim/nui.nvim',
|
||||
-- Optional: If you want to use `nvim-notify` for notifications
|
||||
-- 'rcarriga/nvim-notify',
|
||||
},
|
||||
opts = {
|
||||
lsp = {
|
||||
-- Override markdown rendering so that **cmp** and other plugins use **Treesitter**
|
||||
override = {
|
||||
['vim.lsp.util.convert_input_to_markdown_lines'] = true,
|
||||
['vim.lsp.util.stylize_markdown'] = true,
|
||||
['cmp.entry.get_documentation'] = true,
|
||||
},
|
||||
},
|
||||
-- Presets for easier configuration
|
||||
presets = {
|
||||
bottom_search = true, -- Use a classic bottom cmdline for search
|
||||
command_palette = true, -- Position the cmdline and popupmenu together
|
||||
long_message_to_split = true, -- Long messages will be sent to a split
|
||||
inc_rename = false, -- Enables an input dialog for inc-rename.nvim
|
||||
lsp_doc_border = true, -- Add a border to hover docs and signature help
|
||||
},
|
||||
-- Routes configuration (optional customization)
|
||||
routes = {
|
||||
{
|
||||
filter = {
|
||||
event = 'msg_show',
|
||||
kind = '',
|
||||
find = 'written',
|
||||
},
|
||||
opts = { skip = true },
|
||||
},
|
||||
},
|
||||
},
|
||||
keys = {
|
||||
{
|
||||
'<leader>sn',
|
||||
'',
|
||||
desc = '+noice',
|
||||
},
|
||||
{
|
||||
'<leader>snl',
|
||||
function()
|
||||
require('noice').cmd('last')
|
||||
end,
|
||||
desc = 'Noice Last Message',
|
||||
},
|
||||
{
|
||||
'<leader>snh',
|
||||
function()
|
||||
require('noice').cmd('history')
|
||||
end,
|
||||
desc = 'Noice History',
|
||||
},
|
||||
{
|
||||
'<leader>sna',
|
||||
function()
|
||||
require('noice').cmd('all')
|
||||
end,
|
||||
desc = 'Noice All',
|
||||
},
|
||||
{
|
||||
'<leader>snd',
|
||||
function()
|
||||
require('noice').cmd('dismiss')
|
||||
end,
|
||||
desc = 'Dismiss All',
|
||||
},
|
||||
{
|
||||
'<c-f>',
|
||||
function()
|
||||
if not require('noice.lsp').scroll(4) then
|
||||
return '<c-f>'
|
||||
end
|
||||
end,
|
||||
silent = true,
|
||||
expr = true,
|
||||
desc = 'Scroll Forward',
|
||||
mode = { 'i', 'n', 's' },
|
||||
},
|
||||
{
|
||||
'<c-b>',
|
||||
function()
|
||||
if not require('noice.lsp').scroll(-4) then
|
||||
return '<c-b>'
|
||||
end
|
||||
end,
|
||||
silent = true,
|
||||
expr = true,
|
||||
desc = 'Scroll Backward',
|
||||
mode = { 'i', 'n', 's' },
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
-- ========================================================================
|
||||
-- ADDITIONAL COMMON PLUGINS
|
||||
-- ========================================================================
|
||||
-- You can add more common plugins here that should be available across
|
||||
-- all language profiles. Examples:
|
||||
--
|
||||
-- - Better terminal integration
|
||||
-- - Git integration enhancements (beyond gitsigns in init.lua)
|
||||
-- - Session management
|
||||
-- - Project management
|
||||
-- - Alternative completion sources
|
||||
-- - UI enhancements
|
||||
--
|
||||
-- Just add them to this return table following the same pattern as above.
|
||||
-- ========================================================================
|
||||
}
|
||||
22
lua/plugins/core/git.lua
Normal file
22
lua/plugins/core/git.lua
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
-- ========================================================================
|
||||
-- GIT INTEGRATION PLUGINS
|
||||
-- ========================================================================
|
||||
-- Git tools for version control
|
||||
-- - Gitsigns: Git decorations and utilities
|
||||
-- ========================================================================
|
||||
|
||||
return {
|
||||
-- Git signs in gutter and utilities for managing changes
|
||||
{
|
||||
'lewis6991/gitsigns.nvim',
|
||||
opts = {
|
||||
signs = {
|
||||
add = { text = '+' },
|
||||
change = { text = '~' },
|
||||
delete = { text = '_' },
|
||||
topdelete = { text = '‾' },
|
||||
changedelete = { text = '~' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
81
lua/plugins/core/neo-tree.lua
Normal file
81
lua/plugins/core/neo-tree.lua
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
-- Neo-tree is a Neovim plugin to browse the file system
|
||||
-- https://github.com/nvim-neo-tree/neo-tree.nvim
|
||||
|
||||
return {
|
||||
'nvim-neo-tree/neo-tree.nvim',
|
||||
version = '*',
|
||||
dependencies = {
|
||||
'nvim-lua/plenary.nvim',
|
||||
'nvim-tree/nvim-web-devicons', -- not strictly required, but recommended
|
||||
'MunifTanjim/nui.nvim',
|
||||
},
|
||||
lazy = false,
|
||||
keys = {
|
||||
{ '\\', ':Neotree reveal<CR>', desc = 'NeoTree reveal', silent = true },
|
||||
},
|
||||
opts = {
|
||||
-- Don't open Neo-tree on startup, only when toggled
|
||||
close_if_last_window = true, -- Close Neo-tree if it's the last window
|
||||
popup_border_style = 'rounded',
|
||||
enable_git_status = true,
|
||||
enable_diagnostics = true,
|
||||
|
||||
-- Default to filesystem view
|
||||
default_component_configs = {
|
||||
indent = {
|
||||
padding = 0,
|
||||
},
|
||||
},
|
||||
|
||||
-- Global window mappings (apply to all Neo-tree windows)
|
||||
window = {
|
||||
mappings = {
|
||||
-- Disable <Space> for toggle_node to allow <leader> (Space) to work
|
||||
['<space>'] = 'none',
|
||||
-- Use <CR> (Enter) to toggle nodes instead (already default, but making it explicit)
|
||||
['<cr>'] = 'toggle_node',
|
||||
-- Use 'za' (vim fold toggle) as alternative for toggle node
|
||||
['za'] = 'toggle_node',
|
||||
},
|
||||
},
|
||||
|
||||
filesystem = {
|
||||
-- Follow the current file in the tree
|
||||
follow_current_file = {
|
||||
enabled = true,
|
||||
leave_dirs_open = false,
|
||||
},
|
||||
-- Use system commands for file operations
|
||||
use_libuv_file_watcher = true,
|
||||
|
||||
window = {
|
||||
position = 'left',
|
||||
width = 30,
|
||||
mappings = {
|
||||
['\\'] = 'close_window',
|
||||
-- Make <leader>sf work the same in Neo-tree as in editor
|
||||
['<leader>sf'] = 'telescope_find',
|
||||
['<leader>sg'] = 'telescope_grep',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
-- Add custom commands for Telescope integration
|
||||
commands = {
|
||||
telescope_find = function(state)
|
||||
local node = state.tree:get_node()
|
||||
local path = node:get_id()
|
||||
require('telescope.builtin').find_files {
|
||||
cwd = vim.fn.isdirectory(path) == 1 and path or vim.fn.fnamemodify(path, ':h'),
|
||||
}
|
||||
end,
|
||||
telescope_grep = function(state)
|
||||
local node = state.tree:get_node()
|
||||
local path = node:get_id()
|
||||
require('telescope.builtin').live_grep {
|
||||
cwd = vim.fn.isdirectory(path) == 1 and path or vim.fn.fnamemodify(path, ':h'),
|
||||
}
|
||||
end,
|
||||
},
|
||||
},
|
||||
}
|
||||
105
lua/plugins/core/session.lua
Normal file
105
lua/plugins/core/session.lua
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
-- ========================================================================
|
||||
-- SESSION MANAGEMENT - Auto-save and restore your workspace
|
||||
-- ========================================================================
|
||||
--
|
||||
-- This plugin automatically saves your session (open files, window layout,
|
||||
-- buffers, etc.) when you quit Neovim and restores it when you reopen
|
||||
-- the same directory.
|
||||
--
|
||||
-- Features:
|
||||
-- - ✅ Auto-saves session on exit (automatically!)
|
||||
-- - ✅ Auto-restores session when you `cd` into a directory and run `nvim`
|
||||
-- - Saves per-directory (each project has its own session)
|
||||
-- - Saves open buffers, window splits, cursor positions, and more
|
||||
--
|
||||
-- IMPORTANT: Auto-restore works when you:
|
||||
-- 1. cd /path/to/your/project
|
||||
-- 2. nvim (without specifying files)
|
||||
--
|
||||
-- If you open a specific file (e.g., `nvim main.dart`), auto-restore is skipped.
|
||||
-- Use manual restore (<leader>Sr) if needed.
|
||||
--
|
||||
-- Keymaps:
|
||||
-- <leader>Ss - Save session manually
|
||||
-- <leader>Sr - Restore session manually (if auto-restore didn't trigger)
|
||||
-- <leader>Sd - Delete session for current directory
|
||||
-- <leader>Sf - Find/search all sessions (Telescope)
|
||||
--
|
||||
-- Quit keymaps (in init.lua, integrated with auto-session):
|
||||
-- <leader>Qa - Quit all and save session (most common)
|
||||
-- <leader>Qq - Force quit all without saving (no session save)
|
||||
-- <leader>Qw - Save all files, save session, then quit
|
||||
--
|
||||
-- WORKFLOW:
|
||||
-- 1. cd into your project directory
|
||||
-- 2. nvim (session auto-restores if it exists!)
|
||||
-- 3. Work on your project
|
||||
-- 4. Quit with <leader>Qa or just :qa (auto-saves!)
|
||||
-- 5. Next time: repeat from step 1 - your workspace is restored!
|
||||
--
|
||||
-- Sessions are saved in: ~/.local/share/nvim/sessions/
|
||||
-- ========================================================================
|
||||
|
||||
return {
|
||||
'rmagatti/auto-session',
|
||||
lazy = false, -- Load on startup to restore session
|
||||
opts = {
|
||||
-- Session save/restore options
|
||||
auto_session_enabled = true, -- Automatically save sessions on exit
|
||||
auto_restore_enabled = true, -- Automatically restore sessions on startup
|
||||
auto_save_enabled = true, -- Auto-save session on exit
|
||||
auto_session_suppress_dirs = { '~/', '~/Downloads', '/' }, -- Don't save sessions in these dirs
|
||||
auto_session_use_git_branch = false, -- One session per directory (not per git branch)
|
||||
|
||||
-- What to save in the session
|
||||
auto_session_enable_last_session = false, -- Don't restore last session if not in a project
|
||||
auto_session_create_enabled = true, -- Auto-create session on first save
|
||||
|
||||
-- Hooks to run before/after session save/restore
|
||||
pre_save_cmds = {
|
||||
'Neotree close', -- Close Neo-tree before saving session
|
||||
},
|
||||
post_restore_cmds = {
|
||||
-- You can add commands to run after restore here
|
||||
},
|
||||
|
||||
-- Session lens (Telescope integration for browsing sessions)
|
||||
session_lens = {
|
||||
load_on_setup = true,
|
||||
theme_conf = { border = true },
|
||||
previewer = false,
|
||||
},
|
||||
},
|
||||
keys = {
|
||||
-- Manual session control (Capital S to avoid conflict with search)
|
||||
{
|
||||
'<leader>Ss',
|
||||
'<cmd>AutoSession save<cr>',
|
||||
desc = '[S]ession: [S]ave',
|
||||
},
|
||||
{
|
||||
'<leader>Sr',
|
||||
'<cmd>AutoSession restore<cr>',
|
||||
desc = '[S]ession: [R]estore',
|
||||
},
|
||||
{
|
||||
'<leader>Sd',
|
||||
'<cmd>AutoSession delete<cr>',
|
||||
desc = '[S]ession: [D]elete',
|
||||
},
|
||||
{
|
||||
'<leader>Sf',
|
||||
'<cmd>AutoSession search<cr>',
|
||||
desc = '[S]ession: [F]ind/search',
|
||||
},
|
||||
},
|
||||
config = function(_, opts)
|
||||
require('auto-session').setup(opts)
|
||||
|
||||
-- Register with which-key
|
||||
require('which-key').add {
|
||||
{ '<leader>s', group = '[S]ession' },
|
||||
{ '<leader>Q', group = '[Q]uit' },
|
||||
}
|
||||
end,
|
||||
}
|
||||
93
lua/plugins/core/ui.lua
Normal file
93
lua/plugins/core/ui.lua
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
-- ========================================================================
|
||||
-- UI PLUGINS
|
||||
-- ========================================================================
|
||||
-- Visual enhancements and UI components
|
||||
-- - Colorscheme: tokyonight
|
||||
-- - Statusline: mini.statusline
|
||||
-- - Treesitter: Syntax highlighting
|
||||
-- - Mini modules: Textobjects, surround, pairs
|
||||
-- - Todo comments: Highlight TODOs/FIXMEs
|
||||
-- ========================================================================
|
||||
|
||||
return {
|
||||
-- Colorscheme
|
||||
{
|
||||
'folke/tokyonight.nvim',
|
||||
priority = 1000,
|
||||
config = function()
|
||||
require('tokyonight').setup {
|
||||
styles = {
|
||||
comments = { italic = false },
|
||||
},
|
||||
}
|
||||
vim.cmd.colorscheme 'tokyonight-night'
|
||||
end,
|
||||
},
|
||||
|
||||
-- Highlight todo, notes, etc in comments
|
||||
{
|
||||
'folke/todo-comments.nvim',
|
||||
event = 'VimEnter',
|
||||
dependencies = { 'nvim-lua/plenary.nvim' },
|
||||
opts = { signs = false },
|
||||
},
|
||||
|
||||
-- Mini.nvim collection
|
||||
{
|
||||
'echasnovski/mini.nvim',
|
||||
config = function()
|
||||
-- Better Around/Inside textobjects
|
||||
require('mini.ai').setup { n_lines = 500 }
|
||||
|
||||
-- Add/delete/replace surroundings (brackets, quotes, etc.)
|
||||
require('mini.surround').setup()
|
||||
|
||||
-- Autopairs - automatically close brackets, quotes, etc.
|
||||
require('mini.pairs').setup()
|
||||
|
||||
-- Simple and easy statusline
|
||||
local statusline = require 'mini.statusline'
|
||||
statusline.setup { use_icons = vim.g.have_nerd_font }
|
||||
|
||||
---@diagnostic disable-next-line: duplicate-set-field
|
||||
statusline.section_location = function()
|
||||
return '%2l:%-2v'
|
||||
end
|
||||
end,
|
||||
},
|
||||
|
||||
-- Treesitter: Syntax highlighting and code understanding
|
||||
{
|
||||
'nvim-treesitter/nvim-treesitter',
|
||||
build = ':TSUpdate',
|
||||
main = 'nvim-treesitter.configs',
|
||||
opts = {
|
||||
ensure_installed = {
|
||||
'bash',
|
||||
'c',
|
||||
'diff',
|
||||
'html',
|
||||
'lua',
|
||||
'luadoc',
|
||||
'markdown',
|
||||
'markdown_inline',
|
||||
'query',
|
||||
'vim',
|
||||
'vimdoc',
|
||||
'javascript',
|
||||
'typescript',
|
||||
'css',
|
||||
'json',
|
||||
},
|
||||
auto_install = true,
|
||||
highlight = {
|
||||
enable = true,
|
||||
additional_vim_regex_highlighting = { 'ruby' },
|
||||
},
|
||||
indent = { enable = true, disable = { 'ruby' } },
|
||||
fold = {
|
||||
enable = true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
469
lua/plugins/lang/flutter.lua
Normal file
469
lua/plugins/lang/flutter.lua
Normal file
|
|
@ -0,0 +1,469 @@
|
|||
-- ========================================================================
|
||||
-- FLUTTER/DART PROFILE - Language-specific plugins and LSP configuration
|
||||
-- ========================================================================
|
||||
--
|
||||
-- This file contains all Flutter and Dart-specific plugins and configurations.
|
||||
-- These plugins will ONLY load when you open a .dart file, keeping your
|
||||
-- startup time fast and avoiding conflicts with other languages.
|
||||
--
|
||||
-- Key features to configure here:
|
||||
-- - Flutter tools (hot reload, device management, widget inspector)
|
||||
-- - Dart LSP (dartls via flutter-tools)
|
||||
-- - Dart-specific formatters and linters
|
||||
-- - Flutter-specific keymaps (e.g., <leader>fr for Flutter Run)
|
||||
--
|
||||
-- Usage: Just open a .dart file and these plugins will automatically load!
|
||||
-- ========================================================================
|
||||
|
||||
return {
|
||||
-- ========================================================================
|
||||
-- NVIM-DAP - Debug Adapter Protocol for Flutter debugging
|
||||
-- ========================================================================
|
||||
-- Load DAP when opening Dart files to enable breakpoint debugging
|
||||
{
|
||||
'mfussenegger/nvim-dap',
|
||||
ft = 'dart',
|
||||
dependencies = {
|
||||
'rcarriga/nvim-dap-ui',
|
||||
'nvim-neotest/nvim-nio',
|
||||
},
|
||||
},
|
||||
|
||||
-- ========================================================================
|
||||
-- FLUTTER TOOLS - Complete Flutter development environment
|
||||
-- ========================================================================
|
||||
-- Provides Flutter-specific features like hot reload, device management,
|
||||
-- widget inspector, and integrates the Dart LSP server.
|
||||
--
|
||||
-- Flutter-specific keymaps (available in .dart files):
|
||||
-- <leader>fr - Flutter Run (start app)
|
||||
-- <leader>fq - Flutter Quit (stop app)
|
||||
-- <leader>fR - Flutter Hot Restart
|
||||
-- <leader>fd - Flutter Devices (show connected devices)
|
||||
-- <leader>fe - Flutter Emulators (launch emulator)
|
||||
-- <leader>fo - Flutter Outline (toggle outline/widget tree)
|
||||
-- <leader>fc - Flutter Copy Profile URL (for DevTools)
|
||||
--
|
||||
-- Debug keymaps:
|
||||
-- <F5> - Start/Continue debugging
|
||||
-- <F10> - Step over
|
||||
-- <F11> - Step into
|
||||
-- <F12> - Step out
|
||||
-- <leader>db - Toggle breakpoint
|
||||
-- <leader>dB - Set conditional breakpoint
|
||||
-- <leader>dc - Continue
|
||||
-- <leader>dt - Terminate debugging
|
||||
-- ========================================================================
|
||||
{
|
||||
'nvim-flutter/flutter-tools.nvim',
|
||||
ft = 'dart', -- Only load when opening Dart files
|
||||
dependencies = {
|
||||
'nvim-lua/plenary.nvim',
|
||||
'stevearc/dressing.nvim', -- Optional: better UI for Flutter commands
|
||||
'mfussenegger/nvim-dap',
|
||||
'rcarriga/nvim-dap-ui',
|
||||
'nvim-neotest/nvim-nio',
|
||||
},
|
||||
config = function()
|
||||
-- Get shared LSP capabilities from blink.cmp
|
||||
local capabilities = require('blink.cmp').get_lsp_capabilities()
|
||||
|
||||
require('flutter-tools').setup {
|
||||
-- UI configuration
|
||||
ui = {
|
||||
border = 'rounded', -- border type for floating windows
|
||||
notification_style = 'native', -- 'native' or 'plugin' (native uses vim.notify)
|
||||
},
|
||||
|
||||
-- Flutter SDK path (usually auto-detected, but you can specify if needed)
|
||||
-- flutter_path = '/path/to/flutter/bin/flutter',
|
||||
-- flutter_lookup_cmd = nil, -- example: "dirname $(which flutter)" or "asdf where flutter"
|
||||
|
||||
-- FVM support - takes priority over path, uses <workspace>/.fvm/flutter_sdk if enabled
|
||||
fvm = false,
|
||||
|
||||
-- Root patterns to find the root of your flutter project
|
||||
root_patterns = { '.git', 'pubspec.yaml' },
|
||||
|
||||
-- Uncomment to set a default device (get ID from `flutter devices`)
|
||||
-- device = {
|
||||
-- id = 'chrome', -- or 'macos', 'emulator-5554', etc.
|
||||
-- },
|
||||
|
||||
lsp = {
|
||||
capabilities = capabilities,
|
||||
|
||||
-- Suppress didChange errors during snippet expansion
|
||||
on_attach = function(client, bufnr)
|
||||
-- Reduce didChange notification frequency to prevent errors with snippets
|
||||
client.server_capabilities.textDocumentSync = vim.tbl_deep_extend('force', client.server_capabilities.textDocumentSync or {}, {
|
||||
change = 2, -- 2 = Incremental (less prone to errors than full sync)
|
||||
})
|
||||
|
||||
-- Filter out didChange error notifications (they're harmless during snippet expansion)
|
||||
-- We'll use an autocmd to do this after noice.nvim is loaded
|
||||
vim.api.nvim_create_autocmd('User', {
|
||||
pattern = 'VeryLazy',
|
||||
once = true,
|
||||
callback = function()
|
||||
local notify = vim.notify
|
||||
vim.notify = function(msg, level, opts)
|
||||
if type(msg) == 'string' and msg:match('textDocument/didChange') then
|
||||
return -- Suppress this specific error
|
||||
end
|
||||
notify(msg, level, opts)
|
||||
end
|
||||
end,
|
||||
})
|
||||
end,
|
||||
|
||||
-- Color preview for dart variables (Colors.red, Color(0xFF...), etc.)
|
||||
-- This shows the actual Material Design colors inline!
|
||||
color = {
|
||||
enabled = true, -- whether or not to highlight color variables at all, only supported on flutter >= 2.10
|
||||
background = true, -- highlight the background
|
||||
background_color = nil, -- required, when background is transparent (i.e. background_color = { r = 19, g = 17, b = 24},)
|
||||
foreground = false, -- highlight the foreground
|
||||
virtual_text = true, -- show the highlight using virtual text
|
||||
virtual_text_str = '■', -- the virtual text character to highlight
|
||||
},
|
||||
-- Settings passed to the Dart LSP
|
||||
settings = {
|
||||
-- Show TODOs in the problems pane
|
||||
showTodos = true,
|
||||
-- Completion settings
|
||||
completeFunctionCalls = true,
|
||||
-- Enable/disable specific lints
|
||||
-- analysisExcludedFolders = {},
|
||||
renameFilesWithClasses = 'prompt', -- "always" or "prompt"
|
||||
enableSnippets = true,
|
||||
updateImportsOnRename = true, -- Whether to update imports and other directives when files are renamed
|
||||
},
|
||||
},
|
||||
|
||||
-- Flutter-specific settings
|
||||
decorations = {
|
||||
statusline = {
|
||||
-- Set to true to show Flutter app info in statusline
|
||||
app_version = false,
|
||||
device = true, -- Show device name
|
||||
},
|
||||
},
|
||||
|
||||
widget_guides = {
|
||||
enabled = true, -- Show visual guides for widget nesting
|
||||
},
|
||||
|
||||
closing_tags = {
|
||||
highlight = 'Comment', -- Highlight color for closing tags
|
||||
prefix = '// ', -- Text to show before closing tag
|
||||
enabled = true, -- Show closing tags for widgets
|
||||
},
|
||||
|
||||
dev_log = {
|
||||
enabled = true,
|
||||
notify_errors = false, -- Don't show error notifications for log buffer issues
|
||||
open_cmd = 'tabedit', -- Open logs in a new tab
|
||||
focus_on_open = false, -- Don't auto-focus the log window
|
||||
},
|
||||
|
||||
dev_tools = {
|
||||
autostart = false, -- autostart devtools server if not detected
|
||||
auto_open_browser = false, -- Automatically opens devtools in the browser
|
||||
},
|
||||
|
||||
outline = {
|
||||
open_cmd = '30vnew', -- command to use to open the outline buffer
|
||||
auto_open = false, -- if true this will open the outline automatically when it is first populated
|
||||
},
|
||||
|
||||
debugger = {
|
||||
enabled = true, -- Enable Flutter debugger integration
|
||||
run_via_dap = true, -- Use DAP for debugging
|
||||
-- if empty dap will not stop on any exceptions, otherwise it will stop on those specified
|
||||
-- see |:help dap.set_exception_breakpoints()| for more info
|
||||
exception_breakpoints = {},
|
||||
-- Whether to call toString() on objects in debug views like hovers and the variables list.
|
||||
-- Invoking toString() has a performance cost and may introduce side-effects,
|
||||
-- although users may expected this functionality. null is treated like false.
|
||||
evaluate_to_string_in_debug_views = true,
|
||||
-- Flutter tools will automatically register DAP configurations
|
||||
-- No need to manually configure launch.json
|
||||
},
|
||||
}
|
||||
|
||||
-- ========================================================================
|
||||
-- DAP UI SETUP - Beautiful debugging interface
|
||||
-- ========================================================================
|
||||
local dap, dapui = require 'dap', require 'dapui'
|
||||
|
||||
-- Configure DAP UI to open in tabs for better half-width screen support
|
||||
dapui.setup {
|
||||
icons = { expanded = '▾', collapsed = '▸', current_frame = '*' },
|
||||
controls = {
|
||||
icons = {
|
||||
pause = '⏸',
|
||||
play = '▶',
|
||||
step_into = '⏎',
|
||||
step_over = '⏭',
|
||||
step_out = '⏮',
|
||||
step_back = 'b',
|
||||
run_last = '▶▶',
|
||||
terminate = '⏹',
|
||||
disconnect = '⏏',
|
||||
},
|
||||
},
|
||||
-- Open each element in a new tab instead of side panels
|
||||
-- This prevents layout issues on small/half-width screens
|
||||
layouts = {
|
||||
{
|
||||
elements = {
|
||||
{ id = 'scopes', size = 0.25 },
|
||||
{ id = 'breakpoints', size = 0.25 },
|
||||
{ id = 'stacks', size = 0.25 },
|
||||
{ id = 'watches', size = 0.25 },
|
||||
},
|
||||
size = 40,
|
||||
position = 'right',
|
||||
},
|
||||
{
|
||||
elements = {
|
||||
{ id = 'repl', size = 0.5 },
|
||||
{ id = 'console', size = 0.5 },
|
||||
},
|
||||
size = 10,
|
||||
position = 'bottom',
|
||||
},
|
||||
},
|
||||
-- Override element window commands to open in tabs
|
||||
element_mappings = {},
|
||||
windows = { indent = 1 },
|
||||
}
|
||||
|
||||
-- Custom function to open DAP UI elements in tabs
|
||||
local function open_dapui_in_tabs()
|
||||
-- Save current tab to return to it
|
||||
local current_tab = vim.fn.tabpagenr()
|
||||
|
||||
-- Create new tab with a named buffer for debug views
|
||||
vim.cmd 'tabnew'
|
||||
local debug_buf = vim.api.nvim_create_buf(false, true)
|
||||
vim.api.nvim_buf_set_name(debug_buf, 'Flutter Debug')
|
||||
vim.api.nvim_set_current_buf(debug_buf)
|
||||
|
||||
-- Open DAP UI in this tab
|
||||
dapui.open()
|
||||
|
||||
-- Return to original tab so user continues coding there
|
||||
vim.cmd('tabnext ' .. current_tab)
|
||||
end
|
||||
|
||||
-- Custom function to close DAP UI tabs
|
||||
local function close_dapui_tabs()
|
||||
dapui.close()
|
||||
|
||||
-- Find and close the Flutter Debug tab
|
||||
local current_tab = vim.fn.tabpagenr()
|
||||
for i = 1, vim.fn.tabpagenr '$' do
|
||||
vim.cmd('tabnext ' .. i)
|
||||
local bufname = vim.api.nvim_buf_get_name(0)
|
||||
if bufname:match('Flutter Debug') then
|
||||
vim.cmd 'tabclose'
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
-- Return to original tab
|
||||
if vim.fn.tabpagenr '$' >= current_tab then
|
||||
vim.cmd('tabnext ' .. current_tab)
|
||||
end
|
||||
end
|
||||
|
||||
-- Automatically open/close DAP UI in tabs
|
||||
dap.listeners.after.event_initialized['dapui_config'] = open_dapui_in_tabs
|
||||
dap.listeners.before.event_terminated['dapui_config'] = close_dapui_tabs
|
||||
dap.listeners.before.event_exited['dapui_config'] = close_dapui_tabs
|
||||
|
||||
-- Fix for Flutter Tools log buffer - make it non-saveable
|
||||
-- This prevents Vim from asking to save changes to the log file on exit
|
||||
vim.api.nvim_create_autocmd({ 'BufEnter', 'BufWinEnter' }, {
|
||||
pattern = '*',
|
||||
callback = function(args)
|
||||
local bufname = vim.api.nvim_buf_get_name(args.buf)
|
||||
-- Check if this is a Flutter log buffer
|
||||
if bufname:match('__FLUTTER_DEV_LOG__') or vim.bo[args.buf].filetype == 'log' then
|
||||
vim.bo[args.buf].modifiable = true -- Allow Flutter to write to it
|
||||
vim.bo[args.buf].modified = false -- Mark as unmodified
|
||||
vim.bo[args.buf].buftype = 'nofile' -- Don't associate with a file (prevents save prompt)
|
||||
vim.bo[args.buf].swapfile = false -- Don't create swap file
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
-- Keep log buffer marked as unmodified whenever it changes
|
||||
-- This prevents the "save changes?" prompt on exit
|
||||
vim.api.nvim_create_autocmd('BufModifiedSet', {
|
||||
pattern = '*',
|
||||
callback = function(args)
|
||||
local bufname = vim.api.nvim_buf_get_name(args.buf)
|
||||
if bufname:match('__FLUTTER_DEV_LOG__') then
|
||||
vim.bo[args.buf].modifiable = true
|
||||
vim.bo[args.buf].modified = false -- Keep it marked as unmodified
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
-- ========================================================================
|
||||
-- ENABLE TREESITTER FOLDING FOR DART FILES
|
||||
-- ========================================================================
|
||||
-- Set fold method to use Treesitter for Flutter widgets
|
||||
-- Using multiple autocmds to ensure it sticks (some plugins override it)
|
||||
local fold_augroup = vim.api.nvim_create_augroup('DartFolding', { clear = true })
|
||||
|
||||
vim.api.nvim_create_autocmd({ 'BufRead', 'BufEnter', 'BufWinEnter' }, {
|
||||
group = fold_augroup,
|
||||
pattern = '*.dart',
|
||||
callback = function()
|
||||
vim.opt_local.foldmethod = 'expr'
|
||||
vim.opt_local.foldexpr = 'nvim_treesitter#foldexpr()'
|
||||
vim.opt_local.foldlevel = 99 -- High level = everything unfolded
|
||||
vim.opt_local.foldlevelstart = 99 -- Start with everything unfolded
|
||||
|
||||
-- Hide fold column (no extra column, folds still work!)
|
||||
vim.opt_local.foldcolumn = '0'
|
||||
|
||||
-- Minimal fold display (VS Code style - just shows first line)
|
||||
vim.opt_local.foldtext = ''
|
||||
end,
|
||||
})
|
||||
|
||||
-- Also set after LSP attaches (flutter-tools might reset it)
|
||||
vim.api.nvim_create_autocmd('LspAttach', {
|
||||
group = fold_augroup,
|
||||
callback = function(args)
|
||||
local client = vim.lsp.get_client_by_id(args.data.client_id)
|
||||
if client and client.name == 'dartls' then
|
||||
vim.opt_local.foldmethod = 'expr'
|
||||
vim.opt_local.foldexpr = 'nvim_treesitter#foldexpr()'
|
||||
vim.opt_local.foldlevel = 99 -- Everything unfolded
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
-- ========================================================================
|
||||
-- FLUTTER-SPECIFIC KEYMAPS
|
||||
-- ========================================================================
|
||||
-- These keymaps are only available when editing Dart files
|
||||
-- They provide quick access to common Flutter commands
|
||||
-- ========================================================================
|
||||
vim.api.nvim_create_autocmd('FileType', {
|
||||
pattern = 'dart',
|
||||
callback = function()
|
||||
local opts = { buffer = true, silent = true }
|
||||
|
||||
-- ========================================================================
|
||||
-- ENABLE TREESITTER FOLDING FOR DART FILES
|
||||
-- ========================================================================
|
||||
-- Set fold method to use Treesitter for Flutter widgets
|
||||
vim.opt_local.foldmethod = 'expr'
|
||||
vim.opt_local.foldexpr = 'nvim_treesitter#foldexpr()'
|
||||
vim.opt_local.foldenable = false -- Start with folds open
|
||||
vim.opt_local.foldlevel = 99
|
||||
vim.opt_local.foldlevelstart = 99
|
||||
|
||||
-- Flutter run/quit
|
||||
-- WORKFLOW:
|
||||
-- 1. First time: <leader>fd to select device
|
||||
-- 2. Then: <leader>fr to run (uses selected device)
|
||||
-- 3. Subsequent runs: <leader>fr uses same device
|
||||
vim.keymap.set('n', '<leader>fr', '<cmd>FlutterRun<cr>', vim.tbl_extend('force', opts, { desc = '[F]lutter [R]un' }))
|
||||
vim.keymap.set('n', '<leader>fR', '<cmd>FlutterRestart<cr>', vim.tbl_extend('force', opts, { desc = '[F]lutter Hot [R]estart' }))
|
||||
vim.keymap.set('n', '<leader>fq', '<cmd>FlutterQuit<cr>', vim.tbl_extend('force', opts, { desc = '[F]lutter [Q]uit' }))
|
||||
|
||||
-- Code Actions (Cmd+. equivalent) - wrap, remove, extract widgets, etc.
|
||||
vim.keymap.set('n', '<leader>.', vim.lsp.buf.code_action, vim.tbl_extend('force', opts, { desc = 'Code Actions (Cmd+.)' }))
|
||||
vim.keymap.set('v', '<leader>.', vim.lsp.buf.code_action, vim.tbl_extend('force', opts, { desc = 'Code Actions (Cmd+.)' }))
|
||||
-- Alternative: use the default LSP keymap
|
||||
vim.keymap.set('n', 'gra', vim.lsp.buf.code_action, vim.tbl_extend('force', opts, { desc = '[G]oto Code [A]ction' }))
|
||||
vim.keymap.set('v', 'gra', vim.lsp.buf.code_action, vim.tbl_extend('force', opts, { desc = '[G]oto Code [A]ction' }))
|
||||
|
||||
-- Device management
|
||||
-- Use <leader>fd to see/select devices FIRST, then <leader>fr will use that device
|
||||
vim.keymap.set('n', '<leader>fd', '<cmd>FlutterDevices<cr>', vim.tbl_extend('force', opts, { desc = '[F]lutter [D]evices (select)' }))
|
||||
vim.keymap.set('n', '<leader>fe', '<cmd>FlutterEmulators<cr>', vim.tbl_extend('force', opts, { desc = '[F]lutter [E]mulators' }))
|
||||
|
||||
-- Dev tools
|
||||
vim.keymap.set('n', '<leader>fo', '<cmd>FlutterOutlineToggle<cr>', vim.tbl_extend('force', opts, { desc = '[F]lutter [O]utline Toggle' }))
|
||||
vim.keymap.set(
|
||||
'n',
|
||||
'<leader>fc',
|
||||
'<cmd>FlutterCopyProfilerUrl<cr>',
|
||||
vim.tbl_extend('force', opts, { desc = '[F]lutter [C]opy Profiler URL' })
|
||||
)
|
||||
vim.keymap.set('n', '<leader>fl', '<cmd>FlutterLspRestart<cr>', vim.tbl_extend('force', opts, { desc = '[F]lutter [L]SP Restart' }))
|
||||
|
||||
-- ========================================================================
|
||||
-- DEBUG KEYMAPS - Available only in Dart files
|
||||
-- ========================================================================
|
||||
-- Function key shortcuts (standard debugging)
|
||||
vim.keymap.set('n', '<F5>', function()
|
||||
require('dap').continue()
|
||||
end, vim.tbl_extend('force', opts, { desc = 'Debug: Start/Continue' }))
|
||||
|
||||
vim.keymap.set('n', '<F10>', function()
|
||||
require('dap').step_over()
|
||||
end, vim.tbl_extend('force', opts, { desc = 'Debug: Step Over' }))
|
||||
|
||||
vim.keymap.set('n', '<F11>', function()
|
||||
require('dap').step_into()
|
||||
end, vim.tbl_extend('force', opts, { desc = 'Debug: Step Into' }))
|
||||
|
||||
vim.keymap.set('n', '<F12>', function()
|
||||
require('dap').step_out()
|
||||
end, vim.tbl_extend('force', opts, { desc = 'Debug: Step Out' }))
|
||||
|
||||
-- Leader-based debug commands
|
||||
vim.keymap.set('n', '<leader>db', function()
|
||||
require('dap').toggle_breakpoint()
|
||||
end, vim.tbl_extend('force', opts, { desc = '[D]ebug: Toggle [B]reakpoint' }))
|
||||
|
||||
vim.keymap.set('n', '<leader>dB', function()
|
||||
require('dap').set_breakpoint(vim.fn.input 'Breakpoint condition: ')
|
||||
end, vim.tbl_extend('force', opts, { desc = '[D]ebug: Set Conditional [B]reakpoint' }))
|
||||
|
||||
vim.keymap.set('n', '<leader>dc', function()
|
||||
require('dap').continue()
|
||||
end, vim.tbl_extend('force', opts, { desc = '[D]ebug: [C]ontinue' }))
|
||||
|
||||
vim.keymap.set('n', '<leader>dt', function()
|
||||
require('dap').terminate()
|
||||
end, vim.tbl_extend('force', opts, { desc = '[D]ebug: [T]erminate' }))
|
||||
|
||||
vim.keymap.set('n', '<leader>du', function()
|
||||
require('dapui').toggle()
|
||||
end, vim.tbl_extend('force', opts, { desc = '[D]ebug: Toggle [U]I' }))
|
||||
|
||||
-- Register groups with which-key
|
||||
require('which-key').add {
|
||||
{ '<leader>f', group = '[F]lutter', mode = 'n' },
|
||||
{ '<leader>d', group = '[D]ebug', mode = 'n' },
|
||||
}
|
||||
end,
|
||||
})
|
||||
end,
|
||||
},
|
||||
|
||||
-- ========================================================================
|
||||
-- DART TREESITTER - Ensure dart parser is installed for proper folding
|
||||
-- ========================================================================
|
||||
{
|
||||
'nvim-treesitter/nvim-treesitter',
|
||||
ft = 'dart',
|
||||
opts = function(_, opts)
|
||||
-- Ensure Dart parser is installed
|
||||
opts.ensure_installed = opts.ensure_installed or {}
|
||||
vim.list_extend(opts.ensure_installed, { 'dart' })
|
||||
return opts
|
||||
end,
|
||||
},
|
||||
}
|
||||
176
lua/plugins/lang/python.lua
Normal file
176
lua/plugins/lang/python.lua
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
-- ========================================================================
|
||||
-- PYTHON PROFILE - Language-specific plugins and LSP configuration
|
||||
-- ========================================================================
|
||||
--
|
||||
-- This file contains all Python-specific plugins and configurations.
|
||||
-- These plugins will ONLY load when you open a .py file, keeping your
|
||||
-- startup time fast and avoiding conflicts with other languages.
|
||||
--
|
||||
-- Key features to configure here:
|
||||
-- - Python LSP (pyright or pylsp)
|
||||
-- - Python formatters (black, ruff, isort, etc.)
|
||||
-- - Python linters and type checkers
|
||||
-- - Debugger integration (debugpy)
|
||||
-- - Testing tools (pytest)
|
||||
-- - Virtual environment detection
|
||||
-- - Python-specific keymaps
|
||||
--
|
||||
-- Usage: Just open a .py file and these plugins will automatically load!
|
||||
-- ========================================================================
|
||||
|
||||
return {
|
||||
-- ========================================================================
|
||||
-- MASON TOOL INSTALLER - Install Python tools on-demand
|
||||
-- ========================================================================
|
||||
{
|
||||
'WhoIsSethDaniel/mason-tool-installer.nvim',
|
||||
ft = 'python',
|
||||
dependencies = { 'williamboman/mason.nvim' },
|
||||
config = function()
|
||||
-- Wait for Mason registry to be ready
|
||||
local function install_tools()
|
||||
local registry_ok, registry = pcall(require, 'mason-registry')
|
||||
if not registry_ok then
|
||||
vim.notify('Mason registry not ready, retrying...', vim.log.levels.WARN)
|
||||
vim.defer_fn(install_tools, 100)
|
||||
return
|
||||
end
|
||||
|
||||
-- Refresh registry and install tools
|
||||
registry.refresh(function()
|
||||
local tools = { 'pyright', 'ruff' }
|
||||
for _, tool in ipairs(tools) do
|
||||
local ok, package = pcall(registry.get_package, tool)
|
||||
if ok and not package:is_installed() then
|
||||
vim.notify('Installing ' .. tool .. '...', vim.log.levels.INFO)
|
||||
package:install()
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
-- Start installation after a short delay
|
||||
vim.defer_fn(install_tools, 200)
|
||||
end,
|
||||
},
|
||||
|
||||
-- ========================================================================
|
||||
-- PYTHON LSP - Language Server Protocol for Python
|
||||
-- ========================================================================
|
||||
-- Pyright LSP is started via autocmd when opening .py files
|
||||
-- This approach works because we set it up after LSP infrastructure loads
|
||||
-- ========================================================================
|
||||
{
|
||||
'neovim/nvim-lspconfig',
|
||||
ft = 'python',
|
||||
config = function()
|
||||
-- Python LSP - starts when opening .py files
|
||||
vim.api.nvim_create_autocmd('FileType', {
|
||||
pattern = 'python',
|
||||
once = false,
|
||||
callback = function(args)
|
||||
-- Check if pyright is already attached
|
||||
local clients = vim.lsp.get_clients { bufnr = args.buf, name = 'pyright' }
|
||||
if #clients > 0 then
|
||||
return
|
||||
end
|
||||
|
||||
-- Get capabilities from blink.cmp
|
||||
local capabilities = require('blink.cmp').get_lsp_capabilities()
|
||||
|
||||
local root_dir = vim.fs.root(args.buf, {
|
||||
'pyproject.toml',
|
||||
'setup.py',
|
||||
'setup.cfg',
|
||||
'requirements.txt',
|
||||
'Pipfile',
|
||||
'pyrightconfig.json',
|
||||
'.git',
|
||||
})
|
||||
|
||||
-- Find Python interpreter (prioritize virtual environments)
|
||||
local function find_python()
|
||||
if not root_dir then
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Check common venv locations relative to project root
|
||||
local venv_paths = {
|
||||
root_dir .. '/.venv/bin/python',
|
||||
root_dir .. '/venv/bin/python',
|
||||
root_dir .. '/.env/bin/python',
|
||||
root_dir .. '/env/bin/python',
|
||||
}
|
||||
|
||||
for _, path in ipairs(venv_paths) do
|
||||
if vim.fn.executable(path) == 1 then
|
||||
return path
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
local python_path = find_python()
|
||||
|
||||
vim.lsp.start {
|
||||
name = 'pyright',
|
||||
cmd = { vim.fn.stdpath 'data' .. '/mason/bin/pyright-langserver', '--stdio' },
|
||||
root_dir = root_dir or vim.fn.getcwd(),
|
||||
capabilities = capabilities,
|
||||
settings = {
|
||||
python = {
|
||||
pythonPath = python_path,
|
||||
analysis = {
|
||||
typeCheckingMode = 'basic',
|
||||
autoImportCompletions = true,
|
||||
autoSearchPaths = true,
|
||||
useLibraryCodeForTypes = true,
|
||||
diagnosticMode = 'openFilesOnly',
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
end,
|
||||
})
|
||||
end,
|
||||
},
|
||||
|
||||
|
||||
-- ========================================================================
|
||||
-- PYTHON FORMATTERS - Auto-format Python code
|
||||
-- ========================================================================
|
||||
-- Uses Ruff for fast formatting and import organization
|
||||
-- Ruff provides Black-compatible formatting + import sorting in one tool
|
||||
-- ========================================================================
|
||||
{
|
||||
'stevearc/conform.nvim',
|
||||
ft = 'python',
|
||||
opts = function(_, opts)
|
||||
-- Extend the existing formatters_by_ft table
|
||||
opts.formatters_by_ft = opts.formatters_by_ft or {}
|
||||
opts.formatters_by_ft.python = {
|
||||
-- Ruff handles both formatting and import sorting (fast & modern)
|
||||
'ruff_organize_imports', -- First: organize imports
|
||||
'ruff_format', -- Then: format code (Black-compatible)
|
||||
}
|
||||
return opts
|
||||
end,
|
||||
},
|
||||
|
||||
-- ========================================================================
|
||||
-- PYTHON-SPECIFIC KEYMAPS AND CONFIGURATION
|
||||
-- ========================================================================
|
||||
-- Additional Python-specific settings and keymaps
|
||||
-- ========================================================================
|
||||
{
|
||||
'nvim-treesitter/nvim-treesitter',
|
||||
ft = 'python',
|
||||
opts = function(_, opts)
|
||||
-- Ensure Python parser is installed
|
||||
opts.ensure_installed = opts.ensure_installed or {}
|
||||
vim.list_extend(opts.ensure_installed, { 'python' })
|
||||
return opts
|
||||
end,
|
||||
},
|
||||
}
|
||||
183
lua/plugins/lang/svelte.lua
Normal file
183
lua/plugins/lang/svelte.lua
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
-- ========================================================================
|
||||
-- SVELTE PROFILE - Language-specific plugins and LSP configuration
|
||||
-- ========================================================================
|
||||
--
|
||||
-- This file contains all Svelte-specific plugins and configurations.
|
||||
-- These plugins will ONLY load when you open a .svelte file, keeping your
|
||||
-- startup time fast and avoiding conflicts with other languages.
|
||||
--
|
||||
-- Key features to configure here:
|
||||
-- - Svelte LSP (svelte-language-server)
|
||||
-- - TypeScript/JavaScript support for Svelte components
|
||||
-- - Tailwind CSS integration (if using Tailwind)
|
||||
-- - Prettier formatting for Svelte files
|
||||
-- - Emmet support for Svelte
|
||||
-- - Svelte-specific keymaps
|
||||
--
|
||||
-- Note: You may also want to configure support for related web files:
|
||||
-- - JavaScript/TypeScript (.js, .ts)
|
||||
-- - HTML/CSS (.html, .css)
|
||||
--
|
||||
-- Usage: Just open a .svelte file and these plugins will automatically load!
|
||||
-- ========================================================================
|
||||
|
||||
return {
|
||||
-- ========================================================================
|
||||
-- SVELTE LSP - Language Server Protocol for Svelte
|
||||
-- ========================================================================
|
||||
-- Provides intelligent code completion, diagnostics, and more for Svelte
|
||||
-- components, including support for TypeScript, CSS, and HTML within .svelte files
|
||||
-- ========================================================================
|
||||
{
|
||||
'neovim/nvim-lspconfig',
|
||||
ft = { 'svelte', 'typescript', 'javascript' }, -- Load for web files
|
||||
dependencies = {
|
||||
'WhoIsSethDaniel/mason-tool-installer.nvim',
|
||||
},
|
||||
config = function()
|
||||
-- Get shared LSP capabilities from blink.cmp
|
||||
local capabilities = require('blink.cmp').get_lsp_capabilities()
|
||||
|
||||
-- Setup Svelte LSP server using new vim.lsp.config API (Neovim 0.11+)
|
||||
local svelte_config = require('lspconfig.configs').svelte
|
||||
if svelte_config then
|
||||
vim.lsp.config('svelte', {
|
||||
cmd = svelte_config.default_config.cmd,
|
||||
filetypes = svelte_config.default_config.filetypes,
|
||||
root_markers = svelte_config.default_config.root_dir,
|
||||
capabilities = capabilities,
|
||||
settings = {
|
||||
svelte = {
|
||||
plugin = {
|
||||
html = { completions = { enable = true, emmet = true } },
|
||||
svelte = { completions = { enable = true } },
|
||||
css = { completions = { enable = true } },
|
||||
typescript = { diagnostics = { enable = true } },
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
end
|
||||
|
||||
-- Setup TypeScript LSP for .ts/.js files in Svelte projects
|
||||
local tsserver_config = require('lspconfig.configs').ts_ls
|
||||
if tsserver_config then
|
||||
vim.lsp.config('ts_ls', {
|
||||
cmd = tsserver_config.default_config.cmd,
|
||||
filetypes = {
|
||||
'javascript',
|
||||
'javascriptreact',
|
||||
'typescript',
|
||||
'typescriptreact',
|
||||
},
|
||||
root_markers = tsserver_config.default_config.root_dir,
|
||||
capabilities = capabilities,
|
||||
})
|
||||
end
|
||||
|
||||
-- Setup Tailwind CSS LSP if you're using Tailwind
|
||||
local tailwind_config = require('lspconfig.configs').tailwindcss
|
||||
if tailwind_config then
|
||||
vim.lsp.config('tailwindcss', {
|
||||
cmd = tailwind_config.default_config.cmd,
|
||||
filetypes = {
|
||||
'svelte',
|
||||
'html',
|
||||
'css',
|
||||
'scss',
|
||||
'javascript',
|
||||
'javascriptreact',
|
||||
'typescript',
|
||||
'typescriptreact',
|
||||
},
|
||||
root_markers = tailwind_config.default_config.root_dir,
|
||||
capabilities = capabilities,
|
||||
})
|
||||
end
|
||||
|
||||
-- Install web development tools via Mason
|
||||
require('mason-tool-installer').setup {
|
||||
ensure_installed = {
|
||||
'svelte-language-server', -- Svelte LSP
|
||||
'typescript-language-server', -- TypeScript/JavaScript LSP
|
||||
'tailwindcss-language-server', -- Tailwind CSS LSP (optional)
|
||||
'prettier', -- Code formatter for web files
|
||||
'eslint_d', -- Fast ESLint for linting JS/TS
|
||||
},
|
||||
}
|
||||
end,
|
||||
},
|
||||
|
||||
-- ========================================================================
|
||||
-- WEB FORMATTERS - Prettier for Svelte/JS/TS/CSS
|
||||
-- ========================================================================
|
||||
-- Configures prettier to format Svelte and related web files
|
||||
-- ========================================================================
|
||||
{
|
||||
'stevearc/conform.nvim',
|
||||
ft = { 'svelte', 'typescript', 'javascript', 'css', 'html', 'json' },
|
||||
opts = function(_, opts)
|
||||
-- Extend the existing formatters_by_ft table
|
||||
opts.formatters_by_ft = opts.formatters_by_ft or {}
|
||||
opts.formatters_by_ft.svelte = { 'prettier' }
|
||||
opts.formatters_by_ft.javascript = { 'prettier' }
|
||||
opts.formatters_by_ft.javascriptreact = { 'prettier' }
|
||||
opts.formatters_by_ft.typescript = { 'prettier' }
|
||||
opts.formatters_by_ft.typescriptreact = { 'prettier' }
|
||||
opts.formatters_by_ft.css = { 'prettier' }
|
||||
opts.formatters_by_ft.html = { 'prettier' }
|
||||
opts.formatters_by_ft.json = { 'prettier' }
|
||||
opts.formatters_by_ft.markdown = { 'prettier' }
|
||||
return opts
|
||||
end,
|
||||
},
|
||||
|
||||
-- ========================================================================
|
||||
-- TREESITTER PARSERS - Syntax highlighting for web languages
|
||||
-- ========================================================================
|
||||
-- Ensures Treesitter parsers are installed for better syntax highlighting
|
||||
-- ========================================================================
|
||||
{
|
||||
'nvim-treesitter/nvim-treesitter',
|
||||
ft = { 'svelte', 'typescript', 'javascript', 'css', 'html' },
|
||||
opts = function(_, opts)
|
||||
-- Ensure web language parsers are installed
|
||||
opts.ensure_installed = opts.ensure_installed or {}
|
||||
vim.list_extend(opts.ensure_installed, {
|
||||
'svelte',
|
||||
'typescript',
|
||||
'tsx',
|
||||
'javascript',
|
||||
'jsdoc',
|
||||
'css',
|
||||
'html',
|
||||
'json',
|
||||
})
|
||||
return opts
|
||||
end,
|
||||
},
|
||||
|
||||
-- ========================================================================
|
||||
-- EMMET - HTML/CSS abbreviation expansion
|
||||
-- ========================================================================
|
||||
-- Provides Emmet abbreviation support for faster HTML/CSS writing
|
||||
-- Type abbreviations like `div.container>ul>li*3` and expand with <C-y>,
|
||||
-- ========================================================================
|
||||
{
|
||||
'mattn/emmet-vim',
|
||||
ft = { 'svelte', 'html', 'css', 'javascript', 'typescript' },
|
||||
init = function()
|
||||
-- Set Emmet leader key (default is <C-y>)
|
||||
vim.g.user_emmet_leader_key = '<C-e>'
|
||||
-- Enable only for specific file types
|
||||
vim.g.user_emmet_install_global = 0
|
||||
-- Enable Emmet for Svelte files
|
||||
vim.api.nvim_create_autocmd('FileType', {
|
||||
pattern = { 'html', 'css', 'svelte', 'javascript', 'typescript' },
|
||||
callback = function()
|
||||
vim.cmd 'EmmetInstall'
|
||||
end,
|
||||
})
|
||||
end,
|
||||
},
|
||||
}
|
||||
214
lua/plugins/lsp/init.lua
Normal file
214
lua/plugins/lsp/init.lua
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
-- ========================================================================
|
||||
-- LSP CONFIGURATION
|
||||
-- ========================================================================
|
||||
-- Language Server Protocol setup
|
||||
-- Provides features like:
|
||||
-- - Go to definition
|
||||
-- - Find references
|
||||
-- - Autocompletion
|
||||
-- - Symbol search
|
||||
-- - Code actions
|
||||
-- - Rename refactoring
|
||||
-- ========================================================================
|
||||
|
||||
return {
|
||||
-- Main LSP Configuration
|
||||
{
|
||||
'neovim/nvim-lspconfig',
|
||||
dependencies = {
|
||||
{ 'mason-org/mason.nvim', opts = {} },
|
||||
'mason-org/mason-lspconfig.nvim',
|
||||
'WhoIsSethDaniel/mason-tool-installer.nvim',
|
||||
{ 'j-hui/fidget.nvim', opts = {} },
|
||||
'saghen/blink.cmp',
|
||||
},
|
||||
config = function()
|
||||
-- LSP UI Enhancements - Better hover, signature help, and borders
|
||||
vim.lsp.handlers['textDocument/hover'] = vim.lsp.with(vim.lsp.handlers.hover, {
|
||||
border = 'rounded',
|
||||
max_width = 80,
|
||||
})
|
||||
|
||||
vim.lsp.handlers['textDocument/signatureHelp'] = vim.lsp.with(vim.lsp.handlers.signature_help, {
|
||||
border = 'rounded',
|
||||
max_width = 80,
|
||||
})
|
||||
|
||||
-- LSP Keymaps (applied when LSP attaches to a buffer)
|
||||
vim.api.nvim_create_autocmd('LspAttach', {
|
||||
group = vim.api.nvim_create_augroup('kickstart-lsp-attach', { clear = true }),
|
||||
callback = function(event)
|
||||
local map = function(keys, func, desc, mode)
|
||||
mode = mode or 'n'
|
||||
vim.keymap.set(mode, keys, func, { buffer = event.buf, desc = 'LSP: ' .. desc })
|
||||
end
|
||||
|
||||
map('grn', vim.lsp.buf.rename, '[R]e[n]ame')
|
||||
map('K', vim.lsp.buf.hover, 'Hover Documentation')
|
||||
map('gra', vim.lsp.buf.code_action, '[G]oto Code [A]ction', { 'n', 'x' })
|
||||
map('grr', require('telescope.builtin').lsp_references, '[G]oto [R]eferences')
|
||||
map('gri', require('telescope.builtin').lsp_implementations, '[G]oto [I]mplementation')
|
||||
map('grd', require('telescope.builtin').lsp_definitions, '[G]oto [D]efinition')
|
||||
map('grD', vim.lsp.buf.declaration, '[G]oto [D]eclaration')
|
||||
map('gO', require('telescope.builtin').lsp_document_symbols, 'Open Document Symbols')
|
||||
map('gW', require('telescope.builtin').lsp_dynamic_workspace_symbols, 'Open Workspace Symbols')
|
||||
map('grt', require('telescope.builtin').lsp_type_definitions, '[G]oto [T]ype Definition')
|
||||
|
||||
local function client_supports_method(client, method, bufnr)
|
||||
if vim.fn.has 'nvim-0.11' == 1 then
|
||||
return client:supports_method(method, bufnr)
|
||||
else
|
||||
return client.supports_method(method, { bufnr = bufnr })
|
||||
end
|
||||
end
|
||||
|
||||
-- Highlight references under cursor
|
||||
local client = vim.lsp.get_client_by_id(event.data.client_id)
|
||||
if client and client_supports_method(client, vim.lsp.protocol.Methods.textDocument_documentHighlight, event.buf) then
|
||||
local highlight_augroup = vim.api.nvim_create_augroup('kickstart-lsp-highlight', { clear = false })
|
||||
vim.api.nvim_create_autocmd({ 'CursorHold', 'CursorHoldI' }, {
|
||||
buffer = event.buf,
|
||||
group = highlight_augroup,
|
||||
callback = vim.lsp.buf.document_highlight,
|
||||
})
|
||||
|
||||
vim.api.nvim_create_autocmd({ 'CursorMoved', 'CursorMovedI' }, {
|
||||
buffer = event.buf,
|
||||
group = highlight_augroup,
|
||||
callback = vim.lsp.buf.clear_references,
|
||||
})
|
||||
|
||||
vim.api.nvim_create_autocmd('LspDetach', {
|
||||
group = vim.api.nvim_create_augroup('kickstart-lsp-detach', { clear = true }),
|
||||
callback = function(event2)
|
||||
vim.lsp.buf.clear_references()
|
||||
vim.api.nvim_clear_autocmds { group = 'kickstart-lsp-highlight', buffer = event2.buf }
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
-- Inlay hints toggle
|
||||
if client and client_supports_method(client, vim.lsp.protocol.Methods.textDocument_inlayHint, event.buf) then
|
||||
map('<leader>th', function()
|
||||
vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled { bufnr = event.buf })
|
||||
end, '[T]oggle Inlay [H]ints')
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
-- Diagnostic Config
|
||||
vim.diagnostic.config {
|
||||
severity_sort = true,
|
||||
underline = {
|
||||
severity = { min = vim.diagnostic.severity.WARN },
|
||||
},
|
||||
signs = {
|
||||
text = {
|
||||
[vim.diagnostic.severity.ERROR] = '',
|
||||
[vim.diagnostic.severity.WARN] = '',
|
||||
[vim.diagnostic.severity.INFO] = '',
|
||||
[vim.diagnostic.severity.HINT] = '',
|
||||
},
|
||||
},
|
||||
virtual_text = {
|
||||
spacing = 4,
|
||||
source = 'if_many',
|
||||
prefix = '■',
|
||||
format = function(diagnostic)
|
||||
return diagnostic.message
|
||||
end,
|
||||
},
|
||||
float = {
|
||||
border = 'rounded',
|
||||
source = 'always',
|
||||
header = '',
|
||||
prefix = '',
|
||||
focusable = true,
|
||||
},
|
||||
update_in_insert = false,
|
||||
}
|
||||
|
||||
-- Get capabilities from blink.cmp
|
||||
local capabilities = require('blink.cmp').get_lsp_capabilities()
|
||||
|
||||
-- General LSP servers (lua_ls for Neovim config)
|
||||
local servers = {
|
||||
lua_ls = {
|
||||
settings = {
|
||||
Lua = {
|
||||
completion = {
|
||||
callSnippet = 'Replace',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
local ensure_installed = vim.tbl_keys(servers or {})
|
||||
vim.list_extend(ensure_installed, {
|
||||
'stylua', -- Lua formatter
|
||||
})
|
||||
require('mason-tool-installer').setup { ensure_installed = ensure_installed }
|
||||
|
||||
require('mason-lspconfig').setup {
|
||||
ensure_installed = {},
|
||||
automatic_installation = false,
|
||||
handlers = {
|
||||
function(server_name)
|
||||
local server = servers[server_name] or {}
|
||||
server.capabilities = vim.tbl_deep_extend('force', {}, capabilities, server.capabilities or {})
|
||||
|
||||
local ok, lspconfig_server = pcall(require, 'lspconfig.server_configurations.' .. server_name)
|
||||
if ok and lspconfig_server.default_config then
|
||||
local config = lspconfig_server.default_config
|
||||
vim.lsp.config(server_name, {
|
||||
cmd = server.cmd or config.cmd,
|
||||
filetypes = server.filetypes or config.filetypes,
|
||||
root_markers = config.root_dir,
|
||||
capabilities = server.capabilities,
|
||||
settings = server.settings,
|
||||
})
|
||||
vim.lsp.enable(server_name)
|
||||
end
|
||||
end,
|
||||
},
|
||||
}
|
||||
end,
|
||||
},
|
||||
|
||||
-- Autoformat
|
||||
{
|
||||
'stevearc/conform.nvim',
|
||||
event = { 'BufWritePre' },
|
||||
cmd = { 'ConformInfo' },
|
||||
keys = {
|
||||
{
|
||||
'<leader>f',
|
||||
function()
|
||||
require('conform').format { async = true, lsp_format = 'fallback' }
|
||||
end,
|
||||
mode = '',
|
||||
desc = '[F]ormat buffer',
|
||||
},
|
||||
},
|
||||
opts = {
|
||||
notify_on_error = false,
|
||||
format_on_save = function(bufnr)
|
||||
local disable_filetypes = { c = true, cpp = true }
|
||||
local lsp_format_opt
|
||||
if disable_filetypes[vim.bo[bufnr].filetype] then
|
||||
lsp_format_opt = 'never'
|
||||
else
|
||||
lsp_format_opt = 'fallback'
|
||||
end
|
||||
return {
|
||||
timeout_ms = 500,
|
||||
lsp_format = lsp_format_opt,
|
||||
}
|
||||
end,
|
||||
formatters_by_ft = {
|
||||
lua = { 'stylua' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue