Skip to content

Commit 79e3c25

Browse files
committed
Add ESC key handler to dismiss highlights
- Add command to clear brace matching and property-argument highlights - Bind ESC key to clear highlights command (C# files only) - Add tests for ESC handler functionality - Update documentation with ESC feature
1 parent 5c192b5 commit 79e3c25

File tree

8 files changed

+115
-9
lines changed

8 files changed

+115
-9
lines changed

CLAUDE.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,13 +85,14 @@ vsce publish
8585
- **Project Setup**: package.json, TypeScript config, webpack bundling, extension entry point
8686
- **Core Parsing**: Template parser, expression parser & tokenizer, string literal parser, Serilog call detector
8787
- **Decoration-based Highlighting**: Full highlighting system with decoration manager
88+
- **Brace Matching**: Real-time brace pair highlighting with multi-line support
89+
- **Property-Argument Highlighting**: Visual connection between template properties and arguments
90+
- **Navigation Provider**: Code actions to jump from properties to their arguments
91+
- **ESC Handler**: Keyboard shortcut (ESC key) to temporarily dismiss highlights
8892
- **Performance Optimization**: Caching system, debouncing, LRU cache for templates
8993
- **Theme Management**: Automatic theme detection and WCAG AA compliant colors
9094
- **Testing Infrastructure**: Jest setup with comprehensive test coverage
9195
- **Configuration**: Extensive user customization options
92-
- **Property-Argument Highlighting**: Cursor-based highlighting showing connection between properties and arguments
93-
- **Navigation Provider**: Code actions to jump from properties to their arguments
94-
- **Brace Matching**: Highlights matching braces in all Serilog contexts (templates, expressions, output templates)
9596

9697
### 🚫 Not Implemented (by design)
9798
- **Semantic Tokens Provider**: Replaced with decoration-based approach for better control

Example/README.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,12 @@ Open `Program.cs` in Visual Studio with the Serilog Syntax extension installed t
9494
Colors automatically adapt for light themes with WCAG AA compliant contrast ratios - darker variants of the same color families for optimal readability on light backgrounds.
9595

9696
### Interactive Features
97-
- **Brace matching** when cursor is on `{` or `}` in any Serilog context
98-
- **Property-Argument highlighting** when cursor is on a property or argument
99-
- **Light bulb navigation** from properties to arguments
100-
- **Immediate highlighting** as you type (before closing quotes)
101-
- **Multi-line support** for verbatim and raw strings
97+
- **Brace matching** - Position cursor on `{` or `}` to see matching brace highlighted
98+
- **Property-argument highlighting** - Click on a property or argument to see its pair highlighted
99+
- **Light bulb navigation** - Code actions to jump from properties to arguments
100+
- **ESC to clear** - Press ESC to temporarily dismiss all highlights
101+
- **Immediate highlighting** - Updates as you type (before closing quotes)
102+
- **Multi-line support** - Works across verbatim and raw string boundaries
102103

103104
## Output
104105

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ A Visual Studio Code extension that provides syntax highlighting and enhanced su
5252
- Works in all Serilog contexts: message templates, output templates, and Serilog.Expressions
5353
- **Multi-line support** - matches braces across line boundaries in verbatim and raw strings
5454
- Uses colored, bold braces for visibility without interfering with other highlighting
55+
- **Press ESC** to temporarily dismiss brace matching highlights
5556

5657
### 🎯 Property-Argument Highlighting
5758
- **Synchronous highlighting** of template properties and their corresponding arguments
@@ -60,6 +61,7 @@ A Visual Studio Code extension that provides syntax highlighting and enhanced su
6061
- Includes quotes when highlighting string arguments (e.g., `"userId"`)
6162
- Helps visualize the connection between template properties and their values
6263
- Uses background fill to distinguish from brace matching
64+
- **Press ESC** to temporarily dismiss property-argument highlights
6365

6466
## Installation
6567

package.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,18 @@
3333
"command": "serilog.navigateToArgument",
3434
"title": "Navigate to Argument",
3535
"category": "Serilog"
36+
},
37+
{
38+
"command": "serilog.clearHighlights",
39+
"title": "Clear Highlights",
40+
"category": "Serilog"
41+
}
42+
],
43+
"keybindings": [
44+
{
45+
"command": "serilog.clearHighlights",
46+
"key": "escape",
47+
"when": "editorTextFocus && editorLangId == csharp"
3648
}
3749
],
3850
"configuration": {

src/extension.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,16 @@ export function activate(context: vscode.ExtensionContext) {
368368
});
369369
context.subscriptions.push(refreshCommand);
370370

371+
// Register ESC handler to clear highlights
372+
const clearHighlightsCommand = vscode.commands.registerCommand('serilog.clearHighlights', () => {
373+
// Clear brace matching highlights
374+
braceMatchProvider.clearHighlights();
375+
376+
// Clear property-argument highlights
377+
propertyArgumentHighlighter.clearDecorations();
378+
});
379+
context.subscriptions.push(clearHighlightsCommand);
380+
371381
// Initial update without debouncing
372382
updateDecorations();
373383

src/providers/braceMatchProvider.test.ts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,67 @@ describe('SerilogBraceMatchProvider', () => {
378378
});
379379
});
380380

381+
describe('ESC Handler', () => {
382+
test('should clear highlights when clearHighlights is called', () => {
383+
// Arrange
384+
const text = 'logger.LogInformation("User {UserId} logged in", userId);';
385+
386+
// Mock vscode window
387+
const mockSetDecorations = jest.fn();
388+
const mockEditor: any = {
389+
document: {
390+
languageId: 'csharp',
391+
lineAt: jest.fn(() => ({ text: text })),
392+
getText: jest.fn(() => text),
393+
offsetAt: jest.fn((pos: any) => pos.character),
394+
positionAt: jest.fn((offset: number) => new (vscode as any).Position(0, offset))
395+
},
396+
selection: {
397+
active: new (vscode as any).Position(0, 29) // On { of {UserId}
398+
},
399+
setDecorations: mockSetDecorations
400+
};
401+
402+
(vscode.window as any).activeTextEditor = mockEditor;
403+
404+
// Mock isSerilogCall
405+
(isSerilogCall as jest.Mock).mockReturnValue(true);
406+
407+
// Mock string parser
408+
const mockFindAllStringLiterals = jest.fn();
409+
StringLiteralParser.prototype.findAllStringLiterals = mockFindAllStringLiterals;
410+
mockFindAllStringLiterals.mockReturnValue([{
411+
type: 'regular',
412+
content: 'User {UserId} logged in',
413+
contentStart: 23,
414+
contentEnd: 47
415+
}]);
416+
417+
const provider = new SerilogBraceMatchProvider();
418+
419+
// Act - First update to set highlights
420+
provider.updateBraceMatching(mockEditor);
421+
422+
// Assert - Highlights are set
423+
expect(mockSetDecorations).toHaveBeenCalledWith(
424+
expect.anything(),
425+
expect.arrayContaining([
426+
expect.any(Object),
427+
expect.any(Object)
428+
])
429+
);
430+
431+
// Act - Clear highlights
432+
provider.clearHighlights();
433+
434+
// Assert - Highlights are cleared
435+
expect(mockSetDecorations).toHaveBeenLastCalledWith(
436+
expect.anything(),
437+
[]
438+
);
439+
});
440+
});
441+
381442
describe('Edge Cases', () => {
382443
test('should not match when cursor not on brace', () => {
383444
const lineText = 'logger.LogInformation("User {UserId} logged in", userId);';

src/providers/propertyArgumentHighlighter.test.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,25 @@ describe('PropertyArgumentHighlighter', () => {
295295
});
296296
});
297297

298+
describe('ESC Handler', () => {
299+
test('should clear decorations when clearDecorations is called', () => {
300+
// Arrange
301+
highlighter = new PropertyArgumentHighlighter();
302+
303+
// Mock active editor
304+
(vscode.window as any).activeTextEditor = mockEditor;
305+
306+
// Act - Clear decorations
307+
highlighter.clearDecorations();
308+
309+
// Assert - Decorations are cleared
310+
expect(mockSetDecorations).toHaveBeenCalledWith(
311+
expect.anything(),
312+
[]
313+
);
314+
});
315+
});
316+
298317
describe('LogError with Exception parameter', () => {
299318
test('should highlight property-argument pairs when Exception is first parameter (single-line)', () => {
300319
// Arrange

src/providers/propertyArgumentHighlighter.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ export class PropertyArgumentHighlighter implements vscode.Disposable {
407407
editor.setDecorations(this.decorationType, decorations);
408408
}
409409

410-
private clearDecorations(): void {
410+
public clearDecorations(): void {
411411
if (vscode.window.activeTextEditor) {
412412
vscode.window.activeTextEditor.setDecorations(this.decorationType, []);
413413
}

0 commit comments

Comments
 (0)