@@ -14,14 +14,12 @@ import {
1414} from "vscode-languageclient/node" ;
1515
1616let client : LanguageClient ;
17- let downloadLs = true ;
1817
1918export function getArch ( ) : String | null {
2019 if ( process . arch == "x64" ) return "x86_64" ;
2120 if ( process . arch == "arm64" ) return "aarch64" ;
2221 else {
2322 vscode . window . showErrorMessage ( "Unsupported architecture: " + process . arch ) ;
24- downloadLs = false ;
2523 return null ;
2624 }
2725}
@@ -32,43 +30,41 @@ export function getPlatform(): String | null {
3230 if ( process . platform == "linux" ) return "unknown-linux-gnu" ;
3331 else {
3432 vscode . window . showErrorMessage ( "Unsupported platform: " + process . platform ) ;
35- downloadLs = false ;
3633 return null ;
3734 }
3835}
3936
40- async function downloadLSP ( context : ExtensionContext ) {
37+ async function downloadLSP ( context : ExtensionContext ) : Promise < void > {
4138 const TAG = "v0.3.8" ;
4239 const URL = `https://github.com/errata-ai/vale-ls/releases/download/${ TAG } /vale-ls-${ getArch ( ) } -${ getPlatform ( ) } .zip` ;
4340 const extStorage = context . extensionPath ;
4441 const tmpZip = path . join ( extStorage , "vale-ls.zip" ) ;
4542
46- vscode . window . showInformationMessage (
47- "First launch: Downloading Vale Language Server"
48- ) ;
43+ try {
44+ vscode . window . showInformationMessage (
45+ "First launch: Downloading Vale Language Server"
46+ ) ;
47+
48+ const response = await fetch ( URL ) ;
49+ if ( ! response . body ) {
50+ throw new Error ( "Failed to fetch the response body." ) ;
51+ }
4952
50- const response = await fetch ( URL ) ;
51- if ( response . body ) {
5253 const stream = Readable . fromWeb ( response . body ) ;
53- await writeFile ( tmpZip , stream ) . then ( async ( ) => {
54- // console.log("Downloaded to " + tmpZip);
55- await unzipper . Open . file ( tmpZip ) . then ( ( directory ) => {
56- // console.log("Extracting to " + extStorage);
57- directory
58- . extract ( { path : extStorage } )
59- . then ( async ( ) => {
60- fs . chmodSync ( path . join ( extStorage , "vale-ls" ) , 766 ) ;
61- } )
62- . finally ( ( ) => {
63- fs . unlinkSync ( tmpZip ) ;
64- vscode . window . showInformationMessage (
65- "First launch: Vale Language Server downloaded"
66- ) ;
67- } ) ;
68- } ) ;
69- } ) ;
70- } else {
71- throw new Error ( "Failed to fetch the response body." ) ;
54+ await writeFile ( tmpZip , stream ) ;
55+
56+ const directory = await unzipper . Open . file ( tmpZip ) ;
57+ await directory . extract ( { path : extStorage } ) ;
58+
59+ await fs . promises . chmod ( path . join ( extStorage , "vale-ls" ) , 0o755 ) ;
60+ await fs . promises . unlink ( tmpZip ) ;
61+
62+ vscode . window . showInformationMessage (
63+ "First launch: Vale Language Server downloaded"
64+ ) ;
65+ } catch ( error ) {
66+ console . error ( "Download failed:" , error ) ;
67+ throw error ;
7268 }
7369}
7470
@@ -83,98 +79,94 @@ interface valeArgs {
8379}
8480
8581export async function activate ( context : ExtensionContext ) {
86- // TODO: Always needs reload on first activate
8782 const filePath = path . join ( context . extensionPath , "vale-ls" ) ;
88- console . log ( filePath ) ;
83+
8984 try {
9085 await vscode . workspace . fs . stat ( vscode . Uri . file ( filePath ) ) ;
91- console . log ( "File exists" ) ;
86+ console . log ( "Language server exists" ) ;
9287 } catch {
93- console . log ( "File doesn't exist" ) ;
94-
95- await vscode . workspace . fs
96- . createDirectory ( context . globalStorageUri )
97- . then ( async ( ) => {
98- await downloadLSP ( context ) ;
99- } ) ;
100- } finally {
101- const valePath = path . join ( context . extensionPath , "vale-ls" ) ;
102- // TODO: Must be a better way?
103- var escapedPath = valePath . replace ( / ( \s ) / , "\\ " ) ;
104-
105- // TODO: Factor in https://vale.sh/docs/integrations/guide/#vale-ls
106- // Has the user defined a config file manually?
107- const configuration = vscode . workspace . getConfiguration ( ) ;
108- // Make global constant for now as will reuse and build upon later
109- let valeFilter : valeArgs = { value : "" } ;
110- let filters : string [ ] = [ ] ;
111-
112- // console.log("Using binary: " + escapedPath);
113-
114- // Handle old minAlertLevel to output as filter
115- if ( configuration . get ( "vale.valeCLI.minAlertLevel" ) !== "inherited" ) {
116- let minAlertLevel = configuration . get ( "vale.valeCLI.minAlertLevel" ) ;
117-
118- if ( minAlertLevel === "suggestion" ) {
119- filters . push ( `.Level in ["suggestion", "warning", "error"]` ) ;
120- }
121- if ( minAlertLevel === "warning" ) {
122- filters . push ( `.Level in ["warning", "error"]` ) ;
123- }
124- if ( minAlertLevel === "error" ) {
125- filters . push ( `.Level in ["error"]` ) ;
126- }
127- }
88+ console . log ( "Language server not found, downloading..." ) ;
89+ await downloadLSP ( context ) ;
12890
129- // Handle old enableSpellcheck to output as filter
130- if ( configuration . get ( "vale.enableSpellcheck" ) === false ) {
131- filters . push ( `.Extends != "spelling"` ) ;
132- }
91+ // Verify download succeeded
92+ await vscode . workspace . fs . stat ( vscode . Uri . file ( filePath ) ) ;
93+ }
94+
95+ console . log ( "Starting language server" ) ;
96+ const valePath = path . join ( context . extensionPath , "vale-ls" ) ;
97+ // TODO: Must be a better way?
98+ var escapedPath = valePath . replace ( / ( \s ) / , "\\ " ) ;
99+
100+ // TODO: Factor in https://vale.sh/docs/integrations/guide/#vale-ls
101+ // Has the user defined a config file manually?
102+ const configuration = vscode . workspace . getConfiguration ( ) ;
103+ // Make global constant for now as will reuse and build upon later
104+ let valeFilter : valeArgs = { value : "" } ;
105+ let filters : string [ ] = [ ] ;
106+
107+ // Handle old minAlertLevel to output as filter
108+ if ( configuration . get ( "vale.valeCLI.minAlertLevel" ) !== "inherited" ) {
109+ let minAlertLevel = configuration . get ( "vale.valeCLI.minAlertLevel" ) ;
133110
134- // Create combined filters
135- if ( filters . length > 0 ) {
136- valeFilter = filters . join ( " and " ) as unknown as valeArgs ;
111+ if ( minAlertLevel === "suggestion" ) {
112+ filters . push ( `.Level in ["suggestion", "warning", "error"]` ) ;
137113 }
114+ if ( minAlertLevel === "warning" ) {
115+ filters . push ( `.Level in ["warning", "error"]` ) ;
116+ }
117+ if ( minAlertLevel === "error" ) {
118+ filters . push ( `.Level in ["error"]` ) ;
119+ }
120+ }
138121
139- let valeConfig : Record < valeConfigOptions , valeArgs > = {
140- configPath : configuration . get ( "vale.valeCLI.configPath" ) as valeArgs ,
141- syncOnStartup : configuration . get (
142- "vale.valeCLI.syncOnStartup"
143- ) as valeArgs ,
144- filter : valeFilter as unknown as valeArgs ,
145- installVale : configuration . get ( "vale.valeCLI.installVale" ) as valeArgs ,
146- } ;
147- // console.log(valeConfig);
148- // TODO: So do I need the below?
149- let tempArgs : never [ ] = [ ] ;
150- let serverOptions : ServerOptions = {
151- run : { command : escapedPath , args : tempArgs } ,
152- debug : { command : escapedPath , args : tempArgs } ,
153- } ;
154-
155- // Options to control the language client
156- let clientOptions : LanguageClientOptions = {
157- // TODO: Refine
158- initializationOptions : valeConfig ,
159- documentSelector : [ { scheme : "file" , language : "*" } ] ,
160- synchronize : {
161- fileEvents : workspace . createFileSystemWatcher ( "**/.clientrc" ) ,
162- } ,
163- } ;
164-
165- // Create the language client and start the client.
166- client = new LanguageClient (
167- "vale" ,
168- "Vale VSCode" ,
169- serverOptions ,
170- clientOptions
171- ) ;
122+ // Handle old enableSpellcheck to output as filter
123+ if ( configuration . get ( "vale.enableSpellcheck" ) === false ) {
124+ filters . push ( `.Extends != "spelling"` ) ;
125+ }
126+
127+ // Create combined filters
128+ if ( filters . length > 0 ) {
129+ valeFilter = filters . join ( " and " ) as unknown as valeArgs ;
130+ }
172131
173- // Start the client. This will also launch the server
174- await client . start ( ) . catch ( ( err ) => {
175- console . error ( err ) ;
176- vscode . window . showErrorMessage ( "Failed to start Vale Language Server" ) ;
177- } ) ;
132+ let valeConfig : Record < valeConfigOptions , valeArgs > = {
133+ configPath : configuration . get ( "vale.valeCLI.configPath" ) as valeArgs ,
134+ syncOnStartup : configuration . get ( "vale.valeCLI.syncOnStartup" ) as valeArgs ,
135+ filter : valeFilter as unknown as valeArgs ,
136+ installVale : configuration . get ( "vale.valeCLI.installVale" ) as valeArgs ,
137+ } ;
138+
139+ // TODO: So do I need the below?
140+ let tempArgs : never [ ] = [ ] ;
141+ let serverOptions : ServerOptions = {
142+ run : { command : escapedPath , args : tempArgs } ,
143+ debug : { command : escapedPath , args : tempArgs } ,
144+ } ;
145+
146+ // Options to control the language client
147+ let clientOptions : LanguageClientOptions = {
148+ // TODO: Refine
149+ initializationOptions : valeConfig ,
150+ documentSelector : [ { scheme : "file" , language : "*" } ] ,
151+ synchronize : {
152+ fileEvents : workspace . createFileSystemWatcher ( "**/.clientrc" ) ,
153+ } ,
154+ } ;
155+
156+ // Create the language client and start the client.
157+ client = new LanguageClient (
158+ "vale" ,
159+ "Vale VSCode" ,
160+ serverOptions ,
161+ clientOptions
162+ ) ;
163+
164+ try {
165+ await client . start ( ) ;
166+ } catch ( err ) {
167+ console . error ( err ) ;
168+ vscode . window . showErrorMessage ( "Failed to start Vale Language Server" ) ;
169+ throw err ;
178170 }
179171}
180172
0 commit comments