Skip to content
This repository has been archived by the owner on Apr 13, 2024. It is now read-only.

Commit

Permalink
Merge pull request #64 from AtkinsSJ/command-name-completion
Browse files Browse the repository at this point in the history
Add completers for command names and options
  • Loading branch information
KernelDeimos authored Mar 19, 2024
2 parents 258226a + 6756d98 commit 027e9ca
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 6 deletions.
17 changes: 13 additions & 4 deletions src/ansi-shell/readline/readline.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { Context } from "../../context/context.js";
import { CommandCompleter } from "../../puter-shell/completers/command_completer.js";
import { FileCompleter } from "../../puter-shell/completers/file_completer.js";
import { OptionCompleter } from '../../puter-shell/completers/option_completer.js';
import { Uint8List } from "../../util/bytes.js";
import { Log } from "../../util/log.js";
import { StatefulProcessorBuilder } from "../../util/statemachine.js";
import { ANSIContext } from "../ANSIContext.js";
import { readline_comprehend } from "./rl_comprehend.js";
Expand Down Expand Up @@ -109,14 +110,22 @@ const ReadlineProcessorBuilder = builder => builder
completer = new FileCompleter();
}

// TODO: try to get a completer from the command
if ( inputState.$ === 'command' ) {
completer = new FileCompleter();
if ( inputState.tokens.length === 1 ) {
// Match first token against command names
completer = new CommandCompleter();
} else if ( inputState.input.startsWith('--') ) {
// Match `--*` against option names, if they exist
completer = new OptionCompleter();
} else {
// Match everything else against file names
completer = new FileCompleter();
}
}

if ( completer === null ) return;

const completions = await completer.getCompetions(
const completions = await completer.getCompletions(
externs.commandCtx,
inputState,
);
Expand Down
39 changes: 39 additions & 0 deletions src/puter-shell/completers/command_completer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright (C) 2024 Puter Technologies Inc.
*
* This file is part of Phoenix Shell.
*
* Phoenix Shell is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
export class CommandCompleter {
async getCompletions (ctx, inputState) {
const { builtins } = ctx.registries;
const query = inputState.input;

if ( query === '' ) {
return [];
}

const completions = [];

// TODO: Match executable names as well as builtins
for ( const commandName of Object.keys(builtins) ) {
if ( commandName.startsWith(query) ) {
completions.push(commandName.slice(query.length));
}
}

return completions;
}
}
4 changes: 2 additions & 2 deletions src/puter-shell/completers/file_completer.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import path_ from "path-browserify";
import { resolveRelativePath } from '../../util/path.js';

export class FileCompleter {
async getCompetions (ctx, inputState) {
async getCompletions (ctx, inputState) {
const { filesystem } = ctx.platform;

if ( inputState.input === '' ) {
Expand All @@ -34,7 +34,7 @@ export class FileCompleter {
const completions = [];

const result = await filesystem.readdir(dir);
if ( result == undefined ) {
if ( result === undefined ) {
return [];
}

Expand Down
57 changes: 57 additions & 0 deletions src/puter-shell/completers/option_completer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright (C) 2024 Puter Technologies Inc.
*
* This file is part of Phoenix Shell.
*
* Phoenix Shell is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { DEFAULT_OPTIONS } from '../coreutils/coreutil_lib/help.js';

export class OptionCompleter {
async getCompletions (ctx, inputState) {
const { builtins } = ctx.registries;
const query = inputState.input;

if ( query === '' ) {
return [];
}

// TODO: Query the command through the providers system.
// Or, we could include the command in the context that's given to completers?
const command = builtins[inputState.tokens[0]];
if ( ! command ) {
return [];
}

const completions = [];

const processOptions = (options) => {
for ( const optionName of Object.keys(options) ) {
const prefixedOptionName = `--${optionName}`;
if ( prefixedOptionName.startsWith(query) ) {
completions.push(prefixedOptionName.slice(query.length));
}
}
};

// TODO: Only check these for builtins!
processOptions(DEFAULT_OPTIONS);

if ( command.args?.options ) {
processOptions(command.args.options);
}

return completions;
}
}

0 comments on commit 027e9ca

Please sign in to comment.