|
| 1 | +import * as Process from 'child_process' |
1 | 2 | import * as path from 'path'
|
| 3 | +import * as Path from 'path' |
2 | 4 | import * as TurndownService from 'turndown'
|
3 | 5 | import * as LSP from 'vscode-languageserver'
|
4 | 6 | import { TextDocument } from 'vscode-languageserver-textdocument'
|
@@ -123,6 +125,16 @@ export default class BashServer {
|
123 | 125 | )
|
124 | 126 | }
|
125 | 127 |
|
| 128 | + private getCommandNameAtPoint( |
| 129 | + params: LSP.ReferenceParams | LSP.TextDocumentPositionParams, |
| 130 | + ): string | null { |
| 131 | + return this.analyzer.commandNameAtPoint( |
| 132 | + params.textDocument.uri, |
| 133 | + params.position.line, |
| 134 | + params.position.character, |
| 135 | + ) |
| 136 | + } |
| 137 | + |
126 | 138 | private logRequest({
|
127 | 139 | request,
|
128 | 140 | params,
|
@@ -323,6 +335,22 @@ export default class BashServer {
|
323 | 335 | return []
|
324 | 336 | }
|
325 | 337 |
|
| 338 | + let options: string[] = [] |
| 339 | + if (word && word.startsWith('-')) { |
| 340 | + const commandName = this.getCommandNameAtPoint({ |
| 341 | + ...params, |
| 342 | + position: { |
| 343 | + line: params.position.line, |
| 344 | + // Go one character back to get completion on the current word |
| 345 | + character: Math.max(params.position.character - 1, 0), |
| 346 | + }, |
| 347 | + }) |
| 348 | + |
| 349 | + if (commandName) { |
| 350 | + options = getCommandOptions(commandName, word) |
| 351 | + } |
| 352 | + } |
| 353 | + |
326 | 354 | const currentUri = params.textDocument.uri
|
327 | 355 |
|
328 | 356 | // TODO: an improvement here would be to detect if the current word is
|
@@ -385,11 +413,21 @@ export default class BashServer {
|
385 | 413 | },
|
386 | 414 | }))
|
387 | 415 |
|
| 416 | + const optionsCompletions = options.map(option => ({ |
| 417 | + label: option, |
| 418 | + kind: LSP.SymbolKind.Interface, |
| 419 | + data: { |
| 420 | + name: option, |
| 421 | + type: CompletionItemDataType.Symbol, |
| 422 | + }, |
| 423 | + })) |
| 424 | + |
388 | 425 | const allCompletions = [
|
389 | 426 | ...reservedWordsCompletions,
|
390 | 427 | ...symbolCompletions,
|
391 | 428 | ...programCompletions,
|
392 | 429 | ...builtinsCompletions,
|
| 430 | + ...optionsCompletions, |
393 | 431 | ]
|
394 | 432 |
|
395 | 433 | if (word) {
|
@@ -531,3 +569,21 @@ const getMarkdownContent = (documentation: string): LSP.MarkupContent => ({
|
531 | 569 | // Passed as markdown for syntax highlighting
|
532 | 570 | kind: 'markdown' as const,
|
533 | 571 | })
|
| 572 | + |
| 573 | +function getCommandOptions(name: string, word: string): string[] { |
| 574 | + // TODO: The options could be cached. |
| 575 | + const options = Process.spawnSync(Path.join(__dirname, '../src/get-options.sh'), [ |
| 576 | + name, |
| 577 | + word, |
| 578 | + ]) |
| 579 | + |
| 580 | + if (options.status !== 0) { |
| 581 | + return [] |
| 582 | + } |
| 583 | + |
| 584 | + return options.stdout |
| 585 | + .toString() |
| 586 | + .split('\t') |
| 587 | + .map(l => l.trim()) |
| 588 | + .filter(l => l.length > 0) |
| 589 | +} |
0 commit comments