Skip to content

Conversation

@snakefoot
Copy link
Contributor

@snakefoot snakefoot commented Aug 13, 2025

Thus one can specify text="|Warn|" wholeWords="true" and it will only highlight Warn-word when inside |

@snakefoot snakefoot added enhancement Improvement on existing feature console-target labels Aug 13, 2025
@coderabbitai
Copy link

coderabbitai bot commented Aug 13, 2025

Walkthrough

Adds a private GenerateMatch helper to ConsoleWordHighlightingRule to compute trimmed match spans when WholeWords is enabled, replaces direct match constructions with it, tightens FindNextWordForHighlighting boundary checks, and adds a unit test covering delimiter-only Text with WholeWords.

Changes

Cohort / File(s) Summary
Word-boundary matching logic
src/NLog/Targets/ConsoleWordHighlightingRule.cs
Added private GenerateMatch(string needle, int firstIndex) to trim non-letter/digit edges when WholeWords is true; replaced direct (start, needle.Length) constructions with GenerateMatch(...) across single- and multi-match paths; tightened boundary checks in FindNextWordForHighlighting. No public API changes.
Unit test
tests/NLog.UnitTests/Targets/ColoredConsoleTargetTests.cs
Added test WordHighlightingOnlyTextWholeWords() asserting only the inner word ("at") is highlighted when a rule uses `Text = "

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Caller as Highlighting Logic
  participant Rule as ConsoleWordHighlightingRule
  participant Gen as GenerateMatch

  Caller->>Rule: YieldWordsForHighlighting(needle, text)
  Rule->>Rule: Find firstIndex / nextIndex via FindNextWordForHighlighting
  alt match found
    Rule->>Gen: GenerateMatch(needle, index)
    Gen-->>Rule: (start, length) — trimmed if WholeWords
    Rule-->>Caller: yield (start, length)
  end
  opt additional matches
    Rule->>Gen: GenerateMatch(needle, nextIndex)
    Gen-->>Rule: (start, length)
    Rule-->>Caller: yield (start, length)
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

I nibble words and trim their sleeves,
Pipes fall off like autumn leaves.
“at” stands proud within its space,
Highlighted now in crimson grace.
A rabbit hops — precise, polite. 🐇✨


📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0c35d8a and e887417.

📒 Files selected for processing (2)
  • src/NLog/Targets/ConsoleWordHighlightingRule.cs (2 hunks)
  • tests/NLog.UnitTests/Targets/ColoredConsoleTargetTests.cs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/NLog.UnitTests/Targets/ColoredConsoleTargetTests.cs
  • src/NLog/Targets/ConsoleWordHighlightingRule.cs

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@snakefoot snakefoot closed this Aug 13, 2025
@snakefoot snakefoot reopened this Aug 13, 2025
@snakefoot snakefoot closed this Aug 13, 2025
@snakefoot snakefoot reopened this Aug 13, 2025
@snakefoot snakefoot force-pushed the dev branch 2 times, most recently from 19b8ce3 to 0c35d8a Compare August 13, 2025 20:56
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
src/NLog/Targets/ConsoleWordHighlightingRule.cs (3)

252-282: GenerateMatch: correct trimming; consider EOL symmetry and delimiter-only intent

The trimming logic is sound and produces the desired “word-only” highlight from a delimited needle.

Two follow-ups to consider:

  • Symmetry with end-of-line: The current acceptance logic in FindNextWordForHighlighting accounts for start-of-line but not end-of-line when only one side has a delimiter. If you also want to support patterns like "Warn|" at end-of-message (WholeWords), see my suggestion on Lines 305-309.
  • Delimiter-only needles: When the needle consists entirely of non-letter/digit characters, this returns the original span (highlights only delimiters). Verify that this is intentional with “WholeWords” semantics. If not, you might choose to skip these matches.

Performance (optional): GenerateMatch rescans the same needle each time it’s called. When there are many occurrences, precomputing trim offsets per needle can avoid repeated scans.

Do you want delimiter-only needles to be highlighted under WholeWords, or should they be skipped entirely? I can provide a targeted change and unit test if you want to change this behavior.


286-286: Consistent use of GenerateMatch; consider precomputing trim once per needle

LGTM on switching all yields to GenerateMatch to ensure consistent trimming when WholeWords is enabled.

Optional improvement: precompute the left-trim count and core length once per needle and reuse them across calls to avoid rescanning in GenerateMatch for every match occurrence. If you’d like, I can propose a small helper (e.g., ComputeWordSpan) and wire it here.

Also applies to: 288-288, 295-295


305-309: WholeWords boundary: add end-of-line symmetry for one-sided delimiters

The added condition allows delimited needles like “|Warn|” (or “at ” at index 0) to pass WholeWords checks. To handle the symmetric case at the end of the haystack (e.g., “|Warn” at end-of-message), consider also treating end-of-line as a valid non-word boundary.

Suggested change:

-                if (StringHelpers.IsWholeWord(haystack, needle, index) || ((index == 0 || !char.IsLetterOrDigit(needle[0])) && !char.IsLetterOrDigit(needle[needle.Length - 1])))
+                var startBoundaryOk = (index == 0) || !char.IsLetterOrDigit(needle[0]);
+                var endBoundaryOk = (index + needle.Length == haystack.Length) || !char.IsLetterOrDigit(needle[needle.Length - 1]);
+                if (StringHelpers.IsWholeWord(haystack, needle, index) || (startBoundaryOk && endBoundaryOk))
                     return index;

This keeps the current behavior for “|Warn|” and also supports start-only or end-only delimiter cases at the message boundaries.

If only “both-sides delimited” needles (like “|Warn|”) are intended, and one-sided cases should be ignored, please disregard this suggestion. Otherwise, I can add unit tests for start-only and end-only delimiter scenarios.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5342e9a and 0c35d8a.

📒 Files selected for processing (2)
  • src/NLog/Targets/ConsoleWordHighlightingRule.cs (2 hunks)
  • tests/NLog.UnitTests/Targets/ColoredConsoleTargetTests.cs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/NLog.UnitTests/Targets/ColoredConsoleTargetTests.cs
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: task-list-completed
  • GitHub Check: task-list-completed
🔇 Additional comments (1)
src/NLog/Targets/ConsoleWordHighlightingRule.cs (1)

245-247: Single-match path now trims delimiters correctly via GenerateMatch

Good replacement. Using GenerateMatch here ensures WholeWords highlights only the core word instead of the full needle.

@snakefoot snakefoot added this to the 6.0.4 milestone Aug 30, 2025
@sonarqubecloud
Copy link

sonarqubecloud bot commented Sep 7, 2025

@snakefoot
Copy link
Contributor Author

This was referenced Sep 12, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

console-target documentation done all docs done (wiki, api docs, lists on nlog-project.org, xmldocs) enhancement Improvement on existing feature needs documentation on wiki size/M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant