Update org-api.el to use org-agenda-api package

- Replace custom endpoint code with org-agenda-api require
- Add gtd-todo, scheduled-todo, and tagged-todo capture templates
- Custom commands from init.el will be available via /custom-views

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-14 09:45:24 -08:00
parent 3e9f67c432
commit 5304640c79

View File

@@ -1,91 +1,43 @@
;;; org-api.el --- org-agenda-api server configuration -*- lexical-binding: t; -*-
;; Load main emacs config to get org settings, custom commands, etc.
(let ((current-dir (if load-file-name (file-name-directory load-file-name) "~/.emacs.d/"))) (let ((current-dir (if load-file-name (file-name-directory load-file-name) "~/.emacs.d/")))
(load (expand-file-name "init.el" current-dir))) (load (expand-file-name "init.el" current-dir)))
(use-package simple-httpd ;; Ensure dependencies are loaded
:demand t)
(require 'simple-httpd) (require 'simple-httpd)
(require 'org-agenda-api)
(defun org-api-get-todo-elements-from-filepath (filepath) ;; Configure capture templates for the API
(let ((todo-elements nil)) ;; These use the org-agenda-api format with :prompts for API parameters
(with-current-buffer (find-file-noselect filepath) (setq org-agenda-api-capture-templates
(save-excursion `(("gtd-todo"
(goto-char (point-min)) :name "GTD Todo"
(while (re-search-forward org-todo-regexp nil t) :template ("t" "Todo" entry (file "~/org/inbox.org")
(let* ((element (org-element-at-point)) (function (lambda ()
(type (org-element-type element))) (imalison:make-org-todo-template :content "%^{Title}")))
(when (eq type 'headline) :immediate-finish t)
(let ((todo (org-element-property :todo-keyword element))) :prompts (("Title" :type string :required t)))
(when todo ("scheduled-todo"
(push element todo-elements)))))))) :name "Scheduled Todo"
todo-elements)) :template ("s" "Scheduled" entry (file "~/org/inbox.org")
"* TODO %^{Title}\nSCHEDULED: %^{When}t\n"
:immediate-finish t)
:prompts (("Title" :type string :required t)
("When" :type date :required t)))
("tagged-todo"
:name "Tagged Todo"
:template ("g" "Tagged" entry (file "~/org/inbox.org")
"* TODO %^{Title} %^{Tags}g\n"
:immediate-finish t)
:prompts (("Title" :type string :required t)
("Tags" :type tags :required nil)))))
(defun org-api-get-agenda-todos () ;; Configure the server
(let* ((today (calendar-gregorian-from-absolute (org-today)))) (setq org-agenda-api-port 2025)
(mapcan 'org-api-get-todo-elements-from-filepath org-agenda-files))) (setq org-agenda-api-inbox-file "~/org/inbox.org")
(defun org-api-get-element-json (element) ;; Start the server
(let ((todo (org-element-property :todo-keyword element)) (message "Starting org-agenda-api server on port %d" org-agenda-api-port)
(title (org-element-property :raw-value element)) (org-agenda-api-start)
(tags (org-element-property :tags element)) (message "org-agenda-api server started")
(level (org-element-property :level element))
(scheduled (org-element-property :scheduled element))
(deadline (org-element-property :deadline element)))
`(("todo" . ,todo)
("title" . ,title)
("tags" . ,tags)
("level" . ,level)
("scheduled" . ,(when scheduled (org-format-timestamp scheduled "%Y-%m-%dT%H:%M:%SZ")))
("deadline" . ,(when deadline (org-format-timestamp deadline "%Y-%m-%dT%H:%M:%SZ"))))))
(defun org-api-item-json (item)
(let* ((todo (get-text-property 0 'todo-state item))
(title (substring-no-properties item))
(tags (get-text-property 0 'tags item))
(s (get-text-property 0 'ts-date item))
(scheduled (when s
(org-format-timestamp (org-time-from-absolute s) "%Y-%m-%dT%H:%M:%SZ") )))
`(("todo" . ,todo)
("title" . ,title)
("tags" . ,tags))))
(defun org-api-get-scheduled-or-deadlined (day filepath)
(with-current-buffer (find-file-noselect filepath)
(org-dlet ((date day))
(setf org-agenda-current-date date)
(nconc (org-agenda-get-deadlines) (org-agenda-get-scheduled)))))
(defun org-api-get-today-agenda ()
(let ((day (calendar-current-date)))
(mapcan (lambda (filepath) (org-api-get-scheduled-or-deadlined day filepath))
org-agenda-files)))
(defservlet get-all-todos application/json ()
(insert (json-encode (mapcar 'org-api-get-element-json (org-api-get-agenda-todos)))))
(defservlet get-todays-agenda application/json ()
(insert
(json-encode
(mapcar 'org-api-item-json
(org-api-get-today-agenda)))))
(defservlet create-todo application/json (a b c)
(org-api-capture (gethash "title" (json-parse-string (cadr (assoc "Content" c))))))
(cl-defun org-api-build-capture-template
(content &key (character "d") (heading "Dynamic"))
`(,character ,heading entry (file "~/org/inbox.org")
(function (lambda ()
(imalison:make-org-todo-template :content content)))
:immediate-finish t))
(defun org-api-capture (content)
(let* ((org-capture-templates (list (org-api-build-capture-template content))))
(org-capture nil "d")))
(message "Starting http server")
(setq httpd-port 2025)
(httpd-start)
(message "Finished starting http server")