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 CHANGED
@@ -2,4 +2,8 @@
2
2
 
3
3
  ## v0.0.1 - 2024-07-03
4
4
 
5
- - Initial release
5
+ - Initial release
6
+
7
+ ## v1.2.0
8
+
9
+ - Added support for quotes, triple quotes, backticks, triple backticks.
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
- - [x] **HTML support:** Implement highlighting for nested html tags.
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.1.0",
9
+ "version": "1.2.0",
10
10
  "engines": {
11
11
  "vscode": "^1.90.0"
12
12
  },
@@ -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 backwardResult: MatchingBracket
55
- let forwardResult: MatchingBracket
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
- if (util.isCloseBracket(text.charAt(offset - 1))) {
61
- backwardResult = util.findLeftBracket(text, offset - 2)
62
- forwardResult = util.findRightBracket(text, offset - 1)
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
- backwardResult = util.findLeftBracket(text, offset)
69
- forwardResult = util.findRightBracket(text, offset + 1)
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
- backwardResult = util.findLeftBracket(text, offset - 1)
76
- forwardResult = util.findRightBracket(text, offset)
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
- backwardResult,
83
- forwardResult
123
+ leftbracket,
124
+ rightbracket
84
125
  )
85
126
 
86
- // set up the decoratiosn to highlight the scope and matching brackets
127
+ //
128
+ // Set up the decorations to highlight the scope and matching brackets
129
+ //
87
130
  if (
88
- util.isMatchingBracket(backwardResult.bracket, forwardResult.bracket) &&
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
- backwardResult.offset < text.length
93
- ? backwardResult.offset + 1
94
- : backwardResult.offset
95
- let end = forwardResult.offset
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 - 1),
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 + 1)
167
+ editor.document.positionAt(end + bracketLength)
108
168
  )
109
169
 
110
170
  var rangeDecorations = []
package/src/types.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export interface MatchingBracket {
2
2
  bracket: string
3
+ /** The offset must point the beginning of the bracket */
3
4
  offset: number
4
5
  }
5
6
 
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
- let openingBrackets = ""
5
- let closingBrackets = ""
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
- // Finds to the left the nearest open bracket using a stack.
38
- // Starting from the cursor position (index) to the beginning of the (text)
39
- function findLeftBracket(text: string, index: number): MatchingBracket {
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 offset = 0
42
- let bracket = ""
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
- bracket = char
49
- offset = i
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
- // Finds to the right the nearest open bracket using a stack.
66
- // Starting from the cursor position (index) to the end of the (text)
67
- function findRightBracket(text: string, index: number): MatchingBracket {
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 offset = text.length
70
- let bracket = ""
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
- offset = i
76
- bracket = char
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 + 1
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
- findLeftBracket,
144
- findRightBracket,
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,