Integrating Emacs and Hook, with org-mode

I think I have working Hookmark integration with the Doom Emacs config. It allows linking to text files in emacs. It also allows linking to org-mode tasks both from and org file and from the org-agenda. It likely can be improved…

Update “/opt/homebrew/bin/emacsclient” in the scripts below to the path that emacsclient is at. From a terminal type which emacsclient to know what to use.

Add the following code to Hookmark:

;; Open Item Script
do shell script "/opt/homebrew/bin/emacsclient --eval '(hookmark-open-address \"$0\")'"

Also add “org-hookmark” as the URL scheme.

;;Get Name Script

set emacsLink to do shell script "/opt/homebrew/bin/emacsclient --eval '(hookmark-get-name)'"
set newLink to text 2 thru -2 in emacsLink
return newLink

;; Get Address Script

set emacsLink to do shell script "/opt/homebrew/bin/emacsclient --eval '(hookmark-get-address)'"
set newLink to text 2 thru -2 in emacsLink
return newLink

This works for Doom Emacs. It’ll need to be adapted for other configs. Make sure emacs server is running.

Add the following to your Emacs config.

(after! org

;; Open `hook` links from org-mode files.
  (defun hookmark-org-link (link)
    "Create an org-link target string to LINK using `hook://` url scheme."
    (shell-command (concat "open hook:\"" link "\"")))

  (org-link-set-parameters "hook"
                           :follow #'hookmark-org-link)

;; Helper functions.
  (defun hookmark--org-todo-path nil
    (let ((address))
      (cond
       ((derived-mode-p 'org-agenda-mode)
        (let* ((col (current-column))
               (hdmarker (org-get-at-bol 'org-hd-marker))
               (buffer (marker-buffer hdmarker))
               (pos (marker-position hdmarker))
               (inhibit-read-only t))
          (org-with-remote-undo buffer
            (with-current-buffer buffer
              (widen)
              (goto-char pos)
              (org-fold-show-context 'agenda)
              (setq address (org-id-get-create)))
            (org-move-to-column col))))
       ((derived-mode-p 'org-mode)
        (setq address (org-id-get-create))))

      (princ address)))

  (defun hookmark--org-todo-todo nil
    (let ((todo))
      (cond
       ((derived-mode-p 'org-agenda-mode)
        (let* ((col (current-column))
               (hdmarker (org-get-at-bol 'org-hd-marker))
               (buffer (marker-buffer hdmarker))
               (pos (marker-position hdmarker))
               (inhibit-read-only t))
          (org-with-remote-undo buffer
            (with-current-buffer buffer
              (widen)
              (goto-char pos)
              (org-fold-show-context 'agenda)
              (setq todo (substring-no-properties (org-get-heading t t t t)))
              (org-move-to-column col)))))
       ((derived-mode-p 'org-mode)
        (setq todo (substring-no-properties (org-get-heading t t t t)))))

      (princ todo)))

;; Main functions.
  (defun hookmark-get-address nil
    "Get buffer path or org ID."
    (switch-to-buffer (car (buffer-list)))
    (cond
     ((or (derived-mode-p 'org-agenda-mode) (derived-mode-p 'org-mode))
      (princ (format "org-hookmark://%s"
                     (hookmark--org-todo-path))))
     (t
      (princ (format "%s" (buffer-file-name (car (buffer-list))))))
     ))

  (defun hookmark-get-name nil
    "Get buffer filename or org TODO text."
    (switch-to-buffer (car (buffer-list)))
    (cond
     ((or (derived-mode-p 'org-agenda-mode) (derived-mode-p 'org-mode))
      (princ (format "TODO %s"
                     (hookmark--org-todo-todo))))
     (t
      (princ (format "%s" (buffer-name (car (buffer-list))))))
     ))

  (defun hookmark-open-address (address)
    "Open ADDRESS provided by the Hookmark app."
    (org-link-open-from-string (format "[[id:%s]]" (nth 1 (split-string address "//"))))
    )
  )
1 Like