UNPKG

semo-plugin-shell

Version:

A semo plugin to provide a quick shell.

118 lines 3.84 kB
import { error, splitByChar, success, warn } from '@semo/core'; import { ensureDirSync } from 'fs-extra'; import { closeSync, createWriteStream, openSync, readFileSync, statSync, } from 'node:fs'; import repl from 'node:repl'; import shell from 'shelljs'; /** * Keep repl history * */ export const replHistory = function (repl, file) { try { statSync(file); repl.history = readFileSync(file, 'utf-8').split('\n').reverse(); repl.history.shift(); repl.historyIndex = -1; // will be incremented before pop } catch { } const fd = openSync(file, 'a'); const wstream = createWriteStream(file, { fd, }); wstream.on('error', function (err) { throw err; }); repl.addListener('line', function (code) { if (code && code !== '.history') { wstream.write(code + '\n'); } else { repl.historyIndex++; repl.history.pop(); } }); process.on('exit', function () { closeSync(fd); }); repl.defineCommand('history', { help: 'Show the history', action: function () { const out = []; repl.history.forEach(function (v) { out.push(v); }); repl.output.write(out.reverse().join('\n') + '\n'); repl.displayPrompt(); }, }); }; export 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') { const prefix = splitByChar(cmd, '='); prefix.shift(); argv.prefix = prefix.join(' ').trim(); success(`Prefix has been changed to: ${argv.prefix || '[empty], so you can run any shell commands now.'}`); // if (argv.prefix) { // cli._initialPrompt = `${argv.prefix}:${argv.prompt}` // } else { // cli._initialPrompt = `${argv.prompt}` // } return callback(); } const patternScriptShell = new RegExp(`^${argv.scriptName}\\s+(shell|sh)\\s+`); if (`${argv.prefix} ${cmd}`.match(patternScriptShell)) { 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 { if (cmd) { shell.exec(cmd); } } catch (e) { if (argv.debug) { error(e.stack); } else { error(e.message); } } return callback(); }; return cli; } export async function openRepl(context) { const { argv } = context; const prefix = argv.prefix || ''; const r = repl.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}`; ensureDirSync(Home); replHistory(r, `${Home}/.${argv.scriptName}_shell_history`); Object.keys(context).forEach((key) => { r.context[key] = context[key]; }); corepl(r); } //# sourceMappingURL=utils.js.map