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 #68 from AtkinsSJ/which-builtin
Browse files Browse the repository at this point in the history
Implement a `which` built-in
  • Loading branch information
KernelDeimos authored Mar 29, 2024
2 parents 73db231 + e139461 commit ba67149
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 29 deletions.
1 change: 1 addition & 0 deletions src/ansi-shell/pipeline/Pipeline.js
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,7 @@ export class Pipeline {
let cmdOut = pipe.in;
cmdOut = new ByteWriter({ delegate: cmdOut });
cmdCtx.externs.out = cmdOut;
cmdCtx.externs.commandProvider = ctx.externs.commandProvider;
nextIn = pipe.out;

// TODO: need to consider redirect from out to err
Expand Down
2 changes: 2 additions & 0 deletions src/puter-shell/coreutils/__exports__.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ import module_true from './true.js'
import module_txt2img from './txt2img.js'
import module_usages from './usages.js'
import module_wc from './wc.js'
import module_which from './which.js'

export default {
"ai": module_ai,
Expand Down Expand Up @@ -95,4 +96,5 @@ export default {
"txt2img": module_txt2img,
"usages": module_usages,
"wc": module_wc,
"which": module_which,
};
75 changes: 75 additions & 0 deletions src/puter-shell/coreutils/which.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* 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 { Exit } from './coreutil_lib/exit.js';

export default {
name: 'which',
usage: 'which COMMAND...',
description: 'Look up each COMMAND, and return the path name of its executable.\n\n' +
'Returns 1 if any COMMAND is not found, otherwise returns 0.',
args: {
$: 'simple-parser',
allowPositionals: true,
options: {
'all': {
description: 'Return all matching path names of each COMMAND, not just the first',
type: 'boolean',
short: 'a',
},
},
},
execute: async ctx => {
const { out, err, commandProvider } = ctx.externs;
const { positionals, values } = ctx.locals;

let anyCommandsNotFound = false;

const printPath = async ( commandName, command ) => {
if (command.path) {
await out.write(`${command.path}\n`);
} else {
await out.write(`${commandName}: shell built-in command\n`);
}
};

for ( const commandName of positionals ) {
const result = values.all
? await commandProvider.lookupAll(commandName, { ctx })
: await commandProvider.lookup(commandName, { ctx });

if ( ! result ) {
anyCommandsNotFound = true;
await err.write(`${commandName} not found\n`);
continue;
}

if ( values.all ) {
for ( const command of result ) {
await printPath(commandName, command);
}
} else {
await printPath(commandName, result);
}
}

if ( anyCommandsNotFound ) {
throw new Exit(1);
}
}
};
9 changes: 9 additions & 0 deletions src/puter-shell/providers/BuiltinCommandProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,13 @@ export class BuiltinCommandProvider {
async lookup (id) {
return builtins[id];
}

// Only a single builtin can match a given name
async lookupAll (...a) {
const result = await this.lookup(...a);
if ( result ) {
return [ result ];
}
return undefined;
}
}
13 changes: 13 additions & 0 deletions src/puter-shell/providers/CompositeCommandProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,17 @@ export class CompositeCommandProvider {
}
}
}

async lookupAll (...a) {
const results = [];
for (const provider of this.providers) {
const commands = await provider.lookupAll(...a);
if ( commands ) {
results.push(...commands);
}
}

if ( results.length === 0 ) return undefined;
return results;
}
}
18 changes: 0 additions & 18 deletions src/puter-shell/providers/HostedCommandProvider.js

This file was deleted.

38 changes: 27 additions & 11 deletions src/puter-shell/providers/ScriptCommandProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,30 +22,46 @@ import { resolveRelativePath } from '../../util/path.js';

export class ScriptCommandProvider {
async lookup (id, { ctx }) {
const { filesystem } = ctx.platform;

const is_path = id.match(/^[.\/]/);
if ( ! is_path ) return undefined;

const absPath = resolveRelativePath(ctx.vars, id);

const { filesystem } = ctx.platform;
try {
await filesystem.stat(absPath);
// TODO: More rigorous check that it's an executable text file
} catch (e) {
return undefined;
}

const script_blob = await filesystem.read(absPath);
const script_text = await script_blob.text();
return {
path: id,
async execute (ctx) {
const script_blob = await filesystem.read(absPath);
const script_text = await script_blob.text();

console.log('result though?', script_text);
console.log('result though?', script_text);

// note: it's still called `parseLineForProcessing` but
// it has since been extended to parse the entire file
const ast = ctx.externs.parser.parseScript(script_text);
const statements = ast[0].statements;
// note: it's still called `parseLineForProcessing` but
// it has since been extended to parse the entire file
const ast = ctx.externs.parser.parseScript(script_text);
const statements = ast[0].statements;

return {
async execute (ctx) {
for (const stmt of statements) {
const pipeline = await Pipeline.createFromAST(ctx, stmt);
await pipeline.execute(ctx);
}
}
};
}

// Only a single script can match a given path
async lookupAll (...a) {
const result = await this.lookup(...a);
if ( result ) {
return [ result ];
}
return undefined;
}
}

0 comments on commit ba67149

Please sign in to comment.