semo-plugin-shell
Version:
A semo plugin to provide a quick shell.
125 lines (124 loc) • 4.87 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.handler = exports.builder = exports.aliases = exports.desc = exports.command = exports.plugin = void 0;
const repl_1 = __importDefault(require("repl"));
const fs_extra_1 = __importDefault(require("fs-extra"));
const core_1 = require("@semo/core");
let r; // repl instance
exports.plugin = 'shell';
exports.command = 'shell';
exports.desc = 'Quick shell';
exports.aliases = 'sh';
function corepl(cli) {
// @ts-ignore
cli.eval = function coEval(cmd, context, filename, callback) {
const { argv } = context;
cmd = cmd.trim();
if (!cmd) {
return callback();
}
if (cmd.match(/^prefix[\s|=]+/) || cmd.trim() === 'prefix') {
let prefix = core_1.Utils.splitByChar(cmd, '=');
prefix.shift();
argv.prefix = prefix.join(' ').trim();
core_1.Utils.success(`Prefix has been changed to: ${argv.prefix || '[empty], so you can run any shell commands now.'}`);
if (argv.prefix) {
r._initialPrompt = `${argv.prefix}:${argv.prompt}`;
}
else {
r._initialPrompt = `${argv.prompt}`;
}
return callback();
}
const patternScriptShell = new RegExp(`^${argv.scriptName}\\s+(shell|sh)\\s+`);
if (`${argv.prefix} ${cmd}`.match(patternScriptShell)) {
core_1.Utils.warn('Recursive call shell not allowed!');
return callback();
}
const patternScript = new RegExp(`^${argv.scriptName}\\s+`);
if (`${argv.prefix} ${cmd}`.match(patternScript)) {
cmd = `${argv.prefix} ${cmd} --exec-mode`;
}
else {
cmd = `${argv.prefix} ${cmd}`;
}
try {
cmd && core_1.Utils.exec(cmd);
}
catch (e) {
if (argv.debug) {
core_1.Utils.error(e.stack, false);
}
else {
core_1.Utils.error(e.message, false);
}
}
return callback();
};
return cli;
}
function openRepl(context) {
return __awaiter(this, void 0, void 0, function* () {
const { argv } = context;
const prefix = argv.prefix || '';
r = repl_1.default.start({
prompt: prefix ? `${prefix}:${argv.prompt}` : argv.prompt,
completer: line => {
const completions = '.break .clear .exit .save .load .editor prefix'.split(' ');
const hits = completions.filter(c => c.startsWith(line));
// 如果没有匹配,则显示所有补全。
return [hits.length ? hits : completions, line];
},
});
const Home = process.env.HOME + `/.${argv.scriptName}`;
fs_extra_1.default.ensureDirSync(Home);
core_1.Utils.replHistory(r, `${Home}/.${argv.scriptName}_shell_history`);
// @ts-ignore
// context即为REPL中的上下文环境
r.context = Object.assign(r.context, context);
corepl(r);
});
}
const builder = function (yargs) {
yargs.option('prompt', {
describe: 'Prompt for input.',
});
yargs.option('prefix', {
describe: 'Make input command a little bit faster.',
});
yargs.option('debug', {
describe: 'Debug mode, show error stack',
});
};
exports.builder = builder;
const handler = function (argv) {
return __awaiter(this, void 0, void 0, function* () {
const scriptName = argv.scriptName || 'semo';
const { Utils } = argv.$semo;
argv.prefix = Utils.pluginConfig('prefix', scriptName);
argv.prompt = Utils.pluginConfig('prompt', '$ ');
argv.debug = Utils.pluginConfig('debug', false);
try {
let context = { argv };
yield openRepl(context);
return false;
}
catch (e) {
Utils.error(e.stack);
}
return true;
});
};
exports.handler = handler;