44 * Licensed under the MIT License. See License.txt in the project root for license information.
55 * ------------------------------------------------------------------------------------------ */
66
7- import * as path from 'path' ;
8- // import { workspace, ExtensionContext } from "vscode";
97import * as vscode from 'vscode' ;
108import * as which from 'which' ;
119
1210import {
1311 LanguageClient ,
1412 LanguageClientOptions ,
1513 ServerOptions ,
16- TransportKind ,
1714} from 'vscode-languageclient/node' ;
1815
1916let client : LanguageClient ;
2017
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+
2143export function activate ( context : vscode . ExtensionContext ) {
2244 console . log ( 'Terminals: ' + ( < any > vscode . window ) . terminals . length ) ;
45+
46+ // Find Nushell executable once and reuse it
47+ const found_nushell_path = findNushellExecutable ( ) ;
48+
2349 context . subscriptions . push (
2450 vscode . window . registerTerminalProfileProvider ( 'nushell_default' , {
2551 provideTerminalProfile (
2652 token : vscode . CancellationToken ,
2753 ) : 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-
7854 if ( found_nushell_path == null ) {
7955 console . log (
8056 'Nushell not found in env:PATH or any of the heuristic locations.' ,
@@ -116,37 +92,39 @@ export function activate(context: vscode.ExtensionContext) {
11692 } ) ,
11793 ) ;
11894
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+ }
127107
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
130109 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' ]
136117 } ,
137118 } ;
138119
139120 // Options to control the language client
140121 const clientOptions : LanguageClientOptions = {
141- // Register the server for plain text documents
122+ // Register the server for nushell files
142123 documentSelector : [ { scheme : 'file' , language : 'nushell' } ] ,
143124 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+ }
150128 } ;
151129
152130 // Create the language client and start the client.
@@ -158,7 +136,9 @@ export function activate(context: vscode.ExtensionContext) {
158136 ) ;
159137
160138 // 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+ } ) ;
162142}
163143
164144export function deactivate ( ) : Thenable < void > | undefined {
0 commit comments