feat(nvim): add PIM panel with calendar, alot mail, and abook
Adds itchyny/calendar.vim plugin and keybinds for a PIM sidebar: - r: full-screen tab with alot (top), calendar + abook (bottom split) - n/g/f: individual vsplit toggles for alot, calendar, abook - Restores <C-hjkl> window nav inside calendar buffers - shell-setup.sh installs notmuch, alot, abook (AUR) and syncs lazy.nvim Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>main
parent
867686e409
commit
00b178103e
|
|
@ -37,6 +37,7 @@ require("lazy").setup({
|
|||
"nvim-mini/mini.icons",
|
||||
"tadmccorkle/markdown.nvim",
|
||||
{ "ellisonleao/glow.nvim", config = true },
|
||||
"itchyny/calendar.vim",
|
||||
{
|
||||
"greggh/claude-code.nvim",
|
||||
dependencies = { "nvim-lua/plenary.nvim" },
|
||||
|
|
@ -92,6 +93,18 @@ vim.keymap.set("n", "<C-h>", "<C-w>h")
|
|||
vim.keymap.set("n", "<C-j>", "<C-w>j")
|
||||
vim.keymap.set("n", "<C-k>", "<C-w>k")
|
||||
|
||||
-- calendar.vim steals <C-hjkl> for month nav; restore window movement
|
||||
vim.api.nvim_create_autocmd("FileType", {
|
||||
pattern = "calendar",
|
||||
callback = function()
|
||||
local o = { buffer = true, silent = true }
|
||||
vim.keymap.set("n", "<C-l>", "<C-w>w", o)
|
||||
vim.keymap.set("n", "<C-h>", "<C-w>h", o)
|
||||
vim.keymap.set("n", "<C-j>", "<C-w>j", o)
|
||||
vim.keymap.set("n", "<C-k>", "<C-w>k", o)
|
||||
end,
|
||||
})
|
||||
|
||||
-- quick actions
|
||||
vim.keymap.set("n", "t", ":FloatermNew<CR>", { silent = true })
|
||||
vim.keymap.set("n", "e", ":NERDTreeToggle<CR><C-W>l", { silent = true })
|
||||
|
|
@ -145,3 +158,80 @@ end, { expr = true, silent = true })
|
|||
vim.keymap.set("i", "<CR>", function()
|
||||
return vim.fn["coc#pum#visible"]() == 1 and vim.fn["coc#pum#confirm"]() or "<CR>"
|
||||
end, { expr = true, silent = true })
|
||||
|
||||
-- ── PIM sidebar (calendar / notmuch / abook) ──────────────────────────────────
|
||||
local function _pim_scratch(label, err)
|
||||
vim.cmd("enew")
|
||||
vim.bo.buftype = "nofile"
|
||||
vim.bo.buflisted = false
|
||||
vim.api.nvim_buf_set_lines(0, 0, -1, false, { "[" .. label .. " unavailable]", "", err or "" })
|
||||
end
|
||||
|
||||
local function _pim_close_win(win)
|
||||
if not vim.api.nvim_win_is_valid(win) then return end
|
||||
local buf = vim.api.nvim_win_get_buf(win)
|
||||
vim.api.nvim_win_close(win, true)
|
||||
if vim.api.nvim_buf_is_valid(buf) and vim.bo[buf].buftype == "terminal" then
|
||||
pcall(vim.api.nvim_buf_delete, buf, { force = true })
|
||||
end
|
||||
end
|
||||
|
||||
-- individual toggles: n = notmuch/alot, g = calendar, f = find/abook
|
||||
local _solo = {}
|
||||
|
||||
local function toggle_solo(key, cmd, label, width)
|
||||
local win = _solo[key]
|
||||
if win and vim.api.nvim_win_is_valid(win) then
|
||||
_pim_close_win(win)
|
||||
_solo[key] = nil
|
||||
else
|
||||
local prev = vim.api.nvim_get_current_win()
|
||||
vim.cmd("topleft vsplit")
|
||||
vim.api.nvim_win_set_width(0, width)
|
||||
local ok, err = pcall(vim.cmd, cmd)
|
||||
if not ok then _pim_scratch(label, err) end
|
||||
_solo[key] = vim.api.nvim_get_current_win()
|
||||
vim.api.nvim_set_current_win(prev)
|
||||
end
|
||||
end
|
||||
|
||||
vim.keymap.set("n", "n", function() toggle_solo("n", "terminal alot", "alot", 55) end, { silent = true })
|
||||
vim.keymap.set("n", "g", function() toggle_solo("g", "Calendar", "calendar.vim", 35) end, { silent = true })
|
||||
vim.keymap.set("n", "f", function() toggle_solo("f", "terminal abook", "abook", 80) end, { silent = true })
|
||||
|
||||
-- r = full-screen PIM tab (mail top, calendar bottom-left, abook bottom-right)
|
||||
local _pim_tab = nil
|
||||
|
||||
local function toggle_pim()
|
||||
if _pim_tab and vim.api.nvim_tabpage_is_valid(_pim_tab) then
|
||||
vim.cmd("tabclose " .. vim.api.nvim_tabpage_get_number(_pim_tab))
|
||||
_pim_tab = nil
|
||||
return
|
||||
end
|
||||
|
||||
vim.cmd("tabnew")
|
||||
_pim_tab = vim.api.nvim_get_current_tabpage()
|
||||
|
||||
-- top pane: alot (mail), full width
|
||||
local ok, err = pcall(vim.cmd, "terminal alot")
|
||||
if not ok then _pim_scratch("alot", err) end
|
||||
|
||||
-- split bottom third for calendar + abook
|
||||
vim.cmd("belowright split")
|
||||
vim.cmd("resize 24")
|
||||
|
||||
-- bottom-left: calendar
|
||||
vim.cmd("leftabove vsplit")
|
||||
ok, err = pcall(vim.cmd, "Calendar")
|
||||
if not ok then _pim_scratch("calendar.vim", err) end
|
||||
|
||||
-- bottom-right: abook
|
||||
vim.cmd("wincmd l")
|
||||
ok, err = pcall(vim.cmd, "terminal abook")
|
||||
if not ok then _pim_scratch("abook", err) end
|
||||
|
||||
-- focus mail
|
||||
vim.cmd("wincmd k")
|
||||
end
|
||||
|
||||
vim.keymap.set("n", "r", toggle_pim, { silent = true })
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ log "Updating system..."
|
|||
sudo pacman -Syu --noconfirm
|
||||
|
||||
log "Installing base shell packages..."
|
||||
PACKAGES=(zsh neovim curl pyright bash atftp bash-language-server btop clang fastfetch fzf hyfetch lua-language-server micro nano pulsemixer yazi z qrencode distrobox dysk python python-pip glow)
|
||||
PACKAGES=(zsh neovim curl pyright bash atftp bash-language-server btop clang fastfetch fzf hyfetch lua-language-server micro nano pulsemixer yazi z qrencode distrobox dysk python python-pip glow notmuch alot)
|
||||
for pkg in "${PACKAGES[@]}"; do
|
||||
if ! pacman -Qi "$pkg" &>/dev/null; then
|
||||
log "Installing $pkg..."
|
||||
|
|
@ -16,6 +16,14 @@ for pkg in "${PACKAGES[@]}"; do
|
|||
fi
|
||||
done
|
||||
|
||||
# abook (AUR)
|
||||
if ! command -v abook &>/dev/null; then
|
||||
log "Installing abook (AUR)..."
|
||||
yay -S --noconfirm --needed abook
|
||||
else
|
||||
skip "abook already installed."
|
||||
fi
|
||||
|
||||
# yay
|
||||
if ! command -v yay &>/dev/null; then
|
||||
log "Installing yay..."
|
||||
|
|
@ -64,6 +72,9 @@ cp -r ~/Dotfiles/micro ~/.config/
|
|||
rm -rf ~/.config/nvim
|
||||
ln -sf ~/Dotfiles/nvim ~/.config/nvim
|
||||
|
||||
log "Syncing neovim plugins (lazy.nvim)..."
|
||||
nvim --headless "+Lazy! sync" +qa 2>/dev/null || true
|
||||
|
||||
rm -rf ~/.config/yazi
|
||||
ln -sf ~/Dotfiles/yazi ~/.config/yazi
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue