#+title:      Trot: TRAMP Org Noter integration

 
* Usage

Remember to configure the hook in order to actually enable this functionality:

#+BEGIN_SRC emacs-lisp :eval no
  ;; `add-hook' might be preferable.
  ;; I like to know that nothing else is going on.
  (setopt org-noter-open-document-functions '(trot-open))
#+END_SRC

* materials
:PROPERTIES:
:header-args: :results verbatim :cache yes
:END:

Org Noter prioritizes the hook ~org-noter-open-document-functions~.
There's nothing in it by default, so anything I put there will be called.
Its functions take one argument, the value of the org property specifying the file Noter should use.

** We'll need to determine whether or not the notes file itself is being accessed through TRAMP:

#+BEGIN_SRC emacs-lisp
  (cons (tramp-tramp-file-p "/home/ty/")
        (tramp-tramp-file-p "/ssh:tykozic.net:/home/ty/"))
#+END_SRC

#+RESULTS[093b86cb0c40f4208689e04a188d69d273b9e171]:
: (nil . t)

** If it is, parse it to obtain the TRAMP location

#+BEGIN_SRC emacs-lisp
  (tramp-dissect-file-name "/ssh:tykozic.net:/home/ty/")

  ;; causes error: not a tramp file name
  ;;(tramp-dissect-file-name "/home/ty/test.txt")
#+END_SRC

#+RESULTS[05e2e72c58c14b39e15c47b2632ab8f8059e92d2]:
: (tramp-file-name "ssh" nil nil "tykozic.net" nil "/home/ty/" nil)

** Assume no hops, and rebuild the file of the document

#+BEGIN_SRC emacs-lisp :eval no :noweb-ref code

  (defun trot-ensure-suffix (suffix str)
    (if (string-suffix-p suffix str)
        str
      (concat str suffix)))

  (defun trot-tramp-substitute-file (tramp-file-string new-local-name)
    (let ((old (tramp-dissect-file-name tramp-file-string)))
      (tramp-make-tramp-file-name
       old
       (if (file-name-absolute-p new-local-name)
  	 new-local-name
         (concat (trot-ensure-suffix "/" (tramp-file-name-localname old))
  	       new-local-name)))))
#+END_SRC

#+BEGIN_SRC emacs-lisp :noweb yes
  <<code>>

  (format "%s\n%s"
  	(trot-tramp-substitute-file
  	 "/ssh:ty@tykozic.net:/home/ty/sync"
  	 "ref/document.pdf")
  	(trot-tramp-substitute-file
  	 "/ssh:ty@tykozic.net:/home/ty/sync/"
  	 "/somewhere/else.epub"))
#+END_SRC

#+RESULTS[5e8cfbfce9b70405b730713bdb0936dd68d0c75b]:
: "/ssh:ty@tykozic.net:/home/ty/sync/ref/document.pdf
: /ssh:ty@tykozic.net:/somewhere/else.epub"

** But we won't use that file directly; we'll download a temporary copy and return its buffer

#+BEGIN_SRC emacs-lisp :eval no :noweb-ref code

  (defun trot-locally-accessible-copy (file)
    "Returns the path to a locally accessible copy of FILE.
  Therefore, if FILE is already accessible, returns FILE. Otherwise
  invokes TRAMP."
    (or (file-local-copy file)
        file))
#+END_SRC

* Putting it all together

#+BEGIN_SRC emacs-lisp :eval no :noweb-ref code

  (defun trot-open (doc-path)
    "Function for `org-noter-open-document-functions'.
  If the notes file is opened via TRAMP, open a local copy of the document
  file instead of attempting to open it using TRAMP. Otherwise, defer to
  org noter's fallback methods of opening it."
    (when (tramp-tramp-file-p default-directory)
      (find-file-noselect
       (trot-locally-accessible-copy
        (trot-tramp-substitute-file default-directory doc-path)))))
#+END_SRC

* Final tangle

#+BEGIN_SRC emacs-lisp :tangle trot.el :noweb yes
  ;;; trot.el --- TRAMP with Org Noter using local copies -*- lexical-binding: t; -*-

  ;; Copyright (C) 2025 Ty Kozic

  ;; Author: Ty Kozic <tykozic@posteo.net>
  ;; Created: 16 Nov 2025
  ;; URL: https://tykozic.net/fossil/emacs-trot

  ;; This file is not part of GNU Emacs.

  ;; Copyright 2025 Ty Kozic

  ;; This file is free software: you can redistribute it and/or modify
  ;; it under the terms of the GNU General Public License as published
  ;; by the Free Software Foundation, either version 3 of the License,
  ;; or (at your option) any later version. This file is distributed in
  ;; the hope that it will be useful, but WITHOUT ANY WARRANTY; without
  ;; even the implied warranty of MERCHANTABILITY or FITNESS FOR A
  ;; PARTICULAR PURPOSE. See the GNU General Public License for more
  ;; details. You should have received a copy of the GNU General Public
  ;; License along with this file. If not, see
  ;; <https://www.gnu.org/licenses/>.

  ;; Tangled from =trot.org=.
  <<code>>

  (provide 'trot)
  ;;; trot.el ends here
#+END_SRC
