6
6
7
7
import * as vscode from 'vscode' ;
8
8
import * as which from 'which' ;
9
+ import { window , type OutputChannel } from 'vscode' ;
9
10
10
11
import {
11
12
LanguageClient ,
12
13
LanguageClientOptions ,
13
14
ServerOptions ,
15
+ Trace ,
14
16
} from 'vscode-languageclient/node' ;
15
- import { time } from 'console' ;
16
17
17
18
let client : LanguageClient ;
19
+ let outputChannel : OutputChannel ; // Trace channel
20
+ let serverOutputChannel : OutputChannel ; // Server logs channel (single instance)
18
21
19
22
function findNushellExecutable ( ) : string | null {
20
23
try {
@@ -48,6 +51,24 @@ function startLanguageServer(
48
51
context : vscode . ExtensionContext ,
49
52
found_nushell_path : string ,
50
53
) : void {
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 ) ;
71
+
51
72
// Use Nushell's native LSP server
52
73
const serverOptions : ServerOptions = {
53
74
run : {
@@ -60,8 +81,22 @@ function startLanguageServer(
60
81
} ,
61
82
} ;
62
83
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
+
63
90
// Options to control the language client
64
91
const clientOptions : LanguageClientOptions = {
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 ,
96
+ markdown : {
97
+ isTrusted : true ,
98
+ supportHtml : true ,
99
+ } ,
65
100
initializationOptions : {
66
101
timeout : 10000 , // 10 seconds
67
102
} ,
@@ -81,6 +116,43 @@ function startLanguageServer(
81
116
clientOptions ,
82
117
) ;
83
118
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
+
84
156
// Start the language client and register a disposable that stops it when disposed
85
157
client . start ( ) . catch ( ( error ) => {
86
158
vscode . window . showErrorMessage (
@@ -168,6 +240,9 @@ export function activate(context: vscode.ExtensionContext) {
168
240
return ;
169
241
}
170
242
243
+ console . log ( `Found nushell executable at: ${ found_nushell_path } ` ) ;
244
+ console . log ( 'Activating Nushell Language Server extension.' ) ;
245
+
171
246
// Start the language server when the extension is activated
172
247
startLanguageServer ( context , found_nushell_path ) ;
173
248
0 commit comments