Skip to content

Feature/338 hide line - #718

Draft
Hirogen wants to merge 11 commits into
Developmentfrom
feature/338-hide-line
Draft

Hirogen wants to merge 11 commits into
Developmentfrom
feature/338-hide-line

Conversation

@Hirogen

@Hirogen Hirogen commented Sep 26, 2026 •

Copy link
Copy Markdown
Collaborator

What

Highlight Entries get a Hide line checkbox. Lines matching any hide rule in the active Highlight Group are removed from the Log Window's main grid.

  • Hiding is display-only. Lines stay in the reader and remain available to Log Search, the Window Filter, Filter Pipes and tail triggers (stop tail, bookmarks, plugins, audio, LED).
  • Line numbers stay the original ones, so gaps are expected.
  • A notice bar at the top of the grid shows how many lines are hidden. It has a per-window Show hidden lines checkbox. That setting is not saved in the Session File.

Behaviour

  • Rule precedence: a line is hidden when any matching hide rule applies. Rule order doesn't matter, and coloring rules can't cancel a hide. Temporary search highlights never hide lines.
  • Matching: hide rules match the whole line with the existing case-sensitivity and regex semantics, the same as tail triggers. For a word-mode rule, the painting only highlights matches inside columns, so a match that spans a column boundary hides the line without being painted.
  • Explicit navigation to a hidden line turns on "Show hidden lines" and selects that exact line. This covers:
  • Non-explicit movement selects the nearest visible line instead (next visible, else previous):
    • windows following a time sync
    • restoring saved session and reload positions
    • Stop Tail triggers (the trigger still fires; the selection moves to the nearest visible line)
    • multi-file jumps (Alt+Up/Down)
  • Follow tail tracks the last visible line.
  • Next/previous highlight (Alt+PgUp/PgDn) skips hidden lines.
  • Rule or group changes rescan in the background. The selected line is kept if it stays visible; otherwise the selection moves to the next visible line, else the previous one. If every line is hidden, the grid is empty and navigation still works.
  • Load and reload: the grid shows no rows until the first scan finishes, so hidden lines never flash up. Saved positions are applied after that, and explicit navigation made meanwhile (Go to Line, bookmark window, marker clicks, timestamp navigation, including windows following a time sync) is queued and runs as requested once the scan finishes. A newer request from the user replaces a queued one; a time sync never replaces the user's own. Any reload drops it, the -line target included, as Reload() already did before this PR.
  • Copy and copy-to-tab only include the selected visible rows.
  • Marker Bar: markers keep their original-line positions. A hide-only rule still produces a marker if it has colours, following the Feature request: Visually mark positions of lines highlighted by Highlighter on scrollbar #27 colour policy; a hide rule with no colours or bold produces none.

How

  • Core: HighlightEntry.IsHideLine defaults to false, so existing settings load unchanged. It is cloned, serialized and survives highlight export/import.
  • Core: HighlightEvaluator.IsHidden makes the hide decision. It never fires triggers.
  • Core: LineVisibilityMap is an immutable mapping between visible rows and original lines. Its memory is proportional to the number of hidden lines, and tail appends share storage.
  • Core: LineVisibilityTracker keeps the map up to date:
    • Full scans run on a cancellable background task against a snapshot of the rules. Results from outdated scans are discarded.
    • Tail appends are evaluated on the tail thread, and rollover shifts the map.
    • Log lines are never read while the tracker holds its lock, and each batch of lines is pinned before it is read, like the marker scan.
    • If a rule fails (for example a bad regex), all lines are shown and the error goes to the status line.
  • UI: VisibleRows holds the displayed map, publishes it to the grid and keeps the selection and scroll position by original line. HiddenLinesBar is the notice bar control. LogWindow keeps the wiring: the row↔line conversion, the reveal policy (NavigationRow) and the load and tail hooks.
  • UI: LogWindow.cs — every place that used a grid row index as a reader line now converts between the two. That covers selection, clipboard, bookmarks, row heights, timestamps, source-file lookup, the columnizer callback, sessions and follow tail.
  • UI: ColumnCache.PrefetchLines pins only the lines that visible rows display, even when they are far apart in the file.
  • CONTEXT.md documents the new terms and the reveal policy: Hide-line rule, Original logical line, Visible row, Line Visibility Map, Show hidden lines.
  • New strings are added in en, de and zh-CN.

Tests

  • Core unit tests cover the map, the hide decision, tracker lifecycle and staleness, and pinned reads, including a regression test that a blocked read from the log can't block the UI thread. Highlight export/import keeps IsHideLine, and older files without it load as false. Marker criteria tests pin the colour policy for hide rules.
  • 36 window tests on a real Log Window cover hiding, the override, reveal on navigation, navigation during the first scan (Go to Line, bookmark window, timestamp, time-sync follower), selection relocation, all lines hidden, follow tail, truncation, multi-file rollover, tail triggers, copy, session and reload positions, search, bookmarks, filter, Filter Pipe tabs, marker bar, command line, time sync and notice bar layout.
  • A performance test is marked [Explicit]. On 1M lines (62 MB) with 500k hidden:
    • the scan takes 613 ms
    • it uses about 2.1 MB of extra managed memory
    • the longest UI stall is 193 ms, from the grid rebuilding its rows
    • Go to Line on the hidden last line takes 649 ms; turning the override off and scrolling to the middle takes 443 ms

HighlightEntry.IsHideLine (default false, cloned, serialized),
HighlightEvaluator.IsHidden, an immutable row<->original-line map with
append-only shared storage, and a tracker that rebuilds the map on a
cancellable background scan with generation-tagged results.
The main grid now displays the rows of a LineVisibilityMap; reader,
bookmark, timestamp, search, session and row-height code keeps using
original logical lines. Explicit navigation to a hidden line turns on
the per-window 'Show hidden lines' override; tail follow tracks the last
visible row. A notice bar shows the hidden-line count and the override,
and the Highlight Entry dialog gets a 'Hide line' checkbox.
The UI thread takes the tracker lock (Load/Rebuild/IsScanning) while a
reader call made under it could wait for the UI thread, which could hang
the window. Tail/scan evaluation now reads outside the lock and commits
only if the state is unchanged. Also cancels the scan when the window
closes, fixes marker navigation to lines beyond the visible row count,
adds lifecycle/trigger/marker/perf tests and the CONTEXT.md glossary.
…en (#338)

- While a load's first visibility scan runs the grid shows no rows, and
  saved/reload positions are applied once it has published.
- Windows following a time sync select the nearest visible line; only the
  window the user navigates in reveals a hidden line.
- Review fixes: shared evaluate-and-commit loop in the tracker, one
  publish path for the grid, CurrentLineNum instead of a duplicate
  property, line/row naming, unsubscribe on close, drop unused Truncate.
@Hirogen Hirogen linked an issue Sep 26, 2026 that may be closed by this pull request
@Hirogen

Hirogen commented Sep 26, 2026 •

Copy link
Copy Markdown
Collaborator Author
image image

Comment on lines +293 to +308
catch (Exception ex)
{
lock (_lock)
{
if (generation != _generation)
{
return;
}

map = LineVisibilityMap.Identity(_map.LineCount);
SetStateLocked(map, []);
_pendingRules = null;
_loadPending = false;
error = ex;
}
}
- Remove stray Temp/Statusbar.png and unrelated Resources.Designer.cs whitespace
- Queue explicit navigation (Go to Line, bookmark window, marker clicks) until the first visibility scan finishes
- Pin line buffers in batches while the tracker reads, like the marker scan
- One reveal-or-nearest decision (NavigationRow); rename SelectLine to RevealAndSelectLine
- GridPosition replaces the loose current/first line pair; one ApplyPosition for restore and map changes
- Share the hide-rule predicate; tracker tail methods return nothing; trim comments
- Record reveal and matching policy in CONTEXT.md
- Tests: truncation and rollover in a Log Window, Filter Pipe hiding and locate, highlight export/import, hide-rule markers, pinned reads, navigation during the first scan
- HiddenLinesBar: the notice bar control (count and Show hidden lines check box)
- VisibleRows: the displayed Line Visibility Map, publishing it to the grid and keeping the position by original line
- The remaining wiring moves into LogWindow.cs; LogWindow.LineVisibility.cs is removed
- Queue explicit navigation made before the first scan as the call itself, keeping its time-sync flag and follow-tail state; timestamp navigation from the sync origin is queued too and reports it did not scroll
- Drop queued navigation when a reload replaces loaded content
- Restoring a saved or reload position selects through SelectRow again (clears a pending time sync, focuses the grid)
- VisibleRows takes an IVisibleRowsHost instead of three callbacks and owns the current-line lookup
- Rename NavigationRow to RevealOrNearestRow; the pin delegate is required; comment fixes
- Tests: bookmark window and timestamp navigation during the first scan
- One pending navigation (an Action) replaces the target line and the queued call; RunWhenNavigable runs it now or once navigable
- Windows following a time sync queue during their first scan too, and move to the nearest visible line
- Every reload after the first load drops queued navigation, the -line target included
- A reload restores its position without taking focus; session restore still focuses; both clear a pending time sync
- VisibleRows splits select-and-scroll from scroll-only; SameRules says why three fields suffice
- Tests: time-sync follower during the first scan; timestamp tests skip instead of racing the scan
- Automatic reloads (ReloadNewFile) drop queued navigation where they start, like Reload(); entering the load status no longer does, so a multi-file session keeps its -line target
- Queued time-sync following never replaces the user's own queued navigation (PendingNavigation)
- Rename GoToTargetLine to GotoRequestedLine; inline the time-sync reset at the two restores; document ScrollToTimestampWorker's result
- Test: a time sync during the first scan doesn't replace a queued Go to Line
- RestorePositionWithoutTimeSync replaces the two inlined copies
- Queue -> SetPendingNavigation, PendingNavigation.Run -> Navigate, record moved out of the methods
- Name the time-sync-follow condition in ScrollToTimestampWorker
- ReloadNewFile drops queued navigation only for the reload it actually starts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature Request] Ability to hide line in Highlight rules

1 participant