import std/[ collections/sequtils, strformat, sugar, ] import fp/[ option, resultM, ] import fusion/matching import ./org_types import ./org_builder_api import ../parser/parser import ../utils/fp # import std/strformat # import std/sugar # import std/collections/sequtils # import results # import fp/[ # maybe, # option, # ] # import ./org_builder_api # import ../parser/parser_internals # import ../parser/parser_types {.experimental: "caseStmtMacros".} # -- Parsers let linkStartParser* = ignore(str("[[")) + anyUntil(choice(@[str("]["), str("]]")])) + optional(ignore(str("]["))) let linkEndParser* = 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 proc linkStringifier*(linkUrl: string, linkDescription: Option[string]): string = case (linkUrl, linkDescription): of (@linkUrl, Some(@linkDescription)): return &"[[{linkUrl}][{linkDescription}]]" of (@linkUrl, None()): return &"[[{linkUrl}]]" proc linkTokenizer*(parserTokens: seq[ParserToken]): seq[OrgInlineBuilderT] = [@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, # )