Go to file
Levi Neely 0a06ca60bf Fix drag-to-refile: ListView stole the grip's drag
The grip used a bare MouseArea for the drag. Inside the ListView (a
Flickable), once the pointer moved past the drag threshold the ListView
stole the gesture for flicking, so the grip's positionChanged stopped
firing: the drop target was never resolved and release did nothing.

Replace the MouseArea with a DragHandler (target: null — it tracks, it
doesn't move the item) whose grabPermissions take the pointer grab and
refuse to yield it to the Flickable, so the drag is no longer stolen. It
reports centroid.scenePosition continuously, mapped to ListView content
coordinates via contentItem.mapFromScene, driving the same updateDrop/
commitDrop path. A HoverHandler keeps the hover affordance, and the grip
gets a slightly larger hit target.

QML compiles (AOT cache build of OutlineView). The drop resolution and
refile commit paths were already verified; this restores the gesture
that feeds them.
2026-10-02 16:57:18 +02:00
crates Add drag-and-drop structural moves with a live drop indicator 2026-10-02 16:00:54 +02:00
doc Add complete section properties to 9P namespace 2026-09-30 14:16:18 +02:00
ui Fix drag-to-refile: ListView stole the grip's drag 2026-10-02 16:57:18 +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 Add in-place body editing with timestamp insertion 2026-10-02 15:18:08 +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