diff --git a/cli.mjs b/cli.mjs index fd6a768..3c20cbe 100644 --- a/cli.mjs +++ b/cli.mjs @@ -71,8 +71,11 @@ await new Promise((resolve, reject) => { // Spawn child process to execute script let child = spawn( - path, - scriptArgs, { + '/usr/bin/env', [ + '-u', 'PKG_EXECPATH', + path, + ...scriptArgs + ], { stdio: 'inherit', argv0: fileName } diff --git a/src/character_stream.mjs b/src/character_stream.mjs index 77d94db..74de964 100644 --- a/src/character_stream.mjs +++ b/src/character_stream.mjs @@ -37,9 +37,9 @@ export class CharacterStream { } // Peek first character after any characters that match predicate - peekAfter(predicate) { + peekAfter(predicate, length = 1) { const skip = this.peekWhile(predicate); - return this.peek(skip.length + 1).substring(skip.length); + return this.peek(skip.length + length).substring(skip.length); } isNext(str) { diff --git a/src/template_engine.mjs b/src/template_engine.mjs index ef55b95..23040d1 100644 --- a/src/template_engine.mjs +++ b/src/template_engine.mjs @@ -45,6 +45,9 @@ export class TemplateEngine { case 'comment': buffer += this._renderComment(token.value); break; + case 'source': + buffer += this._renderSource(token.value); + break; default: throw new Error(`Unrecognized token: ${token.type}`); } @@ -61,6 +64,10 @@ export class TemplateEngine { return `# ${value}\n`; } + _renderSource(value) { + return `source <(n0m -c "${value.trim()}")\n`; + } + _renderStatement(value) { return `${value}\n`; } diff --git a/src/token_stream.mjs b/src/token_stream.mjs index 6a150e1..198fd14 100644 --- a/src/token_stream.mjs +++ b/src/token_stream.mjs @@ -15,6 +15,7 @@ export class TokenStream { static CLOSE_INLINE_STATEMENT_UNESCAPED = '%>'; static STATEMENT = '$'; static COMMENT = '#'; + static SOURCE = '.INCLUDE'; constructor() { this.reset(); @@ -73,7 +74,8 @@ export class TokenStream { TokenStream.OPEN_INLINE_STATEMENT, TokenStream.OPEN_INLINE_STATEMENT_UNESCAPED, TokenStream.STATEMENT, - TokenStream.COMMENT + TokenStream.COMMENT, + TokenStream.SOURCE ])) { // Skip escape this._cs.next(TokenStream.ESCAPE.length); @@ -89,16 +91,12 @@ export class TokenStream { return flushRaw() || this._readInlineStatement(); } else if (this._cs.isNext(TokenStream.OPEN_INLINE_STATEMENT_UNESCAPED)) { return flushRaw() || this._readInlineStatementUnescaped(); - } else if ( - this._cs.column === 0 && - this._cs.peekAfter(this._isSpace) === TokenStream.STATEMENT - ) { + } else if (this._matchFullLine(TokenStream.STATEMENT)) { return flushRaw() || this._readStatement(); - } else if ( - this._cs.column === 0 && - this._cs.peekAfter(this._isSpace) === TokenStream.COMMENT - ) { + } else if (this._matchFullLine(TokenStream.COMMENT)) { return flushRaw() || this._readComment(); + } else if (this._matchFullLine(TokenStream.SOURCE)) { + return flushRaw() || this._readSource(); } else { raw += this._cs.next(); } @@ -248,6 +246,13 @@ export class TokenStream { ); } + _readSource() { + return this._readFullLineGeneric( + 'source', + TokenStream.SOURCE + ); + } + // Utility methods _isSpace(c) { return /[^\S\r\n]/.test(c); @@ -260,4 +265,11 @@ export class TokenStream { this._cs.isNext(TokenStream.ESCAPE + tag) ); } + + _matchFullLine(tag) { + return ( + this._cs.column === 0 && + this._cs.peekAfter(this._isSpace, tag.length) === tag + ); + } }