Create an org heading builder

This commit is contained in:
Florian Schroedl
2022-05-04 17:00:00 +02:00
parent bec4953a97
commit 722e66cf85
10 changed files with 342 additions and 0 deletions

View File

@@ -0,0 +1,87 @@
import std/sugar
import std/strformat
import std/collections/sequtils
import std/strutils
import results
import fusion/matching
import ../utils/fp
import ../parser/parser_internals
import ../parser/parser_types
import ../parser/utils
import ./org_properties_block
import ./org_types
import ./org_builder
{.experimental: "caseStmtMacros".}
let parseHeadingStars = @[
manyUntil(ch('*'), ch(' ')),
ignore(ch(' '))
]
proc createTodoKeywordParser(xs: seq[string]): (Parser -> ParserResult) =
choice(xs.map((x: string) => str(x) + ignore(ch(' '))))
let todoKeywords = @["TODO"]
let doneKeywords = @["DONE"]
let parseTodoKeyword = todoKeywords.createTodoKeywordParser()
let parseDoneKeyword = doneKeywords.createTodoKeywordParser()
let parseHeadingText = @[
anyUntil(newline),
ignore(newline),
]
# func buildStars(token: seq[ParserToken]): seq[ParserToken] =
# # builder.kind = orgHeading
# # builder.level = token.tokenStringValue().len
# token
let buildStars = func(tokens: seq[ParserToken], org: OrgBlock): OrgBlock {.closure.}=
org.level = tokens[0].tokenStringValue().len
org
proc tryBuildHeading(builder: OrgBuilderResult): OrgBuilderResult =
builder
.applyParsersSeqToSingle(
OrgBlock(kind: orgHeading),
@[(parseHeadingStars, buildStars)]
)
when isMainModule:
echo initOrgBuilder("**** TODO Some stars")
.tryBuildHeading()
# let sampleBuilder = StringBuilderResult
# .ok(StringBuilder((
# parser: initParser("""**** TODO Some stars
# :PROPERTIES:
# :PROP_NAME: Value
# :PROP_NAME: Value
# :PROP_NAME: Value
# :PROP_NAME: Value
# :PROPERTIES_END:
# Foo
# """),
# tree: newSeq[StringBuilderT](),
# )))
# .applyParsersSeq(@[
# (parseHeadingStars, stringConcat("Stars: ")),
# (@[optional(parseTodoKeyword)], stringConcat("TODO: ")),
# (@[optional(parseDoneKeyword)], stringConcat("DONE: ")),
# (parseHeadingText, stringConcat("Text: ")),
# (parseProperties, stringConcat("Properties: ", seperator = ", ")),
# # (@[optional(choice(parseProperties))], stringConcat("Properties: ")),
# ])
# .foldBuilder(
# err => &"Error Parsing: {err}",
# xs => "Parser Succesfull:\n" & xs.join("\n"),
# )
# echo sampleBuilder

View File

@@ -1,8 +1,10 @@
import std/sugar
import results
import std/collections/sequtils
import ./org_types
import ../parser/parser_types
## Inline Blocks
type OrgInlineBuilderT* = OrgInlineBlock
type OrgInlineBuilder* = Builder[OrgInlineBuilderT]
type OrgInlineBuilderResult* = BuilderResult[OrgInlineBuilderT]
@@ -28,3 +30,25 @@ func rawTextTokenizer*(kind: orgInlineBlockKind): string -> OrgInlineBuilderT =
kind: kind,
content: content,
)
## Blocks
type OrgBuilderT* = OrgBlock
type OrgBuilder* = Builder[OrgBuilderT]
type OrgBuilderResult* = BuilderResult[OrgBuilderT]
func initOrgBuilder*(content: string): OrgBuilderResult =
return OrgBuilderResult.ok(OrgBuilder((
parser: initParser(content),
tree: newSeq[OrgBuilderT](),
)))
# proc orgBuilderConcat*(typeInfo: OrgBuilderT, concatFn: (ParserToken, OrgBuilderT) -> OrgBuilderT):
# (seq[ParserToken], OrgBuilderT) -> OrgBuilderT =
# return proc(xs: seq[ParserToken], builder: OrgBuilderT): OrgBuilderT =
# return xs.foldl(concatFn(b, a), typeInfo)
proc orgBuilderApply*(concatFn: (ParserToken, OrgBuilderT) -> OrgBuilderT):
(seq[ParserToken], OrgBuilderT) -> OrgBuilderT =
return proc(tokens: seq[ParserToken], builder: OrgBuilderT): OrgBuilderT =
tokens.foldl(concatFn(b, a), builder)

39
src/org/org_document.nim Normal file
View File

@@ -0,0 +1,39 @@
import std/sugar
import std/collections/sequtils
import std/strformat
import std/strutils
import results
import fusion/matching
import ./org_types
import ./org_builder
import ./org_text_link
import ../utils/fp
import ../parser/parser_internals
import ../parser/parser_types
import ../parser/builder_api
when isMainModule:
let test = initOrgBuilder("""
Some text to be ignored for now
* Stars 1
Ignore me
** Stars 1-1
*** Stars 1-1-1
** Stars 1-2
* Stars 2
""")
.flatMap((builder: OrgBuilder) => tryParseBuild(
builder = builder,
builderFns = orgStyledTextBuilders,
defaultBuilderFn = makeRawTokenOrEmpty,
)
echo test

View File

@@ -3,6 +3,7 @@ import std/sugar
import std/strutils
import fp/maybe
## Inline Block
type
orgInlineBlockKind* = enum
orgRawText,
@@ -76,3 +77,49 @@ proc `$`*(x: OrgInlineBlock): string =
stringifySpecialFields(x) &
"""
)"""
## Block
type
orgBlockKind* = enum
orgHeading
# orgParagraph
OrgBlock* = ref object
children*: seq[OrgInlineBlock]
case kind*: orgBlockKind
of orgHeading:
level*: int
func stringifySpecialFields(x: OrgBlock): string =
let specialFields = case x.kind:
of orgHeading:
&"""level: {x.level}"""
else: ""
specialFields
.just()
.notEmpty()
.map(x => x.indent(2))
.map(x => "\n" & x & "\n")
.getOrElse("")
proc `$`*(x: OrgBlock): string =
&"""OrgBlock(
kind: {x.kind}""" &
stringifySpecialFields(x) &
&"""
children: {x.children}
)
"""
type
OrgDocument* = ref object
children*: seq[OrgBlock]
proc `$`*(x: OrgDocument): string =
&"""OrgDocument(
children: {x.children}
)"""
when isMainModule:
echo OrgBlock(kind: orgHeading)