3
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
4
*--------------------------------------------------------------------------------------------*/
5
5
import * as vscode from 'vscode' ;
6
- import * as os from 'os' ;
7
6
import * as fs from 'fs/promises' ;
8
7
import * as path from 'path' ;
9
8
import { ExecOptionsWithStringEncoding , execSync } from 'child_process' ;
10
9
import { upstreamSpecs } from './constants' ;
11
10
import codeCompletionSpec from './completions/code' ;
12
11
import cdSpec from './completions/cd' ;
13
12
import codeInsidersCompletionSpec from './completions/code-insiders' ;
13
+ import { osIsWindows } from './helpers/os' ;
14
+ import { isExecutable } from './helpers/executable' ;
14
15
16
+ const isWindows = osIsWindows ( ) ;
15
17
let cachedAvailableCommandsPath : string | undefined ;
16
18
let cachedAvailableCommands : Set < string > | undefined ;
17
19
const cachedBuiltinCommands : Map < string , string [ ] | undefined > = new Map ( ) ;
@@ -101,7 +103,7 @@ export async function activate(context: vscode.ExtensionContext) {
101
103
const result = await getCompletionItemsFromSpecs ( availableSpecs , terminalContext , commands , prefix , terminal . shellIntegration ?. cwd , token ) ;
102
104
if ( result . cwd && ( result . filesRequested || result . foldersRequested ) ) {
103
105
// const cwd = resolveCwdFromPrefix(prefix, terminal.shellIntegration?.cwd) ?? terminal.shellIntegration?.cwd;
104
- return new vscode . TerminalCompletionList ( result . items , { filesRequested : result . filesRequested , foldersRequested : result . foldersRequested , cwd : result . cwd , pathSeparator : osIsWindows ( ) ? '\\' : '/' } ) ;
106
+ return new vscode . TerminalCompletionList ( result . items , { filesRequested : result . filesRequested , foldersRequested : result . foldersRequested , cwd : result . cwd , pathSeparator : isWindows ? '\\' : '/' } ) ;
105
107
}
106
108
return result . items ;
107
109
}
@@ -123,7 +125,7 @@ export async function resolveCwdFromPrefix(prefix: string, currentCwd?: vscode.U
123
125
// Get the nearest folder path from the prefix. This ignores everything after the `/` as
124
126
// they are what triggers changes in the directory.
125
127
let lastSlashIndex : number ;
126
- if ( osIsWindows ( ) ) {
128
+ if ( isWindows ) {
127
129
// TODO: This support is very basic, ideally the slashes supported would depend upon the
128
130
// shell type. For example git bash under Windows does not allow using \ as a path
129
131
// separator.
@@ -179,28 +181,10 @@ function createCompletionItem(cursorPosition: number, prefix: string, label: str
179
181
} ;
180
182
}
181
183
182
- async function isExecutable ( filePath : string ) : Promise < boolean > {
183
- // Windows doesn't have the concept of an executable bit and running any
184
- // file is possible. We considered using $PATHEXT here but since it's mostly
185
- // there for legacy reasons and it would be easier and more intuitive to add
186
- // a setting if needed instead.
187
- if ( osIsWindows ( ) ) {
188
- return true ;
189
- }
190
- try {
191
- const stats = await fs . stat ( filePath ) ;
192
- // On macOS/Linux, check if the executable bit is set
193
- return ( stats . mode & 0o100 ) !== 0 ;
194
- } catch ( error ) {
195
- // If the file does not exist or cannot be accessed, it's not executable
196
- return false ;
197
- }
198
- }
199
-
200
184
async function getCommandsInPath ( env : { [ key : string ] : string | undefined } = process . env ) : Promise < Set < string > | undefined > {
201
185
// Get PATH value
202
186
let pathValue : string | undefined ;
203
- if ( osIsWindows ( ) ) {
187
+ if ( isWindows ) {
204
188
const caseSensitivePathKey = Object . keys ( env ) . find ( key => key . toLowerCase ( ) === 'path' ) ;
205
189
if ( caseSensitivePathKey ) {
206
190
pathValue = env [ caseSensitivePathKey ] ;
@@ -218,7 +202,6 @@ async function getCommandsInPath(env: { [key: string]: string | undefined } = pr
218
202
}
219
203
220
204
// Extract executables from PATH
221
- const isWindows = osIsWindows ( ) ;
222
205
const paths = pathValue . split ( isWindows ? ';' : ':' ) ;
223
206
const pathSeparator = isWindows ? '\\' : '/' ;
224
207
const executables = new Set < string > ( ) ;
@@ -484,9 +467,7 @@ function getCompletionItemsFromArgs(args: Fig.SingleOrArray<Fig.Arg> | undefined
484
467
return { items, filesRequested, foldersRequested } ;
485
468
}
486
469
487
- function osIsWindows ( ) : boolean {
488
- return os . platform ( ) === 'win32' ;
489
- }
470
+
490
471
491
472
function getFirstCommand ( commandLine : string ) : string | undefined {
492
473
const wordsOnLine = commandLine . split ( ' ' ) ;
0 commit comments