Files
org-parser/src_v2/org/org_builder_link.nim
Florian Schroedl 0cf8f6791d Cleanup
2022-08-28 16:03:03 +02:00

90 lines
2.3 KiB
Nim

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