@@ -35,6 +35,23 @@ export type FindNvimOptions = {
35
35
* (Optional) Stop searching after found a valid match
36
36
*/
37
37
readonly firstMatch ?: boolean ;
38
+ /**
39
+ * (Optional) Additional specific file paths to check for Nvim executables.
40
+ * These paths will be checked before searching `dirs`.
41
+ * Useful for allowing users to specify exact Nvim executable locations.
42
+ *
43
+ * Example: ['/usr/local/bin/nvim', '/opt/homebrew/bin/nvim']
44
+ */
45
+ readonly paths ?: string [ ] ;
46
+ /**
47
+ * (Optional) Additional directories to search for Nvim executables.
48
+ * These directories will be searched after checking `paths`
49
+ * but before searching `$PATH` and other default locations.
50
+ * Useful for including non-standard installation directories.
51
+ *
52
+ * Example: ['/opt/neovim/bin', '/home/user/custom/bin']
53
+ */
54
+ readonly dirs ?: string [ ] ;
38
55
} ;
39
56
40
57
export type FindNvimResult = {
@@ -117,13 +134,14 @@ function compareVersions(a: string, b: string): number {
117
134
return 0 ;
118
135
}
119
136
120
- function getPlatformPaths ( ) {
137
+ function normalizePath ( path : string ) : string {
138
+ return normalize ( windows ? path . toLowerCase ( ) : path ) ;
139
+ }
140
+
141
+ function getPlatformSearchDirs ( ) : Set < string > {
121
142
const paths = new Set < string > ( ) ;
122
143
const { PATH , USERPROFILE , LOCALAPPDATA , PROGRAMFILES , HOME } = process . env ;
123
144
124
- const normalizePath = ( path : string ) =>
125
- normalize ( windows ? path . toLowerCase ( ) : path ) ;
126
-
127
145
PATH ?. split ( delimiter ) . forEach ( p => paths . add ( normalizePath ( p ) ) ) ;
128
146
129
147
// Add common Neovim installation paths not always in the system's PATH.
@@ -147,6 +165,7 @@ function getPlatformPaths() {
147
165
paths . add ( normalizePath ( `${ PROGRAMFILES } (x86)/WinGet/Packages` ) ) ;
148
166
}
149
167
} else {
168
+ // Common paths for Unix-like systems
150
169
[
151
170
'/usr/local/bin' ,
152
171
'/usr/bin' ,
@@ -170,15 +189,24 @@ function getPlatformPaths() {
170
189
* @param opt.minVersion See {@link FindNvimOptions.minVersion}
171
190
* @param opt.orderBy See {@link FindNvimOptions.orderBy}
172
191
* @param opt.firstMatch See {@link FindNvimOptions.firstMatch}
192
+ * @param opt.paths See {@link FindNvimOptions.paths}
193
+ * @param opt.dirs See {@link FindNvimOptions.dirs}
173
194
*/
174
195
export function findNvim ( opt : FindNvimOptions = { } ) : Readonly < FindNvimResult > {
175
- const paths = getPlatformPaths ( ) ;
196
+ const platformDirs = getPlatformSearchDirs ( ) ;
197
+ const nvimExecutable = windows ? 'nvim.exe' : 'nvim' ;
198
+ const normalizedPathsFromUser = ( opt . paths ?? [ ] ) . map ( normalizePath ) ;
199
+
200
+ const allPaths = new Set < string > ( [
201
+ ...normalizedPathsFromUser ,
202
+ ...( opt . dirs ?? [ ] ) . map ( dir => normalizePath ( join ( dir , nvimExecutable ) ) ) ,
203
+ ...[ ...platformDirs ] . map ( dir => join ( dir , nvimExecutable ) ) ,
204
+ ] ) ;
176
205
177
206
const matches = new Array < NvimVersion > ( ) ;
178
207
const invalid = new Array < NvimVersion > ( ) ;
179
- for ( const path of paths ) {
180
- const nvimPath = join ( path , windows ? 'nvim.exe' : 'nvim' ) ;
181
- if ( existsSync ( nvimPath ) ) {
208
+ for ( const nvimPath of allPaths ) {
209
+ if ( existsSync ( nvimPath ) || normalizedPathsFromUser . includes ( nvimPath ) ) {
182
210
try {
183
211
accessSync ( nvimPath , constants . X_OK ) ;
184
212
const nvimVersionFull = execFileSync ( nvimPath , [
@@ -245,5 +273,6 @@ if (process.env.NODE_ENV === 'test') {
245
273
exportsForTesting = {
246
274
parseVersion,
247
275
compareVersions,
276
+ normalizePath,
248
277
} ;
249
278
}
0 commit comments