Files
org-parser/src_v2/org/org_builder_link.nim
Florian Schroedl e876a487f5 Restore link parser
2022-08-28 14:54:12 +02:00

94 lines
2.4 KiB
Nim

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,
# )