@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.
Files changed (143) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +41 -0
  3. package/bin/sharedProcess.js +3 -0
  4. package/index.js +6 -0
  5. package/package.json +96 -0
  6. package/src/parts/Assert/Assert.js +57 -0
  7. package/src/parts/Callback/Callback.js +48 -0
  8. package/src/parts/ChildProcess/ChildProcess.js +98 -0
  9. package/src/parts/ClipBoard/ClipBoard.ipc.js +7 -0
  10. package/src/parts/ClipBoard/ClipBoard.js +23 -0
  11. package/src/parts/ClipBoard/ClipBoardGnome.js +78 -0
  12. package/src/parts/ClipBoard/ClipBoardNoop.js +14 -0
  13. package/src/parts/ClipBoard/ClipBoardWindows.js +22 -0
  14. package/src/parts/Command/Command.js +264 -0
  15. package/src/parts/Configuration/Configuration.ipc.js +7 -0
  16. package/src/parts/Configuration/Configuration.js +39 -0
  17. package/src/parts/Credentials/Credentials.ipc.js +10 -0
  18. package/src/parts/Credentials/Credentials.js +69 -0
  19. package/src/parts/Debug/Debug.js +3 -0
  20. package/src/parts/Developer/Developer.ipc.js +20 -0
  21. package/src/parts/Developer/Developer.js +132 -0
  22. package/src/parts/Download/Download.js +33 -0
  23. package/src/parts/Electron/Electron.ipc.js +19 -0
  24. package/src/parts/Electron/Electron.js +99 -0
  25. package/src/parts/Env/Env.js +3 -0
  26. package/src/parts/Error/Error.js +30 -0
  27. package/src/parts/ErrorHandling/ErrorHandling.js +40 -0
  28. package/src/parts/Exec/Exec.js +16 -0
  29. package/src/parts/Extension/Extension.js +7 -0
  30. package/src/parts/ExtensionHost/ExtensionHost.ipc.js +80 -0
  31. package/src/parts/ExtensionHost/ExtensionHost.js +163 -0
  32. package/src/parts/ExtensionHost/ExtensionHostBraceCompletion.js +14 -0
  33. package/src/parts/ExtensionHost/ExtensionHostClosingTag.js +14 -0
  34. package/src/parts/ExtensionHost/ExtensionHostColorTheme.js +60 -0
  35. package/src/parts/ExtensionHost/ExtensionHostCommand.js +19 -0
  36. package/src/parts/ExtensionHost/ExtensionHostCompletion.js +12 -0
  37. package/src/parts/ExtensionHost/ExtensionHostDefinition.js +12 -0
  38. package/src/parts/ExtensionHost/ExtensionHostDiagnostic.js +7 -0
  39. package/src/parts/ExtensionHost/ExtensionHostFileSystem.js +23 -0
  40. package/src/parts/ExtensionHost/ExtensionHostFormatting.js +4 -0
  41. package/src/parts/ExtensionHost/ExtensionHostHover.js +12 -0
  42. package/src/parts/ExtensionHost/ExtensionHostIconTheme.js +35 -0
  43. package/src/parts/ExtensionHost/ExtensionHostImplementation.js +12 -0
  44. package/src/parts/ExtensionHost/ExtensionHostKeyBindings.js +23 -0
  45. package/src/parts/ExtensionHost/ExtensionHostLanguages.js +84 -0
  46. package/src/parts/ExtensionHost/ExtensionHostManagement.js +26 -0
  47. package/src/parts/ExtensionHost/ExtensionHostOutput.js +3 -0
  48. package/src/parts/ExtensionHost/ExtensionHostQuickPick.js +6 -0
  49. package/src/parts/ExtensionHost/ExtensionHostReference.js +12 -0
  50. package/src/parts/ExtensionHost/ExtensionHostRename.js +27 -0
  51. package/src/parts/ExtensionHost/ExtensionHostSemanticTokens.js +10 -0
  52. package/src/parts/ExtensionHost/ExtensionHostSourceControl.js +15 -0
  53. package/src/parts/ExtensionHost/ExtensionHostStats.js +3 -0
  54. package/src/parts/ExtensionHost/ExtensionHostStatusBar.js +7 -0
  55. package/src/parts/ExtensionHost/ExtensionHostTabCompletion.js +12 -0
  56. package/src/parts/ExtensionHost/ExtensionHostTextDocument.js +35 -0
  57. package/src/parts/ExtensionHost/ExtensionHostTypeDefinition.js +12 -0
  58. package/src/parts/ExtensionHost/ExtensionHostWorkspace.js +3 -0
  59. package/src/parts/ExtensionManagement/ExtensionManagement.ipc.js +11 -0
  60. package/src/parts/ExtensionManagement/ExtensionManagement.js +319 -0
  61. package/src/parts/FileSystem/FileSystem.ipc.js +32 -0
  62. package/src/parts/FileSystem/FileSystem.js +228 -0
  63. package/src/parts/Git/Git.js +58 -0
  64. package/src/parts/Json/Json.js +67 -0
  65. package/src/parts/JsonFile/JsonFile.js +14 -0
  66. package/src/parts/JsonRpc/JsonRpc.js +22 -0
  67. package/src/parts/Native/Native.ipc.js +6 -0
  68. package/src/parts/Native/Native.js +14 -0
  69. package/src/parts/OutputChannel/OutputChannel.ipc.js +51 -0
  70. package/src/parts/OutputChannel/OutputChannel.js +37 -0
  71. package/src/parts/ParentIpc/ParentIpc.js +203 -0
  72. package/src/parts/Path/Path.js +17 -0
  73. package/src/parts/Platform/Platform.ipc.js +18 -0
  74. package/src/parts/Platform/Platform.js +165 -0
  75. package/src/parts/Preferences/Preferences.ipc.js +6 -0
  76. package/src/parts/Preferences/Preferences.js +75 -0
  77. package/src/parts/PrettyError/PrettyError.js +86 -0
  78. package/src/parts/Process/Process.ipc.js +7 -0
  79. package/src/parts/Process/Process.js +7 -0
  80. package/src/parts/Queue/Queue.js +35 -0
  81. package/src/parts/RequiresSocket/RequiresSocket.js +11 -0
  82. package/src/parts/RgPath/RgPath.js +1 -0
  83. package/src/parts/Root/Root.js +6 -0
  84. package/src/parts/Search/Search.ipc.js +6 -0
  85. package/src/parts/Search/Search.js +101 -0
  86. package/src/parts/SearchFile/SearchFile.ipc.js +6 -0
  87. package/src/parts/SearchFile/SearchFile.js +51 -0
  88. package/src/parts/Socket/Socket.js +132 -0
  89. package/src/parts/Stats/Stats.js +45 -0
  90. package/src/parts/Terminal/Terminal.ipc.js +45 -0
  91. package/src/parts/Terminal/Terminal.js +161 -0
  92. package/src/parts/TextDocument/TextDocument.ipc.js +6 -0
  93. package/src/parts/TextDocument/TextDocument.js +37 -0
  94. package/src/parts/Trace/Trace.js +15 -0
  95. package/src/parts/Trash/Trash.js +11 -0
  96. package/src/parts/WebSocketServer/WebSocketServer.ipc.js +6 -0
  97. package/src/parts/WebSocketServer/WebSocketServer.js +43 -0
  98. package/src/parts/Workspace/Workspace.ipc.js +7 -0
  99. package/src/parts/Workspace/Workspace.js +107 -0
  100. package/src/sharedProcessMain.js +61 -0
  101. package/test/Callback.test.js +42 -0
  102. package/test/ClipBoard.test.js +105 -0
  103. package/test/Credentials.test.js +147 -0
  104. package/test/Developer.test.js +34 -0
  105. package/test/Electron.test.js +93 -0
  106. package/test/Error.test.js +16 -0
  107. package/test/Exec.test.js +25 -0
  108. package/test/ExtensionHost.test.js +127 -0
  109. package/test/ExtensionHostColorTheme.test.js +141 -0
  110. package/test/ExtensionHostCommand.test.js +27 -0
  111. package/test/ExtensionHostCompletion.test.js +45 -0
  112. package/test/ExtensionHostDefinition.test.js +35 -0
  113. package/test/ExtensionHostDiagnostic.test.js +23 -0
  114. package/test/ExtensionHostFileSystem.test.js +91 -0
  115. package/test/ExtensionHostFormatting.test.js +27 -0
  116. package/test/ExtensionHostIconTheme.test.js +73 -0
  117. package/test/ExtensionHostLanguages.test.js +212 -0
  118. package/test/ExtensionHostOutput.test.js +23 -0
  119. package/test/ExtensionHostRename.test.js +59 -0
  120. package/test/ExtensionHostSemanticTokens.test.js +26 -0
  121. package/test/ExtensionHostTabCompletion.test.js +35 -0
  122. package/test/ExtensionHostTextDocument.test.js +61 -0
  123. package/test/ExtensionHostTypeDefinition.test.js +35 -0
  124. package/test/ExtensionHostWorkspace.test.js +21 -0
  125. package/test/ExtensionManagement.test.js +408 -0
  126. package/test/FileSystem.test.js +294 -0
  127. package/test/Json.test.js +25 -0
  128. package/test/Native.test.js +31 -0
  129. package/test/OutputChannel.test.js +68 -0
  130. package/test/Path.test.js +17 -0
  131. package/test/Platform.test.js +61 -0
  132. package/test/Preferences.test.js +140 -0
  133. package/test/Process.test.js +9 -0
  134. package/test/RgPath.test.js +5 -0
  135. package/test/Search.test.js +45 -0
  136. package/test/SearchFile.test.js +80 -0
  137. package/test/Terminal.test.js +53 -0
  138. package/test/Trash.test.js +34 -0
  139. package/test/WebSocketServer.test.js +98 -0
  140. package/test/fixture-search-1/index.html +10 -0
  141. package/test/fixture-search-file-1/fileA +0 -0
  142. package/test/fixture-search-file-1/fileB +0 -0
  143. 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,6 @@
1
+ import * as Command from '../Command/Command.js'
2
+ import * as Preferences from '../Preferences/Preferences.js'
3
+
4
+ export const __initialize__ = () => {
5
+ Command.register("Preferences.getAll", Preferences.getAll)
6
+ }
@@ -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,7 @@
1
+ import * as Command from '../Command/Command.js'
2
+ import * as Process from './Process.js'
3
+
4
+ export const __initialize__ = () => {
5
+ Command.register(555, Process.crash)
6
+ Command.register(556, Process.crashAsync)
7
+ }
@@ -0,0 +1,7 @@
1
+ export const crash = (message) => {
2
+ throw new Error(message)
3
+ }
4
+
5
+ export const crashAsync = async (message) => {
6
+ throw new Error(message)
7
+ }
@@ -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,6 @@
1
+ import { dirname, resolve } from 'node:path'
2
+ import { fileURLToPath } from 'node:url'
3
+
4
+ const __dirname = dirname(fileURLToPath(import.meta.url))
5
+
6
+ export const root = resolve(__dirname, '../../../../../')
@@ -0,0 +1,6 @@
1
+ import * as Command from '../Command/Command.js'
2
+ import * as Search from './Search.js'
3
+
4
+ export const __initialize__ = () => {
5
+ Command.register('Search.search', Search.search)
6
+ }
@@ -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,6 @@
1
+ import * as Command from '../Command/Command.js'
2
+ import * as SearchFile from './SearchFile.js'
3
+
4
+ export const __initialize__ = () => {
5
+ Command.register('SearchFile.searchFile', SearchFile.searchFile)
6
+ }
@@ -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
+ }