import std/[ collections/sequtils, strformat, sugar, ] import fp/[ option, resultM, ] import ./org_types import ./org_builder_api import ../parser/parser import ../utils/fp import fusion/matching {.experimental: "caseStmtMacros".} # -- Parsers let linkStartParser* = following(@[ ignore(str("[[")), anyUntil(choice(@[str("]["), str("]]")])), optional(ignore(str("]["))) ]) let linkEndParser* = following(@[ anyUntil(str("]]")), ignore(str("]]")), ]) let linkParser* = proc(parser: Parser): ParserResult {.closure.} = # Parse an an org link in the `parser` state. # Return two tokens for a link with description: [[url][description]] # Return one token for a link without description : [[url]] let linkUrl = linkStartParser(parser) .map(flattenTokens) let linkValue = linkUrl .map(emptyTokens) .flatMap(linkEndParser) .map(flattenTokens) case (linkUrl, linkValue): of (Some(@key), Some(@value)): ParserResult.ok( Parser( state: value.state, tokens: @[ key.tokens[0], value.tokens[0], ], ) ) else: linkValue # -- Tokenizers func linkStringifier*(linkUrl: string, linkDescription: Option[string]): string = case (linkUrl, linkDescription): of (@linkUrl, Some(@linkDescription)): return &"[[{linkUrl}][{linkDescription}]]" of (@linkUrl, None()): return &"[[{linkUrl}]]" let linkTokenizer* = func(parserTokens: seq[ParserToken]): seq[OrgInlineBuilderT] {.closure.} = [@linkUrl, @linkDescription] := parserTokens.map(toString) let linkDescriptionOption = linkDescription.some().notEmpty() return @[ OrgInlineBuilderT( kind: orgLink, content: linkStringifier(linkUrl, linkDescriptionOption), linkUrl: linkUrl, linkDescription: linkDescriptionOption, ) ] when isMainModule: block testParsers: proc testParser(str: string, parser: parserFnT): string = initParserResult(str).flatMap(parser).tokensToString() assert testParser("[[placeholder.com]]", linkParser) == "placeholder.com" assert testParser("[[placeholder.com][ - title]]", linkParser) == "placeholder.com - title" # .linkParser() # .foldTokens( # onError = xs => newSeq[OrgInlineBuilderT](), # onSuccess = linkTokenizer, # )