[OCaml] Org mode parser.
refactor rename library from ocaml-org to org
Rename the opam package and Dune library from 'ocaml-org' (module prefix Ocaml_org) to 'org' (module prefix Org). org.ml now serves as the manual Dune wrapper module, exposing: - Org.parse, Org.parse_with_diagnostics, Org.version at top level - Org.Ast, Org.Config, Org.Prescan, Org.Diagnostic as public modules - Org.Lexer, Org.Parse_bridge, Org.Raw_ast as internal/unstable Consumer code simplifies from Ocaml_org.Org.parse to Org.parse and from Ocaml_org.Ast to Org.Ast. BREAKING CHANGE: library renamed from ocaml-org to org; all module paths change from Ocaml_org.* to Org.*
Changed files
.kiro/steering/main.md
@@ -892,7 +892,7 @@
892
892
The following choices were made during requirements elicitation and
893
893
are binding for the current implementation:
894
894
895
Removed:
* **Package name**: `ocaml-org`.
895
Added:
* **Package name**: `org`.
896
896
* **OCaml version**: 5.5.0 (local opam switch).
897
897
* **Test framework**: Alcotest.
898
898
* **Structural lexer**: handwritten OCaml (not ocamllex). The lexer
@@ -948,13 +948,12 @@
948
948
949
949
### Library wrapping
950
950
951
Removed:
The library uses Dune's automatic module wrapping. There is no
952
Removed:
manual `ocaml_org.ml` wrapper — all modules are sub-modules of
953
Removed:
`Ocaml_org` (e.g. `Ocaml_org.Org.parse`, `Ocaml_org.Ast`,
954
Removed:
`Ocaml_org.Config`).
951
Added:
The library uses `org.ml` as a manual Dune wrapper module. All
952
Added:
public sub-modules are accessible under the `Org` namespace
953
Added:
(e.g. `Org.parse`, `Org.Ast`, `Org.Config`).
955
954
956
Removed:
The public API entry point is `lib/org.ml` (accessed as
957
Removed:
`Ocaml_org.Org`).
955
Added:
The public API entry point is `lib/org.ml` which serves both as
956
Added:
the wrapper and the top-level API, exposing `Org.parse` directly.
958
957
959
958
### Structural parser conflicts
960
959
dune-project
@@ -1,6 +1,6 @@
1
1
(lang dune 3.0)
2
2
3
Removed:
(name ocaml-org)
3
Added:
(name org)
4
4
5
5
(version 0.1.0)
6
6
@@ -9,7 +9,7 @@
9
9
(using menhir 2.1)
10
10
11
11
(package
12
Removed:
(name ocaml-org)
12
Added:
(name org)
13
13
(synopsis "OCaml Org Mode parser library")
14
14
(description
15
15
"A compact, high-quality OCaml library for parsing Org Mode documents into a semantic, strongly typed abstract syntax tree.")
lib/dune
@@ -1,6 +1,6 @@
1
1
(library
2
Removed:
(name ocaml_org)
3
Removed:
(public_name ocaml-org)
2
Added:
(name org)
3
Added:
(public_name org)
4
4
(libraries menhirLib))
5
5
6
6
(menhir
lib/org.ml
@@ -1,8 +1,33 @@
1
Removed:
(** OCaml Org Mode parser - public entry points.
1
Added:
(** Org — OCaml Org Mode parser library.
2
2
3
Removed:
This module provides the primary API for parsing Org Mode
4
Removed:
documents into a semantic AST. *)
3
Added:
This is the top-level module for the [org] library. It re-exports
4
Added:
the public API and sub-modules, providing a convenient namespace
5
Added:
for consumers:
5
6
7
Added:
{[
8
Added:
let doc = Org.parse input
9
Added:
let headings = doc.Org.Ast.headings
10
Added:
]}
11
Added:
*)
12
Added:
13
Added:
(** {1 Public sub-modules} *)
14
Added:
15
Added:
module Ast = Ast
16
Added:
module Config = Config
17
Added:
module Prescan = Prescan
18
Added:
module Diagnostic = Diagnostic
19
Added:
20
Added:
(** {1 Internal sub-modules}
21
Added:
22
Added:
These are exposed for testing and advanced use. They are not
23
Added:
part of the stable public API and may change without notice. *)
24
Added:
25
Added:
module Lexer = Lexer
26
Added:
module Parse_bridge = Parse_bridge
27
Added:
module Raw_ast = Raw_ast
28
Added:
29
Added:
(** {1 Parsing entry points} *)
30
Added:
6
31
let version = "0.1.0"
7
32
8
33
(** Parse an Org Mode document string into a semantic AST.
@@ -24,11 +49,7 @@
24
49
(** Parse an Org Mode document with diagnostic reporting.
25
50
26
51
Returns both the best-effort AST and a list of diagnostics
27
Removed:
for recoverable issues encountered during parsing.
28
Removed:
29
Removed:
Currently diagnostics are minimal (the parser is permissive
30
Removed:
and rarely needs to report issues). Future versions may
31
Removed:
report more detailed warnings. *)
52
Added:
for recoverable issues encountered during parsing. *)
32
53
let parse_with_diagnostics input =
33
54
let _collector = Diagnostic.create_collector () in
34
55
let doc = parse input in
ocaml-org.opam
@@ -1,32 +0,0 @@
1
Removed:
# This file is generated by dune, edit dune-project instead
2
Removed:
opam-version: "2.0"
3
Removed:
version: "0.1.0"
4
Removed:
synopsis: "OCaml Org Mode parser library"
5
Removed:
description:
6
Removed:
"A compact, high-quality OCaml library for parsing Org Mode documents into a semantic, strongly typed abstract syntax tree."
7
Removed:
maintainer: ["blendux"]
8
Removed:
authors: ["blendux"]
9
Removed:
license: "ISC"
10
Removed:
homepage: "https://github.com/blendux/ocaml-org"
11
Removed:
bug-reports: "https://github.com/blendux/ocaml-org/issues"
12
Removed:
depends: [
13
Removed:
"dune" {>= "3.0"}
14
Removed:
"ocaml" {>= "5.0"}
15
Removed:
"menhir" {>= "20231231"}
16
Removed:
"alcotest" {with-test & >= "0.8.5"}
17
Removed:
"odoc" {with-doc}
18
Removed:
]
19
Removed:
build: [
20
Removed:
["dune" "subst"] {dev}
21
Removed:
[
22
Removed:
"dune"
23
Removed:
"build"
24
Removed:
"-p"
25
Removed:
name
26
Removed:
"-j"
27
Removed:
jobs
28
Removed:
"@install"
29
Removed:
"@runtest" {with-test}
30
Removed:
"@doc" {with-doc}
31
Removed:
]
32
Removed:
]
org.opam
@@ -0,0 +1,32 @@
1
Added:
# This file is generated by dune, edit dune-project instead
2
Added:
opam-version: "2.0"
3
Added:
version: "0.1.0"
4
Added:
synopsis: "OCaml Org Mode parser library"
5
Added:
description:
6
Added:
"A compact, high-quality OCaml library for parsing Org Mode documents into a semantic, strongly typed abstract syntax tree."
7
Added:
maintainer: ["blendux"]
8
Added:
authors: ["blendux"]
9
Added:
license: "ISC"
10
Added:
homepage: "https://github.com/blendux/ocaml-org"
11
Added:
bug-reports: "https://github.com/blendux/ocaml-org/issues"
12
Added:
depends: [
13
Added:
"dune" {>= "3.0"}
14
Added:
"ocaml" {>= "5.0"}
15
Added:
"menhir" {>= "20231231"}
16
Added:
"alcotest" {with-test & >= "0.8.5"}
17
Added:
"odoc" {with-doc}
18
Added:
]
19
Added:
build: [
20
Added:
["dune" "subst"] {dev}
21
Added:
[
22
Added:
"dune"
23
Added:
"build"
24
Added:
"-p"
25
Added:
name
26
Added:
"-j"
27
Added:
jobs
28
Added:
"@install"
29
Added:
"@runtest" {with-test}
30
Added:
"@doc" {with-doc}
31
Added:
]
32
Added:
]
test/dune
@@ -1,3 +1,3 @@
1
1
(test
2
2
(name test_main)
3
Removed:
(libraries ocaml-org alcotest))
3
Added:
(libraries org alcotest))
test/test_main.ml
@@ -1,17 +1,17 @@
1
1
let test_version () =
2
Removed:
Alcotest.(check string) "version" "0.1.0" Ocaml_org.Org.version
2
Added:
Alcotest.(check string) "version" "0.1.0" Org.version
3
3
4
4
(* Prescan tests *)
5
5
6
6
let test_prescan_default () =
7
Removed:
let config = Ocaml_org.Prescan.scan "" in
8
Removed:
let kws = Ocaml_org.Config.all_todo_keywords config in
7
Added:
let config = Org.Prescan.scan "" in
8
Added:
let kws = Org.Config.all_todo_keywords config in
9
9
Alcotest.(check (list string)) "default keywords" [ "TODO"; "DONE" ] kws
10
10
11
11
let test_prescan_custom_todo () =
12
12
let input = "#+TODO: NEXT WAITING | DONE CANCELLED\n" in
13
Removed:
let config = Ocaml_org.Prescan.scan input in
14
Removed:
let kws = Ocaml_org.Config.all_todo_keywords config in
13
Added:
let config = Org.Prescan.scan input in
14
Added:
let kws = Org.Config.all_todo_keywords config in
15
15
Alcotest.(check (list string)) "custom keywords"
16
16
[ "NEXT"; "WAITING"; "DONE"; "CANCELLED" ] kws
17
17
@@ -20,31 +20,31 @@
20
20
"#+TODO: TODO | DONE\n\
21
21
#+TODO: OPEN | CLOSED\n"
22
22
in
23
Removed:
let config = Ocaml_org.Prescan.scan input in
24
Removed:
let kws = Ocaml_org.Config.all_todo_keywords config in
23
Added:
let config = Org.Prescan.scan input in
24
Added:
let kws = Org.Config.all_todo_keywords config in
25
25
Alcotest.(check (list string)) "multiple sequences"
26
26
[ "TODO"; "DONE"; "OPEN"; "CLOSED" ] kws
27
27
28
28
let test_prescan_seq_todo () =
29
29
let input = "#+SEQ_TODO: NEXT ACTIVE | DONE\n" in
30
Removed:
let config = Ocaml_org.Prescan.scan input in
30
Added:
let config = Org.Prescan.scan input in
31
31
Alcotest.(check bool) "NEXT is todo" true
32
Removed:
(Ocaml_org.Config.is_todo_keyword config "NEXT");
32
Added:
(Org.Config.is_todo_keyword config "NEXT");
33
33
Alcotest.(check bool) "DONE is todo" true
34
Removed:
(Ocaml_org.Config.is_todo_keyword config "DONE");
34
Added:
(Org.Config.is_todo_keyword config "DONE");
35
35
Alcotest.(check bool) "UNKNOWN is not todo" false
36
Removed:
(Ocaml_org.Config.is_todo_keyword config "UNKNOWN")
36
Added:
(Org.Config.is_todo_keyword config "UNKNOWN")
37
37
38
38
let test_prescan_case_insensitive_key () =
39
39
let input = "#+todo: BUG FIX | RESOLVED\n" in
40
Removed:
let config = Ocaml_org.Prescan.scan input in
41
Removed:
let kws = Ocaml_org.Config.all_todo_keywords config in
40
Added:
let config = Org.Prescan.scan input in
41
Added:
let kws = Org.Config.all_todo_keywords config in
42
42
Alcotest.(check (list string)) "case insensitive key"
43
43
[ "BUG"; "FIX"; "RESOLVED" ] kws
44
44
45
45
let test_prescan_no_bar () =
46
46
let input = "#+TODO: TODO DOING DONE\n" in
47
Removed:
let config = Ocaml_org.Prescan.scan input in
47
Added:
let config = Org.Prescan.scan input in
48
48
let seqs = config.todo_sequences in
49
49
let seq = List.hd seqs in
50
50
Alcotest.(check (list string)) "all active" [ "TODO"; "DOING"; "DONE" ]
@@ -52,9 +52,9 @@
52
52
Alcotest.(check (list string)) "no done" [] seq.done_
53
53
54
54
(* Lexer tests *)
55
Removed:
module L = Ocaml_org.Lexer
55
Added:
module L = Org.Lexer
56
56
57
Removed:
let config = Ocaml_org.Config.default
57
Added:
let config = Org.Config.default
58
58
59
59
let lex input =
60
60
L.tokenize ~config input |> List.map fst
@@ -159,9 +159,9 @@
159
159
check_tok "property" "Property(\"CUSTOM_ID\", \"my-id\")" (List.nth toks 0)
160
160
161
161
(* Parser tests *)
162
Removed:
module P = Ocaml_org.Parse_bridge
163
Removed:
module R = Ocaml_org.Raw_ast
164
Removed:
module A = Ocaml_org.Ast
162
Added:
module P = Org.Parse_bridge
163
Added:
module R = Org.Raw_ast
164
Added:
module A = Org.Ast
165
165
166
166
let parse input = P.parse ~config input
167
167
let parse_inline input = P.parse_inline input
@@ -400,7 +400,7 @@
400
400
A range: <2024-01-15 Mon>--<2024-01-20 Sat>.
401
401
|}
402
402
403
Removed:
let full_doc = Ocaml_org.Org.parse full_fixture
403
Added:
let full_doc = Org.parse full_fixture
404
404
405
405
let test_integration_structure () =
406
406
(* Directives *)
@@ -594,7 +594,7 @@
594
594
Alcotest.(check bool) "has timestamp range" true has_range
595
595
596
596
let () =
597
Removed:
Alcotest.run "ocaml-org"
597
Added:
Alcotest.run "org"
598
598
[
599
599
("basic", [ Alcotest.test_case "version" `Quick test_version ]);
600
600
( "prescan",