UNPKG

partpipe

Version:

Command line filter to apply unix filter to parts of input stream.

242 lines (232 loc) 9.36 kB
// Generated by CoffeeScript 2.4.1 var D, E, T, checkSeparator, child_process, co, escapeRegExp, partpipe; co = require('co'); child_process = require('child_process'); T = console.log; E = console.error; D = (opt, str) => { if ((opt != null ? opt.debugConsole : void 0) != null) { return opt.debugConsole("partpipe:" + str); } }; checkSeparator = (str) => { return !str.match(/[():;]/); }; //str.match /\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|/ escapeRegExp = function(str) { return str.replace(/[\-\[\]\/\{\}\*\+\.\\\^\$]/g, "\\$&"); }; partpipe = function(input, opt = {}) { var debugConsole, inputLines, marker, processIndent, runProcessWithInjection, tags, unknownTag; ({tags = {}, marker = null, debugConsole = null, processIndent = true, unknownTag = 'bypass'} = opt); if (marker && !checkSeparator(marker)) { throw `you can't use '():;' for separator: ${marker}`; } if (marker == null) { marker = '(?:@PARTPIPE@)'; } D(opt, "===starting partpipe process"); D(opt, `marker:${marker}`); D(opt, `processIndent:${processIndent}`); D(opt, `tags:${JSON.stringify(tags)}`); D(opt, `unknownTag:${unknownTag}`); inputLines = input.split("\n"); runProcessWithInjection = function(commandLine, buffer, opt) { return new Promise(function(rv, rj) { var isEcho, p; switch (commandLine) { case 'cat': D(opt, "command line is cat, bypassing content"); return rv(buffer != null ? buffer : ''); case '': D(opt, "command line is null, removing content"); return rv(); default: isEcho = commandLine.match(/^echo (.*)$/); if (isEcho) { D(opt, `command line is echo, overwriting content with ${isEcho[1]}`); return rv(isEcho[1]); } } p = child_process.exec(commandLine, function(err, stdout, stderr) { if (err) { return rj(stderr); } else { return rv(stdout); } }); if (buffer !== null) { p.stdin.write(buffer); } return p.stdin.end(); }); }; return co(function*() { var actualMarkerE, actualMarkerS, beginningLineno, buffer, commandLine, commandOutput, emarkerE, emarkerS, i, indent, inlineRegexp, len, line, lineno, m, mi, numEmarkerUsed, output, ref, ref1, ref2, ref3, regex, regex2, state; buffer = ''; commandLine = ''; state = 'bypass'; output = ''; lineno = 0; beginningLineno = 0; for (i = 0, len = inputLines.length; i < len; i++) { line = inputLines[i]; lineno++; D(opt, "block:input:" + line); m = line.match(new RegExp(`^([ ]*)${escapeRegExp(marker)}([|=!]?)([^;]*)$`)); if (m && m[3] && state === 'buffering') { throw `Missing block separator for line ${beginningLineno}`; } if (m != null ? m[3].match(new RegExp(escapeRegExp(marker))) : void 0) { //if inline, drop it m = null; } D(opt, "block:match:" + JSON.stringify(m)); if (m && m[3] && m[2] === '') { m[2] = '='; } if ((m != null ? m[2] : void 0) === '=' && !tags.hasOwnProperty(m != null ? m[3] : void 0)) { switch (unknownTag) { case 'remove': D(opt, `Removing uknown tag '${m[3]}'`); m[2] = 'x'; break; case 'show': D(opt, `Showing uknown tag '${m[3]}'`); m[2] = '|'; m[3] = 'cat'; break; case 'bypass': m = 0; state = 'bypass'; break; default: throw `Unknown tag '${m[3]}' found on line ${lineno}.check argument or input syntax or use option about unknown tag. `; } } switch (false) { case !(m && state === 'bypass' && ((ref = m[2]) === '|' || ref === '=' || ref === 'x' || ref === '!')): D(opt, `block:found beginnning marker at line ${lineno}`); state = 'buffering'; commandLine = m[3]; if (m[2] === '=') { commandLine = tags[m[3]]; } if (m[2] === 'x') { commandLine = ''; } indent = m[1]; buffer = m[2] !== '!' ? '' : null; beginningLineno = lineno; D(opt, `block:command line:${commandLine}`); D(opt, `block:current indent:[${indent}]`); break; case !(m && state === 'buffering'): D(opt, `block:found end marker at line ${lineno}`); state = 'bypass'; D(opt, `block:command:${(commandLine === '' ? 'REMOVE' : commandLine)}`); D(opt, `block:indent:${indent.length}`); if (buffer !== null) { D(opt, `\n###\n${buffer}###`); } commandOutput = (yield runProcessWithInjection(commandLine, buffer, opt)); if (!commandOutput) { continue; } commandOutput = commandOutput.replace(/\n$/m, ""); D(opt, `block:command output:\n###\n${commandOutput}\n###`); if (indent.length > 0 && processIndent) { commandOutput = commandOutput.replace(/^/mg, indent); } output += `${commandOutput}\n`; break; case !(!m && state === 'buffering'): if (indent.length > 0 && processIndent) { line = line.replace(new RegExp(`^${indent}`), ''); } if (buffer !== null) { buffer += `${line}\n`; } break; default: actualMarkerS = "@PARTPIPE@"; actualMarkerE = "@PARTPIPE@"; numEmarkerUsed = 0; while (true) { emarkerS = `@${Math.floor(Math.random() * 10000000)}@`; emarkerE = `@${Math.floor(Math.random() * 10000000)}@`; if (!(line.match(emarkerS || line.match(emarkerE)))) { break; } } while (true) { //regex="(#{escapeRegExp(marker)})([!|=]?)([^;]+?)(;.*?)?(#{escapeRegExp(marker)})" regex = `(${escapeRegExp(marker)})(.+?)(${escapeRegExp(marker)})`; inlineRegexp = new RegExp(regex); D(opt, "inline:input:" + line); mi = line.match(inlineRegexp); if (mi) { D(opt, "inline:macth:" + JSON.stringify(mi)); actualMarkerS = mi[1]; actualMarkerE = mi[3]; regex2 = "([!|=]?)([^;]+);?(.*?)$"; mi = mi[2].match(regex2); D(opt, "inline:2nd macth:" + JSON.stringify(mi)); if ((mi != null ? mi[1] : void 0) === '') { mi[1] = '='; } mi[3] = (ref1 = (ref2 = mi[3]) != null ? ref2.replace(/^/, '') : void 0) != null ? ref1 : ''; if ((mi != null ? mi[1] : void 0) === '=' && !tags.hasOwnProperty(mi[2])) { D(opt, `found inline marker at line ${lineno}`); D(opt, `match:${JSON.stringify(mi)}`); switch (unknownTag) { case 'remove': D(opt, `Removing uknown tag '${mi[2]}'`); line = line.replace(inlineRegexp, ""); break; case 'show': D(opt, `Showing uknown tag '${mi[2]}'`); line = line.replace(inlineRegexp, `${mi[3]}`); break; case 'bypass': D(opt, `replacing remaining of line with internal maker '${emarkerS}' '${emarkerE}'`); line = line.replace(inlineRegexp, `${emarkerS}${mi[1]}${mi[2]};${(ref3 = mi[3]) != null ? ref3 : ''}${emarkerE}`); numEmarkerUsed++; break; default: throw `Unknown tag '${mi[2]}' found on line ${lineno}.check argument or input syntax or use option about unknown tag. `; } continue; } commandLine = mi[2]; if (mi[1] === '=') { commandLine = tags[mi[2]]; } buffer = mi[1] !== '!' ? mi[3] : null; D(opt, `inline:command:${commandLine}`); D(opt, `inline:buffer:${buffer}`); commandOutput = (yield runProcessWithInjection(commandLine, buffer, opt)); commandOutput = commandOutput != null ? commandOutput : ''; D(opt, `inline:command output:${commandOutput != null ? typeof commandOutput.trim === "function" ? commandOutput.trim() : void 0 : void 0}`); line = line.replace(inlineRegexp, commandOutput.replace(/\n$/, '')); } else { break; } } if (numEmarkerUsed > 0) { D(opt, `restoring internal markers to actual marker, '${emarkerS}','${emarkerE}'->'${actualMarkerS}','${actualMarkerE}'`); D(opt, `before:${line}`); line = line.replace(new RegExp(escapeRegExp(emarkerS), 'g'), actualMarkerS); line = line.replace(new RegExp(escapeRegExp(emarkerE), 'g'), actualMarkerE); D(opt, `after:${line}`); } output += `${line}\n`; } } if (state === 'buffering') { throw `Missing block separator for line ${beginningLineno}`; } D(opt, "===partpipe process finished"); return output; }); }; module.exports = partpipe;