Skip to content

Commit b61bce5

Browse files
committed
Further improve auto completions
1 parent 528acce commit b61bce5

File tree

4 files changed

+43
-34
lines changed

4 files changed

+43
-34
lines changed
+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Command } from "./Command";
22

33
export abstract class AutocompletingCommand extends Command {
4-
abstract autocomplete(arg: string): string[];
4+
abstract suggestAutocompletions(arg: string): string[];
55
}

assets/ts/terminal/Terminal.ts

+40-25
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ export class Terminal {
4848
* Handle enter key press to clear the prompt input.
4949
*/
5050
document.addEventListener("keydown", (event: KeyboardEvent) => {
51-
const input = this.inputElement.textContent?.replace(/\xA0/g, " ").trim() ?? "";
51+
const input = this.getInput();
5252

5353
switch (event.key) {
5454
case "ArrowLeft":
@@ -91,8 +91,8 @@ export class Terminal {
9191
});
9292
}
9393

94-
private onEnter(input: string) {
95-
const { command, args } = getCommandFromInput(input);
94+
private onEnter(input: string): void {
95+
const { command, args } = getCommandFromInput(input.trim());
9696
this.setInput();
9797
this.clearOutput();
9898

@@ -105,31 +105,42 @@ export class Terminal {
105105
return;
106106
}
107107

108-
private onTab(input: string) {
108+
private onTab(input: string): void {
109+
this.clearOutput();
110+
109111
if (input.length === 0) {
112+
this.print(...Terminal.commands.map((command: Command) => command.name));
110113
return;
111114
}
112115

113-
this.clearOutput();
114-
115116
const { command, args } = getCommandFromInput(input);
116117

117-
// Autocomplete command arguments
118-
if (command && command instanceof AutocompletingCommand && args.length > 0) {
119-
const completions = command.autocomplete(args[args.length - 1]);
120-
if (completions.length === 1) {
121-
args[args.length - 1] = completions[0];
122-
this.setInput(`${command.name} ${args.join(" ")}`);
123-
}
118+
if (command && command instanceof AutocompletingCommand) {
119+
// If the input is exactly the command name (with no space after), don't autocomplete arguments.
120+
if (input === command.name) return;
124121

125-
if (completions.length > 1) {
126-
this.print(...completions);
127-
this.setInput(`${command.name} ${longestCommonPrefix(completions)}`);
128-
}
122+
this.autocompleteArguments(command, args);
129123
return;
130124
}
131125

132-
// Autocomplete command names
126+
this.autocompleteCommands(input);
127+
}
128+
129+
private autocompleteArguments(command: AutocompletingCommand, args: string[] = []) {
130+
const argument = args[args.length - 1] ?? "";
131+
const suggestions = command.suggestAutocompletions(argument);
132+
133+
if (suggestions.length === 1) {
134+
this.setInput(`${command.name} ${suggestions[0]}`);
135+
}
136+
137+
if (suggestions.length > 1) {
138+
this.print(...suggestions);
139+
this.setInput(`${command.name} ${longestCommonPrefix(suggestions)}`);
140+
}
141+
}
142+
143+
private autocompleteCommands(input: string): void {
133144
const matchingCommandNames = Terminal.commands
134145
.filter((command: Command) => command.name.startsWith(input))
135146
.map((command: Command) => command.name);
@@ -148,10 +159,9 @@ export class Terminal {
148159
this.print(...matchingCommandNames);
149160
this.setInput(longestCommonPrefix(matchingCommandNames));
150161
}
151-
return;
152162
}
153163

154-
private moveCaretToEnd() {
164+
private moveCaretToEnd(): void {
155165
const range = document.createRange();
156166
const selection = window.getSelection();
157167

@@ -162,21 +172,26 @@ export class Terminal {
162172
selection?.addRange(range);
163173
}
164174

165-
public print(...lines: string[]) {
175+
public print(...lines: string[]): void {
166176
lines.forEach((line: string) => {
167177
const outputElement = document.createElement("pre");
168178
outputElement.textContent = line;
169179
this.terminalOutputElement.appendChild(outputElement);
170180
});
171181
}
172182

173-
public setInput(newInput: string = "") {
174-
this.inputElement.textContent = newInput;
175-
this.promptBlurElement.textContent = newInput;
183+
private getInput() {
184+
return this.inputElement.textContent?.replace(/\xA0/g, " ") ?? "";
185+
}
186+
187+
public setInput(input: string = ""): void {
188+
const formattedInput = input.replace(/ /g, "\xA0");
189+
this.inputElement.textContent = formattedInput;
190+
this.promptBlurElement.textContent = formattedInput;
176191
this.moveCaretToEnd();
177192
}
178193

179-
public clearOutput() {
194+
public clearOutput(): void {
180195
while (this.terminalOutputElement?.firstChild) {
181196
this.terminalOutputElement.removeChild(this.terminalOutputElement.firstChild);
182197
}

assets/ts/terminal/commands/ChangeDirectory.ts

+1-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { Command } from "../Command";
21
import { HugoPage } from "../../types/hugo";
32
import { Terminal } from "../Terminal";
43
import { getAllPages, getPagesInPath, slugPath } from "../helpers";
@@ -66,11 +65,6 @@ export class ChangeDirectory extends AutocompletingCommand {
6665
// Change to a relative path
6766
if (
6867
this.pagesInPath.find((p: HugoPage) => {
69-
console.log(
70-
inputPath,
71-
p.Path.replace(window.location.pathname, "").toLowerCase(),
72-
slugPath(p).replace(window.location.pathname, "").toLowerCase(),
73-
);
7468
return (
7569
p.Path.replace(window.location.pathname, "").toLowerCase() === inputPath ||
7670
slugPath(p).replace(window.location.pathname, "").toLowerCase() === inputPath
@@ -82,7 +76,7 @@ export class ChangeDirectory extends AutocompletingCommand {
8276
}
8377
}
8478

85-
public autocomplete(arg: string): string[] {
79+
public suggestAutocompletions(arg: string): string[] {
8680
const suggestions = this.pagesInPath
8781
.map((page: HugoPage) => slugPath(page))
8882
.map((path: string) => path.replace(window.location.pathname, ""));

assets/ts/terminal/commands/Help.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export class Help extends AutocompletingCommand {
3131
}
3232
}
3333

34-
public autocomplete(arg: string): string[] {
34+
public suggestAutocompletions(arg: string): string[] {
3535
return Terminal.commands
3636
.map((command: Command) => command.name)
3737
.filter((name: string) => name.startsWith(arg));

0 commit comments

Comments
 (0)