4
4
* Licensed under the MIT License. See License.txt in the project root for license information.
5
5
* ------------------------------------------------------------------------------------------ */
6
6
7
- import * as path from 'path' ;
8
- // import { workspace, ExtensionContext } from "vscode";
9
7
import * as vscode from 'vscode' ;
10
8
import * as which from 'which' ;
11
9
12
10
import {
13
11
LanguageClient ,
14
12
LanguageClientOptions ,
15
13
ServerOptions ,
16
- TransportKind ,
17
14
} from 'vscode-languageclient/node' ;
18
15
19
16
let client : LanguageClient ;
20
17
18
+ function findNushellExecutable ( ) : string | null {
19
+ try {
20
+ // Get the configured executable path from VSCode settings
21
+ // Use null for resource to get global/workspace settings
22
+ const config = vscode . workspace . getConfiguration ( 'nushellLanguageServer' , null ) ;
23
+ const configuredPath = config . get < string > ( 'nushellExecutablePath' , 'nu' ) ;
24
+
25
+ // If user configured a specific path, try to find it
26
+ if ( configuredPath && configuredPath !== 'nu' ) {
27
+ // User specified a custom path
28
+ try {
29
+ // Test if the configured path works
30
+ return which . sync ( configuredPath , { nothrow : true } ) ;
31
+ } catch {
32
+ // Fall back to searching PATH for 'nu'
33
+ }
34
+ }
35
+
36
+ // Fall back to searching PATH for 'nu'
37
+ return which . sync ( 'nu' , { nothrow : true } ) ;
38
+ } catch ( error ) {
39
+ return null ;
40
+ }
41
+ }
42
+
21
43
export function activate ( context : vscode . ExtensionContext ) {
22
44
console . log ( 'Terminals: ' + ( < any > vscode . window ) . terminals . length ) ;
45
+
46
+ // Find Nushell executable once and reuse it
47
+ const found_nushell_path = findNushellExecutable ( ) ;
48
+
23
49
context . subscriptions . push (
24
50
vscode . window . registerTerminalProfileProvider ( 'nushell_default' , {
25
51
provideTerminalProfile (
26
52
token : vscode . CancellationToken ,
27
53
) : vscode . ProviderResult < vscode . TerminalProfile > {
28
- // const which = require('which');
29
- // const path = require('path');
30
-
31
- const PATH_FROM_ENV = process . env [ 'PATH' ] ;
32
- const pathsToCheck = [
33
- PATH_FROM_ENV ,
34
- // cargo install location
35
- ( process . env [ 'CARGO_HOME' ] || '~/.cargo' ) + '/bin' ,
36
-
37
- // winget on Windows install location
38
- 'c:\\program files\\nu\\bin' ,
39
- // just add a few other drives for fun
40
- 'd:\\program files\\nu\\bin' ,
41
- 'e:\\program files\\nu\\bin' ,
42
- 'f:\\program files\\nu\\bin' ,
43
-
44
- // SCOOP:TODO
45
- // all user installed programs and scoop itself install to
46
- // c:\users\<user>\scoop\ unless SCOOP env var is set
47
- // globally installed programs go in
48
- // c:\programdata\scoop unless SCOOP_GLOBAL env var is set
49
- // scoop install location
50
- // SCOOP should already set up the correct `PATH` env var
51
- //"~/scoop/apps/nu/*/nu.exe",
52
- //"~/scoop/shims/nu.exe",
53
-
54
- // chocolatey install location - same as winget
55
- // 'c:\\program files\\nu\\bin\\nu.exe',
56
-
57
- // macos dmg install
58
- // we currentl don't have a dmg install
59
-
60
- // linux and mac zips can be put anywhere so it's hard to guess
61
-
62
- // brew install location mac
63
- // intel
64
- '/usr/local/bin' ,
65
- // arm
66
- '/opt/homebrew/bin' ,
67
-
68
- // native package manager install location
69
- // standard location should be in `PATH` env var
70
- //"/usr/bin/nu",
71
- ] ;
72
-
73
- const found_nushell_path = which . sync ( 'nu' , {
74
- nothrow : true ,
75
- path : pathsToCheck . join ( path . delimiter ) ,
76
- } ) ;
77
-
78
54
if ( found_nushell_path == null ) {
79
55
console . log (
80
56
'Nushell not found in env:PATH or any of the heuristic locations.' ,
@@ -116,37 +92,39 @@ export function activate(context: vscode.ExtensionContext) {
116
92
} ) ,
117
93
) ;
118
94
119
- // The server is implemented in node
120
- const serverModule = context . asAbsolutePath (
121
- path . join ( 'out' , 'server' , 'src' , 'server.js' ) ,
122
- ) ;
123
-
124
- // The debug options for the server
125
- // --inspect=6009: runs the server in Node's Inspector mode so VS Code can attach to the server for debugging
126
- const debugOptions = { execArgv : [ '--nolazy' , '--inspect=6009' ] } ;
95
+ // Check if Nushell was found for LSP server
96
+ if ( ! found_nushell_path ) {
97
+ vscode . window . showErrorMessage (
98
+ 'Nushell executable not found. Please install Nushell and restart VSCode.' ,
99
+ 'Install from website'
100
+ ) . then ( ( selection ) => {
101
+ if ( selection ) {
102
+ vscode . env . openExternal ( vscode . Uri . parse ( 'https://www.nushell.sh/' ) ) ;
103
+ }
104
+ } ) ;
105
+ return ;
106
+ }
127
107
128
- // If the extension is launched in debug mode then the debug server options are used
129
- // Otherwise the run options are used
108
+ // Use Nushell's native LSP server
130
109
const serverOptions : ServerOptions = {
131
- run : { module : serverModule , transport : TransportKind . ipc } ,
132
- debug : {
133
- module : serverModule ,
134
- transport : TransportKind . ipc ,
135
- options : debugOptions ,
110
+ run : {
111
+ command : found_nushell_path ,
112
+ args : [ '--lsp' ]
113
+ } ,
114
+ debug : {
115
+ command : found_nushell_path ,
116
+ args : [ '--lsp' ]
136
117
} ,
137
118
} ;
138
119
139
120
// Options to control the language client
140
121
const clientOptions : LanguageClientOptions = {
141
- // Register the server for plain text documents
122
+ // Register the server for nushell files
142
123
documentSelector : [ { scheme : 'file' , language : 'nushell' } ] ,
143
124
synchronize : {
144
- // Notify the server about file changes to '.clientrc files contained in the workspace
145
- fileEvents : vscode . workspace . createFileSystemWatcher ( '**/.clientrc' ) ,
146
- } ,
147
- markdown : {
148
- isTrusted : true ,
149
- } ,
125
+ // Notify the server about file changes to nushell files
126
+ fileEvents : vscode . workspace . createFileSystemWatcher ( '**/*.nu' ) ,
127
+ }
150
128
} ;
151
129
152
130
// Create the language client and start the client.
@@ -158,7 +136,9 @@ export function activate(context: vscode.ExtensionContext) {
158
136
) ;
159
137
160
138
// Start the client. This will also launch the server
161
- client . start ( ) ;
139
+ client . start ( ) . catch ( ( error ) => {
140
+ vscode . window . showErrorMessage ( `Failed to start Nushell language server: ${ error . message } ` ) ;
141
+ } ) ;
162
142
}
163
143
164
144
export function deactivate ( ) : Thenable < void > | undefined {
0 commit comments