diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-03-18 21:52:27 +0000 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-03-18 21:52:27 +0000 |
commit | 91576afc7e64f11dde2bed14b578e4914d253a6a (patch) | |
tree | 1a3b26b40881e2b1d1e87992090a79c0b40b09d5 | |
parent | 7fc35d391c76aed4defc8600e75215845afa66b7 (diff) | |
parent | 34b428cc5e4b37ecd44063547f73fd1b05bf2b9e (diff) |
Merge #995
995: Install and run `cargo watch` if user agrees r=matklad a=Xanewok
This isn't a glorious patch but hopefully is useful :+1: This introduces a default background `cargo watch` task and (separately from that) asks the user on every startup if they want to run `cargo watch` (installs it if it's not available).
r? @matklad does it fit the what you've been thinking about?
Co-authored-by: Igor Matuszewski <[email protected]>
-rw-r--r-- | editors/code/package.json | 5 | ||||
-rw-r--r-- | editors/code/src/commands/runnables.ts | 91 | ||||
-rw-r--r-- | editors/code/src/config.ts | 8 | ||||
-rw-r--r-- | editors/code/src/extension.ts | 4 |
4 files changed, 106 insertions, 2 deletions
diff --git a/editors/code/package.json b/editors/code/package.json index 3834f2847..3e8cde388 100644 --- a/editors/code/package.json +++ b/editors/code/package.json | |||
@@ -168,6 +168,11 @@ | |||
168 | "default": "ra_lsp_server", | 168 | "default": "ra_lsp_server", |
169 | "description": "Path to ra_lsp_server executable" | 169 | "description": "Path to ra_lsp_server executable" |
170 | }, | 170 | }, |
171 | "rust-analyzer.enableCargoWatchOnStartup": { | ||
172 | "type": "boolean", | ||
173 | "default": "true", | ||
174 | "description": "When enabled, ask the user whether to run `cargo watch` on startup" | ||
175 | }, | ||
171 | "rust-analyzer.trace.server": { | 176 | "rust-analyzer.trace.server": { |
172 | "type": "string", | 177 | "type": "string", |
173 | "scope": "window", | 178 | "scope": "window", |
diff --git a/editors/code/src/commands/runnables.ts b/editors/code/src/commands/runnables.ts index c0f2ada76..ea2883ad4 100644 --- a/editors/code/src/commands/runnables.ts +++ b/editors/code/src/commands/runnables.ts | |||
@@ -1,5 +1,8 @@ | |||
1 | import * as child_process from 'child_process'; | ||
2 | import * as util from 'util'; | ||
1 | import * as vscode from 'vscode'; | 3 | import * as vscode from 'vscode'; |
2 | import * as lc from 'vscode-languageclient'; | 4 | import * as lc from 'vscode-languageclient'; |
5 | |||
3 | import { Server } from '../server'; | 6 | import { Server } from '../server'; |
4 | 7 | ||
5 | interface RunnablesParams { | 8 | interface RunnablesParams { |
@@ -8,7 +11,6 @@ interface RunnablesParams { | |||
8 | } | 11 | } |
9 | 12 | ||
10 | interface Runnable { | 13 | interface Runnable { |
11 | range: lc.Range; | ||
12 | label: string; | 14 | label: string; |
13 | bin: string; | 15 | bin: string; |
14 | args: string[]; | 16 | args: string[]; |
@@ -38,7 +40,7 @@ function createTask(spec: Runnable): vscode.Task { | |||
38 | const TASK_SOURCE = 'Rust'; | 40 | const TASK_SOURCE = 'Rust'; |
39 | const definition: CargoTaskDefinition = { | 41 | const definition: CargoTaskDefinition = { |
40 | type: 'cargo', | 42 | type: 'cargo', |
41 | label: 'cargo', | 43 | label: spec.label, |
42 | command: spec.bin, | 44 | command: spec.bin, |
43 | args: spec.args, | 45 | args: spec.args, |
44 | env: spec.env | 46 | env: spec.env |
@@ -124,3 +126,88 @@ export async function handleSingle(runnable: Runnable) { | |||
124 | 126 | ||
125 | return vscode.tasks.executeTask(task); | 127 | return vscode.tasks.executeTask(task); |
126 | } | 128 | } |
129 | |||
130 | export const autoCargoWatchTask: vscode.Task = { | ||
131 | name: 'cargo watch', | ||
132 | source: 'rust-analyzer', | ||
133 | definition: { | ||
134 | type: 'watch' | ||
135 | }, | ||
136 | execution: new vscode.ShellExecution('cargo', ['watch'], { cwd: '.' }), | ||
137 | |||
138 | isBackground: true, | ||
139 | problemMatchers: ['$rustc-watch'], | ||
140 | presentationOptions: { | ||
141 | clear: true | ||
142 | }, | ||
143 | // Not yet exposed in the vscode.d.ts | ||
144 | // https://github.com/Microsoft/vscode/blob/ea7c31d770e04b51d586b0d3944f3a7feb03afb9/src/vs/workbench/contrib/tasks/common/tasks.ts#L444-L456 | ||
145 | runOptions: ({ | ||
146 | runOn: 2 // RunOnOptions.folderOpen | ||
147 | } as unknown) as vscode.RunOptions | ||
148 | }; | ||
149 | |||
150 | /** | ||
151 | * Interactively asks the user whether we should run `cargo check` in order to | ||
152 | * provide inline diagnostics; the user is met with a series of dialog boxes | ||
153 | * that, when accepted, allow us to `cargo install cargo-watch` and then run it. | ||
154 | */ | ||
155 | export async function interactivelyStartCargoWatch() { | ||
156 | if (!Server.config.enableCargoWatchOnStartup) { | ||
157 | return; | ||
158 | } | ||
159 | |||
160 | const execPromise = util.promisify(child_process.exec); | ||
161 | |||
162 | const watch = await vscode.window.showInformationMessage( | ||
163 | 'Start watching changes with cargo? (Executes `cargo watch`, provides inline diagnostics)', | ||
164 | 'yes', | ||
165 | 'no' | ||
166 | ); | ||
167 | if (watch === 'no') { | ||
168 | return; | ||
169 | } | ||
170 | |||
171 | const { stderr } = await execPromise('cargo watch --version').catch(e => e); | ||
172 | if (stderr.includes('no such subcommand: `watch`')) { | ||
173 | const msg = | ||
174 | 'The `cargo-watch` subcommand is not installed. Install? (takes ~1-2 minutes)'; | ||
175 | const install = await vscode.window.showInformationMessage( | ||
176 | msg, | ||
177 | 'yes', | ||
178 | 'no' | ||
179 | ); | ||
180 | if (install === 'no') { | ||
181 | return; | ||
182 | } | ||
183 | |||
184 | const label = 'install-cargo-watch'; | ||
185 | const taskFinished = new Promise((resolve, reject) => { | ||
186 | const disposable = vscode.tasks.onDidEndTask(({ execution }) => { | ||
187 | if (execution.task.name === label) { | ||
188 | disposable.dispose(); | ||
189 | resolve(); | ||
190 | } | ||
191 | }); | ||
192 | }); | ||
193 | |||
194 | vscode.tasks.executeTask( | ||
195 | createTask({ | ||
196 | label, | ||
197 | bin: 'cargo', | ||
198 | args: ['install', 'cargo-watch'], | ||
199 | env: {} | ||
200 | }) | ||
201 | ); | ||
202 | await taskFinished; | ||
203 | const output = await execPromise('cargo watch --version').catch(e => e); | ||
204 | if (output.stderr !== '') { | ||
205 | vscode.window.showErrorMessage( | ||
206 | `Couldn't install \`cargo-\`watch: ${output.stderr}` | ||
207 | ); | ||
208 | return; | ||
209 | } | ||
210 | } | ||
211 | |||
212 | vscode.tasks.executeTask(autoCargoWatchTask); | ||
213 | } | ||
diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts index afc5cc6af..d8795f3b0 100644 --- a/editors/code/src/config.ts +++ b/editors/code/src/config.ts | |||
@@ -9,6 +9,7 @@ export class Config { | |||
9 | public enableEnhancedTyping = true; | 9 | public enableEnhancedTyping = true; |
10 | public raLspServerPath = RA_LSP_DEBUG || 'ra_lsp_server'; | 10 | public raLspServerPath = RA_LSP_DEBUG || 'ra_lsp_server'; |
11 | public showWorkspaceLoadedNotification = true; | 11 | public showWorkspaceLoadedNotification = true; |
12 | public enableCargoWatchOnStartup = true; | ||
12 | 13 | ||
13 | private prevEnhancedTyping: null | boolean = null; | 14 | private prevEnhancedTyping: null | boolean = null; |
14 | 15 | ||
@@ -68,5 +69,12 @@ export class Config { | |||
68 | this.raLspServerPath = | 69 | this.raLspServerPath = |
69 | RA_LSP_DEBUG || (config.get('raLspServerPath') as string); | 70 | RA_LSP_DEBUG || (config.get('raLspServerPath') as string); |
70 | } | 71 | } |
72 | |||
73 | if (config.has('enableCargoWatchOnStartup')) { | ||
74 | this.enableCargoWatchOnStartup = config.get<boolean>( | ||
75 | 'enableCargoWatchOnStartup', | ||
76 | true | ||
77 | ); | ||
78 | } | ||
71 | } | 79 | } |
72 | } | 80 | } |
diff --git a/editors/code/src/extension.ts b/editors/code/src/extension.ts index 941beba18..2e13c87de 100644 --- a/editors/code/src/extension.ts +++ b/editors/code/src/extension.ts | |||
@@ -2,6 +2,7 @@ import * as vscode from 'vscode'; | |||
2 | import * as lc from 'vscode-languageclient'; | 2 | import * as lc from 'vscode-languageclient'; |
3 | 3 | ||
4 | import * as commands from './commands'; | 4 | import * as commands from './commands'; |
5 | import { interactivelyStartCargoWatch } from './commands/runnables'; | ||
5 | import { SyntaxTreeContentProvider } from './commands/syntaxTree'; | 6 | import { SyntaxTreeContentProvider } from './commands/syntaxTree'; |
6 | import * as events from './events'; | 7 | import * as events from './events'; |
7 | import * as notifications from './notifications'; | 8 | import * as notifications from './notifications'; |
@@ -119,6 +120,9 @@ export function activate(context: vscode.ExtensionContext) { | |||
119 | context.subscriptions | 120 | context.subscriptions |
120 | ); | 121 | ); |
121 | 122 | ||
123 | // Executing `cargo watch` provides us with inline diagnostics on save | ||
124 | interactivelyStartCargoWatch(); | ||
125 | |||
122 | // Start the language server, finally! | 126 | // Start the language server, finally! |
123 | Server.start(allNotifications); | 127 | Server.start(allNotifications); |
124 | } | 128 | } |