{"id":25201342,"url":"https://github.com/haxscramper/haxorg","last_synced_at":"2026-03-06T18:38:21.802Z","repository":{"id":134341221,"uuid":"589166887","full_name":"haxscramper/haxorg","owner":"haxscramper","description":"Org-mode markup language parser written in C++","archived":false,"fork":false,"pushed_at":"2026-02-18T10:38:08.000Z","size":14870,"stargazers_count":7,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-02-18T12:57:34.056Z","etag":null,"topics":["cmake","cpp","cpp23","fuzztest","markup-language","org-mode","parsing","pybind11","python","python3"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/haxscramper.png","metadata":{"files":{"readme":"README.org","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-01-15T09:46:04.000Z","updated_at":"2026-02-03T17:06:13.000Z","dependencies_parsed_at":"2023-10-10T21:45:35.322Z","dependency_job_id":"23d60ccc-607b-4985-a759-07804d77dade","html_url":"https://github.com/haxscramper/haxorg","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/haxscramper/haxorg","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/haxscramper%2Fhaxorg","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/haxscramper%2Fhaxorg/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/haxscramper%2Fhaxorg/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/haxscramper%2Fhaxorg/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/haxscramper","download_url":"https://codeload.github.com/haxscramper/haxorg/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/haxscramper%2Fhaxorg/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30191237,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-06T18:30:16.692Z","status":"ssl_error","status_checked_at":"2026-03-06T18:30:13.818Z","response_time":250,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cmake","cpp","cpp23","fuzztest","markup-language","org-mode","parsing","pybind11","python","python3"],"created_at":"2025-02-10T04:37:27.584Z","updated_at":"2026-03-06T18:38:21.791Z","avatar_url":"https://github.com/haxscramper.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"#+title: haxorg\n\nOrg-mode parser with focus on scripting, structured data processing and ease of embedding in software.\n\n- Built for fast processing -- core is implemented in C++\n- With scripting in mind -- Python API, export to structured data (JSON, Yaml, S-expressions, protobuf)\n- Strictly defined schema -- strongly typed AST/DOM structure for individual nodes, auto-generated protobuf grammar, extensive use of vocabulary types in the data model.\n- Expressive debug capabilities -- built-in tracing framework for all document processing steps for ease of debugging\n- Extensive testing -- curated corpus of documents, fuzzy content generation for automatic bug detection using python hypothesis.\n\n* Development phases\n\nCurrently working on the [[https://github.com/haxscramper/haxorg/pull/3][second phase]] of the Python API, improving the ergonomics and adding more tests. Next step is to implement the CI for testing, documentation and artifact builds.\n\n| Phase      | Status   | Notes                                                   |\n|------------+----------+---------------------------------------------------------|\n| C++ core   | 🚧 Alpha | Whole pipeline is complete, working on testing          |\n| Python API | 🚧 Alpha | Whole DOM model is exposed, working on API improvements |\n| C API      | ⬜ Todo  | Make the library usable from virtually any PL           |\n\n** COMPLETED 🚧 C++ Core\n\n- ✅ Machine-readable data model -- describe the data model in machine-readable format and generate C++ code for it\n- ✅ Data transform pipeline -- lexer, parser, sem convert\n- ✅ Document test corpus -- yaml specification for the given/expected files\n- ✅ WIP Org-mode AST back to string -- for document formatting and round-trip PBT testing (make random document, render, parse back, compare with original)\n\n** WIP 🚧 Python API\n\n- ✅ Automatically wrap C++ data model for python -- done, tested, working on ergonomics improvements\n- 🚧 Implement common data format exporters -- (latex, HTML, XML, Pandoc)\n- 🚧 Use hypothesis for fuzz testing -- porting earlier C++ =google/fuzztest= implementation\n\n** TODO ⬜ C API\n\n- ⬜ Automatic wrapper of the C++ API to C\n- ⬜ Machine-readable description of the C API\n\n\n* Tools\n\n** ~haxorg~\n\nMain entry point for file manipulation -- python script implementing commands for export, analysis and file modifications.\n\n** ~pyhaxorg~\n\n=pybind11= python module exposing the org-mode AST for scripting.\n\n** TODO ~haxorg_lite~\n\nNot a fan of sprawling python dependencies when you only need to parse the file? Totally understandable. ~haxorg_lite~ is intended as a self-contained binary for the C++ parser core -- parse org-mode and output to json, yaml, binary protobuf, protobuf JSON, reformatted org-mode, S-expressions.\n\n# Binary parser CLI comes in two versions -- json-parameters and switch parameters.\n# \u003cexample of json-parameters\u003e\n# \u003cexample of switch-parameters\u003e\n# The interfaces are fully interchangeable as they are automatically generated from the CLI structure description thanks to the boost.describe (read more on how reflection is used in this project)\n\n* Development considerations, planning, some questions\n\n** Why?\n\nThere is no working and usable org-mode parser that can be decoupled from emacs /and even emacs one is absolute garbage/. Let's start with the 'canonical' implementation: aside from the fact it seems more like a huge collection of random regex rules, it barely has an AST, certainly not in a way that is ready for export into other consumers. Exporter customization system still mainly revolves around string manipulation. Very few parts are implemented as a data processing pipelines where you take in an AST and return some other content -- this is not limited to the exporters, org agenda customization is also a string processing. ~subtree.isRecurring()~ is easy to implement in the C++, but for emacs it is a ~re-search-forward~ with some ~rx~ hacks on top. And so on.\n\nSo while the emacs is certainly a good org-mode editor, it does a terrible job at being org-mode processor (all default exports block the UI, batch exporting in CLI is something you need to hack around) unless you are planning to dive knee-deep into the lisp programming and figure out all the details of how things need to fit together. Adding support for new source block languages is also tricky. And be a lisp programmer, again. Most people aren't lisp programmers -- I'm not one, even after using emacs for 5+ years at this point. There are far more python and c++ programmers out there than lisp ones.\n\nThis pretty much sums up the problem statement -- *implement an org-mode parser in some programming language that /I/ know and expose the interface in python for quicker scripting*. C++ fits the bill, so that's what I went with. Might've been a good opportunity to use Rust or Zig or some other PL, but as it turned out the C++ can be moved into a very ergonomic direction even without full syntax revamps like Carbon or =cppfront= (aka C++ Syntax 2).\n\n** How?\n\n*** Tooling, libraries used\n\nAfter I stated what in the world I'm doing here in this project, lets take a closer look at how I'm planning to actually carry this out. Let's go over the development tools first. The programming language is C++, specifically the latest C++23 -- to simplify toolchain and stdlib bundling I will just use LLVM releases directly. Dependencies are managed by submodules because not all the libraries I used even have conan packaging (=fuzztest=, abseil, =libgit2= (1 year outdated), other things). And\n\n*** Feature parity\n\nEmacs is still the reference implementation, but sensible extensions taken either from the common packages or ones that I use personally (nested tags ~#parent##sub##[subsub1,subsub2]~, ~@mention~, admonition blocks and ~NOTE:~ prefixes) will be implemented and tested as well. AST structure will conform to whatever data model makes the most sense, not necessarily following the S-Expr blurbs at the [[https://orgmode.org/worg/org-syntax.html][org-syntax]].\n\n*** Testing\n\nUnit testing for the regular cxx code if possible, plus collection of test documents in the ~.yaml~ spec corpus ([[file:tests/org/corpus]]). Each test document goes through the whole lex-parse-sem process, then to ~AST-\u003estring~ formatter and parsed again. This ensures every test validates the whole processing pipeline, even if no intermediate assertions are provided. For more on testing, read the [[file:ARCHITECTURE.org]] section \"Testing infrastructure\".\n\n** Where?\n   :PROPERTIES:\n   :ID:       2e97816d-eb26-463c-9a9b-db60b15fdc55\n   :END:\n\nWhere is the project on the roadmap at the moment, are there any fixed plans or it is just me bumping around the code and fixing things if I see anything that catches my attention this particular moment? Not in a formal sense at the moment, but a rough outline of the things I want to do is:\n\n- *Finish rewrite to the standard library types and RE-flex lexer* -- implementation with Qt types was working correctly as far back as August 2023, but since then I decided to completely drop dependency on Qt, use the RE-flex lexer instead of hand-rolled one and so some other things reorganizing the project. It has taken quite a bit of time, the main missing link being the new lexer implementation. Parser and sem convert don't have to change as much.\n- *Stabilize exposed python API* -- =nanobind= wrapper generation relies on the\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhaxscramper%2Fhaxorg","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhaxscramper%2Fhaxorg","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhaxscramper%2Fhaxorg/lists"}