fix(neovim): Improve borders and default flex layout (#488)

* fix(neovim): Improve borders and default flex layout

* chore: Update docs for - fix(neovim): Improve borders and default flex layout

* fix(ci): Use gustav pat

* fix(lua): Resolve type check warnings

Annotate state shape and inject-field warnings flagged by
lua-language-server.
This commit is contained in:
Dmitriy Kovalenko
2026-05-19 21:10:18 -07:00
committed by GitHub
parent 11dcdb589d
commit 19ca421550
31 changed files with 2202 additions and 386 deletions
+2 -1
View File
@@ -54,6 +54,7 @@ jobs:
uses: peter-evans/create-pull-request@v7
with:
branch: bot/regenerate-vimdoc
token: ${{ secrets.GUSTAV_PAT }}
delete-branch: true
title: "chore: regenerate Neovim vimdoc"
commit-message: |
@@ -68,5 +69,5 @@ jobs:
- name: Enable auto-merge
if: steps.cpr.outputs.pull-request-number
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_TOKEN: ${{ secrets.GUSTAV_PAT }}
run: gh pr merge --auto --squash "${{ steps.cpr.outputs.pull-request-number }}"
+20 -3
View File
@@ -1,4 +1,5 @@
PLENARY_DIR ?= ../plenary.nvim
MINI_DIR ?= ../mini.nvim
PREFIX ?= /usr/local
LIBDIR ?= $(PREFIX)/lib
@@ -8,7 +9,7 @@ INCLUDEDIR ?= $(PREFIX)/include
STRESS_RUSTFLAGS := --cfg stress
FFF_STRESS_DEFAULT_SEED ?= 0xDEADBEEFCAFEBABE
.PHONY: build build-c-lib install uninstall test test-rust test-lua test-version test-bun test-node prepare-bun prepare-node set-npm-version header test-stress test-stress-seeded test-stress-random test-stress-repos
.PHONY: build build-c-lib install uninstall test test-rust test-lua test-lua-snap test-version test-bun test-node prepare-bun prepare-node set-npm-version header test-stress test-stress-seeded test-stress-random test-stress-repos
all: format test lint
@@ -54,6 +55,10 @@ test-setup:
echo "Cloning plenary.nvim..."; \
git clone --depth 1 https://github.com/nvim-lua/plenary.nvim $(PLENARY_DIR); \
fi
@if [ ! -d "$(MINI_DIR)" ]; then \
echo "Cloning mini.nvim..."; \
git clone --depth 1 https://github.com/echasnovski/mini.nvim $(MINI_DIR); \
fi
test-rust:
cargo test --workspace --features zlob --exclude fff-nvim
@@ -70,6 +75,19 @@ test-lua: test-setup build
exit 1; \
fi
# mini.test reference_screenshot snapshots. Separate runner because mini.test
# spawns child processes and uses its own collector (incompatible with
# PlenaryBustedDirectory).
test-lua-snap: test-setup build
@output=$$(nvim --headless -u tests/minimal_init.lua \
-c "lua require('mini.test').run_file('tests/picker_ui_snap.lua')" 2>&1); \
echo "$$output"; \
if echo "$$output" | grep -qE "SIG(SEGV|ABRT|BUS|FPE|ILL)"; then \
echo ""; \
echo "FAIL: native crash detected during snapshot tests"; \
exit 1; \
fi
test-version: test-setup
nvim --headless -u tests/minimal_init.lua \
-c "PlenaryBustedFile tests/version_spec.lua" 2>&1
@@ -95,8 +113,7 @@ test-bun: prepare-bun
test-node: prepare-node
cd packages/fff-node && npm run build && node test/e2e.mjs
test: test-rust test-lua test-version test-bun test-node
test: test-rust test-lua test-lua-snap test-version test-bun test-node
test-stress-seeded:
FFF_STRESS_SEED="$${FFF_STRESS_SEED:-$(FFF_STRESS_DEFAULT_SEED)}" \
+28 -218
View File
@@ -1,239 +1,49 @@
--- Combo header policy.
---
--- Pure logic: detects whether the current result set has a "combo" boost,
--- and produces the label text for the list separator. The actual divider
--- is rendered by `list_separator` so this module owns no windows or buffers.
local M = {}
local overlay_state = {
left_buf = nil,
left_win = nil,
right_buf = nil,
right_win = nil,
ns_id = nil,
-- Cache last position to avoid unnecessary updates
last_row = nil,
last_col = nil,
last_border_hl = nil,
-- Track if combo was rendered in last call
was_rendered = false,
}
local LEFT_OVERLAY_CONTENT = '├────'
local RIGHT_OVERLAY_CONTENT = '─┤'
local LEFT_OVERLAY_WIDTH = vim.fn.strdisplaywidth(LEFT_OVERLAY_CONTENT)
local LEFT_HEADER_PADDING = LEFT_OVERLAY_WIDTH - 2
local RIGHT_OVERLAY_WIDTH = vim.fn.strdisplaywidth(RIGHT_OVERLAY_CONTENT)
local COMBO_TEXT_FORMAT = 'Last Match (×%d combo) '
local LAST_MATCH_TEXT_FORMAT = 'Last Match '
function M.init(ns_id) overlay_state.ns_id = ns_id end
local COMBO_TEXT_FORMAT = 'Last Match (×%d combo)'
local LAST_MATCH_TEXT = 'Last Match'
--- @param items table[]
--- @param file_picker table
--- @param combo_boost_score_multiplier number
--- @return number|nil idx 1-based item index of the combo anchor, nil if none
--- @return number combo_count Multiplier (combo_match_boost / multiplier)
local function detect_combo_item(items, file_picker, combo_boost_score_multiplier)
if not items or #items == 0 then return nil, 0 end
local first_score = file_picker.get_file_score(1)
local last_score = file_picker.get_file_score(#items)
if first_score.combo_match_boost > combo_boost_score_multiplier then
if first_score and first_score.combo_match_boost > combo_boost_score_multiplier then
return 1, first_score.combo_match_boost / combo_boost_score_multiplier
elseif last_score.combo_match_boost > combo_boost_score_multiplier then
elseif last_score and last_score.combo_match_boost > combo_boost_score_multiplier then
return #items, last_score.combo_match_boost / combo_boost_score_multiplier
end
return nil, 0
end
local function create_header_text(combo_count, win_width, disable_combo_display)
local combo_text
if disable_combo_display then
combo_text = LAST_MATCH_TEXT_FORMAT
else
combo_text = string.format(COMBO_TEXT_FORMAT, combo_count)
end
--- @class FffComboInfo
--- @field idx number Item index of the combo anchor
--- @field text string Label text for the separator
--- @field count number Combo multiplier
local text_len = vim.fn.strdisplaywidth(combo_text)
local available_for_content = win_width - LEFT_HEADER_PADDING - RIGHT_OVERLAY_WIDTH
local remaining_dashes = math.max(0, available_for_content - text_len)
--- @param items table[]
--- @param file_picker table
--- @param combo_boost_score_multiplier number
--- @param disable_combo_display boolean
--- @return FffComboInfo|nil
function M.detect(items, file_picker, combo_boost_score_multiplier, disable_combo_display)
local idx, count = detect_combo_item(items, file_picker, combo_boost_score_multiplier)
if not idx then return nil end
return string.rep(' ', LEFT_HEADER_PADDING) .. combo_text .. string.rep('', remaining_dashes), text_len
end
local function apply_header_highlights(buf, ns_id, line_idx, text_len, border_hl)
local config = require('fff.conf').get()
vim.api.nvim_buf_set_extmark(buf, ns_id, line_idx - 1, 0, { end_row = line_idx, end_col = 0, hl_group = border_hl })
vim.api.nvim_buf_set_extmark(
buf,
ns_id,
line_idx - 1,
LEFT_HEADER_PADDING,
{ end_col = LEFT_HEADER_PADDING + text_len, hl_group = config.hl.combo_header }
)
end
local function get_or_create_overlay_buf(state_key)
if not overlay_state[state_key] or not vim.api.nvim_buf_is_valid(overlay_state[state_key]) then
---@diagnostic disable-next-line: assign-type-mismatch
overlay_state[state_key] = vim.api.nvim_create_buf(false, true)
vim.api.nvim_set_option_value('bufhidden', 'wipe', { buf = overlay_state[state_key] })
end
return overlay_state[state_key]
end
local function update_overlay_content(buf, content, border_hl)
-- Batch all buffer operations together for performance
vim.api.nvim_set_option_value('modifiable', true, { buf = buf })
vim.api.nvim_buf_set_lines(buf, 0, -1, false, { content })
vim.api.nvim_buf_clear_namespace(buf, overlay_state.ns_id, 0, -1)
vim.api.nvim_buf_set_extmark(buf, overlay_state.ns_id, 0, 0, { end_row = 1, end_col = 0, hl_group = border_hl })
vim.api.nvim_set_option_value('modifiable', false, { buf = buf })
end
local function position_overlay_window(state_key, buf, width, row, col)
local win_config = {
relative = 'editor',
width = width,
height = 1,
row = row,
col = col,
style = 'minimal',
border = 'none',
focusable = false,
zindex = 250,
}
if overlay_state[state_key] and vim.api.nvim_win_is_valid(overlay_state[state_key]) then
vim.api.nvim_win_set_config(overlay_state[state_key], win_config)
else
---@diagnostic disable-next-line: assign-type-mismatch
overlay_state[state_key] = vim.api.nvim_open_win(buf, false, win_config)
end
vim.api.nvim_set_option_value('winhighlight', 'Normal:Normal', { win = overlay_state[state_key] })
end
local function update_overlays(list_win, combo_header_line, border_hl)
local list_config = vim.api.nvim_win_get_config(list_win)
-- combo_header_line is a 1-based buffer line index (includes any padding offset)
-- list_config.row is where the window starts (0-based, at the top border)
-- Content starts at list_config.row + 1 (after the top border)
-- Buffer line 1 -> screen row (list_config.row + 1)
-- Buffer line N -> screen row (list_config.row + N)
-- Since combo_header_line is 1-based, the formula naturally works out
local combo_header_row = list_config.row + combo_header_line
-- Skip update if position and highlight haven't changed
if
overlay_state.last_row == combo_header_row
and overlay_state.last_col == list_config.col
and overlay_state.last_border_hl == border_hl
and overlay_state.left_win
and vim.api.nvim_win_is_valid(overlay_state.left_win)
and overlay_state.right_win
and vim.api.nvim_win_is_valid(overlay_state.right_win)
then
return
end
overlay_state.last_row = combo_header_row
overlay_state.last_col = list_config.col
overlay_state.last_border_hl = border_hl
local left_buf = get_or_create_overlay_buf('left_buf')
local right_buf = get_or_create_overlay_buf('right_buf')
update_overlay_content(left_buf, LEFT_OVERLAY_CONTENT, border_hl)
update_overlay_content(right_buf, RIGHT_OVERLAY_CONTENT, border_hl)
position_overlay_window('left_win', left_buf, LEFT_OVERLAY_WIDTH, combo_header_row, list_config.col)
position_overlay_window(
'right_win',
right_buf,
RIGHT_OVERLAY_WIDTH,
combo_header_row,
list_config.col + list_config.width
)
end
local function clear_overlays_internal()
if overlay_state.left_win and vim.api.nvim_win_is_valid(overlay_state.left_win) then
vim.api.nvim_win_close(overlay_state.left_win, true)
overlay_state.left_win = nil
end
if overlay_state.right_win and vim.api.nvim_win_is_valid(overlay_state.right_win) then
vim.api.nvim_win_close(overlay_state.right_win, true)
overlay_state.right_win = nil
end
overlay_state.last_row = nil
overlay_state.last_col = nil
overlay_state.last_border_hl = nil
-- Note: we intentionally don't clear was_rendered here to track the transition
end
function M.detect_and_prepare(items, file_picker, win_width, combo_boost_score_multiplier, disable_combo_display)
local combo_item_index, combo_count = detect_combo_item(items, file_picker, combo_boost_score_multiplier)
if not combo_item_index then return false, nil, 0, nil end
local header_line, text_len = create_header_text(combo_count, win_width, disable_combo_display)
return true, header_line, text_len, combo_item_index
end
--- Render combo highlights and overlays
--- @return boolean was_hidden True if combo was just hidden (was rendered before, not now)
function M.render_highlights_and_overlays(
combo_item_index,
text_len,
list_buf,
list_win,
ns_id,
border_hl,
item_to_lines,
prompt_position,
total_items
)
local was_rendered_before = overlay_state.was_rendered
local is_rendering_now = false
if not combo_item_index then
clear_overlays_internal()
else
local combo_item_lines = item_to_lines[combo_item_index]
if not combo_item_lines then
clear_overlays_internal()
else
local combo_header_line_idx = combo_item_lines.first
apply_header_highlights(list_buf, ns_id, combo_header_line_idx, text_len, border_hl)
if prompt_position == 'bottom' and total_items and total_items > 1 then
combo_header_line_idx = combo_header_line_idx - 1
end
-- when rendering items in the reverse order for some reason this makes the
-- indexing shifted by one in the internal list config, so just adjust for that
update_overlays(list_win, combo_header_line_idx, border_hl)
is_rendering_now = true
end
end
overlay_state.was_rendered = is_rendering_now
-- Return true if combo was just hidden (transition from visible to hidden)
return was_rendered_before and not is_rendering_now
end
--- Get the combo header text for a given item
--- @param combo_count number The combo multiplier count
--- @param win_width number Window width for formatting
--- @param disable_combo_display boolean Whether to show combo count
--- @return string header_text The formatted header line
--- @return number text_len Length of the header text (without padding)
function M.get_combo_header_text(combo_count, win_width, disable_combo_display)
return create_header_text(combo_count, win_width, disable_combo_display)
end
function M.get_overlay_widths() return LEFT_OVERLAY_WIDTH, RIGHT_OVERLAY_WIDTH end
function M.cleanup()
clear_overlays_internal()
overlay_state.was_rendered = false
local text = disable_combo_display and LAST_MATCH_TEXT or string.format(COMBO_TEXT_FORMAT, count)
return { idx = idx, text = text, count = count }
end
return M
+3 -8
View File
@@ -14,21 +14,16 @@ local M = {}
--- @field access_frecency_score number Access-based frecency score
--- @field modification_frecency_score number Modification-based frecency score
--- @field git_status string|nil Git status string (e.g. 'modified', 'untracked') if file is in git repo
--- internal:
--- @field _has_group_header boolean Internal flag for render_line to indicate if this item has a combo header line (not from Rust)
--- Render a file item line
--- @param item FileItem File item from Rust
--- @param ctx ListRenderContext Render context with all state
--- @param item_idx number Item index (1-based)
--- @return string[] Array of line strings (1 or 2 lines if combo)
function M.render_line(item, ctx, item_idx)
--- @param _item_idx number Item index (1-based)
--- @return string[] Array of line strings (always exactly 1)
function M.render_line(item, ctx, _item_idx)
local icons = require('fff.file_picker.icons')
local lines = {}
local has_combo = item_idx == 1 and ctx.has_combo and ctx.combo_header_line
if has_combo then table.insert(lines, ctx.combo_header_line) end
local icon, _ = icons.get_icon(item.name, item.extension, false)
-- Build frecency indicator (debug mode only)
+3
View File
@@ -210,10 +210,12 @@ function M.render_line(item, ctx)
local match_line = render_match_line(item, ctx)
if is_new_group then
---@diagnostic disable-next-line: inject-field
item._has_group_header = true
local header_line = build_group_header(item, ctx)
return { header_line, match_line }
else
---@diagnostic disable-next-line: inject-field
item._has_group_header = false
return { match_line }
end
@@ -237,6 +239,7 @@ function M.apply_highlights(item, ctx, item_idx, buf, ns_id, line_idx, line_cont
-- If this item has a group header, highlight it (the line above)
-- using file_renderer for identical appearance to the file picker list.
---@diagnostic disable-next-line: undefined-field
if item._has_group_header then apply_group_header_highlights(item, ctx, buf, ns_id, row - 1) end
end
+44 -34
View File
@@ -1,17 +1,4 @@
--- List Renderer
--- Handles all list rendering: line generation, virtual rows, bottom padding,
--- buffer writes, cursor positioning, and highlight application.
---
--- Virtual rows (combo headers, grep file group headers) are decorations that
--- belong to buffer rendering, NOT to the data model. The cursor and selection
--- always operate on the items array (1-based indices), never on buffer lines.
---
--- Pagination is unaffected: Rust returns N items per page. The renderer may
--- produce N + K buffer lines (where K = number of virtual header rows), but
--- the page_size contract with Rust stays item-based.
---
--- Selection always operates on item.relative_path keys. Virtual rows have no identity
--- of their own — they derive from the item they belong to.
--- List Renderer, renders any type of list results produced by fff
local M = {}
--- @class ListRenderContext
@@ -49,18 +36,23 @@ local M = {}
--- @field item_to_lines table<number, ItemLineMapping> Maps item index -> line range
--- @field padding_offset number Number of empty lines prepended for bottom prompt
--- @field total_content_lines number Lines before padding was applied
--- @field separator_line number|nil Buffer line (1-based) where separator sits, nil if none
--- Generate all display lines from items using the renderer.
--- Each item may produce 1 or more lines (virtual header + content).
--- When cross-mode suggestions are active, a suggestion banner is prepended
--- (for top prompt) or appended (for bottom prompt) so it always appears
--- above the suggestion items visually.
--- @class ListSeparator
--- @field idx number 1-based item index — separator visually sits between this item and the previous one in the iteration order
--- @field text string Label text rendered inside the separator
--- @field text_hl string|nil Highlight group for label
--- @field border_hl string|nil Highlight group for the dashes
--- Generate all display lines from items from the renderer ctx
--- @param ctx table
--- @return string[] lines Array of line strings
--- @return table<number, ItemLineMapping> item_to_lines
--- @return number|nil separator_line 1-based buffer line of the separator, nil if none
local function generate_item_lines(ctx)
local lines = {}
local item_to_lines = {}
local separator_line = nil
-- Cross-mode suggestion header: rendered above items visually.
-- For top prompt that means before items; for bottom prompt after items
@@ -92,25 +84,39 @@ local function generate_item_lines(ctx)
local renderer = ctx.renderer
if not renderer then renderer = require('fff.file_renderer') end
-- Insert a gap on the side of the anchor away from the prompt.
-- Bottom prompt: gap BEFORE anchor in iter — anchor renders last with
-- reverse iter, so gap lands just above anchor visually.
-- Top prompt: gap AFTER anchor in iter — anchor renders first with
-- forward iter, so gap lands just below anchor visually.
-- Either way: anchor stays adjacent to the prompt, separator on far side.
local gap_before_anchor = ctx.prompt_position == 'bottom'
for i = ctx.iter_start, ctx.iter_end, ctx.iter_step do
if ctx.separator and ctx.separator.idx == i and gap_before_anchor then
table.insert(lines, '')
separator_line = #lines
end
local item = ctx.items[i]
local item_start_line = #lines + 1
-- Renderer returns 1+ lines: virtual headers first, content line last.
-- This contract is shared by file_renderer (combo header) and
-- grep_renderer (file group header).
---@diagnostic disable-next-line: param-type-mismatch
local item_lines = renderer.render_line(item, ctx, i)
vim.list_extend(lines, item_lines)
local item_end_line = #lines
local virtual_count = item_end_line - item_start_line -- 0 if single line, 1 if header + content
local virtual_count = item_end_line - item_start_line
item_to_lines[i] = {
first = item_start_line,
last = item_end_line,
virtual_count = virtual_count,
}
if ctx.separator and ctx.separator.idx == i and not gap_before_anchor then
table.insert(lines, '')
separator_line = #lines
end
end
-- For bottom prompt: suggestion header goes after items (appears above visually)
@@ -120,7 +126,7 @@ local function generate_item_lines(ctx)
end
end
return lines, item_to_lines
return lines, item_to_lines, separator_line
end
--- Apply bottom padding: prepend empty lines so content sits at the bottom.
@@ -128,29 +134,31 @@ end
--- @param lines string[] Lines array (mutated)
--- @param item_to_lines table<number, ItemLineMapping> Mapping (mutated)
--- @param ctx table
--- @param separator_line number|nil Pre-padding separator line (mutated via return value)
--- @return number padding_offset Number of empty lines prepended
local function apply_bottom_padding(lines, item_to_lines, ctx)
if ctx.prompt_position ~= 'bottom' then return 0 end
--- @return number|nil shifted_separator_line
local function apply_bottom_padding(lines, item_to_lines, ctx, separator_line)
if ctx.prompt_position ~= 'bottom' then return 0, separator_line end
local total_content_lines = #lines
local empty_lines_needed = math.max(0, ctx.win_height - total_content_lines)
if empty_lines_needed > 0 then
-- Prepend empty lines
for _ = empty_lines_needed, 1, -1 do
table.insert(lines, 1, string.rep(' ', ctx.win_width + 5))
end
-- Shift all line indices
for i = ctx.display_start, ctx.display_end do
if item_to_lines[i] then
item_to_lines[i].first = item_to_lines[i].first + empty_lines_needed
item_to_lines[i].last = item_to_lines[i].last + empty_lines_needed
end
end
if separator_line then separator_line = separator_line + empty_lines_needed end
end
return empty_lines_needed
return empty_lines_needed, separator_line
end
--- Write lines to the buffer and position the cursor on the correct line.
@@ -218,11 +226,13 @@ end
--- @param list_buf number List buffer handle
--- @param list_win number List window handle
--- @param ns_id number Highlight namespace
--- @return table<number, ItemLineMapping> item_to_lines for combo/scrollbar use
--- @return number|nil separator_line 1-based buffer line of the separator (post-padding), nil if none
--- @return table<number, ItemLineMapping> item_to_lines
function M.render(ctx, list_buf, list_win, ns_id)
local lines, item_to_lines = generate_item_lines(ctx)
local lines, item_to_lines, separator_line = generate_item_lines(ctx)
apply_bottom_padding(lines, item_to_lines, ctx)
local _, shifted_separator_line = apply_bottom_padding(lines, item_to_lines, ctx, separator_line)
separator_line = shifted_separator_line
update_buffer_and_cursor(lines, item_to_lines, ctx, list_buf, list_win, ns_id)
if #ctx.items > 0 then apply_all_highlights(lines, item_to_lines, ctx, list_buf, ns_id) end
@@ -245,7 +255,7 @@ function M.render(ctx, list_buf, list_win, ns_id)
end
end
return item_to_lines
return separator_line, item_to_lines
end
--- Get the buffer line for an item's content (selectable) line.
+138
View File
@@ -0,0 +1,138 @@
-- Renders list separator at any index, designed to be floating on top of list renderer
local M = {}
local LEFT_PADDING = 2
local RIGHT_PADDING = 1
-- overflow BOTH borders on left and right
local OVERFLOW_TOTAL = 2
---@class fff.list_separator.State
---@field buf integer|nil
---@field win integer|nil
---@field ns_id integer
---@field last string|nil
local state = {
buf = nil,
win = nil,
ns_id = 0,
last = nil,
}
--- @class FffSeparatorOpts
--- @field list_win number List window handle (used to read its config)
--- @field row number 1-based screen row where the separator sits (relative to editor)
--- @field text string Label text rendered between the dashes (callers prefix arrow glyphs themselves)
--- @field text_hl string Highlight group for the label
--- @field border_hl string Highlight group for the dashes / junctions
function M.init(ns_id) state.ns_id = ns_id end
---@return integer
local function get_or_create_buf()
if not state.buf or not vim.api.nvim_buf_is_valid(state.buf) then
state.buf = vim.api.nvim_create_buf(false, true)
vim.api.nvim_set_option_value('bufhidden', 'wipe', { buf = state.buf })
end
return state.buf --[[@as integer]]
end
--- @param total_width number Width of the float in cells (incl. `├` and `┤`)
--- @param text string Label text (we add the surrounding spaces)
--- @return string content
--- @return number label_byte_start Byte offset where the highlighted label begins
--- @return number label_byte_len Byte length of the highlighted label run
local function build_line(total_width, text)
local label = ' ' .. text .. ' '
local label_disp = vim.fn.strdisplaywidth(label)
-- 2 cells consumed by `├` and `┤`, plus LEFT_PADDING + RIGHT_PADDING dashes.
local inner = math.max(0, total_width - 2 - LEFT_PADDING - RIGHT_PADDING - label_disp)
local left = string.rep('', LEFT_PADDING)
local right = string.rep('', inner + RIGHT_PADDING)
local content = '' .. left .. label .. right .. ''
local label_byte_start = #('' .. left)
return content, label_byte_start, #label
end
--- Render or reposition the separator
--- @param opts FffSeparatorOpts
function M.update(opts)
local list_cfg = vim.api.nvim_win_get_config(opts.list_win)
local list_col = list_cfg.col
local list_width = list_cfg.width
-- Span the full bordered list footprint: `├` lands on the left vertical,
-- `┤` on the right. nvim_win_get_config().col is already the column of the
-- left border, so we don't shift further.
local total_width = list_width + OVERFLOW_TOTAL
local col = list_col
local row = opts.row
local key = string.format('%d|%d|%d|%s|%s|%s', row, col, total_width, opts.text, opts.text_hl, opts.border_hl)
if state.last == key and state.win and vim.api.nvim_win_is_valid(state.win) then return end
local buf = get_or_create_buf()
local content, label_byte_start, label_byte_len = build_line(total_width, opts.text)
vim.api.nvim_set_option_value('modifiable', true, { buf = buf })
vim.api.nvim_buf_set_lines(buf, 0, -1, false, { content })
vim.api.nvim_buf_clear_namespace(buf, state.ns_id, 0, -1)
vim.api.nvim_buf_set_extmark(buf, state.ns_id, 0, 0, {
end_row = 1,
end_col = 0,
hl_group = opts.border_hl,
hl_eol = false,
})
if label_byte_len > 0 then
vim.api.nvim_buf_set_extmark(buf, state.ns_id, 0, label_byte_start, {
end_row = 0,
end_col = label_byte_start + label_byte_len,
hl_group = opts.text_hl,
})
end
vim.api.nvim_set_option_value('modifiable', false, { buf = buf })
-- the actual fake floating window
local win_cfg = {
relative = 'editor',
width = total_width,
height = 1,
row = row,
col = col,
style = 'minimal',
border = 'none',
focusable = false,
zindex = 250,
}
if state.win and vim.api.nvim_win_is_valid(state.win) then
vim.api.nvim_win_set_config(state.win, win_cfg)
else
state.win = vim.api.nvim_open_win(buf, false, win_cfg)
vim.api.nvim_set_option_value('winhighlight', 'Normal:Normal', { win = state.win })
end
state.last = key
end
--- Hide the separator if visible. Safe to call repeatedly.
--- @return boolean was_visible True if a hide actually happened
function M.hide()
local was_visible = false
if state.win and vim.api.nvim_win_is_valid(state.win) then
pcall(vim.api.nvim_win_close, state.win, true)
was_visible = true
end
state.win = nil
state.last = nil
return was_visible
end
function M.cleanup()
M.hide()
if state.buf and vim.api.nvim_buf_is_valid(state.buf) then
pcall(vim.api.nvim_buf_delete, state.buf, { force = true })
end
state.buf = nil
end
return M
+352 -122
View File
@@ -6,6 +6,7 @@ local preview = require('fff.file_picker.preview')
local utils = require('fff.utils')
local location_utils = require('fff.location_utils')
local combo_renderer = require('fff.combo_renderer')
local list_separator = require('fff.list_separator')
local list_renderer = require('fff.list_renderer')
local scrollbar = require('fff.scrollbar')
local rust = require('fff.rust')
@@ -40,26 +41,54 @@ local BORDER_PRESETS = {
}
local T_JUNCTION_PRESETS = {
single = { '', '' },
double = { '', '' },
rounded = { '', '' }, -- Rounded only affects corners
solid = { '', '' },
shadow = { '', '' },
none = { '', '' },
single = { '', '', '', '', '' },
double = { '', '', '', '', '' },
rounded = { '', '', '', '', '' },
solid = { '', '', '', '', '' },
shadow = { '', '', '', '', '' },
none = { '', '', '', '', '' },
}
--- Get border characters from vim.o.winborder for custom connected borders
--- @return table Array of 8 border characters
--- @return table Array of 2 T-junction characters (left, right)
--- @return table Array of 5 T-junction characters (left, right, top, bottom, cross)
local function get_border_chars()
local winborder = vim.o.winborder or 'single'
if BORDER_PRESETS[winborder] then return BORDER_PRESETS[winborder], T_JUNCTION_PRESETS[winborder] end
-- Fallback to single for unknown border styles
return BORDER_PRESETS.single, T_JUNCTION_PRESETS.single
end
--- Resolve a corner glyph based on adjacency flags. Each neighbour flag means
--- another float shares the edge meeting at that corner, so the corner needs
--- to extend a stem in that direction instead of being a plain corner.
--- @param corner string Default corner glyph (e.g. '┌')
--- @param chars table Border preset
--- @param j table T-junction preset { left, right, top, bottom, cross }
--- @param which 'tl'|'tr'|'bl'|'br' Which corner we're computing
--- @param n table { up=bool, down=bool, left=bool, right=bool } adjacency
--- @return string
local function resolve_corner(corner, chars, j, which, n)
-- Stems present at this corner from the float's own borders.
local stems = {
tl = { down = chars[8] ~= '', right = chars[2] ~= '' },
tr = { down = chars[4] ~= '', left = chars[2] ~= '' },
bl = { up = chars[8] ~= '', right = chars[6] ~= '' },
br = { up = chars[4] ~= '', left = chars[6] ~= '' },
}
local s = stems[which]
-- Compose final stems from own + neighbours
local up = s.up or n.up
local down = s.down or n.down
local left = s.left or n.left
local right = s.right or n.right
local count = (up and 1 or 0) + (down and 1 or 0) + (left and 1 or 0) + (right and 1 or 0)
if count >= 4 then return j[5] end
if up and down and (left or right) then return left and j[2] or j[1] end
if left and right and (up or down) then return up and j[4] or j[3] end
return corner
end
local function get_prompt_position()
local config = M.state.config
@@ -98,7 +127,7 @@ local function get_preview_position()
local flex = config.layout.flex
if flex then
local size = flex.size or 130
local size = flex.size or 80
local wrap = flex.wrap or 'top'
if terminal_width < size then return wrap end
end
@@ -291,19 +320,65 @@ end
local function build_window_configs(layout, config)
local border_chars, t_junctions = get_border_chars()
local prompt_position = get_prompt_position()
local preview_position = get_preview_position()
local has_preview = layout.preview ~= nil
local title = ' ' .. (config.title or 'FFFiles') .. ' '
-- List border: when prompt at bottom, list has top+sides (no bottom); when top, T-junctions at top
-- Adjacency flags. Used to decide which corners need T-junctions because a
-- neighbouring float shares that edge.
local list_neighbour_input_top = prompt_position == 'top'
local list_neighbour_input_bottom = prompt_position == 'bottom'
local list_neighbour_preview_top = has_preview and preview_position == 'top'
local list_neighbour_preview_bottom = has_preview and preview_position == 'bottom'
local list_neighbour_preview_left = has_preview and preview_position == 'left'
local list_neighbour_preview_right = has_preview and preview_position == 'right'
-- A side preview shares a *column* (vertical) with the list. Express that
-- as up+down neighbour stems on the corners next to that column. The
-- horizontal-side stem (`left`/`right`) is only added when the corner row
-- is also the preview's top/bottom edge row — i.e. the picker's outer
-- top/bottom edge AND no input/preview is stacked above/below the list at
-- that side.
local list_top_at_picker_top = (not list_neighbour_preview_top) and not list_neighbour_input_top
local list_bottom_at_picker_bottom = (not list_neighbour_preview_bottom) and not list_neighbour_input_bottom
-- Top corners only get an `up` stem if something is genuinely above this
-- row (input or preview stacked above). A side preview shares the column
-- but starts at the same top row, so it contributes a `down` stem only.
local corners = {
tl = resolve_corner(border_chars[1], border_chars, t_junctions, 'tl', {
up = list_neighbour_preview_top or list_neighbour_input_top,
down = list_neighbour_preview_left,
left = list_neighbour_preview_left and list_top_at_picker_top,
}),
tr = resolve_corner(border_chars[3], border_chars, t_junctions, 'tr', {
up = list_neighbour_preview_top or list_neighbour_input_top,
down = list_neighbour_preview_right,
right = list_neighbour_preview_right and list_top_at_picker_top,
}),
br = resolve_corner(border_chars[5], border_chars, t_junctions, 'br', {
down = list_neighbour_preview_bottom or list_neighbour_input_bottom,
up = list_neighbour_preview_right,
right = list_neighbour_preview_right and list_bottom_at_picker_bottom,
}),
bl = resolve_corner(border_chars[7], border_chars, t_junctions, 'bl', {
down = list_neighbour_preview_bottom or list_neighbour_input_bottom,
up = list_neighbour_preview_left,
left = list_neighbour_preview_left and list_bottom_at_picker_bottom,
}),
}
-- Drop the bottom row on bottom-prompt (input owns it); top row on top-prompt.
local list_border = prompt_position == 'bottom'
and { border_chars[1], border_chars[2], border_chars[3], border_chars[4], '', '', '', border_chars[8] }
and { corners.tl, border_chars[2], corners.tr, border_chars[4], '', '', '', border_chars[8] }
or {
t_junctions[1],
corners.tl,
border_chars[2],
t_junctions[2],
corners.tr,
border_chars[4],
border_chars[5],
corners.br,
border_chars[6],
border_chars[7],
corners.bl,
border_chars[8],
}
@@ -322,19 +397,71 @@ local function build_window_configs(layout, config)
list_cfg.title_pos = 'left'
end
-- Input border: inverse of list border
-- Input is glued to the list along one row, and (when preview is on
-- top/bottom) it can also touch the preview on the other row. Side-by-side
-- previews share the input's left/right column too.
local input_neighbour_preview_left = has_preview and preview_position == 'left'
local input_neighbour_preview_right = has_preview and preview_position == 'right'
local input_neighbour_preview_top = has_preview and preview_position == 'top' and prompt_position == 'top'
local input_neighbour_preview_bottom = has_preview and preview_position == 'bottom' and prompt_position == 'bottom'
-- Side-by-side preview shares a *column* (vertical) with the input. The
-- preview vertical extends past the input corner on both sides, so we add
-- `up`/`down` neighbour stems. When the input ALSO sits at the top edge
-- of the picker (prompt=top) the preview top horizontal extends from the
-- shared corner toward the preview, so we need a horizontal stem too.
local input_top_at_picker_top = prompt_position == 'top'
local input_bottom_at_picker_bottom = prompt_position == 'bottom'
-- For each top corner figure out whether a vertical extends UP past it
-- (true only if the input is glued to a list/preview *above*) and whether
-- a horizontal extends OUT (true only if a side preview *also* shares the
-- same top-edge row, i.e. prompt=top with side preview).
local function tl_extends_up()
if prompt_position == 'bottom' then return true end -- list above
if input_neighbour_preview_top then return true end -- preview stack above
return false
end
local function tr_extends_up() return tl_extends_up() end
local function bl_extends_down()
if prompt_position == 'top' then return true end -- list below
if input_neighbour_preview_bottom then return true end -- preview stack below
return false
end
local function br_extends_down() return bl_extends_down() end
local function input_corners()
return {
tl = resolve_corner(border_chars[1], border_chars, t_junctions, 'tl', {
up = tl_extends_up(),
-- side preview shares the column → preview vertical extends from this
-- corner downward when input is at the top edge, upward when at the
-- bottom edge. Horizontal stem (`left`/`right`) only when the corner
-- row is also the preview top/bottom row (true at picker outer edge).
down = input_neighbour_preview_left and input_top_at_picker_top,
left = input_neighbour_preview_left and input_top_at_picker_top,
}),
tr = resolve_corner(border_chars[3], border_chars, t_junctions, 'tr', {
up = tr_extends_up(),
down = input_neighbour_preview_right and input_top_at_picker_top,
right = input_neighbour_preview_right and input_top_at_picker_top,
}),
br = resolve_corner(border_chars[5], border_chars, t_junctions, 'br', {
down = br_extends_down(),
up = input_neighbour_preview_right and input_bottom_at_picker_bottom,
right = input_neighbour_preview_right and input_bottom_at_picker_bottom,
}),
bl = resolve_corner(border_chars[7], border_chars, t_junctions, 'bl', {
down = bl_extends_down(),
up = input_neighbour_preview_left and input_bottom_at_picker_bottom,
left = input_neighbour_preview_left and input_bottom_at_picker_bottom,
}),
}
end
local ic = input_corners()
local input_border = prompt_position == 'bottom'
and {
t_junctions[1],
border_chars[2],
t_junctions[2],
border_chars[4],
border_chars[5],
border_chars[6],
border_chars[7],
border_chars[8],
}
or { border_chars[1], border_chars[2], border_chars[3], border_chars[4], '', '', '', border_chars[8] }
and { ic.tl, border_chars[2], ic.tr, border_chars[4], ic.br, border_chars[6], ic.bl, border_chars[8] }
or { ic.tl, border_chars[2], ic.tr, border_chars[4], '', '', '', border_chars[8] }
local input_cfg = {
relative = 'editor',
@@ -353,6 +480,47 @@ local function build_window_configs(layout, config)
local preview_cfg = nil
if layout.preview then
-- Preview corners that touch the list/input column share verticals with
-- those floats; the other side stays a plain corner. When the debug
-- file_info panel is rendered above the preview, the preview's top edge
-- additionally meets the file_info's bottom edge.
local has_file_info_above = layout.file_info ~= nil
local preview_corners = {
tl = resolve_corner(border_chars[1], border_chars, t_junctions, 'tl', {
right = preview_position == 'left',
up = has_file_info_above,
}),
tr = resolve_corner(border_chars[3], border_chars, t_junctions, 'tr', {
left = preview_position == 'right',
up = has_file_info_above,
}),
br = resolve_corner(border_chars[5], border_chars, t_junctions, 'br', {
left = preview_position == 'right',
}),
bl = resolve_corner(border_chars[7], border_chars, t_junctions, 'bl', {
right = preview_position == 'left',
}),
}
-- For top/bottom preview position we additionally have a shared row with
-- the list; the matching horizontal edge gets T-junctions.
if preview_position == 'top' then
preview_corners.bl = resolve_corner(border_chars[7], border_chars, t_junctions, 'bl', { down = true })
preview_corners.br = resolve_corner(border_chars[5], border_chars, t_junctions, 'br', { down = true })
elseif preview_position == 'bottom' then
preview_corners.tl = resolve_corner(border_chars[1], border_chars, t_junctions, 'tl', { up = true })
preview_corners.tr = resolve_corner(border_chars[3], border_chars, t_junctions, 'tr', { up = true })
end
local pc = preview_corners
local preview_border = {
pc.tl,
border_chars[2],
pc.tr,
border_chars[4],
pc.br,
border_chars[6],
pc.bl,
border_chars[8],
}
preview_cfg = {
relative = 'editor',
width = layout.preview.width,
@@ -360,8 +528,11 @@ local function build_window_configs(layout, config)
col = layout.preview.col,
row = layout.preview.row,
style = 'minimal',
border = border_chars,
title = ' Preview ',
border = preview_border,
-- Title hidden when file_info is rendered above — its footer already
-- says "Preview". Otherwise show the preview title with the active
-- file's relative path (set in update_preview_title).
title = layout.file_info and '' or ' Preview ',
title_pos = 'left',
zindex = 51,
}
@@ -369,6 +540,44 @@ local function build_window_configs(layout, config)
local file_info_cfg = nil
if layout.file_info then
-- file_info sits on top of the preview. The corner shared with the list's
-- right vertical (preview=right) gets a horizontal stem pointing *into*
-- the list at the top, so the corner reads as a `┬` instead of `┌`.
-- Symmetric for preview=left.
local list_meets_fi_left = preview_position == 'right'
local list_meets_fi_right = preview_position == 'left'
local fi_corners = {
tl = resolve_corner(border_chars[1], border_chars, t_junctions, 'tl', {
-- preview=right -> list lives to the left of file_info's tl, list
-- top horizontal stem points right *into* the corner.
left = list_meets_fi_left,
}),
tr = resolve_corner(border_chars[3], border_chars, t_junctions, 'tr', {
right = list_meets_fi_right,
}),
-- bl/br share a row with the preview top. The file_info bottom row IS
-- the preview top row, so the corner doubles as preview's top corner:
-- only add a `down` stem (preview vertical extends below). The list's
-- adjacent column has *vertical* there, not horizontal, so we don't
-- add a left/right stem here — the list verticals stay continuous and
-- the corner reads as `├` / `┤`.
bl = resolve_corner(border_chars[7], border_chars, t_junctions, 'bl', {
down = true,
}),
br = resolve_corner(border_chars[5], border_chars, t_junctions, 'br', {
down = true,
}),
}
local fi_border = {
fi_corners.tl,
border_chars[2],
fi_corners.tr,
border_chars[4],
fi_corners.br,
border_chars[6],
fi_corners.bl,
border_chars[8],
}
file_info_cfg = {
relative = 'editor',
width = layout.file_info.width,
@@ -376,9 +585,13 @@ local function build_window_configs(layout, config)
col = layout.file_info.col,
row = layout.file_info.row,
style = 'minimal',
border = border_chars,
border = fi_border,
title = ' File Info ',
title_pos = 'left',
-- Above the list zindex so the file_info borders win over the list's
-- shared-column verticals at junction cells, and above the preview so
-- the shared bottom-border row reads as file_info's `├──┤`.
zindex = 53,
}
end
@@ -528,26 +741,23 @@ function M.calculate_layout_dimensions(cfg)
end
-- Section 4: Position debug panel (if enabled)
if cfg.debug_enabled and preview_enabled and layout.preview then
if cfg.preview_position == 'left' or cfg.preview_position == 'right' then
layout.file_info = {
width = layout.preview.width,
height = cfg.file_info_height,
col = layout.preview.col,
row = layout.preview.row,
}
layout.preview.row = layout.preview.row + cfg.file_info_height + SEPARATOR_HEIGHT + 1
layout.preview.height = math.max(3, layout.preview.height - cfg.file_info_height - SEPARATOR_HEIGHT - 1)
else
layout.file_info = {
width = layout.preview.width,
height = cfg.file_info_height,
col = layout.preview.col,
row = layout.preview.row,
}
layout.preview.row = layout.preview.row + cfg.file_info_height + SEPARATOR_HEIGHT + 1
layout.preview.height = math.max(3, layout.preview.height - cfg.file_info_height - SEPARATOR_HEIGHT - 1)
end
-- Only shown in side-by-side preview layouts. When the layout has wrapped
-- to a stacked top/bottom preview (compact view), the preview is already
-- short — squeezing in a debug panel makes both unreadable.
local is_side_by_side = cfg.preview_position == 'left' or cfg.preview_position == 'right'
if cfg.debug_enabled and preview_enabled and layout.preview and is_side_by_side then
layout.file_info = {
width = layout.preview.width,
height = cfg.file_info_height,
col = layout.preview.col,
row = layout.preview.row,
}
-- Stack preview directly below file_info so they share a border row;
-- the shared row resolves to ├──...──┤ T-junctions instead of two
-- adjacent corners.
local consumed = cfg.file_info_height + 1 -- file_info content + its bottom border row
layout.preview.row = layout.preview.row + consumed
layout.preview.height = math.max(3, layout.preview.height - consumed)
end
return layout
@@ -658,7 +868,7 @@ function M.create_ui()
if not M.state.ns_id then
M.state.ns_id = vim.api.nvim_create_namespace('fff_picker_status')
combo_renderer.init(M.state.ns_id)
list_separator.init(M.state.ns_id)
end
local layout, debug_enabled_in_preview = compute_layout(config)
@@ -1547,6 +1757,8 @@ end
--- Render the grep empty state: tips + bordered section of recent files.
--- Called when grep mode has an empty query and no items.
local function render_grep_empty_state(ctx)
list_separator.hide()
local config = ctx.config
local win_width = ctx.win_width
local win_height = ctx.win_height
@@ -1650,31 +1862,50 @@ local function build_render_context()
-- Combo detection (only in file picker mode with real results, not grep or suggestions)
local combo_boost_score_multiplier = config.history and config.history.combo_boost_score_multiplier or 100
local has_combo, combo_header_line, combo_header_text_len, combo_item_index
if M.state.mode == 'grep' or M.state.suggestion_source then
has_combo = false
combo_header_line = nil
combo_header_text_len = nil
combo_item_index = nil
else
has_combo, combo_header_line, combo_header_text_len, combo_item_index = combo_renderer.detect_and_prepare(
local separator = nil
local combo_info = nil
if M.state.mode ~= 'grep' and not M.state.suggestion_source then
combo_info = combo_renderer.detect(
items,
file_picker,
win_width,
combo_boost_score_multiplier,
M.state.next_search_force_combo_boost or config.history.min_combo_count == 0
)
end
M.state.next_search_force_combo_boost = false
if has_combo and not M.state.combo_visible then
has_combo = false
combo_item_index = nil
if combo_info and M.state.combo_visible then
-- Text is finalised in finalize_render once we know whether the
-- separator landed visually above or below the match (depends on iter
-- direction + which end of the iter the anchor sits on).
separator = {
idx = combo_info.idx,
text = combo_info.text,
text_hl = config.hl.combo_header,
border_hl = config.hl.border,
}
-- Track the actual anchor so the navigation hide-rule measures distance
-- from the real separator, not an assumed item-1 anchor.
M.state.combo_initial_cursor = combo_info.idx
end
-- Determine iteration order
local display_start = 1
local display_end = #items
-- Reserve one row for the separator gap when present. Without this, items
-- fill the list to the brim, the gap overflows the window, and the
-- separator float (positioned by buffer line) gets clipped or drawn on
-- top of the input border. Drop the item at the far end of the items
-- list, opposite the anchor — that's the row farthest from the prompt.
if separator and (display_end - display_start + 1) >= win_height then
if separator.idx == display_start then
display_end = display_end - 1
else
display_start = display_start + 1
end
end
local iter_start, iter_end, iter_step
if prompt_position == 'bottom' then
iter_start, iter_end, iter_step = display_end, display_start, -1
@@ -1691,10 +1922,8 @@ local function build_render_context()
max_path_width = text_width, -- Actual text area width (excluding signcolumn)
debug_enabled = config and config.debug and config.debug.show_scores,
prompt_position = prompt_position,
has_combo = has_combo,
combo_header_line = combo_header_line,
combo_header_text_len = combo_header_text_len,
combo_item_index = combo_item_index,
separator = separator,
combo_info = combo_info,
display_start = display_start,
display_end = display_end,
iter_start = iter_start,
@@ -1710,28 +1939,29 @@ local function build_render_context()
}
end
local function finalize_render(item_to_lines, ctx)
local combo_text_len = nil
if ctx.combo_item_index and item_to_lines[ctx.combo_item_index] then
combo_text_len = item_to_lines[ctx.combo_item_index].combo_header_text_len
local function finalize_render(separator_line, _item_to_lines, ctx)
if ctx.separator and separator_line then
-- Arrow points toward the prompt: matches sit between the separator and
-- the prompt, so the arrow visually leads the eye from "rest of list"
-- through the separator toward the match + prompt.
local arrow = ctx.prompt_position == 'bottom' and '' or ''
local list_cfg = vim.api.nvim_win_get_config(M.state.list_win)
-- list_cfg.row is on the top border; content starts at list_cfg.row + 1.
-- separator_line is 1-based -> add directly.
local screen_row = list_cfg.row + separator_line
list_separator.update({
list_win = M.state.list_win,
row = screen_row,
text = arrow .. ' ' .. ctx.separator.text,
text_hl = ctx.separator.text_hl,
border_hl = ctx.separator.border_hl,
})
else
list_separator.hide()
end
local combo_was_hidden = combo_renderer.render_highlights_and_overlays(
ctx.combo_item_index,
combo_text_len or ctx.combo_header_text_len,
M.state.list_buf,
M.state.list_win,
M.state.ns_id,
ctx.config.hl.border,
item_to_lines,
ctx.prompt_position,
#ctx.items
)
-- it's important part of functionality when user scrolls to the middle of the page we hide
-- the combo overlay which leaves the gap of the internal neovim buffer, so scroll to show last item
if combo_was_hidden and ctx.prompt_position == 'bottom' then scroll_to_bottom() end
-- Scrollbar is only meaningful for file picker mode where total_matched is exact.
-- Grep uses early termination so total_matched is approximate — scrollbar would be misleading.
-- Also skip scrollbar when showing cross-mode suggestions (total_matched reflects the primary search, not suggestions).
@@ -1749,17 +1979,12 @@ function M.render_list()
return
end
-- Delegate line generation, padding, buffer write, cursor, and highlights
-- to the list_renderer module. It returns the item_to_lines mapping needed
-- by finalize_render for combo overlays and scrollbar.
local item_to_lines = list_renderer.render(ctx, M.state.list_buf, M.state.list_win, M.state.ns_id)
local separator_line, item_to_lines = list_renderer.render(ctx, M.state.list_buf, M.state.list_win, M.state.ns_id)
-- For bottom prompt, always ensure content is anchored at the bottom after rendering
-- This prevents results from appearing in the middle when there are few items
if ctx.prompt_position == 'bottom' then scroll_to_bottom() end
-- Finalize with combo overlays and scrollbar
finalize_render(item_to_lines, ctx)
finalize_render(separator_line, item_to_lines, ctx)
end
--- Build and set the preview window title for a given item and location.
@@ -1915,7 +2140,13 @@ function M.update_preview()
M.update_preview_title(item, effective_location)
if M.state.file_info_buf then preview.update_file_info_buffer(item, M.state.file_info_buf, M.state.cursor) end
if M.state.file_info_buf then
preview.update_file_info_buffer(item, M.state.file_info_buf, M.state.cursor)
if M.state.file_info_win and vim.api.nvim_win_is_valid(M.state.file_info_win) then
local rel = item.relative_path or item.path or ''
pcall(vim.api.nvim_win_set_config, M.state.file_info_win, { title = ' ' .. rel .. ' ', title_pos = 'left' })
end
end
preview.set_preview_window(M.state.preview_win)
preview.preview(resolve_item_path(item), M.state.preview_buf, effective_location, item.is_binary)
@@ -2007,13 +2238,11 @@ function M.update_status(progress)
local win_width = vim.api.nvim_win_get_width(M.state.input_win)
local available_width = win_width - 2
local virt_text
if fallback_label then
local total_len = #fallback_label
local col_position = available_width - total_len
virt_text = { { fallback_label, 'DiagnosticWarn' } }
vim.api.nvim_buf_set_extmark(M.state.input_buf, M.state.ns_id, 0, 0, {
virt_text = virt_text,
virt_text = { { fallback_label, 'DiagnosticWarn' } },
virt_text_win_col = col_position,
})
else
@@ -2105,6 +2334,27 @@ function M.wrap_to_last()
return true
end
--- After cursor moves, decide whether the combo separator should hide.
--- Hide rule: cursor has moved more than 50% of a page *past* the separator
--- anchor (in the direction away from it). Direction-agnostic w.r.t. prompt
--- position because we measure against the item index of the anchor, not its
--- visual row.
local function maybe_hide_combo_separator()
if not (M.state.combo_initial_cursor and M.state.combo_visible) then return end
local distance_past = M.state.cursor - M.state.combo_initial_cursor
-- Anchor at index 1 → "past" means cursor index grew. Anchor at #items
-- → "past" means cursor index shrank. Use absolute distance + a sign that
-- matches which side of the anchor the user crossed to.
if distance_past == 0 then return end
local half_page = math.floor(M.state.pagination.page_size * 0.5)
if math.abs(distance_past) <= half_page then return end
M.state.combo_visible = false
list_separator.hide()
M.render_list()
if get_prompt_position() == 'bottom' then scroll_to_bottom() end
end
function M.move_up()
if not M.state.active then return end
if #M.state.filtered_items == 0 then return end
@@ -2167,17 +2417,7 @@ function M.move_up()
end
M.update_status()
if M.state.combo_initial_cursor and M.state.combo_visible then
local cursor_distance = math.abs(M.state.cursor - M.state.combo_initial_cursor)
local half_page = math.floor(M.state.pagination.page_size / 2)
if cursor_distance > half_page then
M.state.combo_visible = false
combo_renderer.cleanup()
M.render_list() -- Re-render once without combo
-- Scroll to bottom for bottom prompt to eliminate gap
if get_prompt_position() == 'bottom' then scroll_to_bottom() end
end
end
maybe_hide_combo_separator()
end
function M.move_down()
@@ -2242,17 +2482,7 @@ function M.move_down()
end
M.update_status()
if M.state.combo_initial_cursor and M.state.combo_visible then
local cursor_distance = math.abs(M.state.cursor - M.state.combo_initial_cursor)
local half_page = math.floor(M.state.pagination.page_size / 2)
if cursor_distance > half_page then
M.state.combo_visible = false
combo_renderer.cleanup()
M.render_list() -- Re-render once without combo
-- Scroll to bottom for bottom prompt to eliminate gap
if get_prompt_position() == 'bottom' then scroll_to_bottom() end
end
end
maybe_hide_combo_separator()
end
--- Scroll preview up by half window height
@@ -2702,7 +2932,7 @@ function M.close()
restore_paste(M.state.restore_paste)
combo_renderer.cleanup()
list_separator.cleanup()
scrollbar.cleanup()
-- Clean up treesitter scratch buffers used for grep syntax highlighting
+4
View File
@@ -49,6 +49,10 @@ function M.render(layout, config, list_win, pagination, prompt_position)
border = 'none',
style = 'minimal',
focusable = false,
-- Float above the list/preview borders so the thumb is visible. Must
-- be higher than the list (52) and preview (51) zindex; 200 leaves
-- room for transient overlays (combo separator at 250 still wins).
zindex = 200,
})
local scrollbar_hl = string.format('Normal:%s', config.hl.border)
+5
View File
@@ -4,9 +4,14 @@
-- Set up runtimepath to include the plugin and plenary
local plugin_dir = vim.fn.fnamemodify(vim.fn.resolve(vim.fn.expand('<sfile>:p')), ':h:h')
local plenary_dir = os.getenv('PLENARY_DIR') or (plugin_dir .. '/../plenary.nvim')
local mini_dir = os.getenv('MINI_DIR') or (plugin_dir .. '/../mini.nvim')
vim.opt.runtimepath:prepend(plugin_dir)
vim.opt.runtimepath:prepend(plenary_dir)
vim.opt.runtimepath:prepend(mini_dir)
-- Make `tests/` itself a Lua require root so test helper modules (e.g. tests.snapshot.fixture) resolve.
package.path = string.format('%s/?.lua;%s/?/init.lua;%s', plugin_dir, plugin_dir, package.path)
-- Disable swap files and other noise for testing
vim.o.swapfile = false
+204
View File
@@ -0,0 +1,204 @@
--- End-to-end snapshot tests for fff.nvim's picker UI.
local MiniTest = require('mini.test')
local fixture_lib = require('tests.snapshot.fixture')
local PLUGIN_DIR = vim.fn.fnamemodify(debug.getinfo(1, 'S').source:sub(2), ':p:h:h')
local FORCE = vim.env.UPDATE_SNAPSHOTS == '1'
local child, fixture
local function setup(geometry, opts)
opts = opts or {}
fixture = fixture_lib.create()
child = MiniTest.new_child_neovim()
child.start({
'--clean',
'-n',
'-i',
'NONE',
'--cmd',
string.format('let &lines = %d', geometry.rows),
'--cmd',
string.format('let &columns = %d', geometry.cols),
}, {
connection_timeout = 15000,
})
child.o.lines = geometry.rows
child.o.columns = geometry.cols
child.lua(
string.format(
[[
local plugin = %q
vim.opt.runtimepath:prepend(plugin)
package.path = plugin .. '/lua/?.lua;' .. plugin .. '/lua/?/init.lua;' .. package.path
vim.cmd('cd ' .. vim.fn.fnameescape(%q))
local winborder = %q
if winborder ~= '' then vim.o.winborder = winborder end
vim.g.fff = {
prompt = '> ',
frecency = { enabled = true, db_path = %q },
history = { enabled = true, db_path = %q },
logging = { enabled = false },
debug = { enabled = %s, show_scores = %s },
}
require('fff.core').ensure_initialized()
require('fff.rust').wait_for_initial_scan(8000)
]],
PLUGIN_DIR,
fixture.root,
geometry.winborder or '',
fixture.frecency_db,
fixture.history_db,
tostring(opts.debug == true),
tostring(opts.debug == true)
)
)
end
local function teardown()
if child and child.is_running() then pcall(child.stop) end
if fixture then fixture_lib.cleanup(fixture) end
child, fixture = nil, nil
end
--- @param opts table|nil { ignore_text?: number[] }
local function assert_snapshot_match(opts)
opts = opts or {}
MiniTest.expect.reference_screenshot(child.get_screenshot(), nil, {
force = FORCE,
ignore_text = opts.ignore_text or false,
})
end
local function open_picker(prompt_position, query)
child.lua(string.format('require("fff.picker_ui").open({ layout = { prompt_position = %q } })', prompt_position))
vim.loop.sleep(400)
if query and query ~= '' then
child.type_keys(query)
vim.loop.sleep(400)
end
end
local LAYOUTS = {
{ name = 'wide', cols = 180, rows = 40, winborder = 'double' },
{ name = 'default', cols = 140, rows = 32 }, -- standard on most screens
{ name = 'narrow', cols = 70, rows = 24, winborder = 'rounded' },
}
local T = MiniTest.new_set()
for _, geometry in ipairs(LAYOUTS) do
local set = MiniTest.new_set({
hooks = {
pre_case = function() setup(geometry) end,
post_case = teardown,
},
})
set['empty_bottom'] = function()
open_picker('bottom')
assert_snapshot_match()
end
set['empty_top'] = function()
open_picker('top')
assert_snapshot_match()
end
set['query_main_bottom'] = function()
open_picker('bottom', 'main')
assert_snapshot_match()
end
set['no_results_bottom'] = function()
open_picker('bottom', 'zzzzzzzzz')
assert_snapshot_match()
end
set['cursor_second_item'] = function()
open_picker('bottom')
child.type_keys('<Down>')
vim.loop.sleep(200)
assert_snapshot_match()
end
T[geometry.name] = set
end
-- File info panel only renders in non-flex layouts where there's room for it,
-- so we only exercise it on the default geometry.
local default_geom = LAYOUTS[2]
local debug_set = MiniTest.new_set({
hooks = {
pre_case = function() setup(default_geom, { debug = true }) end,
post_case = teardown,
},
})
debug_set['file_info_panel'] = function()
open_picker('bottom', 'main')
-- Modified / Last Access timestamps drift between runs; ignore those text
-- rows but still verify everything else (panel layout, scores, attrs).
assert_snapshot_match({ ignore_text = { 13, 14 } })
end
T['debug'] = debug_set
T['combo'] = MiniTest.new_set({
hooks = {
pre_case = function() setup({ cols = 140, rows = 32 }) end,
post_case = teardown,
},
})
local function train_combo()
-- Train: "main" → src/main.rs four times so open_count crosses the default
-- min_combo_count (3). track_query_completion is async; pause between calls
-- + final settle for the lmdb writer.
for _ = 1, 4 do
child.lua(
string.format('require("fff.rust").track_query_completion(%q, %q)', 'main', fixture.root .. '/src/main.rs')
)
vim.loop.sleep(120)
end
vim.loop.sleep(400)
end
T['combo']['boost_bottom'] = function()
train_combo()
open_picker('bottom', 'main')
-- Combo overlay float renders asynchronously after render_list.
vim.loop.sleep(400)
assert_snapshot_match()
end
T['combo']['boost_top'] = function()
train_combo()
open_picker('top', 'main')
vim.loop.sleep(400)
assert_snapshot_match()
end
T['scrollbar'] = MiniTest.new_set({
hooks = {
pre_case = function() setup({ cols = 140, rows = 32 }) end,
post_case = teardown,
},
})
T['scrollbar']['next_page'] = function()
open_picker('bottom')
-- Bottom prompt iters in reverse — `<Up>` advances cursor toward higher
-- indices (visually up the list). Walking past the last in-page item
-- triggers load_next_page; the scrollbar thumb appears at the new offset.
for _ = 1, 30 do
child.type_keys('<Up>')
vim.loop.sleep(20)
end
vim.loop.sleep(400)
assert_snapshot_match()
end
return T
@@ -0,0 +1,67 @@
--|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|
01|
02|~
03|~
04|~ ┌ FFFiles ────────────────────────────────────────────┬ src/main.rs ───────────────────────────────────────────┐
05|~ │ │fn main() {} │
06|~ │ table.tsx src/components │ │
07|~ │ list.tsx src/components │ │
08|~ │ dialog.tsx src/components │ │
09|~ │ button.tsx src/components │ │
10|~ │ api.rs src │ │
11|~ │ license.md docs │ │
12|~ │ regression.rs tests │ │
13|~ │ menu.tsx src/components │ │
14|~ │ changelog.md docs │ │
15|~ │ contributing.md docs │ │
16|~ │ integration.rs tests │ │
17|~ │ input.tsx src/components │ │
18|~ │ intro.md docs │ │
19|~ │ main_test.rs tests │ │
20|~ │ main_utils.rs src │ │
21|~ │ main_runner.rs src │ │
22|~ │ main_loop.rs src │ │
23|~ │ main_helper.rs src │ │
24|~ ├── ↓ Last Match (×4 combo) ──────────────────────────┤ │
25|~ │ main.rs src │ │
26|~ ├─────────────────────────────────────────────────────┤ │
27|~ │> main 19/32 │ │
28|~ └─────────────────────────────────────────────────────┴────────────────────────────────────────────────────────┘
29|~
30|~
31|[No Name] 0,1 All
32|-- INSERT -- 1,7 All
--|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|
01|00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
02|11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
03|11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
04|11111111111111123333333332222222222222222222222222222222222222222222223333333333333222222222222222222222222222222222222222222221111111111111
05|11111111111111124455555555555555555555555555555555555555555555555555525555555555555555555555555555555555555555555555555555555521111111111111
06|11111111111111124455555555556666666666666655555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
07|11111111111111124455555555566666666666666555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
08|11111111111111124455555555555666666666666665555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
09|11111111111111124455555555555666666666666665555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
10|11111111111111124455555556665555555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
11|11111111111111124455555555555666655555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
12|11111111111111124455555555555555666665555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
13|11111111111111124455555555566666666666666555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
14|11111111111111124455555555555556666555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
15|11111111111111124455555555555555556666555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
16|11111111111111124455555555555555566666555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
17|11111111111111124455555555556666666666666655555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
18|11111111111111124455555555566665555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
19|11111111111111124477775555555556666655555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
20|11111111111111124477775555555555666555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
21|11111111111111124477775555555555566655555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
22|11111111111111124477775555555556665555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
23|11111111111111124477775555555555566655555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
24|11111111111111188888888888888888888888888888888888888888888888888888884444444444444444444444444444444444444444444444444444444421111111111111
25|1111111111111112997777::::;;;::::::::::::::::::::::::::::::::::::::::24444444444444444444444444444444444444444444444444444444421111111111111
26|11111111111111122222222222222222222222222222222222222222222222222222224444444444444444444444444444444444444444444444444444444421111111111111
27|11111111111111125555555555555555555555555555555555555555555555444445524444444444444444444444444444444444444444444444444444444421111111111111
28|11111111111111122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221111111111111
29|11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
30|11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
31|<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
32|============>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
@@ -0,0 +1,67 @@
--|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|
01|
02|~
03|~
04|~ ┌ FFFiles ────────────────────────────────────────────┬ src/main.rs ───────────────────────────────────────────┐
05|~ │> main 19/32 │fn main() {} │
06|~ ├─────────────────────────────────────────────────────┤ │
07|~ │ main.rs src │ │
08|~ ├── ↑ Last Match (×4 combo) ──────────────────────────┤ │
09|~ │ main_helper.rs src │ │
10|~ │ main_loop.rs src │ │
11|~ │ main_runner.rs src │ │
12|~ │ main_utils.rs src │ │
13|~ │ main_test.rs tests │ │
14|~ │ intro.md docs │ │
15|~ │ input.tsx src/components │ │
16|~ │ integration.rs tests │ │
17|~ │ contributing.md docs │ │
18|~ │ changelog.md docs │ │
19|~ │ menu.tsx src/components │ │
20|~ │ regression.rs tests │ │
21|~ │ license.md docs │ │
22|~ │ api.rs src │ │
23|~ │ button.tsx src/components │ │
24|~ │ dialog.tsx src/components │ │
25|~ │ list.tsx src/components │ │
26|~ │ table.tsx src/components │ │
27|~ │ │ │
28|~ └─────────────────────────────────────────────────────┴────────────────────────────────────────────────────────┘
29|~
30|~
31|[No Name] 0,1 All
32|-- INSERT -- 1,7 All
--|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|
01|00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
02|11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
03|11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
04|11111111111111123333333332222222222222222222222222222222222222222222223333333333333222222222222222222222222222222222222222222221111111111111
05|11111111111111124444444444444444444444444444444444444444444444555554424444444444444444444444444444444444444444444444444444444421111111111111
06|11111111111111122222222222222222222222222222222222222222222222222222225555555555555555555555555555555555555555555555555555555521111111111111
07|11111111111111126677778888999888888888888888888888888888888888888888825555555555555555555555555555555555555555555555555555555521111111111111
08|111111111111111:::::::::::::::::::::::::::::::::::::::::::::::::::::::5555555555555555555555555555555555555555555555555555555521111111111111
09|111111111111111255777744444444444;;;44444444444444444444444444444444425555555555555555555555555555555555555555555555555555555521111111111111
10|1111111111111112557777444444444;;;4444444444444444444444444444444444425555555555555555555555555555555555555555555555555555555521111111111111
11|111111111111111255777744444444444;;;44444444444444444444444444444444425555555555555555555555555555555555555555555555555555555521111111111111
12|11111111111111125577774444444444;;;444444444444444444444444444444444425555555555555555555555555555555555555555555555555555555521111111111111
13|1111111111111112557777444444444;;;;;44444444444444444444444444444444425555555555555555555555555555555555555555555555555555555521111111111111
14|111111111111111255444444444;;;;4444444444444444444444444444444444444425555555555555555555555555555555555555555555555555555555521111111111111
15|1111111111111112554444444444;;;;;;;;;;;;;;44444444444444444444444444425555555555555555555555555555555555555555555555555555555521111111111111
16|111111111111111255444444444444444;;;;;444444444444444444444444444444425555555555555555555555555555555555555555555555555555555521111111111111
17|1111111111111112554444444444444444;;;;444444444444444444444444444444425555555555555555555555555555555555555555555555555555555521111111111111
18|1111111111111112554444444444444;;;;444444444444444444444444444444444425555555555555555555555555555555555555555555555555555555521111111111111
19|111111111111111255444444444;;;;;;;;;;;;;;444444444444444444444444444425555555555555555555555555555555555555555555555555555555521111111111111
20|11111111111111125544444444444444;;;;;4444444444444444444444444444444425555555555555555555555555555555555555555555555555555555521111111111111
21|11111111111111125544444444444;;;;44444444444444444444444444444444444425555555555555555555555555555555555555555555555555555555521111111111111
22|1111111111111112554444444;;;4444444444444444444444444444444444444444425555555555555555555555555555555555555555555555555555555521111111111111
23|11111111111111125544444444444;;;;;;;;;;;;;;4444444444444444444444444425555555555555555555555555555555555555555555555555555555521111111111111
24|11111111111111125544444444444;;;;;;;;;;;;;;4444444444444444444444444425555555555555555555555555555555555555555555555555555555521111111111111
25|111111111111111255444444444;;;;;;;;;;;;;;444444444444444444444444444425555555555555555555555555555555555555555555555555555555521111111111111
26|1111111111111112554444444444;;;;;;;;;;;;;;44444444444444444444444444425555555555555555555555555555555555555555555555555555555521111111111111
27|11111111111111125555555555555555555555555555555555555555555555555555525555555555555555555555555555555555555555555555555555555521111111111111
28|11111111111111122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221111111111111
29|11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
30|11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
31|<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
32|============>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
@@ -0,0 +1,67 @@
--|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|
01|
02|~
03|~
04|~ ┌ FFFiles ────────────────────────────────────────────┬ src/main.rs ───────────────────────────────────────────┐
05|~ │ │Size: 13 B │ Total Score: 60 │
06|~ │ │Type: rust │ Match Type: fuzzy_filename │
07|~ │ table.tsx src/components │Git: clean │ Frecency Mod: 0, Acc: 0 │
08|~ │ list.tsx src/components │Score Breakdown: base=52, name_bonus=8, special_bonus=0 │
09|~ │ dialog.tsx src/components │Score Modifiers: frec_boost=0, dist_penalty=0, current_p│
10|~ │ button.tsx src/components │ │
11|~ │ api.rs src │TIMINGS │
12|~ │ license.md docs │────────────────────────────────────────────────── │
13|~ │ regression.rs tests │Modified: 2026-05-19 17:05:37 │
14|~ │ menu.tsx src/components │Last Access: 2026-05-19 17:05:37 │
15|~ │ changelog.md docs ├────────────────────────────────────────────────────────┤
16|~ │ contributing.md docs │fn main() {} │
17|~ │ integration.rs tests │ │
18|~ │ input.tsx src/components │ │
19|~ │ intro.md docs │ │
20|~ │ main_test.rs tests │ │
21|~ │ main_utils.rs src │ │
22|~ │ main_runner.rs src │ │
23|~ │ main_loop.rs src │ │
24|~ │ main_helper.rs src │ │
25|~ │ main.rs src │ │
26|~ ├─────────────────────────────────────────────────────┤ │
27|~ │> main 19/32 │ │
28|~ └─────────────────────────────────────────────────────┴────────────────────────────────────────────────────────┘
29|~
30|~
31|[No Name] 0,1 All
32|-- INSERT -- 1,7 All
--|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|
01|00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
02|11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
03|11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
04|11111111111111123333333332222222222222222222222222222222222222222222223333333333333222222222222222222222222222222222222222222221111111111111
05|11111111111111124455555555555555555555555555555555555555555555555555525555555555555555555555555555555555555555555555555555555521111111111111
06|11111111111111124455555555555555555555555555555555555555555555555555525555555555555555555555555555555555555555555555555555555521111111111111
07|11111111111111124455555555556666666666666655555555555555555555555555525555555555555555555555555555555555555555555555555555555521111111111111
08|11111111111111124455555555566666666666666555555555555555555555555555525555555555555555555555555555555555555555555555555555555521111111111111
09|11111111111111124455555555555666666666666665555555555555555555555555525555555555555555555555555555555555555555555555555555555521111111111111
10|11111111111111124455555555555666666666666665555555555555555555555555525555555555555555555555555555555555555555555555555555555521111111111111
11|11111111111111124455555556665555555555555555555555555555555555555555525555555555555555555555555555555555555555555555555555555521111111111111
12|11111111111111124455555555555666655555555555555555555555555555555555525555555555555555555555555555555555555555555555555555555521111111111111
13|11111111111111124455555555555555666665555555555555555555555555555555525555555555555555555555555555555555555555555555555555555521111111111111
14|11111111111111124455555555566666666666666555555555555555555555555555525555555555555555555555555555555555555555555555555555555521111111111111
15|11111111111111124455555555555556666555555555555555555555555555555555522222222222222222222222222222222222222222222222222222222221111111111111
16|11111111111111124455555555555555556666555555555555555555555555555555525555555555555555555555555555555555555555555555555555555521111111111111
17|11111111111111124455555555555555566666555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
18|11111111111111124455555555556666666666666655555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
19|11111111111111124455555555566665555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
20|11111111111111124477775555555556666655555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
21|11111111111111124477775555555555666555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
22|11111111111111124477775555555555566655555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
23|11111111111111124477775555555556665555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
24|11111111111111124477775555555555566655555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
25|11111111111111128877779999:::999999999999999999999999999999999999999924444444444444444444444444444444444444444444444444444444421111111111111
26|11111111111111122222222222222222222222222222222222222222222222222222224444444444444444444444444444444444444444444444444444444421111111111111
27|11111111111111125555555555555555555555555555555555555555555555444445524444444444444444444444444444444444444444444444444444444421111111111111
28|11111111111111122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221111111111111
29|11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
30|11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
31|;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
32|<<<<<<<<<<<<================================================================================================================================
@@ -0,0 +1,67 @@
--|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|
01|
02|~
03|~
04|~ ┌ FFFiles ────────────────────────────────────────────┬ README.md ─────────────────────────────────────────────┐
05|~ │ store.rs src │# Fixture │
06|~ │ state.rs src │ │
07|~ │ runner.rs src │ │
08|~ │ parser.rs src │ │
09|~ │ main_utils.rs src │ │
10|~ │ main_runner.rs src │ │
11|~ │ main_loop.rs src │ │
12|~ │ main_helper.rs src │ │
13|~ │ main.rs src │ │
14|~ │ lib.rs src │ │
15|~ │ error.rs src │ │
16|~ │ config.rs src │ │
17|~ │ cli.rs src │ │
18|~ │ api.rs src │ │
19|~ │ reference.md docs │ │
20|~ │ license.md docs │ │
21|~ │ intro.md docs │ │
22|~ │ guide.md docs │ │
23|~ │ contributing.md docs │ │
24|~ │ changelog.md docs │ │
25|~ │ README.md │ │
26|~ ├─────────────────────────────────────────────────────┤ │
27|~ │> 32 │ │
28|~ └─────────────────────────────────────────────────────┴────────────────────────────────────────────────────────┘
29|~
30|~
31|[No Name] 0,1 All
32|-- INSERT -- 1,3 All
--|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|
01|00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
02|11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
03|11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
04|11111111111111123333333332222222222222222222222222222222222222222222223333333333322222222222222222222222222222222222222222222221111111111111
05|11111111111111124455555555566655555555555555555555555555555555555555527777777775555555555555555555555555555555555555555555555521111111111111
06|11111111111111124455555555566655555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
07|11111111111111124455555555556665555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
08|11111111111111124455555555556665555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
09|11111111111111124455555555555555666555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
10|11111111111111124455555555555555566655555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
11|11111111111111124455555555555556665555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
12|11111111111111124455555555555555566655555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
13|11111111111111124455555555666555555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
14|11111111111111124455555556665555555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
15|11111111111111124455555555566655555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
16|11111111111111124455555555556665555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
17|11111111111111124455555556665555555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
18|11111111111111124455555556665555555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
19|11111111111111124455555555555556666555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
20|11111111111111124455555555555666655555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
21|11111111111111124455555555566665555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
22|11111111111111124455555555566665555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
23|11111111111111124455555555555555556666555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
24|11111111111111124455555555555556666555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
25|11111111111111128899999999999999999999999999999999999999999999999999924444444444444444444444444444444444444444444444444444444421111111111111
26|11111111111111122222222222222222222222222222222222222222222222222222224444444444444444444444444444444444444444444444444444444421111111111111
27|11111111111111125555555555555555555555555555555555555555555555555445524444444444444444444444444444444444444444444444444444444421111111111111
28|11111111111111122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221111111111111
29|11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
30|11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
31|::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
32|;;;;;;;;;;;;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@@ -0,0 +1,67 @@
--|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|
01|
02|~
03|~
04|~ ┌ FFFiles ────────────────────────────────────────────┬ README.md ─────────────────────────────────────────────┐
05|~ │ store.rs src │# Fixture │
06|~ │ state.rs src │ │
07|~ │ runner.rs src │ │
08|~ │ parser.rs src │ │
09|~ │ main_utils.rs src │ │
10|~ │ main_runner.rs src │ │
11|~ │ main_loop.rs src │ │
12|~ │ main_helper.rs src │ │
13|~ │ main.rs src │ │
14|~ │ lib.rs src │ │
15|~ │ error.rs src │ │
16|~ │ config.rs src │ │
17|~ │ cli.rs src │ │
18|~ │ api.rs src │ │
19|~ │ reference.md docs │ │
20|~ │ license.md docs │ │
21|~ │ intro.md docs │ │
22|~ │ guide.md docs │ │
23|~ │ contributing.md docs │ │
24|~ │ changelog.md docs │ │
25|~ │ README.md │ │
26|~ ├─────────────────────────────────────────────────────┤ │
27|~ │> 32 │ │
28|~ └─────────────────────────────────────────────────────┴────────────────────────────────────────────────────────┘
29|~
30|~
31|[No Name] 0,1 All
32|-- INSERT -- 1,3 All
--|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|
01|00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
02|11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
03|11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
04|11111111111111123333333332222222222222222222222222222222222222222222223333333333322222222222222222222222222222222222222222222221111111111111
05|11111111111111124455555555566655555555555555555555555555555555555555527777777775555555555555555555555555555555555555555555555521111111111111
06|11111111111111124455555555566655555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
07|11111111111111124455555555556665555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
08|11111111111111124455555555556665555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
09|11111111111111124455555555555555666555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
10|11111111111111124455555555555555566655555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
11|11111111111111124455555555555556665555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
12|11111111111111124455555555555555566655555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
13|11111111111111124455555555666555555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
14|11111111111111124455555556665555555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
15|11111111111111124455555555566655555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
16|11111111111111124455555555556665555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
17|11111111111111124455555556665555555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
18|11111111111111124455555556665555555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
19|11111111111111124455555555555556666555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
20|11111111111111124455555555555666655555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
21|11111111111111124455555555566665555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
22|11111111111111124455555555566665555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
23|11111111111111124455555555555555556666555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
24|11111111111111124455555555555556666555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
25|11111111111111128899999999999999999999999999999999999999999999999999924444444444444444444444444444444444444444444444444444444421111111111111
26|11111111111111122222222222222222222222222222222222222222222222222222224444444444444444444444444444444444444444444444444444444421111111111111
27|11111111111111125555555555555555555555555555555555555555555555555445524444444444444444444444444444444444444444444444444444444421111111111111
28|11111111111111122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221111111111111
29|11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
30|11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
31|::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
32|;;;;;;;;;;;;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@@ -0,0 +1,67 @@
--|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|
01|
02|~
03|~
04|~ ┌ FFFiles ────────────────────────────────────────────┬ README.md ─────────────────────────────────────────────┐
05|~ │> 32 │# Fixture │
06|~ ├─────────────────────────────────────────────────────┤ │
07|~ │ README.md │ │
08|~ │ changelog.md docs │ │
09|~ │ contributing.md docs │ │
10|~ │ guide.md docs │ │
11|~ │ intro.md docs │ │
12|~ │ license.md docs │ │
13|~ │ reference.md docs │ │
14|~ │ api.rs src │ │
15|~ │ cli.rs src │ │
16|~ │ config.rs src │ │
17|~ │ error.rs src │ │
18|~ │ lib.rs src │ │
19|~ │ main.rs src │ │
20|~ │ main_helper.rs src │ │
21|~ │ main_loop.rs src │ │
22|~ │ main_runner.rs src │ │
23|~ │ main_utils.rs src │ │
24|~ │ parser.rs src │ │
25|~ │ runner.rs src │ │
26|~ │ state.rs src │ │
27|~ │ store.rs src │ │
28|~ └─────────────────────────────────────────────────────┴────────────────────────────────────────────────────────┘
29|~
30|~
31|[No Name] 0,1 All
32|-- INSERT -- 1,3 All
--|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|
01|00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
02|11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
03|11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
04|11111111111111123333333332222222222222222222222222222222222222222222223333333333322222222222222222222222222222222222222222222221111111111111
05|11111111111111124444444444444444444444444444444444444444444444444554426666666664444444444444444444444444444444444444444444444421111111111111
06|11111111111111122222222222222222222222222222222222222222222222222222225555555555555555555555555555555555555555555555555555555521111111111111
07|11111111111111127788888888888888888888888888888888888888888888888888825555555555555555555555555555555555555555555555555555555521111111111111
08|11111111111111125544444444444449999444444444444444444444444444444444425555555555555555555555555555555555555555555555555555555521111111111111
09|11111111111111125544444444444444449999444444444444444444444444444444425555555555555555555555555555555555555555555555555555555521111111111111
10|11111111111111125544444444499994444444444444444444444444444444444444425555555555555555555555555555555555555555555555555555555521111111111111
11|11111111111111125544444444499994444444444444444444444444444444444444425555555555555555555555555555555555555555555555555555555521111111111111
12|11111111111111125544444444444999944444444444444444444444444444444444425555555555555555555555555555555555555555555555555555555521111111111111
13|11111111111111125544444444444449999444444444444444444444444444444444425555555555555555555555555555555555555555555555555555555521111111111111
14|11111111111111125544444449994444444444444444444444444444444444444444425555555555555555555555555555555555555555555555555555555521111111111111
15|11111111111111125544444449994444444444444444444444444444444444444444425555555555555555555555555555555555555555555555555555555521111111111111
16|11111111111111125544444444449994444444444444444444444444444444444444425555555555555555555555555555555555555555555555555555555521111111111111
17|11111111111111125544444444499944444444444444444444444444444444444444425555555555555555555555555555555555555555555555555555555521111111111111
18|11111111111111125544444449994444444444444444444444444444444444444444425555555555555555555555555555555555555555555555555555555521111111111111
19|11111111111111125544444444999444444444444444444444444444444444444444425555555555555555555555555555555555555555555555555555555521111111111111
20|11111111111111125544444444444444499944444444444444444444444444444444425555555555555555555555555555555555555555555555555555555521111111111111
21|11111111111111125544444444444449994444444444444444444444444444444444425555555555555555555555555555555555555555555555555555555521111111111111
22|11111111111111125544444444444444499944444444444444444444444444444444425555555555555555555555555555555555555555555555555555555521111111111111
23|11111111111111125544444444444444999444444444444444444444444444444444425555555555555555555555555555555555555555555555555555555521111111111111
24|11111111111111125544444444449994444444444444444444444444444444444444425555555555555555555555555555555555555555555555555555555521111111111111
25|11111111111111125544444444449994444444444444444444444444444444444444425555555555555555555555555555555555555555555555555555555521111111111111
26|11111111111111125544444444499944444444444444444444444444444444444444425555555555555555555555555555555555555555555555555555555521111111111111
27|11111111111111125544444444499944444444444444444444444444444444444444425555555555555555555555555555555555555555555555555555555521111111111111
28|11111111111111122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221111111111111
29|11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
30|11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
31|::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
32|;;;;;;;;;;;;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@@ -0,0 +1,67 @@
--|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|
01|
02|~
03|~
04|~ ┌ FFFiles ────────────────────────────────────────────┬ Preview ───────────────────────────────────────────────┐
05|~ │ │No preview available │
06|~ │ │ │
07|~ │ │ │
08|~ │ │ │
09|~ │ │ │
10|~ │ │ │
11|~ │ │ │
12|~ │ │ │
13|~ │ │ │
14|~ │ │ │
15|~ │ │ │
16|~ │ │ │
17|~ │ │ │
18|~ │ │ │
19|~ │ │ │
20|~ │ │ │
21|~ │ │ │
22|~ │ │ │
23|~ │ │ │
24|~ │ │ │
25|~ │ │ │
26|~ ├─────────────────────────────────────────────────────┤ │
27|~ │> zzzzzzzzz 0/32 │ │
28|~ └─────────────────────────────────────────────────────┴────────────────────────────────────────────────────────┘
29|~
30|~
31|[No Name] 0,1 All
32|-- INSERT -- 1,12 All
--|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|
01|00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
02|11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
03|11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
04|11111111111111123333333332222222222222222222222222222222222222222222223333333332222222222222222222222222222222222222222222222221111111111111
05|11111111111111124455555555555555555555555555555555555555555555555555525555555555555555555555555555555555555555555555555555555521111111111111
06|11111111111111124455555555555555555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
07|11111111111111124455555555555555555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
08|11111111111111124455555555555555555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
09|11111111111111124455555555555555555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
10|11111111111111124455555555555555555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
11|11111111111111124455555555555555555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
12|11111111111111124455555555555555555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
13|11111111111111124455555555555555555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
14|11111111111111124455555555555555555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
15|11111111111111124455555555555555555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
16|11111111111111124455555555555555555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
17|11111111111111124455555555555555555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
18|11111111111111124455555555555555555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
19|11111111111111124455555555555555555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
20|11111111111111124455555555555555555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
21|11111111111111124455555555555555555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
22|11111111111111124455555555555555555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
23|11111111111111124455555555555555555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
24|11111111111111124455555555555555555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
25|11111111111111124455555555555555555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
26|11111111111111122222222222222222222222222222222222222222222222222222224444444444444444444444444444444444444444444444444444444421111111111111
27|11111111111111125555555555555555555555555555555555555555555555544445524444444444444444444444444444444444444444444444444444444421111111111111
28|11111111111111122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221111111111111
29|11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
30|11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
31|66666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666
32|77777777777788888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888
@@ -0,0 +1,67 @@
--|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|
01|
02|~
03|~
04|~ ┌ FFFiles ────────────────────────────────────────────┬ src/main.rs ───────────────────────────────────────────┐
05|~ │ │fn main() {} │
06|~ │ │ │
07|~ │ table.tsx src/components │ │
08|~ │ list.tsx src/components │ │
09|~ │ dialog.tsx src/components │ │
10|~ │ button.tsx src/components │ │
11|~ │ api.rs src │ │
12|~ │ license.md docs │ │
13|~ │ regression.rs tests │ │
14|~ │ menu.tsx src/components │ │
15|~ │ changelog.md docs │ │
16|~ │ contributing.md docs │ │
17|~ │ integration.rs tests │ │
18|~ │ input.tsx src/components │ │
19|~ │ intro.md docs │ │
20|~ │ main_test.rs tests │ │
21|~ │ main_utils.rs src │ │
22|~ │ main_runner.rs src │ │
23|~ │ main_loop.rs src │ │
24|~ │ main_helper.rs src │ │
25|~ │ main.rs src │ │
26|~ ├─────────────────────────────────────────────────────┤ │
27|~ │> main 19/32 │ │
28|~ └─────────────────────────────────────────────────────┴────────────────────────────────────────────────────────┘
29|~
30|~
31|[No Name] 0,1 All
32|-- INSERT -- 1,7 All
--|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|
01|00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
02|11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
03|11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
04|11111111111111123333333332222222222222222222222222222222222222222222223333333333333222222222222222222222222222222222222222222221111111111111
05|11111111111111124455555555555555555555555555555555555555555555555555525555555555555555555555555555555555555555555555555555555521111111111111
06|11111111111111124455555555555555555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
07|11111111111111124455555555556666666666666655555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
08|11111111111111124455555555566666666666666555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
09|11111111111111124455555555555666666666666665555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
10|11111111111111124455555555555666666666666665555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
11|11111111111111124455555556665555555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
12|11111111111111124455555555555666655555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
13|11111111111111124455555555555555666665555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
14|11111111111111124455555555566666666666666555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
15|11111111111111124455555555555556666555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
16|11111111111111124455555555555555556666555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
17|11111111111111124455555555555555566666555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
18|11111111111111124455555555556666666666666655555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
19|11111111111111124455555555566665555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
20|11111111111111124477775555555556666655555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
21|11111111111111124477775555555555666555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
22|11111111111111124477775555555555566655555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
23|11111111111111124477775555555556665555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
24|11111111111111124477775555555555566655555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
25|11111111111111128877779999:::999999999999999999999999999999999999999924444444444444444444444444444444444444444444444444444444421111111111111
26|11111111111111122222222222222222222222222222222222222222222222222222224444444444444444444444444444444444444444444444444444444421111111111111
27|11111111111111125555555555555555555555555555555555555555555555444445524444444444444444444444444444444444444444444444444444444421111111111111
28|11111111111111122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221111111111111
29|11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
30|11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
31|;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
32|<<<<<<<<<<<<================================================================================================================================
@@ -0,0 +1,51 @@
--|---------|---------|---------|---------|---------|---------|---------|
01|
02|~
03|~ ╭ README.md ───────────────────────────────────────────╮
04|~ │# Fixture │
05|~ │ │
06|~ │ │
07|~ │ │
08|~ │ │
09|~ │ │
10|~ │ │
11|~ │ │
12|~ │ │
13|~ ├ FFFiles ─────────────────────────────────────────────┤
14|~ │ intro.md docs │
15|~ │ guide.md docs │
16|~ │ contributing.md docs │
17|~ │ changelog.md docs │
18|~ │ README.md │
19|~ ├──────────────────────────────────────────────────────┤
20|~ │> 32 │
21|~ ╰──────────────────────────────────────────────────────╯
22|~
23|[No Name] 0,1 All
24|-- INSERT -- 1,3 All
--|---------|---------|---------|---------|---------|---------|---------|
01|0000000000000000000000000000000000000000000000000000000000000000000000
02|1111111111111111111111111111111111111111111111111111111111111111111111
03|1111111123333333333322222222222222222222222222222222222222222222111111
04|1111111124444444445555555555555555555555555555555555555555555552111111
05|1111111126666666666666666666666666666666666666666666666666666662111111
06|1111111126666666666666666666666666666666666666666666666666666662111111
07|1111111126666666666666666666666666666666666666666666666666666662111111
08|1111111126666666666666666666666666666666666666666666666666666662111111
09|1111111126666666666666666666666666666666666666666666666666666662111111
10|1111111126666666666666666666666666666666666666666666666666666662111111
11|1111111126666666666666666666666666666666666666666666666666666662111111
12|1111111126666666666666666666666666666666666666666666666666666662111111
13|1111111123333333332222222222222222222222222222222222222222222222111111
14|1111111126655555555577775555555555555555555555555555555555555552111111
15|1111111126655555555577775555555555555555555555555555555555555552111111
16|1111111126655555555555555557777555555555555555555555555555555552111111
17|1111111126655555555555557777555555555555555555555555555555555552111111
18|1111111128899999999999999999999999999999999999999999999999999992111111
19|1111111122222222222222222222222222222222222222222222222222222222111111
20|1111111125555555555555555555555555555555555555555555555555566552111111
21|1111111122222222222222222222222222222222222222222222222222222222111111
22|1111111111111111111111111111111111111111111111111111111111111111111111
23|::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
24|;;;;;;;;;;;;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@@ -0,0 +1,51 @@
--|---------|---------|---------|---------|---------|---------|---------|
01|
02|~
03|~ ╭ README.md ───────────────────────────────────────────╮
04|~ │# Fixture │
05|~ │ │
06|~ │ │
07|~ │ │
08|~ │ │
09|~ │ │
10|~ │ │
11|~ │ │
12|~ │ │
13|~ ├ FFFiles ─────────────────────────────────────────────┤
14|~ │ intro.md docs │
15|~ │ guide.md docs │
16|~ │ contributing.md docs │
17|~ │ changelog.md docs │
18|~ │ README.md │
19|~ ├──────────────────────────────────────────────────────┤
20|~ │> 32 │
21|~ ╰──────────────────────────────────────────────────────╯
22|~
23|[No Name] 0,1 All
24|-- INSERT -- 1,3 All
--|---------|---------|---------|---------|---------|---------|---------|
01|0000000000000000000000000000000000000000000000000000000000000000000000
02|1111111111111111111111111111111111111111111111111111111111111111111111
03|1111111123333333333322222222222222222222222222222222222222222222111111
04|1111111124444444445555555555555555555555555555555555555555555552111111
05|1111111126666666666666666666666666666666666666666666666666666662111111
06|1111111126666666666666666666666666666666666666666666666666666662111111
07|1111111126666666666666666666666666666666666666666666666666666662111111
08|1111111126666666666666666666666666666666666666666666666666666662111111
09|1111111126666666666666666666666666666666666666666666666666666662111111
10|1111111126666666666666666666666666666666666666666666666666666662111111
11|1111111126666666666666666666666666666666666666666666666666666662111111
12|1111111126666666666666666666666666666666666666666666666666666662111111
13|1111111123333333332222222222222222222222222222222222222222222222111111
14|1111111126655555555577775555555555555555555555555555555555555552111111
15|1111111126655555555577775555555555555555555555555555555555555552111111
16|1111111126655555555555555557777555555555555555555555555555555552111111
17|1111111126655555555555557777555555555555555555555555555555555552111111
18|1111111128899999999999999999999999999999999999999999999999999992111111
19|1111111122222222222222222222222222222222222222222222222222222222111111
20|1111111125555555555555555555555555555555555555555555555555566552111111
21|1111111122222222222222222222222222222222222222222222222222222222111111
22|1111111111111111111111111111111111111111111111111111111111111111111111
23|::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
24|;;;;;;;;;;;;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@@ -0,0 +1,51 @@
--|---------|---------|---------|---------|---------|---------|---------|
01|
02|~
03|~ ╭ README.md ───────────────────────────────────────────╮
04|~ │# Fixture │
05|~ │ │
06|~ │ │
07|~ │ │
08|~ │ │
09|~ │ │
10|~ │ │
11|~ │ │
12|~ │ │
13|~ ├ FFFiles ─────────────────────────────────────────────┤
14|~ │> 32 │
15|~ ├──────────────────────────────────────────────────────┤
16|~ │ README.md │
17|~ │ changelog.md docs │
18|~ │ contributing.md docs │
19|~ ╰──────────────────────────────────────────────────────╯
20|~
21|~
22|~
23|[No Name] 0,1 All
24|-- INSERT -- 1,3 All
--|---------|---------|---------|---------|---------|---------|---------|
01|0000000000000000000000000000000000000000000000000000000000000000000000
02|1111111111111111111111111111111111111111111111111111111111111111111111
03|1111111123333333333322222222222222222222222222222222222222222222111111
04|1111111124444444445555555555555555555555555555555555555555555552111111
05|1111111126666666666666666666666666666666666666666666666666666662111111
06|1111111126666666666666666666666666666666666666666666666666666662111111
07|1111111126666666666666666666666666666666666666666666666666666662111111
08|1111111126666666666666666666666666666666666666666666666666666662111111
09|1111111126666666666666666666666666666666666666666666666666666662111111
10|1111111126666666666666666666666666666666666666666666666666666662111111
11|1111111126666666666666666666666666666666666666666666666666666662111111
12|1111111126666666666666666666666666666666666666666666666666666662111111
13|1111111123333333332222222222222222222222222222222222222222222222111111
14|1111111125555555555555555555555555555555555555555555555555566552111111
15|1111111122222222222222222222222222222222222222222222222222222222111111
16|1111111127788888888888888888888888888888888888888888888888888882111111
17|1111111126655555555555559999555555555555555555555555555555555552111111
18|1111111126655555555555555559999555555555555555555555555555555552111111
19|1111111122222222222222222222222222222222222222222222222222222222111111
20|1111111111111111111111111111111111111111111111111111111111111111111111
21|1111111111111111111111111111111111111111111111111111111111111111111111
22|1111111111111111111111111111111111111111111111111111111111111111111111
23|::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
24|;;;;;;;;;;;;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@@ -0,0 +1,51 @@
--|---------|---------|---------|---------|---------|---------|---------|
01|
02|~
03|~ ╭ Preview ─────────────────────────────────────────────╮
04|~ │No preview available │
05|~ │ │
06|~ │ │
07|~ │ │
08|~ │ │
09|~ │ │
10|~ │ │
11|~ │ │
12|~ │ │
13|~ ├ FFFiles ─────────────────────────────────────────────┤
14|~ │ │
15|~ │ │
16|~ │ │
17|~ │ │
18|~ │ │
19|~ ├──────────────────────────────────────────────────────┤
20|~ │> zzzzzzzzz 0/32 │
21|~ ╰──────────────────────────────────────────────────────╯
22|~
23|[No Name] 0,1 All
24|-- INSERT -- 1,12 All
--|---------|---------|---------|---------|---------|---------|---------|
01|0000000000000000000000000000000000000000000000000000000000000000000000
02|1111111111111111111111111111111111111111111111111111111111111111111111
03|1111111123333333332222222222222222222222222222222222222222222222111111
04|1111111124444444444444444444444444444444444444444444444444444442111111
05|1111111125555555555555555555555555555555555555555555555555555552111111
06|1111111125555555555555555555555555555555555555555555555555555552111111
07|1111111125555555555555555555555555555555555555555555555555555552111111
08|1111111125555555555555555555555555555555555555555555555555555552111111
09|1111111125555555555555555555555555555555555555555555555555555552111111
10|1111111125555555555555555555555555555555555555555555555555555552111111
11|1111111125555555555555555555555555555555555555555555555555555552111111
12|1111111125555555555555555555555555555555555555555555555555555552111111
13|1111111123333333332222222222222222222222222222222222222222222222111111
14|1111111125544444444444444444444444444444444444444444444444444442111111
15|1111111125544444444444444444444444444444444444444444444444444442111111
16|1111111125544444444444444444444444444444444444444444444444444442111111
17|1111111125544444444444444444444444444444444444444444444444444442111111
18|1111111125544444444444444444444444444444444444444444444444444442111111
19|1111111122222222222222222222222222222222222222222222222222222222111111
20|1111111124444444444444444444444444444444444444444444444445555442111111
21|1111111122222222222222222222222222222222222222222222222222222222111111
22|1111111111111111111111111111111111111111111111111111111111111111111111
23|6666666666666666666666666666666666666666666666666666666666666666666666
24|7777777777778888888888888888888888888888888888888888888888888888888888
@@ -0,0 +1,51 @@
--|---------|---------|---------|---------|---------|---------|---------|
01|
02|~
03|~ ╭ src/main.rs ─────────────────────────────────────────╮
04|~ │fn main() {} │
05|~ │ │
06|~ │ │
07|~ │ │
08|~ │ │
09|~ │ │
10|~ │ │
11|~ │ │
12|~ │ │
13|~ ├ FFFiles ─────────────────────────────────────────────┤
14|~ │ main_utils.rs src │
15|~ │ main_runner.rs src │
16|~ │ main_loop.rs src │
17|~ │ main_helper.rs src │
18|~ │ main.rs src │
19|~ ├──────────────────────────────────────────────────────┤
20|~ │> main 19/32 │
21|~ ╰──────────────────────────────────────────────────────╯
22|~
23|[No Name] 0,1 All
24|-- INSERT -- 1,7 All
--|---------|---------|---------|---------|---------|---------|---------|
01|0000000000000000000000000000000000000000000000000000000000000000000000
02|1111111111111111111111111111111111111111111111111111111111111111111111
03|1111111123333333333333222222222222222222222222222222222222222222111111
04|1111111124444444444444444444444444444444444444444444444444444442111111
05|1111111125555555555555555555555555555555555555555555555555555552111111
06|1111111125555555555555555555555555555555555555555555555555555552111111
07|1111111125555555555555555555555555555555555555555555555555555552111111
08|1111111125555555555555555555555555555555555555555555555555555552111111
09|1111111125555555555555555555555555555555555555555555555555555552111111
10|1111111125555555555555555555555555555555555555555555555555555552111111
11|1111111125555555555555555555555555555555555555555555555555555552111111
12|1111111125555555555555555555555555555555555555555555555555555552111111
13|1111111123333333332222222222222222222222222222222222222222222222111111
14|1111111125566664444444444777444444444444444444444444444444444442111111
15|1111111125566664444444444477744444444444444444444444444444444442111111
16|1111111125566664444444447774444444444444444444444444444444444442111111
17|1111111125566664444444444477744444444444444444444444444444444442111111
18|1111111128866669999:::999999999999999999999999999999999999999992111111
19|1111111122222222222222222222222222222222222222222222222222222222111111
20|1111111124444444444444444444444444444444444444444444444455555442111111
21|1111111122222222222222222222222222222222222222222222222222222222111111
22|1111111111111111111111111111111111111111111111111111111111111111111111
23|;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
24|<<<<<<<<<<<<==========================================================
@@ -0,0 +1,67 @@
--|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|
01|
02|~
03|~
04|~ ┌ FFFiles ────────────────────────────────────────────┬ tests/main_test.rs ────────────────────────────────────┐
05|~ │ ▊#[test] fn main_test() {} │
06|~ │ ▊ │
07|~ │ ▊ │
08|~ │ ▊ │
09|~ │ ▊ │
10|~ │ ▊ │
11|~ │ ▊ │
12|~ │ ▊ │
13|~ │ ▊ │
14|~ │ ▊ │
15|~ │ regression.rs tests │ │
16|~ │ main_test.rs tests │ │
17|~ │ integration.rs tests │ │
18|~ │ table.tsx src/components │ │
19|~ │ menu.tsx src/components │ │
20|~ │ list.tsx src/components │ │
21|~ │ input.tsx src/components │ │
22|~ │ dialog.tsx src/components │ │
23|~ │ button.tsx src/components │ │
24|~ │ utils.rs src │ │
25|~ │ types.rs src │ │
26|~ ├─────────────────────────────────────────────────────┤ │
27|~ │> 32 │ │
28|~ └─────────────────────────────────────────────────────┴────────────────────────────────────────────────────────┘
29|~
30|~
31|[No Name] 0,1 All
32|-- INSERT -- 1,3 All
--|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|
01|00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
02|11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
03|11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
04|11111111111111123333333332222222222222222222222222222222222222222222223333333333333333333322222222222222222222222222222222222221111111111111
05|11111111111111124455555555555555555555555555555555555555555555555555565555555555555555555555555555555555555555555555555555555521111111111111
06|11111111111111124455555555555555555555555555555555555555555555555555564444444444444444444444444444444444444444444444444444444421111111111111
07|11111111111111124455555555555555555555555555555555555555555555555555564444444444444444444444444444444444444444444444444444444421111111111111
08|11111111111111124455555555555555555555555555555555555555555555555555564444444444444444444444444444444444444444444444444444444421111111111111
09|11111111111111124455555555555555555555555555555555555555555555555555564444444444444444444444444444444444444444444444444444444421111111111111
10|11111111111111124455555555555555555555555555555555555555555555555555564444444444444444444444444444444444444444444444444444444421111111111111
11|11111111111111124455555555555555555555555555555555555555555555555555564444444444444444444444444444444444444444444444444444444421111111111111
12|11111111111111124455555555555555555555555555555555555555555555555555564444444444444444444444444444444444444444444444444444444421111111111111
13|11111111111111124455555555555555555555555555555555555555555555555555564444444444444444444444444444444444444444444444444444444421111111111111
14|11111111111111124455555555555555555555555555555555555555555555555555564444444444444444444444444444444444444444444444444444444421111111111111
15|11111111111111124455555555555555777775555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
16|1111111111111112889999999999999:::::99999999999999999999999999999999924444444444444444444444444444444444444444444444444444444421111111111111
17|11111111111111124455555555555555577777555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
18|11111111111111124455555555557777777777777755555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
19|11111111111111124455555555577777777777777555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
20|11111111111111124455555555577777777777777555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
21|11111111111111124455555555557777777777777755555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
22|11111111111111124455555555555777777777777775555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
23|11111111111111124455555555555777777777777775555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
24|11111111111111124455555555577755555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
25|11111111111111124455555555577755555555555555555555555555555555555555524444444444444444444444444444444444444444444444444444444421111111111111
26|11111111111111122222222222222222222222222222222222222222222222222222224444444444444444444444444444444444444444444444444444444421111111111111
27|11111111111111125555555555555555555555555555555555555555555555555445524444444444444444444444444444444444444444444444444444444421111111111111
28|11111111111111122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221111111111111
29|11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
30|11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
31|;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
32|<<<<<<<<<<<<================================================================================================================================
@@ -0,0 +1,83 @@
--|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|
01|
02|~
03|~
04|~
05|~ ╔ FFFiles ════════════════════════════════════════════════════════════╦ README.md ═════════════════════════════════════════════════════════════╗
06|~ ║ menu.tsx src/components ║# Fixture ║
07|~ ║ list.tsx src/components ║ ║
08|~ ║ input.tsx src/components ║ ║
09|~ ║ dialog.tsx src/components ║ ║
10|~ ║ button.tsx src/components ║ ║
11|~ ║ utils.rs src ║ ║
12|~ ║ types.rs src ║ ║
13|~ ║ store.rs src ║ ║
14|~ ║ state.rs src ║ ║
15|~ ║ runner.rs src ║ ║
16|~ ║ parser.rs src ║ ║
17|~ ║ main_utils.rs src ║ ║
18|~ ║ main_runner.rs src ║ ║
19|~ ║ main_loop.rs src ║ ║
20|~ ║ main_helper.rs src ║ ║
21|~ ║ main.rs src ║ ║
22|~ ║ lib.rs src ║ ║
23|~ ║ error.rs src ║ ║
24|~ ║ config.rs src ║ ║
25|~ ║ cli.rs src ║ ║
26|~ ║ api.rs src ║ ║
27|~ ║ reference.md docs ║ ║
28|~ ║ license.md docs ║ ║
29|~ ║ intro.md docs ║ ║
30|~ ║ guide.md docs ║ ║
31|~ ║ contributing.md docs ║ ║
32|~ ║ changelog.md docs ║ ║
33|~ ║ README.md ║ ║
34|~ ╠═════════════════════════════════════════════════════════════════════╣ ║
35|~ ║> 32 ║ ║
36|~ ╚═════════════════════════════════════════════════════════════════════╩════════════════════════════════════════════════════════════════════════╝
37|~
38|~
39|[No Name] 0,1 All
40|-- INSERT -- 1,3 All
--|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|
01|000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
02|111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
03|111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
04|111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
05|111111111111111111123333333332222222222222222222222222222222222222222222222222222222222222333333333332222222222222222222222222222222222222222222222222222222222222211111111111111111
06|111111111111111111124455555555566666666666666555555555555555555555555555555555555555555552777777777555555555555555555555555555555555555555555555555555555555555555211111111111111111
07|111111111111111111124455555555566666666666666555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
08|111111111111111111124455555555556666666666666655555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
09|111111111111111111124455555555555666666666666665555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
10|111111111111111111124455555555555666666666666665555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
11|111111111111111111124455555555566655555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
12|111111111111111111124455555555566655555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
13|111111111111111111124455555555566655555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
14|111111111111111111124455555555566655555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
15|111111111111111111124455555555556665555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
16|111111111111111111124455555555556665555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
17|111111111111111111124455555555555555666555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
18|111111111111111111124455555555555555566655555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
19|111111111111111111124455555555555556665555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
20|111111111111111111124455555555555555566655555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
21|111111111111111111124455555555666555555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
22|111111111111111111124455555556665555555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
23|111111111111111111124455555555566655555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
24|111111111111111111124455555555556665555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
25|111111111111111111124455555556665555555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
26|111111111111111111124455555556665555555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
27|111111111111111111124455555555555556666555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
28|111111111111111111124455555555555666655555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
29|111111111111111111124455555555566665555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
30|111111111111111111124455555555566665555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
31|111111111111111111124455555555555555556666555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
32|111111111111111111124455555555555556666555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
33|111111111111111111128899999999999999999999999999999999999999999999999999999999999999999992444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
34|111111111111111111122222222222222222222222222222222222222222222222222222222222222222222222444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
35|111111111111111111125555555555555555555555555555555555555555555555555555555555555555544552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
36|111111111111111111122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211111111111111111
37|111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
38|111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
39|::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
40|;;;;;;;;;;;;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@@ -0,0 +1,83 @@
--|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|
01|
02|~
03|~
04|~
05|~ ╔ FFFiles ════════════════════════════════════════════════════════════╦ README.md ═════════════════════════════════════════════════════════════╗
06|~ ║ menu.tsx src/components ║# Fixture ║
07|~ ║ list.tsx src/components ║ ║
08|~ ║ input.tsx src/components ║ ║
09|~ ║ dialog.tsx src/components ║ ║
10|~ ║ button.tsx src/components ║ ║
11|~ ║ utils.rs src ║ ║
12|~ ║ types.rs src ║ ║
13|~ ║ store.rs src ║ ║
14|~ ║ state.rs src ║ ║
15|~ ║ runner.rs src ║ ║
16|~ ║ parser.rs src ║ ║
17|~ ║ main_utils.rs src ║ ║
18|~ ║ main_runner.rs src ║ ║
19|~ ║ main_loop.rs src ║ ║
20|~ ║ main_helper.rs src ║ ║
21|~ ║ main.rs src ║ ║
22|~ ║ lib.rs src ║ ║
23|~ ║ error.rs src ║ ║
24|~ ║ config.rs src ║ ║
25|~ ║ cli.rs src ║ ║
26|~ ║ api.rs src ║ ║
27|~ ║ reference.md docs ║ ║
28|~ ║ license.md docs ║ ║
29|~ ║ intro.md docs ║ ║
30|~ ║ guide.md docs ║ ║
31|~ ║ contributing.md docs ║ ║
32|~ ║ changelog.md docs ║ ║
33|~ ║ README.md ║ ║
34|~ ╠═════════════════════════════════════════════════════════════════════╣ ║
35|~ ║> 32 ║ ║
36|~ ╚═════════════════════════════════════════════════════════════════════╩════════════════════════════════════════════════════════════════════════╝
37|~
38|~
39|[No Name] 0,1 All
40|-- INSERT -- 1,3 All
--|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|
01|000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
02|111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
03|111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
04|111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
05|111111111111111111123333333332222222222222222222222222222222222222222222222222222222222222333333333332222222222222222222222222222222222222222222222222222222222222211111111111111111
06|111111111111111111124455555555566666666666666555555555555555555555555555555555555555555552777777777555555555555555555555555555555555555555555555555555555555555555211111111111111111
07|111111111111111111124455555555566666666666666555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
08|111111111111111111124455555555556666666666666655555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
09|111111111111111111124455555555555666666666666665555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
10|111111111111111111124455555555555666666666666665555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
11|111111111111111111124455555555566655555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
12|111111111111111111124455555555566655555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
13|111111111111111111124455555555566655555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
14|111111111111111111124455555555566655555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
15|111111111111111111124455555555556665555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
16|111111111111111111124455555555556665555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
17|111111111111111111124455555555555555666555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
18|111111111111111111124455555555555555566655555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
19|111111111111111111124455555555555556665555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
20|111111111111111111124455555555555555566655555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
21|111111111111111111124455555555666555555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
22|111111111111111111124455555556665555555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
23|111111111111111111124455555555566655555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
24|111111111111111111124455555555556665555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
25|111111111111111111124455555556665555555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
26|111111111111111111124455555556665555555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
27|111111111111111111124455555555555556666555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
28|111111111111111111124455555555555666655555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
29|111111111111111111124455555555566665555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
30|111111111111111111124455555555566665555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
31|111111111111111111124455555555555555556666555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
32|111111111111111111124455555555555556666555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
33|111111111111111111128899999999999999999999999999999999999999999999999999999999999999999992444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
34|111111111111111111122222222222222222222222222222222222222222222222222222222222222222222222444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
35|111111111111111111125555555555555555555555555555555555555555555555555555555555555555544552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
36|111111111111111111122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211111111111111111
37|111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
38|111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
39|::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
40|;;;;;;;;;;;;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@@ -0,0 +1,83 @@
--|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|
01|
02|~
03|~
04|~
05|~ ╔ FFFiles ════════════════════════════════════════════════════════════╦ README.md ═════════════════════════════════════════════════════════════╗
06|~ ║> 32 ║# Fixture ║
07|~ ╠═════════════════════════════════════════════════════════════════════╣ ║
08|~ ║ README.md ║ ║
09|~ ║ changelog.md docs ║ ║
10|~ ║ contributing.md docs ║ ║
11|~ ║ guide.md docs ║ ║
12|~ ║ intro.md docs ║ ║
13|~ ║ license.md docs ║ ║
14|~ ║ reference.md docs ║ ║
15|~ ║ api.rs src ║ ║
16|~ ║ cli.rs src ║ ║
17|~ ║ config.rs src ║ ║
18|~ ║ error.rs src ║ ║
19|~ ║ lib.rs src ║ ║
20|~ ║ main.rs src ║ ║
21|~ ║ main_helper.rs src ║ ║
22|~ ║ main_loop.rs src ║ ║
23|~ ║ main_runner.rs src ║ ║
24|~ ║ main_utils.rs src ║ ║
25|~ ║ parser.rs src ║ ║
26|~ ║ runner.rs src ║ ║
27|~ ║ state.rs src ║ ║
28|~ ║ store.rs src ║ ║
29|~ ║ types.rs src ║ ║
30|~ ║ utils.rs src ║ ║
31|~ ║ button.tsx src/components ║ ║
32|~ ║ dialog.tsx src/components ║ ║
33|~ ║ input.tsx src/components ║ ║
34|~ ║ list.tsx src/components ║ ║
35|~ ║ menu.tsx src/components ║ ║
36|~ ╚═════════════════════════════════════════════════════════════════════╩════════════════════════════════════════════════════════════════════════╝
37|~
38|~
39|[No Name] 0,1 All
40|-- INSERT -- 1,3 All
--|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|
01|000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
02|111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
03|111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
04|111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
05|111111111111111111123333333332222222222222222222222222222222222222222222222222222222222222333333333332222222222222222222222222222222222222222222222222222222222222211111111111111111
06|111111111111111111124444444444444444444444444444444444444444444444444444444444444444455442666666666444444444444444444444444444444444444444444444444444444444444444211111111111111111
07|111111111111111111122222222222222222222222222222222222222222222222222222222222222222222222555555555555555555555555555555555555555555555555555555555555555555555555211111111111111111
08|111111111111111111127788888888888888888888888888888888888888888888888888888888888888888882555555555555555555555555555555555555555555555555555555555555555555555555211111111111111111
09|111111111111111111125544444444444449999444444444444444444444444444444444444444444444444442555555555555555555555555555555555555555555555555555555555555555555555555211111111111111111
10|111111111111111111125544444444444444449999444444444444444444444444444444444444444444444442555555555555555555555555555555555555555555555555555555555555555555555555211111111111111111
11|111111111111111111125544444444499994444444444444444444444444444444444444444444444444444442555555555555555555555555555555555555555555555555555555555555555555555555211111111111111111
12|111111111111111111125544444444499994444444444444444444444444444444444444444444444444444442555555555555555555555555555555555555555555555555555555555555555555555555211111111111111111
13|111111111111111111125544444444444999944444444444444444444444444444444444444444444444444442555555555555555555555555555555555555555555555555555555555555555555555555211111111111111111
14|111111111111111111125544444444444449999444444444444444444444444444444444444444444444444442555555555555555555555555555555555555555555555555555555555555555555555555211111111111111111
15|111111111111111111125544444449994444444444444444444444444444444444444444444444444444444442555555555555555555555555555555555555555555555555555555555555555555555555211111111111111111
16|111111111111111111125544444449994444444444444444444444444444444444444444444444444444444442555555555555555555555555555555555555555555555555555555555555555555555555211111111111111111
17|111111111111111111125544444444449994444444444444444444444444444444444444444444444444444442555555555555555555555555555555555555555555555555555555555555555555555555211111111111111111
18|111111111111111111125544444444499944444444444444444444444444444444444444444444444444444442555555555555555555555555555555555555555555555555555555555555555555555555211111111111111111
19|111111111111111111125544444449994444444444444444444444444444444444444444444444444444444442555555555555555555555555555555555555555555555555555555555555555555555555211111111111111111
20|111111111111111111125544444444999444444444444444444444444444444444444444444444444444444442555555555555555555555555555555555555555555555555555555555555555555555555211111111111111111
21|111111111111111111125544444444444444499944444444444444444444444444444444444444444444444442555555555555555555555555555555555555555555555555555555555555555555555555211111111111111111
22|111111111111111111125544444444444449994444444444444444444444444444444444444444444444444442555555555555555555555555555555555555555555555555555555555555555555555555211111111111111111
23|111111111111111111125544444444444444499944444444444444444444444444444444444444444444444442555555555555555555555555555555555555555555555555555555555555555555555555211111111111111111
24|111111111111111111125544444444444444999444444444444444444444444444444444444444444444444442555555555555555555555555555555555555555555555555555555555555555555555555211111111111111111
25|111111111111111111125544444444449994444444444444444444444444444444444444444444444444444442555555555555555555555555555555555555555555555555555555555555555555555555211111111111111111
26|111111111111111111125544444444449994444444444444444444444444444444444444444444444444444442555555555555555555555555555555555555555555555555555555555555555555555555211111111111111111
27|111111111111111111125544444444499944444444444444444444444444444444444444444444444444444442555555555555555555555555555555555555555555555555555555555555555555555555211111111111111111
28|111111111111111111125544444444499944444444444444444444444444444444444444444444444444444442555555555555555555555555555555555555555555555555555555555555555555555555211111111111111111
29|111111111111111111125544444444499944444444444444444444444444444444444444444444444444444442555555555555555555555555555555555555555555555555555555555555555555555555211111111111111111
30|111111111111111111125544444444499944444444444444444444444444444444444444444444444444444442555555555555555555555555555555555555555555555555555555555555555555555555211111111111111111
31|111111111111111111125544444444444999999999999994444444444444444444444444444444444444444442555555555555555555555555555555555555555555555555555555555555555555555555211111111111111111
32|111111111111111111125544444444444999999999999994444444444444444444444444444444444444444442555555555555555555555555555555555555555555555555555555555555555555555555211111111111111111
33|111111111111111111125544444444449999999999999944444444444444444444444444444444444444444442555555555555555555555555555555555555555555555555555555555555555555555555211111111111111111
34|111111111111111111125544444444499999999999999444444444444444444444444444444444444444444442555555555555555555555555555555555555555555555555555555555555555555555555211111111111111111
35|111111111111111111125544444444499999999999999444444444444444444444444444444444444444444442555555555555555555555555555555555555555555555555555555555555555555555555211111111111111111
36|111111111111111111122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211111111111111111
37|111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
38|111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
39|::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
40|;;;;;;;;;;;;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@@ -0,0 +1,83 @@
--|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|
01|
02|~
03|~
04|~
05|~ ╔ FFFiles ════════════════════════════════════════════════════════════╦ Preview ═══════════════════════════════════════════════════════════════╗
06|~ ║ ║No preview available ║
07|~ ║ ║ ║
08|~ ║ ║ ║
09|~ ║ ║ ║
10|~ ║ ║ ║
11|~ ║ ║ ║
12|~ ║ ║ ║
13|~ ║ ║ ║
14|~ ║ ║ ║
15|~ ║ ║ ║
16|~ ║ ║ ║
17|~ ║ ║ ║
18|~ ║ ║ ║
19|~ ║ ║ ║
20|~ ║ ║ ║
21|~ ║ ║ ║
22|~ ║ ║ ║
23|~ ║ ║ ║
24|~ ║ ║ ║
25|~ ║ ║ ║
26|~ ║ ║ ║
27|~ ║ ║ ║
28|~ ║ ║ ║
29|~ ║ ║ ║
30|~ ║ ║ ║
31|~ ║ ║ ║
32|~ ║ ║ ║
33|~ ║ ║ ║
34|~ ╠═════════════════════════════════════════════════════════════════════╣ ║
35|~ ║> zzzzzzzzz 0/32 ║ ║
36|~ ╚═════════════════════════════════════════════════════════════════════╩════════════════════════════════════════════════════════════════════════╝
37|~
38|~
39|[No Name] 0,1 All
40|-- INSERT -- 1,12 All
--|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|
01|000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
02|111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
03|111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
04|111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
05|111111111111111111123333333332222222222222222222222222222222222222222222222222222222222222333333333222222222222222222222222222222222222222222222222222222222222222211111111111111111
06|111111111111111111124455555555555555555555555555555555555555555555555555555555555555555552555555555555555555555555555555555555555555555555555555555555555555555555211111111111111111
07|111111111111111111124455555555555555555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
08|111111111111111111124455555555555555555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
09|111111111111111111124455555555555555555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
10|111111111111111111124455555555555555555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
11|111111111111111111124455555555555555555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
12|111111111111111111124455555555555555555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
13|111111111111111111124455555555555555555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
14|111111111111111111124455555555555555555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
15|111111111111111111124455555555555555555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
16|111111111111111111124455555555555555555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
17|111111111111111111124455555555555555555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
18|111111111111111111124455555555555555555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
19|111111111111111111124455555555555555555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
20|111111111111111111124455555555555555555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
21|111111111111111111124455555555555555555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
22|111111111111111111124455555555555555555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
23|111111111111111111124455555555555555555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
24|111111111111111111124455555555555555555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
25|111111111111111111124455555555555555555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
26|111111111111111111124455555555555555555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
27|111111111111111111124455555555555555555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
28|111111111111111111124455555555555555555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
29|111111111111111111124455555555555555555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
30|111111111111111111124455555555555555555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
31|111111111111111111124455555555555555555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
32|111111111111111111124455555555555555555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
33|111111111111111111124455555555555555555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
34|111111111111111111122222222222222222222222222222222222222222222222222222222222222222222222444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
35|111111111111111111125555555555555555555555555555555555555555555555555555555555555554444552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
36|111111111111111111122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211111111111111111
37|111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
38|111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
39|666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666
40|777777777777888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888
@@ -0,0 +1,83 @@
--|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|
01|
02|~
03|~
04|~
05|~ ╔ FFFiles ════════════════════════════════════════════════════════════╦ src/main.rs ═══════════════════════════════════════════════════════════╗
06|~ ║ ║fn main() {} ║
07|~ ║ ║ ║
08|~ ║ ║ ║
09|~ ║ ║ ║
10|~ ║ ║ ║
11|~ ║ ║ ║
12|~ ║ ║ ║
13|~ ║ ║ ║
14|~ ║ ║ ║
15|~ ║ table.tsx src/components ║ ║
16|~ ║ list.tsx src/components ║ ║
17|~ ║ dialog.tsx src/components ║ ║
18|~ ║ button.tsx src/components ║ ║
19|~ ║ api.rs src ║ ║
20|~ ║ license.md docs ║ ║
21|~ ║ regression.rs tests ║ ║
22|~ ║ menu.tsx src/components ║ ║
23|~ ║ changelog.md docs ║ ║
24|~ ║ contributing.md docs ║ ║
25|~ ║ integration.rs tests ║ ║
26|~ ║ input.tsx src/components ║ ║
27|~ ║ intro.md docs ║ ║
28|~ ║ main_test.rs tests ║ ║
29|~ ║ main_utils.rs src ║ ║
30|~ ║ main_runner.rs src ║ ║
31|~ ║ main_loop.rs src ║ ║
32|~ ║ main_helper.rs src ║ ║
33|~ ║ main.rs src ║ ║
34|~ ╠═════════════════════════════════════════════════════════════════════╣ ║
35|~ ║> main 19/32 ║ ║
36|~ ╚═════════════════════════════════════════════════════════════════════╩════════════════════════════════════════════════════════════════════════╝
37|~
38|~
39|[No Name] 0,1 All
40|-- INSERT -- 1,7 All
--|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|
01|000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
02|111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
03|111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
04|111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
05|111111111111111111123333333332222222222222222222222222222222222222222222222222222222222222333333333333322222222222222222222222222222222222222222222222222222222222211111111111111111
06|111111111111111111124455555555555555555555555555555555555555555555555555555555555555555552555555555555555555555555555555555555555555555555555555555555555555555555211111111111111111
07|111111111111111111124455555555555555555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
08|111111111111111111124455555555555555555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
09|111111111111111111124455555555555555555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
10|111111111111111111124455555555555555555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
11|111111111111111111124455555555555555555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
12|111111111111111111124455555555555555555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
13|111111111111111111124455555555555555555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
14|111111111111111111124455555555555555555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
15|111111111111111111124455555555556666666666666655555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
16|111111111111111111124455555555566666666666666555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
17|111111111111111111124455555555555666666666666665555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
18|111111111111111111124455555555555666666666666665555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
19|111111111111111111124455555556665555555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
20|111111111111111111124455555555555666655555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
21|111111111111111111124455555555555555666665555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
22|111111111111111111124455555555566666666666666555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
23|111111111111111111124455555555555556666555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
24|111111111111111111124455555555555555556666555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
25|111111111111111111124455555555555555566666555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
26|111111111111111111124455555555556666666666666655555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
27|111111111111111111124455555555566665555555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
28|111111111111111111124477775555555556666655555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
29|111111111111111111124477775555555555666555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
30|111111111111111111124477775555555555566655555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
31|111111111111111111124477775555555556665555555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
32|111111111111111111124477775555555555566655555555555555555555555555555555555555555555555552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
33|111111111111111111128877779999:::999999999999999999999999999999999999999999999999999999992444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
34|111111111111111111122222222222222222222222222222222222222222222222222222222222222222222222444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
35|111111111111111111125555555555555555555555555555555555555555555555555555555555555544444552444444444444444444444444444444444444444444444444444444444444444444444444211111111111111111
36|111111111111111111122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211111111111111111
37|111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
38|111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
39|;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
40|<<<<<<<<<<<<========================================================================================================================================================================
+126
View File
@@ -0,0 +1,126 @@
--- Test fixtures for fff.nvim snapshot tests.
---
--- Builds a deterministic, throwaway directory tree on disk and tears it down
--- after each test. Also scopes frecency/history DBs to temp paths so picker
--- ordering is reproducible regardless of the developer's history.
local M = {}
--- Files used by every snapshot test. Sized to overflow the list page so
--- snapshots reflect realistic scrolling/clipping behaviour.
local FIXTURE_FILES = {
['README.md'] = '# Fixture\n',
['src/main.rs'] = 'fn main() {}\n',
['src/main_helper.rs'] = 'pub fn helper() {}\n',
['src/main_utils.rs'] = 'pub fn util() {}\n',
['src/main_runner.rs'] = 'pub fn run() {}\n',
['src/main_loop.rs'] = 'pub fn loop_() {}\n',
['src/lib.rs'] = 'pub fn it_works() -> i32 { 42 }\n',
['src/utils.rs'] = 'pub fn helper() {}\n',
['src/parser.rs'] = 'pub fn parse() {}\n',
['src/runner.rs'] = 'pub fn run() {}\n',
['src/state.rs'] = 'pub struct State {}\n',
['src/config.rs'] = 'pub struct Config {}\n',
['src/error.rs'] = 'pub enum Error {}\n',
['src/types.rs'] = 'pub type Id = u64;\n',
['src/store.rs'] = 'pub struct Store {}\n',
['src/api.rs'] = 'pub fn api() {}\n',
['src/cli.rs'] = 'pub fn cli() {}\n',
['src/components/button.tsx'] = 'export const Button = () => null\n',
['src/components/input.tsx'] = 'export const Input = () => null\n',
['src/components/dialog.tsx'] = 'export const Dialog = () => null\n',
['src/components/menu.tsx'] = 'export const Menu = () => null\n',
['src/components/list.tsx'] = 'export const List = () => null\n',
['src/components/table.tsx'] = 'export const Table = () => null\n',
['docs/intro.md'] = '# Intro\n',
['docs/guide.md'] = '# Guide\n',
['docs/reference.md'] = '# Reference\n',
['docs/changelog.md'] = '# Changelog\n',
['docs/contributing.md'] = '# Contributing\n',
['docs/license.md'] = '# License\n',
['tests/main_test.rs'] = '#[test] fn main_test() {}\n',
['tests/integration.rs'] = '#[test] fn it() {}\n',
['tests/regression.rs'] = '#[test] fn regress() {}\n',
}
--- @class fff.snapshot.Fixture
--- @field root string absolute path to fixture root
--- @field frecency_db string
--- @field history_db string
--- Create a fresh fixture: deterministic file tree, scoped DBs, fff config
--- pointing at the temp DB paths.
--- @return fff.snapshot.Fixture
function M.create()
local raw_root = vim.fn.tempname() .. '_fff_snap_fixture'
vim.fn.mkdir(raw_root, 'p')
-- Resolve symlinks (on macOS /tmp → /private/tmp). Without this, picker_ui's
-- change_indexing_directory canonicalises the path and silently reinitialises
-- the FilePicker, which invalidates query-tracker entries we've trained
-- against the original path.
local root = vim.fn.resolve(raw_root)
for rel, content in pairs(FIXTURE_FILES) do
local path = root .. '/' .. rel
vim.fn.mkdir(vim.fn.fnamemodify(path, ':h'), 'p')
local f = assert(io.open(path, 'w'))
f:write(content)
f:close()
end
-- Initialise as a git repo so the picker exercises its git-status path the
-- same way it would in real use.
vim.fn.system({ 'git', '-C', root, 'init', '-q' })
vim.fn.system({ 'git', '-C', root, '-c', 'user.email=t@t', '-c', 'user.name=t', 'add', '-A' })
vim.fn.system({ 'git', '-C', root, '-c', 'user.email=t@t', '-c', 'user.name=t', 'commit', '-q', '-m', 'init' })
local frecency_db = vim.fn.tempname() .. '_fff_snap_frecency'
local history_db = vim.fn.tempname() .. '_fff_snap_history'
return { root = root, frecency_db = frecency_db, history_db = history_db }
end
--- Apply fff config that uses the fixture's scoped DBs and sane defaults for
--- snapshot tests (no debounce, fixed sizes).
--- @param fixture fff.snapshot.Fixture
function M.configure(fixture)
---@diagnostic disable-next-line: missing-fields
vim.g.fff = {
frecency = { enabled = true, db_path = fixture.frecency_db },
---@diagnostic disable-next-line: missing-fields
history = { enabled = true, db_path = fixture.history_db },
}
-- Reload config so the new vim.g.fff is picked up.
package.loaded['fff.conf'] = nil
end
--- Destroy fixture artefacts on disk and reset module state.
--- @param fixture fff.snapshot.Fixture
function M.cleanup(fixture)
local rust_ok, fff_rust = pcall(require, 'fff.rust')
if rust_ok then
pcall(fff_rust.stop_background_monitor)
pcall(fff_rust.cleanup_file_picker)
pcall(fff_rust.destroy_frecency_db)
pcall(fff_rust.destroy_query_db)
end
if fixture.root then vim.fn.delete(fixture.root, 'rf') end
if fixture.frecency_db then vim.fn.delete(fixture.frecency_db, 'rf') end
if fixture.history_db then vim.fn.delete(fixture.history_db, 'rf') end
vim.g.fff = nil
package.loaded['fff.conf'] = nil
end
--- Initialise the picker against the fixture and wait for the initial scan.
--- @param fixture fff.snapshot.Fixture
function M.init_picker(fixture)
vim.cmd('cd ' .. vim.fn.fnameescape(fixture.root))
local fff_rust = require('fff.rust')
assert(fff_rust.init_db(fixture.frecency_db, fixture.history_db, true), 'init_db failed')
assert(fff_rust.init_file_picker(fixture.root), 'init_file_picker failed')
fff_rust.wait_for_initial_scan(10000)
end
return M