diff --git a/AGENTS.md b/AGENTS.md index debcb2a2..ceee174d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -143,6 +143,14 @@ Do not remove useful annotations just to reduce lines. - Respect platform guards (e.g., `make` checks, Windows conditionals). - Do not edit lockfile manually; let lazy manage `lazy-lock.json` updates. +## Custom Keymap and Layout Conventions + +- Keep **custom** keymaps in `lua/custom/keymaps.lua`. +- Keep upstream kickstart keymaps in `init.lua` unless intentionally overriding behavior. +- If adding a new `` namespace in `lua/custom/keymaps.lua`, also register its group in which-key (`init.lua` `which-key` spec). +- Keep layout/window helper logic centralized in `lua/custom/layout.lua` (for example `focus_main_window()`), and reuse it from plugin modules instead of duplicating sidebar/window filtering logic. +- If a plugin needs startup window choreography, call `require('custom.layout')` helpers rather than re-implementing window focus rules. + ## Editing and Change Scope - Keep changes minimal and local to the requested task. diff --git a/init.lua b/init.lua index 6bb0946e..6ca9aec9 100644 --- a/init.lua +++ b/init.lua @@ -233,6 +233,7 @@ vim.api.nvim_create_autocmd('TextYankPost', { }) require 'custom.beancount' +require 'custom.keymaps' -- [[ Install `lazy.nvim` plugin manager ]] -- See `:help lazy.nvim.txt` or https://github.com/folke/lazy.nvim for more info @@ -322,6 +323,7 @@ require('lazy').setup({ spec = { { 's', group = '[S]earch', mode = { 'n', 'v' } }, { 't', group = '[T]oggle' }, + { 'w', group = '[W]indows' }, { 'h', group = 'Git [H]unk', mode = { 'n', 'v' } }, -- Enable gitsigns recommended keymaps first { 'gr', group = 'LSP Actions', mode = { 'n' } }, }, diff --git a/lua/custom/keymaps.lua b/lua/custom/keymaps.lua new file mode 100644 index 00000000..7aea5e9b --- /dev/null +++ b/lua/custom/keymaps.lua @@ -0,0 +1 @@ +vim.keymap.set('n', 'wr', function() require('custom.layout').reset_ide_layout() end, { desc = '[W]indows: [R]eset IDE layout' }) diff --git a/lua/custom/layout.lua b/lua/custom/layout.lua new file mode 100644 index 00000000..217f2226 --- /dev/null +++ b/lua/custom/layout.lua @@ -0,0 +1,83 @@ +local M = {} + +local sidebar_filetypes = { + ['neo-tree'] = true, + ['snacks_layout_box'] = true, + ['snacks_terminal'] = true, + ['toggleterm'] = true, + ['opencode'] = true, +} + +function M.focus_main_window() + for _, win in ipairs(vim.api.nvim_tabpage_list_wins(0)) do + local buf = vim.api.nvim_win_get_buf(win) + local ft = vim.bo[buf].filetype + local bt = vim.bo[buf].buftype + if not sidebar_filetypes[ft] and bt == '' then + vim.api.nvim_set_current_win(win) + return true + end + end + + return false +end + +local function find_window_by_filetype(filetype) + for _, win in ipairs(vim.api.nvim_tabpage_list_wins(0)) do + local buf = vim.api.nvim_win_get_buf(win) + if vim.bo[buf].filetype == filetype then return win end + end + + return nil +end + +local function ensure_neotree_window() + local neotree_win = find_window_by_filetype 'neo-tree' + if neotree_win then return neotree_win end + + pcall( + function() + require('neo-tree.command').execute { + action = 'show', + source = 'filesystem', + position = 'left', + reveal = true, + } + end + ) + + return find_window_by_filetype 'neo-tree' +end + +local function ensure_opencode_window() + local opencode_win = find_window_by_filetype 'opencode' + if opencode_win then return opencode_win end + + pcall(function() require('opencode').toggle() end) + + vim.wait(1000, function() return find_window_by_filetype 'opencode' ~= nil end, 50) + return find_window_by_filetype 'opencode' +end + +function M.reset_ide_layout() + local neotree_win = ensure_neotree_window() + local opencode_win = ensure_opencode_window() + + local total_columns = vim.o.columns + local left_width = math.max(20, math.floor(total_columns * 0.10)) + local right_width = math.max(40, math.floor(total_columns * 0.25)) + local min_main_width = 40 + + if left_width + right_width + min_main_width > total_columns then + local available_sidebar_width = math.max(total_columns - min_main_width, 0) + left_width = math.floor(available_sidebar_width * (10 / 35)) + right_width = available_sidebar_width - left_width + end + + if neotree_win and vim.api.nvim_win_is_valid(neotree_win) then vim.api.nvim_win_set_width(neotree_win, left_width) end + if opencode_win and vim.api.nvim_win_is_valid(opencode_win) then vim.api.nvim_win_set_width(opencode_win, right_width) end + + M.focus_main_window() +end + +return M diff --git a/lua/custom/plugins/opencode.lua b/lua/custom/plugins/opencode.lua index c14e4086..d62b4c81 100644 --- a/lua/custom/plugins/opencode.lua +++ b/lua/custom/plugins/opencode.lua @@ -25,27 +25,7 @@ return { }, }, config = function() - local sidebar_filetypes = { - ['neo-tree'] = true, - ['snacks_layout_box'] = true, - ['snacks_terminal'] = true, - ['toggleterm'] = true, - ['opencode'] = true, - } - - local function focus_main_window() - for _, win in ipairs(vim.api.nvim_tabpage_list_wins(0)) do - local buf = vim.api.nvim_win_get_buf(win) - local ft = vim.bo[buf].filetype - local bt = vim.bo[buf].buftype - if not sidebar_filetypes[ft] and bt == '' then - vim.api.nvim_set_current_win(win) - return true - end - end - - return false - end + local layout = require 'custom.layout' ---@type opencode.Opts vim.g.opencode_opts = { @@ -85,15 +65,13 @@ return { vim.api.nvim_create_autocmd('VimEnter', { callback = function() - if vim.fn.argc() == 1 and vim.fn.isdirectory(vim.fn.argv(0)) == 1 then + local argv = vim.fn.argv() + local first_arg = argv[1] + if vim.fn.argc() == 1 and type(first_arg) == 'string' and vim.fn.isdirectory(first_arg) == 1 then vim.schedule(function() - pcall(function() require('persistence').load() end) - - vim.schedule(function() - focus_main_window() - require('opencode').toggle() - focus_main_window() - end) + layout.focus_main_window() + require('opencode').toggle() + layout.focus_main_window() end) end end,