diff --git a/src/org/org_block_heading.nim b/src/org/org_block_heading.nim index fb9f351..136966f 100644 --- a/src/org/org_block_heading.nim +++ b/src/org/org_block_heading.nim @@ -40,19 +40,38 @@ let parseHeadingText = @[ # token let buildStars = func(tokens: seq[ParserToken], org: OrgBlock): OrgBlock {.closure.}= - org.level = tokens[0].tokenStringValue().len + 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.}= + org.headlineContent = tokens.tokensToString() org proc tryBuildHeading(builder: OrgBuilderResult): OrgBuilderResult = builder .applyParsersSeqToSingle( OrgBlock(kind: orgHeading), - @[(parseHeadingStars, buildStars)] + @[ + (parseHeadingStars, buildStars, false), + + (@[optional(parseTodoKeyword)], buildTodo, true), + (@[optional(parseDoneKeyword)], buildTodo, true), + + (parseHeadingText, buildHeadlineContent, false), + ] ) when isMainModule: - echo initOrgBuilder("**** TODO Some stars") + echo initOrgBuilder("*** Some stars") .tryBuildHeading() + .fold( + x => "Nothing", + x => $x.tree + ) # let sampleBuilder = StringBuilderResult diff --git a/src/org/org_types.nim b/src/org/org_types.nim index e6f0d77..c066a51 100644 --- a/src/org/org_types.nim +++ b/src/org/org_types.nim @@ -1,3 +1,4 @@ +import std/options import std/strformat import std/sugar import std/strutils @@ -89,11 +90,15 @@ type case kind*: orgBlockKind of orgHeading: level*: int + todo*: Option[string] + headlineContent*: string func stringifySpecialFields(x: OrgBlock): string = let specialFields = case x.kind: of orgHeading: - &"""level: {x.level}""" + &"""level: {x.level} +todo: {x.todo} +headlineContent: {x.headlineContent}""" else: "" specialFields diff --git a/src/parser/parser_types.nim b/src/parser/parser_types.nim index da90d4d..af6b422 100644 --- a/src/parser/parser_types.nim +++ b/src/parser/parser_types.nim @@ -166,6 +166,7 @@ proc applyParsersToSingle*[T]( builder: Builder[T], parsers: seq[Parser -> ParserResult], tokenFoldFn: (seq[ParserToken], T) -> T, + optional = false, initT: T, ): BuilderResult[T] = # Apply the current parsing functions and convert to text tokens wrapped in ParserResult @@ -178,15 +179,20 @@ proc applyParsersToSingle*[T]( newParser .foldTokens( (err: ParserError) => BuilderResult[T].err((builder, "foo")), - (newTokens: seq[ParserToken]) => BuilderResult[T].ok( - builder.initBuilder( - newParser.unsafeGet(), - builder.tree - .last() - .orElse(just(initT)) - .map((x: T) => @[tokenFoldFn(newTokens, x)]) - .getOrElse(newSeq[T]()) - ) + (newTokens: seq[ParserToken]) => ( + if optional and newTokens.len == 0: + BuilderResult[T].ok(builder) + else: + BuilderResult[T].ok( + builder.initBuilder( + newParser.unsafeGet(), + builder.tree + .last() + .orElse(just(initT)) + .map((x: T) => @[tokenFoldFn(newTokens, x)]) + .getOrElse(newSeq[T]()) + ) + ) ) ) @@ -196,10 +202,17 @@ proc applyParsersSeqToSingle*[T]( xs: seq[tuple[ parsers: seq[Parser -> ParserResult], tokenFoldFn: (seq[ParserToken], T) -> T, + ignoreEmpty: bool, ]], ): BuilderResult[T] = xs.foldl( - a.flatMap((builder: Builder[T]) => applyParsersToSingle(builder, b[0], b[1], initT)), + a.flatMap((builder: Builder[T]) => applyParsersToSingle( + builder, + b.parsers, + b.tokenFoldFn, + b.ignoreEmpty, + initT + )), builderResult )