Skip to content

Commit

Permalink
feat: Add command names to phoenix tab-completion
Browse files Browse the repository at this point in the history
Gives CommandProviders a `complete(query, {ctx})` method where they can provide completed command names, and then make use of this in CommandCompleter.

Supported CommandProvider sources:
- Shell built-ins (was supported previously)
- PATH executables (when running under Node)
- Puter app names (when running in Puter)

Script filenames are not yet supported.
  • Loading branch information
AtkinsSJ committed Apr 24, 2024
1 parent dc5b010 commit cf0eee1
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 10 deletions.
17 changes: 7 additions & 10 deletions packages/phoenix/src/puter-shell/completers/CommandCompleter.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,12 @@ export class CommandCompleter {
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;
return (await ctx.externs.commandProvider.complete(query, { ctx }))
// Remove any duplicate results
.filter((item, pos, self) => self.indexOf(item) === pos)
// TODO: Sort completions?
// Remove the `query` part of each result, as that's what is expected
// TODO: Supply whole results instead?
.map(it => it.slice(query.length));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,9 @@ export class BuiltinCommandProvider {
}
return undefined;
}

async complete (query) {
return Object.keys(builtins)
.filter(commandName => commandName.startsWith(query));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,15 @@ export class CompositeCommandProvider {
if ( results.length === 0 ) return undefined;
return results;
}

async complete (...a) {
const query = a[0];
if (query === '') return [];

const results = [];
for (const provider of this.providers) {
results.push(...await provider.complete(...a));
}
return results;
}
}
22 changes: 22 additions & 0 deletions packages/phoenix/src/puter-shell/providers/PathCommandProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,4 +200,26 @@ export class PathCommandProvider {
async lookupAll(id, { ctx }) {
return findCommandsInPath(id, ctx, false);
}

async complete(query, { ctx }) {
if (query === '') return [];

const PATH = ctx.env['PATH'];
if (!PATH)
return [];
const path_directories = PATH.split(path_.delimiter);

const results = [];

for (const dir of path_directories) {
const dir_entries = await ctx.platform.filesystem.readdir(dir);
for (const dir_entry of dir_entries) {
if (dir_entry.name.startsWith(query)) {
results.push(dir_entry.name);
}
}
}

return results;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -114,4 +114,34 @@ export class PuterAppCommandProvider {
}
return undefined;
}

async complete (query, { ctx }) {
if (query === '') return [];

const results = [];

for (const app_name of BUILT_IN_APPS) {
if (app_name.startsWith(query)) {
results.push(app_name);
}
}

const request = await fetch(`${puter.APIOrigin}/drivers/call`, {
"headers": {
"Content-Type": "application/json",
"Authorization": `Bearer ${puter.authToken}`,
},
"body": JSON.stringify({ interface: 'puter-apps', method: 'select', args: { predicate: [ 'name-like', query + '%' ] } }),
"method": "POST",
});

const json = await request.json();
if (json.success) {
for (const app of json.result) {
results.push(app.name);
}
}

return results;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,9 @@ export class ScriptCommandProvider {
}
return undefined;
}

async complete (query, { ctx }) {
// TODO: Implement this
return [];
}
}

0 comments on commit cf0eee1

Please sign in to comment.