@@ -12,11 +12,12 @@ import {
1212 LanguageClient ,
1313 LanguageClientOptions ,
1414 ServerOptions ,
15+ Trace ,
1516} from 'vscode-languageclient/node' ;
16- import { time } from 'console' ;
1717
1818let client : LanguageClient ;
19- let outputChannel : OutputChannel ;
19+ let outputChannel : OutputChannel ; // Trace channel
20+ let serverOutputChannel : OutputChannel ; // Server logs channel (single instance)
2021
2122function findNushellExecutable ( ) : string | null {
2223 try {
@@ -50,7 +51,23 @@ function startLanguageServer(
5051 context : vscode . ExtensionContext ,
5152 found_nushell_path : string ,
5253) : void {
53- outputChannel = window . createOutputChannel ( 'Nushell LSP Output' , 'log' ) ;
54+ // Prevent duplicate clients/channels
55+ if ( client ) {
56+ vscode . window . showInformationMessage (
57+ 'Nushell Language Server is already running.' ,
58+ ) ;
59+ return ;
60+ }
61+ // Channel to receive detailed JSON-RPC trace between VS Code and the LSP server
62+ if ( outputChannel ) {
63+ try {
64+ outputChannel . dispose ( ) ;
65+ } catch {
66+ // ignore
67+ }
68+ }
69+ outputChannel = window . createOutputChannel ( 'Nushell LSP Trace' ) ;
70+ context . subscriptions . push ( outputChannel ) ;
5471
5572 // Use Nushell's native LSP server
5673 const serverOptions : ServerOptions = {
@@ -64,9 +81,18 @@ function startLanguageServer(
6481 } ,
6582 } ;
6683
84+ // Ensure a single server output channel exists and is reused
85+ if ( ! serverOutputChannel ) {
86+ serverOutputChannel = window . createOutputChannel ( 'Nushell Language Server' ) ;
87+ context . subscriptions . push ( serverOutputChannel ) ;
88+ }
89+
6790 // Options to control the language client
6891 const clientOptions : LanguageClientOptions = {
69- outputChannelName : 'Nushell Language Server' ,
92+ // Route general server logs to a single, reusable channel
93+ outputChannel : serverOutputChannel ,
94+ // Send JSON-RPC trace to a dedicated channel visible in the Output panel
95+ traceOutputChannel : outputChannel ,
7096 markdown : {
7197 isTrusted : true ,
7298 supportHtml : true ,
@@ -90,6 +116,43 @@ function startLanguageServer(
90116 clientOptions ,
91117 ) ;
92118
119+ // Initialize trace level from settings and react to changes
120+ const applyTraceFromConfig = ( ) => {
121+ const configured = vscode . workspace
122+ . getConfiguration ( 'nushellLanguageServer' )
123+ . get < 'off' | 'messages' | 'verbose' > ( 'trace.server' ) ;
124+ const level : 'off' | 'messages' | 'verbose' = configured ?? 'messages' ;
125+ const map : Record < 'off' | 'messages' | 'verbose' , Trace > = {
126+ off : Trace . Off ,
127+ messages : Trace . Messages ,
128+ verbose : Trace . Verbose ,
129+ } ;
130+ client . setTrace ( map [ level ] ) ;
131+ try {
132+ outputChannel . appendLine ( `[Nushell] JSON-RPC tracing set to: ${ level } ` ) ;
133+ if ( level !== 'off' ) {
134+ outputChannel . show ( true ) ;
135+ }
136+ } catch {
137+ // ignore
138+ }
139+ } ;
140+ applyTraceFromConfig ( ) ;
141+ const cfgDisp = vscode . workspace . onDidChangeConfiguration ( ( e ) => {
142+ if ( e . affectsConfiguration ( 'nushellLanguageServer.trace.server' ) ) {
143+ applyTraceFromConfig ( ) ;
144+ }
145+ } ) ;
146+ context . subscriptions . push ( cfgDisp ) ;
147+ // Log client lifecycle
148+ client . onDidChangeState ( ( e ) => {
149+ try {
150+ outputChannel . appendLine ( `[Nushell] Client state changed: ${ e . newState } ` ) ;
151+ } catch {
152+ // ignore
153+ }
154+ } ) ;
155+
93156 // Start the language client and register a disposable that stops it when disposed
94157 client . start ( ) . catch ( ( error ) => {
95158 vscode . window . showErrorMessage (
@@ -177,7 +240,6 @@ export function activate(context: vscode.ExtensionContext) {
177240 return ;
178241 }
179242
180- context . subscriptions . push ( outputChannel ) ;
181243 console . log ( `Found nushell executable at: ${ found_nushell_path } ` ) ;
182244 console . log ( 'Activating Nushell Language Server extension.' ) ;
183245
0 commit comments