@lvce-editor/shared-process 0.7.12 → 0.8.1

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.
Files changed (27) hide show
  1. package/config/defaultKeyBindings.json +10 -0
  2. package/config/defaultSettings.json +2 -0
  3. package/extensions/builtin.language-basics-elm/src/tokenizeElm.js +276 -6
  4. package/extensions/builtin.language-basics-graphql/README.md +14 -0
  5. package/extensions/builtin.language-basics-graphql/extension.json +12 -0
  6. package/extensions/builtin.language-basics-graphql/src/tokenizeGraphql.js +28 -0
  7. package/extensions/builtin.language-basics-r/README.md +14 -0
  8. package/extensions/builtin.language-basics-r/extension.json +12 -0
  9. package/extensions/builtin.language-basics-r/src/tokenizeR.js +71 -0
  10. package/extensions/builtin.language-basics-shellscript/src/tokenizeShellScript.js +3 -14
  11. package/extensions/builtin.language-basics-toml/extension.json +2 -9
  12. package/extensions/builtin.language-basics-toml/src/tokenizeToml.js +5 -15
  13. package/extensions/builtin.theme-cobalt2/README.md +18 -0
  14. package/extensions/builtin.theme-cobalt2/color-theme.json +135 -0
  15. package/extensions/builtin.theme-cobalt2/extension.json +12 -0
  16. package/extensions/builtin.theme-gruvbox/README.md +18 -0
  17. package/extensions/builtin.theme-gruvbox/color-theme.json +173 -0
  18. package/extensions/builtin.theme-gruvbox/extension.json +12 -0
  19. package/extensions/builtin.theme-slime/README.md +1 -1
  20. package/extensions/builtin.vscode-icons/icon.png +0 -0
  21. package/package.json +3 -3
  22. package/src/parts/ExtensionManagement/ExtensionManagement.ipc.js +2 -1
  23. package/src/parts/ExtensionManagement/ExtensionManagement.js +4 -130
  24. package/src/parts/ExtensionManagement/ExtensionManagementColorTheme.js +38 -12
  25. package/src/parts/FileSystemWatch/FileSystemWatch.js +6 -0
  26. package/src/parts/ModuleMap/ModuleMap.js +1 -0
  27. package/src/parts/RequiresSocket/RequiresSocket.js +1 -0
@@ -307,6 +307,16 @@
307
307
  "command": "Extensions.focusNext",
308
308
  "when": "focus.Extensions"
309
309
  },
310
+ {
311
+ "key": "Space",
312
+ "command": "Extensions.handleClickCurrentButKeepFocus",
313
+ "when": "focus.Extensions"
314
+ },
315
+ {
316
+ "key": "Enter",
317
+ "command": "Extensions.handleClickCurrent",
318
+ "when": "focus.Extensions"
319
+ },
310
320
  {
311
321
  "key": "ctrl+Space",
312
322
  "command": "Extensions.toggleSuggest",
@@ -1,6 +1,8 @@
1
1
  {
2
2
  "completions.loadingDelay": 1200,
3
3
 
4
+ "development.watchColorTheme": true,
5
+
4
6
  "editor.fontSize": 15,
5
7
  "editor.fontFamily": "'Fira Code'",
6
8
  "editor.lineHeight": 20,
@@ -1,28 +1,298 @@
1
+ /**
2
+ * @enum number
3
+ */
4
+ export const State = {
5
+ TopLevelContent: 1,
6
+ Keyword: 2,
7
+ AfterKeyword: 3,
8
+ InsideBlockComment: 4,
9
+ AfterKeywordImport: 5,
10
+ AfterKeywordImportAfterWhitespace: 6,
11
+ AfterTypeColon: 7,
12
+ AfterKeywordType: 8,
13
+ AfterKeywordTypeAfterWhitespace: 9,
14
+ InsideTypeRightHandSide: 10,
15
+ AfterTypeName: 11,
16
+ AfterTypeNameAfterWhitespace: 12,
17
+ InsideLineComment: 13,
18
+ AfterKeywordModule: 14,
19
+ AfterModuleName: 15,
20
+ }
21
+
22
+ export const StateMap = {
23
+ [State.TopLevelContent]: 'TopLevelContent',
24
+ }
25
+
1
26
  /**
2
27
  * @enum number
3
28
  */
4
29
  export const TokenType = {
5
- Text: 1,
30
+ None: 1,
31
+ Whitespace: 2,
32
+ PunctuationString: 3,
33
+ String: 4,
34
+ Keyword: 5,
35
+ Numeric: 6,
36
+ Punctuation: 7,
37
+ VariableName: 8,
38
+ Comment: 885,
39
+ Text: 9,
40
+ LanguageConstantBoolean: 10,
41
+ Definition: 11,
42
+ Type: 12,
43
+ KeywordImport: 14,
6
44
  }
7
45
 
8
46
  export const TokenMap = {
47
+ [TokenType.None]: 'None',
48
+ [TokenType.Whitespace]: 'Whitespace',
49
+ [TokenType.PunctuationString]: 'PunctuationString',
50
+ [TokenType.String]: 'String',
51
+ [TokenType.Keyword]: 'Keyword',
52
+ [TokenType.Numeric]: 'Numeric',
53
+ [TokenType.Punctuation]: 'Punctuation',
54
+ [TokenType.VariableName]: 'VariableName',
55
+ [TokenType.Comment]: 'Comment',
9
56
  [TokenType.Text]: 'Text',
57
+ [TokenType.LanguageConstantBoolean]: 'LanguageConstantBoolean',
58
+ [TokenType.Definition]: 'Type',
59
+ [TokenType.Type]: 'TypeName',
60
+ [TokenType.Type]: 'Type',
61
+ [TokenType.KeywordImport]: 'KeywordImport',
10
62
  }
11
63
 
12
64
  export const initialLineState = {
13
- state: 1,
14
- tokens: [],
65
+ state: State.TopLevelContent,
15
66
  }
16
67
 
68
+ const RE_WHITESPACE = /^\s+/
69
+ const RE_WHITESPACE_SINGLE_LINE = /^( |\t)+/
70
+ const RE_WHITESPACE_NEWLINE = /^\n/
71
+ const RE_CONSTANT = /^(true|false|null)/
72
+ const RE_STRING_DOUBLE_QUOTE_CONTENT = /^[^"\n]+/
73
+ const RE_STRING_SINGLE_QUOTE_CONTENT = /^[^'\n]+/
74
+ const RE_DOUBLE_QUOTE = /^"/
75
+ const RE_CURLY_OPEN = /^\{/
76
+ const RE_CURLY_CLOSE = /^\}/
77
+ const RE_SQUARE_OPEN = /^\[/
78
+ const RE_SQUARE_CLOSE = /^\]/
79
+ const RE_COMMA = /^,/
80
+ const RE_COLON = /^:/
81
+ const RE_NUMERIC =
82
+ /^((0(x|X)[0-9a-fA-F]*)|(([0-9]+\.?[0-9]*)|(\.[0-9]+))((e|E)(\+|-)?[0-9]+)?)\b/
83
+
84
+ const RE_KEYWORD =
85
+ /^(?:where|type|True|then|port|of|module|let|in|import|if|False|exposing|else|case|as)\b/
86
+ const RE_LANGUAGE_CONSTANT = /^(?:True|False)\b/
87
+ const RE_IMPORT = /^[a-zA-Z\.]+/
88
+ const RE_SEMICOLON = /^;/
89
+ const RE_VARIABLE_NAME = /^[a-zA-Z][a-zA-Z\d\_\-]*/
90
+ const RE_ROUND_OPEN = /^\(/
91
+ const RE_ROUND_CLOSE = /^\)/
92
+ const RE_DOT = /^\./
93
+ const RE_EQUAL_SIGN = /^=/
94
+ const RE_SINGLE_QUOTE = /^'/
95
+ const RE_LINE_COMMENT = /^\-\-[^\n]*/
96
+ const RE_BLOCK_COMMENT_START = /^\{\-/
97
+ const RE_BLOCK_COMMENT_END = /^\-\}/
98
+ const RE_BLOCK_COMMENT_CONTENT = /^.+(?=\-\})/s
99
+ const RE_PUNCTUATION = /^(?:\(|\)|\[|\]|\||\->)/
100
+ const RE_WORD_ALIAS = /^alias/
101
+ const RE_ANYTHING_UNTIL_END = /^.+/s
102
+
17
103
  export const hasArrayReturn = true
18
104
 
19
105
  /**
20
106
  * @param {string} line
107
+ * @param {any} lineState
21
108
  */
22
- export const tokenizeLine = (line) => {
23
- const tokens = [TokenType.Text, line.length]
109
+ export const tokenizeLine = (line, lineState) => {
110
+ let next = null
111
+ let index = 0
112
+ let tokens = []
113
+ let token = TokenType.None
114
+ let state = lineState.state
115
+ while (index < line.length) {
116
+ const part = line.slice(index)
117
+ switch (state) {
118
+ case State.TopLevelContent:
119
+ if ((next = part.match(RE_WHITESPACE))) {
120
+ token = TokenType.Whitespace
121
+ state = State.TopLevelContent
122
+ } else if ((next = part.match(RE_KEYWORD))) {
123
+ state = State.Keyword
124
+ continue
125
+ } else if ((next = part.match(RE_VARIABLE_NAME))) {
126
+ token = TokenType.VariableName
127
+ state = State.TopLevelContent
128
+ } else if ((next = part.match(RE_LINE_COMMENT))) {
129
+ token = TokenType.Comment
130
+ state = State.TopLevelContent
131
+ } else if ((next = part.match(RE_BLOCK_COMMENT_START))) {
132
+ token = TokenType.Comment
133
+ state = State.InsideBlockComment
134
+ } else if ((next = part.match(RE_COLON))) {
135
+ token = TokenType.Punctuation
136
+ state = State.AfterTypeColon
137
+ } else if ((next = part.match(RE_PUNCTUATION))) {
138
+ token = TokenType.Punctuation
139
+ state = State.TopLevelContent
140
+ } else if ((next = part.match(RE_ANYTHING_UNTIL_END))) {
141
+ token = TokenType.Text
142
+ state = State.TopLevelContent
143
+ } else {
144
+ part.startsWith('Bool') //?
145
+ throw new Error('no')
146
+ }
147
+ break
148
+ case State.InsideBlockComment:
149
+ if ((next = part.match(RE_BLOCK_COMMENT_END))) {
150
+ token = TokenType.Comment
151
+ state = State.TopLevelContent
152
+ } else if ((next = part.match(RE_BLOCK_COMMENT_CONTENT))) {
153
+ token = TokenType.Comment
154
+ state = State.InsideBlockComment
155
+ } else if ((next = part.match(RE_ANYTHING_UNTIL_END))) {
156
+ token = TokenType.Comment
157
+ state = State.InsideBlockComment
158
+ } else {
159
+ part //?
160
+ throw new Error('no')
161
+ }
162
+ break
163
+ case State.Keyword:
164
+ const keyword = next[0]
165
+ switch (keyword) {
166
+ case 'import':
167
+ case 'exposing':
168
+ token = TokenType.Keyword
169
+ state = State.TopLevelContent
170
+ break
171
+ case 'False':
172
+ case 'True':
173
+ token = TokenType.LanguageConstantBoolean
174
+ state = State.TopLevelContent
175
+ break
176
+ case 'type':
177
+ token = TokenType.Keyword
178
+ state = State.AfterKeywordType
179
+ break
180
+ case 'module':
181
+ token = TokenType.KeywordImport
182
+ state = State.AfterKeywordModule
183
+ break
184
+ case 'port':
185
+ token = TokenType.Keyword
186
+ state = State.TopLevelContent
187
+ break
188
+ default:
189
+ throw new Error('no')
190
+ }
191
+ break
192
+ case State.AfterKeywordType:
193
+ if ((next = part.match(RE_WHITESPACE))) {
194
+ token = TokenType.Whitespace
195
+ state = State.AfterKeywordTypeAfterWhitespace
196
+ } else {
197
+ throw new Error('no')
198
+ }
199
+ break
200
+ case State.AfterKeywordTypeAfterWhitespace:
201
+ if ((next = part.match(RE_WORD_ALIAS))) {
202
+ token = TokenType.Keyword
203
+ state = State.AfterKeywordType
204
+ } else if ((next = part.match(RE_VARIABLE_NAME))) {
205
+ token = TokenType.Type
206
+ state = State.AfterTypeName
207
+ } else {
208
+ part //?
209
+ throw new Error('no')
210
+ }
211
+ break
212
+ case State.AfterTypeName:
213
+ if ((next = part.match(RE_WHITESPACE))) {
214
+ token = TokenType.Whitespace
215
+ state = State.AfterTypeNameAfterWhitespace
216
+ } else {
217
+ throw new Error('no')
218
+ }
219
+ break
220
+ case State.AfterTypeNameAfterWhitespace:
221
+ if ((next = part.match(RE_EQUAL_SIGN))) {
222
+ token = TokenType.Punctuation
223
+ state = State.InsideTypeRightHandSide
224
+ } else {
225
+ part //?
226
+ part.startsWith('M') //?
227
+ throw new Error('no')
228
+ }
229
+ break
230
+ case State.InsideTypeRightHandSide:
231
+ if ((next = part.match(RE_VARIABLE_NAME))) {
232
+ token = TokenType.Type
233
+ state = State.InsideTypeRightHandSide
234
+ } else if ((next = part.match(RE_WHITESPACE))) {
235
+ token = TokenType.Whitespace
236
+ state = State.InsideTypeRightHandSide
237
+ } else if ((next = part.match(RE_PUNCTUATION))) {
238
+ token = TokenType.Punctuation
239
+ state = State.InsideTypeRightHandSide
240
+ } else {
241
+ part //?
242
+ throw new Error('no')
243
+ }
244
+ break
245
+ case State.AfterTypeColon:
246
+ if ((next = part.match(RE_WHITESPACE_SINGLE_LINE))) {
247
+ token = TokenType.Whitespace
248
+ state = State.AfterTypeColon
249
+ } else if ((next = part.match(RE_VARIABLE_NAME))) {
250
+ token = TokenType.Type
251
+ state = State.AfterTypeColon
252
+ } else if ((next = part.match(RE_WHITESPACE_NEWLINE))) {
253
+ token = TokenType.Whitespace
254
+ state = State.TopLevelContent
255
+ } else if ((next = part.match(RE_PUNCTUATION))) {
256
+ token = TokenType.Punctuation
257
+ state = State.AfterTypeColon
258
+ } else {
259
+ part //?
260
+ throw new Error('no')
261
+ }
262
+ break
263
+ case State.AfterKeywordModule:
264
+ if ((next = part.match(RE_WHITESPACE))) {
265
+ token = TokenType.Whitespace
266
+ state = State.AfterKeywordModule
267
+ } else if ((next = part.match(RE_VARIABLE_NAME))) {
268
+ token = TokenType.VariableName
269
+ state = State.AfterModuleName
270
+ } else {
271
+ throw new Error('no')
272
+ }
273
+ break
274
+ case State.AfterModuleName:
275
+ if ((next = part.match(RE_WHITESPACE))) {
276
+ token = TokenType.Whitespace
277
+ state = State.TopLevelContent
278
+ } else {
279
+ throw new Error('no')
280
+ }
281
+ break
282
+ default:
283
+ throw new Error('no')
284
+ }
285
+ const tokenLength = next[0].length
286
+ index += tokenLength
287
+ tokens.push(token, tokenLength)
288
+ }
289
+ if (state === State.InsideLineComment) {
290
+ state = State.TopLevelContent
291
+ }
24
292
  return {
25
- state: 1,
293
+ state,
26
294
  tokens,
27
295
  }
28
296
  }
297
+
298
+ tokenizeLine(`port module Main exposing (..)`, initialLineState)
@@ -0,0 +1,14 @@
1
+ # Language Basics Graphql
2
+
3
+ ## Contributing
4
+
5
+ ```sh
6
+ git clone git@github.com:lvce-editor/language-basics-graphql.git &&
7
+ cd language-basics-graphql &&
8
+ npm ci &&
9
+ npm test
10
+ ```
11
+
12
+ ## Gitpod
13
+
14
+ [![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/lvce-editor/language-basics-graphql)
@@ -0,0 +1,12 @@
1
+ {
2
+ "id": "builtin.language-basics-graphql",
3
+ "name": "Language Basics Graphql",
4
+ "description": "Provides syntax highlighting and bracket matching in Graphql files.",
5
+ "languages": [
6
+ {
7
+ "id": "graphql",
8
+ "extensions": [".gql"],
9
+ "tokenize": "src/tokenizeGraphql.js"
10
+ }
11
+ ]
12
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * @enum number
3
+ */
4
+ export const TokenType = {
5
+ Text: 1,
6
+ }
7
+
8
+ export const TokenMap = {
9
+ [TokenType.Text]: 'Text',
10
+ }
11
+
12
+ export const initialLineState = {
13
+ state: 1,
14
+ tokens: [],
15
+ }
16
+
17
+ export const hasArrayReturn = true
18
+
19
+ /**
20
+ * @param {string} line
21
+ */
22
+ export const tokenizeLine = (line) => {
23
+ const tokens = [TokenType.Text, line.length]
24
+ return {
25
+ state: 1,
26
+ tokens,
27
+ }
28
+ }
@@ -0,0 +1,14 @@
1
+ # Language Basics R
2
+
3
+ ## Contributing
4
+
5
+ ```sh
6
+ git clone git@github.com:lvce-editor/language-basics-r.git &&
7
+ cd language-basics-r &&
8
+ npm ci &&
9
+ npm test
10
+ ```
11
+
12
+ ## Gitpod
13
+
14
+ [![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/lvce-editor/language-basics-r)
@@ -0,0 +1,12 @@
1
+ {
2
+ "id": "builtin.language-basics-r",
3
+ "name": "Language Basics R",
4
+ "description": "Provides syntax highlighting and bracket matching in R files.",
5
+ "languages": [
6
+ {
7
+ "id": "r",
8
+ "extensions": [".r", ".rhistory", ".rprofile", ".rt"],
9
+ "tokenize": "src/tokenizeR.js"
10
+ }
11
+ ]
12
+ }
@@ -0,0 +1,71 @@
1
+ /**
2
+ * @enum number
3
+ */
4
+ export const State = {
5
+ TopLevelContent: 1,
6
+ InsideString: 2,
7
+ InsideLineComment: 3,
8
+ }
9
+
10
+ /**
11
+ * @enum number
12
+ */
13
+ export const TokenType = {
14
+ None: 0,
15
+ Text: 1,
16
+ Function: 2,
17
+ }
18
+
19
+ export const TokenMap = {
20
+ [TokenType.Text]: 'Text',
21
+ [TokenType.Function]: 'Function',
22
+ }
23
+
24
+ export const initialLineState = {
25
+ state: State.TopLevelContent,
26
+ tokens: [],
27
+ }
28
+
29
+ export const hasArrayReturn = true
30
+
31
+ const RE_BUILTIN_FUNCTION =
32
+ /^(?:abbreviate|abline|abs|acf2AR|acos|acosh|addmargins|addNA|addTaskCallback|addNextMethod|addNextCallback|adist|adjustcolor|aggregate|agrep|agrepl|alarm|alist|all\.equal|all|allGenerics|approx|approxfun|apropos|aregexc|argsAnywhere|arrows|as\.data\.frame|as\.Date|as\.double|as\.factor|as\.name|as\.numeric|as\.ordered|as\.single|assocplot|attach|attr|attributes|ave|axis|barplot|body|box|boxplot|browser|call|classLabel|classMetaName|className|completeSubclasses|doPrimitiveMethod|emptyMethodsList)\b/
33
+ const RE_ANYTHING = /^.+/s
34
+
35
+ /**
36
+ * @param {string} line
37
+ * @param {any} lineState
38
+ */
39
+ export const tokenizeLine = (line, lineState) => {
40
+ let next = null
41
+ let index = 0
42
+ let tokens = []
43
+ let token = TokenType.None
44
+ let state = lineState.state
45
+ while (index < line.length) {
46
+ const part = line.slice(index)
47
+ switch (state) {
48
+ case State.TopLevelContent:
49
+ if ((next = part.match(RE_BUILTIN_FUNCTION))) {
50
+ token = TokenType.Function
51
+ state = State.TopLevelContent
52
+ } else if ((next = part.match(RE_ANYTHING))) {
53
+ token = TokenType.Text
54
+ state = State.TopLevelContent
55
+ } else {
56
+ part //?
57
+ throw new Error('no')
58
+ }
59
+ break
60
+ default:
61
+ throw new Error('no')
62
+ }
63
+ const tokenLength = next[0].length
64
+ index += tokenLength
65
+ tokens.push(token, tokenLength)
66
+ }
67
+ return {
68
+ state,
69
+ tokens,
70
+ }
71
+ }
@@ -40,7 +40,7 @@ export const TokenMap = {
40
40
  [TokenType.Text]: 'Text',
41
41
  }
42
42
 
43
- const RE_LINE_COMMENT_START = /^#/
43
+ const RE_LINE_COMMENT = /^#.*/s
44
44
  const RE_SELECTOR = /^[\.a-zA-Z\d\-\:>]+/
45
45
  const RE_WHITESPACE = /^ +/
46
46
  const RE_CURLY_OPEN = /^\{/
@@ -110,9 +110,9 @@ export const tokenizeLine = (line, lineState) => {
110
110
  } else if ((next = part.match(RE_QUOTE_DOUBLE))) {
111
111
  token = TokenType.PunctuationString
112
112
  state = State.InsideString
113
- } else if ((next = part.match(RE_LINE_COMMENT_START))) {
113
+ } else if ((next = part.match(RE_LINE_COMMENT))) {
114
114
  token = TokenType.Comment
115
- state = State.InsideLineComment
115
+ state = State.TopLevelContent
116
116
  } else if ((next = part.match(RE_ANYTHING))) {
117
117
  token = TokenType.Text
118
118
  state = State.TopLevelContent
@@ -132,14 +132,6 @@ export const tokenizeLine = (line, lineState) => {
132
132
  throw new Error('no')
133
133
  }
134
134
  break
135
- case State.InsideLineComment:
136
- if ((next = part.match(RE_ANYTHING))) {
137
- token = TokenType.Comment
138
- state = State.TopLevelContent
139
- } else {
140
- throw new Error('no')
141
- }
142
- break
143
135
  default:
144
136
  throw new Error('no')
145
137
  }
@@ -147,9 +139,6 @@ export const tokenizeLine = (line, lineState) => {
147
139
  index += tokenLength
148
140
  tokens.push(token, tokenLength)
149
141
  }
150
- if (state === State.InsideLineComment) {
151
- state = State.TopLevelContent
152
- }
153
142
  return {
154
143
  state,
155
144
  tokens,
@@ -6,15 +6,8 @@
6
6
  "languages": [
7
7
  {
8
8
  "id": "toml",
9
- "extensions": [
10
- ".toml",
11
- ".tml",
12
- ".replit"
13
- ],
14
- "fileNames": [
15
- "Cargo.lock",
16
- "Gopkg.lock"
17
- ],
9
+ "extensions": [".toml", ".tml", ".replit"],
10
+ "fileNames": ["Cargo.lock", "Gopkg.lock"],
18
11
  "tokenize": "src/tokenizeToml.js"
19
12
  }
20
13
  ]
@@ -3,7 +3,6 @@
3
3
  */
4
4
  export const State = {
5
5
  TopLevelContent: 1,
6
- InsideLineComment: 2,
7
6
  AfterPropertyName: 3,
8
7
  AfterPropertyNameAfterEqualSign: 4,
9
8
  InsideString: 5,
@@ -11,7 +10,6 @@ export const State = {
11
10
 
12
11
  export const StateMap = {
13
12
  [State.TopLevelContent]: 'TopLevelContent',
14
- [State.InsideLineComment]: 'InsideLineComment',
15
13
  }
16
14
 
17
15
  /**
@@ -53,7 +51,7 @@ export const TokenMap = {
53
51
  [TokenType.String]: 'String',
54
52
  }
55
53
 
56
- const RE_LINE_COMMENT_START = /^#/
54
+ const RE_LINE_COMMENT = /^#.*/s
57
55
  const RE_WHITESPACE = /^ +/
58
56
  const RE_CURLY_OPEN = /^\{/
59
57
  const RE_CURLY_CLOSE = /^\}/
@@ -113,9 +111,9 @@ export const tokenizeLine = (line, lineState) => {
113
111
  if ((next = part.match(RE_PROPERTY_NAME))) {
114
112
  token = TokenType.PropertyName
115
113
  state = State.AfterPropertyName
116
- } else if ((next = part.match(RE_LINE_COMMENT_START))) {
114
+ } else if ((next = part.match(RE_LINE_COMMENT))) {
117
115
  token = TokenType.Comment
118
- state = State.InsideLineComment
116
+ state = State.TopLevelContent
119
117
  } else if ((next = part.match(RE_WHITESPACE))) {
120
118
  token = TokenType.Whitespace
121
119
  state = State.TopLevelContent
@@ -127,14 +125,6 @@ export const tokenizeLine = (line, lineState) => {
127
125
  throw new Error('no')
128
126
  }
129
127
  break
130
- case State.InsideLineComment:
131
- if ((next = part.match(RE_ANYTHING))) {
132
- token = TokenType.Comment
133
- state = State.TopLevelContent
134
- } else {
135
- throw new Error('no')
136
- }
137
- break
138
128
  case State.AfterPropertyName:
139
129
  if ((next = part.match(RE_EQUAL_SIGN))) {
140
130
  token = TokenType.Punctuation
@@ -162,9 +152,9 @@ export const tokenizeLine = (line, lineState) => {
162
152
  } else if ((next = part.match(RE_NUMERIC_FLOAT))) {
163
153
  token = TokenType.Numeric
164
154
  state = State.TopLevelContent
165
- } else if ((next = part.match(RE_LINE_COMMENT_START))) {
155
+ } else if ((next = part.match(RE_LINE_COMMENT))) {
166
156
  token = TokenType.Comment
167
- state = State.InsideLineComment
157
+ state = State.TopLevelContent
168
158
  } else if ((next = part.match(RE_NAN))) {
169
159
  token = TokenType.Numeric
170
160
  state = State.TopLevelContent
@@ -0,0 +1,18 @@
1
+ # Theme Cobalt2
2
+
3
+ ## Contributing
4
+
5
+ ```sh
6
+ git clone git@github.com:lvce-editor/theme-cobalt2.git &&
7
+ cd theme-cobalt2 &&
8
+ npm ci &&
9
+ npm run dev
10
+ ```
11
+
12
+ ## Gitpod
13
+
14
+ [![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/lvce-editor/theme-cobalt2)
15
+
16
+ ## Credits
17
+
18
+ Extension is based on https://github.com/wesbos/cobalt2-vscode by @wesbos (License MIT)
@@ -0,0 +1,135 @@
1
+ {
2
+ "type": "dark",
3
+ "colors": {
4
+ "ActivityBarBackground": "#122738",
5
+ "ActivityBarActiveForeground": "rgb(255, 255, 255)",
6
+ "ActivityBarForeground": "rgba(255, 255, 255, 0.4)",
7
+
8
+ "BadgeBackground": "#ffc600",
9
+ "BadgeForeground": "#000",
10
+
11
+ "ContextMenuBackground": "#122738",
12
+ "ContextMenuForeground": "rgb(255, 255, 255)",
13
+
14
+ "EditorBackGround": "",
15
+ "EditorScrollBarBackground": "rgba(64, 97, 121, 0.8)",
16
+ "EditorCursorBackground": "#ffc600",
17
+ "EditorSelectionBackground": "#0050a4",
18
+
19
+ "FocusOutline": "#0d3a58",
20
+
21
+ "InputBoxBackground": "#193549",
22
+ "InputBoxForeground": "#ffc600",
23
+
24
+ "ListActiveSelectionBackground": "#193549",
25
+ "ListActiveSelectionForeground": "#aaa",
26
+ "ListHoverBackground": "#193549",
27
+ "ListHoverForeground": "#aaa",
28
+ "ListInactiveSelectionBackground": "",
29
+ "ListForeground": "rgb(170, 170, 170)",
30
+
31
+ "MainBackground": "#193549",
32
+
33
+ "MenuBackground": "rgb(18, 39, 56)",
34
+ "MenuItemHoverBackground": "rgb(25, 53, 73)",
35
+
36
+ "PanelBackground": "#122738",
37
+ "PanelBorderTopColor": "#ffc600",
38
+ "PanelTabHoverForeground": "rgb(255, 198, 0)",
39
+ "PanelTabForeground": "rgb(170, 170, 170)",
40
+
41
+ "QuickPickBackground": "rgb(21, 35, 45)",
42
+ "QuickPickInputBackground": "",
43
+
44
+ "SideBarBackground": "#15232d",
45
+
46
+ "StatusBarBackground": "#15232d",
47
+ "StatusBarBorderTopColor": "#0d3a58",
48
+
49
+ "TabActiveForeground": "rgb(255, 255, 255)",
50
+ "TabForeground": "rgb(170, 170, 170)",
51
+ "TabActiveBackground": "rgb(25, 53, 73)",
52
+ "TabInactiveBackground": "",
53
+
54
+ "TabsBackground": "rgb(18, 39, 56)",
55
+
56
+ "TitleBarBackground": "#15232D",
57
+ "TitleBarBorderBottomColor": "",
58
+ "TitleBarColor": "",
59
+ "TitleBarColorInactive": "rgba(204, 204, 204, 0.6)"
60
+ },
61
+ "tokenColors": [
62
+ {
63
+ "name": "CssSelector",
64
+ "foreground": "#3AD900"
65
+ },
66
+ {
67
+ "name": "CssPropertyName",
68
+ "foreground": "#A5FF90"
69
+ },
70
+ {
71
+ "name": "CssPropertyValue",
72
+ "foreground": "#FFEE80"
73
+ },
74
+ {
75
+ "name": "TagName",
76
+ "foreground": "#9EFFFF"
77
+ },
78
+ {
79
+ "name": "AttributeName",
80
+ "foreground": "#FFC600"
81
+ },
82
+ {
83
+ "name": "String",
84
+ "foreground": "#A5FF90"
85
+ },
86
+ {
87
+ "name": "PunctuationString",
88
+ "foreground": "#92FC79"
89
+ },
90
+ {
91
+ "name": "JsonPropertyName",
92
+ "foreground": "#FFC600"
93
+ },
94
+ {
95
+ "name": "LanguageConstant",
96
+ "foreground": "#FF628C"
97
+ },
98
+ {
99
+ "name": "Keyword",
100
+ "foreground": "#FFC600"
101
+ },
102
+ {
103
+ "name": "Numeric",
104
+ "foreground": "#FF628C"
105
+ },
106
+ {
107
+ "name": "KeywordImport",
108
+ "foreground": "#FF9D00"
109
+ },
110
+ {
111
+ "name": "Type",
112
+ "foreground": "#80FFBB"
113
+ },
114
+ {
115
+ "name": "Macro",
116
+ "foreground": "#FF9D00"
117
+ },
118
+ {
119
+ "name": "KeywordControl",
120
+ "foreground": "#FF9D00"
121
+ },
122
+ {
123
+ "name": "Regex",
124
+ "foreground": "#9EFFFF"
125
+ },
126
+ {
127
+ "name": "Function",
128
+ "foreground": "#ffc600"
129
+ },
130
+ {
131
+ "name": "Comment",
132
+ "foreground": "#0088FF"
133
+ }
134
+ ]
135
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "id": "builtin.theme-cobalt2",
3
+ "name": "Cobalt 2 Theme",
4
+ "description": "🔥 Official theme by Wes Bos.",
5
+ "colorThemes": [
6
+ {
7
+ "id": "cobalt2",
8
+ "label": "Cobalt 2",
9
+ "path": "color-theme.json"
10
+ }
11
+ ]
12
+ }
@@ -0,0 +1,18 @@
1
+ # Theme Gruvbox
2
+
3
+ ## Contributing
4
+
5
+ ```sh
6
+ git clone git@github.com:lvce-editor/theme-gruvbox.git &&
7
+ cd theme-gruvbox &&
8
+ npm ci &&
9
+ npm run dev
10
+ ```
11
+
12
+ ## Gitpod
13
+
14
+ [![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/lvce-editor/theme-gruvbox)
15
+
16
+ ## Credits
17
+
18
+ Extension is based on https://github.com/sainnhe/gruvbox-material-vscode by @sainnhe (License MIT)
@@ -0,0 +1,173 @@
1
+ {
2
+ "type": "dark",
3
+ "colors": {
4
+ "ActivityBarBackground": "rgb(41, 40, 40)",
5
+ "ActivityBarActiveForeground": "rgb(168, 153, 132)",
6
+ "ActivityBarForeground": "rgb(124, 111, 100)",
7
+
8
+ "BadgeBackground": "",
9
+ "BadgeForeground": "",
10
+
11
+ "ContextMenuBackground": "rgb(41, 40, 40)",
12
+ "ContextMenuForeground": "rgb(168, 153, 132)",
13
+
14
+ "EditorBackGround": "rgb(41, 40, 40)",
15
+ "EditorScrollBarBackground": "rgba(124, 111, 100, 0.5)",
16
+ "EditorCursorBackground": "#d4be98",
17
+ "EditorSelectionBackground": "rgba(80, 73, 69, 0.69)",
18
+
19
+ "FocusOutline": "",
20
+
21
+ "InputBoxBackground": "",
22
+ "InputBoxForeground": "",
23
+
24
+ "ListActiveSelectionBackground": "rgba(69, 64, 61, 0.38)",
25
+ "ListActiveSelectionForeground": "",
26
+ "ListHoverBackground": "rgba(69, 64, 61, 0.38)",
27
+ "ListHoverForeground": "",
28
+ "ListInactiveSelectionBackground": "",
29
+ "ListForeground": "rgb(212, 190, 152)",
30
+
31
+ "MainBackground": "rgb(41, 40, 40)",
32
+
33
+ "MenuBackground": "",
34
+ "MenuForeground": "rgb(168, 153, 132)",
35
+ "MenuItemHoverBackground": "rgb(50, 48, 47)",
36
+
37
+ "PanelBackground": "rgb(41, 40, 40)",
38
+ "PanelBorderTopColor": "",
39
+ "PanelTabHoverForeground": "",
40
+ "PanelTabActiveForeground": "#a89984",
41
+ "PanelTabHoverForeground": "#a89984",
42
+ "PanelTabForeground": "rgb(124, 111, 100)",
43
+
44
+ "QuickPickBackground": "rgb(41, 40, 40)",
45
+ "QuickPickInputBackground": "",
46
+
47
+ "SideBarBackground": "rgb(41, 40, 40)",
48
+ "SideBarForeground": "rgb(168, 153, 132)",
49
+
50
+ "StatusBarBackground": "rgb(41, 40, 40)",
51
+ "StatusBarBorderTopColor": "",
52
+
53
+ "TabActiveForeground": "rgb(212, 190, 152)",
54
+ "TabForeground": "rgb(212, 190, 152)",
55
+ "TabActiveBackground": "",
56
+ "TabInactiveBackground": "",
57
+
58
+ "TabsBackground": "",
59
+
60
+ "TitleBarBackground": "rgb(41, 40, 40)",
61
+ "TitleBarBorderBottomColor": "",
62
+ "TitleBarForeground": "rgb(168, 153, 132)",
63
+ "TitleBarColorInactive": "",
64
+
65
+ "TreeItemForeground": "rgb(146, 131, 116)"
66
+ },
67
+ "tokenColors": [
68
+ {
69
+ "name": "CssSelector",
70
+ "foreground": "#EA6962"
71
+ },
72
+ {
73
+ "name": "CssPropertyName",
74
+ "foreground": "#89B482"
75
+ },
76
+ {
77
+ "name": "CssPropertyValue",
78
+ "foreground": "#A9B665"
79
+ },
80
+ {
81
+ "name": "TagName",
82
+ "foreground": "#E78A4E"
83
+ },
84
+ {
85
+ "name": "AttributeName",
86
+ "foreground": "#D8A657"
87
+ },
88
+ {
89
+ "name": "String",
90
+ "foreground": "#A9B665"
91
+ },
92
+ {
93
+ "name": "PunctuationString",
94
+ "foreground": ""
95
+ },
96
+ {
97
+ "name": "PunctuationTag",
98
+ "foreground": "#A9B665"
99
+ },
100
+ {
101
+ "name": "JsonPropertyName",
102
+ "foreground": "#e78a4e"
103
+ },
104
+ {
105
+ "name": "JsonPropertyValueString",
106
+ "foreground": "#a9b665"
107
+ },
108
+ {
109
+ "name": "LanguageConstant",
110
+ "foreground": "#d3869b"
111
+ },
112
+ {
113
+ "name": "Keyword",
114
+ "foreground": "#EA6962"
115
+ },
116
+ {
117
+ "name": "Numeric",
118
+ "foreground": "#A9B665"
119
+ },
120
+ {
121
+ "name": "KeywordImport",
122
+ "foreground": "#89B482"
123
+ },
124
+ {
125
+ "name": "Type",
126
+ "foreground": ""
127
+ },
128
+ {
129
+ "name": "Macro",
130
+ "foreground": ""
131
+ },
132
+ {
133
+ "name": "KeywordControl",
134
+ "foreground": "#EA6962"
135
+ },
136
+ {
137
+ "name": "Regex",
138
+ "foreground": "#D8A657"
139
+ },
140
+ {
141
+ "name": "Function",
142
+ "foreground": ""
143
+ },
144
+ {
145
+ "name": "Comment",
146
+ "foreground": "#928374"
147
+ },
148
+ {
149
+ "name": "Punctuation",
150
+ "foreground": "#928374"
151
+ },
152
+ {
153
+ "name": "VariableName",
154
+ "foreground": "#D4BE98"
155
+ },
156
+ {
157
+ "name": "Text",
158
+ "foreground": "#d4be98"
159
+ },
160
+ {
161
+ "name": "KeywordReturn",
162
+ "foreground": "#EA6962"
163
+ },
164
+ {
165
+ "name": "Heading",
166
+ "foreground": "#E78A4E"
167
+ },
168
+ {
169
+ "name": "KeywordNew",
170
+ "foreground": "#EA6962"
171
+ }
172
+ ]
173
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "id": "builtin.theme-gruvbox",
3
+ "name": "Gruvbox",
4
+ "description": "Theme based on gruvbox-material-vscode theme by sainnhe",
5
+ "colorThemes": [
6
+ {
7
+ "id": "gruvbox",
8
+ "label": "Gruvbox",
9
+ "path": "color-theme.json"
10
+ }
11
+ ]
12
+ }
@@ -1,4 +1,4 @@
1
- # Theme Monokai
1
+ # Theme Slime
2
2
 
3
3
  ## Credits
4
4
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/shared-process",
3
- "version": "0.7.12",
3
+ "version": "0.8.1",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -20,8 +20,8 @@
20
20
  "node": ">=16"
21
21
  },
22
22
  "dependencies": {
23
- "@lvce-editor/extension-host": "0.7.12",
24
- "@lvce-editor/pty-host": "0.7.12",
23
+ "@lvce-editor/extension-host": "0.8.1",
24
+ "@lvce-editor/pty-host": "0.8.1",
25
25
  "chokidar": "^3.5.3",
26
26
  "debug": "^4.3.4",
27
27
  "execa": "^6.1.0",
@@ -10,9 +10,10 @@ export const Commands = {
10
10
  'ExtensionHost.getIconThemeJson': ExtensionHostIconTheme.getIconTheme,
11
11
  'ExtensionHost.getLanguageConfiguration': ExtensionHostLanguages.getLanguageConfiguration,
12
12
  'ExtensionHost.getLanguages': ExtensionHostLanguages.getLanguages,
13
+ 'ExtensionHost.watchColorTheme':ExtensionHostColorTheme.watch,
13
14
  'ExtensionManagement.disable': ExtensionManagement.disable,
14
15
  'ExtensionManagement.enable': ExtensionManagement.enable,
15
- 'ExtensionManagement.getAllExtensions': ExtensionManagement.getAllExtensions,
16
+ 'ExtensionManagement.getAllExtensions': ExtensionManagement.getExtensions,
16
17
  'ExtensionManagement.getExtensions': ExtensionManagement.getExtensions,
17
18
  'ExtensionManagement.install': ExtensionManagement.install,
18
19
  'ExtensionManagement.uninstall': ExtensionManagement.uninstall,
@@ -1,5 +1,4 @@
1
- import { mkdir, readdir, rename, rm } from 'node:fs/promises'
2
- import { performance } from 'node:perf_hooks'
1
+ import { mkdir, rename, rm } from 'node:fs/promises'
3
2
  import VError from 'verror'
4
3
  import * as Debug from '../Debug/Debug.js'
5
4
  import * as ExtensionManifestInputType from '../ExtensionManifestInputType/ExtensionManifestInputType.js'
@@ -8,28 +7,6 @@ import * as Path from '../Path/Path.js'
8
7
  import * as Platform from '../Platform/Platform.js'
9
8
  import * as Queue from '../Queue/Queue.js'
10
9
 
11
- const isLanguageBasics = (extension) => {
12
- if (extension && extension.id) {
13
- return extension.id.includes('language-basics')
14
- }
15
- return false
16
- }
17
-
18
- const getEnabledExtensionWithOnlyExtension = (
19
- builtinExtensions,
20
- onlyExtension
21
- ) => {
22
- const extensions = []
23
- for (const builtinExtension of builtinExtensions) {
24
- if (builtinExtension.id === onlyExtension.id) {
25
- continue
26
- }
27
- extensions.push(builtinExtension)
28
- }
29
- extensions.push(onlyExtension)
30
- return extensions
31
- }
32
-
33
10
  export const install = async (id) => {
34
11
  // TODO this should be a stateless function, renderer-worker should have info on marketplace url
35
12
  // TODO use command.execute
@@ -107,81 +84,7 @@ export const disable = async (id) => {
107
84
  }
108
85
  }
109
86
 
110
- const getAbsoluteDisabledPath = (dirent) => {
111
- const disabledExtensionsPath = Platform.getDisabledExtensionsPath()
112
- return Path.join(disabledExtensionsPath, dirent)
113
- }
114
-
115
- const getDisabledExtensionPaths = async () => {
116
- try {
117
- const disabledExtensionsPaths = Platform.getDisabledExtensionsPath()
118
- const dirents = await readdir(disabledExtensionsPaths)
119
- const paths = dirents.map(getAbsoluteDisabledPath)
120
- return paths
121
- } catch {
122
- // TODO handle error
123
- return []
124
- }
125
- }
126
-
127
- const getAbsoluteBuiltinExtensionPath = (dirent) => {
128
- const builtinExtensionsPath = Platform.getBuiltinExtensionsPath()
129
- return Path.join(builtinExtensionsPath, dirent)
130
- }
131
-
132
- const isIncludedBuiltinExtension = (dirent) => {
133
- const SKIPPED = [
134
- 'hello-world',
135
- 'vite',
136
- 'soundcloud',
137
- 'npm',
138
- // 'builtin.git', ~40MB memory usage (too many file watchers)
139
- // 'builtin.prettier', ~20MB memory usage (maybe lazyload prettier)
140
- // 'language-features-typescript',
141
- // 'builtin.vscode-icons',
142
- ]
143
- return !SKIPPED.includes(dirent)
144
- }
145
-
146
- // TODO pass builtin extensions path from renderer-worker
147
- // only negative: more messages sent between renderer-worker and shared process on startup
148
- const getBuiltinExtensionPaths = async () => {
149
- try {
150
- const builtinExtensionsPath = Platform.getBuiltinExtensionsPath()
151
- const dirents = await readdir(builtinExtensionsPath)
152
- const filteredDirents = dirents.filter(isIncludedBuiltinExtension)
153
- const paths = filteredDirents.map(getAbsoluteBuiltinExtensionPath)
154
- return paths
155
- } catch {
156
- console.info('no builtin extension paths found')
157
- return []
158
- }
159
- }
160
-
161
- const getAbsoluteInstalledExtensionPath = (dirent) => {
162
- const extensionsPath = Platform.getExtensionsPath()
163
- return Path.join(extensionsPath, dirent)
164
- }
165
-
166
- const getInstalledExtensionPaths = async () => {
167
- try {
168
- const extensionsPath = Platform.getExtensionsPath()
169
- const dirents = await readdir(extensionsPath)
170
- const paths = dirents.map(getAbsoluteInstalledExtensionPath)
171
- return paths
172
- } catch (error) {
173
- // TODO how to make typescript happy?
174
- // @ts-ignore
175
- if (error.code === 'ENOENT') {
176
- // TODO what if mkdir fails?
177
- await mkdir(Platform.getExtensionsPath(), { recursive: true })
178
- return []
179
- }
180
- throw new VError(error, 'Failed to get installed extensions')
181
- }
182
- }
183
-
184
- export const getBuiltinExtensions = async () => {
87
+ export const getBuiltinExtensions = () => {
185
88
  return ExtensionManifests.getAll([
186
89
  {
187
90
  type: ExtensionManifestInputType.Folder,
@@ -199,7 +102,7 @@ export const getInstalledExtensions = () => {
199
102
  ])
200
103
  }
201
104
 
202
- export const getExtensions = async () => {
105
+ export const getExtensions = () => {
203
106
  return ExtensionManifests.getAll([
204
107
  {
205
108
  type: ExtensionManifestInputType.OnlyExtension,
@@ -220,7 +123,7 @@ export const getExtensions = async () => {
220
123
  ])
221
124
  }
222
125
 
223
- export const getDisabledExtensions = async () => {
126
+ export const getDisabledExtensions = () => {
224
127
  return ExtensionManifests.getAll([
225
128
  {
226
129
  type: ExtensionManifestInputType.Folder,
@@ -228,32 +131,3 @@ export const getDisabledExtensions = async () => {
228
131
  },
229
132
  ])
230
133
  }
231
-
232
- export const getAllExtensions = async () => {
233
- const onlyExtensionPath = Platform.getOnlyExtensionPath()
234
- if (onlyExtensionPath) {
235
- return ExtensionManifests.getAll([
236
- {
237
- type: ExtensionManifestInputType.OnlyExtension,
238
- path: onlyExtensionPath,
239
- },
240
- ])
241
- }
242
- const t1 = performance.now()
243
- const [builtinExtensions, installedExtensions, disabledExtensions] =
244
- // TODO handle error when one of them fails
245
- await Promise.all([
246
- getBuiltinExtensions(),
247
- getInstalledExtensions(),
248
- getDisabledExtensions(),
249
- ])
250
- const t4 = performance.now()
251
- // TODO can optimize this by loading extension manifest while loading paths (though 2ms isn't a bottleneck right now)
252
- // e.g.
253
- // await Promise.all([getBuiltinExtensionPaths.then(getExtensionManifests), getInstalledExtensionPaths.then(getExtensionManifests)])
254
- const timings = {
255
- total: t4 - t1,
256
- }
257
- // console.log(timings)
258
- return [...builtinExtensions, ...installedExtensions, ...disabledExtensions]
259
- }
@@ -3,11 +3,12 @@ import * as Error from '../Error/Error.js'
3
3
  import * as ReadJson from '../JsonFile/JsonFile.js'
4
4
  import * as Path from '../Path/Path.js'
5
5
  import * as ExtensionManagement from './ExtensionManagement.js'
6
+ import * as FileSystemWatch from '../FileSystemWatch/FileSystemWatch.js'
6
7
 
7
8
  // TODO test this function
8
9
  // TODO very similar with getIconTheme
9
- export const getColorThemeJson = async (colorThemeId) => {
10
- const extensions = await ExtensionManagement.getExtensions()
10
+
11
+ const getColorThemePath = async (extensions, colorThemeId) => {
11
12
  for (const extension of extensions) {
12
13
  if (!extension.colorThemes) {
13
14
  continue
@@ -17,18 +18,27 @@ export const getColorThemeJson = async (colorThemeId) => {
17
18
  continue
18
19
  }
19
20
  const absolutePath = Path.join(extension.path, colorTheme.path)
20
- try {
21
- const json = await ReadJson.readJson(absolutePath)
22
- return json
23
- } catch (error) {
24
- throw new VError(error, `Failed to load color theme "${colorThemeId}"`)
25
- }
21
+ return absolutePath
26
22
  }
27
23
  }
28
- throw new Error.OperationalError({
29
- code: 'E_COLOR_THEME_NOT_FOUND',
30
- message: `Color theme "${colorThemeId}" not found in extensions folder`,
31
- })
24
+ return ''
25
+ }
26
+
27
+ export const getColorThemeJson = async (colorThemeId) => {
28
+ const extensions = await ExtensionManagement.getExtensions()
29
+ const colorThemePath = await getColorThemePath(extensions, colorThemeId)
30
+ if (!colorThemePath) {
31
+ throw new Error.OperationalError({
32
+ code: 'E_COLOR_THEME_NOT_FOUND',
33
+ message: `Color theme "${colorThemeId}" not found in extensions folder`,
34
+ })
35
+ }
36
+ try {
37
+ const json = await ReadJson.readJson(colorThemePath)
38
+ return json
39
+ } catch (error) {
40
+ throw new VError(error, `Failed to load color theme "${colorThemeId}"`)
41
+ }
32
42
  }
33
43
 
34
44
  const getColorThemeInfo = (extension) => {
@@ -56,3 +66,19 @@ export const getColorThemes = async () => {
56
66
  const colorThemes = extensions.flatMap(getColorThemeInfo)
57
67
  return colorThemes
58
68
  }
69
+
70
+ export const watch = async (socket, colorThemeId) => {
71
+ // console.log({ socket, colorThemeId })
72
+ const extensions = await ExtensionManagement.getExtensions()
73
+ const colorThemePath = await getColorThemePath(extensions, colorThemeId)
74
+ const verbose = process.argv.includes('--verbose')
75
+ if (verbose) {
76
+ console.info(
77
+ `[shared-process] starting to watch color theme ${colorThemeId} at ${colorThemePath}`
78
+ )
79
+ }
80
+ const watcher = FileSystemWatch.watchFile(colorThemePath)
81
+ for await (const event of watcher) {
82
+ socket.send({ jsonrpc: '2.0', method: 'ColorTheme.reload', params: [] })
83
+ }
84
+ }
@@ -0,0 +1,6 @@
1
+ import * as fs from 'node:fs/promises'
2
+
3
+ export const watchFile = (path) => {
4
+ const watcher = fs.watch(path)
5
+ return watcher
6
+ }
@@ -66,6 +66,7 @@ export const getModuleId = (commandId) => {
66
66
  case 'ExtensionHost.getIconThemeJson':
67
67
  case 'ExtensionHost.getLanguageConfiguration':
68
68
  case 'ExtensionHost.getLanguages':
69
+ case 'ExtensionHost.watchColorTheme':
69
70
  case 'ExtensionManagement.disable':
70
71
  case 'ExtensionManagement.enable':
71
72
  case 'ExtensionManagement.getAllExtensions':
@@ -5,6 +5,7 @@ const METHODS_THAT_REQUIRE_SOCKET = new Set([
5
5
  'OutputChannel.open',
6
6
  'ExtensionHost.start',
7
7
  'ExtensionHost.send',
8
+ 'ExtensionHost.watchColorTheme',
8
9
  ])
9
10
 
10
11
  export const requiresSocket = (method) => {