chore: import upstream snapshot with attribution
Python CI / Python bindings (ubuntu-latest) (push) Failing after 0s
Build & Publish / Build Neovim aarch64-linux-android (push) Failing after 0s
Build & Publish / Build Neovim aarch64-unknown-linux-gnu (push) Failing after 0s
Build & Publish / Build MCP x86_64-unknown-linux-musl (push) Failing after 1s
Build & Publish / Build Python wheels aarch64 (ubuntu-latest) (push) Failing after 0s
Build & Publish / Build Python wheels x86_64 (ubuntu-latest) (push) Failing after 1s
Build & Publish / Build Python sdist (push) Failing after 1s
Rust CI / Fuzz Tests (ubuntu-latest) (push) Failing after 1s
Rust CI / Build i686-unknown-linux-gnu (push) Failing after 0s
Rust CI / cargo clippy (push) Failing after 1s
e2e Tests / e2e (ubuntu-latest) (push) Failing after 1s
Lua CI / luacheck lint (push) Failing after 1s
Build & Publish / Build Neovim aarch64-unknown-linux-musl (push) Failing after 1s
Build & Publish / Build Neovim x86_64-unknown-linux-gnu (push) Failing after 0s
Build & Publish / Build Neovim x86_64-unknown-linux-musl (push) Failing after 1s
Build & Publish / Build C FFI aarch64-linux-android (push) Failing after 0s
Build & Publish / Build C FFI aarch64-unknown-linux-gnu (push) Failing after 0s
Build & Publish / Build C FFI aarch64-unknown-linux-musl (push) Failing after 1s
Build & Publish / Build C FFI x86_64-unknown-linux-gnu (push) Failing after 0s
Build & Publish / Build C FFI x86_64-unknown-linux-musl (push) Failing after 1s
Build & Publish / Build MCP aarch64-unknown-linux-gnu (push) Failing after 1s
Build & Publish / Build MCP aarch64-unknown-linux-musl (push) Failing after 0s
Build & Publish / Build MCP x86_64-unknown-linux-gnu (push) Failing after 1s
Spelling / Spell Check with Typos (push) Failing after 0s
Rust CI / Test (ubuntu-latest) (push) Failing after 0s
Rust CI / cargo fmt (push) Failing after 0s
Stylua / Check lua files using Stylua (push) Failing after 1s
Lua CI / lua-language-server type check (push) Failing after 12m29s
e2e Tests / e2e (alpine-musl) (push) Successful in 57m31s
e2e Tests / e2e (macos-latest) (push) Has been cancelled
Build & Publish / Build C FFI aarch64-apple-darwin (push) Has been cancelled
Rust CI / Test (windows-latest) (push) Has been cancelled
e2e Tests / e2e (windows-latest) (push) Has been cancelled
Nix CI / check (push) Has been cancelled
Python CI / Python bindings (macos-latest) (push) Has been cancelled
Python CI / Python bindings (windows-latest) (push) Has been cancelled
Build & Publish / Build Neovim aarch64-apple-darwin (push) Has been cancelled
Build & Publish / Build Neovim aarch64-pc-windows-msvc (push) Has been cancelled
Build & Publish / Build Neovim x86_64-apple-darwin (push) Has been cancelled
Build & Publish / Build Neovim x86_64-pc-windows-msvc (push) Has been cancelled
Build & Publish / Build C FFI aarch64-pc-windows-msvc (push) Has been cancelled
Build & Publish / Build C FFI x86_64-apple-darwin (push) Has been cancelled
Build & Publish / Build C FFI x86_64-pc-windows-msvc (push) Has been cancelled
Build & Publish / Build MCP aarch64-apple-darwin (push) Has been cancelled
Build & Publish / Build MCP aarch64-pc-windows-msvc (push) Has been cancelled
Build & Publish / Build MCP x86_64-apple-darwin (push) Has been cancelled
Build & Publish / Build MCP x86_64-pc-windows-msvc (push) Has been cancelled
Build & Publish / Build Python wheels aarch64 (macos-latest) (push) Has been cancelled
Build & Publish / Build Python wheels x86_64 (macos-latest) (push) Has been cancelled
Build & Publish / Build Python wheels x86_64 (windows-latest) (push) Has been cancelled
Build & Publish / Release (push) Has been cancelled
Build & Publish / Publish Python wheels to PyPI (push) Has been cancelled
Build & Publish / Publish Rust crates (push) Has been cancelled
Build & Publish / Publish npm packages (push) Has been cancelled
Rust CI / Fuzz Tests (windows-latest) (push) Has been cancelled
Rust CI / Test (macos-latest) (push) Has been cancelled
Rust CI / Fuzz Tests (macos-latest) (push) Has been cancelled
Python CI / Python bindings (ubuntu-latest) (push) Failing after 0s
Build & Publish / Build Neovim aarch64-linux-android (push) Failing after 0s
Build & Publish / Build Neovim aarch64-unknown-linux-gnu (push) Failing after 0s
Build & Publish / Build MCP x86_64-unknown-linux-musl (push) Failing after 1s
Build & Publish / Build Python wheels aarch64 (ubuntu-latest) (push) Failing after 0s
Build & Publish / Build Python wheels x86_64 (ubuntu-latest) (push) Failing after 1s
Build & Publish / Build Python sdist (push) Failing after 1s
Rust CI / Fuzz Tests (ubuntu-latest) (push) Failing after 1s
Rust CI / Build i686-unknown-linux-gnu (push) Failing after 0s
Rust CI / cargo clippy (push) Failing after 1s
e2e Tests / e2e (ubuntu-latest) (push) Failing after 1s
Lua CI / luacheck lint (push) Failing after 1s
Build & Publish / Build Neovim aarch64-unknown-linux-musl (push) Failing after 1s
Build & Publish / Build Neovim x86_64-unknown-linux-gnu (push) Failing after 0s
Build & Publish / Build Neovim x86_64-unknown-linux-musl (push) Failing after 1s
Build & Publish / Build C FFI aarch64-linux-android (push) Failing after 0s
Build & Publish / Build C FFI aarch64-unknown-linux-gnu (push) Failing after 0s
Build & Publish / Build C FFI aarch64-unknown-linux-musl (push) Failing after 1s
Build & Publish / Build C FFI x86_64-unknown-linux-gnu (push) Failing after 0s
Build & Publish / Build C FFI x86_64-unknown-linux-musl (push) Failing after 1s
Build & Publish / Build MCP aarch64-unknown-linux-gnu (push) Failing after 1s
Build & Publish / Build MCP aarch64-unknown-linux-musl (push) Failing after 0s
Build & Publish / Build MCP x86_64-unknown-linux-gnu (push) Failing after 1s
Spelling / Spell Check with Typos (push) Failing after 0s
Rust CI / Test (ubuntu-latest) (push) Failing after 0s
Rust CI / cargo fmt (push) Failing after 0s
Stylua / Check lua files using Stylua (push) Failing after 1s
Lua CI / lua-language-server type check (push) Failing after 12m29s
e2e Tests / e2e (alpine-musl) (push) Successful in 57m31s
e2e Tests / e2e (macos-latest) (push) Has been cancelled
Build & Publish / Build C FFI aarch64-apple-darwin (push) Has been cancelled
Rust CI / Test (windows-latest) (push) Has been cancelled
e2e Tests / e2e (windows-latest) (push) Has been cancelled
Nix CI / check (push) Has been cancelled
Python CI / Python bindings (macos-latest) (push) Has been cancelled
Python CI / Python bindings (windows-latest) (push) Has been cancelled
Build & Publish / Build Neovim aarch64-apple-darwin (push) Has been cancelled
Build & Publish / Build Neovim aarch64-pc-windows-msvc (push) Has been cancelled
Build & Publish / Build Neovim x86_64-apple-darwin (push) Has been cancelled
Build & Publish / Build Neovim x86_64-pc-windows-msvc (push) Has been cancelled
Build & Publish / Build C FFI aarch64-pc-windows-msvc (push) Has been cancelled
Build & Publish / Build C FFI x86_64-apple-darwin (push) Has been cancelled
Build & Publish / Build C FFI x86_64-pc-windows-msvc (push) Has been cancelled
Build & Publish / Build MCP aarch64-apple-darwin (push) Has been cancelled
Build & Publish / Build MCP aarch64-pc-windows-msvc (push) Has been cancelled
Build & Publish / Build MCP x86_64-apple-darwin (push) Has been cancelled
Build & Publish / Build MCP x86_64-pc-windows-msvc (push) Has been cancelled
Build & Publish / Build Python wheels aarch64 (macos-latest) (push) Has been cancelled
Build & Publish / Build Python wheels x86_64 (macos-latest) (push) Has been cancelled
Build & Publish / Build Python wheels x86_64 (windows-latest) (push) Has been cancelled
Build & Publish / Release (push) Has been cancelled
Build & Publish / Publish Python wheels to PyPI (push) Has been cancelled
Build & Publish / Publish Rust crates (push) Has been cancelled
Build & Publish / Publish npm packages (push) Has been cancelled
Rust CI / Fuzz Tests (windows-latest) (push) Has been cancelled
Rust CI / Test (macos-latest) (push) Has been cancelled
Rust CI / Fuzz Tests (macos-latest) (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,260 @@
|
||||
local M = {}
|
||||
|
||||
local utils = require('fff.utils')
|
||||
|
||||
local canonicalize_fff_path = utils.canonicalize_fff_path
|
||||
|
||||
-- State structure definitions
|
||||
M.state = {
|
||||
-- UI state
|
||||
active = false,
|
||||
layout = nil,
|
||||
input_win = nil,
|
||||
input_buf = nil,
|
||||
list_win = nil,
|
||||
list_buf = nil,
|
||||
file_info_win = nil,
|
||||
file_info_buf = nil,
|
||||
preview_win = nil,
|
||||
preview_buf = nil,
|
||||
preview_visible = false,
|
||||
|
||||
-- Data state
|
||||
items = {},
|
||||
filtered_items = {},
|
||||
cursor = 1,
|
||||
top = 1,
|
||||
query = '',
|
||||
line_to_item = {},
|
||||
item_to_lines = {},
|
||||
last_render_ctx = nil,
|
||||
location = nil,
|
||||
|
||||
-- Cursor index to restore after the next search completes (set on resume).
|
||||
-- Lets the re-search run for fresh results while keeping the saved position.
|
||||
pending_restore_cursor = nil,
|
||||
|
||||
-- History cycling state
|
||||
history_offset = nil,
|
||||
next_search_force_combo_boost = false,
|
||||
|
||||
-- Combo state
|
||||
combo_visible = true,
|
||||
combo_initial_cursor = nil,
|
||||
|
||||
-- History cycling state (tracked alongside combo state)
|
||||
updating_from_history = false,
|
||||
|
||||
-- Pagination state
|
||||
pagination = {
|
||||
page_index = 0,
|
||||
page_size = 20,
|
||||
total_matched = 0,
|
||||
prefetch_margin = 5,
|
||||
grep_file_offsets = {},
|
||||
grep_next_file_offset = 0,
|
||||
},
|
||||
|
||||
-- Configuration and mode
|
||||
config = nil,
|
||||
renderer = nil,
|
||||
mode = nil,
|
||||
grep_mode = 'plain',
|
||||
grep_config = nil,
|
||||
grep_regex_fallback_error = nil,
|
||||
|
||||
-- Selection state
|
||||
selected_files = {},
|
||||
selected_file_order = {},
|
||||
selected_items = {},
|
||||
|
||||
-- Cross-mode suggestion state
|
||||
suggestion_items = nil,
|
||||
suggestion_source = nil,
|
||||
|
||||
-- Preview state
|
||||
last_preview_file = nil,
|
||||
last_preview_location = nil,
|
||||
preview_timer = nil,
|
||||
preview_debounce_ms = 10,
|
||||
|
||||
-- Misc
|
||||
ns_id = nil,
|
||||
last_status_info = nil,
|
||||
restore_paste = false,
|
||||
current_file_cache = nil,
|
||||
}
|
||||
|
||||
-- Helper function to generate grep item keys
|
||||
local function grep_item_key(item)
|
||||
return string.format('%s:%d:%d', item.relative_path, item.line_number or 1, item.col or 0)
|
||||
end
|
||||
|
||||
-- Reset history-related state
|
||||
function M.reset_history_state()
|
||||
M.state.history_offset = nil
|
||||
M.state.next_search_force_combo_boost = false
|
||||
M.state.combo_visible = true
|
||||
M.state.combo_initial_cursor = nil
|
||||
M.state.updating_from_history = false
|
||||
end
|
||||
|
||||
-- Complete state reset (called on close)
|
||||
function M.reset_state()
|
||||
M.state.active = false
|
||||
M.state.layout = nil
|
||||
M.state.input_win = nil
|
||||
M.state.input_buf = nil
|
||||
M.state.list_win = nil
|
||||
M.state.list_buf = nil
|
||||
M.state.file_info_win = nil
|
||||
M.state.file_info_buf = nil
|
||||
M.state.preview_win = nil
|
||||
M.state.preview_buf = nil
|
||||
M.state.preview_visible = false
|
||||
|
||||
M.state.items = {}
|
||||
M.state.filtered_items = {}
|
||||
M.state.cursor = 1
|
||||
M.state.top = 1
|
||||
M.state.query = ''
|
||||
M.state.line_to_item = {}
|
||||
M.state.item_to_lines = {}
|
||||
M.state.last_render_ctx = nil
|
||||
M.state.location = nil
|
||||
M.state.pending_restore_cursor = nil
|
||||
|
||||
M.reset_history_state()
|
||||
|
||||
M.state.pagination = {
|
||||
page_index = 0,
|
||||
page_size = 20,
|
||||
total_matched = 0,
|
||||
prefetch_margin = 5,
|
||||
grep_file_offsets = {},
|
||||
grep_next_file_offset = 0,
|
||||
}
|
||||
|
||||
M.state.config = nil
|
||||
M.state.renderer = nil
|
||||
M.state.mode = nil
|
||||
M.state.grep_mode = 'plain'
|
||||
M.state.grep_config = nil
|
||||
M.state.grep_regex_fallback_error = nil
|
||||
|
||||
M.state.selected_files = {}
|
||||
M.state.selected_file_order = {}
|
||||
M.state.selected_items = {}
|
||||
M.state.suggestion_items = nil
|
||||
M.state.suggestion_source = nil
|
||||
|
||||
M.state.last_preview_file = nil
|
||||
M.state.last_preview_location = nil
|
||||
M.state.preview_timer = nil
|
||||
M.state.current_file_cache = nil
|
||||
M.state.ns_id = nil
|
||||
M.state.last_status_info = nil
|
||||
M.state.restore_paste = false
|
||||
M.state.combo_visible = true
|
||||
M.state.combo_initial_cursor = nil
|
||||
M.state.updating_from_history = false
|
||||
end
|
||||
|
||||
-- Clear all selections
|
||||
function M.clear_selections()
|
||||
M.state.selected_files = {}
|
||||
M.state.selected_file_order = {}
|
||||
M.state.selected_items = {}
|
||||
end
|
||||
|
||||
-- Get selected items for quickfix list
|
||||
function M.get_selected_items()
|
||||
local selected = {}
|
||||
|
||||
if M.state.mode == 'grep' then
|
||||
-- Grep mode: return selected items
|
||||
for _, item in pairs(M.state.selected_items) do
|
||||
table.insert(selected, item)
|
||||
end
|
||||
else
|
||||
-- Normal file mode: return selected files
|
||||
for relative_path, _ in pairs(M.state.selected_files) do
|
||||
local abs_path = canonicalize_fff_path(relative_path)
|
||||
if abs_path then table.insert(selected, { relative_path = relative_path }) end
|
||||
end
|
||||
end
|
||||
|
||||
return selected
|
||||
end
|
||||
|
||||
-- Toggle item selection (called from keymaps via M.toggle_select)
|
||||
function M.toggle_selection()
|
||||
if not M.state.active then return end
|
||||
|
||||
local items = M.state.filtered_items
|
||||
if #items == 0 or M.state.cursor > #items then return end
|
||||
|
||||
local item = items[M.state.cursor]
|
||||
if not item or not item.relative_path then return end
|
||||
|
||||
local was_selected
|
||||
|
||||
if M.state.mode == 'grep' then
|
||||
-- Per-occurrence selection for grep mode
|
||||
local key = grep_item_key(item)
|
||||
was_selected = M.state.selected_items[key] ~= nil
|
||||
if was_selected then
|
||||
M.state.selected_items[key] = nil
|
||||
else
|
||||
M.state.selected_items[key] = item
|
||||
end
|
||||
else
|
||||
-- Per-file selection for normal file mode
|
||||
was_selected = M.state.selected_files[item.relative_path]
|
||||
if was_selected then
|
||||
M.state.selected_files[item.relative_path] = nil
|
||||
M.state.selected_file_order = vim.tbl_filter(
|
||||
function(path) return path ~= item.relative_path end,
|
||||
M.state.selected_file_order
|
||||
)
|
||||
else
|
||||
M.state.selected_files[item.relative_path] = true
|
||||
table.insert(M.state.selected_file_order, item.relative_path)
|
||||
end
|
||||
end
|
||||
|
||||
return was_selected
|
||||
end
|
||||
|
||||
-- Ordered, deduped selected file entries for opening (file mode only).
|
||||
-- Each entry has the raw fff relative_path and a cwd-relative edit_path.
|
||||
function M.get_selected_file_entries()
|
||||
if not next(M.state.selected_files) then return {} end
|
||||
|
||||
local entries = {}
|
||||
local seen = {}
|
||||
|
||||
local function add(relative_path)
|
||||
if not relative_path or seen[relative_path] or not M.state.selected_files[relative_path] then return end
|
||||
|
||||
local abs_path = canonicalize_fff_path(relative_path)
|
||||
if not abs_path then return end
|
||||
|
||||
seen[relative_path] = true
|
||||
table.insert(entries, {
|
||||
relative_path = relative_path,
|
||||
edit_path = vim.fn.fnamemodify(abs_path, ':.'),
|
||||
})
|
||||
end
|
||||
|
||||
for _, relative_path in ipairs(M.state.selected_file_order) do
|
||||
add(relative_path)
|
||||
end
|
||||
for relative_path, _ in pairs(M.state.selected_files) do
|
||||
add(relative_path)
|
||||
end
|
||||
|
||||
return entries
|
||||
end
|
||||
|
||||
return M
|
||||
Reference in New Issue
Block a user