@kispace-io/core 0.7.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/dist/api/base-classes.d.ts +7 -0
- package/dist/api/base-classes.d.ts.map +1 -0
- package/dist/api/constants.d.ts +2 -0
- package/dist/api/constants.d.ts.map +1 -0
- package/dist/api/index.d.ts +6 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +80 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/services.d.ts +27 -0
- package/dist/api/services.d.ts.map +1 -0
- package/dist/api/types.d.ts +11 -0
- package/dist/api/types.d.ts.map +1 -0
- package/dist/commands/files.d.ts +2 -0
- package/dist/commands/files.d.ts.map +1 -0
- package/dist/commands/global.d.ts +1 -0
- package/dist/commands/global.d.ts.map +1 -0
- package/dist/commands/index.d.ts +1 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/version-info.d.ts +2 -0
- package/dist/commands/version-info.d.ts.map +1 -0
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/k-app-selector.d.ts +17 -0
- package/dist/components/k-app-selector.d.ts.map +1 -0
- package/dist/components/k-app-switcher.d.ts +13 -0
- package/dist/components/k-app-switcher.d.ts.map +1 -0
- package/dist/components/k-command.d.ts +31 -0
- package/dist/components/k-command.d.ts.map +1 -0
- package/dist/components/k-extensions.d.ts +32 -0
- package/dist/components/k-extensions.d.ts.map +1 -0
- package/dist/components/k-fastviews.d.ts +34 -0
- package/dist/components/k-fastviews.d.ts.map +1 -0
- package/dist/components/k-filebrowser.d.ts +40 -0
- package/dist/components/k-filebrowser.d.ts.map +1 -0
- package/dist/components/k-language-selector.d.ts +12 -0
- package/dist/components/k-language-selector.d.ts.map +1 -0
- package/dist/components/k-log-terminal.d.ts +36 -0
- package/dist/components/k-log-terminal.d.ts.map +1 -0
- package/dist/components/k-part-name.d.ts +12 -0
- package/dist/components/k-part-name.d.ts.map +1 -0
- package/dist/components/k-tasks.d.ts +13 -0
- package/dist/components/k-tasks.d.ts.map +1 -0
- package/dist/components/k-workspace-name.d.ts +14 -0
- package/dist/components/k-workspace-name.d.ts.map +1 -0
- package/dist/contributions/default-ui-contributions.d.ts +2 -0
- package/dist/contributions/default-ui-contributions.d.ts.map +1 -0
- package/dist/contributions/index.d.ts +1 -0
- package/dist/contributions/index.d.ts.map +1 -0
- package/dist/contributions/marketplace-catalog-contributions.d.ts +2 -0
- package/dist/contributions/marketplace-catalog-contributions.d.ts.map +1 -0
- package/dist/core/app-host-config.d.ts +7 -0
- package/dist/core/app-host-config.d.ts.map +1 -0
- package/dist/core/apploader.d.ts +214 -0
- package/dist/core/apploader.d.ts.map +1 -0
- package/dist/core/appstate.d.ts +12 -0
- package/dist/core/appstate.d.ts.map +1 -0
- package/dist/core/commandregistry.d.ts +79 -0
- package/dist/core/commandregistry.d.ts.map +1 -0
- package/dist/core/config.d.ts +15 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/constants.d.ts +21 -0
- package/dist/core/constants.d.ts.map +1 -0
- package/dist/core/contributionregistry.d.ts +49 -0
- package/dist/core/contributionregistry.d.ts.map +1 -0
- package/dist/core/di.d.ts +18 -0
- package/dist/core/di.d.ts.map +1 -0
- package/dist/core/dialogservice.d.ts +33 -0
- package/dist/core/dialogservice.d.ts.map +1 -0
- package/dist/core/editorregistry.d.ts +73 -0
- package/dist/core/editorregistry.d.ts.map +1 -0
- package/dist/core/esmsh-service.d.ts +40 -0
- package/dist/core/esmsh-service.d.ts.map +1 -0
- package/dist/core/events.d.ts +7 -0
- package/dist/core/events.d.ts.map +1 -0
- package/dist/core/events.js +63 -0
- package/dist/core/events.js.map +1 -0
- package/dist/core/extensionregistry.d.ts +98 -0
- package/dist/core/extensionregistry.d.ts.map +1 -0
- package/dist/core/filesys.d.ts +139 -0
- package/dist/core/filesys.d.ts.map +1 -0
- package/dist/core/i18n.d.ts +50 -0
- package/dist/core/i18n.d.ts.map +1 -0
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/k-utils.d.ts +2 -0
- package/dist/core/k-utils.d.ts.map +1 -0
- package/dist/core/keybindings.d.ts +67 -0
- package/dist/core/keybindings.d.ts.map +1 -0
- package/dist/core/logger.d.ts +44 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/marketplaceregistry.d.ts +25 -0
- package/dist/core/marketplaceregistry.d.ts.map +1 -0
- package/dist/core/packageinfoservice.d.ts +16 -0
- package/dist/core/packageinfoservice.d.ts.map +1 -0
- package/dist/core/persistenceservice.d.ts +6 -0
- package/dist/core/persistenceservice.d.ts.map +1 -0
- package/dist/core/settingsservice.d.ts +19 -0
- package/dist/core/settingsservice.d.ts.map +1 -0
- package/dist/core/signals.d.ts +3 -0
- package/dist/core/signals.d.ts.map +1 -0
- package/dist/core/taskservice.d.ts +20 -0
- package/dist/core/taskservice.d.ts.map +1 -0
- package/dist/core/toast.d.ts +4 -0
- package/dist/core/toast.d.ts.map +1 -0
- package/dist/core/tree-utils.d.ts +16 -0
- package/dist/core/tree-utils.d.ts.map +1 -0
- package/dist/dialogs/confirm-dialog.d.ts +14 -0
- package/dist/dialogs/confirm-dialog.d.ts.map +1 -0
- package/dist/dialogs/index.d.ts +5 -0
- package/dist/dialogs/index.d.ts.map +1 -0
- package/dist/dialogs/info-dialog.d.ts +13 -0
- package/dist/dialogs/info-dialog.d.ts.map +1 -0
- package/dist/dialogs/navigable-info-dialog.d.ts +33 -0
- package/dist/dialogs/navigable-info-dialog.d.ts.map +1 -0
- package/dist/dialogs/prompt-dialog.d.ts +21 -0
- package/dist/dialogs/prompt-dialog.d.ts.map +1 -0
- package/dist/externals/lit.d.ts +20 -0
- package/dist/externals/lit.d.ts.map +1 -0
- package/dist/externals/lit.js +15 -0
- package/dist/externals/lit.js.map +1 -0
- package/dist/externals/third-party.d.ts +7 -0
- package/dist/externals/third-party.d.ts.map +1 -0
- package/dist/externals/third-party.js +2 -0
- package/dist/externals/third-party.js.map +1 -0
- package/dist/externals/webawesome.d.ts +1 -0
- package/dist/externals/webawesome.d.ts.map +1 -0
- package/dist/externals/webawesome.js +52 -0
- package/dist/externals/webawesome.js.map +1 -0
- package/dist/i18n/extensions.json.d.ts +42 -0
- package/dist/i18n/fastviews.json.d.ts +13 -0
- package/dist/i18n/filebrowser.json.d.ts +35 -0
- package/dist/i18n/index.d.ts +2 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/logterminal.json.d.ts +45 -0
- package/dist/i18n/partname.json.d.ts +15 -0
- package/dist/i18n/tasks.json.d.ts +15 -0
- package/dist/i18n/workspace.json.d.ts +15 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +80 -0
- package/dist/index.js.map +1 -0
- package/dist/k-icon-BZC7dQV0.js +492 -0
- package/dist/k-icon-BZC7dQV0.js.map +1 -0
- package/dist/k-nocontent-Bh_yToGh.js +48 -0
- package/dist/k-nocontent-Bh_yToGh.js.map +1 -0
- package/dist/k-resizable-grid-Ch3iWZaL.js +3157 -0
- package/dist/k-resizable-grid-Ch3iWZaL.js.map +1 -0
- package/dist/k-standard-layout-CQ1VZoxa.js +5011 -0
- package/dist/k-standard-layout-CQ1VZoxa.js.map +1 -0
- package/dist/layouts/k-standard-layout.d.ts +16 -0
- package/dist/layouts/k-standard-layout.d.ts.map +1 -0
- package/dist/parts/index.d.ts +1 -0
- package/dist/parts/index.d.ts.map +1 -0
- package/dist/parts/index.js +53 -0
- package/dist/parts/index.js.map +1 -0
- package/dist/parts/k-app.d.ts +11 -0
- package/dist/parts/k-app.d.ts.map +1 -0
- package/dist/parts/k-container.d.ts +4 -0
- package/dist/parts/k-container.d.ts.map +1 -0
- package/dist/parts/k-contextmenu.d.ts +38 -0
- package/dist/parts/k-contextmenu.d.ts.map +1 -0
- package/dist/parts/k-dialog-content.d.ts +9 -0
- package/dist/parts/k-dialog-content.d.ts.map +1 -0
- package/dist/parts/k-element.d.ts +36 -0
- package/dist/parts/k-element.d.ts.map +1 -0
- package/dist/parts/k-part.d.ts +96 -0
- package/dist/parts/k-part.d.ts.map +1 -0
- package/dist/parts/k-resizable-grid.d.ts +31 -0
- package/dist/parts/k-resizable-grid.d.ts.map +1 -0
- package/dist/parts/k-tabs.d.ts +74 -0
- package/dist/parts/k-tabs.d.ts.map +1 -0
- package/dist/parts/k-toolbar.d.ts +21 -0
- package/dist/parts/k-toolbar.d.ts.map +1 -0
- package/dist/widgets/index.d.ts +1 -0
- package/dist/widgets/index.d.ts.map +1 -0
- package/dist/widgets/index.js +3 -0
- package/dist/widgets/index.js.map +1 -0
- package/dist/widgets/k-icon.d.ts +10 -0
- package/dist/widgets/k-icon.d.ts.map +1 -0
- package/dist/widgets/k-nocontent.d.ts +13 -0
- package/dist/widgets/k-nocontent.d.ts.map +1 -0
- package/dist/widgets/k-widget.d.ts +25 -0
- package/dist/widgets/k-widget.d.ts.map +1 -0
- package/package.json +81 -0
- package/src/api/base-classes.ts +10 -0
- package/src/api/constants.ts +3 -0
- package/src/api/index.ts +31 -0
- package/src/api/services.ts +52 -0
- package/src/api/types.ts +46 -0
- package/src/commands/files.ts +829 -0
- package/src/commands/global.ts +225 -0
- package/src/commands/index.ts +4 -0
- package/src/commands/version-info.ts +214 -0
- package/src/components/index.ts +10 -0
- package/src/components/k-app-selector.ts +233 -0
- package/src/components/k-app-switcher.ts +126 -0
- package/src/components/k-command.ts +236 -0
- package/src/components/k-extensions.ts +615 -0
- package/src/components/k-fastviews.ts +314 -0
- package/src/components/k-filebrowser.ts +442 -0
- package/src/components/k-language-selector.ts +166 -0
- package/src/components/k-log-terminal.ts +337 -0
- package/src/components/k-part-name.ts +54 -0
- package/src/components/k-tasks.ts +267 -0
- package/src/components/k-workspace-name.ts +56 -0
- package/src/contributions/default-ui-contributions.ts +51 -0
- package/src/contributions/index.ts +3 -0
- package/src/contributions/marketplace-catalog-contributions.ts +6 -0
- package/src/core/app-host-config.ts +23 -0
- package/src/core/apploader.ts +630 -0
- package/src/core/appstate.ts +15 -0
- package/src/core/commandregistry.ts +210 -0
- package/src/core/config.ts +29 -0
- package/src/core/constants.ts +27 -0
- package/src/core/contributionregistry.ts +77 -0
- package/src/core/di.ts +54 -0
- package/src/core/dialogservice.ts +266 -0
- package/src/core/editorregistry.ts +303 -0
- package/src/core/esmsh-service.ts +404 -0
- package/src/core/events.ts +68 -0
- package/src/core/extensionregistry.ts +399 -0
- package/src/core/filesys.ts +618 -0
- package/src/core/i18n.ts +221 -0
- package/src/core/index.ts +51 -0
- package/src/core/k-utils.ts +11 -0
- package/src/core/keybindings.ts +274 -0
- package/src/core/logger.ts +187 -0
- package/src/core/marketplaceregistry.ts +197 -0
- package/src/core/packageinfoservice.ts +56 -0
- package/src/core/persistenceservice.ts +15 -0
- package/src/core/settingsservice.ts +70 -0
- package/src/core/signals.ts +18 -0
- package/src/core/taskservice.ts +72 -0
- package/src/core/toast.ts +11 -0
- package/src/core/tree-utils.ts +24 -0
- package/src/dialogs/confirm-dialog.ts +72 -0
- package/src/dialogs/index.ts +4 -0
- package/src/dialogs/info-dialog.ts +67 -0
- package/src/dialogs/navigable-info-dialog.ts +256 -0
- package/src/dialogs/prompt-dialog.ts +123 -0
- package/src/externals/lit.ts +26 -0
- package/src/externals/third-party.ts +9 -0
- package/src/externals/webawesome.ts +54 -0
- package/src/i18n/extensions.json +39 -0
- package/src/i18n/fastviews.json +10 -0
- package/src/i18n/filebrowser.json +33 -0
- package/src/i18n/index.ts +25 -0
- package/src/i18n/logterminal.json +42 -0
- package/src/i18n/partname.json +12 -0
- package/src/i18n/tasks.json +12 -0
- package/src/i18n/workspace.json +12 -0
- package/src/icons/icons.txt +3 -0
- package/src/icons/js.svg +6 -0
- package/src/icons/jupyter.svg +18 -0
- package/src/icons/python.svg +15 -0
- package/src/index.ts +3 -0
- package/src/layouts/k-standard-layout.ts +174 -0
- package/src/parts/index.ts +6 -0
- package/src/parts/k-app.ts +29 -0
- package/src/parts/k-container.ts +4 -0
- package/src/parts/k-contextmenu.ts +245 -0
- package/src/parts/k-dialog-content.ts +31 -0
- package/src/parts/k-element.ts +100 -0
- package/src/parts/k-part.ts +158 -0
- package/src/parts/k-resizable-grid.ts +366 -0
- package/src/parts/k-tabs.ts +574 -0
- package/src/parts/k-toolbar.ts +158 -0
- package/src/vite-env.d.ts +2 -0
- package/src/widgets/index.ts +2 -0
- package/src/widgets/k-icon.ts +39 -0
- package/src/widgets/k-nocontent.ts +40 -0
- package/src/widgets/k-widget.ts +90 -0
|
@@ -0,0 +1,829 @@
|
|
|
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 {promptDialog, confirmDialog} from "../dialogs";
|
|
5
|
+
import {activeSelectionSignal} from "../core/appstate";
|
|
6
|
+
import {editorRegistry, EditorContentProvider} from "../core/editorregistry";
|
|
7
|
+
import logger from "../core/logger";
|
|
8
|
+
|
|
9
|
+
async function getWorkspaceAndPath(params: any, requirePath: boolean = true): Promise<{workspace: Directory, path: string} | null> {
|
|
10
|
+
const workspace = await workspaceService.getWorkspace()
|
|
11
|
+
if (!workspace) {
|
|
12
|
+
return null
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const path = params?.path
|
|
16
|
+
if (requirePath && !path) {
|
|
17
|
+
return null
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return { workspace, path: path || '' }
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Type guard to check if an editor implements EditorContentProvider
|
|
25
|
+
*/
|
|
26
|
+
function isEditorContentProvider(editor: any): editor is EditorContentProvider {
|
|
27
|
+
return editor &&
|
|
28
|
+
typeof editor.getContent === 'function' &&
|
|
29
|
+
typeof editor.getSelection === 'function' &&
|
|
30
|
+
typeof editor.getSnippet === 'function' &&
|
|
31
|
+
typeof editor.getLanguage === 'function' &&
|
|
32
|
+
typeof editor.getFilePath === 'function';
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Helper to get a resource from path or active selection
|
|
37
|
+
*/
|
|
38
|
+
async function getResourceFromContext(context: ExecutionContext, params?: any): Promise<any> {
|
|
39
|
+
let resource = undefined
|
|
40
|
+
const path = params?.path || context.params?.["path"]
|
|
41
|
+
|
|
42
|
+
if (path) {
|
|
43
|
+
const workspaceDir = await workspaceService.getWorkspace()
|
|
44
|
+
if (workspaceDir) {
|
|
45
|
+
resource = await workspaceDir.getResource(path)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (!resource) {
|
|
50
|
+
resource = activeSelectionSignal.get()
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return resource
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Helper to read text file contents with error handling
|
|
58
|
+
*/
|
|
59
|
+
async function readTextFile(file: File): Promise<string | null> {
|
|
60
|
+
try {
|
|
61
|
+
const contents = await file.getContents()
|
|
62
|
+
if (typeof contents !== 'string') {
|
|
63
|
+
toastError("File is not a text file")
|
|
64
|
+
return null
|
|
65
|
+
}
|
|
66
|
+
return contents
|
|
67
|
+
} catch (err: any) {
|
|
68
|
+
toastError(`Failed to read file: ${err.message}`)
|
|
69
|
+
return null
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Helper to create null editor response
|
|
75
|
+
*/
|
|
76
|
+
function createNullEditorResponse(includeCursorLine: boolean = false) {
|
|
77
|
+
const base = {
|
|
78
|
+
filePath: null,
|
|
79
|
+
language: null
|
|
80
|
+
}
|
|
81
|
+
if (includeCursorLine) {
|
|
82
|
+
return { ...base, snippet: null, cursorLine: null }
|
|
83
|
+
}
|
|
84
|
+
return base
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
async function getWorkspaceAndFile(params: any, requirePath: boolean = true): Promise<{workspace: Directory, path: string, file: File} | null> {
|
|
88
|
+
const result = await getWorkspaceAndPath(params, requirePath)
|
|
89
|
+
if (!result) {
|
|
90
|
+
return null
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const { workspace, path } = result
|
|
94
|
+
|
|
95
|
+
if (!path) {
|
|
96
|
+
return null
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
try {
|
|
100
|
+
const resource = await workspace.getResource(path)
|
|
101
|
+
if (!resource || !(resource instanceof File)) {
|
|
102
|
+
return null
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return { workspace, path, file: resource }
|
|
106
|
+
} catch (err: any) {
|
|
107
|
+
return null
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
registerAll({
|
|
112
|
+
command: {
|
|
113
|
+
"id": "create_file",
|
|
114
|
+
"name": "Create new file",
|
|
115
|
+
"description": "Creates a new file within the workspace. For .geospace map files, use create_map_file instead.",
|
|
116
|
+
"keyBinding": "CTRL+N",
|
|
117
|
+
"parameters": [
|
|
118
|
+
{
|
|
119
|
+
"name": "path",
|
|
120
|
+
"description": "the path including name of the file to be created, must be relative to the workspace",
|
|
121
|
+
"required": false
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"name": "contents",
|
|
125
|
+
"description": "the textual contents of the file",
|
|
126
|
+
"required": false
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"name": "ask",
|
|
130
|
+
"description": "whether to prompt the user for the file path",
|
|
131
|
+
"required": false
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
"name": "extension",
|
|
135
|
+
"description": "required file extension (e.g., '.geospace'), will be appended if missing",
|
|
136
|
+
"required": false
|
|
137
|
+
}
|
|
138
|
+
],
|
|
139
|
+
"output": [
|
|
140
|
+
{
|
|
141
|
+
"name": "path",
|
|
142
|
+
"description": "the path of the created file"
|
|
143
|
+
}
|
|
144
|
+
]
|
|
145
|
+
},
|
|
146
|
+
handler: {
|
|
147
|
+
execute: async ({params}: any) => {
|
|
148
|
+
let path = params?.path
|
|
149
|
+
const contents = params?.contents
|
|
150
|
+
const ask = params?.ask
|
|
151
|
+
const extension = params?.extension
|
|
152
|
+
|
|
153
|
+
if (ask || !path) {
|
|
154
|
+
path = await promptDialog("Enter path to new file (directories will be created if not exist):", path || "")
|
|
155
|
+
if (!path) {
|
|
156
|
+
return
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (extension && !path.endsWith(extension)) {
|
|
161
|
+
path += extension
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const result = await getWorkspaceAndPath({path}, true)
|
|
165
|
+
if (!result) {
|
|
166
|
+
return
|
|
167
|
+
}
|
|
168
|
+
const { workspace: workspaceDir } = result
|
|
169
|
+
|
|
170
|
+
const existingResource = await workspaceDir.getResource(path)
|
|
171
|
+
if (existingResource) {
|
|
172
|
+
const overwrite = await confirmDialog(`File "${path}" already exists. Do you want to overwrite it?`)
|
|
173
|
+
if (!overwrite) {
|
|
174
|
+
return
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const createdResource = await workspaceDir.getResource(path, {create: true})
|
|
179
|
+
if (!createdResource) {
|
|
180
|
+
toastError("Could not create file: " + path)
|
|
181
|
+
} else {
|
|
182
|
+
if (contents) {
|
|
183
|
+
await (createdResource as File).saveContents(contents)
|
|
184
|
+
}
|
|
185
|
+
logger.info("File created: " + path)
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return path
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
})
|
|
192
|
+
|
|
193
|
+
registerAll({
|
|
194
|
+
command: {
|
|
195
|
+
"id": "rename_resource",
|
|
196
|
+
"name": "Rename a resource (file or directory)",
|
|
197
|
+
"description": "Renames a resource (file or directory)",
|
|
198
|
+
"keyBinding": "F2",
|
|
199
|
+
"parameters": [
|
|
200
|
+
{
|
|
201
|
+
"name": "path",
|
|
202
|
+
"description": "the path of the resource within the workspace to rename or the currently active selection",
|
|
203
|
+
"required": false
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
"name": "newName",
|
|
207
|
+
"description": "the new name for the resource",
|
|
208
|
+
"required": false
|
|
209
|
+
}
|
|
210
|
+
]
|
|
211
|
+
},
|
|
212
|
+
handler: {
|
|
213
|
+
execute: async context => {
|
|
214
|
+
const resource = await getResourceFromContext(context)
|
|
215
|
+
if (!resource) {
|
|
216
|
+
toastError("No resource to rename provided!")
|
|
217
|
+
return
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const currentName = resource.getName()
|
|
221
|
+
const newName = context.params?.newName ||
|
|
222
|
+
await promptDialog(`Enter new name for "${currentName}":`, currentName)
|
|
223
|
+
|
|
224
|
+
if (!newName || newName === currentName) {
|
|
225
|
+
return
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
try {
|
|
229
|
+
await resource.rename(newName)
|
|
230
|
+
toastInfo(`Resource renamed to: ${newName}`)
|
|
231
|
+
} catch (err: any) {
|
|
232
|
+
toastError(`Failed to rename ${currentName}: ${err.message}`)
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
})
|
|
237
|
+
|
|
238
|
+
registerAll({
|
|
239
|
+
command: {
|
|
240
|
+
"id": "delete_resource",
|
|
241
|
+
"name": "Delete a resource (file or directory)",
|
|
242
|
+
"description": "Deletes a resource (file or directory)",
|
|
243
|
+
"parameters": [
|
|
244
|
+
{
|
|
245
|
+
"name": "path",
|
|
246
|
+
"description": "the path of the resource within the workspace to delete or the currently active selection",
|
|
247
|
+
"required": false
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
"name": "confirm",
|
|
251
|
+
"description": "whether to ask the user to confirm the deletion, true by default",
|
|
252
|
+
"required": false
|
|
253
|
+
}
|
|
254
|
+
]
|
|
255
|
+
},
|
|
256
|
+
handler: {
|
|
257
|
+
execute: async context => {
|
|
258
|
+
const resource = await getResourceFromContext(context)
|
|
259
|
+
if (!resource) {
|
|
260
|
+
toastError("No resource to delete provided!")
|
|
261
|
+
return
|
|
262
|
+
}
|
|
263
|
+
const path = resource.getWorkspacePath()
|
|
264
|
+
const confirmParam = context.params && context.params["confirm"]
|
|
265
|
+
let yes = true
|
|
266
|
+
if (confirmParam === undefined || confirmParam === true) {
|
|
267
|
+
yes = await confirmDialog(`Are you sure you want to delete ${path}?`)
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
if (yes) {
|
|
271
|
+
try {
|
|
272
|
+
await resource.delete()
|
|
273
|
+
toastInfo("Resource deleted: " + path)
|
|
274
|
+
} catch (err: any) {
|
|
275
|
+
toastError(`Resource ${path} could not be deleted: ${err.message || err}`)
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
})
|
|
281
|
+
|
|
282
|
+
// Register local filesystem workspace contribution
|
|
283
|
+
registerAll({
|
|
284
|
+
command: {
|
|
285
|
+
"id": "load_workspace",
|
|
286
|
+
"name": "Local Folder",
|
|
287
|
+
"description": "Connect to a local folder using File System Access API",
|
|
288
|
+
"parameters": []
|
|
289
|
+
},
|
|
290
|
+
handler: {
|
|
291
|
+
execute: async _context => {
|
|
292
|
+
// @ts-ignore
|
|
293
|
+
await window.showDirectoryPicker({
|
|
294
|
+
mode: "readwrite"
|
|
295
|
+
}).then((dirHandle: FileSystemDirectoryHandle) => {
|
|
296
|
+
return workspaceService.connectWorkspace(dirHandle);
|
|
297
|
+
}).catch((err: Error) => {
|
|
298
|
+
toastError(err.message)
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
},
|
|
302
|
+
contribution: {
|
|
303
|
+
target: "filebrowser.connections",
|
|
304
|
+
label: "Local Folder",
|
|
305
|
+
icon: "folder-open"
|
|
306
|
+
}
|
|
307
|
+
})
|
|
308
|
+
|
|
309
|
+
registerAll({
|
|
310
|
+
command: {
|
|
311
|
+
"id": "reload_workspace",
|
|
312
|
+
"name": "Reload workspace folder",
|
|
313
|
+
"description": "Reloads the active workspace folder",
|
|
314
|
+
"parameters": []
|
|
315
|
+
},
|
|
316
|
+
handler: {
|
|
317
|
+
execute: async _context => {
|
|
318
|
+
const workspace = await workspaceService.getWorkspace()
|
|
319
|
+
if (!workspace) {
|
|
320
|
+
toastError("No workspace selected.")
|
|
321
|
+
}
|
|
322
|
+
workspace!.touch()
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
})
|
|
326
|
+
|
|
327
|
+
registerAll({
|
|
328
|
+
command: {
|
|
329
|
+
"id": "open_editor",
|
|
330
|
+
"name": "Open editor",
|
|
331
|
+
"description": "Opens a file in an editor",
|
|
332
|
+
"parameters": [
|
|
333
|
+
{
|
|
334
|
+
"name": "path",
|
|
335
|
+
"description": "tha path of the file to open within the workspace",
|
|
336
|
+
"required": true
|
|
337
|
+
}
|
|
338
|
+
]
|
|
339
|
+
},
|
|
340
|
+
handler: {
|
|
341
|
+
execute: async context => {
|
|
342
|
+
const result = await getWorkspaceAndFile({path: context.params?.["path"]})
|
|
343
|
+
if (!result) {
|
|
344
|
+
return
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
const { file } = result
|
|
348
|
+
await editorRegistry.loadEditor(file)
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
})
|
|
352
|
+
|
|
353
|
+
registerAll({
|
|
354
|
+
command: {
|
|
355
|
+
"id": "head_file",
|
|
356
|
+
"name": "Head - Show first lines",
|
|
357
|
+
"description": "Shows the first N lines of a file",
|
|
358
|
+
"parameters": [
|
|
359
|
+
{
|
|
360
|
+
"name": "path",
|
|
361
|
+
"description": "the path of the file to read",
|
|
362
|
+
"required": true
|
|
363
|
+
},
|
|
364
|
+
{
|
|
365
|
+
"name": "lines",
|
|
366
|
+
"description": "number of lines to show from the beginning (default: 10)",
|
|
367
|
+
"type": "number",
|
|
368
|
+
"required": false
|
|
369
|
+
}
|
|
370
|
+
],
|
|
371
|
+
"output": [
|
|
372
|
+
{
|
|
373
|
+
"name": "content",
|
|
374
|
+
"description": "the first N lines of the file"
|
|
375
|
+
}
|
|
376
|
+
]
|
|
377
|
+
},
|
|
378
|
+
handler: {
|
|
379
|
+
execute: async ({params}: any) => {
|
|
380
|
+
const result = await getWorkspaceAndFile(params)
|
|
381
|
+
if (!result) {
|
|
382
|
+
return
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
const { file } = result
|
|
386
|
+
const numLines = params?.lines ? parseInt(params.lines, 10) : 10
|
|
387
|
+
if (isNaN(numLines) || numLines < 1) {
|
|
388
|
+
toastError("Number of lines must be a positive integer")
|
|
389
|
+
return
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
const contents = await readTextFile(file)
|
|
393
|
+
if (!contents) {
|
|
394
|
+
return
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
const lines = contents.split('\n')
|
|
398
|
+
const headLines = lines.slice(0, numLines).join('\n')
|
|
399
|
+
return headLines
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
})
|
|
403
|
+
|
|
404
|
+
registerAll({
|
|
405
|
+
command: {
|
|
406
|
+
"id": "tail_file",
|
|
407
|
+
"name": "Tail - Show last lines",
|
|
408
|
+
"description": "Shows the last N lines of a file",
|
|
409
|
+
"parameters": [
|
|
410
|
+
{
|
|
411
|
+
"name": "path",
|
|
412
|
+
"description": "the path of the file to read",
|
|
413
|
+
"required": true
|
|
414
|
+
},
|
|
415
|
+
{
|
|
416
|
+
"name": "lines",
|
|
417
|
+
"description": "number of lines to show from the end (default: 10)",
|
|
418
|
+
"type": "number",
|
|
419
|
+
"required": false
|
|
420
|
+
}
|
|
421
|
+
],
|
|
422
|
+
"output": [
|
|
423
|
+
{
|
|
424
|
+
"name": "content",
|
|
425
|
+
"description": "the last N lines of the file"
|
|
426
|
+
}
|
|
427
|
+
]
|
|
428
|
+
},
|
|
429
|
+
handler: {
|
|
430
|
+
execute: async ({params}: any) => {
|
|
431
|
+
const result = await getWorkspaceAndFile(params)
|
|
432
|
+
if (!result) {
|
|
433
|
+
return
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
const { file } = result
|
|
437
|
+
const numLines = params?.lines ? parseInt(params.lines, 10) : 10
|
|
438
|
+
if (isNaN(numLines) || numLines < 1) {
|
|
439
|
+
toastError("Number of lines must be a positive integer")
|
|
440
|
+
return
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
const contents = await readTextFile(file)
|
|
444
|
+
if (!contents) {
|
|
445
|
+
return
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
const lines = contents.split('\n')
|
|
449
|
+
const tailLines = lines.slice(-numLines).join('\n')
|
|
450
|
+
return tailLines
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
})
|
|
454
|
+
|
|
455
|
+
registerAll({
|
|
456
|
+
command: {
|
|
457
|
+
"id": "cat_file",
|
|
458
|
+
"name": "Cat - Show file contents",
|
|
459
|
+
"description": "Shows the complete contents of a file",
|
|
460
|
+
"parameters": [
|
|
461
|
+
{
|
|
462
|
+
"name": "path",
|
|
463
|
+
"description": "the path of the file to read",
|
|
464
|
+
"required": true
|
|
465
|
+
}
|
|
466
|
+
],
|
|
467
|
+
"output": [
|
|
468
|
+
{
|
|
469
|
+
"name": "content",
|
|
470
|
+
"description": "the complete contents of the file"
|
|
471
|
+
}
|
|
472
|
+
]
|
|
473
|
+
},
|
|
474
|
+
handler: {
|
|
475
|
+
execute: async ({params}: any) => {
|
|
476
|
+
const result = await getWorkspaceAndFile(params)
|
|
477
|
+
if (!result) {
|
|
478
|
+
return
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
const { file } = result
|
|
482
|
+
|
|
483
|
+
return await readTextFile(file)
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
})
|
|
487
|
+
|
|
488
|
+
registerAll({
|
|
489
|
+
command: {
|
|
490
|
+
"id": "wc_file",
|
|
491
|
+
"name": "Word count",
|
|
492
|
+
"description": "Counts lines, words, and characters in a file",
|
|
493
|
+
"parameters": [
|
|
494
|
+
{
|
|
495
|
+
"name": "path",
|
|
496
|
+
"description": "the path of the file to analyze",
|
|
497
|
+
"required": true
|
|
498
|
+
}
|
|
499
|
+
],
|
|
500
|
+
"output": [
|
|
501
|
+
{
|
|
502
|
+
"name": "lines",
|
|
503
|
+
"description": "number of lines in the file"
|
|
504
|
+
},
|
|
505
|
+
{
|
|
506
|
+
"name": "words",
|
|
507
|
+
"description": "number of words in the file"
|
|
508
|
+
},
|
|
509
|
+
{
|
|
510
|
+
"name": "characters",
|
|
511
|
+
"description": "number of characters in the file"
|
|
512
|
+
}
|
|
513
|
+
]
|
|
514
|
+
},
|
|
515
|
+
handler: {
|
|
516
|
+
execute: async ({params}: any) => {
|
|
517
|
+
const result = await getWorkspaceAndFile(params)
|
|
518
|
+
if (!result) {
|
|
519
|
+
return
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
const { file } = result
|
|
523
|
+
|
|
524
|
+
const contents = await readTextFile(file)
|
|
525
|
+
if (!contents) {
|
|
526
|
+
return
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
const lines = contents.split('\n')
|
|
530
|
+
const lineCount = lines.length
|
|
531
|
+
const wordCount = contents.trim() === '' ? 0 : contents.trim().split(/\s+/).filter(w => w.length > 0).length
|
|
532
|
+
const charCount = contents.length
|
|
533
|
+
|
|
534
|
+
return {
|
|
535
|
+
lines: lineCount,
|
|
536
|
+
words: wordCount,
|
|
537
|
+
characters: charCount
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
})
|
|
542
|
+
|
|
543
|
+
registerAll({
|
|
544
|
+
command: {
|
|
545
|
+
"id": "file_exists",
|
|
546
|
+
"name": "Check if file exists",
|
|
547
|
+
"description": "Checks if a file exists at the given path",
|
|
548
|
+
"parameters": [
|
|
549
|
+
{
|
|
550
|
+
"name": "path",
|
|
551
|
+
"description": "the path of the file to check, relative to the workspace",
|
|
552
|
+
"required": true
|
|
553
|
+
}
|
|
554
|
+
],
|
|
555
|
+
"output": [
|
|
556
|
+
{
|
|
557
|
+
"name": "exists",
|
|
558
|
+
"description": "true if the file exists, false otherwise"
|
|
559
|
+
}
|
|
560
|
+
]
|
|
561
|
+
},
|
|
562
|
+
handler: {
|
|
563
|
+
execute: async ({params}: any) => {
|
|
564
|
+
const result = await getWorkspaceAndPath(params)
|
|
565
|
+
if (!result) {
|
|
566
|
+
return false
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
const { workspace, path } = result
|
|
570
|
+
|
|
571
|
+
try {
|
|
572
|
+
const resource = await workspace.getResource(path)
|
|
573
|
+
return resource instanceof File
|
|
574
|
+
} catch (err: any) {
|
|
575
|
+
return false
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
})
|
|
580
|
+
|
|
581
|
+
async function collectFilesRecursive(directory: Directory): Promise<string[]> {
|
|
582
|
+
const files: string[] = []
|
|
583
|
+
const children = await directory.listChildren(true)
|
|
584
|
+
|
|
585
|
+
for (const child of children) {
|
|
586
|
+
if (child instanceof File) {
|
|
587
|
+
files.push(child.getWorkspacePath())
|
|
588
|
+
} else if (child instanceof Directory) {
|
|
589
|
+
const subFiles = await collectFilesRecursive(child)
|
|
590
|
+
files.push(...subFiles)
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
return files
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
registerAll({
|
|
598
|
+
command: {
|
|
599
|
+
"id": "ls",
|
|
600
|
+
"name": "List files",
|
|
601
|
+
"description": "Lists files from a directory. If recursive is provided, it traverses from the provided directory down to all leaves. If no directory is provided, it will traverse from the workspace root.",
|
|
602
|
+
"parameters": [
|
|
603
|
+
{
|
|
604
|
+
"name": "path",
|
|
605
|
+
"description": "the path of the directory to list, relative to the workspace. If not provided, uses workspace root",
|
|
606
|
+
"required": false
|
|
607
|
+
},
|
|
608
|
+
{
|
|
609
|
+
"name": "recursive",
|
|
610
|
+
"description": "whether to recursively traverse all subdirectories",
|
|
611
|
+
"type": "boolean",
|
|
612
|
+
"required": false
|
|
613
|
+
}
|
|
614
|
+
],
|
|
615
|
+
"output": [
|
|
616
|
+
{
|
|
617
|
+
"name": "files",
|
|
618
|
+
"description": "array of file objects with path and size information"
|
|
619
|
+
}
|
|
620
|
+
]
|
|
621
|
+
},
|
|
622
|
+
handler: {
|
|
623
|
+
execute: async ({params}: any) => {
|
|
624
|
+
const result = await getWorkspaceAndPath(params, false)
|
|
625
|
+
if (!result) {
|
|
626
|
+
toastError("No workspace available")
|
|
627
|
+
return []
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
const { workspace, path } = result
|
|
631
|
+
const recursive = params?.recursive === true || params?.recursive === "true"
|
|
632
|
+
|
|
633
|
+
try {
|
|
634
|
+
let targetDir: Directory = workspace
|
|
635
|
+
|
|
636
|
+
if (path) {
|
|
637
|
+
const resource = await workspace.getResource(path)
|
|
638
|
+
if (!resource) {
|
|
639
|
+
toastError(`Path not found: ${path}`)
|
|
640
|
+
return []
|
|
641
|
+
}
|
|
642
|
+
if (!(resource instanceof Directory)) {
|
|
643
|
+
toastError(`Path is not a directory: ${path}`)
|
|
644
|
+
return []
|
|
645
|
+
}
|
|
646
|
+
targetDir = resource
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
if (recursive) {
|
|
650
|
+
const files = await collectFilesRecursive(targetDir)
|
|
651
|
+
const result = []
|
|
652
|
+
for (const filePath of files) {
|
|
653
|
+
const file = await workspace.getResource(filePath)
|
|
654
|
+
if (file instanceof File) {
|
|
655
|
+
const size = await file.size()
|
|
656
|
+
result.push({
|
|
657
|
+
path: filePath,
|
|
658
|
+
size: size
|
|
659
|
+
})
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
return result
|
|
663
|
+
} else {
|
|
664
|
+
const children = await targetDir.listChildren(true)
|
|
665
|
+
const result = []
|
|
666
|
+
for (const child of children) {
|
|
667
|
+
if (child instanceof File) {
|
|
668
|
+
const size = await child.size()
|
|
669
|
+
result.push({
|
|
670
|
+
path: child.getWorkspacePath(),
|
|
671
|
+
size: size
|
|
672
|
+
})
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
return result
|
|
676
|
+
}
|
|
677
|
+
} catch (err: any) {
|
|
678
|
+
toastError(`Failed to list files: ${err.message}`)
|
|
679
|
+
return []
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
})
|
|
684
|
+
|
|
685
|
+
registerAll({
|
|
686
|
+
command: {
|
|
687
|
+
"id": "get_active_editor_content",
|
|
688
|
+
"name": "Get active editor content",
|
|
689
|
+
"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.",
|
|
690
|
+
"parameters": [],
|
|
691
|
+
"output": [
|
|
692
|
+
{
|
|
693
|
+
"name": "content",
|
|
694
|
+
"description": "the complete contents of the active editor, or null if no editor is active"
|
|
695
|
+
},
|
|
696
|
+
{
|
|
697
|
+
"name": "filePath",
|
|
698
|
+
"description": "the workspace path of the file in the active editor, or null if no editor is active"
|
|
699
|
+
},
|
|
700
|
+
{
|
|
701
|
+
"name": "language",
|
|
702
|
+
"description": "the programming language of the active editor, or null if no editor is active"
|
|
703
|
+
}
|
|
704
|
+
]
|
|
705
|
+
},
|
|
706
|
+
handler: {
|
|
707
|
+
execute: async (context: ExecutionContext) => {
|
|
708
|
+
const activeEditor = context.activeEditor as any
|
|
709
|
+
if (!isEditorContentProvider(activeEditor)) {
|
|
710
|
+
return { ...createNullEditorResponse(), content: null }
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
try {
|
|
714
|
+
return {
|
|
715
|
+
content: activeEditor.getContent(),
|
|
716
|
+
filePath: activeEditor.getFilePath(),
|
|
717
|
+
language: activeEditor.getLanguage()
|
|
718
|
+
}
|
|
719
|
+
} catch (err: any) {
|
|
720
|
+
return { ...createNullEditorResponse(), content: null }
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
})
|
|
725
|
+
|
|
726
|
+
registerAll({
|
|
727
|
+
command: {
|
|
728
|
+
"id": "get_active_editor_selection",
|
|
729
|
+
"name": "Get active editor selection",
|
|
730
|
+
"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.",
|
|
731
|
+
"parameters": [],
|
|
732
|
+
"output": [
|
|
733
|
+
{
|
|
734
|
+
"name": "selection",
|
|
735
|
+
"description": "the selected text in the active editor, or null if no selection exists or no editor is active"
|
|
736
|
+
},
|
|
737
|
+
{
|
|
738
|
+
"name": "filePath",
|
|
739
|
+
"description": "the workspace path of the file in the active editor, or null if no editor is active"
|
|
740
|
+
},
|
|
741
|
+
{
|
|
742
|
+
"name": "language",
|
|
743
|
+
"description": "the programming language of the active editor, or null if no editor is active"
|
|
744
|
+
}
|
|
745
|
+
]
|
|
746
|
+
},
|
|
747
|
+
handler: {
|
|
748
|
+
execute: async (context: ExecutionContext) => {
|
|
749
|
+
const activeEditor = context.activeEditor as any
|
|
750
|
+
if (!isEditorContentProvider(activeEditor)) {
|
|
751
|
+
return { ...createNullEditorResponse(), selection: null }
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
try {
|
|
755
|
+
return {
|
|
756
|
+
selection: activeEditor.getSelection(),
|
|
757
|
+
filePath: activeEditor.getFilePath(),
|
|
758
|
+
language: activeEditor.getLanguage()
|
|
759
|
+
}
|
|
760
|
+
} catch (err: any) {
|
|
761
|
+
return { ...createNullEditorResponse(), selection: null }
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
})
|
|
766
|
+
|
|
767
|
+
registerAll({
|
|
768
|
+
command: {
|
|
769
|
+
"id": "get_active_editor_snippet",
|
|
770
|
+
"name": "Get active editor snippet around cursor",
|
|
771
|
+
"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.",
|
|
772
|
+
"parameters": [
|
|
773
|
+
{
|
|
774
|
+
"name": "lines",
|
|
775
|
+
"description": "number of lines to include before and after the cursor position (default: 5)",
|
|
776
|
+
"type": "number",
|
|
777
|
+
"required": false
|
|
778
|
+
}
|
|
779
|
+
],
|
|
780
|
+
"output": [
|
|
781
|
+
{
|
|
782
|
+
"name": "snippet",
|
|
783
|
+
"description": "the code snippet with n lines before and after the cursor, or null if no editor is active"
|
|
784
|
+
},
|
|
785
|
+
{
|
|
786
|
+
"name": "filePath",
|
|
787
|
+
"description": "the workspace path of the file in the active editor, or null if no editor is active"
|
|
788
|
+
},
|
|
789
|
+
{
|
|
790
|
+
"name": "language",
|
|
791
|
+
"description": "the programming language of the active editor, or null if no editor is active"
|
|
792
|
+
},
|
|
793
|
+
{
|
|
794
|
+
"name": "cursorLine",
|
|
795
|
+
"description": "the line number where the cursor is positioned (1-based), or null if no editor is active"
|
|
796
|
+
}
|
|
797
|
+
]
|
|
798
|
+
},
|
|
799
|
+
handler: {
|
|
800
|
+
execute: async (context: ExecutionContext) => {
|
|
801
|
+
const activeEditor = context.activeEditor as any
|
|
802
|
+
if (!isEditorContentProvider(activeEditor)) {
|
|
803
|
+
return createNullEditorResponse(true)
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
try {
|
|
807
|
+
const numLines = context.params?.lines ? parseInt(context.params.lines, 10) : 5
|
|
808
|
+
if (isNaN(numLines) || numLines < 0) {
|
|
809
|
+
return createNullEditorResponse(true)
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
const snippetResult = activeEditor.getSnippet(numLines)
|
|
813
|
+
if (!snippetResult) {
|
|
814
|
+
return createNullEditorResponse(true)
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
return {
|
|
818
|
+
snippet: snippetResult.snippet,
|
|
819
|
+
filePath: activeEditor.getFilePath(),
|
|
820
|
+
language: activeEditor.getLanguage(),
|
|
821
|
+
cursorLine: snippetResult.cursorLine
|
|
822
|
+
}
|
|
823
|
+
} catch (err: any) {
|
|
824
|
+
return createNullEditorResponse(true)
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
})
|
|
829
|
+
|