@struktoai/mirage-core
Version:
A Unified Virtual Filesystem For AI Agents
58 lines • 2.39 kB
JavaScript
// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
const ESCAPABLE = new Set(['$', '`', '\\']);
/**
* Split a backtick region into its commands and the text between them,
* each with its span in the region.
*
* The node's subtree is not what runs: bash removes the backslashes of a
* backtick body before it parses it, so the body is lexed again from the
* node's own text. The evaluator runs each command as a line of its own
* and the judging pass reads it the same way, so this is the one lexer
* both share, and the spans are what place each command on the line.
*
* Inside a command, POSIX keeps the backslash literal except before
* `$`, `` ` `` and `\\`, where it escapes. Consuming those pairs whole
* is what makes the parity right: `\\\\` is one escaped backslash, so a
* backtick straight after it still closes the region rather than
* reading as an escaped backtick.
*/
export function splitBacktickRegion(raw) {
const segments = [];
let buf = '';
let inCommand = false;
let start = 0;
let i = 0;
while (i < raw.length) {
const next = raw[i + 1];
if (raw[i] === '\\' && inCommand && next !== undefined && ESCAPABLE.has(next)) {
buf += next;
i += 2;
continue;
}
if (raw[i] === '`') {
segments.push({ text: buf, command: inCommand, start, end: i });
buf = '';
inCommand = !inCommand;
i += 1;
start = i;
continue;
}
buf += raw.charAt(i);
i += 1;
}
segments.push({ text: buf, command: inCommand, start, end: raw.length });
return segments.filter((s) => s.text !== '' || s.command);
}
//# sourceMappingURL=backticks.js.map