diff --git a/nvim/init.lua b/nvim/init.lua index 2ce1cdd..bba220d 100644 --- a/nvim/init.lua +++ b/nvim/init.lua @@ -1,19 +1,4 @@ --- This file simply bootstraps the installation of Lazy.nvim and then calls other files for execution --- This file doesn't necessarily need to be touched, BE CAUTIOUS editing this file and proceed at your own risk. -local lazypath = vim.env.LAZY or vim.fn.stdpath "data" .. "/lazy/lazy.nvim" -if not (vim.env.LAZY or (vim.uv or vim.loop).fs_stat(lazypath)) then - -- stylua: ignore - vim.fn.system({ "git", "clone", "--filter=blob:none", "https://github.com/folke/lazy.nvim.git", "--branch=stable", lazypath }) -end -vim.opt.rtp:prepend(lazypath) - --- validate that lazy is available -if not pcall(require, "lazy") then - -- stylua: ignore - vim.api.nvim_echo({ { ("Unable to load lazy from: %s\n"):format(lazypath), "ErrorMsg" }, { "Press any key to exit...", "MoreMsg" } }, true, {}) - vim.fn.getchar() - vim.cmd.quit() -end - -require "lazy_setup" -require "polish" +require("config.options") +require("config.lazy") +require("config.keymaps") +require("config.autocmds") diff --git a/nvim/lua/community.lua b/nvim/lua/community.lua deleted file mode 100644 index 4e22c9d..0000000 --- a/nvim/lua/community.lua +++ /dev/null @@ -1,14 +0,0 @@ --- AstroCommunity: import any community modules here --- We import this file in `lazy_setup.lua` before the `plugins/` folder. --- This guarantees that the specs are processed before any user plugins. - ----@type LazySpec -return { - "AstroNvim/astrocommunity", - { import = "astrocommunity.pack.lua" }, - { import = "astrocommunity.pack.ruby" }, - { import = "astrocommunity.pack.go" }, - { import = "astrocommunity.pack.typescript" }, - -- { import = "astrocommunity.markdown-and-latex.markdown-preview-nvim" }, -- replaced by glow.nvim - { import = "astrocommunity.recipes.auto-session-restore" }, -- セッション自動保存・復元 -} diff --git a/nvim/lua/config/autocmds.lua b/nvim/lua/config/autocmds.lua new file mode 100644 index 0000000..c20c86d --- /dev/null +++ b/nvim/lua/config/autocmds.lua @@ -0,0 +1,65 @@ +-- Autocommands + +local augroup = vim.api.nvim_create_augroup +local autocmd = vim.api.nvim_create_autocmd + +-- Auto-save on text change, insert leave, focus lost +autocmd({ "TextChanged", "InsertLeave", "FocusLost" }, { + group = augroup("auto_save", { clear = true }), + pattern = "*", + callback = function() + if vim.bo.modified and vim.bo.buftype == "" and vim.fn.expand("%") ~= "" then + vim.cmd("silent! write") + end + end, +}) + +-- Large file detection +local large_buf_group = augroup("large_buf", { clear = true }) +autocmd("BufReadPre", { + group = large_buf_group, + callback = function(args) + local ok, stats = pcall(vim.uv.fs_stat, vim.api.nvim_buf_get_name(args.buf)) + if ok and stats and stats.size > 1024 * 500 then + vim.b[args.buf].large_buf = true + vim.opt_local.spell = false + vim.opt_local.swapfile = false + vim.opt_local.undofile = false + vim.opt_local.foldmethod = "manual" + -- Disable treesitter highlight for large files + pcall(function() + vim.treesitter.stop(args.buf) + end) + end + end, +}) + +-- Highlight on yank +autocmd("TextYankPost", { + group = augroup("highlight_yank", { clear = true }), + callback = function() + vim.highlight.on_yank({ timeout = 200 }) + end, +}) + +-- Restore cursor position +autocmd("BufReadPost", { + group = augroup("restore_cursor", { clear = true }), + callback = function() + local mark = vim.api.nvim_buf_get_mark(0, '"') + local line_count = vim.api.nvim_buf_line_count(0) + if mark[1] > 0 and mark[1] <= line_count then + pcall(vim.api.nvim_win_set_cursor, 0, mark) + end + end, +}) + +-- Close certain filetypes with q +autocmd("FileType", { + group = augroup("close_with_q", { clear = true }), + pattern = { "help", "qf", "man", "notify", "lspinfo", "checkhealth" }, + callback = function(event) + vim.bo[event.buf].buflisted = false + vim.keymap.set("n", "q", "close", { buffer = event.buf, silent = true }) + end, +}) diff --git a/nvim/lua/config/keymaps.lua b/nvim/lua/config/keymaps.lua new file mode 100644 index 0000000..5256608 --- /dev/null +++ b/nvim/lua/config/keymaps.lua @@ -0,0 +1,39 @@ +-- Keymaps +local map = vim.keymap.set + +-- Buffer navigation +map("n", "]b", "bnext", { desc = "Next buffer" }) +map("n", "[b", "bprevious", { desc = "Previous buffer" }) + +-- Buffer close +map("n", "bd", "bdelete", { desc = "Close buffer" }) + +-- Copy relative file path +map("n", "cp", function() + local path = vim.fn.expand("%") + vim.fn.setreg("+", path) + vim.notify("Copied: " .. path) +end, { desc = "Copy relative file path" }) + +-- Window navigation +map("n", "", "h", { desc = "Move to left window" }) +map("n", "", "j", { desc = "Move to lower window" }) +map("n", "", "k", { desc = "Move to upper window" }) +map("n", "", "l", { desc = "Move to right window" }) + +-- Resize windows +map("n", "", "resize +2", { desc = "Increase window height" }) +map("n", "", "resize -2", { desc = "Decrease window height" }) +map("n", "", "vertical resize -2", { desc = "Decrease window width" }) +map("n", "", "vertical resize +2", { desc = "Increase window width" }) + +-- Move lines +map("v", "J", ":m '>+1gv=gv", { desc = "Move line down" }) +map("v", "K", ":m '<-2gv=gv", { desc = "Move line up" }) + +-- Better indenting +map("v", "<", "", ">gv") + +-- Clear search highlights +map("n", "", "nohlsearch", { desc = "Clear search highlights" }) diff --git a/nvim/lua/config/lazy.lua b/nvim/lua/config/lazy.lua new file mode 100644 index 0000000..23a0aa3 --- /dev/null +++ b/nvim/lua/config/lazy.lua @@ -0,0 +1,28 @@ +-- Bootstrap lazy.nvim +local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" +if not (vim.uv or vim.loop).fs_stat(lazypath) then + vim.fn.system({ + "git", "clone", "--filter=blob:none", + "https://github.com/folke/lazy.nvim.git", + "--branch=stable", lazypath, + }) +end +vim.opt.rtp:prepend(lazypath) + +require("lazy").setup({ + { import = "plugins" }, +}, { + install = { colorscheme = { "tokyonight-night", "habamax" } }, + ui = { backdrop = 100 }, + performance = { + rtp = { + disabled_plugins = { + "gzip", + "netrwPlugin", + "tarPlugin", + "tohtml", + "zipPlugin", + }, + }, + }, +}) diff --git a/nvim/lua/config/options.lua b/nvim/lua/config/options.lua new file mode 100644 index 0000000..2ae1657 --- /dev/null +++ b/nvim/lua/config/options.lua @@ -0,0 +1,43 @@ +-- Options: vim.opt, vim.g settings +-- Must be loaded before lazy.nvim + +vim.g.mapleader = " " +vim.g.maplocalleader = "," + +-- Editor options +vim.opt.relativenumber = true +vim.opt.number = true +vim.opt.spell = false +vim.opt.signcolumn = "yes" +vim.opt.wrap = false +vim.opt.termguicolors = true +vim.opt.clipboard = "unnamedplus" +vim.opt.undofile = true +vim.opt.showmode = false +vim.opt.splitbelow = true +vim.opt.splitright = true +vim.opt.cursorline = true +vim.opt.scrolloff = 8 +vim.opt.sidescrolloff = 8 +vim.opt.ignorecase = true +vim.opt.smartcase = true +vim.opt.updatetime = 300 +vim.opt.timeoutlen = 500 +vim.opt.completeopt = { "menu", "menuone", "noselect" } +vim.opt.shortmess:append("c") +vim.opt.fillchars = { eob = " " } + +-- Folding (for nvim-ufo) +vim.opt.foldcolumn = "1" +vim.opt.foldlevel = 99 +vim.opt.foldlevelstart = 99 +vim.opt.foldenable = true + +-- Diagnostics +vim.diagnostic.config({ + virtual_text = true, + underline = true, + signs = true, + update_in_insert = false, + severity_sort = true, +}) diff --git a/nvim/lua/lazy_setup.lua b/nvim/lua/lazy_setup.lua deleted file mode 100644 index 621de3b..0000000 --- a/nvim/lua/lazy_setup.lua +++ /dev/null @@ -1,32 +0,0 @@ -require("lazy").setup({ - { - "AstroNvim/AstroNvim", - version = "^4", -- Remove version tracking to elect for nighly AstroNvim - import = "astronvim.plugins", - opts = { -- AstroNvim options must be set here with the `import` key - mapleader = " ", -- This ensures the leader key must be configured before Lazy is set up - maplocalleader = ",", -- This ensures the localleader key must be configured before Lazy is set up - icons_enabled = true, -- Set to false to disable icons (if no Nerd Font is available) - pin_plugins = nil, -- Default will pin plugins when tracking `version` of AstroNvim, set to true/false to override - update_notifications = true, -- Enable/disable notification about running `:Lazy update` twice to update pinned plugins - }, - }, - { import = "community" }, - { import = "plugins" }, -} --[[@as LazySpec]], { - -- Configure any other `lazy.nvim` configuration options here - install = { colorscheme = { "astrodark", "habamax" } }, - ui = { backdrop = 100 }, - performance = { - rtp = { - -- disable some rtp plugins, add more to your liking - disabled_plugins = { - "gzip", - "netrwPlugin", - "tarPlugin", - "tohtml", - "zipPlugin", - }, - }, - }, -} --[[@as LazyConfig]]) diff --git a/nvim/lua/plugins/activity-monitor.lua b/nvim/lua/plugins/activity-monitor.lua index f2c69e3..21248c0 100644 --- a/nvim/lua/plugins/activity-monitor.lua +++ b/nvim/lua/plugins/activity-monitor.lua @@ -18,13 +18,14 @@ ---@field free_mem_gb number ---@field mem_percent number --- Module-level cache for statusline (matches gwq worktree_cache pattern) -local stats_cache = { +-- Use global cache shared with statusline.lua +_G._activity_stats_cache = _G._activity_stats_cache or { cpu_total = 0, mem_percent = 0, top_process = "", updated_at = 0, } +local stats_cache = _G._activity_stats_cache local refresh_timer = nil local CACHE_TTL_SEC = 10 @@ -90,17 +91,17 @@ local function fetch_vm_stat(callback) if val then return tonumber((val:gsub("%.", ""))) or 0 end return 0 end - local free = extract "Pages free:%s+(%d+%.)" - local active = extract "Pages active:%s+(%d+%.)" - local wired = extract "Pages wired down:%s+(%d+%.)" + local free = extract("Pages free:%s+(%d+%.)") + local active = extract("Pages active:%s+(%d+%.)") + local wired = extract("Pages wired down:%s+(%d+%.)") local used_bytes = (active + wired) * PAGE_SIZE - callback { + callback({ total_mem_gb = TOTAL_MEM / (1024 ^ 3), used_mem_gb = used_bytes / (1024 ^ 3), free_mem_gb = (TOTAL_MEM - used_bytes) / (1024 ^ 3), mem_percent = (used_bytes / TOTAL_MEM) * 100, - } + }) end) end) end @@ -152,7 +153,7 @@ local function fetch_processes(callback) local processes = {} for i = 2, #lines do local pid, cpu, mem, rss, user, comm = - lines[i]:match "^%s*(%d+)%s+([%d.]+)%s+([%d.]+)%s+(%d+)%s+(%S+)%s+(.+)$" + lines[i]:match("^%s*(%d+)%s+([%d.]+)%s+([%d.]+)%s+(%d+)%s+(%S+)%s+(.+)$") if pid then local p = { pid = tonumber(pid), @@ -162,7 +163,7 @@ local function fetch_processes(callback) user = user, comm = vim.fn.fnamemodify(vim.trim(comm), ":t"), full_cmd = vim.trim(comm), - is_killable = (user == os.getenv "USER"), + is_killable = (user == os.getenv("USER")), recommendation = nil, } p.recommendation = compute_recommendation(p) @@ -182,8 +183,8 @@ end ---@param signal number ---@param reopen_fn fun() local function kill_process(prompt_bufnr, signal, reopen_fn) - local action_state = require "telescope.actions.state" - local actions = require "telescope.actions" + local action_state = require("telescope.actions.state") + local actions = require("telescope.actions") local selection = action_state.get_selected_entry() if not selection then return end @@ -230,13 +231,13 @@ local function process_picker(opts, sort_by) opts = opts or {} sort_by = sort_by or "cpu" - local pickers = require "telescope.pickers" - local finders = require "telescope.finders" + local pickers = require("telescope.pickers") + local finders = require("telescope.finders") local conf = require("telescope.config").values - local actions = require "telescope.actions" - local action_state = require "telescope.actions.state" - local entry_display = require "telescope.pickers.entry_display" - local previewers = require "telescope.previewers" + local actions = require("telescope.actions") + local action_state = require("telescope.actions.state") + local entry_display = require("telescope.pickers.entry_display") + local previewers = require("telescope.previewers") fetch_processes(function(processes) if not processes or #processes == 0 then @@ -257,7 +258,7 @@ local function process_picker(opts, sort_by) stats_cache.top_process = processes[1] and processes[1].comm or "" stats_cache.updated_at = os.clock() - local displayer = entry_display.create { + local displayer = entry_display.create({ separator = " ", items = { { width = 2 }, @@ -268,12 +269,12 @@ local function process_picker(opts, sort_by) { width = 12 }, { remaining = true }, }, - } + }) pickers .new(opts, { prompt_title = "Activity Monitor (sort: " .. sort_by .. ")", - finder = finders.new_table { + finder = finders.new_table({ results = processes, entry_maker = function(proc) return { @@ -287,7 +288,7 @@ local function process_picker(opts, sort_by) local mem_hl = p.mem > 5 and "DiagnosticError" or p.mem > 2 and "DiagnosticWarn" or "TelescopeResultsNumber" - return displayer { + return displayer({ { indicator, p.recommendation and "DiagnosticWarn" or "Normal" }, { tostring(p.pid), "TelescopeResultsComment" }, { string.format("%.1f%%", p.cpu), cpu_hl }, @@ -295,14 +296,14 @@ local function process_picker(opts, sort_by) { format_rss(p.rss), "TelescopeResultsNumber" }, { p.user, "TelescopeResultsComment" }, { p.comm, "TelescopeResultsIdentifier" }, - } + }) end, ordinal = proc.comm .. " " .. tostring(proc.pid) .. " " .. proc.user, } end, - }, + }), sorter = conf.generic_sorter(opts), - previewer = previewers.new_buffer_previewer { + previewer = previewers.new_buffer_previewer({ title = "Process Details", define_preview = function(self, entry) local p = entry.value @@ -326,7 +327,7 @@ local function process_picker(opts, sort_by) end vim.api.nvim_buf_set_lines(self.state.bufnr, 0, -1, false, lines) end, - }, + }), attach_mappings = function(prompt_bufnr, map) actions.select_default:replace(function() local selection = action_state.get_selected_entry() @@ -375,13 +376,13 @@ end ---@param opts? table flagged_picker = function(opts) opts = opts or {} - local pickers = require "telescope.pickers" - local finders = require "telescope.finders" + local pickers = require("telescope.pickers") + local finders = require("telescope.finders") local conf = require("telescope.config").values - local actions = require "telescope.actions" - local action_state = require "telescope.actions.state" - local entry_display = require "telescope.pickers.entry_display" - local previewers = require "telescope.previewers" + local actions = require("telescope.actions") + local action_state = require("telescope.actions.state") + local entry_display = require("telescope.pickers.entry_display") + local previewers = require("telescope.previewers") fetch_processes(function(processes) local flagged = vim.tbl_filter(function(p) return p.recommendation ~= nil end, processes) @@ -390,7 +391,7 @@ flagged_picker = function(opts) return end - local displayer = entry_display.create { + local displayer = entry_display.create({ separator = " ", items = { { width = 7 }, @@ -400,33 +401,33 @@ flagged_picker = function(opts) { width = 20 }, { remaining = true }, }, - } + }) pickers .new(opts, { prompt_title = "Flagged Processes (" .. #flagged .. " found)", - finder = finders.new_table { + finder = finders.new_table({ results = flagged, entry_maker = function(proc) return { value = proc, display = function(entry) local p = entry.value - return displayer { + return displayer({ { tostring(p.pid), "TelescopeResultsComment" }, { string.format("%.1f%%", p.cpu), "DiagnosticWarn" }, { string.format("%.1f%%", p.mem), "DiagnosticWarn" }, { format_rss(p.rss), "TelescopeResultsNumber" }, { p.comm, "TelescopeResultsIdentifier" }, { p.recommendation or "", "DiagnosticHint" }, - } + }) end, ordinal = proc.comm .. " " .. tostring(proc.pid), } end, - }, + }), sorter = conf.generic_sorter(opts), - previewer = previewers.new_buffer_previewer { + previewer = previewers.new_buffer_previewer({ title = "Process Details", define_preview = function(self, entry) local p = entry.value @@ -443,7 +444,7 @@ flagged_picker = function(opts) } vim.api.nvim_buf_set_lines(self.state.bufnr, 0, -1, false, lines) end, - }, + }), attach_mappings = function(prompt_bufnr, map) actions.select_default:replace(function() local selection = action_state.get_selected_entry() @@ -531,99 +532,59 @@ local function stop_stats_refresh() end end --- ── Plugin Specs ───────────────────────────────────────────────── +-- ── Plugin Spec ───────────────────────────────────────────────── ---@type LazySpec return { { - "AstroNvim/astrocore", - ---@type AstroCoreOpts - opts = function(_, opts) - local maps = opts.mappings or {} - - maps.n["a"] = { desc = "Activity Monitor" } - maps.n["aa"] = { function() process_picker() end, desc = "Process list (CPU)" } - maps.n["am"] = { function() process_picker({}, "mem") end, desc = "Process list (Memory)" } - maps.n["af"] = { function() flagged_picker() end, desc = "Flagged processes" } - maps.n["as"] = { function() show_system_summary() end, desc = "System summary" } - - opts.commands = opts.commands or {} - opts.commands.ActivityMonitor = { function() process_picker() end, desc = "Open activity monitor" } - opts.commands.ActivitySummary = { - function() show_system_summary() end, - desc = "Show system resource summary", - } - opts.commands.ActivityKill = { - function(cmd) - local pid = tonumber(cmd.args) - if not pid then - vim.notify("Usage: :ActivityKill ", vim.log.levels.WARN) - return - end - vim.ui.input({ prompt = "Kill PID " .. pid .. "? (y/N): " }, function(input) - if input and input:lower() == "y" then - vim.system({ "kill", "-15", tostring(pid) }, { text = true }, function(result) - vim.schedule(function() - if result.code == 0 then - vim.notify("Killed PID " .. pid) - else - vim.notify("Failed: " .. (result.stderr or ""), vim.log.levels.ERROR) - end - end) - end) - end + "nvim-telescope/telescope.nvim", + keys = { + { "a", "", desc = "Activity Monitor" }, + { "aa", function() process_picker() end, desc = "Process list (CPU)" }, + { "am", function() process_picker({}, "mem") end, desc = "Process list (Memory)" }, + { "af", function() flagged_picker() end, desc = "Flagged processes" }, + { "as", function() show_system_summary() end, desc = "System summary" }, + }, + init = function() + -- User commands + vim.api.nvim_create_user_command("ActivityMonitor", function() process_picker() end, { desc = "Open activity monitor" }) + vim.api.nvim_create_user_command("ActivitySummary", function() show_system_summary() end, { desc = "Show system resource summary" }) + vim.api.nvim_create_user_command("ActivityKill", function(cmd) + local pid = tonumber(cmd.args) + if not pid then + vim.notify("Usage: :ActivityKill ", vim.log.levels.WARN) + return + end + vim.ui.input({ prompt = "Kill PID " .. pid .. "? (y/N): " }, function(input) + if input and input:lower() == "y" then + vim.system({ "kill", "-15", tostring(pid) }, { text = true }, function(result) + vim.schedule(function() + if result.code == 0 then + vim.notify("Killed PID " .. pid) + else + vim.notify("Failed: " .. (result.stderr or ""), vim.log.levels.ERROR) + end + end) end) - end, - nargs = 1, - desc = "Kill process by PID", - } - - opts.autocmds = opts.autocmds or {} - opts.autocmds.activity_monitor_refresh = { - { - event = "VimEnter", - desc = "Start activity monitor stats refresh", - callback = function() - fetch_total_memory(function(bytes) TOTAL_MEM = bytes end) - start_stats_refresh() - end, - }, - { - event = "VimLeavePre", - desc = "Stop activity monitor stats refresh", - callback = stop_stats_refresh, - }, - } - end, - }, - - { - "rebelot/heirline.nvim", - opts = function(_, opts) - if not opts.statusline then return end - - local activity_component = { - condition = function() return stats_cache.updated_at > 0 end, - provider = function() - return string.format(" CPU:%.0f%% Mem:%.0f%% ", stats_cache.cpu_total, stats_cache.mem_percent) - end, - hl = function() - if stats_cache.mem_percent > 80 or stats_cache.cpu_total > 200 then - return { fg = "#ed8796", bold = true } - elseif stats_cache.mem_percent > 60 or stats_cache.cpu_total > 100 then - return { fg = "#f5a97f", bold = true } - else - return { fg = "#a6da95" } - end - end, - on_click = { - callback = function() process_picker() end, - name = "activity_monitor_click", - }, - } - - local insert_pos = math.max(#opts.statusline, 1) - table.insert(opts.statusline, insert_pos, activity_component) - end, + end + end) + end, { nargs = 1, desc = "Kill process by PID" }) + + -- Autocmds for background refresh + local group = vim.api.nvim_create_augroup("activity_monitor_refresh", { clear = true }) + vim.api.nvim_create_autocmd("VimEnter", { + group = group, + desc = "Start activity monitor stats refresh", + callback = function() + fetch_total_memory(function(bytes) TOTAL_MEM = bytes end) + start_stats_refresh() + end, + }) + vim.api.nvim_create_autocmd("VimLeavePre", { + group = group, + desc = "Stop activity monitor stats refresh", + callback = stop_stats_refresh, + }) + end, }, } diff --git a/nvim/lua/plugins/ai-review.lua b/nvim/lua/plugins/ai-review.lua index 3c87156..c09a0d4 100644 --- a/nvim/lua/plugins/ai-review.lua +++ b/nvim/lua/plugins/ai-review.lua @@ -1,4 +1,3 @@ ----@type LazySpec return { dir = vim.fn.expand("~/ghq/github.com/o8n/ai-review.nvim"), cmd = "AIReview", @@ -6,19 +5,8 @@ return { review_script = vim.fn.expand("~/.dotfiles/hooks/lib/dual-review.sh"), notify = true, }, - specs = { - { - "AstroNvim/astrocore", - opts = function(_, opts) - opts.mappings.n["ar"] = { - "AIReview", - desc = "AI Review (staged)", - } - opts.mappings.n["aR"] = { - "AIReview --push", - desc = "AI Review (push)", - } - end, - }, + keys = { + { "ar", "AIReview", desc = "AI Review (staged)" }, + { "aR", "AIReview --push", desc = "AI Review (push)" }, }, } diff --git a/nvim/lua/plugins/astrocore.lua b/nvim/lua/plugins/astrocore.lua deleted file mode 100644 index b545375..0000000 --- a/nvim/lua/plugins/astrocore.lua +++ /dev/null @@ -1,80 +0,0 @@ --- AstroCore provides a central place to modify mappings, vim options, autocommands, and more! --- Configuration documentation can be found with `:h astrocore` --- NOTE: We highly recommend setting up the Lua Language Server (`:LspInstall lua_ls`) --- as this provides autocomplete and documentation while editing - ----@type LazySpec -return { - "AstroNvim/astrocore", - ---@type AstroCoreOpts - opts = { - -- Configure core features of AstroNvim - features = { - large_buf = { size = 1024 * 500, lines = 10000 }, -- set global limits for large files for disabling features like treesitter - autopairs = true, -- enable autopairs at start - cmp = true, -- enable completion at start - diagnostics_mode = 3, -- diagnostic mode on start (0 = off, 1 = no signs/virtual text, 2 = no virtual text, 3 = on) - highlighturl = true, -- highlight URLs at start - notifications = true, -- enable notifications at start - }, - -- Diagnostics configuration (for vim.diagnostics.config({...})) when diagnostics are on - diagnostics = { - virtual_text = true, - underline = true, - }, - -- vim options can be configured here - options = { - opt = { -- vim.opt. - relativenumber = true, -- sets vim.opt.relativenumber - number = true, -- sets vim.opt.number - spell = false, -- sets vim.opt.spell - signcolumn = "yes", -- sets vim.opt.signcolumn to yes - wrap = false, -- sets vim.opt.wrap - }, - g = { -- vim.g. - -- configure global vim variables (vim.g) - -- NOTE: `mapleader` and `maplocalleader` must be set in the AstroNvim opts or before `lazy.setup` - -- This can be found in the `lua/lazy_setup.lua` file - }, - }, - -- Mappings can be configured through AstroCore as well. - -- NOTE: keycodes follow the casing in the vimdocs. For example, `` must be capitalized - mappings = { - -- first key is the mode - n = { - -- second key is the lefthand side of the map - - -- navigate buffer tabs - ["]b"] = { function() require("astrocore.buffer").nav(vim.v.count1) end, desc = "Next buffer" }, - ["[b"] = { function() require("astrocore.buffer").nav(-vim.v.count1) end, desc = "Previous buffer" }, - - -- copy file path - ["cp"] = { - function() - local path = vim.fn.expand("%") - vim.fn.setreg("+", path) - vim.notify("Copied: " .. path) - end, - desc = "Copy relative file path", - }, - - -- mappings seen under group name "Buffer" - ["bd"] = { - function() - require("astroui.status.heirline").buffer_picker( - function(bufnr) require("astrocore.buffer").close(bufnr) end - ) - end, - desc = "Close buffer from tabline", - }, - - -- tables with just a `desc` key will be registered with which-key if it's installed - -- this is useful for naming menus - -- ["b"] = { desc = "Buffers" }, - - -- disable Telescope live_grep (replaced by fff.nvim) - ["fw"] = false, - }, - }, - }, -} diff --git a/nvim/lua/plugins/astrolsp.lua b/nvim/lua/plugins/astrolsp.lua deleted file mode 100644 index 7bde432..0000000 --- a/nvim/lua/plugins/astrolsp.lua +++ /dev/null @@ -1,106 +0,0 @@ -if true then return {} end -- WARN: REMOVE THIS LINE TO ACTIVATE THIS FILE - --- AstroLSP allows you to customize the features in AstroNvim's LSP configuration engine --- Configuration documentation can be found with `:h astrolsp` --- NOTE: We highly recommend setting up the Lua Language Server (`:LspInstall lua_ls`) --- as this provides autocomplete and documentation while editing - ----@type LazySpec -return { - "AstroNvim/astrolsp", - ---@type AstroLSPOpts - opts = { - -- Configuration table of features provided by AstroLSP - features = { - autoformat = true, -- enable or disable auto formatting on start - codelens = true, -- enable/disable codelens refresh on start - inlay_hints = false, -- enable/disable inlay hints on start - semantic_tokens = true, -- enable/disable semantic token highlighting - }, - -- customize lsp formatting options - formatting = { - -- control auto formatting on save - format_on_save = { - enabled = true, -- enable or disable format on save globally - allow_filetypes = { -- enable format on save for specified filetypes only - -- "go", - }, - ignore_filetypes = { -- disable format on save for specified filetypes - -- "python", - }, - }, - disabled = { -- disable formatting capabilities for the listed language servers - -- disable lua_ls formatting capability if you want to use StyLua to format your lua code - -- "lua_ls", - }, - timeout_ms = 1000, -- default format timeout - -- filter = function(client) -- fully override the default formatting function - -- return true - -- end - }, - -- enable servers that you already have installed without mason - servers = { - -- "pyright" - }, - -- customize language server configuration options passed to `lspconfig` - ---@diagnostic disable: missing-fields - config = { - -- clangd = { capabilities = { offsetEncoding = "utf-8" } }, - }, - -- customize how language servers are attached - handlers = { - -- a function without a key is simply the default handler, functions take two parameters, the server name and the configured options table for that server - -- function(server, opts) require("lspconfig")[server].setup(opts) end - - -- the key is the server that is being setup with `lspconfig` - -- rust_analyzer = false, -- setting a handler to false will disable the set up of that language server - -- pyright = function(_, opts) require("lspconfig").pyright.setup(opts) end -- or a custom handler function can be passed - }, - -- Configure buffer local auto commands to add when attaching a language server - autocmds = { - -- first key is the `augroup` to add the auto commands to (:h augroup) - lsp_codelens_refresh = { - -- Optional condition to create/delete auto command group - -- can either be a string of a client capability or a function of `fun(client, bufnr): boolean` - -- condition will be resolved for each client on each execution and if it ever fails for all clients, - -- the auto commands will be deleted for that buffer - cond = "textDocument/codeLens", - -- cond = function(client, bufnr) return client.name == "lua_ls" end, - -- list of auto commands to set - { - -- events to trigger - event = { "InsertLeave", "BufEnter" }, - -- the rest of the autocmd options (:h nvim_create_autocmd) - desc = "Refresh codelens (buffer)", - callback = function(args) - if require("astrolsp").config.features.codelens then vim.lsp.codelens.refresh { bufnr = args.buf } end - end, - }, - }, - }, - -- mappings to be set up on attaching of a language server - mappings = { - n = { - -- a `cond` key can provided as the string of a server capability to be required to attach, or a function with `client` and `bufnr` parameters from the `on_attach` that returns a boolean - gD = { - function() vim.lsp.buf.declaration() end, - desc = "Declaration of current symbol", - cond = "textDocument/declaration", - }, - ["uY"] = { - function() require("astrolsp.toggles").buffer_semantic_tokens() end, - desc = "Toggle LSP semantic highlight (buffer)", - cond = function(client) - return client.supports_method "textDocument/semanticTokens/full" and vim.lsp.semantic_tokens ~= nil - end, - }, - }, - }, - -- A custom `on_attach` function to be run after the default `on_attach` function - -- takes two parameters `client` and `bufnr` (`:h lspconfig-setup`) - on_attach = function(client, bufnr) - -- this would disable semanticTokensProvider for all clients - -- client.server_capabilities.semanticTokensProvider = nil - end, - }, -} diff --git a/nvim/lua/plugins/astroui.lua b/nvim/lua/plugins/astroui.lua deleted file mode 100644 index 737a2fb..0000000 --- a/nvim/lua/plugins/astroui.lua +++ /dev/null @@ -1,39 +0,0 @@ -if true then return {} end -- WARN: REMOVE THIS LINE TO ACTIVATE THIS FILE - --- AstroUI provides the basis for configuring the AstroNvim User Interface --- Configuration documentation can be found with `:h astroui` --- NOTE: We highly recommend setting up the Lua Language Server (`:LspInstall lua_ls`) --- as this provides autocomplete and documentation while editing - ----@type LazySpec -return { - "AstroNvim/astroui", - ---@type AstroUIOpts - opts = { - -- change colorscheme - colorscheme = "astrodark", - -- AstroUI allows you to easily modify highlight groups easily for any and all colorschemes - highlights = { - init = { -- this table overrides highlights in all themes - -- Normal = { bg = "#000000" }, - }, - astrodark = { -- a table of overrides/changes when applying the astrotheme theme - -- Normal = { bg = "#000000" }, - }, - }, - -- Icons can be configured throughout the interface - icons = { - -- configure the loading of the lsp in the status line - LSPLoading1 = "⠋", - LSPLoading2 = "⠙", - LSPLoading3 = "⠹", - LSPLoading4 = "⠸", - LSPLoading5 = "⠼", - LSPLoading6 = "⠴", - LSPLoading7 = "⠦", - LSPLoading8 = "⠧", - LSPLoading9 = "⠇", - LSPLoading10 = "⠏", - }, - }, -} diff --git a/nvim/lua/plugins/cmp-cmdline.lua b/nvim/lua/plugins/cmp-cmdline.lua deleted file mode 100644 index e3dd348..0000000 --- a/nvim/lua/plugins/cmp-cmdline.lua +++ /dev/null @@ -1,35 +0,0 @@ ----@type LazySpec -return { - "hrsh7th/nvim-cmp", - keys = { ":", "/", "?" }, - dependencies = { - "hrsh7th/cmp-cmdline", - }, - config = function(plugin, opts) - require "astronvim.plugins.configs.cmp"(plugin, opts) - local cmp = require "cmp" - - -- `/` `?` 検索補完(バッファの単語から) - cmp.setup.cmdline({ "/", "?" }, { - mapping = cmp.mapping.preset.cmdline(), - sources = { - { name = "buffer" }, - }, - }) - - -- `:` コマンドライン補完 - cmp.setup.cmdline(":", { - mapping = cmp.mapping.preset.cmdline(), - sources = cmp.config.sources({ - { name = "path" }, - }, { - { - name = "cmdline", - option = { - ignore_cmds = { "Man", "!" }, - }, - }, - }), - }) - end, -} diff --git a/nvim/lua/plugins/cmp.lua b/nvim/lua/plugins/cmp.lua new file mode 100644 index 0000000..b6e3270 --- /dev/null +++ b/nvim/lua/plugins/cmp.lua @@ -0,0 +1,89 @@ +-- Completion: nvim-cmp +return { + "hrsh7th/nvim-cmp", + event = { "InsertEnter", "CmdlineEnter" }, + dependencies = { + "hrsh7th/cmp-nvim-lsp", + "hrsh7th/cmp-buffer", + "hrsh7th/cmp-path", + "hrsh7th/cmp-cmdline", + "L3MON4D3/LuaSnip", + "saadparwaiz1/cmp_luasnip", + "onsails/lspkind.nvim", + }, + config = function() + local cmp = require("cmp") + local luasnip = require("luasnip") + local lspkind = require("lspkind") + + cmp.setup({ + snippet = { + expand = function(args) + luasnip.lsp_expand(args.body) + end, + }, + mapping = cmp.mapping.preset.insert({ + [""] = cmp.mapping.scroll_docs(-4), + [""] = cmp.mapping.scroll_docs(4), + [""] = cmp.mapping.complete(), + [""] = cmp.mapping.abort(), + [""] = cmp.mapping.confirm({ select = false }), + [""] = cmp.mapping(function(fallback) + if cmp.visible() then + cmp.select_next_item() + elseif luasnip.expand_or_jumpable() then + luasnip.expand_or_jump() + else + fallback() + end + end, { "i", "s" }), + [""] = cmp.mapping(function(fallback) + if cmp.visible() then + cmp.select_prev_item() + elseif luasnip.jumpable(-1) then + luasnip.jump(-1) + else + fallback() + end + end, { "i", "s" }), + }), + sources = cmp.config.sources({ + { name = "nvim_lsp" }, + { name = "luasnip" }, + }, { + { name = "buffer" }, + { name = "path" }, + }), + formatting = { + format = lspkind.cmp_format({ + mode = "symbol_text", + maxwidth = 50, + ellipsis_char = "...", + }), + }, + }) + + -- `/` `?` search completion + cmp.setup.cmdline({ "/", "?" }, { + mapping = cmp.mapping.preset.cmdline(), + sources = { + { name = "buffer" }, + }, + }) + + -- `:` command completion + cmp.setup.cmdline(":", { + mapping = cmp.mapping.preset.cmdline(), + sources = cmp.config.sources({ + { name = "path" }, + }, { + { + name = "cmdline", + option = { + ignore_cmds = { "Man", "!" }, + }, + }, + }), + }) + end, +} diff --git a/nvim/lua/plugins/colorscheme.lua b/nvim/lua/plugins/colorscheme.lua new file mode 100644 index 0000000..a7d2a92 --- /dev/null +++ b/nvim/lua/plugins/colorscheme.lua @@ -0,0 +1,12 @@ +return { + "folke/tokyonight.nvim", + lazy = false, + priority = 1000, + opts = { + style = "night", + }, + config = function(_, opts) + require("tokyonight").setup(opts) + vim.cmd.colorscheme("tokyonight-night") + end, +} diff --git a/nvim/lua/plugins/dap.lua b/nvim/lua/plugins/dap.lua new file mode 100644 index 0000000..1c207f6 --- /dev/null +++ b/nvim/lua/plugins/dap.lua @@ -0,0 +1,30 @@ +-- Debug Adapter Protocol +return { + { + "mfussenegger/nvim-dap", + dependencies = { + "rcarriga/nvim-dap-ui", + "nvim-neotest/nvim-nio", + "leoluz/nvim-dap-go", + }, + keys = { + { "db", function() require("dap").toggle_breakpoint() end, desc = "Toggle breakpoint" }, + { "dc", function() require("dap").continue() end, desc = "Continue" }, + { "di", function() require("dap").step_into() end, desc = "Step into" }, + { "do", function() require("dap").step_over() end, desc = "Step over" }, + { "dO", function() require("dap").step_out() end, desc = "Step out" }, + { "dr", function() require("dap").repl.open() end, desc = "Open REPL" }, + { "du", function() require("dapui").toggle() end, desc = "Toggle DAP UI" }, + }, + config = function() + local dapui = require("dapui") + dapui.setup() + require("dap-go").setup() + + local dap = require("dap") + dap.listeners.after.event_initialized["dapui_config"] = function() dapui.open() end + dap.listeners.before.event_terminated["dapui_config"] = function() dapui.close() end + dap.listeners.before.event_exited["dapui_config"] = function() dapui.close() end + end, + }, +} diff --git a/nvim/lua/plugins/editing.lua b/nvim/lua/plugins/editing.lua new file mode 100644 index 0000000..e00ba79 --- /dev/null +++ b/nvim/lua/plugins/editing.lua @@ -0,0 +1,80 @@ +-- Editing: autopairs, snippets, comments, etc. +return { + -- Autopairs + { + "windwp/nvim-autopairs", + event = "InsertEnter", + config = function() + local npairs = require("nvim-autopairs") + npairs.setup({}) + local Rule = require("nvim-autopairs.rule") + local cond = require("nvim-autopairs.conds") + npairs.add_rules({ + Rule("$", "$", { "tex", "latex" }) + :with_pair(cond.not_after_regex("%%")) + :with_pair(cond.not_before_regex("xxx", 3)) + :with_move(cond.none()) + :with_del(cond.not_after_regex("xx")) + :with_cr(cond.none()), + Rule("a", "a", "-vim"), + }) + end, + }, + -- Snippets + { + "L3MON4D3/LuaSnip", + version = "v2.*", + build = "make install_jsregexp", + dependencies = { "rafamadriz/friendly-snippets" }, + config = function() + local luasnip = require("luasnip") + luasnip.setup({}) + require("luasnip.loaders.from_vscode").lazy_load() + luasnip.filetype_extend("javascript", { "javascriptreact" }) + end, + }, + -- Comments + { + "numToStr/Comment.nvim", + event = { "BufReadPost", "BufNewFile" }, + opts = {}, + }, + -- Indent guides + { + "lukas-reineke/indent-blankline.nvim", + main = "ibl", + event = { "BufReadPost", "BufNewFile" }, + opts = {}, + }, + -- Word illumination + { + "RRethy/vim-illuminate", + event = { "BufReadPost", "BufNewFile" }, + config = function() + require("illuminate").configure({ + delay = 200, + large_file_cutoff = 2000, + }) + end, + }, + -- Todo comments + { + "folke/todo-comments.nvim", + dependencies = { "nvim-lua/plenary.nvim" }, + event = { "BufReadPost", "BufNewFile" }, + opts = {}, + }, + -- Auto-detect indent + { + "NMAC427/guess-indent.nvim", + event = { "BufReadPost", "BufNewFile" }, + opts = {}, + }, + -- Folding + { + "kevinhwang91/nvim-ufo", + dependencies = { "kevinhwang91/promise-async" }, + event = "BufReadPost", + opts = {}, + }, +} diff --git a/nvim/lua/plugins/git-conflict.lua b/nvim/lua/plugins/git-conflict.lua index 9b578e6..4f1c5ff 100644 --- a/nvim/lua/plugins/git-conflict.lua +++ b/nvim/lua/plugins/git-conflict.lua @@ -1,8 +1,7 @@ ----@type LazySpec return { "akinsho/git-conflict.nvim", version = "*", - event = "User AstroGitFile", + event = "VeryLazy", opts = { default_mappings = true, default_commands = true, @@ -12,20 +11,14 @@ return { current = "DiffText", }, }, - specs = { - { - "AstroNvim/astrocore", - opts = function(_, opts) - local maps = opts.mappings - maps.n["gx"] = { desc = "Git Conflict" } - maps.n["gxo"] = { "GitConflictChooseOurs", desc = "Choose current (ours)" } - maps.n["gxt"] = { "GitConflictChooseTheirs", desc = "Choose incoming (theirs)" } - maps.n["gxb"] = { "GitConflictChooseBoth", desc = "Choose both" } - maps.n["gx0"] = { "GitConflictChooseNone", desc = "Choose none" } - maps.n["gxn"] = { "GitConflictNextConflict", desc = "Next conflict" } - maps.n["gxp"] = { "GitConflictPrevConflict", desc = "Previous conflict" } - maps.n["gxq"] = { "GitConflictListQf", desc = "List conflicts (quickfix)" } - end, - }, + keys = { + { "gx", "", desc = "Git Conflict" }, + { "gxo", "GitConflictChooseOurs", desc = "Choose current (ours)" }, + { "gxt", "GitConflictChooseTheirs", desc = "Choose incoming (theirs)" }, + { "gxb", "GitConflictChooseBoth", desc = "Choose both" }, + { "gx0", "GitConflictChooseNone", desc = "Choose none" }, + { "gxn", "GitConflictNextConflict", desc = "Next conflict" }, + { "gxp", "GitConflictPrevConflict", desc = "Previous conflict" }, + { "gxq", "GitConflictListQf", desc = "List conflicts (quickfix)" }, }, } diff --git a/nvim/lua/plugins/gitsigns.lua b/nvim/lua/plugins/gitsigns.lua new file mode 100644 index 0000000..e35e380 --- /dev/null +++ b/nvim/lua/plugins/gitsigns.lua @@ -0,0 +1,14 @@ +return { + "lewis6991/gitsigns.nvim", + event = { "BufReadPre", "BufNewFile" }, + opts = { + current_line_blame = true, + current_line_blame_opts = { + virt_text = true, + virt_text_pos = "eol", + delay = 500, + ignore_whitespace = false, + }, + current_line_blame_formatter = ", - ", + }, +} diff --git a/nvim/lua/plugins/gwq-ghq.lua b/nvim/lua/plugins/gwq-ghq.lua index 123f2d4..ea41c58 100644 --- a/nvim/lua/plugins/gwq-ghq.lua +++ b/nvim/lua/plugins/gwq-ghq.lua @@ -1,14 +1,15 @@ --- gwq (Git Worktree Manager) + ghq integration for AstroNvim v4 +-- gwq (Git Worktree Manager) + ghq integration -- Provides Telescope pickers, commands, session integration, and statusline indicator -local gwq_bin = vim.fn.expand "$HOME/go/bin/gwq" +local gwq_bin = vim.fn.expand("$HOME/go/bin/gwq") local ghq_bin = "/opt/homebrew/bin/ghq" --- Worktree info cache for statusline (module-level) -local worktree_cache = { +-- Use global cache shared with statusline.lua +_G._gwq_worktree_cache = _G._gwq_worktree_cache or { branch = nil, is_worktree = false, } +local worktree_cache = _G._gwq_worktree_cache ---Run a shell command asynchronously and return parsed JSON via callback ---@param cmd string @@ -60,14 +61,13 @@ local function switch_to_directory(target_path) -- Save current session local resession_ok, resession = pcall(require, "resession") if resession_ok then - local buf_utils = require "astrocore.buffer" - if buf_utils.is_valid_session() then + if vim.fn.expand("%") ~= "" then resession.save(cwd, { dir = "dirsession", notify = false }) end end -- Close all buffers - vim.cmd "silent! %bdelete!" + vim.cmd("silent! %bdelete!") -- Change directory (tab-local) vim.cmd("tcd " .. vim.fn.fnameescape(target_path)) @@ -80,16 +80,17 @@ local function switch_to_directory(target_path) -- If no session, open Neo-tree or a blank buffer if not loaded then - if require("astrocore").is_available "neo-tree.nvim" then - vim.cmd "Neotree focus" + local neotree_ok = pcall(require, "neo-tree") + if neotree_ok then + vim.cmd("Neotree focus") else - vim.cmd "edit ." + vim.cmd("edit .") end end -- Refresh worktree cache and notify vim.api.nvim_exec_autocmds("User", { pattern = "GwqWorktreeChanged" }) - vim.notify("Switched to: " .. target_path:gsub("^" .. vim.pesc(os.getenv "HOME"), "~")) + vim.notify("Switched to: " .. target_path:gsub("^" .. vim.pesc(os.getenv("HOME")), "~")) end ---Refresh worktree info cache (async) @@ -98,23 +99,29 @@ local function refresh_worktree_info() vim.system({ gwq_bin, "list", "--json" }, { text = true }, function(result) vim.schedule(function() if result.code ~= 0 then - worktree_cache = { branch = nil, is_worktree = false } + worktree_cache.branch = nil + worktree_cache.is_worktree = false return end local ok, worktrees = pcall(vim.json.decode, result.stdout) if not ok or not worktrees then - worktree_cache = { branch = nil, is_worktree = false } + worktree_cache.branch = nil + worktree_cache.is_worktree = false return end local found = false for _, wt in ipairs(worktrees) do if wt.path == cwd then - worktree_cache = { branch = wt.branch, is_worktree = not wt.is_main } + worktree_cache.branch = wt.branch + worktree_cache.is_worktree = not wt.is_main found = true break end end - if not found then worktree_cache = { branch = nil, is_worktree = false } end + if not found then + worktree_cache.branch = nil + worktree_cache.is_worktree = false + end end) end) end @@ -123,11 +130,11 @@ end local function ghq_repo_picker(opts) opts = opts or {} - local pickers = require "telescope.pickers" - local finders = require "telescope.finders" + local pickers = require("telescope.pickers") + local finders = require("telescope.finders") local conf = require("telescope.config").values - local actions = require "telescope.actions" - local action_state = require "telescope.actions.state" + local actions = require("telescope.actions") + local action_state = require("telescope.actions.state") run_cmd_lines(ghq_bin, { "list", "--full-path" }, function(repos) if not repos or #repos == 0 then @@ -135,13 +142,13 @@ local function ghq_repo_picker(opts) return end - local home = os.getenv "HOME" + local home = os.getenv("HOME") local ghq_root = home .. "/ghq/" pickers .new(opts, { prompt_title = "ghq Repositories", - finder = finders.new_table { + finder = finders.new_table({ results = repos, entry_maker = function(repo_path) local display = repo_path:gsub("^" .. vim.pesc(home), "~") @@ -152,7 +159,7 @@ local function ghq_repo_picker(opts) ordinal = relative, } end, - }, + }), sorter = conf.generic_sorter(opts), attach_mappings = function(prompt_bufnr, _) actions.select_default:replace(function() @@ -169,12 +176,12 @@ end local function gwq_worktree_picker(opts) opts = opts or {} - local pickers = require "telescope.pickers" - local finders = require "telescope.finders" + local pickers = require("telescope.pickers") + local finders = require("telescope.finders") local conf = require("telescope.config").values - local actions = require "telescope.actions" - local action_state = require "telescope.actions.state" - local entry_display = require "telescope.pickers.entry_display" + local actions = require("telescope.actions") + local action_state = require("telescope.actions.state") + local entry_display = require("telescope.pickers.entry_display") run_cmd_json(gwq_bin, { "list", "--json" }, function(worktrees) if not worktrees or #worktrees == 0 then @@ -182,7 +189,7 @@ local function gwq_worktree_picker(opts) return end - local displayer = entry_display.create { + local displayer = entry_display.create({ separator = " ", items = { { width = 2 }, @@ -190,15 +197,15 @@ local function gwq_worktree_picker(opts) { width = 8 }, { remaining = true }, }, - } + }) local cwd = vim.fn.getcwd() - local home = os.getenv "HOME" + local home = os.getenv("HOME") pickers .new(opts, { prompt_title = "gwq Worktrees", - finder = finders.new_table { + finder = finders.new_table({ results = worktrees, entry_maker = function(wt) return { @@ -208,17 +215,17 @@ local function gwq_worktree_picker(opts) local indicator = w.path == cwd and ">" or " " local short_hash = w.commit_hash:sub(1, 7) local display_path = w.path:gsub("^" .. vim.pesc(home), "~") - return displayer { + return displayer({ { indicator, "TelescopeResultsComment" }, { w.branch, "TelescopeResultsIdentifier" }, { short_hash, "TelescopeResultsNumber" }, { display_path, "TelescopeResultsComment" }, - } + }) end, ordinal = wt.branch .. " " .. wt.path, } end, - }, + }), sorter = conf.generic_sorter(opts), attach_mappings = function(prompt_bufnr, map) actions.select_default:replace(function() @@ -240,7 +247,6 @@ local function gwq_worktree_picker(opts) vim.schedule(function() if result.code == 0 then vim.notify("Removed: " .. wt.branch) - -- Re-open picker to refresh actions.close(prompt_bufnr) gwq_worktree_picker(opts) else @@ -260,12 +266,12 @@ end local function gwq_status_picker(opts) opts = opts or {} - local pickers = require "telescope.pickers" - local finders = require "telescope.finders" + local pickers = require("telescope.pickers") + local finders = require("telescope.finders") local conf = require("telescope.config").values - local actions = require "telescope.actions" - local action_state = require "telescope.actions.state" - local entry_display = require "telescope.pickers.entry_display" + local actions = require("telescope.actions") + local action_state = require("telescope.actions.state") + local entry_display = require("telescope.pickers.entry_display") run_cmd_json(gwq_bin, { "status", "--json", "--no-fetch" }, function(data) if not data or not data.worktrees then @@ -273,7 +279,7 @@ local function gwq_status_picker(opts) return end - local displayer = entry_display.create { + local displayer = entry_display.create({ separator = " ", items = { { width = 10 }, @@ -281,7 +287,7 @@ local function gwq_status_picker(opts) { width = 8 }, { remaining = true }, }, - } + }) local status_hl = { clean = "DiagnosticOk", @@ -289,7 +295,7 @@ local function gwq_status_picker(opts) stale = "DiagnosticError", } - local home = os.getenv "HOME" + local home = os.getenv("HOME") local summary = data.summary or {} local title = string.format( "gwq Status (Total: %s, Modified: %s, Clean: %s)", @@ -301,7 +307,7 @@ local function gwq_status_picker(opts) pickers .new(opts, { prompt_title = title, - finder = finders.new_table { + finder = finders.new_table({ results = data.worktrees, entry_maker = function(wt) return { @@ -315,17 +321,17 @@ local function gwq_status_picker(opts) if (gs.staged or 0) > 0 then table.insert(changes, "S:" .. gs.staged) end local changes_str = #changes > 0 and table.concat(changes, " ") or "" local display_path = w.path:gsub("^" .. vim.pesc(home), "~") - return displayer { + return displayer({ { w.status or "unknown", status_hl[w.status] or "Normal" }, { w.branch, "TelescopeResultsIdentifier" }, { changes_str, "DiagnosticWarn" }, { display_path, "TelescopeResultsComment" }, - } + }) end, ordinal = wt.branch .. " " .. (wt.status or "") .. " " .. wt.path, } end, - }, + }), sorter = conf.generic_sorter(opts), attach_mappings = function(prompt_bufnr, _) actions.select_default:replace(function() @@ -358,7 +364,6 @@ local function gwq_add(branch_name) return end vim.notify("Worktree created: " .. branch_name) - -- Get the new worktree path local path_result = vim.system({ gwq_bin, "get", branch_name }, { text = true }):wait() if path_result.code == 0 then local path = vim.trim(path_result.stdout) @@ -370,77 +375,47 @@ local function gwq_add(branch_name) end) end --- ── Plugin Specs ─────────────────────────────────────────────────── +-- ── Plugin Spec ──────────────────────────────────────────────────── ---@type LazySpec return { - -- Keymaps, commands, and autocmds via astrocore { - "AstroNvim/astrocore", - ---@type AstroCoreOpts - opts = function(_, opts) - local maps = opts.mappings or {} - - -- Worktree group - maps.n["gw"] = { desc = "Worktrees" } - maps.n["gww"] = { function() gwq_worktree_picker() end, desc = "Switch worktree" } - maps.n["gwl"] = { function() gwq_worktree_picker() end, desc = "List worktrees" } - maps.n["gwa"] = { function() gwq_add() end, desc = "Add worktree" } - maps.n["gwr"] = { function() gwq_worktree_picker() end, desc = "Remove worktree (C-d)" } - maps.n["gws"] = { function() gwq_status_picker() end, desc = "Worktree status" } - - -- ghq repositories - maps.n["fp"] = { function() ghq_repo_picker() end, desc = "Find project (ghq)" } - - -- User commands - opts.commands = opts.commands or {} - opts.commands.GwqSwitch = { function() gwq_worktree_picker() end, desc = "Switch gwq worktree" } - opts.commands.GwqAdd = { - function(cmd) gwq_add(cmd.args ~= "" and cmd.args or nil) end, - nargs = "?", - desc = "Create gwq worktree", - } - opts.commands.GwqRemove = { function() gwq_worktree_picker() end, desc = "Remove gwq worktree" } - opts.commands.GwqStatus = { function() gwq_status_picker() end, desc = "Show gwq worktree status" } - opts.commands.GhqList = { function() ghq_repo_picker() end, desc = "Browse ghq repositories" } + "nvim-telescope/telescope.nvim", + keys = { + { "gw", "", desc = "Worktrees" }, + { "gww", function() gwq_worktree_picker() end, desc = "Switch worktree" }, + { "gwl", function() gwq_worktree_picker() end, desc = "List worktrees" }, + { "gwa", function() gwq_add() end, desc = "Add worktree" }, + { "gwr", function() gwq_worktree_picker() end, desc = "Remove worktree (C-d)" }, + { "gws", function() gwq_status_picker() end, desc = "Worktree status" }, + { "fp", function() ghq_repo_picker() end, desc = "Find project (ghq)" }, + }, + init = function() + -- Register user commands + vim.api.nvim_create_user_command("GwqSwitch", function() gwq_worktree_picker() end, { desc = "Switch gwq worktree" }) + vim.api.nvim_create_user_command("GwqAdd", function(cmd) gwq_add(cmd.args ~= "" and cmd.args or nil) end, { nargs = "?", desc = "Create gwq worktree" }) + vim.api.nvim_create_user_command("GwqRemove", function() gwq_worktree_picker() end, { desc = "Remove gwq worktree" }) + vim.api.nvim_create_user_command("GwqStatus", function() gwq_status_picker() end, { desc = "Show gwq worktree status" }) + vim.api.nvim_create_user_command("GhqList", function() ghq_repo_picker() end, { desc = "Browse ghq repositories" }) -- Autocmds for worktree cache refresh - opts.autocmds = opts.autocmds or {} - opts.autocmds.gwq_worktree_refresh = { - { - event = "DirChanged", - desc = "Refresh gwq worktree info", - callback = refresh_worktree_info, - }, - { - event = "VimEnter", - desc = "Initialize gwq worktree info", - callback = refresh_worktree_info, - }, - { - event = "User", - pattern = "GwqWorktreeChanged", - desc = "Refresh worktree cache on switch", - callback = refresh_worktree_info, - }, - } - end, - }, - - -- Heirline statusline: add worktree indicator after git_branch - { - "rebelot/heirline.nvim", - opts = function(_, opts) - if not opts.statusline then return end - - -- Insert worktree indicator after git_branch (index 2) - local worktree_component = { - condition = function() return worktree_cache.is_worktree end, - provider = " wt ", - hl = { fg = "#f5a97f", bold = true }, - } - - table.insert(opts.statusline, 3, worktree_component) + local group = vim.api.nvim_create_augroup("gwq_worktree_refresh", { clear = true }) + vim.api.nvim_create_autocmd("DirChanged", { + group = group, + desc = "Refresh gwq worktree info", + callback = refresh_worktree_info, + }) + vim.api.nvim_create_autocmd("VimEnter", { + group = group, + desc = "Initialize gwq worktree info", + callback = refresh_worktree_info, + }) + vim.api.nvim_create_autocmd("User", { + group = group, + pattern = "GwqWorktreeChanged", + desc = "Refresh worktree cache on switch", + callback = refresh_worktree_info, + }) end, }, } diff --git a/nvim/lua/plugins/lang-go.lua b/nvim/lua/plugins/lang-go.lua new file mode 100644 index 0000000..dfb3ac6 --- /dev/null +++ b/nvim/lua/plugins/lang-go.lua @@ -0,0 +1,17 @@ +-- Language: Go +return { + { + "WhoIsSethDaniel/mason-tool-installer.nvim", + opts = { + ensure_installed = { "gopls", "goimports", "delve" }, + }, + }, + { + "stevearc/conform.nvim", + opts = { + formatters_by_ft = { + go = { "goimports" }, + }, + }, + }, +} diff --git a/nvim/lua/plugins/lang-lua.lua b/nvim/lua/plugins/lang-lua.lua new file mode 100644 index 0000000..ca87c1f --- /dev/null +++ b/nvim/lua/plugins/lang-lua.lua @@ -0,0 +1,26 @@ +-- Language: Lua +return { + { + "folke/lazydev.nvim", + ft = "lua", + opts = { + library = { + { path = "${3rd}/luv/library", words = { "vim%.uv" } }, + }, + }, + }, + { + "WhoIsSethDaniel/mason-tool-installer.nvim", + opts = { + ensure_installed = { "stylua" }, + }, + }, + { + "stevearc/conform.nvim", + opts = { + formatters_by_ft = { + lua = { "stylua" }, + }, + }, + }, +} diff --git a/nvim/lua/plugins/lang-ruby.lua b/nvim/lua/plugins/lang-ruby.lua new file mode 100644 index 0000000..d34b03d --- /dev/null +++ b/nvim/lua/plugins/lang-ruby.lua @@ -0,0 +1,31 @@ +-- Language: Ruby +return { + { + "WhoIsSethDaniel/mason-tool-installer.nvim", + opts = { + ensure_installed = { "solargraph", "rubocop" }, + }, + }, + { + "stevearc/conform.nvim", + opts = { + formatters_by_ft = { + ruby = { "rubocop" }, + }, + }, + }, + { + "mfussenegger/nvim-lint", + event = { "BufReadPost", "BufNewFile" }, + config = function() + require("lint").linters_by_ft = { + ruby = { "rubocop" }, + } + vim.api.nvim_create_autocmd({ "BufWritePost", "BufReadPost" }, { + callback = function() + require("lint").try_lint() + end, + }) + end, + }, +} diff --git a/nvim/lua/plugins/lang-typescript.lua b/nvim/lua/plugins/lang-typescript.lua new file mode 100644 index 0000000..05be665 --- /dev/null +++ b/nvim/lua/plugins/lang-typescript.lua @@ -0,0 +1,20 @@ +-- Language: TypeScript / JavaScript +return { + { + "WhoIsSethDaniel/mason-tool-installer.nvim", + opts = { + ensure_installed = { "ts_ls", "prettier" }, + }, + }, + { + "stevearc/conform.nvim", + opts = { + formatters_by_ft = { + javascript = { "prettier" }, + typescript = { "prettier" }, + javascriptreact = { "prettier" }, + typescriptreact = { "prettier" }, + }, + }, + }, +} diff --git a/nvim/lua/plugins/lsp.lua b/nvim/lua/plugins/lsp.lua new file mode 100644 index 0000000..b547a71 --- /dev/null +++ b/nvim/lua/plugins/lsp.lua @@ -0,0 +1,103 @@ +-- LSP: lspconfig + mason + mason-lspconfig +return { + { + "williamboman/mason.nvim", + cmd = "Mason", + opts = {}, + }, + { + "williamboman/mason-lspconfig.nvim", + dependencies = { "williamboman/mason.nvim" }, + opts = { + ensure_installed = { + "lua_ls", + "solargraph", + "gopls", + "ts_ls", + }, + automatic_installation = true, + }, + }, + { + "neovim/nvim-lspconfig", + event = { "BufReadPre", "BufNewFile" }, + dependencies = { + "williamboman/mason-lspconfig.nvim", + "hrsh7th/cmp-nvim-lsp", + }, + config = function() + local lspconfig = require("lspconfig") + local capabilities = require("cmp_nvim_lsp").default_capabilities() + + -- LSP keymaps on attach + local on_attach = function(_, bufnr) + local opts = function(desc) + return { buffer = bufnr, desc = desc } + end + vim.keymap.set("n", "gd", vim.lsp.buf.definition, opts("Go to definition")) + vim.keymap.set("n", "gD", vim.lsp.buf.declaration, opts("Go to declaration")) + vim.keymap.set("n", "gi", vim.lsp.buf.implementation, opts("Go to implementation")) + vim.keymap.set("n", "gr", vim.lsp.buf.references, opts("References")) + vim.keymap.set("n", "K", vim.lsp.buf.hover, opts("Hover")) + vim.keymap.set("n", "la", vim.lsp.buf.code_action, opts("Code action")) + vim.keymap.set("n", "lr", vim.lsp.buf.rename, opts("Rename")) + vim.keymap.set("n", "ld", vim.diagnostic.open_float, opts("Line diagnostics")) + vim.keymap.set("n", "[d", vim.diagnostic.goto_prev, opts("Previous diagnostic")) + vim.keymap.set("n", "]d", vim.diagnostic.goto_next, opts("Next diagnostic")) + vim.keymap.set("n", "lf", function() + vim.lsp.buf.format({ async = true }) + end, opts("Format")) + end + + -- Setup servers via mason-lspconfig + require("mason-lspconfig").setup_handlers({ + function(server_name) + lspconfig[server_name].setup({ + capabilities = capabilities, + on_attach = on_attach, + }) + end, + ["lua_ls"] = function() + lspconfig.lua_ls.setup({ + capabilities = capabilities, + on_attach = on_attach, + settings = { + Lua = { + diagnostics = { globals = { "vim" } }, + workspace = { checkThirdParty = false }, + telemetry = { enable = false }, + }, + }, + }) + end, + }) + end, + }, + { + "ray-x/lsp_signature.nvim", + event = "BufRead", + config = function() + require("lsp_signature").setup() + end, + }, + -- Formatter + { + "stevearc/conform.nvim", + event = { "BufWritePre" }, + cmd = { "ConformInfo" }, + opts = { + format_on_save = { + timeout_ms = 1000, + lsp_format = "fallback", + }, + }, + }, + -- Mason tool installer (for formatters, linters, etc.) + { + "WhoIsSethDaniel/mason-tool-installer.nvim", + dependencies = { "williamboman/mason.nvim" }, + opts = { + ensure_installed = {}, + }, + }, +} diff --git a/nvim/lua/plugins/markdown-preview.lua b/nvim/lua/plugins/markdown-preview.lua deleted file mode 100644 index 660085c..0000000 --- a/nvim/lua/plugins/markdown-preview.lua +++ /dev/null @@ -1,16 +0,0 @@ ----@type LazySpec -return { - "iamcco/markdown-preview.nvim", - cmd = { "MarkdownPreviewToggle", "MarkdownPreview", "MarkdownPreviewStop" }, - ft = { "markdown" }, - build = "cd app && npm install", - specs = { - { - "AstroNvim/astrocore", - opts = function(_, opts) - local maps = opts.mappings - maps.n["mp"] = { "MarkdownPreviewToggle", desc = "Markdown Preview" } - end, - }, - }, -} diff --git a/nvim/lua/plugins/markdown.lua b/nvim/lua/plugins/markdown.lua new file mode 100644 index 0000000..3ebaef3 --- /dev/null +++ b/nvim/lua/plugins/markdown.lua @@ -0,0 +1,38 @@ +-- Markdown tools: preview, glow, markview +return { + -- Browser-based preview + { + "iamcco/markdown-preview.nvim", + cmd = { "MarkdownPreviewToggle", "MarkdownPreview", "MarkdownPreviewStop" }, + ft = "markdown", + build = "cd app && npm install", + keys = { + { "mp", "MarkdownPreviewToggle", desc = "Markdown Preview" }, + }, + }, + -- Terminal-based preview + { + "ellisonleao/glow.nvim", + cmd = "Glow", + ft = "markdown", + config = function() + require("glow").setup({ + border = "rounded", + style = "dark", + pager = false, + width = 120, + height_ratio = 0.8, + }) + end, + }, + -- Inline preview in buffer + { + "OXY2DEV/markview.nvim", + lazy = false, + ft = "markdown", + dependencies = { + "nvim-treesitter/nvim-treesitter", + "nvim-tree/nvim-web-devicons", + }, + }, +} diff --git a/nvim/lua/plugins/mason.lua b/nvim/lua/plugins/mason.lua deleted file mode 100644 index dfc24a2..0000000 --- a/nvim/lua/plugins/mason.lua +++ /dev/null @@ -1,42 +0,0 @@ -if true then return {} end -- WARN: REMOVE THIS LINE TO ACTIVATE THIS FILE - --- Customize Mason plugins - ----@type LazySpec -return { - -- use mason-lspconfig to configure LSP installations - { - "williamboman/mason-lspconfig.nvim", - -- overrides `require("mason-lspconfig").setup(...)` - opts = function(_, opts) - -- add more things to the ensure_installed table protecting against community packs modifying it - opts.ensure_installed = require("astrocore").list_insert_unique(opts.ensure_installed, { - "lua_ls", - -- add more arguments for adding more language servers - }) - end, - }, - -- use mason-null-ls to configure Formatters/Linter installation for null-ls sources - { - "jay-babu/mason-null-ls.nvim", - -- overrides `require("mason-null-ls").setup(...)` - opts = function(_, opts) - -- add more things to the ensure_installed table protecting against community packs modifying it - opts.ensure_installed = require("astrocore").list_insert_unique(opts.ensure_installed, { - "stylua", - -- add more arguments for adding more null-ls sources - }) - end, - }, - { - "jay-babu/mason-nvim-dap.nvim", - -- overrides `require("mason-nvim-dap").setup(...)` - opts = function(_, opts) - -- add more things to the ensure_installed table protecting against community packs modifying it - opts.ensure_installed = require("astrocore").list_insert_unique(opts.ensure_installed, { - "python", - -- add more arguments for adding more debuggers - }) - end, - }, -} diff --git a/nvim/lua/plugins/neo-tree.lua b/nvim/lua/plugins/neo-tree.lua new file mode 100644 index 0000000..18fca35 --- /dev/null +++ b/nvim/lua/plugins/neo-tree.lua @@ -0,0 +1,31 @@ +return { + "nvim-neo-tree/neo-tree.nvim", + branch = "v3.x", + dependencies = { + "nvim-lua/plenary.nvim", + "nvim-tree/nvim-web-devicons", + "MunifTanjim/nui.nvim", + }, + cmd = "Neotree", + keys = { + { "e", "Neotree toggle", desc = "Toggle Neo-tree" }, + }, + opts = { + filesystem = { + filtered_items = { + visible = true, + hide_dotfiles = false, + hide_gitignored = false, + }, + }, + window = { + position = "left", + mappings = { + ["ff"] = function() + vim.cmd("wincmd l") + require("telescope.builtin").find_files() + end, + }, + }, + }, +} diff --git a/nvim/lua/plugins/none-ls.lua b/nvim/lua/plugins/none-ls.lua deleted file mode 100644 index 382368d..0000000 --- a/nvim/lua/plugins/none-ls.lua +++ /dev/null @@ -1,22 +0,0 @@ -if true then return {} end -- WARN: REMOVE THIS LINE TO ACTIVATE THIS FILE - --- Customize None-ls sources - ----@type LazySpec -return { - "nvimtools/none-ls.nvim", - opts = function(_, config) - -- config variable is the default configuration table for the setup function call - -- local null_ls = require "null-ls" - - -- Check supported formatters and linters - -- https://github.com/nvimtools/none-ls.nvim/tree/main/lua/null-ls/builtins/formatting - -- https://github.com/nvimtools/none-ls.nvim/tree/main/lua/null-ls/builtins/diagnostics - config.sources = { - -- Set a formatter - -- null_ls.builtins.formatting.stylua, - -- null_ls.builtins.formatting.prettier, - } - return config -- return final config table - end, -} diff --git a/nvim/lua/plugins/ruby.lua b/nvim/lua/plugins/ruby.lua deleted file mode 100644 index 68d01c6..0000000 --- a/nvim/lua/plugins/ruby.lua +++ /dev/null @@ -1,34 +0,0 @@ --- Ruby: RuboCop をフォーマッター/リンターとして使用 ----@type LazySpec -return { - -- RuboCop を Mason でインストール - { - "WhoIsSethDaniel/mason-tool-installer.nvim", - optional = true, - opts = function(_, opts) - opts.ensure_installed = require("astrocore").list_insert_unique(opts.ensure_installed, { - "rubocop", - }) - end, - }, - -- フォーマッターを RuboCop に設定 - { - "stevearc/conform.nvim", - optional = true, - opts = { - formatters_by_ft = { - ruby = { "rubocop" }, - }, - }, - }, - -- リンターを RuboCop に設定 - { - "mfussenegger/nvim-lint", - optional = true, - opts = { - linters_by_ft = { - ruby = { "rubocop" }, - }, - }, - }, -} diff --git a/nvim/lua/plugins/session.lua b/nvim/lua/plugins/session.lua new file mode 100644 index 0000000..c57fd2d --- /dev/null +++ b/nvim/lua/plugins/session.lua @@ -0,0 +1,28 @@ +-- Session management: resession.nvim +return { + "stevearc/resession.nvim", + lazy = false, + opts = {}, + config = function(_, opts) + local resession = require("resession") + resession.setup(opts) + + -- Auto-save session on exit + vim.api.nvim_create_autocmd("VimLeavePre", { + callback = function() + if vim.fn.expand("%") ~= "" then + resession.save(vim.fn.getcwd(), { dir = "dirsession", notify = false }) + end + end, + }) + + -- Auto-restore session on start (only if no args) + vim.api.nvim_create_autocmd("VimEnter", { + callback = function() + if vim.fn.argc(-1) == 0 then + pcall(resession.load, vim.fn.getcwd(), { dir = "dirsession", silence_errors = true }) + end + end, + }) + end, +} diff --git a/nvim/lua/plugins/statusline.lua b/nvim/lua/plugins/statusline.lua new file mode 100644 index 0000000..c7b4351 --- /dev/null +++ b/nvim/lua/plugins/statusline.lua @@ -0,0 +1,70 @@ +-- Statusline: lualine.nvim (replaces heirline) + +-- Worktree info cache (shared with gwq-ghq.lua via global) +_G._gwq_worktree_cache = _G._gwq_worktree_cache or { + branch = nil, + is_worktree = false, +} + +-- Activity monitor stats cache (shared with activity-monitor.lua via global) +_G._activity_stats_cache = _G._activity_stats_cache or { + cpu_total = 0, + mem_percent = 0, + top_process = "", + updated_at = 0, +} + +local function worktree_indicator() + if _G._gwq_worktree_cache.is_worktree then + return " wt" + end + return "" +end + +local function activity_monitor() + local stats = _G._activity_stats_cache + if stats.updated_at <= 0 then return "" end + return string.format("CPU:%.0f%% Mem:%.0f%%", stats.cpu_total, stats.mem_percent) +end + +local function activity_monitor_color() + local stats = _G._activity_stats_cache + if stats.mem_percent > 80 or stats.cpu_total > 200 then + return { fg = "#ed8796" } + elseif stats.mem_percent > 60 or stats.cpu_total > 100 then + return { fg = "#f5a97f" } + end + return { fg = "#a6da95" } +end + +return { + "nvim-lualine/lualine.nvim", + dependencies = { "nvim-tree/nvim-web-devicons" }, + event = "VeryLazy", + opts = { + options = { + theme = "tokyonight", + globalstatus = true, + component_separators = { left = "", right = "" }, + section_separators = { left = "", right = "" }, + }, + sections = { + lualine_a = { "mode" }, + lualine_b = { + "branch", + { worktree_indicator, color = { fg = "#f5a97f", gui = "bold" } }, + "diff", + "diagnostics", + }, + lualine_c = { { "filename", path = 1 } }, + lualine_x = { + { activity_monitor, color = activity_monitor_color }, + "encoding", + "fileformat", + "filetype", + }, + lualine_y = { "progress" }, + lualine_z = { "location" }, + }, + }, +} diff --git a/nvim/lua/plugins/telescope.lua b/nvim/lua/plugins/telescope.lua index 974112d..339eb32 100644 --- a/nvim/lua/plugins/telescope.lua +++ b/nvim/lua/plugins/telescope.lua @@ -1,36 +1,46 @@ ----@type LazySpec +-- Telescope: fuzzy finder return { "nvim-telescope/telescope.nvim", - opts = function(_, opts) - local ignore_patterns = { - -- Version control - "^%.git[/\\]", - "[/\\]%.git[/\\]", - -- Dependencies - "[/\\]node_modules[/\\]", - "[/\\]vendor[/\\]", - -- Build artifacts - "[/\\]dist[/\\]", - "[/\\]build[/\\]", - -- Python - "[/\\]%.venv[/\\]", - "[/\\]__pycache__[/\\]", - "%.pyc$", - -- Cache - "[/\\]%.cache[/\\]", - } - - opts.defaults = vim.tbl_deep_extend("force", opts.defaults or {}, { - file_ignore_patterns = ignore_patterns, - }) - - opts.pickers = vim.tbl_deep_extend("force", opts.pickers or {}, { + dependencies = { + "nvim-lua/plenary.nvim", + { "nvim-telescope/telescope-fzf-native.nvim", build = "make" }, + }, + cmd = "Telescope", + keys = { + { "fb", "Telescope buffers", desc = "Find buffers" }, + { "fh", "Telescope help_tags", desc = "Find help" }, + { "fk", "Telescope keymaps", desc = "Find keymaps" }, + { "fo", "Telescope oldfiles", desc = "Find recent files" }, + { "fd", "Telescope diagnostics", desc = "Find diagnostics" }, + { "fr", "Telescope resume", desc = "Resume search" }, + }, + opts = { + defaults = { + file_ignore_patterns = { + "^%.git[/\\]", + "[/\\]%.git[/\\]", + "[/\\]node_modules[/\\]", + "[/\\]vendor[/\\]", + "[/\\]dist[/\\]", + "[/\\]build[/\\]", + "[/\\]%.venv[/\\]", + "[/\\]__pycache__[/\\]", + "%.pyc$", + "[/\\]%.cache[/\\]", + }, + }, + pickers = { find_files = { hidden = true, }, live_grep = { additional_args = { "--hidden" }, }, - }) + }, + }, + config = function(_, opts) + local telescope = require("telescope") + telescope.setup(opts) + pcall(telescope.load_extension, "fzf") end, } diff --git a/nvim/lua/plugins/tfview.lua b/nvim/lua/plugins/tfview.lua new file mode 100644 index 0000000..b728845 --- /dev/null +++ b/nvim/lua/plugins/tfview.lua @@ -0,0 +1,9 @@ +return { + { + dir = "~/ghq/github.com/o8n/tfview", + cmd = { "TerraformPlanTUI", "TerraformPlanSummary", "TerraformPlanRun" }, + opts = { + binary = vim.fn.expand("~/.local/bin/tfview"), + }, + }, +} diff --git a/nvim/lua/plugins/toggleterm.lua b/nvim/lua/plugins/toggleterm.lua index 3d4975d..3c5728e 100644 --- a/nvim/lua/plugins/toggleterm.lua +++ b/nvim/lua/plugins/toggleterm.lua @@ -1,4 +1,3 @@ ----@type LazySpec return { "akinsho/toggleterm.nvim", cmd = { "ToggleTerm", "ToggleTermToggleAll" }, @@ -7,27 +6,19 @@ return { persist_size = true, persist_mode = true, }, - specs = { - { - "AstroNvim/astrocore", - opts = function(_, opts) - local maps = opts.mappings - - for i = 1, 3 do - maps.n[("t%d"):format(i)] = { - ("%dToggleTerm size=15 direction=horizontal"):format(i), - desc = ("Terminal #%d"):format(i), - } - maps.t[("t%d"):format(i)] = { - ("%dToggleTerm size=15 direction=horizontal"):format(i), - desc = ("Terminal #%d"):format(i), - } - end - - maps.n["tA"] = { "ToggleTermToggleAll", desc = "Toggle all terminals" } - maps.n["th"] = { "ToggleTerm size=15 direction=horizontal", desc = "Horizontal terminal" } - maps.t[""] = { "", desc = "Exit terminal mode" } - end, - }, - }, + keys = (function() + local keys = {} + for i = 1, 3 do + table.insert(keys, { + ("t%d"):format(i), + ("%dToggleTerm size=15 direction=horizontal"):format(i), + desc = ("Terminal #%d"):format(i), + mode = { "n", "t" }, + }) + end + table.insert(keys, { "tA", "ToggleTermToggleAll", desc = "Toggle all terminals" }) + table.insert(keys, { "th", "ToggleTerm size=15 direction=horizontal", desc = "Horizontal terminal" }) + table.insert(keys, { "", "", mode = "t", desc = "Exit terminal mode" }) + return keys + end)(), } diff --git a/nvim/lua/plugins/treesitter.lua b/nvim/lua/plugins/treesitter.lua index 424e24f..e12773b 100644 --- a/nvim/lua/plugins/treesitter.lua +++ b/nvim/lua/plugins/treesitter.lua @@ -1,14 +1,35 @@ --- Customize Treesitter - ----@type LazySpec return { "nvim-treesitter/nvim-treesitter", - opts = function(_, opts) - -- add more things to the ensure_installed table protecting against community packs modifying it - opts.ensure_installed = require("astrocore").list_insert_unique(opts.ensure_installed, { + build = ":TSUpdate", + event = { "BufReadPost", "BufNewFile" }, + opts = { + ensure_installed = { "lua", "vim", + "vimdoc", "ruby", - }) + "go", + "gomod", + "gosum", + "typescript", + "javascript", + "tsx", + "html", + "css", + "json", + "yaml", + "toml", + "markdown", + "markdown_inline", + "bash", + "regex", + "query", + }, + highlight = { enable = true }, + indent = { enable = true }, + auto_install = true, + }, + config = function(_, opts) + require("nvim-treesitter.configs").setup(opts) end, } diff --git a/nvim/lua/plugins/ui.lua b/nvim/lua/plugins/ui.lua new file mode 100644 index 0000000..8d72f84 --- /dev/null +++ b/nvim/lua/plugins/ui.lua @@ -0,0 +1,71 @@ +-- UI: which-key, dressing, alpha, notify, colorizer, smart-splits, presence +return { + -- Keymap hints + { + "folke/which-key.nvim", + event = "VeryLazy", + opts = {}, + config = function(_, opts) + local wk = require("which-key") + wk.setup(opts) + wk.add({ + { "b", group = "Buffers" }, + { "f", group = "Find" }, + { "g", group = "Git" }, + { "gw", group = "Worktrees" }, + { "gx", group = "Git Conflict" }, + { "l", group = "LSP" }, + { "t", group = "Terminal" }, + { "a", group = "Activity Monitor" }, + { "m", group = "Markdown" }, + }) + end, + }, + -- Better UI for vim.ui.select/input + { + "stevearc/dressing.nvim", + event = "VeryLazy", + opts = {}, + }, + -- Dashboard + { + "goolord/alpha-nvim", + event = "VimEnter", + dependencies = { "nvim-tree/nvim-web-devicons" }, + config = function() + local alpha = require("alpha") + local dashboard = require("alpha.themes.dashboard") + dashboard.section.header.val = {} + dashboard.section.buttons.val = { + dashboard.button("f", " Find file", "Telescope find_files"), + dashboard.button("r", " Recent files", "Telescope oldfiles"), + dashboard.button("g", " Find text", "Telescope live_grep"), + dashboard.button("e", " New file", "ene"), + dashboard.button("q", " Quit", "qa"), + } + alpha.setup(dashboard.opts) + end, + }, + -- Notifications + { + "rcarriga/nvim-notify", + event = "VeryLazy", + config = function() + vim.notify = require("notify") + end, + }, + -- Color highlighter + { + "NvChad/nvim-colorizer.lua", + event = { "BufReadPost", "BufNewFile" }, + opts = {}, + }, + -- Smart window splits + { + "mrjones2014/smart-splits.nvim", + event = "VeryLazy", + opts = {}, + }, + -- Discord presence + { "andweeb/presence.nvim", event = "VeryLazy" }, +} diff --git a/nvim/lua/plugins/user.lua b/nvim/lua/plugins/user.lua deleted file mode 100644 index fc5db50..0000000 --- a/nvim/lua/plugins/user.lua +++ /dev/null @@ -1,159 +0,0 @@ --- You can also add or configure plugins by creating files in this `plugins/` folder --- Here are some examples: - ----@type LazySpec -return { - - -- == Examples of Adding Plugins == - - "andweeb/presence.nvim", - { - "ray-x/lsp_signature.nvim", - event = "BufRead", - config = function() require("lsp_signature").setup() end, - }, - - -- == Examples of Overriding Plugins == - - -- customize alpha options - { - "goolord/alpha-nvim", - opts = function(_, opts) - -- customize the dashboard header - opts.section.header.val = { - } - return opts - end, - }, - - -- You can disable default plugins as follows: - { "max397574/better-escape.nvim", enabled = false }, - - -- Markdown preview with glow.nvim (renders in terminal buffer) - { - "ellisonleao/glow.nvim", - cmd = "Glow", - ft = "markdown", - config = function() - require("glow").setup({ - border = "rounded", -- floating window border - style = "dark", -- 'dark' or 'light' - pager = false, -- use pager for long content - width = 120, -- max width of window - height_ratio = 0.8, -- height ratio of window - }) - end, - }, - - -- Markdown inline preview (renders in same buffer) - { - "OXY2DEV/markview.nvim", - lazy = false, - ft = "markdown", - dependencies = { - "nvim-treesitter/nvim-treesitter", - "nvim-tree/nvim-web-devicons", - }, - }, - - -- You can also easily customize additional setup of plugins that is outside of the plugin's setup call - { - "L3MON4D3/LuaSnip", - config = function(plugin, opts) - require "astronvim.plugins.configs.luasnip"(plugin, opts) -- include the default astronvim config that calls the setup call - -- add more custom luasnip configuration such as filetype extend or custom snippets - local luasnip = require "luasnip" - luasnip.filetype_extend("javascript", { "javascriptreact" }) - end, - }, - - { - "windwp/nvim-autopairs", - config = function(plugin, opts) - require "astronvim.plugins.configs.nvim-autopairs"(plugin, opts) -- include the default astronvim config that calls the setup call - -- add more custom autopairs configuration such as custom rules - local npairs = require "nvim-autopairs" - local Rule = require "nvim-autopairs.rule" - local cond = require "nvim-autopairs.conds" - npairs.add_rules( - { - Rule("$", "$", { "tex", "latex" }) - -- don't add a pair if the next character is % - :with_pair(cond.not_after_regex "%%") - -- don't add a pair if the previous character is xxx - :with_pair( - cond.not_before_regex("xxx", 3) - ) - -- don't move right when repeat character - :with_move(cond.none()) - -- don't delete if the next character is xx - :with_del(cond.not_after_regex "xx") - -- disable adding a newline when you press - :with_cr(cond.none()), - }, - -- disable for .vim files, but it work for another filetypes - Rule("a", "a", "-vim") - ) - end, - }, - - -- Neo-tree を左側に配置 - { - "nvim-neo-tree/neo-tree.nvim", - opts = { - filesystem = { - filtered_items = { - visible = true, -- フィルタされたアイテムを薄く表示 - hide_dotfiles = false, -- ドットファイル(.envなど)を表示 - hide_gitignored = false, -- gitignoreされたファイルを表示 - }, - }, - window = { - position = "left", - mappings = { - -- Neo-tree内からTelescopeを呼び出す - ["ff"] = function() - vim.cmd("wincmd l") -- 右のウィンドウに移動 - require("telescope.builtin").find_files() - end, - }, - }, - }, - }, - - -- Telescope で隠しファイル・gitignoreファイルを検索可能に - { - "nvim-telescope/telescope.nvim", - opts = { - defaults = { - file_ignore_patterns = {}, -- 無視パターンをクリア - }, - pickers = { - find_files = { - hidden = true, -- 隠しファイルを表示 - no_ignore = true, -- .gitignoreを無視 - }, - live_grep = { - additional_args = function() - return { "--hidden", "--no-ignore" } - end, - }, - }, - }, - }, - - -- GitLens的なgit blame表示 - { - "lewis6991/gitsigns.nvim", - opts = { - current_line_blame = true, -- 行末にblame情報を表示 - current_line_blame_opts = { - virt_text = true, - virt_text_pos = "eol", -- 行末に表示 - delay = 500, -- 500msの遅延後に表示 - ignore_whitespace = false, - }, - current_line_blame_formatter = ", - ", - }, - }, -} diff --git a/nvim/lua/polish.lua b/nvim/lua/polish.lua deleted file mode 100644 index eaf0b2a..0000000 --- a/nvim/lua/polish.lua +++ /dev/null @@ -1,13 +0,0 @@ --- This will run last in the setup process and is a good place to configure --- things like custom filetypes. This just pure lua so anything that doesn't --- fit in the normal config locations above can go here - --- 自動保存: テキスト変更時やフォーカスを失った時に即座に保存 -vim.api.nvim_create_autocmd({ "TextChanged", "InsertLeave", "FocusLost" }, { - pattern = "*", - callback = function() - if vim.bo.modified and vim.bo.buftype == "" and vim.fn.expand("%") ~= "" then - vim.cmd("silent! write") - end - end, -})