lots of keybinds and familiar things changed

This commit is contained in:
RiverMatsumoto 2026-01-01 18:36:08 -10:00
parent 469cb3c874
commit 291ae1ea52
3 changed files with 422 additions and 101 deletions

379
init.lua
View File

@ -1,7 +1,8 @@
vim.g.mapleader = ' '
vim.g.maplocalleader = ' ' vim.g.maplocalleader = ' '
-- for chatgpt vim.g.mapleader = ' '
_G.chatgpt_model = 'gpt-5.1-codex-mini'
-- install deps if need to
require("bootstrap.pacman")
-- ========================= -- =========================
-- Lazy.nvim bootstrap -- Lazy.nvim bootstrap
@ -73,42 +74,6 @@ require('lazy').setup({
}, },
'rhysd/git-messenger.vim', 'rhysd/git-messenger.vim',
{
'jackMort/ChatGPT.nvim',
event = 'VeryLazy',
dependencies = {
'nvim-lua/plenary.nvim',
'MunifTanjim/nui.nvim',
'nvim-telescope/telescope.nvim',
},
config = function()
require('chatgpt').setup {
openai_params = {
-- NOTE: model can be a function returning the model name
-- this is useful if you want to change the model on the fly
-- using commands
-- Example:
-- model = function()
-- if some_condition() then
-- return "gpt-5"
-- else
-- return "gpt-5-mini"
-- end
-- end,
model = function()
return _G.chatgpt_model
end,
frequency_penalty = 0,
presence_penalty = 0,
max_tokens = 4095,
temperature = 0.2,
top_p = 0.1,
n = 1,
api_key_cmd = 'echo $OPENAI_API_KEY',
},
}
end,
},
{ {
'lewis6991/gitsigns.nvim', 'lewis6991/gitsigns.nvim',
@ -218,7 +183,24 @@ require('lazy').setup({
'MunifTanjim/nui.nvim', 'MunifTanjim/nui.nvim',
}, },
opts = { opts = {
enable_preview = true,
filesystem = { filesystem = {
-- open images (and anything else) externally
commands = {
system_open = function(state)
local node = state.tree:get_node()
local path = node:get_id() -- absolute path
vim.fn.jobstart({ 'imv', path }, { detach = true })
end,
},
window = {
mappings = {
['P'] = 'toggle_preview',
['O'] = 'system_open', -- press O to open with external viewer
},
},
filtered_items = { filtered_items = {
visible = false, visible = false,
hide_dotfiles = true, hide_dotfiles = true,
@ -230,25 +212,33 @@ require('lazy').setup({
}, },
}, },
-- Buffers/tabs -- LAZY PLUGIN SPEC (replace bufferline with barbar)
{ {
'akinsho/bufferline.nvim', 'romgrk/barbar.nvim',
version = '*', dependencies = {
dependencies = 'nvim-tree/nvim-web-devicons', 'nvim-tree/nvim-web-devicons',
'lewis6991/gitsigns.nvim', -- optional, for git status icons
},
init = function()
vim.g.barbar_auto_setup = false
end,
opts = { opts = {
options = { animation = true,
mode = 'buffers', -- tabs or buffers auto_hide = false,
diagnostics = 'nvim_lsp', tabpages = false, -- show buffers, not Vim tabpages
show_buffer_close_icons = false, clickable = true,
show_close_icon = false, icons = {
hover = { preset = 'slanted',
enabled = true, button = '󰅖',
delay = 200, },
reveal = {'close'}
}, -- Treat neo-tree as a sidebar so it doesn't become a "tab" and layout stays sane
sidebar_filetypes = {
['neo-tree'] = { event = 'BufWipeout' },
}, },
}, },
}, },
'nvim-tree/nvim-web-devicons', 'nvim-tree/nvim-web-devicons',
{ {
@ -335,16 +325,6 @@ require('lazy').setup({
{ 'nvim-pack/nvim-spectre', opts = {} }, { 'nvim-pack/nvim-spectre', opts = {} },
{
'romgrk/barbar.nvim',
event = 'BufEnter',
dependencies = 'nvim-tree/nvim-web-devicons',
init = function()
vim.g.barbar_auto_setup = false
end,
lazy = true,
},
{ {
'lukas-reineke/indent-blankline.nvim', 'lukas-reineke/indent-blankline.nvim',
main = 'ibl', main = 'ibl',
@ -605,7 +585,7 @@ require('lazy').setup({
map('<leader>ws', require('telescope.builtin').lsp_dynamic_workspace_symbols, '[W]orkspace [S]ymbols') map('<leader>ws', require('telescope.builtin').lsp_dynamic_workspace_symbols, '[W]orkspace [S]ymbols')
map('<leader>rn', vim.lsp.buf.rename, '[R]e[n]ame') map('<leader>rn', vim.lsp.buf.rename, '[R]e[n]ame')
map('<leader>ca', vim.lsp.buf.code_action, '[C]ode [A]ction') map('<leader>ca', vim.lsp.buf.code_action, '[C]ode [A]ction')
map('K', vim.lsp.buf.hover, 'Hover Documentation') map('T', vim.lsp.buf.hover, 'Hover Documentation')
map('<C-k>', vim.lsp.buf.signature_help, 'Signature Documentation') map('<C-k>', vim.lsp.buf.signature_help, 'Signature Documentation')
local client = vim.lsp.get_client_by_id(event.data.client_id) local client = vim.lsp.get_client_by_id(event.data.client_id)
@ -866,6 +846,202 @@ require('lazy').setup({
end, end,
}, },
{
'Kurama622/llm.nvim',
dependencies = { 'nvim-lua/plenary.nvim', 'MunifTanjim/nui.nvim' },
cmd = { 'LLMSessionToggle', 'LLMSelectedTextHandler', 'LLMAppHandler' },
config = function()
require('llm').setup {
-- GitHub Models (Azure inference)
url = 'https://api.openai.com/v1/chat/completions',
api_type = 'openai',
-- Set this to what you want to use (must support /chat/completions)
model = _G.chatgpt_model or 'gpt-5-nano',
-- Sensible coding defaults
--max_tokens = 4095,
--temperature = 0.2,
--top_p = 0.1,
-- Keep it code-focused
prompt = 'You are a helpful programming assistant. Be concise, show code when needed, and prefer practical fixes.',
-- Visual selection -> context prompt
selected_text_handler = {
prompt = function(selection)
return string.format(
'You are a helpful programming assistant.\n\n' .. 'Context (selected text):\n' .. '```text\n%s\n```\n\n' .. 'Task:\n',
selection
)
end,
},
-- Optional cosmetics (minimal)
spinner = {
text = { '', '', '', '', '', '', '', '', '', '' },
hl = 'Title',
},
prefix = {
user = { text = 'You: ', hl = 'Title' },
assistant = { text = 'AI: ', hl = 'Added' },
},
-- Persist chat history
save_session = true,
max_history = 30,
max_history_name_length = 40,
-- Keymaps inside the session UI
keys = {
-- Input window
['Input:Submit'] = { mode = 'i', key = '<cr>' }, -- Enter sends (your issue)
['Input:Cancel'] = { mode = { 'n', 'i' }, key = '<C-c>' },
['Input:Resend'] = { mode = { 'n', 'i' }, key = '<C-r>' },
-- History (only if save_session=true)
['Input:HistoryNext'] = { mode = { 'n', 'i' }, key = '<C-j>' },
['Input:HistoryPrev'] = { mode = { 'n', 'i' }, key = '<C-k>' },
-- Output window ("split" style)
['Output:Ask'] = { mode = 'n', key = 'i' },
['Output:Cancel'] = { mode = 'n', key = '<C-c>' },
['Output:Resend'] = { mode = 'n', key = '<C-r>' },
-- Session window ("float" style)
['Session:Toggle'] = { mode = 'n', key = '<leader>ai' }, -- your chosen toggle
['Session:Close'] = { mode = 'n', key = { '<esc>', 'Q' } },
},
-- Optional diff display used by some tools/handlers
display = {
diff = {
layout = 'vertical',
opts = {
'internal',
'filler',
'closeoff',
'algorithm:patience',
'followwrap',
'linematch:120',
},
provider = 'mini_diff',
disable_diagnostic = true,
},
},
callbacks = {
on_response = function(resp)
local usage = resp and resp.usage
if usage then
vim.notify(
string.format(
'LLM tokens — prompt: %d, completion: %d, total: %d',
usage.prompt_tokens or 0,
usage.completion_tokens or 0,
usage.total_tokens or 0
),
vim.log.levels.INFO
)
end
end,
},
-- If you later add tools:
app_handler = {
-- Visual-select text -> run this -> output in a floating result window.
AskWithContext = {
handler = 'attach_to_chat_handler',
prompt = [[
Answer the users question (likely code related) using the context very briefly and concisely:
]],
opts = {
-- this is the key part: append the visual selection after the prompt
apply_visual_selection = true, -- described in docs for flexi_handler :contentReference[oaicite:2]{index=2}
is_codeblock = true,
enter_input = true,
enter_flexible_window = false,
--exit_on_move = true,
},
},
CodeExplain = {
handler = 'flexi_handler',
prompt = 'Explain the following code very briefly, please only return the explanation',
opts = {
enter_flexible_window = true,
},
},
},
}
end,
keys = {
{ '<leader>ai', '<cmd>LLMSessionToggle<cr>', mode = 'n', silent = true, desc = 'LLM: toggle session' },
{ '<leader>as', '<cmd>LLMSelectedTextHandler<cr>', mode = 'x', silent = true, desc = 'LLM: send selection' },
-- If you add tools:
{ '<leader>ax', '<cmd>LLMAppHandler CodeExplain<cr>', mode = 'x', silent = true, desc = 'LLM tool: Explain' },
{ '<leader>ai', '<cmd>LLMAppHandler AskWithContext<cr>', mode = 'x', silent = true, desc = 'LLM tool: Ask with context' },
},
},
{
'MeanderingProgrammer/render-markdown.nvim',
dependencies = {
{
'nvim-treesitter/nvim-treesitter',
branch = 'main',
config = function()
vim.api.nvim_create_autocmd('FileType', {
pattern = { 'llm', 'markdown' },
callback = function()
vim.treesitter.start(0, 'markdown')
end,
})
end,
},
'nvim-mini/mini.icons',
}, -- if you use standalone mini plugins
ft = { 'markdown', 'llm' },
config = function()
require('render-markdown').setup {
restart_highlighter = true,
heading = {
enabled = true,
sign = false,
position = 'overlay', -- inline | overlay
icons = { '󰎤 ', '󰎧 ', '󰎪 ', '󰎭 ', '󰎱 ', '󰎳 ' },
signs = { '󰫎 ' },
width = 'block',
left_margin = 0,
left_pad = 0,
right_pad = 0,
min_width = 0,
border = false,
border_virtual = false,
border_prefix = false,
above = '',
below = '',
backgrounds = {},
foregrounds = {
'RenderMarkdownH1',
'RenderMarkdownH2',
'RenderMarkdownH3',
'RenderMarkdownH4',
'RenderMarkdownH5',
'RenderMarkdownH6',
},
},
dash = {
enabled = true,
icon = '',
width = 0.5,
left_margin = 0.5,
highlight = 'RenderMarkdownDash',
},
code = { style = 'normal' },
}
end,
},
-- DAP -- DAP
{ {
'mfussenegger/nvim-dap', 'mfussenegger/nvim-dap',
@ -1050,6 +1226,7 @@ local smear_profiles = {
-- 1) Frost Mist -- 1) Frost Mist
eco_smear = { eco_smear = {
-- General (keep core behavior) -- General (keep core behavior)
cursor_color = '#ffe6b2',
smear_between_buffers = true, smear_between_buffers = true,
smear_between_neighbor_lines = true, smear_between_neighbor_lines = true,
min_horizontal_distance_smear = 1, -- reduces tiny smears min_horizontal_distance_smear = 1, -- reduces tiny smears
@ -1141,6 +1318,7 @@ local smear_profiles = {
}, },
} }
-- smear settings
local smear_profile_order = { local smear_profile_order = {
'silver_blade', 'silver_blade',
'eco_smear', 'eco_smear',
@ -1168,6 +1346,8 @@ end, {
return smear_profile_order return smear_profile_order
end, end,
}) })
-- Apply a default on startup (pick one)
apply_smear_profile 'silver_blade'
vim.api.nvim_create_user_command('SmearProfileNext', function() vim.api.nvim_create_user_command('SmearProfileNext', function()
current_idx = (current_idx % #smear_profile_order) + 1 current_idx = (current_idx % #smear_profile_order) + 1
@ -1183,8 +1363,6 @@ end, {})
vim.keymap.set('n', '<leader>pn', '<cmd>SmearProfileNext<CR>', { desc = 'Smear profile: next' }) vim.keymap.set('n', '<leader>pn', '<cmd>SmearProfileNext<CR>', { desc = 'Smear profile: next' })
vim.keymap.set('n', '<leader>pp', '<cmd>SmearProfilePrev<CR>', { desc = 'Smear profile: prev' }) vim.keymap.set('n', '<leader>pp', '<cmd>SmearProfilePrev<CR>', { desc = 'Smear profile: prev' })
-- Apply a default on startup (pick one)
apply_smear_profile 'silver_blade'
-- ========================================= -- =========================================
-- ============ END SMEAR PROFILE ========== -- ============ END SMEAR PROFILE ==========
-- ========================================= -- =========================================
@ -1231,14 +1409,14 @@ local function set_indent(ts)
end end
vim.api.nvim_create_autocmd('FileType', { vim.api.nvim_create_autocmd('FileType', {
pattern = { 'lua', 'javascript', 'typescript', 'tsx', 'json', 'yaml', 'toml', 'html', 'css', 'rust', 'c', 'cpp' }, pattern = { 'lua', 'javascript', 'typescript', 'tsx', 'json', 'yaml', 'toml', 'html', 'css' },
callback = function() callback = function()
set_indent(2) set_indent(2)
end, end,
}) })
vim.api.nvim_create_autocmd('FileType', { vim.api.nvim_create_autocmd('FileType', {
pattern = { 'python', 'sh', 'bash', 'zsh', 'go' }, pattern = { 'python', 'sh', 'bash', 'zsh', 'go', 'rust', 'cpp', 'c' },
callback = function() callback = function()
set_indent(4) set_indent(4)
end, end,
@ -1365,7 +1543,7 @@ vim.keymap.set('n', '<leader>xw', '<cmd>TroubleToggle workspace_diagnostics<cr>'
vim.keymap.set('n', '<leader>xd', '<cmd>TroubleToggle document_diagnostics<cr>', { silent = true, noremap = true, desc = 'Document diagnostics (Trouble)' }) vim.keymap.set('n', '<leader>xd', '<cmd>TroubleToggle document_diagnostics<cr>', { silent = true, noremap = true, desc = 'Document diagnostics (Trouble)' })
-- DAP -- DAP
vim.keymap.set('n', '<F2>', ":lua require('dapui').toggle()<CR>", { desc = 'Toggle DAP UI' }) vim.keymap.set('n', '<leader>dap', ":lua require('dapui').toggle()<CR>", { desc = 'Toggle DAP UI' })
vim.keymap.set('n', '<leader>dc', ":lua require('dap').continue()<CR>", { desc = 'DAP continue' }) vim.keymap.set('n', '<leader>dc', ":lua require('dap').continue()<CR>", { desc = 'DAP continue' })
vim.keymap.set('n', '<leader>do', ":lua require('dap').step_over()<CR>", { desc = 'DAP step over' }) vim.keymap.set('n', '<leader>do', ":lua require('dap').step_over()<CR>", { desc = 'DAP step over' })
vim.keymap.set('n', '<leader>di', ":lua require('dap').step_into()<CR>", { desc = 'DAP step into' }) vim.keymap.set('n', '<leader>di', ":lua require('dap').step_into()<CR>", { desc = 'DAP step into' })
@ -1382,22 +1560,33 @@ vim.keymap.set('n', '<leader>dt', ":lua require('dap').toggle_breakpoint()<CR>",
vim.keymap.set('n', '<leader>dm', ":lua require('dap-python').test_method()<CR>", { silent = true, noremap = true, desc = 'DAP test method' }) vim.keymap.set('n', '<leader>dm', ":lua require('dap-python').test_method()<CR>", { silent = true, noremap = true, desc = 'DAP test method' })
vim.keymap.set('n', '<leader>df', ":lua require('dap-python').test_class()<CR>", { silent = true, noremap = true, desc = 'DAP test class' }) vim.keymap.set('n', '<leader>df', ":lua require('dap-python').test_class()<CR>", { silent = true, noremap = true, desc = 'DAP test class' })
-- barbar -- bufferline
vim.keymap.set('n', '<A-,>', '<cmd>BufferPrevious<cr>', { silent = true, noremap = true, desc = 'Previous buffer' })
vim.keymap.set('n', '<A-.>', '<cmd>BufferNext<cr>', { silent = true, noremap = true, desc = 'Next buffer' })
vim.keymap.set('n', '<A-c>', '<cmd>BufferClose<cr>', { silent = true, noremap = true, desc = 'Close buffer' })
local opts = { noremap = true, silent = true } local opts = { noremap = true, silent = true }
vim.keymap.set('n', '<A-1>', '<Cmd>BufferLineGoToBuffer 1<CR>', vim.tbl_extend('force', opts, { desc = 'Go to buffer 1' }))
vim.keymap.set('n', '<A-2>', '<Cmd>BufferLineGoToBuffer 2<CR>', vim.tbl_extend('force', opts, { desc = 'Go to buffer 2' })) -- KEYMAPS (Barbar)
vim.keymap.set('n', '<A-3>', '<Cmd>BufferLineGoToBuffer 3<CR>', vim.tbl_extend('force', opts, { desc = 'Go to buffer 3' })) local opts = { noremap = true, silent = true }
vim.keymap.set('n', '<A-4>', '<Cmd>BufferLineGoToBuffer 4<CR>', vim.tbl_extend('force', opts, { desc = 'Go to buffer 4' }))
vim.keymap.set('n', '<A-5>', '<Cmd>BufferLineGoToBuffer 5<CR>', vim.tbl_extend('force', opts, { desc = 'Go to buffer 5' })) vim.keymap.set('n', '<A-1>', '<Cmd>BufferGoto 1<CR>', vim.tbl_extend('force', opts, { desc = 'Go to buffer 1' }))
vim.keymap.set('n', '<A-6>', '<Cmd>BufferLineGoToBuffer 6<CR>', vim.tbl_extend('force', opts, { desc = 'Go to buffer 6' })) vim.keymap.set('n', '<A-2>', '<Cmd>BufferGoto 2<CR>', vim.tbl_extend('force', opts, { desc = 'Go to buffer 2' }))
vim.keymap.set('n', '<A-7>', '<Cmd>BufferLineGoToBuffer 7<CR>', vim.tbl_extend('force', opts, { desc = 'Go to buffer 7' })) vim.keymap.set('n', '<A-3>', '<Cmd>BufferGoto 3<CR>', vim.tbl_extend('force', opts, { desc = 'Go to buffer 3' }))
vim.keymap.set('n', '<A-8>', '<Cmd>BufferLineGoToBuffer 8<CR>', vim.tbl_extend('force', opts, { desc = 'Go to buffer 8' })) vim.keymap.set('n', '<A-4>', '<Cmd>BufferGoto 4<CR>', vim.tbl_extend('force', opts, { desc = 'Go to buffer 4' }))
vim.keymap.set('n', '<A-9>', '<Cmd>BufferLineGoToBuffer 9<CR>', vim.tbl_extend('force', opts, { desc = 'Go to buffer 9' })) vim.keymap.set('n', '<A-5>', '<Cmd>BufferGoto 5<CR>', vim.tbl_extend('force', opts, { desc = 'Go to buffer 5' }))
vim.keymap.set('n', '<A-6>', '<Cmd>BufferGoto 6<CR>', vim.tbl_extend('force', opts, { desc = 'Go to buffer 6' }))
vim.keymap.set('n', '<A-7>', '<Cmd>BufferGoto 7<CR>', vim.tbl_extend('force', opts, { desc = 'Go to buffer 7' }))
vim.keymap.set('n', '<A-8>', '<Cmd>BufferGoto 8<CR>', vim.tbl_extend('force', opts, { desc = 'Go to buffer 8' }))
vim.keymap.set('n', '<A-9>', '<Cmd>BufferGoto 9<CR>', vim.tbl_extend('force', opts, { desc = 'Go to buffer 9' }))
vim.keymap.set('n', '<A-0>', '<Cmd>BufferLast<CR>', vim.tbl_extend('force', opts, { desc = 'Go to last buffer' })) vim.keymap.set('n', '<A-0>', '<Cmd>BufferLast<CR>', vim.tbl_extend('force', opts, { desc = 'Go to last buffer' }))
-- Close current buffer (Barbar)
vim.keymap.set('n', '<A-w>', '<Cmd>BufferClose<CR>', vim.tbl_extend('force', opts, { desc = 'Close buffer' }))
-- Close current window/split
vim.keymap.set('n', '<A-q>', '<Cmd>close<CR>', vim.tbl_extend('force', opts, { desc = 'Close window' }))
vim.keymap.set('n', '<Tab>', '<Cmd>BufferNext<CR>', { desc = 'Go to next buffer' })
vim.keymap.set('n', '<S-Tab>', '<Cmd>BufferPrevious<CR>', { desc = 'Go to previous buffer' })
-- barbar colors
-- quickfix -- quickfix
vim.keymap.set('n', '<leader>cn', ':cnext<CR>', { desc = 'Next quickfix item' }) vim.keymap.set('n', '<leader>cn', ':cnext<CR>', { desc = 'Next quickfix item' })
@ -1409,25 +1598,9 @@ vim.keymap.set('n', '<leader>mp', ':MarkdownPreview<CR>', { desc = 'Markdown pre
-- git -- git
vim.keymap.set('n', '<leader>ga', ':Telescope coauthors<CR>', { desc = 'Select git co-authors' }) vim.keymap.set('n', '<leader>ga', ':Telescope coauthors<CR>', { desc = 'Select git co-authors' })
-- AI model switching
vim.keymap.set('n', '<leader>an', function()
_G.chatgpt_model = 'gpt-5-nano'
print 'ChatGPT → gpt-5-nano'
end, { desc = 'ChatGPT model: gpt-5-nano' })
vim.keymap.set('n', '<leader>ac', function()
_G.chatgpt_model = 'gpt-5.1-codex-mini'
print 'ChatGPT → gpt-5.1-codex-mini'
end, { desc = 'ChatGPT model: gpt-5.1-codex-mini' })
vim.keymap.set('n', '<leader>ai', '<Cmd>ChatGPT<CR>', { desc = 'Open ChatGPT prompt' })
-- delete backwards -- delete backwards
vim.keymap.set({ 'i', 'c' }, '<C-BS>', '<C-w>', { noremap = true, desc = 'Delete previous word' }) vim.keymap.set({ 'i', 'c' }, '<C-BS>', '<C-w>', { noremap = true, desc = 'Delete previous word' })
vim.keymap.set('n', '<Tab>', '<cmd>BufferLineCycleNext<CR>', { desc = 'Go to next tab' })
vim.keymap.set('n', '<S-Tab>', '<cmd>BufferLineCyclePrev<CR>', { desc = 'Go backwards a tab' })
vim.keymap.set('n', '<leader>tc', ':tabclose<CR>', { desc = 'Close current tab' }) vim.keymap.set('n', '<leader>tc', ':tabclose<CR>', { desc = 'Close current tab' })
vim.keymap.set('n', '<leader>fk', ':FloatermKill!<CR>', { desc = 'Kill all floaterm terminals' }) vim.keymap.set('n', '<leader>fk', ':FloatermKill!<CR>', { desc = 'Kill all floaterm terminals' })
vim.keymap.set('x', 'S', '<Plug>(nvim-surround-visual)', { remap = true }, { desc = 'Surround selected text' }) vim.keymap.set('x', 'S', '<Plug>(nvim-surround-visual)', { remap = true }, { desc = 'Surround selected text' })
@ -1462,9 +1635,9 @@ _G.toggle_neotree = toggle_neotree
vim.api.nvim_set_keymap('n', '<C-n>', ':lua toggle_neotree()<CR>', { noremap = true, silent = true }) vim.api.nvim_set_keymap('n', '<C-n>', ':lua toggle_neotree()<CR>', { noremap = true, silent = true })
-- Floaterm -- Floaterm
vim.api.nvim_set_keymap('n', '<C-t>', ':FloatermToggle<CR>', { noremap = true }) vim.api.nvim_set_keymap('n', '<C-`>', ':FloatermToggle<CR>', { noremap = true })
vim.api.nvim_set_keymap('i', '<C-t>', ':FloatermToggle<CR>', { noremap = true }) vim.api.nvim_set_keymap('i', '<C-`>', ':FloatermToggle<CR>', { noremap = true })
vim.api.nvim_set_keymap('t', '<C-t>', '<C-\\><C-n>:FloatermToggle<CR>', { noremap = true, silent = true }) vim.api.nvim_set_keymap('t', '<C-`>', '<C-\\><C-n>:FloatermToggle<CR>', { noremap = true, silent = true })
-- Comment.nvim keymaps -- Comment.nvim keymaps
vim.api.nvim_set_keymap('n', '<C-/>', '<cmd>lua require("Comment.api").toggle.linewise.current()<CR>', { noremap = true, silent = true }) vim.api.nvim_set_keymap('n', '<C-/>', '<cmd>lua require("Comment.api").toggle.linewise.current()<CR>', { noremap = true, silent = true })
@ -1478,3 +1651,7 @@ vim.keymap.set('n', '<leader>ga', ':Telescope coauthors<CR>')
-- install treesitter parsers -- install treesitter parsers
require('nvim-treesitter').install { 'c', 'rust', 'gdscript', 'c#' } require('nvim-treesitter').install { 'c', 'rust', 'gdscript', 'c#' }
-- LSP basics
vim.keymap.set('n', '<F2>', vim.lsp.buf.rename, { silent = true, desc = 'LSP: Rename' })
vim.keymap.set('n', '<F12>', vim.lsp.buf.references, { silent = true, desc = 'LSP: References' })

33
lua/bootstrap/deps.lua Normal file
View File

@ -0,0 +1,33 @@
-- lua/bootstrap/deps.lua
-- System-level deps for this config (Arch / pacman names)
return {
-- bootstrap
"neovim",
"git",
-- telescope / grep
"ripgrep",
"fd",
-- builds native plugins (telescope-fzf-native, treesitter parsers, etc.)
"base-devel",
-- clipboard (Wayland)
"wl-clipboard",
-- X11 alternative (optional): "xclip",
-- markdown-preview.nvim build/runtime
"nodejs",
"npm",
-- toggleterm custom commands
"lazygit",
-- neo-tree external opener
"imv",
-- treesitter
"tree-sitter-cli",
}

111
lua/bootstrap/pacman.lua Normal file
View File

@ -0,0 +1,111 @@
-- ~/.config/nvim/lua/bootstrap/pacman.lua
-- Fix1: run pacman inside a Neovim terminal so sudo has a real TTY.
local M = {}
local function has_exe(exe)
return vim.fn.executable(exe) == 1
end
local function pacman_has(pkg)
local out = vim.fn.system({ "pacman", "-Qi", pkg })
return vim.v.shell_error == 0 and out ~= nil and out ~= ""
end
local function missing_pkgs(pkgs)
local missing = {}
for _, p in ipairs(pkgs) do
if not pacman_has(p) then
table.insert(missing, p)
end
end
return missing
end
local function shell_escape_arg(s)
-- minimal quoting for a shell command string
return "'" .. tostring(s):gsub("'", [['"'"']]) .. "'"
end
local function open_install_terminal(pkgs)
if #pkgs == 0 then
return true
end
if not has_exe("sudo") then
vim.notify("Missing `sudo`; cannot auto-install pacman deps.", vim.log.levels.ERROR)
return false
end
-- Build a single shell command so sudo prompts normally.
local parts = { "sudo", "pacman", "-S", "--needed" }
for _, p in ipairs(pkgs) do
table.insert(parts, shell_escape_arg(p))
end
local cmd = table.concat(parts, " ")
vim.notify("Opening terminal to install:\n" .. table.concat(pkgs, ", "), vim.log.levels.WARN)
-- Open a terminal split and run the command. User can enter sudo password normally.
vim.cmd("botright 15split")
vim.cmd("terminal " .. cmd)
vim.cmd("startinsert")
return true
end
function M.check()
if not has_exe("pacman") then
vim.notify("pacman not found. This bootstrap is Arch-specific.", vim.log.levels.WARN)
return {}
end
local deps = require("bootstrap.deps")
return missing_pkgs(deps)
end
function M.install(opts)
opts = opts or {}
local miss = M.check()
if #miss == 0 then
if not opts.quiet then
vim.notify("All system deps already installed.", vim.log.levels.INFO)
end
return true
end
local prompt = "Missing system deps:\n\n"
.. table.concat(miss, "\n")
.. "\n\nOpen a terminal and run sudo pacman to install them?"
local ok = true
if not opts.force then
ok = (vim.fn.confirm(prompt, "&Yes\n&No", 1) == 1)
end
if not ok then
return false
end
return open_install_terminal(miss)
end
-- Commands
vim.api.nvim_create_user_command("DepsCheck", function()
local miss = M.check()
if #miss == 0 then
vim.notify("DepsCheck: OK (no missing packages).", vim.log.levels.INFO)
else
vim.notify("DepsCheck missing:\n" .. table.concat(miss, ", "), vim.log.levels.WARN)
end
end, {})
vim.api.nvim_create_user_command("DepsInstall", function()
M.install({ force = true })
end, {})
-- Run once per session (prompt-based)
if vim.g.__deps_bootstrap_ran ~= true then
vim.g.__deps_bootstrap_ran = true
M.install({ force = false, quiet = true })
end
return M