Skip to content

Comments

Tweaks: Visual display changes, based dedupe support, file display#36

Merged
boyter merged 7 commits intomasterfrom
tweaks
Feb 20, 2026
Merged

Tweaks: Visual display changes, based dedupe support, file display#36
boyter merged 7 commits intomasterfrom
tweaks

Conversation

@boyter
Copy link
Owner

@boyter boyter commented Feb 20, 2026

No description provided.

@boyter boyter requested a review from Copilot February 20, 2026 00:54
@pr-insights pr-insights bot added L/complexity Low complexity S/size Small change labels Feb 20, 2026
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds new search “tweaks” across interfaces: deduplication of byte-identical matches, declaration-vs-usage filtering, and a TUI file viewer, alongside some UI rendering adjustments.

Changes:

  • Add --dedup support and plumb duplicate metadata (count/locations) through console/HTTP/TUI/MCP outputs.
  • Add --only-declarations / --only-usages filtering via match-location classification heuristics.
  • Add a TUI file viewer overlay (keyboard/mouse navigation) and adjust selection styling / line-gap rendering.

Reviewed changes

Copilot reviewed 17 out of 17 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tui.go Adds viewer overlay, mouse interactions, dedup display, line-gap rendering, and extended filter cycling.
syntax.go Removes background from “selected” syntax styles.
search.go Applies declaration/usage filtering during search pipeline and adjusts content-type filtering condition.
pkg/ranker/dedup.go Implements match-span hashing and result deduplication logic.
pkg/ranker/dedup_test.go Adds tests for deduplication and hash behavior.
pkg/ranker/declarations.go Adds declaration-pattern heuristics and match-location classification.
pkg/ranker/declarations_test.go Adds tests for declaration detection and classification.
pkg/common/common.go Extends FileJob with dedup-related fields (MatchHash, duplicate metadata).
mcp.go Documents and parses new filters and dedup argument; applies dedup post-ranking.
main.go Adds new flags, enforces mutual exclusivity, enables mouse support for TUI.
http.go Adds gap rendering for line mode and includes duplicate metadata in JSON; adds request-time dedup and new filter parsing.
console.go Applies dedup before limiting; prints duplicate metadata; adds gap lines in line output; extends JSON output schema.
config.go Adds config flags for new filters and dedup; updates HasContentFilter and cache prefix.
asset/templates/*/search.html Adds visual gaps between non-contiguous line results (template + JS rendering).
README.md Updates docs for OR/grouping, dedup flag, and adds a section about declaration detection.
Comments suppressed due to low confidence (6)

tui.go:1081

  • openViewer parses r.LineRange with fmt.Sscanf but ignores the return values and always does startLine--. If parsing fails, startLine remains 0 and becomes -1, which is an unexpected sentinel and can leak into viewStartLine. Consider only decrementing when the scan succeeded and startLine > 0 (or defaulting to 0 when parsing fails).
	// Parse start line from LineRange (e.g. "42-58")
	startLine := 0
	if r.LineRange != "" {
		fmt.Sscanf(r.LineRange, "%d", &startLine)
		startLine-- // convert to 0-based
	}

tui.go:1067

  • openViewer reads the entire file with os.ReadFile, ignoring the existing MaxReadSizeBytes limit used by the search pipeline. Opening a very large matched file could cause a big memory spike or stall the TUI. Consider reusing the same size-limited read helper (or adding a viewer-specific cap / streaming approach).
func (m *model) openViewer(r searchResult) error {
	data, err := os.ReadFile(r.Location)
	if err != nil {
		return err
	}

	lines := strings.Split(string(data), "\n")

README.md:75

  • This README section claims the structural ranker "uses declaration detection to boost matches that appear on declaration lines". In the current changes, declaration detection is used for filtering (--only-declarations/--only-usages) in the search pipeline, but there's no ranker-side boost implemented. Please adjust the documentation to match the behavior (or implement the described boosting).
The structural ranker also uses declaration detection to boost matches that appear on declaration lines 
(e.g. `func`, `class`, `def`) over plain usages. This currently works for the following languages:

Go, Python, JavaScript, TypeScript, TSX, Rust, Java, C, C++, C#, Ruby, PHP, Kotlin, Swift

For unsupported languages, all matches are treated as usages and ranked by text relevance only. 
Structural filtering (`--only-code`, `--only-comments`, `--only-strings`) still works for any language recognised 
by [scc](https://github.com/boyter/scc).

http.go:241

  • In the codeFilter switch, the only-declarations / only-usages cases (and the default case) don't clear the other mutually-exclusive filter flags. Because searchCfg is copied from the server config, a request can end up with multiple filters enabled (e.g. server started with --only-code and request sets cf=only-declarations), which also affects HasContentFilter() and the search cache key prefix. Consider resetting all Only* filter booleans to false before applying the requested filter (or explicitly clearing the others in every case).
			switch codeFilter {
			case "only-code":
				searchCfg.OnlyCode = true
				searchCfg.OnlyComments = false
				searchCfg.OnlyStrings = false
			case "only-comments":
				searchCfg.OnlyCode = false
				searchCfg.OnlyComments = true
				searchCfg.OnlyStrings = false
			case "only-strings":
				searchCfg.OnlyCode = false
				searchCfg.OnlyComments = false
				searchCfg.OnlyStrings = true
			case "only-declarations":
				searchCfg.OnlyDeclarations = true
			case "only-usages":
				searchCfg.OnlyUsages = true
			default:
				searchCfg.OnlyCode = false
				searchCfg.OnlyComments = false
				searchCfg.OnlyStrings = false
			}

mcp.go:327

  • The MCP code_filter argument handler sets a specific Only* flag but never clears the other mutually-exclusive filter flags inherited from cfg. This can lead to multiple filters being active at once (despite the docs stating they're mutually exclusive), and can also skew cache keys and ranking auto-selection via HasContentFilter(). Reset all Only* flags to false before setting the selected one.
		if v, ok := request.GetArguments()["code_filter"]; ok {
			if s, ok := v.(string); ok && s != "" {
				switch s {
				case "only-code":
					searchCfg.OnlyCode = true
				case "only-comments":
					searchCfg.OnlyComments = true
				case "only-strings":
					searchCfg.OnlyStrings = true
				case "only-declarations":
					searchCfg.OnlyDeclarations = true
				case "only-usages":
					searchCfg.OnlyUsages = true
				}
				if searchCfg.HasContentFilter() {
					searchCfg.Ranker = "structural"
				}
			}

tui.go:450

  • openViewer returns an error, but the caller ignores it. If the file can't be read (deleted, permission error, etc.), the UI will silently do nothing. Consider capturing the error and surfacing it in the TUI (e.g., via a status line message) or at least logging it.
		case tea.KeyF5, tea.KeyCtrlO, tea.KeyCtrlP:
			if len(m.results) > 0 && m.selectedIndex < len(m.results) {
				m.openViewer(m.results[m.selectedIndex])
			}
			return m, nil

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +750 to 770
// cycleCodeFilter cycles: default → only-code → only-comments → only-strings → only-declarations → only-usages → default…
// Auto-switches ranker to "structural" when a filter is active.
func (m *model) cycleCodeFilter() {
switch {
case !m.cfg.OnlyCode && !m.cfg.OnlyComments && !m.cfg.OnlyStrings:
case !m.cfg.OnlyCode && !m.cfg.OnlyComments && !m.cfg.OnlyStrings && !m.cfg.OnlyDeclarations && !m.cfg.OnlyUsages:
m.cfg.OnlyCode = true
m.cfg.OnlyComments = false
m.cfg.OnlyStrings = false
case m.cfg.OnlyCode:
m.cfg.OnlyCode = false
m.cfg.OnlyComments = true
m.cfg.OnlyStrings = false
case m.cfg.OnlyComments:
m.cfg.OnlyCode = false
m.cfg.OnlyComments = false
m.cfg.OnlyStrings = true
default:
m.cfg.OnlyCode = false
m.cfg.OnlyComments = false
case m.cfg.OnlyStrings:
m.cfg.OnlyStrings = false
m.cfg.OnlyDeclarations = true
case m.cfg.OnlyDeclarations:
m.cfg.OnlyDeclarations = false
m.cfg.OnlyUsages = true
case m.cfg.OnlyUsages:
m.cfg.OnlyUsages = false
}
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cycleCodeFilter now cycles through only-declarations and only-usages, but existing TUI unit tests (e.g. TestCycleCodeFilter in tui_test.go) still assert the old 4-step cycle ending at only-strings → default. As-is, this change will break the test suite; update the tests to reflect the new cycle order.

Copilot uses AI. Check for mistakes.
@boyter boyter changed the title Tweaks Tweaks: Visual display changes, based dedupe support, file display Feb 20, 2026
@pr-insights pr-insights bot added M/complexity Normal or medium complexity M/size Normal or medium sized change and removed S/size Small change L/complexity Low complexity labels Feb 20, 2026
@boyter boyter merged commit 9a4c0e5 into master Feb 20, 2026
@boyter boyter deleted the tweaks branch February 20, 2026 01:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

M/complexity Normal or medium complexity M/size Normal or medium sized change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant