Go to file
Levi Neely 623aef4f42 Fix phantom namespace nodes and child section insertion
Dynamic child resolvers returned Some for any name, fabricating phantom
document and section directories so walks to nonexistent paths appeared
to succeed. Validate existence and return None instead:
- root resolver checks get_doc
- document resolver checks new OrkState::section_exists
- section resolver checks child_ids

Also fix create_child_section, which corrupted the org file:
- find_section_end used the parent's headline-end offset, inserting the
  child before the parent's PROPERTIES/ID drawer and detaching its ID.
  Use section.span.end, which covers planning, drawer, body, children.
- The child headline was written verbatim; demote it to parent.level + 1
  via the new restar helper.

Add regression tests for restar and child section nesting.
2026-09-30 21:28:52 +02:00
crates Fix phantom namespace nodes and child section insertion 2026-09-30 21:28:52 +02:00
doc Add complete section properties to 9P namespace 2026-09-30 14:16:18 +02:00
.gitignore Initial commit: org-mode parser and CLI 2026-09-30 09:43:21 +02:00
.gitmodules Initial commit: org-mode parser and CLI 2026-09-30 09:43:21 +02:00
AGENTS.md Add VISION.md and AGENTS.md 2026-09-30 09:45:38 +02:00
Cargo.lock Add 9P2000 server implementation 2026-09-30 15:09:59 +02:00
Cargo.toml Add ork-server crate with virtfs EDSL 2026-09-30 10:31:11 +02:00
LICENSE Initial commit: org-mode parser and CLI 2026-09-30 09:43:21 +02:00
Makefile Add Makefile 2026-09-30 09:46:41 +02:00
README.md Initial commit: org-mode parser and CLI 2026-09-30 09:43:21 +02:00
VISION.md Add VISION.md and AGENTS.md 2026-09-30 09:45:38 +02:00
test.org Initial commit: org-mode parser and CLI 2026-09-30 09:43:21 +02:00

README.md

Orkmode

A standalone org-mode implementation for KDE, built with Rust (parser/core) and C++ (Qt UI).

Project Structure

orkmode/
├── Cargo.toml                    # Workspace root
├── crates/
│   ├── org-ast/                  # AST type definitions
│   │   └── src/
│   │       ├── lib.rs           # Module exports
│   │       ├── document.rs      # Document, settings
│   │       ├── headline.rs      # Section, Headline, Planning
│   │       ├── elements.rs      # Block elements (paragraph, list, table, etc.)
│   │       ├── objects.rs       # Inline objects (markup, links, etc.)
│   │       ├── timestamp.rs     # Timestamp types
│   │       └── span.rs          # Source location tracking
│   ├── org-parser/              # Tree-sitter based parser
│   │   ├── build.rs            # Compiles tree-sitter-org grammar
│   │   ├── tree-sitter-org/    # Git submodule: nvim-orgmode/tree-sitter-org
│   │   └── src/
│   │       ├── lib.rs          # Parser API
│   │       ├── convert.rs      # Tree-sitter → AST conversion
│   │       ├── ts.rs           # Tree-sitter language bindings
│   │       └── error.rs        # Error types
│   ├── orkmode-core/            # Core library with FFI
│   │   └── src/
│   │       ├── lib.rs          # High-level API
│   │       └── ffi.rs          # C FFI for Qt integration
│   └── ork-cli/                 # Command-line interface
│       └── src/
│           ├── main.rs         # CLI entry point
│           └── commands.rs     # Command implementations
└── ui/                          # (future) Qt/QML UI

Features

Supported Org Syntax

  • Headlines with nesting levels
  • TODO keywords (customizable via #+TODO:)
  • Priority cookies ([#A], [#B], [#C])
  • Tags
  • Property drawers
  • Planning lines (SCHEDULED, DEADLINE, CLOSED)
  • Timestamps (active, inactive, ranges, repeaters)
  • Paragraphs
  • Plain lists (unordered, ordered, checkboxes)
  • Source blocks
  • Tables
  • Drawers
  • Keywords/directives
  • Comments
  • LaTeX environments
  • Inline markup (bold, italic, etc.) - AST types ready, parsing TODO
  • Links - AST types ready, parsing TODO
  • Footnotes
  • Citations

Document Settings

Parses common #+KEYWORD directives:

  • TITLE, AUTHOR, EMAIL, DATE
  • TODO, SEQ_TODO, TYP_TODO
  • PROPERTY, STARTUP, OPTIONS
  • FILETAGS, CATEGORY, ARCHIVE

Building

Prerequisites

  • Rust 1.70+
  • C compiler (for tree-sitter grammar)

Build

# Build all crates
cargo build

# Run tests
cargo test

# Build release
cargo build --release

Usage

CLI (ork)

The ork command operates on org directories or individual files. All commands default to the current directory (.) when no path is specified. Use -R for recursive subdirectory scanning.

# List org files
ork files                     # Current directory
ork files ~/org               # Specific directory
ork files -R .                # Recursive

# Document info (aggregated across all files)
ork info                      # Current directory
ork info ~/org -R             # Recursive
ork info file.org             # Single file
ork info --json               # JSON output

# List sections
ork sections                  # All sections in cwd
ork sections --todos-only     # Only TODOs
ork sections --tag work       # Filter by tag
ork sections --depth 2        # Max depth
ork sections -R -j            # Recursive, JSON

# Query sections
ork query "tag:work"          # By tag
ork query "todo:TODO"         # By TODO state
ork query "priority:A"        # By priority
ork query "title:pattern"     # By title
ork query "file:notes"        # By filename
ork query "done:false" -j     # JSON output

# Get specific section by ID or title
ork get "my-task-id"          # Searches all files
ork get "My Task" -j          # JSON output
ork get "intro" ~/org -R      # In specific path

# List tags with counts
ork tags                      # All tags in cwd
ork tags -R --json            # Recursive, JSON

# Export as JSON
ork export --pretty           # All documents
ork export --section my-id    # Specific section

# Add section
ork add "New Task" file.org                           # To specific file
ork add "New Task" --file notes.org                   # When path is directory
ork add "New Task" file.org --todo TODO --priority A --tags "work,urgent"
ork add "New Task" file.org -n                        # Dry run

# Toggle TODO state
ork toggle "task-id"          # Searches all files
ork toggle "task-id" -n       # Dry run

# Agenda view
ork agenda                    # Current directory
ork agenda ~/org -R           # Recursive
ork agenda --days 14 --json   # 14 days, JSON

# Validate syntax
ork check                     # Current directory
ork check -R --json           # Recursive, JSON

Rust API

use org_parser::Parser;

let mut parser = Parser::new();
let doc = parser.parse(r#"
#+TITLE: My Document
#+TODO: TODO WAITING | DONE

* TODO [#A] First Task :work:
DEADLINE: <2025-01-15 Wed 14:00>

Some description.

** Subtask
- [ ] Item 1
- [X] Item 2
"#).unwrap();

// Access document properties
println!("Title: {:?}", doc.title());
println!("Sections: {}", doc.sections.len());
println!("TODOs: {}", doc.todos().count());

// Iterate sections
for section in doc.all_sections() {
    println!("{} {}", 
        "*".repeat(section.level() as usize),
        section.headline.title_text()
    );
}

C/C++ FFI

#include "orkmode.h"

// Parse a document
OrkDocument* doc = ork_parse("* Hello World");
if (doc) {
    // Get as JSON
    char* json = ork_document_to_json(doc);
    printf("%s\n", json);
    ork_string_free(json);
    
    // Get title
    char* title = ork_document_title(doc);
    if (title) {
        printf("Title: %s\n", title);
        ork_string_free(title);
    }
    
    // Cleanup
    ork_document_free(doc);
}

Architecture

Parser Design

The parser uses tree-sitter with the nvim-orgmode/tree-sitter-org grammar.

Benefits:

  • Incremental parsing: Only re-parses changed regions
  • Error recovery: Produces partial AST even with syntax errors
  • Performance: O(n) parsing, minimal memory allocation
  • Battle-tested: Used by Neovim's org-mode plugin

AST Design

The AST follows the org-element specification:

  • Document: Root node with settings and sections
  • Section: Headline + content + children
  • Elements: Block-level constructs (paragraphs, lists, blocks)
  • Objects: Inline constructs (markup, links, timestamps)

All nodes include source span information for editor integration.

Roadmap

Phase 1: Parser (Current)

  • Tree-sitter integration
  • Core AST types
  • Headline/section parsing
  • Block element parsing
  • Complete inline object parsing

Phase 2: Qt UI

  • Document rendering (read-only)
  • Syntax highlighting
  • Folding/cycling
  • Navigation

Phase 3: Editing

  • Inline editing
  • TODO state cycling
  • Tag editing
  • Property editing

Phase 4: Agenda

  • Basic agenda view
  • Day/week/month views
  • Filtering
  • Custom views

Phase 5: Advanced Features

  • Code block execution
  • Diagram rendering (mermaid, plantuml)
  • Capture templates
  • Clock/time tracking

License

GPL-3.0-or-later