@eclipse-lyra/core 0.0.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.
Files changed (281) hide show
  1. package/dist/api/base-classes.d.ts +7 -0
  2. package/dist/api/base-classes.d.ts.map +1 -0
  3. package/dist/api/constants.d.ts +2 -0
  4. package/dist/api/constants.d.ts.map +1 -0
  5. package/dist/api/index.d.ts +6 -0
  6. package/dist/api/index.d.ts.map +1 -0
  7. package/dist/api/index.js +84 -0
  8. package/dist/api/index.js.map +1 -0
  9. package/dist/api/services.d.ts +28 -0
  10. package/dist/api/services.d.ts.map +1 -0
  11. package/dist/api/types.d.ts +11 -0
  12. package/dist/api/types.d.ts.map +1 -0
  13. package/dist/commands/editor.d.ts +1 -0
  14. package/dist/commands/editor.d.ts.map +1 -0
  15. package/dist/commands/files.d.ts +2 -0
  16. package/dist/commands/files.d.ts.map +1 -0
  17. package/dist/commands/global.d.ts +1 -0
  18. package/dist/commands/global.d.ts.map +1 -0
  19. package/dist/commands/index.d.ts +1 -0
  20. package/dist/commands/index.d.ts.map +1 -0
  21. package/dist/commands/open-view-as-editor.d.ts +2 -0
  22. package/dist/commands/open-view-as-editor.d.ts.map +1 -0
  23. package/dist/commands/version-info.d.ts +2 -0
  24. package/dist/commands/version-info.d.ts.map +1 -0
  25. package/dist/components/app-selector.d.ts +17 -0
  26. package/dist/components/app-selector.d.ts.map +1 -0
  27. package/dist/components/app-switcher.d.ts +13 -0
  28. package/dist/components/app-switcher.d.ts.map +1 -0
  29. package/dist/components/command.d.ts +31 -0
  30. package/dist/components/command.d.ts.map +1 -0
  31. package/dist/components/extensions.d.ts +32 -0
  32. package/dist/components/extensions.d.ts.map +1 -0
  33. package/dist/components/fastviews.d.ts +34 -0
  34. package/dist/components/fastviews.d.ts.map +1 -0
  35. package/dist/components/filebrowser.d.ts +45 -0
  36. package/dist/components/filebrowser.d.ts.map +1 -0
  37. package/dist/components/index.d.ts +1 -0
  38. package/dist/components/index.d.ts.map +1 -0
  39. package/dist/components/language-selector.d.ts +12 -0
  40. package/dist/components/language-selector.d.ts.map +1 -0
  41. package/dist/components/log-terminal.d.ts +36 -0
  42. package/dist/components/log-terminal.d.ts.map +1 -0
  43. package/dist/components/part-name.d.ts +12 -0
  44. package/dist/components/part-name.d.ts.map +1 -0
  45. package/dist/components/tasks.d.ts +13 -0
  46. package/dist/components/tasks.d.ts.map +1 -0
  47. package/dist/contributions/default-ui-contributions.d.ts +2 -0
  48. package/dist/contributions/default-ui-contributions.d.ts.map +1 -0
  49. package/dist/contributions/index.d.ts +1 -0
  50. package/dist/contributions/index.d.ts.map +1 -0
  51. package/dist/contributions/marketplace-catalog-contributions.d.ts +2 -0
  52. package/dist/contributions/marketplace-catalog-contributions.d.ts.map +1 -0
  53. package/dist/core/app-host-config.d.ts +7 -0
  54. package/dist/core/app-host-config.d.ts.map +1 -0
  55. package/dist/core/apploader.d.ts +214 -0
  56. package/dist/core/apploader.d.ts.map +1 -0
  57. package/dist/core/appstate.d.ts +12 -0
  58. package/dist/core/appstate.d.ts.map +1 -0
  59. package/dist/core/commandregistry.d.ts +79 -0
  60. package/dist/core/commandregistry.d.ts.map +1 -0
  61. package/dist/core/config.d.ts +15 -0
  62. package/dist/core/config.d.ts.map +1 -0
  63. package/dist/core/constants.d.ts +22 -0
  64. package/dist/core/constants.d.ts.map +1 -0
  65. package/dist/core/contributionregistry.d.ts +53 -0
  66. package/dist/core/contributionregistry.d.ts.map +1 -0
  67. package/dist/core/di.d.ts +18 -0
  68. package/dist/core/di.d.ts.map +1 -0
  69. package/dist/core/dialogservice.d.ts +33 -0
  70. package/dist/core/dialogservice.d.ts.map +1 -0
  71. package/dist/core/editorregistry.d.ts +87 -0
  72. package/dist/core/editorregistry.d.ts.map +1 -0
  73. package/dist/core/esmsh-service.d.ts +40 -0
  74. package/dist/core/esmsh-service.d.ts.map +1 -0
  75. package/dist/core/events.d.ts +7 -0
  76. package/dist/core/events.d.ts.map +1 -0
  77. package/dist/core/events.js +63 -0
  78. package/dist/core/events.js.map +1 -0
  79. package/dist/core/extensionregistry.d.ts +98 -0
  80. package/dist/core/extensionregistry.d.ts.map +1 -0
  81. package/dist/core/filesys/common.d.ts +122 -0
  82. package/dist/core/filesys/common.d.ts.map +1 -0
  83. package/dist/core/filesys/fs-access.d.ts +31 -0
  84. package/dist/core/filesys/fs-access.d.ts.map +1 -0
  85. package/dist/core/filesys/index.d.ts +5 -0
  86. package/dist/core/filesys/index.d.ts.map +1 -0
  87. package/dist/core/filesys/indexeddb.d.ts +41 -0
  88. package/dist/core/filesys/indexeddb.d.ts.map +1 -0
  89. package/dist/core/filesys/opfs.d.ts +14 -0
  90. package/dist/core/filesys/opfs.d.ts.map +1 -0
  91. package/dist/core/i18n.d.ts +50 -0
  92. package/dist/core/i18n.d.ts.map +1 -0
  93. package/dist/core/index.d.ts +1 -0
  94. package/dist/core/index.d.ts.map +1 -0
  95. package/dist/core/keybindings.d.ts +67 -0
  96. package/dist/core/keybindings.d.ts.map +1 -0
  97. package/dist/core/logger.d.ts +44 -0
  98. package/dist/core/logger.d.ts.map +1 -0
  99. package/dist/core/marketplaceregistry.d.ts +25 -0
  100. package/dist/core/marketplaceregistry.d.ts.map +1 -0
  101. package/dist/core/packageinfoservice.d.ts +16 -0
  102. package/dist/core/packageinfoservice.d.ts.map +1 -0
  103. package/dist/core/persistenceservice.d.ts +6 -0
  104. package/dist/core/persistenceservice.d.ts.map +1 -0
  105. package/dist/core/settingsservice.d.ts +54 -0
  106. package/dist/core/settingsservice.d.ts.map +1 -0
  107. package/dist/core/signals.d.ts +3 -0
  108. package/dist/core/signals.d.ts.map +1 -0
  109. package/dist/core/taskservice.d.ts +20 -0
  110. package/dist/core/taskservice.d.ts.map +1 -0
  111. package/dist/core/toast.d.ts +4 -0
  112. package/dist/core/toast.d.ts.map +1 -0
  113. package/dist/core/tree-utils.d.ts +16 -0
  114. package/dist/core/tree-utils.d.ts.map +1 -0
  115. package/dist/dialogs/confirm-dialog.d.ts +14 -0
  116. package/dist/dialogs/confirm-dialog.d.ts.map +1 -0
  117. package/dist/dialogs/index.d.ts +5 -0
  118. package/dist/dialogs/index.d.ts.map +1 -0
  119. package/dist/dialogs/info-dialog.d.ts +13 -0
  120. package/dist/dialogs/info-dialog.d.ts.map +1 -0
  121. package/dist/dialogs/navigable-info-dialog.d.ts +33 -0
  122. package/dist/dialogs/navigable-info-dialog.d.ts.map +1 -0
  123. package/dist/dialogs/prompt-dialog.d.ts +21 -0
  124. package/dist/dialogs/prompt-dialog.d.ts.map +1 -0
  125. package/dist/externals/lit.d.ts +21 -0
  126. package/dist/externals/lit.d.ts.map +1 -0
  127. package/dist/externals/lit.js +24 -0
  128. package/dist/externals/lit.js.map +1 -0
  129. package/dist/externals/third-party.d.ts +7 -0
  130. package/dist/externals/third-party.d.ts.map +1 -0
  131. package/dist/externals/third-party.js +7 -0
  132. package/dist/externals/third-party.js.map +1 -0
  133. package/dist/externals/webawesome.d.ts +1 -0
  134. package/dist/externals/webawesome.d.ts.map +1 -0
  135. package/dist/externals/webawesome.js +75 -0
  136. package/dist/externals/webawesome.js.map +1 -0
  137. package/dist/i18n/extensions.json.d.ts +42 -0
  138. package/dist/i18n/fastviews.json.d.ts +13 -0
  139. package/dist/i18n/filebrowser.json.d.ts +29 -0
  140. package/dist/i18n/index.d.ts +2 -0
  141. package/dist/i18n/index.d.ts.map +1 -0
  142. package/dist/i18n/logterminal.json.d.ts +45 -0
  143. package/dist/i18n/partname.json.d.ts +15 -0
  144. package/dist/i18n/tasks.json.d.ts +15 -0
  145. package/dist/i18n/workspace.json.d.ts +15 -0
  146. package/dist/icon-DN6fp0dg.js +487 -0
  147. package/dist/icon-DN6fp0dg.js.map +1 -0
  148. package/dist/index.d.ts +2 -0
  149. package/dist/index.d.ts.map +1 -0
  150. package/dist/index.js +84 -0
  151. package/dist/index.js.map +1 -0
  152. package/dist/layouts/standard-layout.d.ts +16 -0
  153. package/dist/layouts/standard-layout.d.ts.map +1 -0
  154. package/dist/nocontent-BhrN6yxJ.js +48 -0
  155. package/dist/nocontent-BhrN6yxJ.js.map +1 -0
  156. package/dist/parts/container.d.ts +4 -0
  157. package/dist/parts/container.d.ts.map +1 -0
  158. package/dist/parts/contextmenu.d.ts +50 -0
  159. package/dist/parts/contextmenu.d.ts.map +1 -0
  160. package/dist/parts/dialog-content.d.ts +9 -0
  161. package/dist/parts/dialog-content.d.ts.map +1 -0
  162. package/dist/parts/element.d.ts +36 -0
  163. package/dist/parts/element.d.ts.map +1 -0
  164. package/dist/parts/index.d.ts +1 -0
  165. package/dist/parts/index.d.ts.map +1 -0
  166. package/dist/parts/index.js +3 -0
  167. package/dist/parts/index.js.map +1 -0
  168. package/dist/parts/part.d.ts +96 -0
  169. package/dist/parts/part.d.ts.map +1 -0
  170. package/dist/parts/resizable-grid.d.ts +31 -0
  171. package/dist/parts/resizable-grid.d.ts.map +1 -0
  172. package/dist/parts/tabs.d.ts +75 -0
  173. package/dist/parts/tabs.d.ts.map +1 -0
  174. package/dist/parts/toolbar.d.ts +35 -0
  175. package/dist/parts/toolbar.d.ts.map +1 -0
  176. package/dist/resizable-grid-BRH3MyZK.js +3813 -0
  177. package/dist/resizable-grid-BRH3MyZK.js.map +1 -0
  178. package/dist/standard-layout-BSGa06lP.js +4907 -0
  179. package/dist/standard-layout-BSGa06lP.js.map +1 -0
  180. package/dist/widgets/icon.d.ts +10 -0
  181. package/dist/widgets/icon.d.ts.map +1 -0
  182. package/dist/widgets/index.d.ts +1 -0
  183. package/dist/widgets/index.d.ts.map +1 -0
  184. package/dist/widgets/index.js +3 -0
  185. package/dist/widgets/index.js.map +1 -0
  186. package/dist/widgets/nocontent.d.ts +13 -0
  187. package/dist/widgets/nocontent.d.ts.map +1 -0
  188. package/dist/widgets/widget.d.ts +25 -0
  189. package/dist/widgets/widget.d.ts.map +1 -0
  190. package/package.json +81 -0
  191. package/src/api/base-classes.ts +10 -0
  192. package/src/api/constants.ts +3 -0
  193. package/src/api/index.ts +31 -0
  194. package/src/api/services.ts +58 -0
  195. package/src/api/types.ts +46 -0
  196. package/src/commands/editor.ts +1 -0
  197. package/src/commands/files.ts +425 -0
  198. package/src/commands/global.ts +198 -0
  199. package/src/commands/index.ts +6 -0
  200. package/src/commands/open-view-as-editor.ts +28 -0
  201. package/src/commands/version-info.ts +214 -0
  202. package/src/components/app-selector.ts +233 -0
  203. package/src/components/app-switcher.ts +126 -0
  204. package/src/components/command.ts +236 -0
  205. package/src/components/extensions.ts +615 -0
  206. package/src/components/fastviews.ts +314 -0
  207. package/src/components/filebrowser.ts +518 -0
  208. package/src/components/index.ts +9 -0
  209. package/src/components/language-selector.ts +166 -0
  210. package/src/components/log-terminal.ts +337 -0
  211. package/src/components/part-name.ts +54 -0
  212. package/src/components/tasks.ts +275 -0
  213. package/src/contributions/default-ui-contributions.ts +44 -0
  214. package/src/contributions/index.ts +3 -0
  215. package/src/contributions/marketplace-catalog-contributions.ts +6 -0
  216. package/src/core/app-host-config.ts +23 -0
  217. package/src/core/apploader.ts +630 -0
  218. package/src/core/appstate.ts +15 -0
  219. package/src/core/commandregistry.ts +210 -0
  220. package/src/core/config.ts +29 -0
  221. package/src/core/constants.ts +29 -0
  222. package/src/core/contributionregistry.ts +81 -0
  223. package/src/core/di.ts +54 -0
  224. package/src/core/dialogservice.ts +266 -0
  225. package/src/core/editorregistry.ts +347 -0
  226. package/src/core/esmsh-service.ts +404 -0
  227. package/src/core/events.ts +68 -0
  228. package/src/core/extensionregistry.ts +399 -0
  229. package/src/core/filesys/common.ts +474 -0
  230. package/src/core/filesys/fs-access.ts +339 -0
  231. package/src/core/filesys/index.ts +5 -0
  232. package/src/core/filesys/indexeddb.ts +596 -0
  233. package/src/core/filesys/opfs.ts +95 -0
  234. package/src/core/i18n.ts +221 -0
  235. package/src/core/index.ts +51 -0
  236. package/src/core/keybindings.ts +274 -0
  237. package/src/core/logger.ts +187 -0
  238. package/src/core/marketplaceregistry.ts +197 -0
  239. package/src/core/packageinfoservice.ts +56 -0
  240. package/src/core/persistenceservice.ts +46 -0
  241. package/src/core/settingsservice.ts +191 -0
  242. package/src/core/signals.ts +18 -0
  243. package/src/core/taskservice.ts +72 -0
  244. package/src/core/toast.ts +21 -0
  245. package/src/core/tree-utils.ts +24 -0
  246. package/src/dialogs/confirm-dialog.ts +72 -0
  247. package/src/dialogs/index.ts +4 -0
  248. package/src/dialogs/info-dialog.ts +67 -0
  249. package/src/dialogs/navigable-info-dialog.ts +256 -0
  250. package/src/dialogs/prompt-dialog.ts +123 -0
  251. package/src/externals/lit.ts +36 -0
  252. package/src/externals/third-party.ts +10 -0
  253. package/src/externals/webawesome.ts +76 -0
  254. package/src/i18n/extensions.json +39 -0
  255. package/src/i18n/fastviews.json +10 -0
  256. package/src/i18n/filebrowser.json +27 -0
  257. package/src/i18n/index.ts +25 -0
  258. package/src/i18n/logterminal.json +42 -0
  259. package/src/i18n/partname.json +12 -0
  260. package/src/i18n/tasks.json +12 -0
  261. package/src/i18n/workspace.json +12 -0
  262. package/src/icons/icons.txt +3 -0
  263. package/src/icons/js.svg +6 -0
  264. package/src/icons/jupyter.svg +18 -0
  265. package/src/icons/python.svg +15 -0
  266. package/src/index.ts +3 -0
  267. package/src/layouts/standard-layout.ts +174 -0
  268. package/src/parts/container.ts +4 -0
  269. package/src/parts/contextmenu.ts +266 -0
  270. package/src/parts/dialog-content.ts +31 -0
  271. package/src/parts/element.ts +100 -0
  272. package/src/parts/index.ts +5 -0
  273. package/src/parts/part.ts +158 -0
  274. package/src/parts/resizable-grid.ts +366 -0
  275. package/src/parts/tabs.ts +581 -0
  276. package/src/parts/toolbar.ts +260 -0
  277. package/src/vite-env.d.ts +16 -0
  278. package/src/widgets/icon.ts +38 -0
  279. package/src/widgets/index.ts +2 -0
  280. package/src/widgets/nocontent.ts +40 -0
  281. package/src/widgets/widget.ts +92 -0
@@ -0,0 +1,425 @@
1
+ import {registerAll, type ExecutionContext} from "../core/commandregistry";
2
+ import {File, workspaceService, Directory} from "../core/filesys";
3
+ import {toastError, toastInfo} from "../core/toast";
4
+ import {activeSelectionSignal} from "../core/appstate";
5
+ import {editorRegistry, EditorContentProvider} from "../core/editorregistry";
6
+ import logger from "../core/logger";
7
+
8
+ async function getWorkspaceAndPath(params: any, requirePath: boolean = true): Promise<{workspace: Directory, path: string} | null> {
9
+ const workspace = await workspaceService.getWorkspace()
10
+ if (!workspace) {
11
+ return null
12
+ }
13
+
14
+ const path = params?.path
15
+ if (requirePath && !path) {
16
+ return null
17
+ }
18
+
19
+ return { workspace, path: path || '' }
20
+ }
21
+
22
+ /**
23
+ * Type guard to check if an editor implements EditorContentProvider
24
+ */
25
+ function isEditorContentProvider(editor: any): editor is EditorContentProvider {
26
+ return editor &&
27
+ typeof editor.getContent === 'function' &&
28
+ typeof editor.getSelection === 'function' &&
29
+ typeof editor.getSnippet === 'function' &&
30
+ typeof editor.getLanguage === 'function' &&
31
+ typeof editor.getFilePath === 'function';
32
+ }
33
+
34
+ /**
35
+ * Helper to get a resource from path or active selection
36
+ */
37
+ async function getResourceFromContext(context: ExecutionContext, params?: any): Promise<any> {
38
+ let resource = undefined
39
+ const path = params?.path || context.params?.["path"]
40
+
41
+ if (path) {
42
+ const workspaceDir = await workspaceService.getWorkspace()
43
+ if (workspaceDir) {
44
+ resource = await workspaceDir.getResource(path)
45
+ }
46
+ }
47
+
48
+ if (!resource) {
49
+ resource = activeSelectionSignal.get()
50
+ }
51
+
52
+ return resource
53
+ }
54
+
55
+ /**
56
+ * Helper to read text file contents with error handling
57
+ */
58
+ async function readTextFile(file: File): Promise<string | null> {
59
+ try {
60
+ const contents = await file.getContents()
61
+ if (typeof contents !== 'string') {
62
+ toastError("File is not a text file")
63
+ return null
64
+ }
65
+ return contents
66
+ } catch (err: any) {
67
+ toastError(`Failed to read file: ${err.message}`)
68
+ return null
69
+ }
70
+ }
71
+
72
+ /**
73
+ * Helper to create null editor response
74
+ */
75
+ function createNullEditorResponse(includeCursorLine: boolean = false) {
76
+ const base = {
77
+ filePath: null,
78
+ language: null
79
+ }
80
+ if (includeCursorLine) {
81
+ return { ...base, snippet: null, cursorLine: null }
82
+ }
83
+ return base
84
+ }
85
+
86
+ async function getWorkspaceAndFile(params: any, requirePath: boolean = true): Promise<{workspace: Directory, path: string, file: File} | null> {
87
+ const result = await getWorkspaceAndPath(params, requirePath)
88
+ if (!result) {
89
+ return null
90
+ }
91
+
92
+ const { workspace, path } = result
93
+
94
+ if (!path) {
95
+ return null
96
+ }
97
+
98
+ try {
99
+ const resource = await workspace.getResource(path)
100
+ if (!resource || !(resource instanceof File)) {
101
+ return null
102
+ }
103
+
104
+ return { workspace, path, file: resource }
105
+ } catch (err: any) {
106
+ return null
107
+ }
108
+ }
109
+
110
+ registerAll({
111
+ command: {
112
+ "id": "disconnect_folder",
113
+ "name": "Disconnect folder",
114
+ "description": "Disconnects a folder from the workspace"
115
+ },
116
+ handler: {
117
+ execute: async () => {
118
+ const selection = activeSelectionSignal.get()
119
+ if (!(selection instanceof Directory && selection.getParent() === undefined)) {
120
+ toastError("Select a folder root to disconnect.")
121
+ return
122
+ }
123
+ try {
124
+ await workspaceService.disconnectFolder(selection)
125
+ } catch (err: any) {
126
+ toastError(err.message)
127
+ }
128
+ }
129
+ },
130
+ contribution: {
131
+ target: "contextmenu:filebrowser",
132
+ label: "Disconnect folder",
133
+ icon: "folder-minus",
134
+ disabled: () => {
135
+ const selection = activeSelectionSignal.get();
136
+ return !(selection instanceof Directory && selection.getParent() === undefined);
137
+ }
138
+ }
139
+ })
140
+
141
+ // Register local filesystem workspace contribution
142
+ registerAll({
143
+ command: {
144
+ "id": "load_workspace",
145
+ "name": "Local Folder",
146
+ "description": "Connect to a local folder using File System Access API",
147
+ "parameters": []
148
+ },
149
+ handler: {
150
+ execute: async _context => {
151
+ // @ts-ignore
152
+ await window.showDirectoryPicker({
153
+ mode: "readwrite"
154
+ }).then((dirHandle: FileSystemDirectoryHandle) => {
155
+ return workspaceService.connectWorkspace(dirHandle);
156
+ }).catch((err: Error) => {
157
+ toastError(err.message)
158
+ });
159
+ }
160
+ },
161
+ contribution: {
162
+ target: "filebrowser.connections",
163
+ label: "Local Folder",
164
+ icon: "folder-open"
165
+ }
166
+ })
167
+
168
+ registerAll({
169
+ command: {
170
+ "id": "connect_opfs",
171
+ "name": "OPFS",
172
+ "description": "Connect to Origin Private File System (browser storage)",
173
+ "parameters": []
174
+ },
175
+ handler: {
176
+ execute: async () => {
177
+ try {
178
+ await workspaceService.connectFolder({ opfs: true });
179
+ } catch (err: any) {
180
+ toastError(err.message);
181
+ }
182
+ }
183
+ },
184
+ contribution: {
185
+ target: "filebrowser.connections",
186
+ label: "OPFS (Browser Storage)",
187
+ icon: "database"
188
+ }
189
+ })
190
+
191
+ registerAll({
192
+ command: {
193
+ "id": "connect_indexeddb",
194
+ "name": "IndexedDB",
195
+ "description": "Connect to IndexedDB-backed workspace (browser storage)",
196
+ "parameters": [
197
+ {
198
+ "name": "name",
199
+ "description": "Optional display name for this IndexedDB workspace root",
200
+ "required": false
201
+ }
202
+ ]
203
+ },
204
+ handler: {
205
+ execute: async (context: ExecutionContext) => {
206
+ const nameParam = context.params?.["name"];
207
+ try {
208
+ await workspaceService.connectFolder({ indexeddb: true, name: nameParam });
209
+ } catch (err: any) {
210
+ toastError(err.message);
211
+ }
212
+ }
213
+ },
214
+ contribution: {
215
+ target: "filebrowser.connections",
216
+ label: "IndexedDB (Browser Storage)",
217
+ icon: "database"
218
+ }
219
+ })
220
+
221
+ registerAll({
222
+ command: {
223
+ "id": "refresh_resource",
224
+ "name": "Refresh resource",
225
+ "description": "Refreshes the connected folder of the selected resource, or the whole workspace if nothing is selected",
226
+ "parameters": []
227
+ },
228
+ handler: {
229
+ execute: async () => {
230
+ const selection = activeSelectionSignal.get()
231
+ if (selection) {
232
+ selection.getWorkspace().touch()
233
+ return
234
+ }
235
+ const workspace = await workspaceService.getWorkspace()
236
+ if (!workspace) {
237
+ toastError("No workspace selected.")
238
+ return
239
+ }
240
+ workspace.touch()
241
+ }
242
+ }
243
+ })
244
+
245
+ registerAll({
246
+ command: {
247
+ "id": "open_editor",
248
+ "name": "Open editor",
249
+ "description": "Opens a file in an editor",
250
+ "parameters": [
251
+ {
252
+ "name": "path",
253
+ "description": "The path of the file to open within the workspace; if omitted, the active selection is opened",
254
+ "required": false
255
+ },
256
+ {
257
+ "name": "editorId",
258
+ "description": "Open with this editor id; if omitted, use default editor",
259
+ "required": false
260
+ }
261
+ ]
262
+ },
263
+ handler: {
264
+ execute: async context => {
265
+ const path = context.params?.["path"]
266
+ const editorId = context.params?.["editorId"]
267
+ let file: File | null = null
268
+ if (path) {
269
+ const result = await getWorkspaceAndFile({ path })
270
+ file = result?.file ?? null
271
+ } else {
272
+ const selection = activeSelectionSignal.get()
273
+ file = selection instanceof File ? selection : null
274
+ }
275
+ if (!file) return
276
+ await editorRegistry.loadEditor(file, editorId)
277
+ }
278
+ }
279
+ })
280
+
281
+ registerAll({
282
+ command: {
283
+ "id": "get_active_editor_content",
284
+ "name": "Get active editor content",
285
+ "description": "Gets the complete contents of the currently active editor. Returns null if no editor is active or if the editor is not a code editor.",
286
+ "parameters": [],
287
+ "output": [
288
+ {
289
+ "name": "content",
290
+ "description": "the complete contents of the active editor, or null if no editor is active"
291
+ },
292
+ {
293
+ "name": "filePath",
294
+ "description": "the workspace path of the file in the active editor, or null if no editor is active"
295
+ },
296
+ {
297
+ "name": "language",
298
+ "description": "the programming language of the active editor, or null if no editor is active"
299
+ }
300
+ ]
301
+ },
302
+ handler: {
303
+ execute: async (context: ExecutionContext) => {
304
+ const activeEditor = context.activeEditor as any
305
+ if (!isEditorContentProvider(activeEditor)) {
306
+ return { ...createNullEditorResponse(), content: null }
307
+ }
308
+
309
+ try {
310
+ return {
311
+ content: activeEditor.getContent(),
312
+ filePath: activeEditor.getFilePath(),
313
+ language: activeEditor.getLanguage()
314
+ }
315
+ } catch (err: any) {
316
+ return { ...createNullEditorResponse(), content: null }
317
+ }
318
+ }
319
+ }
320
+ })
321
+
322
+ registerAll({
323
+ command: {
324
+ "id": "get_active_editor_selection",
325
+ "name": "Get active editor selection",
326
+ "description": "Gets the currently selected text in the active editor. Returns null if no editor is active, no selection exists, or if the editor is not a code editor.",
327
+ "parameters": [],
328
+ "output": [
329
+ {
330
+ "name": "selection",
331
+ "description": "the selected text in the active editor, or null if no selection exists or no editor is active"
332
+ },
333
+ {
334
+ "name": "filePath",
335
+ "description": "the workspace path of the file in the active editor, or null if no editor is active"
336
+ },
337
+ {
338
+ "name": "language",
339
+ "description": "the programming language of the active editor, or null if no editor is active"
340
+ }
341
+ ]
342
+ },
343
+ handler: {
344
+ execute: async (context: ExecutionContext) => {
345
+ const activeEditor = context.activeEditor as any
346
+ if (!isEditorContentProvider(activeEditor)) {
347
+ return { ...createNullEditorResponse(), selection: null }
348
+ }
349
+
350
+ try {
351
+ return {
352
+ selection: activeEditor.getSelection(),
353
+ filePath: activeEditor.getFilePath(),
354
+ language: activeEditor.getLanguage()
355
+ }
356
+ } catch (err: any) {
357
+ return { ...createNullEditorResponse(), selection: null }
358
+ }
359
+ }
360
+ }
361
+ })
362
+
363
+ registerAll({
364
+ command: {
365
+ "id": "get_active_editor_snippet",
366
+ "name": "Get active editor snippet around cursor",
367
+ "description": "Gets a code snippet from the active editor with n lines before and n lines after the cursor position. Useful for getting context around the cursor without loading the entire file.",
368
+ "parameters": [
369
+ {
370
+ "name": "lines",
371
+ "description": "number of lines to include before and after the cursor position (default: 5)",
372
+ "type": "number",
373
+ "required": false
374
+ }
375
+ ],
376
+ "output": [
377
+ {
378
+ "name": "snippet",
379
+ "description": "the code snippet with n lines before and after the cursor, or null if no editor is active"
380
+ },
381
+ {
382
+ "name": "filePath",
383
+ "description": "the workspace path of the file in the active editor, or null if no editor is active"
384
+ },
385
+ {
386
+ "name": "language",
387
+ "description": "the programming language of the active editor, or null if no editor is active"
388
+ },
389
+ {
390
+ "name": "cursorLine",
391
+ "description": "the line number where the cursor is positioned (1-based), or null if no editor is active"
392
+ }
393
+ ]
394
+ },
395
+ handler: {
396
+ execute: async (context: ExecutionContext) => {
397
+ const activeEditor = context.activeEditor as any
398
+ if (!isEditorContentProvider(activeEditor)) {
399
+ return createNullEditorResponse(true)
400
+ }
401
+
402
+ try {
403
+ const numLines = context.params?.lines ? parseInt(context.params.lines, 10) : 5
404
+ if (isNaN(numLines) || numLines < 0) {
405
+ return createNullEditorResponse(true)
406
+ }
407
+
408
+ const snippetResult = activeEditor.getSnippet(numLines)
409
+ if (!snippetResult) {
410
+ return createNullEditorResponse(true)
411
+ }
412
+
413
+ return {
414
+ snippet: snippetResult.snippet,
415
+ filePath: activeEditor.getFilePath(),
416
+ language: activeEditor.getLanguage(),
417
+ cursorLine: snippetResult.cursorLine
418
+ }
419
+ } catch (err: any) {
420
+ return createNullEditorResponse(true)
421
+ }
422
+ }
423
+ }
424
+ })
425
+
@@ -0,0 +1,198 @@
1
+ import { registerAll } from "../core/commandregistry";
2
+ import { CommandContribution } from "../core/contributionregistry";
3
+ import { TOOLBAR_MAIN_RIGHT } from "../core/constants";
4
+ import { EditorInput, editorRegistry } from "../core/editorregistry";
5
+ import { html } from "lit";
6
+ import { toastError, toastInfo } from "../core/toast";
7
+ import { activeEditorSignal, activePartSignal } from "../core/appstate";
8
+ import { appSettings } from "../core/settingsservice";
9
+ import { extensionRegistry } from "../core/extensionregistry";
10
+ import type { Extension } from "../core/extensionregistry";
11
+ import { marketplaceRegistry } from "../core/marketplaceregistry";
12
+ import "./files";
13
+ import "./version-info";
14
+
15
+ registerAll({
16
+ command: {
17
+ "id": "save",
18
+ "name": "Save editor",
19
+ "description": "Saves the active/focused editor",
20
+ "keyBinding": "CTRL+S",
21
+ "parameters": []
22
+ },
23
+ handler: {
24
+ execute: async _context => {
25
+ const part = activeEditorSignal.get() || activePartSignal.get()
26
+ if (part && part.isDirty()) {
27
+ part.save()
28
+ }
29
+ }
30
+ },
31
+ contribution: {
32
+ target: "toolbar:.system.editors",
33
+ icon: "floppy-disk",
34
+ label: "Save active editor",
35
+ slot: "start",
36
+ disabled: () => {
37
+ const part = activePartSignal.get()
38
+ return !part || !part.isDirty()
39
+ }
40
+ } as CommandContribution
41
+ })
42
+
43
+ const THEME_SETTINGS_KEY = "theme"
44
+
45
+ async function applyTheme(themeClass: 'wa-dark' | 'wa-light'): Promise<void> {
46
+ const root = document.documentElement
47
+ root.classList.remove('wa-dark', 'wa-light')
48
+ root.classList.add(themeClass)
49
+ }
50
+
51
+ async function loadTheme(): Promise<void> {
52
+ const theme = await appSettings.get(THEME_SETTINGS_KEY)
53
+ await applyTheme(theme || 'wa-dark')
54
+ }
55
+
56
+ async function saveTheme(themeClass: 'wa-dark' | 'wa-light'): Promise<void> {
57
+ await appSettings.set(THEME_SETTINGS_KEY, themeClass)
58
+ }
59
+
60
+ registerAll({
61
+ command: {
62
+ "id": "switch_theme",
63
+ "name": "Switch theme",
64
+ "description": "Switches between dark and light theme",
65
+ "parameters": []
66
+ },
67
+ handler: {
68
+ execute: async _context => {
69
+ const isDark = document.documentElement.classList.contains("wa-dark")
70
+ const newTheme = isDark ? 'wa-light' : 'wa-dark'
71
+ await applyTheme(newTheme)
72
+ await saveTheme(newTheme)
73
+ }
74
+ },
75
+ contribution: {
76
+ target: TOOLBAR_MAIN_RIGHT,
77
+ icon: "circle-half-stroke",
78
+ label: "Theme Switcher",
79
+ }
80
+ })
81
+
82
+ // Load theme on module initialization
83
+ loadTheme().catch(err => {
84
+ console.error('Failed to load theme preference:', err)
85
+ })
86
+
87
+ registerAll({
88
+ command: {
89
+ "id": "fullscreen",
90
+ "name": "Toggle fullscreen",
91
+ "description": "Toggles fullscreen mode",
92
+ "parameters": []
93
+ },
94
+ handler: {
95
+ execute: async _context => {
96
+ if (document.fullscreenElement === document.body) {
97
+ await document.exitFullscreen()
98
+ } else {
99
+ await document.body.requestFullscreen()
100
+ }
101
+ }
102
+ },
103
+ contribution: {
104
+ target: TOOLBAR_MAIN_RIGHT,
105
+ icon: "expand",
106
+ label: "Fullscreen",
107
+ }
108
+ })
109
+
110
+ registerAll({
111
+ command: {
112
+ "id": "open_extensions",
113
+ "name": "Open Extensions",
114
+ "description": "Opens the extensions registry",
115
+ "parameters": []
116
+ },
117
+ handler: {
118
+ execute: _context => {
119
+ const editorInput: EditorInput = {
120
+ title: "Extensions",
121
+ data: {},
122
+ key: "system.extensions",
123
+ icon: "puzzle-piece",
124
+ state: {},
125
+ noOverflow: true,
126
+ widgetFactory: () => html`<lyra-extensions></lyra-extensions>`,
127
+ }
128
+ editorRegistry.loadEditor(editorInput, "extensions-editor").then()
129
+ }
130
+ },
131
+ contribution: {
132
+ target: TOOLBAR_MAIN_RIGHT,
133
+ icon: "puzzle-piece",
134
+ label: "Open Extensions",
135
+ }
136
+ })
137
+
138
+ registerAll({
139
+ command: {
140
+ "id": "list_extensions",
141
+ "name": "List extensions",
142
+ "description": "Lists all available extensions with their status (enabled/disabled)",
143
+ "parameters": [],
144
+ "output": [
145
+ {
146
+ "name": "extensions",
147
+ "description": "array of extension objects with id, name, description, experimental flag, and enabled status"
148
+ }
149
+ ]
150
+ },
151
+ handler: {
152
+ execute: async (_context: any) => {
153
+ const extensions = extensionRegistry.getExtensions().map((e: Extension) => {
154
+ return {
155
+ id: e.id,
156
+ name: e.name,
157
+ description: e.description,
158
+ experimental: e.experimental,
159
+ enabled: extensionRegistry.isEnabled(e.id)
160
+ }
161
+ });
162
+ return extensions;
163
+ }
164
+ }
165
+ })
166
+
167
+ registerAll({
168
+ command: {
169
+ "id": "toast_message",
170
+ "name": "Toast message to user",
171
+ "description": "Shows a toast message",
172
+ "parameters": [
173
+ {
174
+ "name": "message",
175
+ "description": "the message to toast",
176
+ "required": true
177
+ },
178
+ {
179
+ "name": "type",
180
+ "description": "the toast type: info (default), or error",
181
+ "required": false
182
+ }
183
+ ]
184
+ },
185
+ handler: {
186
+ execute: ({ params: { message, type } }: any) => {
187
+ if (!message) {
188
+ return
189
+ }
190
+ if (type === "error") {
191
+ toastError(message)
192
+ } else {
193
+ toastInfo(message)
194
+ }
195
+ }
196
+ }
197
+ })
198
+
@@ -0,0 +1,6 @@
1
+ import "./editor";
2
+ import "./files";
3
+ import "./global";
4
+ import "./open-view-as-editor";
5
+ import "./version-info";
6
+
@@ -0,0 +1,28 @@
1
+ import { registerAll } from "../core/commandregistry";
2
+ import { SYSTEM_VIEWS } from "../core/constants";
3
+ import type { TabContribution } from "../core/contributionregistry";
4
+ import { contributionRegistry } from "../core/contributionregistry";
5
+ import { editorRegistry } from "../core/editorregistry";
6
+
7
+ registerAll({
8
+ command: {
9
+ id: "open_view_as_editor",
10
+ name: "Open view as editor",
11
+ description: "Opens a dashboard view in the editor area",
12
+ parameters: [
13
+ { name: "name", description: "View contribution name", required: true },
14
+ { name: "sourceContributionSlot", description: "source contribution slot (default: SYSTEM_VIEWS)", required: false }
15
+ ]
16
+ },
17
+ handler: {
18
+ execute: async ({ params }: { params?: { name?: string, sourceContributionSlot?: string } }) => {
19
+ const name = params?.name;
20
+ if (!name) return;
21
+ const slot = params?.sourceContributionSlot ?? SYSTEM_VIEWS
22
+ const contributions = contributionRegistry.getContributions(slot) as TabContribution[];
23
+ const contribution = contributions.find(c => c.name === name);
24
+ if (!contribution?.component) return;
25
+ await editorRegistry.openTab(contribution as TabContribution);
26
+ }
27
+ }
28
+ });