Go to file
Levi Neely bfc0c80d09 Scroll to the body segment that contains a link offset
Link reveal previously scrolled only to the section top (offset > 0 just
chose Beginning vs Contain). Thread the body offset through to the
rendered segment so the view scrolls to the matched segment, keeping the
existing segmented body rendering (text/code/table/list).

- The bodyParts builder now records each segment's startLine (the body
  line index where it begins) for text, list, code, and table parts,
  tracked through the line-categorizing loop and pushText.
- A new delegate function offsetToY(bodyOffset) converts the offset to a
  body line, finds the last segment whose startLine <= that line, and
  returns that segment's y relative to the delegate via mapToItem.
- On sectionRevealed with offset > 0, position the row at the viewport
  top (which realizes the delegate), then nudge contentY by offsetToY so
  the matched segment sits at the top, clamped to the content bounds.

The offset->line->segment selection was verified with a standalone
harness replicating the builder and selection logic: for a body mixing
intro text, a code block, a paragraph, a table, trailing text, and a
list, every line maps to the segment that actually contains it. The
final pixel scroll uses standard Qt Quick coordinate mapping; it needs a
rendered scene to verify visually, which is not possible headlessly.
Granularity is now segment-precise; intra-segment line precision is not
attempted (text segments are Labels without glyph positioning).
2026-10-02 12:26:09 +02:00
crates Fix empty section body when content follows a property drawer 2026-10-02 12:21:32 +02:00
doc Add complete section properties to 9P namespace 2026-09-30 14:16:18 +02:00
ui Scroll to the body segment that contains a link offset 2026-10-02 12:26:09 +02:00
.gitignore Add v0.3 read-only Qt6/QML GUI (9P client) 2026-10-01 02:02:53 +02:00
.gitmodules Initial commit: org-mode parser and CLI 2026-09-30 09:43:21 +02:00
AGENTS.md Clean up docs and fix set_planning_field 2026-10-01 08:53:22 +02:00
Cargo.lock Add language plugin registry and Emacs-style #+RESULTS: formatting 2026-10-01 13:36:38 +02:00
Cargo.toml Remove dead orkmode-core (FFI) crate 2026-09-30 22:27:50 +02:00
LICENSE Initial commit: org-mode parser and CLI 2026-09-30 09:43:21 +02:00
Makefile Fix Makefile install target 2026-10-01 10:12:53 +02:00
README.md Clean up docs and fix set_planning_field 2026-10-01 08:53:22 +02:00
VISION.md Update VISION to the 9P architecture and editing model 2026-09-30 22:21:10 +02:00
notes.org Add sample links exercising every resolver branch 2026-10-02 11:43:24 +02:00
test.org Add sample links exercising every resolver branch 2026-10-02 11:43:24 +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
│   ├── ork-cli/                 # Command-line interface (9P client)
│   │   └── src/
│   │       ├── main.rs         # CLI commands (base + friendly verbs)
│   │       └── client.rs       # 9P2000 client
│   └── ork-server/             # 9P server exposing org files
│       └── src/
│           ├── bin/ork-server.rs  # Server entry point
│           ├── state.rs        # Document state, section ops, ctl verbs
│           ├── namespace.rs    # 9P namespace (docs, sections, agenda, query)
│           ├── p9.rs           # 9P protocol handling
│           └── virtfs.rs       # Virtual filesystem tree
└── ui/                          # Qt6/QML GUI (9P client, no FFI)
    ├── CMakeLists.txt          # Qt6 build (Core/Gui/Qml/Quick/Network)
    ├── src/
    │   ├── main.cpp            # Entry point; --addr, --selftest
    │   ├── p9client.{h,cpp}    # Minimal synchronous 9P2000 client
    │   ├── orkclient.{h,cpp}   # QML-facing façade over the 9P client
    │   └── documentmodel.{h,cpp}  # Lazy QAbstractItemModel section tree
    └── qml/
        ├── Main.qml            # Window, document sidebar, outline
        └── OutlineView.qml     # Folding TreeView with structural styling

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)
  • Qt 6.3+ and CMake 3.21+ (for the GUI)

Build

# Build all crates
cargo build

# Run tests
cargo test

# Build release
cargo build --release

GUI

The GUI is a separate Qt6/CMake project that talks to ork-server over 9P.

cmake -S ui -B ui/build -DCMAKE_BUILD_TYPE=Release
cmake --build ui/build -j

# Run against a running ork-server (see below)
./ui/build/bin/orkmode -a unix:///tmp/ork.sock

Usage

Server

Start the 9P server to expose an org directory:

# Unix socket (preferred for local use)
ork-server -a unix:///tmp/ork.sock -d ~/org

# TCP socket
ork-server -a tcp://localhost:5640 -d ~/org

CLI (ork)

ork is a 9P client that talks to ork-server. All org-mode intelligence lives in the server.

# Set the server address (or use -a on each call)
export ORK_ADDR=unix:///tmp/ork.sock

# Base 9P operations
ork ls /                       # List root namespace
ork read /idx                  # Read a file
ork write /work/task/keyword DONE  # Write a value

# Friendly verbs (compositions of 9P ops)
ork docs                       # List documents (name + title)
ork sections work              # Top-level sections in work.org
ork tree work                  # Full section outline
ork todos                      # All TODO items across docs
ork todos work                 # TODOs in work.org only

# Section details
ork get work my-task           # Show section fields
ork set work my-task keyword DONE  # Set a field
ork set work my-task tags work:urgent  # Set tags (colon-separated)

# Create sections
ork mkdoc notes                # Create notes.org
ork add work "* TODO New task :work:"  # Add top-level section
ork add work "* Subtask" -p parent-id  # Add child section

# TODO management
ork todo work my-task          # Cycle to next state
ork todo work my-task DONE     # Set explicit state
ork tag work my-task urgent    # Add tag
ork tag work my-task urgent -r # Remove tag

# Structural operations
ork mv work my-task up         # Reorder among siblings
ork promote work my-task       # Decrease level
ork demote work my-task        # Increase level
ork rm work my-task            # Delete section and subtree
ork refile work my-task archive        # Move to another doc
ork refile work my-task archive -p done  # As child of 'done' section
ork archive work my-task       # Move to work.org_archive

# Properties
ork prop work my-task CUSTOM_ID        # Get property
ork prop work my-task EFFORT 2h        # Set property
ork prop work my-task EFFORT -d        # Delete property

# Agenda views
ork agenda todos               # All TODOs
ork agenda today               # Items scheduled/due today
ork agenda week                # Next 7 days

# Query
ork query 'tag:work'           # Match sections by tag
ork query 'tag:work+todo:TODO' # Compound query
ork query 'priority:A'         # By priority

# Maintenance
ork reload                     # Rescan files from disk
ork lint                       # Validate all documents
ork lint work                  # Validate one document

Any 9P client works (e.g., plan9port 9p):

9p -a 'unix!/tmp/ork.sock' ls /
9p -a 'unix!/tmp/ork.sock' read /idx
9p -a 'unix!/tmp/ork.sock' write /work/task/keyword DONE

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 ✓

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

Phase 2: 9P Server ✓

  • Document state with locking
  • Read/write section fields (keyword, priority, title, tags, timestamps, body)
  • Create documents and sections
  • Structural ops (delete, move, promote, demote, refile, archive)
  • Agenda views (todos, today, week)
  • Query interface (tag, todo, priority)
  • ctl verbs (reload, lint)

Phase 3: Qt UI (Current)

  • Document rendering (read-only)
  • Structural styling (keywords, priorities, tags, timestamps)
  • Folding/cycling (TreeView)
  • Navigation
  • Inline editing
  • TODO state cycling (click to toggle)
  • Tag/property editing
  • Syntax highlighting for bodies

Phase 4: Agenda

  • Dedicated agenda view panel
  • Day/week/month views
  • Filtering and sorting
  • Custom views

Phase 5: Advanced Features

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

License

GPL-3.0-or-later