name: emacs-org description: Use when working with Emacs org-mode - provides elisp patterns for headings, properties, tables, links, and org-mode manipulation
Emacs Org-Mode Skill
Display Guidelines
E-ink Monitor Compatibility: User uses an e-ink monitor that only supports black, white, and grey.
- NEVER use colors (
:foreground "red",:foreground "cyan", etc.) - Use
:weight bold,:weight light,:slant italic,:underline tfor differentiation - Standard Emacs faces (font-lock-*-face) are acceptable as they adapt to themes
Org Properties
Get property with inheritance
(org-entry-get nil "PROPERTY_NAME" t) ; t enables inheritance
Get property without inheritance
(org-entry-get nil "PROPERTY_NAME" nil)
Set property
(org-entry-put nil "PROPERTY_NAME" "value")
Safe property access (for header-line, mode-line contexts)
;; Wrap in ignore-errors when called from non-org-mode contexts
(ignore-errors
(org-entry-get nil "PROPERTY_NAME" t))
Headings Navigation
Go to heading
(org-back-to-heading t) ; t means error if not at heading
Walk up headings
(while (org-up-heading-safe)
;; process each parent heading
)
Check if at heading
(org-at-heading-p)
Get current level
(org-current-level) ; returns integer
Tags
Get tags for current heading
(org-get-tags nil t) ; returns list of strings
Check for specific tag
(member "my_tag" (org-get-tags nil t))
Subtree Operations
Get subtree end
(save-excursion
(org-end-of-subtree t t)
(point))
Map over entries with tag
(org-map-entries
(lambda ()
;; body executed at each matching heading
(org-entry-get nil "PROPERTY"))
"+my_tag")
File-Level Properties
Get file keyword (#+PROPERTY: NAME value)
(save-excursion
(goto-char (point-min))
(when (re-search-forward "^#\\+PROPERTY:\\s-+NAME\\s-+\\(.+\\)$" nil t)
(match-string 1)))
Tables
Move in table
(org-table-goto-column 2) ; go to column 2
(org-table-next-row) ; go to next row
Get cell value
(org-table-get-field) ; current cell
(org-table-get-field 3) ; column 3 of current row
Links
Parse link at point
(org-element-context) ; returns element with :path, :type properties
Create link
(org-link-make-string "https://example.com" "description")
Common Patterns
Safely get session info for mode-line
(defun my-get-session-id ()
"Get session ID safely from any context."
(ignore-errors
(save-excursion
(org-entry-get nil "SESSION_ID" t))))
Find heading with property value
(save-excursion
(goto-char (point-min))
(catch 'found
(while (re-search-forward "^\\*+ " nil t)
(when (equal "target" (org-entry-get nil "MY_PROP"))
(throw 'found (point))))
nil))
Insert property drawer
(org-back-to-heading t)
(forward-line 1)
(insert ":PROPERTIES:\n")
(insert ":MY_PROP: value\n")
(insert ":END:\n")
Error Prevention
Functions called from header-line or mode-line should wrap org-* calls:
;; BAD - will error in non-org buffers
(defun my-header-line ()
(org-entry-get nil "PROP" t))
;; GOOD - safe in any buffer
(defun my-header-line ()
(ignore-errors
(org-entry-get nil "PROP" t)))
CRITICAL: Async/Callback Context Warning
org-entry-get nil uses CURRENT cursor position!
In async callbacks (:on-complete, run-at-time, process filters), the cursor
may have moved. See /emacs-async skill for full patterns.
Quick Fix Pattern for Async
;; When called from async context with a marker:
(defun handle-async-result (session-key result)
(let ((marker (get-session-marker session-key)))
(when (marker-buffer marker)
(with-current-buffer (marker-buffer marker)
(save-excursion
(goto-char marker) ; Position cursor FIRST!
;; NOW org-entry-get works correctly
(org-entry-get nil "PROPERTY" t))))))
Common Bug Pattern
;; BUG: Called from async callback, cursor may be anywhere!
(defun bad-error-handler (error)
(let ((session-key (my-get-session-from-cursor))) ; WRONG!
(recover-session session-key)))
;; FIX: Pass session-key explicitly from the original call
(defun good-error-handler (session-key error)
(recover-session session-key))