Skip to content

Commit

Permalink
fix: Add simple repl feature to suggestions. (#2403)
Browse files Browse the repository at this point in the history
  • Loading branch information
Jason3S committed Feb 5, 2022
1 parent 011f1b7 commit f9835b7
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 33 deletions.
72 changes: 42 additions & 30 deletions packages/cspell/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 7 additions & 2 deletions packages/cspell/src/application.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import * as async from '@cspell/cspell-pipe';
import type { CSpellReporter, RunResult } from '@cspell/cspell-types';
import type { CheckTextInfo, SuggestionsForWordResult, TraceResult } from 'cspell-lib';
import {
Expand All @@ -12,7 +13,7 @@ import {
import * as path from 'path';
import { LintRequest, runLint } from './lint';
import { BaseOptions, fixLegacy, LegacyOptions, LinterOptions, SuggestionOptions, TraceOptions } from './options';
import * as async from '@cspell/cspell-pipe';
import { simpleRepl } from './repl';
import { calcFinalConfigInfo, readConfig, readFile } from './util/fileHelper';
import { readStdin } from './util/stdin';
import * as util from './util/util';
Expand Down Expand Up @@ -56,7 +57,11 @@ export async function* suggestions(
): AsyncIterable<SuggestionsForWordResult> {
options = fixLegacy(options);
const configFile = await readConfig(options.config, undefined);
const iWords = options.useStdin ? async.toAsyncIterable(words, readStdin()) : words;
const iWords = options.repl
? async.toAsyncIterable(words, simpleRepl())
: options.useStdin
? async.toAsyncIterable(words, readStdin())
: words;
try {
const results = suggestionsForWords(iWords, options, configFile.config);
yield* results;
Expand Down
3 changes: 2 additions & 1 deletion packages/cspell/src/commandSuggestion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ export function commandSuggestion(prog: Command): Command {
'Force the number of suggested to be limited, by not including suggestions that have the same edit cost.'
)
.option('--stdin', 'Use stdin for input.')
.addOption(new CommanderOption('--repl', 'REPL interface for looking up suggestions.').hideHelp())
.option('-v, --verbose', 'Show detailed output.', count, 0)
.option(
'-d, --dictionary <dictionary name>',
Expand All @@ -76,7 +77,7 @@ export function commandSuggestion(prog: Command): Command {
options.useStdin = options.stdin;
options.dictionaries = mergeArrays(options.dictionaries, options.dictionary);

if (!words.length && !options.useStdin) {
if (!words.length && !options.useStdin && !options.repl) {
suggestionCommand.outputHelp();
throw new CheckFailed('outputHelp', 1);
}
Expand Down
5 changes: 5 additions & 0 deletions packages/cspell/src/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,11 @@ export interface SuggestionOptions extends BaseOptions {
* Use stdin for the input
*/
useStdin?: boolean;

/**
* Use REPL interface for making suggestions.
*/
repl?: boolean;
}

export interface LegacyOptions {
Expand Down
59 changes: 59 additions & 0 deletions packages/cspell/src/repl/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import * as readline from 'readline';

export function simpleRepl(): AsyncIterable<string> {
return new SimpleRepl();
}

export type CompleterResult = [string[], string];
export type Completer = (line: string) => CompleterResult;

export class SimpleRepl implements AsyncIterable<string> {
public beforeEach: undefined | (() => void);
public completer: undefined | Completer;
private _history: string[];
private rl: readline.ReadLine;

constructor(public prompt = '> ') {
this._history = [];
this.rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
prompt,
history: this._history,
historySize: 100,
completer: (line: string) => this._completer(line),
});

this.rl.on('history', (h) => ((this._history = h), undefined));
}

question(query: string): Promise<string> {
return new Promise<string>((resolve) => {
this.rl.question(query, resolve);
});
}

private _completer(line: string): CompleterResult {
// console.log('Complete: %s', line);
// console.log('History: %o', this._history);
if (this.completer) return this.completer(line);
const hist = this._history.filter((h) => h.startsWith(line));
return [hist, line];
}

get history() {
return this._history;
}

[Symbol.asyncIterator]() {
const next = (): Promise<IteratorResult<string, undefined>> => {
if (this.beforeEach) this.beforeEach();
// console.log('%o', this.rl);
return this.question(this.prompt)
.then((value: string) => ({ value }))
.catch(() => ({ done: true, value: undefined }));
};

return { next };
}
}
1 change: 1 addition & 0 deletions packages/cspell/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"skipLibCheck": true,
"exactOptionalPropertyTypes": false, // make this true
"outDir": "dist"
},
Expand Down

0 comments on commit f9835b7

Please sign in to comment.