Go to file
Levi Neely 70ec9509a4 Replace TreeView with ListView for document outline
TreeView (inherits TableView) is designed for file browsers with fixed row
heights, not structured document editing. ListView gives us:
- Full control over row heights (implicitHeight just works)
- Simpler delegate without TreeViewDelegate quirks
- Manual indentation via leftMargin based on level
- Expansion state tracked in model with hasChildren/expanded roles
- Click-to-expand triangles for sections with children

DocumentModel changed from QAbstractItemModel (tree) to QAbstractListModel
(flat list) with sections ordered depth-first. Tree structure preserved via
level, parentId, childIds fields. Expansion state controls visibility.
2026-10-01 09:32:56 +02:00
crates Clean up docs and fix set_planning_field 2026-10-01 08:53:22 +02:00
doc Add complete section properties to 9P namespace 2026-09-30 14:16:18 +02:00
ui Replace TreeView with ListView for document outline 2026-10-01 09:32:56 +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 Remove dead orkmode-core (FFI) crate 2026-09-30 22:27:50 +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 Update Makefile to install all targets 2026-10-01 08:58:42 +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
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
│   ├── 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