code-scope-highlighter 1.1.0 β 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -1
- package/LICENSE.md +3 -3
- package/README.md +2 -2
- package/package.json +2 -2
- package/src/highlighter.ts +81 -21
- package/src/types.ts +1 -0
- package/src/util.ts +144 -23
package/CHANGELOG.md
CHANGED
package/LICENSE.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: License
|
|
3
|
-
description: MIT License for Code Highlighter
|
|
3
|
+
description: MIT License for Code Scope Highlighter
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# π License β Code Highlighter
|
|
6
|
+
# π License β Code Scope Highlighter
|
|
7
7
|
|
|
8
8
|
This project is open-source and freely available under the terms below.
|
|
9
9
|
|
|
@@ -21,4 +21,4 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
|
21
21
|
|
|
22
22
|
---
|
|
23
23
|
|
|
24
|
-
_Originally published at [github.com/joseavr/code-highlighter](https://github.com/joseavr/code-highlighter)_
|
|
24
|
+
_Originally published at [github.com/joseavr/code-scope-highlighter](https://github.com/joseavr/code-scope-highlighter)_
|
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
</p>
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
# Code Highlighter - A Highlighter Extension for Better Readability
|
|
14
|
+
# Code Scope Highlighter - A Highlighter Extension for Better Readability
|
|
15
15
|
|
|
16
16
|
A customizable scope highlighter, inspired by Dr Racket IDE.
|
|
17
17
|
|
|
@@ -76,7 +76,7 @@ The extension now supports HTML tag highlighting with intelligent cursor positio
|
|
|
76
76
|
|
|
77
77
|
## πΊοΈ Roadmap
|
|
78
78
|
|
|
79
|
-
- [
|
|
79
|
+
- [ ] **HTML support:** Implement highlighting for nested html tags.
|
|
80
80
|
- [ ] **Language Specific Settings:** Implement highlighting for specific programming languages.
|
|
81
81
|
- [ ] **Bracket Specific Settings:** Implement highlighting for specific matching bracket symbols.
|
|
82
82
|
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "code-scope-highlighter",
|
|
3
3
|
"publisher": "joseavr",
|
|
4
|
-
"displayName": "Code Highlighter",
|
|
4
|
+
"displayName": "Code Scope Highlighter",
|
|
5
5
|
"description": "Highlight the scope of matching brackets with customizable colors and flexible highlight modes.",
|
|
6
6
|
"repository": "https://github.com/joseavr/code-highlighter",
|
|
7
7
|
"icon": "code-scope-highlighter-logo.webp",
|
|
8
8
|
"license": "MIT",
|
|
9
|
-
"version": "1.
|
|
9
|
+
"version": "1.2.0",
|
|
10
10
|
"engines": {
|
|
11
11
|
"vscode": "^1.90.0"
|
|
12
12
|
},
|
package/src/highlighter.ts
CHANGED
|
@@ -51,60 +51,120 @@ class Highlighter {
|
|
|
51
51
|
const offset = editor.document.offsetAt(editor.selection.active)
|
|
52
52
|
const text = editor.document.getText()
|
|
53
53
|
|
|
54
|
-
let
|
|
55
|
-
let
|
|
54
|
+
let leftbracket: MatchingBracket
|
|
55
|
+
let rightbracket: MatchingBracket
|
|
56
|
+
|
|
57
|
+
//
|
|
58
|
+
// Triple """ or ``` - cursor after closing
|
|
59
|
+
//
|
|
60
|
+
// """..."""
|
|
61
|
+
// ^
|
|
62
|
+
//
|
|
63
|
+
if (util.isCloseTripleQuote(text, offset - 1)) {
|
|
64
|
+
leftbracket = util.findLeftOpenTripleBracket(text, offset - 4, '"""')
|
|
65
|
+
rightbracket = { bracket: '"""', offset: offset - 3 }
|
|
66
|
+
} else if (util.isCloseTripleBacktick(text, offset - 1)) {
|
|
67
|
+
leftbracket = util.findLeftOpenTripleBracket(text, offset - 4, "```")
|
|
68
|
+
rightbracket = { bracket: "```", offset: offset - 3 }
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
//
|
|
72
|
+
// Triple """ or ``` - cursor at opening
|
|
73
|
+
//
|
|
74
|
+
// """..."""
|
|
75
|
+
// ^
|
|
76
|
+
else if (util.isOpenTripleQuote(text, offset)) {
|
|
77
|
+
leftbracket = { bracket: '"""', offset: offset }
|
|
78
|
+
rightbracket = util.findRightCloseTripleBracket(text, offset + 3, '"""')
|
|
79
|
+
} else if (util.isOpenTripleBacktick(text, offset)) {
|
|
80
|
+
leftbracket = { bracket: "```", offset: offset }
|
|
81
|
+
rightbracket = util.findRightCloseTripleBracket(text, offset + 3, "```")
|
|
82
|
+
}
|
|
56
83
|
|
|
84
|
+
//
|
|
85
|
+
// Single char - cursor after closing
|
|
86
|
+
//
|
|
87
|
+
// Example:
|
|
57
88
|
// ^: cursor position
|
|
58
89
|
// (...)
|
|
59
90
|
// ^
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
91
|
+
//
|
|
92
|
+
else if (util.isCloseBracket(text.charAt(offset - 1))) {
|
|
93
|
+
leftbracket = util.findLeftOpenBracket(text, offset - 2)
|
|
94
|
+
rightbracket = util.findRightCloseBracket(text, offset - 1)
|
|
63
95
|
}
|
|
64
96
|
|
|
97
|
+
//
|
|
98
|
+
// Single char - cursor at opening
|
|
99
|
+
//
|
|
100
|
+
// Example:
|
|
65
101
|
// (...)
|
|
66
102
|
// ^
|
|
103
|
+
//
|
|
67
104
|
else if (util.isOpenBracket(text.charAt(offset))) {
|
|
68
|
-
|
|
69
|
-
|
|
105
|
+
leftbracket = util.findLeftOpenBracket(text, offset)
|
|
106
|
+
rightbracket = util.findRightCloseBracket(text, offset + 1)
|
|
70
107
|
}
|
|
71
108
|
|
|
72
|
-
//
|
|
109
|
+
//
|
|
110
|
+
// Cursor inside
|
|
111
|
+
//
|
|
112
|
+
// Example:
|
|
113
|
+
// (...)
|
|
73
114
|
// ^
|
|
74
115
|
else {
|
|
75
|
-
|
|
76
|
-
|
|
116
|
+
leftbracket = util.findLeftOpenBracket(text, offset - 1)
|
|
117
|
+
rightbracket = util.findRightCloseBracket(text, offset)
|
|
77
118
|
}
|
|
78
119
|
|
|
79
120
|
const shouldHighlight = util.shouldHighlight(
|
|
80
121
|
this.userConfigHighlightingMode,
|
|
81
122
|
offset,
|
|
82
|
-
|
|
83
|
-
|
|
123
|
+
leftbracket,
|
|
124
|
+
rightbracket
|
|
84
125
|
)
|
|
85
126
|
|
|
86
|
-
//
|
|
127
|
+
//
|
|
128
|
+
// Set up the decorations to highlight the scope and matching brackets
|
|
129
|
+
//
|
|
87
130
|
if (
|
|
88
|
-
util.isMatchingBracket(
|
|
131
|
+
util.isMatchingBracket(leftbracket.bracket, rightbracket.bracket) &&
|
|
89
132
|
shouldHighlight
|
|
90
133
|
) {
|
|
134
|
+
const bracketLength = leftbracket.bracket.length || 1
|
|
135
|
+
//
|
|
136
|
+
// Start must be the first index of the inside range
|
|
137
|
+
//
|
|
91
138
|
let start =
|
|
92
|
-
|
|
93
|
-
?
|
|
94
|
-
:
|
|
95
|
-
|
|
96
|
-
|
|
139
|
+
leftbracket.offset < text.length
|
|
140
|
+
? leftbracket.offset + bracketLength
|
|
141
|
+
: leftbracket.offset
|
|
142
|
+
//
|
|
143
|
+
// End must be the last index of the inside range + 1
|
|
144
|
+
// since vscode.Range second param is exclusive
|
|
145
|
+
//
|
|
146
|
+
let end = rightbracket.offset
|
|
147
|
+
|
|
148
|
+
//
|
|
149
|
+
// Open bracket decoration
|
|
150
|
+
//
|
|
97
151
|
const start_decoration = new vscode.Range(
|
|
98
|
-
editor.document.positionAt(start -
|
|
152
|
+
editor.document.positionAt(start - bracketLength),
|
|
99
153
|
editor.document.positionAt(start)
|
|
100
154
|
)
|
|
155
|
+
//
|
|
156
|
+
// Inside range decoration
|
|
157
|
+
//
|
|
101
158
|
const range_decoration = new vscode.Range(
|
|
102
159
|
editor.document.positionAt(start),
|
|
103
160
|
editor.document.positionAt(end)
|
|
104
161
|
)
|
|
162
|
+
//
|
|
163
|
+
// Close bracket decoration
|
|
164
|
+
//
|
|
105
165
|
const end_decoration = new vscode.Range(
|
|
106
166
|
editor.document.positionAt(end),
|
|
107
|
-
editor.document.positionAt(end +
|
|
167
|
+
editor.document.positionAt(end + bracketLength)
|
|
108
168
|
)
|
|
109
169
|
|
|
110
170
|
var rangeDecorations = []
|
package/src/types.ts
CHANGED
package/src/util.ts
CHANGED
|
@@ -1,26 +1,39 @@
|
|
|
1
1
|
import * as vscode from "vscode"
|
|
2
2
|
import { HighlighterMode, MatchingBracket } from "./types"
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
const TRIPLE_QUOTE = '"""'
|
|
5
|
+
const TRIPLE_BACKTICK = "```"
|
|
6
|
+
|
|
7
|
+
let openingBrackets: string[] = []
|
|
8
|
+
let closingBrackets: string[] = []
|
|
6
9
|
|
|
7
10
|
function updateConfig() {
|
|
8
11
|
const activeEditor = vscode.window.activeTextEditor
|
|
9
12
|
|
|
10
13
|
if (activeEditor) {
|
|
11
|
-
openingBrackets = "({["
|
|
12
|
-
closingBrackets = ")}]"
|
|
14
|
+
openingBrackets = ["`", `'`, `"`, "(", "{", "["]
|
|
15
|
+
closingBrackets = ["`", `'`, `"`, ")", "}", "]"]
|
|
13
16
|
}
|
|
14
17
|
}
|
|
15
18
|
|
|
16
19
|
function isMatchingBracket(open: string, close: string) {
|
|
17
20
|
switch (open) {
|
|
21
|
+
case TRIPLE_QUOTE:
|
|
22
|
+
return close === TRIPLE_QUOTE
|
|
23
|
+
case TRIPLE_BACKTICK:
|
|
24
|
+
return close === TRIPLE_BACKTICK
|
|
18
25
|
case "(":
|
|
19
26
|
return close === ")"
|
|
20
27
|
case "{":
|
|
21
28
|
return close === "}"
|
|
22
29
|
case "[":
|
|
23
30
|
return close === "]"
|
|
31
|
+
case `"`:
|
|
32
|
+
return close === `"`
|
|
33
|
+
case `'`:
|
|
34
|
+
return close === `'`
|
|
35
|
+
case "`":
|
|
36
|
+
return close === "`"
|
|
24
37
|
default:
|
|
25
38
|
return false
|
|
26
39
|
}
|
|
@@ -34,19 +47,62 @@ function isCloseBracket(char: string) {
|
|
|
34
47
|
return closingBrackets.includes(char)
|
|
35
48
|
}
|
|
36
49
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
50
|
+
function isCloseTripleQuote(text: string, offset: number): boolean {
|
|
51
|
+
return (
|
|
52
|
+
offset >= 3 &&
|
|
53
|
+
text.charAt(offset) === '"' &&
|
|
54
|
+
text.charAt(offset - 1) === '"' &&
|
|
55
|
+
text.charAt(offset - 2) === '"'
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function isOpenTripleQuote(text: string, offset: number): boolean {
|
|
60
|
+
return (
|
|
61
|
+
offset + 2 < text.length &&
|
|
62
|
+
text.charAt(offset) === '"' &&
|
|
63
|
+
text.charAt(offset + 1) === '"' &&
|
|
64
|
+
text.charAt(offset + 2) === '"'
|
|
65
|
+
)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function isCloseTripleBacktick(text: string, offset: number): boolean {
|
|
69
|
+
return (
|
|
70
|
+
offset >= 3 &&
|
|
71
|
+
text.charAt(offset) === "`" &&
|
|
72
|
+
text.charAt(offset - 1) === "`" &&
|
|
73
|
+
text.charAt(offset - 2) === "`"
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function isOpenTripleBacktick(text: string, offset: number): boolean {
|
|
78
|
+
return (
|
|
79
|
+
offset + 2 < text.length &&
|
|
80
|
+
text.charAt(offset) === "`" &&
|
|
81
|
+
text.charAt(offset + 1) === "`" &&
|
|
82
|
+
text.charAt(offset + 2) === "`"
|
|
83
|
+
)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Finds to the left, the nearest open bracket.
|
|
89
|
+
*
|
|
90
|
+
* Scans starting from the cursor position `index` to the beginning of the `text`
|
|
91
|
+
*
|
|
92
|
+
* @param text text from current editor tab
|
|
93
|
+
* @param index current position of the cursor in the text
|
|
94
|
+
*/
|
|
95
|
+
function findLeftOpenBracket(text: string, index: number): MatchingBracket {
|
|
40
96
|
const bracketStack = []
|
|
41
|
-
let
|
|
42
|
-
let
|
|
97
|
+
let openbracketIndex = 0
|
|
98
|
+
let openbracket = ""
|
|
43
99
|
|
|
44
100
|
for (let i = index; i >= 0; i--) {
|
|
45
101
|
let char = text.charAt(i)
|
|
46
102
|
if (isOpenBracket(char)) {
|
|
47
103
|
if (bracketStack.length === 0) {
|
|
48
|
-
|
|
49
|
-
|
|
104
|
+
openbracket = char
|
|
105
|
+
openbracketIndex = i
|
|
50
106
|
break
|
|
51
107
|
} else {
|
|
52
108
|
let top = bracketStack.pop()!
|
|
@@ -59,21 +115,28 @@ function findLeftBracket(text: string, index: number): MatchingBracket {
|
|
|
59
115
|
}
|
|
60
116
|
}
|
|
61
117
|
|
|
62
|
-
return { bracket, offset }
|
|
118
|
+
return { bracket: openbracket, offset: openbracketIndex }
|
|
63
119
|
}
|
|
64
120
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Finds to the right, the nearest close bracket.
|
|
124
|
+
*
|
|
125
|
+
* Starting from the cursor position `index` to the end of the `text`
|
|
126
|
+
*
|
|
127
|
+
* @param text text from current editor tab
|
|
128
|
+
* @param index current position of the cursor in the text
|
|
129
|
+
*/
|
|
130
|
+
function findRightCloseBracket(text: string, index: number): MatchingBracket {
|
|
68
131
|
const bracketStack = []
|
|
69
|
-
let
|
|
70
|
-
let
|
|
132
|
+
let closebracketIndex = text.length
|
|
133
|
+
let closebracket = ""
|
|
71
134
|
for (let i = index; i < text.length; i++) {
|
|
72
135
|
let char = text.charAt(i)
|
|
73
136
|
if (isCloseBracket(char)) {
|
|
74
137
|
if (bracketStack.length === 0) {
|
|
75
|
-
|
|
76
|
-
|
|
138
|
+
closebracketIndex = i
|
|
139
|
+
closebracket = char
|
|
77
140
|
break
|
|
78
141
|
} else {
|
|
79
142
|
let top = bracketStack.pop()!
|
|
@@ -86,7 +149,58 @@ function findRightBracket(text: string, index: number): MatchingBracket {
|
|
|
86
149
|
}
|
|
87
150
|
}
|
|
88
151
|
|
|
89
|
-
return { bracket, offset }
|
|
152
|
+
return { bracket: closebracket, offset: closebracketIndex }
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Finds the matching opening triple bracket (""" or ```) to the left.
|
|
157
|
+
* Use when cursor is after a closing triple.
|
|
158
|
+
*/
|
|
159
|
+
function findLeftOpenTripleBracket(
|
|
160
|
+
text: string,
|
|
161
|
+
startIndex: number,
|
|
162
|
+
triple: string
|
|
163
|
+
): MatchingBracket {
|
|
164
|
+
const char = triple.charAt(0)
|
|
165
|
+
|
|
166
|
+
for (let i = startIndex; i >= 0; i--) {
|
|
167
|
+
if (
|
|
168
|
+
text.length > i + 2 &&
|
|
169
|
+
text.charAt(i) === char &&
|
|
170
|
+
text.charAt(i + 1) === char &&
|
|
171
|
+
text.charAt(i + 2) === char
|
|
172
|
+
) {
|
|
173
|
+
return { bracket: triple, offset: i }
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// if not found
|
|
178
|
+
return { bracket: "", offset: 0 }
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Finds the matching closing triple bracket (""" or ```) to the right.
|
|
183
|
+
* Use when cursor is after an opening triple.
|
|
184
|
+
*/
|
|
185
|
+
function findRightCloseTripleBracket(
|
|
186
|
+
text: string,
|
|
187
|
+
startIndex: number,
|
|
188
|
+
triple: string
|
|
189
|
+
): MatchingBracket {
|
|
190
|
+
const char = triple.charAt(0)
|
|
191
|
+
|
|
192
|
+
for (let i = startIndex; i < text.length; i++) {
|
|
193
|
+
if (
|
|
194
|
+
text.length > i + 2 &&
|
|
195
|
+
text.charAt(i) === char &&
|
|
196
|
+
text.charAt(i + 1) === char &&
|
|
197
|
+
text.charAt(i + 2) === char
|
|
198
|
+
) {
|
|
199
|
+
return { bracket: triple, offset: i }
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return { bracket: "", offset: text.length }
|
|
90
204
|
}
|
|
91
205
|
|
|
92
206
|
function shouldHighlight(
|
|
@@ -98,9 +212,10 @@ function shouldHighlight(
|
|
|
98
212
|
switch (highlighterMode) {
|
|
99
213
|
// highlight only when the cursor is next to the matching bracket
|
|
100
214
|
case HighlighterMode.Near:
|
|
215
|
+
const bracketLength = rightMatchingBracket.bracket.length || 1
|
|
101
216
|
return (
|
|
102
217
|
offset === leftMatchingBracket.offset ||
|
|
103
|
-
offset === rightMatchingBracket.offset +
|
|
218
|
+
offset === rightMatchingBracket.offset + bracketLength
|
|
104
219
|
)
|
|
105
220
|
case HighlighterMode.Always:
|
|
106
221
|
return true
|
|
@@ -140,8 +255,14 @@ export default {
|
|
|
140
255
|
isMatchingBracket,
|
|
141
256
|
isOpenBracket,
|
|
142
257
|
isCloseBracket,
|
|
143
|
-
|
|
144
|
-
|
|
258
|
+
isCloseTripleQuote,
|
|
259
|
+
isOpenTripleQuote,
|
|
260
|
+
isCloseTripleBacktick,
|
|
261
|
+
isOpenTripleBacktick,
|
|
262
|
+
findLeftOpenBracket,
|
|
263
|
+
findRightCloseBracket,
|
|
264
|
+
findLeftOpenTripleBracket,
|
|
265
|
+
findRightCloseTripleBracket,
|
|
145
266
|
shouldHighlight,
|
|
146
267
|
setRangeStyle,
|
|
147
268
|
setEndStyle,
|