Create an org heading builder
This commit is contained in:
87
src/org/org_block_heading.nim
Normal file
87
src/org/org_block_heading.nim
Normal 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
|
||||
@@ -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
39
src/org/org_document.nim
Normal 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
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user