feat(status,highlights): Handle renamed files in restore and picker flows

- Improve status-line parsing to support top-level and nested rename 
        syntaxes, so actions no longer include trailing braces in paths.
    - Update the Snacks status picker integration to pass structured 
        rename/status metadata and use git_status formatting, preserving 
        icons/highlighting while showing rename pairs correctly.
    - Also tighten renamed-line highlighting in the editor buffer for consistent jjRenamed behavior.
This commit is contained in:
NicolasGB
2026-05-19 18:05:17 +02:00
parent 5558c22471
commit 71f640be45
4 changed files with 75 additions and 78 deletions
+28 -31
View File
@@ -55,50 +55,47 @@ end
--- Handles renamed files and regular status lines.
--- @return {old_path : string, new_path : string, is_rename : boolean}|nil A table with , or nil if parsing fails
function M.parse_file_info_from_status_line(line)
-- Handle renamed files: "R path/{old_name => new_name}" or "R old_path => new_path"
local rename_pattern_curly = "^R (.*)/{(.*) => ([^}]+)}"
local dir_path, old_name, new_name = line:match(rename_pattern_curly)
if not line then
return nil
end
line = vim.trim(line)
-- Handle renamed files in nested path form:
-- R dir/{old_name => new_name}
local dir_path, old_name, new_name = line:match("^R%s+(.*)/{(.*)%s=>%s([^}]+)}$")
if dir_path and old_name and new_name then
return {
old_path = dir_path .. "/" .. old_name,
new_path = dir_path .. "/" .. new_name,
is_rename = true,
}
else
-- Try simple rename pattern: "R old_path => new_path"
local rename_pattern_simple = "^R (.*) => (.+)$"
local old_path, new_path = line:match(rename_pattern_simple)
if old_path and new_path then
return {
old_path = old_path,
new_path = new_path,
is_rename = true,
}
end
end
-- Not a rename, try regular status patterns
local filepath
-- Handle renamed files: "R path/{old_name => new_name}" or "R old_path => new_path"
local rename_pattern_curly_new = "^R (.*)/{.* => ([^}]+)}"
local dir_path_new, renamed_file = line:match(rename_pattern_curly_new)
if dir_path_new and renamed_file then
filepath = dir_path_new .. "/" .. renamed_file
else
-- Try simple rename pattern: "R old_path => new_path"
local rename_pattern_simple_new = "^R .* => (.+)$"
filepath = line:match(rename_pattern_simple_new)
-- Handle renamed files in top-level brace form:
-- R {old_name => new_name}
local old_top, new_top = line:match("^R%s+{(.-)%s=>%s([^}]+)}$")
if old_top and new_top then
return {
old_path = old_top,
new_path = new_top,
is_rename = true,
}
end
if not filepath then
-- jj status format: "M filename" or "A filename"
-- Match lines that start with status letter followed by space and filename
local pattern = "^[MAD?!] (.+)$"
filepath = line:match(pattern)
-- Handle simple rename form:
-- R old_path => new_path
local old_path, new_path = line:match("^R%s+(.+)%s=>%s(.+)$")
if old_path and new_path then
return {
old_path = vim.trim(old_path),
new_path = vim.trim(new_path),
is_rename = true,
}
end
-- Regular status lines (M/A/D/?/!)
local filepath = line:match("^[MAD?!]%s+(.+)$")
if filepath then
return {
old_path = filepath,