import {Command, ParseContext, StrTerm, unwrapString, wrapString} from "./command.js"; import {LexInput} from "../lexer.js"; import {StrVM} from "../vm.js"; import {Awaitable} from "../../util/types.js"; export type EncloseData = { left?: StrTerm, right?: StrTerm, } export class Enclose extends Command { attemptParse(context: ParseContext): EncloseData { return { left: context.popOptionalTerm(), right: context.popOptionalTerm(), } } getDisplayName(): string { return 'enclose' } isParseCandidate(token: LexInput): boolean { return this.isKeyword(token, 'enclose') } execute(vm: StrVM, data: EncloseData): Awaitable { return vm.tapInPlace(ctx => { const [left, right] = this.determineSurroundingStrings( data.left ? ctx.resolveString(data.left) : undefined, data.right ? ctx.resolveString(data.right) : undefined, ) return ctx.replaceSubjectAsString(sub => `${left}${sub}${right}`) }) } private determineSurroundingStrings(left?: string, right?: string): [string, string] { if ( !left ) { left = '(' } if ( !right ) { right = ({ '(': ')', '[': ']', '{': '}', '<': '>', })[left] ?? left } return [left, right] } }