@lvce-editor/shared-process 0.0.2
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/LICENSE +21 -0
- package/README.md +41 -0
- package/bin/sharedProcess.js +3 -0
- package/index.js +6 -0
- package/package.json +96 -0
- package/src/parts/Assert/Assert.js +57 -0
- package/src/parts/Callback/Callback.js +48 -0
- package/src/parts/ChildProcess/ChildProcess.js +98 -0
- package/src/parts/ClipBoard/ClipBoard.ipc.js +7 -0
- package/src/parts/ClipBoard/ClipBoard.js +23 -0
- package/src/parts/ClipBoard/ClipBoardGnome.js +78 -0
- package/src/parts/ClipBoard/ClipBoardNoop.js +14 -0
- package/src/parts/ClipBoard/ClipBoardWindows.js +22 -0
- package/src/parts/Command/Command.js +264 -0
- package/src/parts/Configuration/Configuration.ipc.js +7 -0
- package/src/parts/Configuration/Configuration.js +39 -0
- package/src/parts/Credentials/Credentials.ipc.js +10 -0
- package/src/parts/Credentials/Credentials.js +69 -0
- package/src/parts/Debug/Debug.js +3 -0
- package/src/parts/Developer/Developer.ipc.js +20 -0
- package/src/parts/Developer/Developer.js +132 -0
- package/src/parts/Download/Download.js +33 -0
- package/src/parts/Electron/Electron.ipc.js +19 -0
- package/src/parts/Electron/Electron.js +99 -0
- package/src/parts/Env/Env.js +3 -0
- package/src/parts/Error/Error.js +30 -0
- package/src/parts/ErrorHandling/ErrorHandling.js +40 -0
- package/src/parts/Exec/Exec.js +16 -0
- package/src/parts/Extension/Extension.js +7 -0
- package/src/parts/ExtensionHost/ExtensionHost.ipc.js +80 -0
- package/src/parts/ExtensionHost/ExtensionHost.js +163 -0
- package/src/parts/ExtensionHost/ExtensionHostBraceCompletion.js +14 -0
- package/src/parts/ExtensionHost/ExtensionHostClosingTag.js +14 -0
- package/src/parts/ExtensionHost/ExtensionHostColorTheme.js +60 -0
- package/src/parts/ExtensionHost/ExtensionHostCommand.js +19 -0
- package/src/parts/ExtensionHost/ExtensionHostCompletion.js +12 -0
- package/src/parts/ExtensionHost/ExtensionHostDefinition.js +12 -0
- package/src/parts/ExtensionHost/ExtensionHostDiagnostic.js +7 -0
- package/src/parts/ExtensionHost/ExtensionHostFileSystem.js +23 -0
- package/src/parts/ExtensionHost/ExtensionHostFormatting.js +4 -0
- package/src/parts/ExtensionHost/ExtensionHostHover.js +12 -0
- package/src/parts/ExtensionHost/ExtensionHostIconTheme.js +35 -0
- package/src/parts/ExtensionHost/ExtensionHostImplementation.js +12 -0
- package/src/parts/ExtensionHost/ExtensionHostKeyBindings.js +23 -0
- package/src/parts/ExtensionHost/ExtensionHostLanguages.js +84 -0
- package/src/parts/ExtensionHost/ExtensionHostManagement.js +26 -0
- package/src/parts/ExtensionHost/ExtensionHostOutput.js +3 -0
- package/src/parts/ExtensionHost/ExtensionHostQuickPick.js +6 -0
- package/src/parts/ExtensionHost/ExtensionHostReference.js +12 -0
- package/src/parts/ExtensionHost/ExtensionHostRename.js +27 -0
- package/src/parts/ExtensionHost/ExtensionHostSemanticTokens.js +10 -0
- package/src/parts/ExtensionHost/ExtensionHostSourceControl.js +15 -0
- package/src/parts/ExtensionHost/ExtensionHostStats.js +3 -0
- package/src/parts/ExtensionHost/ExtensionHostStatusBar.js +7 -0
- package/src/parts/ExtensionHost/ExtensionHostTabCompletion.js +12 -0
- package/src/parts/ExtensionHost/ExtensionHostTextDocument.js +35 -0
- package/src/parts/ExtensionHost/ExtensionHostTypeDefinition.js +12 -0
- package/src/parts/ExtensionHost/ExtensionHostWorkspace.js +3 -0
- package/src/parts/ExtensionManagement/ExtensionManagement.ipc.js +11 -0
- package/src/parts/ExtensionManagement/ExtensionManagement.js +319 -0
- package/src/parts/FileSystem/FileSystem.ipc.js +32 -0
- package/src/parts/FileSystem/FileSystem.js +228 -0
- package/src/parts/Git/Git.js +58 -0
- package/src/parts/Json/Json.js +67 -0
- package/src/parts/JsonFile/JsonFile.js +14 -0
- package/src/parts/JsonRpc/JsonRpc.js +22 -0
- package/src/parts/Native/Native.ipc.js +6 -0
- package/src/parts/Native/Native.js +14 -0
- package/src/parts/OutputChannel/OutputChannel.ipc.js +51 -0
- package/src/parts/OutputChannel/OutputChannel.js +37 -0
- package/src/parts/ParentIpc/ParentIpc.js +203 -0
- package/src/parts/Path/Path.js +17 -0
- package/src/parts/Platform/Platform.ipc.js +18 -0
- package/src/parts/Platform/Platform.js +165 -0
- package/src/parts/Preferences/Preferences.ipc.js +6 -0
- package/src/parts/Preferences/Preferences.js +75 -0
- package/src/parts/PrettyError/PrettyError.js +86 -0
- package/src/parts/Process/Process.ipc.js +7 -0
- package/src/parts/Process/Process.js +7 -0
- package/src/parts/Queue/Queue.js +35 -0
- package/src/parts/RequiresSocket/RequiresSocket.js +11 -0
- package/src/parts/RgPath/RgPath.js +1 -0
- package/src/parts/Root/Root.js +6 -0
- package/src/parts/Search/Search.ipc.js +6 -0
- package/src/parts/Search/Search.js +101 -0
- package/src/parts/SearchFile/SearchFile.ipc.js +6 -0
- package/src/parts/SearchFile/SearchFile.js +51 -0
- package/src/parts/Socket/Socket.js +132 -0
- package/src/parts/Stats/Stats.js +45 -0
- package/src/parts/Terminal/Terminal.ipc.js +45 -0
- package/src/parts/Terminal/Terminal.js +161 -0
- package/src/parts/TextDocument/TextDocument.ipc.js +6 -0
- package/src/parts/TextDocument/TextDocument.js +37 -0
- package/src/parts/Trace/Trace.js +15 -0
- package/src/parts/Trash/Trash.js +11 -0
- package/src/parts/WebSocketServer/WebSocketServer.ipc.js +6 -0
- package/src/parts/WebSocketServer/WebSocketServer.js +43 -0
- package/src/parts/Workspace/Workspace.ipc.js +7 -0
- package/src/parts/Workspace/Workspace.js +107 -0
- package/src/sharedProcessMain.js +61 -0
- package/test/Callback.test.js +42 -0
- package/test/ClipBoard.test.js +105 -0
- package/test/Credentials.test.js +147 -0
- package/test/Developer.test.js +34 -0
- package/test/Electron.test.js +93 -0
- package/test/Error.test.js +16 -0
- package/test/Exec.test.js +25 -0
- package/test/ExtensionHost.test.js +127 -0
- package/test/ExtensionHostColorTheme.test.js +141 -0
- package/test/ExtensionHostCommand.test.js +27 -0
- package/test/ExtensionHostCompletion.test.js +45 -0
- package/test/ExtensionHostDefinition.test.js +35 -0
- package/test/ExtensionHostDiagnostic.test.js +23 -0
- package/test/ExtensionHostFileSystem.test.js +91 -0
- package/test/ExtensionHostFormatting.test.js +27 -0
- package/test/ExtensionHostIconTheme.test.js +73 -0
- package/test/ExtensionHostLanguages.test.js +212 -0
- package/test/ExtensionHostOutput.test.js +23 -0
- package/test/ExtensionHostRename.test.js +59 -0
- package/test/ExtensionHostSemanticTokens.test.js +26 -0
- package/test/ExtensionHostTabCompletion.test.js +35 -0
- package/test/ExtensionHostTextDocument.test.js +61 -0
- package/test/ExtensionHostTypeDefinition.test.js +35 -0
- package/test/ExtensionHostWorkspace.test.js +21 -0
- package/test/ExtensionManagement.test.js +408 -0
- package/test/FileSystem.test.js +294 -0
- package/test/Json.test.js +25 -0
- package/test/Native.test.js +31 -0
- package/test/OutputChannel.test.js +68 -0
- package/test/Path.test.js +17 -0
- package/test/Platform.test.js +61 -0
- package/test/Preferences.test.js +140 -0
- package/test/Process.test.js +9 -0
- package/test/RgPath.test.js +5 -0
- package/test/Search.test.js +45 -0
- package/test/SearchFile.test.js +80 -0
- package/test/Terminal.test.js +53 -0
- package/test/Trash.test.js +34 -0
- package/test/WebSocketServer.test.js +98 -0
- package/test/fixture-search-1/index.html +10 -0
- package/test/fixture-search-file-1/fileA +0 -0
- package/test/fixture-search-file-1/fileB +0 -0
- package/test/fixture-search-file-1/nested/fileC +0 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import * as NodePath from 'node:path'
|
|
2
|
+
|
|
3
|
+
export const getHomeDir = () => {}
|
|
4
|
+
|
|
5
|
+
export const getTmpDir = () => {}
|
|
6
|
+
|
|
7
|
+
export const getBuiltinExtensionDir = () => {}
|
|
8
|
+
|
|
9
|
+
export const getMarketplaceExtensionDir = () => {}
|
|
10
|
+
|
|
11
|
+
export const join = (...parts) => {
|
|
12
|
+
return NodePath.join(...parts)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const dirname = (path) => {
|
|
16
|
+
return NodePath.dirname(path)
|
|
17
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as Command from '../Command/Command.js'
|
|
2
|
+
import * as Platform from '../Platform/Platform.js'
|
|
3
|
+
|
|
4
|
+
export const __initialize__ = () => {
|
|
5
|
+
Command.register('Platform.getConfigDir', Platform.getConfigDir)
|
|
6
|
+
Command.register('Platform.getAppDir', Platform.getAppDir)
|
|
7
|
+
Command.register('Platform.getHomeDir', Platform.getHomeDir)
|
|
8
|
+
Command.register('Platform.getDataDir', Platform.getDataDir)
|
|
9
|
+
Command.register('Platform.getExtensionsPath', Platform.getExtensionsPath)
|
|
10
|
+
Command.register('Platform.getBuiltinExtensionsPath', Platform.getBuiltinExtensionsPath)
|
|
11
|
+
Command.register('Platform.getDisabledExtensionsPath', Platform.getDisabledExtensionsPath)
|
|
12
|
+
Command.register('Platform.getCachedExtensionsPath', Platform.getCachedExtensionsPath)
|
|
13
|
+
Command.register('Platform.getMarketplaceUrl', Platform.getMarketplaceUrl)
|
|
14
|
+
Command.register('Platform.getLogsDir', Platform.getLogsDir)
|
|
15
|
+
Command.register('Platform.getUserSettingsPath', Platform.getUserSettingsPath)
|
|
16
|
+
Command.register('Platform.getRecentlyOpenedPath', Platform.getRecentlyOpenedPath)
|
|
17
|
+
Command.register('Platform.getCacheDir', Platform.getCacheDir)
|
|
18
|
+
}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { homedir, tmpdir } from 'node:os'
|
|
2
|
+
import { sep } from 'node:path'
|
|
3
|
+
import { xdgCache, xdgConfig, xdgData, xdgState } from 'xdg-basedir'
|
|
4
|
+
import * as Root from '../Root/Root.js'
|
|
5
|
+
import * as Path from '../Path/Path.js'
|
|
6
|
+
import { extensionHostPath } from '@lvce-editor/extension-host'
|
|
7
|
+
|
|
8
|
+
export const state = {
|
|
9
|
+
getApplicationName() {
|
|
10
|
+
return 'lvce-oss'
|
|
11
|
+
},
|
|
12
|
+
isWindows() {
|
|
13
|
+
return process.platform === 'win32'
|
|
14
|
+
},
|
|
15
|
+
isMacOs() {
|
|
16
|
+
return process.platform === 'darwin'
|
|
17
|
+
},
|
|
18
|
+
getDataDir() {
|
|
19
|
+
return Path.join(xdgData || tmpdir(), this.getApplicationName())
|
|
20
|
+
},
|
|
21
|
+
getConfigDir() {
|
|
22
|
+
return Path.join(xdgConfig || tmpdir(), this.getApplicationName())
|
|
23
|
+
},
|
|
24
|
+
getCacheDir() {
|
|
25
|
+
return Path.join(xdgCache || tmpdir(), this.getApplicationName())
|
|
26
|
+
},
|
|
27
|
+
getAppDir() {
|
|
28
|
+
return Root.root
|
|
29
|
+
},
|
|
30
|
+
getExtensionsPath() {
|
|
31
|
+
return Path.join(this.getDataDir(), 'extensions')
|
|
32
|
+
},
|
|
33
|
+
getBuiltinExtensionsPath() {
|
|
34
|
+
return Path.join(Root.root, 'extensions')
|
|
35
|
+
},
|
|
36
|
+
getDisabledExtensionsPath() {
|
|
37
|
+
return Path.join(this.getDataDir(), 'disabled-extensions')
|
|
38
|
+
},
|
|
39
|
+
getCachedExtensionsPath() {
|
|
40
|
+
return Path.join(this.getCacheDir(), 'cached-extensions')
|
|
41
|
+
},
|
|
42
|
+
getMarketplaceUrl() {
|
|
43
|
+
return (
|
|
44
|
+
process.env.LVCE_MARKETPLACE_URL ||
|
|
45
|
+
'https://marketplace.22e924c84de072d4b25b.com'
|
|
46
|
+
)
|
|
47
|
+
},
|
|
48
|
+
getDesktop() {
|
|
49
|
+
if (
|
|
50
|
+
process.env.ORIGINAL_XDG_CURRENT_DESKTOP &&
|
|
51
|
+
process.env.ORIGINAL_XDG_CURRENT_DESKTOP !== 'undefined'
|
|
52
|
+
) {
|
|
53
|
+
if (process.env.ORIGINAL_XDG_CURRENT_DESKTOP === 'ubuntu:GNOME') {
|
|
54
|
+
return 'gnome'
|
|
55
|
+
}
|
|
56
|
+
return process.env.ORIGINAL_XDG_CURRENT_DESKTOP
|
|
57
|
+
}
|
|
58
|
+
if (process.env.XDG_CURRENT_DESKTOP) {
|
|
59
|
+
if (process.env.XDG_CURRENT_DESKTOP === 'ubuntu:GNOME') {
|
|
60
|
+
return 'gnome'
|
|
61
|
+
}
|
|
62
|
+
return process.env.XDG_CURRENT_DESKTOP
|
|
63
|
+
}
|
|
64
|
+
if (process.platform === 'win32') {
|
|
65
|
+
return 'windows'
|
|
66
|
+
}
|
|
67
|
+
return ''
|
|
68
|
+
},
|
|
69
|
+
getPathSeparator() {
|
|
70
|
+
return sep
|
|
71
|
+
},
|
|
72
|
+
getStateDir() {
|
|
73
|
+
return xdgState
|
|
74
|
+
},
|
|
75
|
+
getLogsDir() {
|
|
76
|
+
return Path.join(xdgState || tmpdir(), this.getApplicationName(), 'logs')
|
|
77
|
+
},
|
|
78
|
+
getUserSettingsPath() {
|
|
79
|
+
return Path.join(this.getConfigDir(), 'settings.json')
|
|
80
|
+
},
|
|
81
|
+
getExtensionHostPath() {
|
|
82
|
+
return extensionHostPath
|
|
83
|
+
},
|
|
84
|
+
getRecentlyOpenedPath() {
|
|
85
|
+
return Path.join(this.getCacheDir(), 'recently-opened.json')
|
|
86
|
+
},
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export const isWindows = () => {
|
|
90
|
+
return state.isWindows()
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export const isMacOs = () => {
|
|
94
|
+
return state.isMacOs()
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// TODO pass which version when building: insiders|oss|normal
|
|
98
|
+
|
|
99
|
+
export const getDataDir = () => {
|
|
100
|
+
return state.getDataDir()
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export const getConfigDir = () => {
|
|
104
|
+
return state.getConfigDir()
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export const getCacheDir = () => {
|
|
108
|
+
return state.getCacheDir()
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export const getHomeDir = () => {
|
|
112
|
+
return isWindows() ? '' : homedir()
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export const getAppDir = () => {
|
|
116
|
+
return state.getAppDir()
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export const getExtensionsPath = () => {
|
|
120
|
+
return state.getExtensionsPath()
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export const getBuiltinExtensionsPath = () => {
|
|
124
|
+
return state.getBuiltinExtensionsPath()
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export const getDisabledExtensionsPath = () => {
|
|
128
|
+
return state.getDisabledExtensionsPath()
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export const getCachedExtensionsPath = () => {
|
|
132
|
+
return state.getCachedExtensionsPath()
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export const getMarketplaceUrl = () => {
|
|
136
|
+
return state.getMarketplaceUrl()
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export const getDesktop = () => {
|
|
140
|
+
return state.getDesktop()
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export const getPathSeparator = () => {
|
|
144
|
+
return state.getPathSeparator()
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export const getStateDir = () => {
|
|
148
|
+
return state.getStateDir()
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export const getLogsDir = () => {
|
|
152
|
+
return state.getLogsDir()
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export const getUserSettingsPath = () => {
|
|
156
|
+
return state.getUserSettingsPath()
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export const getExtensionHostPath = () => {
|
|
160
|
+
return state.getExtensionHostPath()
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export const getRecentlyOpenedPath = () => {
|
|
164
|
+
return state.getRecentlyOpenedPath()
|
|
165
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { join } from 'node:path'
|
|
2
|
+
import VError from 'verror'
|
|
3
|
+
import * as JsonFile from '../JsonFile/JsonFile.js'
|
|
4
|
+
import * as Platform from '../Platform/Platform.js'
|
|
5
|
+
|
|
6
|
+
const CACHED_SETTINGS_PATH = '~/.cache/vscode/cachedSettings.json'
|
|
7
|
+
// TODO need jsonc parser for settings with comments
|
|
8
|
+
|
|
9
|
+
export const getUserPreferences = async () => {
|
|
10
|
+
try {
|
|
11
|
+
const userSettingsPath = Platform.getUserSettingsPath()
|
|
12
|
+
let json
|
|
13
|
+
try {
|
|
14
|
+
json = await JsonFile.readJson(userSettingsPath)
|
|
15
|
+
} catch (error) {
|
|
16
|
+
if (error && error.code === 'ENOENT') {
|
|
17
|
+
return {}
|
|
18
|
+
}
|
|
19
|
+
throw error
|
|
20
|
+
}
|
|
21
|
+
return json
|
|
22
|
+
} catch (error) {
|
|
23
|
+
throw new VError(error, 'failed to get user preferences')
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// TODO handle error
|
|
28
|
+
export const getDefaultPreferences = async () => {
|
|
29
|
+
try {
|
|
30
|
+
const defaultSettingsPath = join(
|
|
31
|
+
Platform.getAppDir(),
|
|
32
|
+
'static',
|
|
33
|
+
'config',
|
|
34
|
+
'defaultSettings.json'
|
|
35
|
+
)
|
|
36
|
+
return await JsonFile.readJson(defaultSettingsPath)
|
|
37
|
+
} catch (error) {
|
|
38
|
+
throw new VError(error, 'Failed to load default preferences')
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// TODO efficiently load preferences -> first load cached preferences
|
|
43
|
+
// -> on idle check preferences
|
|
44
|
+
|
|
45
|
+
// TODO compare with timestamp/hash that preferences are fresh
|
|
46
|
+
export const getAll = async () => {
|
|
47
|
+
try {
|
|
48
|
+
// try {
|
|
49
|
+
// const cachedPreferences = JSON.parse(
|
|
50
|
+
// await readFile(CACHED_SETTINGS_PATH, 'utf-8')
|
|
51
|
+
// )
|
|
52
|
+
// return cachedPreferences
|
|
53
|
+
// } catch {
|
|
54
|
+
// // ignore
|
|
55
|
+
// }
|
|
56
|
+
const defaultPreferences = await getDefaultPreferences()
|
|
57
|
+
const userPreferences = await getUserPreferences()
|
|
58
|
+
// TODO separate backend and frontend preferences, ui only needs frontend preferences
|
|
59
|
+
const preferences = { ...defaultPreferences, ...userPreferences }
|
|
60
|
+
// try {
|
|
61
|
+
// await mkdir(dirname(CACHED_SETTINGS_PATH), { recursive: true })
|
|
62
|
+
// await writeFile(
|
|
63
|
+
// CACHED_SETTINGS_PATH,
|
|
64
|
+
// JSON.stringify(preferences, null, 2) + '\n'
|
|
65
|
+
// )
|
|
66
|
+
// } catch {
|
|
67
|
+
// // ignore
|
|
68
|
+
// }
|
|
69
|
+
return preferences
|
|
70
|
+
} catch (error) {
|
|
71
|
+
throw new VError(error, 'Failed to get all preferences')
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// TODO when preferences cannot be loaded, ui should show useful error message
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs'
|
|
2
|
+
import { fileURLToPath } from 'node:url'
|
|
3
|
+
import { codeFrameColumns } from '@babel/code-frame'
|
|
4
|
+
import cleanStack from 'clean-stack'
|
|
5
|
+
import { LinesAndColumns } from 'lines-and-columns'
|
|
6
|
+
|
|
7
|
+
const getActualPath = (fileUri) => {
|
|
8
|
+
if (fileUri.startsWith('file://')) {
|
|
9
|
+
return fileURLToPath(fileUri)
|
|
10
|
+
}
|
|
11
|
+
return fileUri
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const prepare = (error) => {
|
|
15
|
+
const message = error.message
|
|
16
|
+
if (error.cause) {
|
|
17
|
+
error = error.cause()
|
|
18
|
+
}
|
|
19
|
+
const cleanedStack = cleanStack(error.stack)
|
|
20
|
+
const lines = cleanedStack.split('\n')
|
|
21
|
+
const file = lines[1]
|
|
22
|
+
let codeFrame = ''
|
|
23
|
+
if (error.codeFrame) {
|
|
24
|
+
codeFrame = error.codeFrame
|
|
25
|
+
} else if (file) {
|
|
26
|
+
let match = file.match(/\((.*):(\d+):(\d+)\)$/)
|
|
27
|
+
if (!match) {
|
|
28
|
+
match = file.match(/at (.*):(\d+):(\d+)$/)
|
|
29
|
+
}
|
|
30
|
+
if (match) {
|
|
31
|
+
const [_, path, line, column] = match
|
|
32
|
+
const actualPath = getActualPath(path)
|
|
33
|
+
const rawLines = readFileSync(actualPath, 'utf-8')
|
|
34
|
+
const location = {
|
|
35
|
+
start: {
|
|
36
|
+
line: Number.parseInt(line),
|
|
37
|
+
column: Number.parseInt(column),
|
|
38
|
+
},
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
codeFrame = codeFrameColumns(rawLines, location)
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const relevantStack = lines.slice(1).join('\n')
|
|
45
|
+
return {
|
|
46
|
+
message,
|
|
47
|
+
stack: relevantStack,
|
|
48
|
+
codeFrame,
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const fixBackslashes = (string) => {
|
|
53
|
+
return string.replaceAll('\\\\', '\\')
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const stringifyJson = (json) => {
|
|
57
|
+
return JSON.stringify(json, null, 2) + '\n'
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export const prepareJsonError = (json, property, message) => {
|
|
61
|
+
const string = fixBackslashes(stringifyJson(json))
|
|
62
|
+
const stringifiedPropertyName = `"${property}"`
|
|
63
|
+
const index = string.indexOf(stringifiedPropertyName) // TODO this could be wrong in some cases, find a better way
|
|
64
|
+
console.log({ string, index })
|
|
65
|
+
const jsonError = {
|
|
66
|
+
stack: '',
|
|
67
|
+
}
|
|
68
|
+
if (index !== -1) {
|
|
69
|
+
const lines = new LinesAndColumns(string)
|
|
70
|
+
const location = lines.locationForIndex(
|
|
71
|
+
index + stringifiedPropertyName.length + 1
|
|
72
|
+
)
|
|
73
|
+
const codeFrame = codeFrameColumns(string, {
|
|
74
|
+
start: { line: location.line + 1, column: location.column + 1 },
|
|
75
|
+
})
|
|
76
|
+
jsonError.codeFrame = codeFrame
|
|
77
|
+
}
|
|
78
|
+
// jsonError.stack = `${bottomMessage}\n at ${filePath}`
|
|
79
|
+
return jsonError
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export const print = (prettyError) => {
|
|
83
|
+
console.error(
|
|
84
|
+
`Error: ${prettyError.message}\n\n${prettyError.codeFrame}\n\n${prettyError.stack}`
|
|
85
|
+
)
|
|
86
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export const state = {
|
|
2
|
+
queueMap: Object.create(null),
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
const run = async (queue) => {
|
|
6
|
+
if (queue.state === 'running') {
|
|
7
|
+
return
|
|
8
|
+
}
|
|
9
|
+
queue.state = 'running'
|
|
10
|
+
let item
|
|
11
|
+
while ((item = queue.items.shift())) {
|
|
12
|
+
try {
|
|
13
|
+
await item.fn()
|
|
14
|
+
item.resolve()
|
|
15
|
+
} catch (error) {
|
|
16
|
+
item.reject(error)
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
queue.state = 'idle'
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const add = async (key, fn) => {
|
|
23
|
+
const queue = (state.queueMap[key] ||= {
|
|
24
|
+
state: 'idle',
|
|
25
|
+
items: [],
|
|
26
|
+
})
|
|
27
|
+
await new Promise((resolve, reject) => {
|
|
28
|
+
queue.items.push({
|
|
29
|
+
fn,
|
|
30
|
+
resolve,
|
|
31
|
+
reject,
|
|
32
|
+
})
|
|
33
|
+
run(queue)
|
|
34
|
+
})
|
|
35
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// TODO find a better way to do this
|
|
2
|
+
// most commands don't require sockets
|
|
3
|
+
// but output channel and terminal need to continuously send data through the socket
|
|
4
|
+
const METHODS_THAT_REQUIRE_SOCKET = [
|
|
5
|
+
'OutputChannel.open', // OutputChannel.open
|
|
6
|
+
'ExtensionHost.start', // ExtensionHost.start
|
|
7
|
+
]
|
|
8
|
+
|
|
9
|
+
export const requiresSocket = (method) => {
|
|
10
|
+
return METHODS_THAT_REQUIRE_SOCKET.includes(method)
|
|
11
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { rgPath } from 'vscode-ripgrep-with-github-api-error-fix'
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process'
|
|
2
|
+
import * as RgPath from '../RgPath/RgPath.js'
|
|
3
|
+
import * as Platform from '../Platform/Platform.js'
|
|
4
|
+
|
|
5
|
+
const MAX_SEARCH_RESULTS = 300
|
|
6
|
+
|
|
7
|
+
const toSearchResult = (parsedLine) => ({
|
|
8
|
+
preview: parsedLine.data.lines.text,
|
|
9
|
+
absoluteOffset: parsedLine.data.absolute_offset,
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
// TODO update vscode-ripgrep when https://github.com/mhinz/vim-grepper/issues/244, https://github.com/BurntSushi/ripgrep/issues/1892 is fixed
|
|
13
|
+
|
|
14
|
+
// need to use '.' as last argument for ripgrep
|
|
15
|
+
// issue 1 https://github.com/nvim-telescope/telescope.nvim/pull/908/files
|
|
16
|
+
// issue 2 https://github.com/BurntSushi/ripgrep/issues/1892
|
|
17
|
+
// remove workaround when ripgrep is fixed
|
|
18
|
+
|
|
19
|
+
// TODO no function call at toplevel!
|
|
20
|
+
const useNice = !Platform.isWindows()
|
|
21
|
+
// TODO stats flag might not be necessary
|
|
22
|
+
// TODO update client
|
|
23
|
+
// TODO not always run nice, maybe configure nice via flag/options
|
|
24
|
+
|
|
25
|
+
export const search = async (searchDir, searchString) => {
|
|
26
|
+
// TODO reject promise when ripgrep search fails
|
|
27
|
+
return new Promise((resolve, reject) => {
|
|
28
|
+
const childProcess = useNice
|
|
29
|
+
? spawn(
|
|
30
|
+
'nice',
|
|
31
|
+
[
|
|
32
|
+
'-20',
|
|
33
|
+
RgPath.rgPath,
|
|
34
|
+
'--smart-case',
|
|
35
|
+
'--stats',
|
|
36
|
+
'--json',
|
|
37
|
+
searchString,
|
|
38
|
+
'.',
|
|
39
|
+
],
|
|
40
|
+
{
|
|
41
|
+
cwd: searchDir,
|
|
42
|
+
}
|
|
43
|
+
)
|
|
44
|
+
: spawn(
|
|
45
|
+
RgPath.rgPath,
|
|
46
|
+
['--smart-case', '--stats', '--json', searchString, '.'],
|
|
47
|
+
{
|
|
48
|
+
cwd: searchDir,
|
|
49
|
+
}
|
|
50
|
+
)
|
|
51
|
+
const allSearchResults = Object.create(null)
|
|
52
|
+
let buffer = ''
|
|
53
|
+
let stats = {}
|
|
54
|
+
let numberOfResults = 0
|
|
55
|
+
// TODO use pipeline / transform stream maybe
|
|
56
|
+
childProcess.stdout.on('data', (chunk) => {
|
|
57
|
+
buffer += chunk
|
|
58
|
+
const lines = buffer.split('\n')
|
|
59
|
+
// @ts-ignore
|
|
60
|
+
buffer = lines.pop()
|
|
61
|
+
for (const line of lines) {
|
|
62
|
+
const parsedLine = JSON.parse(line)
|
|
63
|
+
switch (parsedLine.type) {
|
|
64
|
+
case 'begin': {
|
|
65
|
+
allSearchResults[parsedLine.data.path.text] = []
|
|
66
|
+
break
|
|
67
|
+
}
|
|
68
|
+
case 'match': {
|
|
69
|
+
numberOfResults++
|
|
70
|
+
allSearchResults[parsedLine.data.path.text].push(
|
|
71
|
+
toSearchResult(parsedLine)
|
|
72
|
+
)
|
|
73
|
+
break
|
|
74
|
+
}
|
|
75
|
+
case 'summary':
|
|
76
|
+
stats = parsedLine.data
|
|
77
|
+
break
|
|
78
|
+
default:
|
|
79
|
+
break
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if (numberOfResults > MAX_SEARCH_RESULTS) {
|
|
83
|
+
childProcess.kill()
|
|
84
|
+
}
|
|
85
|
+
})
|
|
86
|
+
childProcess.once('close', () => {
|
|
87
|
+
resolve({
|
|
88
|
+
results: Object.entries(allSearchResults),
|
|
89
|
+
stats,
|
|
90
|
+
})
|
|
91
|
+
})
|
|
92
|
+
childProcess.once('error', (error) => {
|
|
93
|
+
// TODO check type of error
|
|
94
|
+
console.error(error)
|
|
95
|
+
resolve({
|
|
96
|
+
results: [],
|
|
97
|
+
stats,
|
|
98
|
+
})
|
|
99
|
+
})
|
|
100
|
+
})
|
|
101
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import * as RgPath from '../RgPath/RgPath.js'
|
|
2
|
+
import * as Exec from '../Exec/Exec.js'
|
|
3
|
+
|
|
4
|
+
const ripGrepPath = process.env.RIP_GREP_PATH || RgPath.rgPath
|
|
5
|
+
|
|
6
|
+
const isEnoentErrorLinux = (error) => {
|
|
7
|
+
return error.code === 'ENOENT'
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const isEnoentErrorWindows = (error) => {
|
|
11
|
+
return error.message.includes('The system cannot find the path specified.')
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const isEnoentError = (error) => {
|
|
15
|
+
if (!error) {
|
|
16
|
+
return false
|
|
17
|
+
}
|
|
18
|
+
return isEnoentErrorLinux(error) || isEnoentErrorWindows(error)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// TODO don't necessarily need ripgrep to list all the files,
|
|
22
|
+
// maybe also a faster c program can do it
|
|
23
|
+
// another option would be to cache the results in renderer-worker and
|
|
24
|
+
// do a delta comparison, so the first time it would send 100kB
|
|
25
|
+
// but the second time only a few hundred bytes of changes
|
|
26
|
+
|
|
27
|
+
export const searchFile = async (path, searchTerm) => {
|
|
28
|
+
try {
|
|
29
|
+
const { stdout, stderr } = await Exec.exec(
|
|
30
|
+
ripGrepPath,
|
|
31
|
+
['--files', '--sort-files'],
|
|
32
|
+
{
|
|
33
|
+
cwd: path,
|
|
34
|
+
}
|
|
35
|
+
)
|
|
36
|
+
const lines = stdout.split('\n')
|
|
37
|
+
return lines
|
|
38
|
+
} catch (error) {
|
|
39
|
+
// @ts-ignore
|
|
40
|
+
if (isEnoentError(error)) {
|
|
41
|
+
console.info(`[info] ripgrep could not be found at "${ripGrepPath}"`)
|
|
42
|
+
return []
|
|
43
|
+
}
|
|
44
|
+
// @ts-ignore
|
|
45
|
+
if (error && error.stderr === '') {
|
|
46
|
+
return []
|
|
47
|
+
}
|
|
48
|
+
console.error(error)
|
|
49
|
+
return []
|
|
50
|
+
}
|
|
51
|
+
}
|