Parse the :results switch from a src block's header arguments and apply
Emacs org-babel semantics when writing results:
- silent/none: execute and report, but do not write a #+RESULTS: block
- raw: insert output verbatim, no prefix or wrapping
- drawer: wrap output in a :results: ... 🔚 drawer
- default: fixed-width for <10 lines, #+begin_example for 10+
The insert_results detection loop now recognizes and replaces all four
wrapping styles in place, so re-execution and cross-mode transitions
(e.g. drawer to fixed-width) update cleanly without duplication. Raw
results, which have no delimiters, terminate at a blank line or heading.
Expose the language registry via ctl: `languages` lists supported src
block languages (one per line), `reload-languages` reloads plugin configs
from /etc/orkmode/languages and ~/.config/orkmode/languages and reports
how many were loaded.
Code execution now uses a LanguageRegistry with built-in defaults
(bash, python, ruby, perl, javascript) that can be overridden by TOML
config files in /etc/orkmode/languages or ~/.config/orkmode/languages.
Match Emacs org-babel result formatting: fixed-width (": " prefix) for
output under 10 lines, #+begin_example blocks for 10+ lines
(org-babel-min-lines-for-block-output).
Fix insert_results duplication: the source block span end already points
to the start of the line after #+END_SRC, so searching for the next
newline skipped the existing #+RESULTS: line and prepended duplicates on
re-execution. Also handle replacing existing #+begin_example result blocks.
Fix parser: #+begin_example, comment, and export blocks were misparsed as
SourceBlock with a bogus language, causing "unsupported language" errors
on re-execution. Map them to their correct AST element kinds.
- Execute returns results and writes them to the org file
- Replaces existing #+RESULTS: block if present
- Results formatted with : prefix per org convention
- Process blocks in reverse order to preserve byte offsets
- Blank line added after results for proper separation
- execute <doc> — all blocks in document
- execute <doc> <section> — all blocks in subtree
- execute <doc> <section> <idx> — single block by index
- execute <doc> <section> <name> — block by #+NAME in section
- execute <doc> :<name> — named block anywhere in doc
Parser now extracts #+NAME: from block's affiliated keywords.
Supports bash, python, ruby, perl, and node interpreters.
Basic sandboxing via env_clear() and restricted PATH.
- Use 'contains' instead of 'starts_with' to handle combined lines
like 'SCHEDULED: <...> DEADLINE: <...>'
- Track 'seen_content' to strip planning/drawers only at the start
- Skip empty lines before content
- Continue stripping planning lines until real content appears
section_body() now filters out:
- Leading planning line (SCHEDULED/DEADLINE/CLOSED)
- Property drawers (:PROPERTIES: ... :END:)
- Any other drawers (:LOGBOOK:, etc.)
- Leading/trailing blank lines
These are displayed separately in the UI.
Dropping the C FFI layer left orkmode-core unused: nothing in the
workspace depends on it, and the GUI will speak 9P instead. Delete the
crate, drop it from the workspace, and scrub FFI references from the
docs (README structure/usage, AGENTS structure/FFI/next-steps).
Client verbs for the new server capabilities, each a thin wrapper over
the base 9P operations: the structural verbs write to /ctl, and query
writes to /query and prints the matches.
Rework /ctl into a self-describing dispatch table (name, desc, fn),
inspired by the ollie 9P server: an empty write or "help" lists the
verbs, and unknown verbs report the valid set.
New control verbs, each operating on a section subtree:
- rm: delete a section and its subtree
- move up|down: reorder among siblings
- promote/demote: shift the subtree's outline level
- refile <to-doc> [parent]: move a subtree across or within documents,
re-leveling to the target depth
- archive: move a subtree to the companion <doc>.org_archive file
- lint [doc]: reparse and report per document
Add a root /query file (rdwr): write a tag:X+todo:Y+priority:Z match
expression, read back matching sections.
Implement the previously stubbed agenda today/week views with real date
filtering, using a dependency-free civil-date day-number calculation.
Subtree edits share span-based helpers (subtree_range, sibling_ranges,
shift_headline_levels, insert_at). Covered by unit tests.
Four more friendly verbs, all pure compositions of the base 9P
operations against the existing namespace (no server change):
- tag <doc> <id> <tag> [--remove]: toggle a single tag, mirroring
org-toggle-tag, instead of rewriting the whole tag list.
- prop <doc> <id> <key> [value] [--delete]: get, set, or delete one
property, mirroring org-set-property, instead of the whole drawer.
- todo <doc> <id> [state]: set the keyword, or with no argument cycle
to the next state following the /keywords sequence, like org-todo.
- tree <doc>: print the recursive section outline.
Each edit reads the relevant namespace file, modifies it, and writes it
back; all validate the section exists first for a clear error.
ork now operates solely as a 9P client against ork-server; all org
intelligence lives in the server. Remove the local file-parsing command
layer (commands.rs) and its org-ast/org-parser/orkmode-core/serde deps.
Base verbs speak raw 9P: ls, read, write, rdwr. Address resolves from
--addr, then $ORK_ADDR, then tcp://localhost:5640.
Add friendly commands, all thin compositions of the base 9P operations:
docs, sections, todos, agenda, get, set, add (--parent), mkdoc, reload.
Fix the directory-listing parser in client.rs: the stat-entry name offset
double-counted the size field (pos + 2 + 41 instead of pos + 41), so ls
returned nothing. Handle a downstream reader closing early (e.g. | head)
by treating BrokenPipe as a clean exit instead of panicking.
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.
- set_section_keyword/priority/title/tags
- set_section_scheduled/deadline/closed
- set_section_properties/body
- rebuild_headline helper for atomic headline updates
- Fixed replace_headline to preserve DEADLINE/:PROPERTIES: lines
- Clear read cache on write in 9P server
All writes tested working via 9p client.
Simple 9P2000 client supporting:
- Connect via Unix socket or TCP
- read/write/rdwr operations
- Directory listing
Preparation for reworking CLI to use 9P server.
- new file at root: create org file
- new file at doc level: create top-level section
- new file at section level: create child section
- All created sections get UUID in :ID: property
- body file added to doc (alias for raw)
- Test for section creation via 9P namespace