diff --git a/LOG.md b/LOG.md index 59cb29f..d050ca1 100644 --- a/LOG.md +++ b/LOG.md @@ -9,7 +9,7 @@ Authoritative notes for the Neovim migration. Use this alongside `MIGRATION_PLAN Record every decision here with a short rationale. Append new entries; do not rewrite history. -- 2025-01-13: **Git files to quickfix**: Added `gf` keymap to send all modified, deleted, and untracked Git files to quickfix list with status indicators. Uses `git status --porcelain` to parse file status (Modified, Deleted, Added, Untracked, etc.) and displays it in the quickfix text column. Complements existing `hq` (Gitsigns hunks to quickfix) with file-level Git status workflow. +- 2025-01-13: **Git files to quickfix**: Added `gg` keymap to send all modified, deleted, and untracked Git files to quickfix list with status indicators. Uses `git status --porcelain` to parse file status (Modified, Deleted, Added, Untracked, etc.) and displays it in the quickfix text column. Implementation in `utils.git_changed_files()`. Complements existing `hq` (Gitsigns hunks to quickfix) with file-level Git status workflow. - 2025-01-12: **Custom Tabline Function**: Implemented configurable custom tabline to replace Neovim's hardcoded path shortening (e.g., `a/p/file.txt`). Function in `lua/utils.lua` allows controlling: (1) number of full parent directories via `utils.tabline_full_parents` (default: 1), and (2) shortening length via `utils.tabline_shorten_length` (default: 3 characters). Example: with defaults, `/path/to/my/project/src/file.txt` becomes `pat/to/my/project/src/file.txt`. User preference for seeing enough context in shortened paths while keeping tab width manageable. - 2025-12-06: PHP LSP = `intelephense` (good PHP ecosystem support; integrates includePaths). - 2025-12-06: Enable Markdown LSP = `marksman` (lightweight, good MD features). diff --git a/README.md b/README.md index 5a1f849..c483d7b 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ Core keymaps available globally (not plugin-specific). These provide fallbacks f | n | `]d` | Diagnostics: next item | Uses `vim.diagnostic.goto_next` | | n | `xd` | Diagnostic float | Opens hover window for cursor diagnostic | | n | `xt` | Toggle diagnostics | Flips `vim.diagnostic.enable()` | -| n | `gf` | Git: Changed files → quickfix | Lists all modified/deleted/untracked files with status | +| n | `gg` | Git: Changed files → quickfix | Lists all modified/deleted/untracked files with status | | n | `hi` | Highlight inspector | Shows highlight/capture stack under cursor | ### `lua/netrw-config.lua` diff --git a/lua/keymaps.lua b/lua/keymaps.lua index 382ca7c..13484c6 100644 --- a/lua/keymaps.lua +++ b/lua/keymaps.lua @@ -51,54 +51,13 @@ map('n', 'xt', function() end, { desc = 'Diagnostics: Toggle display', silent = true }) -- Git: Modified, deleted, and untracked files to quickfix -map('n', 'gf', function() - -- Use git status --porcelain to get all changes with status indicators - -- Format: "XY filename" where X=index status, Y=worktree status - -- Status codes: M=modified, D=deleted, A=added, ??=untracked, etc. - local handle = io.popen('git status --porcelain 2>/dev/null') - if not handle then - vim.notify('Failed to run git status', vim.log.levels.ERROR) - return +map('n', 'gg', function() + local utils = require('utils') + local qf_list = utils.git_changed_files() + if qf_list then + vim.fn.setqflist(qf_list, 'r') + vim.cmd('copen') end - - local result = handle:read('*a') - handle:close() - - if result == '' then - vim.notify('No git changes found', vim.log.levels.INFO) - return - end - - local qf_list = {} - local status_map = { - ['M'] = 'Modified', - ['A'] = 'Added', - ['D'] = 'Deleted', - ['R'] = 'Renamed', - ['C'] = 'Copied', - ['U'] = 'Unmerged', - ['?'] = 'Untracked', - } - - for line in result:gmatch('[^\n]+') do - -- Parse porcelain format: "XY filename" or "XY original -> renamed" - local index_status = line:sub(1, 1) - local work_status = line:sub(2, 2) - local filename = line:sub(4) -- Skip "XY " prefix - - -- Determine status text (worktree takes precedence over index) - local status_code = work_status ~= ' ' and work_status or index_status - local status_text = status_map[status_code] or 'Changed' - - table.insert(qf_list, { - filename = filename, - lnum = 1, - text = status_text, - }) - end - - vim.fn.setqflist(qf_list, 'r') - vim.cmd('copen') end, { desc = 'Git: Changed files to quickfix (with status)', silent = true }) -- Debug: Show highlight group and color under cursor diff --git a/lua/utils.lua b/lua/utils.lua index 00d090c..16aec51 100644 --- a/lua/utils.lua +++ b/lua/utils.lua @@ -17,6 +17,57 @@ M.tabline_full_parents = 1 -- Example: with shorten_length = 1, /path/to/my becomes p/t/m M.tabline_shorten_length = 3 +-- Get all modified, deleted, and untracked Git files with status +-- Returns a list suitable for setqflist() or nil on error +function M.git_changed_files() + -- Use git status --porcelain to get all changes with status indicators + -- Format: "XY filename" where X=index status, Y=worktree status + -- Status codes: M=modified, D=deleted, A=added, ??=untracked, etc. + local handle = io.popen('git status --porcelain 2>/dev/null') + if not handle then + vim.notify('Failed to run git status', vim.log.levels.ERROR) + return nil + end + + local result = handle:read('*a') + handle:close() + + if result == '' then + vim.notify('No git changes found', vim.log.levels.INFO) + return nil + end + + local qf_list = {} + local status_map = { + ['M'] = 'Modified', + ['A'] = 'Added', + ['D'] = 'Deleted', + ['R'] = 'Renamed', + ['C'] = 'Copied', + ['U'] = 'Unmerged', + ['?'] = 'Untracked', + } + + for line in result:gmatch('[^\n]+') do + -- Parse porcelain format: "XY filename" or "XY original -> renamed" + local index_status = line:sub(1, 1) + local work_status = line:sub(2, 2) + local filename = line:sub(4) -- Skip "XY " prefix + + -- Determine status text (worktree takes precedence over index) + local status_code = work_status ~= ' ' and work_status or index_status + local status_text = status_map[status_code] or 'Changed' + + table.insert(qf_list, { + filename = filename, + lnum = 1, + text = status_text, + }) + end + + return qf_list +end + -- Custom tabline function -- Shows configurable number of full parent directories, shortens the rest function M.custom_tabline()