import {Command, ParseContext, StrTerm} from "./command.js"; import {LexInput} from "../lexer.js"; import {StrVM} from "../vm.js"; import {Awaitable} from "../../util/types.js"; export const QUOTEMARKS = ['"', '\'', '`'] export const stripQuotemarkLayer = (s: string, marks?: string[]): string => { if ( !marks ) { marks = QUOTEMARKS } for ( const mark of marks ) { if ( !s.startsWith(mark) || !s.endsWith(mark) ) { continue } s = s.substring(mark.length, s.length - mark.length) break } return s } export class Quote extends Command<{ with?: StrTerm }> { attemptParse(context: ParseContext): { with?: StrTerm } { return { with: context.popOptionalTerm(), } } getDisplayName(): string { return 'quote' } isParseCandidate(token: LexInput): boolean { return this.isKeyword(token, 'quote') } execute(vm: StrVM, data: { with?: StrTerm }): Awaitable { return vm.inPlace(ctx => ctx.replaceSubject(sub => sub.modify(s => { let quote = '\'' if ( data.with ) { quote = ctx.resolveString(data.with) } s = stripQuotemarkLayer(s) return `${quote}${s}${quote}` }))) } }