219 lines
5.1 KiB
Nim
219 lines
5.1 KiB
Nim
import std/[
|
|
collections/sequtils,
|
|
strformat,
|
|
strutils,
|
|
sugar,
|
|
]
|
|
import fp/[
|
|
option,
|
|
resultM,
|
|
]
|
|
import fusion/matching
|
|
{.experimental: "caseStmtMacros".}
|
|
import ./org_types
|
|
import ./org_builder_api
|
|
import ../parser/parser
|
|
import ../utils/fp
|
|
|
|
# -- Parsers
|
|
|
|
let headingStarsParser* = following(@[
|
|
ignore(optional(newline)),
|
|
manyUntil(ch('*'), ch(' ')),
|
|
ignore(space)
|
|
])
|
|
|
|
proc createTodoKeywordParser(xs: seq[string]): parserFnT =
|
|
choice(xs.map((x: string) => str(x) + ignore(space)))
|
|
|
|
let todoKeywords = @["TODO"]
|
|
let doneKeywords = @["DONE"]
|
|
|
|
let parseTodoKeyword = todoKeywords.createTodoKeywordParser()
|
|
let parseDoneKeyword = doneKeywords.createTodoKeywordParser()
|
|
|
|
# let parseContentText = @[
|
|
# anyUntil(choice(@[endOfStream, str("\n")])),
|
|
# ]
|
|
|
|
# let parseHeadlineNewline = @[
|
|
# choice(@[
|
|
# ch(NewLines),
|
|
# endOfStream,
|
|
# ])
|
|
# ]
|
|
|
|
# let parseHeadingText = @[
|
|
# anyUntil(newline),
|
|
# ]
|
|
|
|
# -- Tokenizers
|
|
|
|
let buildStars = func(tokens: seq[ParserToken], org: OrgBlock): OrgBlock {.closure.}=
|
|
org.level = tokens.len
|
|
org
|
|
|
|
# let buildTodo = func(tokens: seq[ParserToken], org: OrgBlock): OrgBlock {.closure.}=
|
|
# org.todo = tokens.tokensToString().some()
|
|
# org
|
|
|
|
# let buildHeadlineContent = func(tokens: seq[ParserToken], org: OrgBlock): OrgBlock {.closure.}=
|
|
# let headlineString = tokens.tokensToString()
|
|
|
|
# let tokens = tryBuildInline(headlineString)
|
|
# .fold(
|
|
# x => newSeq[OrgInlineBuilderT](),
|
|
# (x: OrgInlineBuilder) => x.tree,
|
|
# )
|
|
|
|
# org.headlineContent = tokens
|
|
# org
|
|
|
|
# let buildHeadlineChildren = func(tokens: seq[ParserToken], org: OrgBlock): OrgBlock {.closure.}=
|
|
# # let headlineString = tokens.tokensToString()
|
|
|
|
# org
|
|
|
|
# let buildHeadlineNewline = func(tokens: seq[ParserToken], org: OrgBlock): OrgBlock {.closure.}=
|
|
# org
|
|
|
|
proc tryBuildHeading(builder: OrgBuilderResult): OrgBuilderResult =
|
|
# echo builder
|
|
builder
|
|
.applyParsersSeqToSingle(
|
|
OrgBlock(kind: orgHeading),
|
|
@[
|
|
(parseHeadingStars, buildStars, false),
|
|
|
|
(@[optional(parseTodoKeyword)], buildTodo, true),
|
|
(@[optional(parseDoneKeyword)], buildTodo, true),
|
|
|
|
(parseHeadingText, buildHeadlineContent, false),
|
|
|
|
# (parseContentText, buildHeadlineChildren, true),
|
|
|
|
(parseHeadlineNewline, buildHeadlineNewline, false),
|
|
]
|
|
)
|
|
|
|
# let headingParser = choice(@[
|
|
# newline + ch('*'),
|
|
# endOfStream,
|
|
# ])
|
|
|
|
|
|
# let contentEndParser = newline
|
|
|
|
# let buildNewline = func(tokens: seq[ParserToken], org: OrgBlock): OrgBlock {.closure.} =
|
|
# OrgBlock(
|
|
# kind: orgNewline
|
|
# )
|
|
|
|
# proc concatOrgBlock(xs: seq[OrgBlock], ys: seq[OrgBlock]): seq[OrgBlock] = xs & ys
|
|
|
|
# let parseBlockText = @[
|
|
# anyUntil(choice(@[endOfStream, str("\n")])),
|
|
# ]
|
|
|
|
# let contentParsersSeq: seq[tuple[
|
|
# parsers: seq[Parser -> ParserResult],
|
|
# tokenFoldFn: (seq[ParserToken], OrgBlock) -> OrgBlock,
|
|
# ignoreEmpty: bool,
|
|
# # concatFn: (seq[OrgBlock], seq[OrgBlock]) -> seq[OrgBlock],
|
|
# ]] = @[
|
|
# (parseBlockText, buildNewline, true),
|
|
# (contentEndParser, buildNewline, true),
|
|
# ]
|
|
|
|
# proc parseHeadlineChildren(builder: OrgBuilder): OrgBuilderResult =
|
|
# var headingBlock = builder.tree[0]
|
|
|
|
# # echo "Builder " & $builder
|
|
|
|
# # var builderAcc: OrgBuilderResult = OrgBuilderResult.ok(builder)
|
|
# var builderAcc: OrgBuilderResult = OrgBuilderResult.ok(OrgBuilder(
|
|
# (
|
|
# parser: builder.parser,
|
|
# tree: @[],
|
|
# )
|
|
# ))
|
|
|
|
# echo "builderAcc before parse content ", builderAcc
|
|
# # echo builderAcc.tryParser(headingParser)
|
|
# while builderAcc.isOk() and builderAcc.tryParser(headingParser).isErr():
|
|
# builderAcc = builderAcc
|
|
# .applyParsersSeqToSeq(
|
|
# contentParsersSeq
|
|
# )
|
|
# echo "builderAcc after parse in while loop ", builderAcc
|
|
# # echo builderAcc
|
|
|
|
|
|
# let content = builderAcc.fold(
|
|
# (err) => 0, # newSeq[OrgBlock](),
|
|
# (builder: OrgBuilder) => len builder.tree,
|
|
# )
|
|
|
|
# # echo "builderAcc" & $builderAcc
|
|
# echo "content" & $content
|
|
|
|
# # headingBlock.content = content
|
|
|
|
# let res = builderAcc.fold(
|
|
# (err) => OrgBuilderResult.err((builder, "Could not parse content")),
|
|
# (builder: OrgBuilder) => OrgBuilderResult.ok((
|
|
# parser: builder.parser.emptyTokens(),
|
|
# tree: @[headingBlock],
|
|
# ))
|
|
# )
|
|
|
|
# res
|
|
|
|
# proc makeOrg*(x: string): OrgBuilderResult =
|
|
# var acc = initOrgBuilder(x)
|
|
|
|
# while acc.isOk() and acc.tryParser(endOfStream).isErr():
|
|
# let unsafeAcc = acc.unsafeGet()
|
|
|
|
# let item = acc
|
|
# .tryBuildHeading()
|
|
# .flatMap(
|
|
# (x: OrgBuilder) => parseHeadlineChildren(x)
|
|
# )
|
|
# .flatMap(
|
|
# (x: OrgBuilder) => OrgBuilderResult.ok(OrgBuilder((
|
|
# parser: x.parser,
|
|
# tree: unsafeAcc.tree & x.tree,
|
|
# )))
|
|
# )
|
|
|
|
# acc = item
|
|
|
|
# acc
|
|
|
|
# proc foldOrg*(x: OrgBuilderResult): string =
|
|
# x
|
|
# .fold(
|
|
# (err) => "Error" & $err,
|
|
# (builder: OrgBuilder) => $builder.tree,
|
|
# )
|
|
# # echo acc.unsafeGet().tree[^1]
|
|
|
|
# when isMainModule:
|
|
# let test1 = """* TODO Level 1"""
|
|
|
|
# let test2 = """* TODO Level 1
|
|
# Foo
|
|
# ** DONE Level 2
|
|
|
|
# Some more content
|
|
# """
|
|
|
|
# let test3 = """* TODO Level 1
|
|
# Foo
|
|
# """
|
|
|
|
# let acc = makeOrg(test3).foldOrg()
|
|
|
|
# discard acc
|