emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
From: Sergei Kosyrev <kosejin@proton.me>
To: "emacs-orgmode@gnu.org" <emacs-orgmode@gnu.org>
Subject: [PATCH] org-id: implement arbitrary cross-file references
Date: Thu, 25 May 2023 12:29:56 +0000	[thread overview]
Message-ID: <iccUHPQoQP5Ob2AmNBGngaIGkX5yXZoW_LQ6W8xBurSKjtQP-GBUlRkLEvM-Px4ywUNoK-fUqhIx4lFwNCU52wHu1yWff-zrHTvqJw_3TTg=@proton.me> (raw)

[-- Attachment #1: Type: text/plain, Size: 341 bytes --]

Good day list!

This extends org-id in a way that allows table formulae to reference
table content in other files.

Patch is attached, and can be alternatively observed via github:

https://github.com/deepfire/org-mode/pull/1/files

This is my first contribution, so caveat emptor!

Thank you!

-- 
best regards,
Serge Kosyrev

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-org-id-implement-arbitrary-cross-file-references.patch --]
[-- Type: text/x-patch; name=0001-org-id-implement-arbitrary-cross-file-references.patch, Size: 4967 bytes --]

From f712fa57a90c68d3d9066b10f49822ea0337b923 Mon Sep 17 00:00:00 2001
From: Kosyrev Serge <serge.kosyrev@iohk.io>
Date: Thu, 25 May 2023 19:30:01 +0800
Subject: [PATCH] org-id: implement arbitrary cross-file references

* Table formulae can now refer to data from tables in other files.

TINYCHANGE
---
 etc/ORG-NEWS      | 10 +++++++++
 lisp/org-id.el    | 57 ++++++++++++++++++++++++++++++++++++++---------
 lisp/org-table.el |  2 +-
 3 files changed, 58 insertions(+), 11 deletions(-)

diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index 6b40198b5..311067628 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -221,6 +221,16 @@ Running shell blocks with the ~:session~ header freezes Emacs until
 execution completes.  The new ~:async~ header allows users to continue
 editing with Emacs while a ~:session~ block executes.
 
+*** ~remote~ ~org-table~ can now refer to variables in other files
+
+Table formulae can now refer to data from tables in other files.
+
+Example:
+
+#+BEGIN_src org
+#+TBLFM: $2='(identity remote(file:./org-wile-with-tables.org,@@#$Value))
+#+END_src
+
 ** Miscellaneous
 *** =org-crypt.el= now applies initial visibility settings to decrypted entries
 
diff --git a/lisp/org-id.el b/lisp/org-id.el
index aa9610f16..2fcecbb50 100644
--- a/lisp/org-id.el
+++ b/lisp/org-id.el
@@ -337,6 +337,40 @@ Move the cursor to that entry in that buffer."
     (move-marker m nil)
     (org-fold-show-context)))
 
+(defun org-id-parse-remote-table-ref (refstr)
+  (let ((match (string-match "^file:\\([^:]+\\)\\(\\|:.+\\)$" refstr)))
+    (unless (null match)
+      (let* ((m1 (match-string 1 refstr))
+             (m2 (match-string 2 refstr))
+             (filename (cl-remove-if (lambda (c) (member c '(40 41)))
+                                  (org-table-formula-substitute-names m1)))
+             (table-name (org-table-formula-substitute-names m2)))
+        (list filename table-name)))))
+
+(defun org-id-find-remote (file table-id markerp)
+  (if (file-exists-p file)
+      (let ((buffer (let ((query-about-changed-file nil))
+                      (find-file-noselect file))))
+        (unwind-protect
+	    (with-current-buffer buffer
+              (goto-char (point-min))
+	      (let ((pos (progn
+                           (unless (string= table-id "")
+                             (let* ((ident (cl-subseq table-id 1))
+                                    (id-match (search-forward (concat "#+NAME: " ident) nil t)))
+                               (unless id-match
+                                 (error "org-id-find-remote: file \"%s\" has no table with NAME \"%s\"." file ident))
+                               (forward-line)))
+                           (re-search-forward "^|-")
+                           (move-beginning-of-line nil))))
+                (cond
+	         ((null pos) nil)
+	         (markerp (move-marker (make-marker) pos buffer))
+	         (t (cons file pos)))))
+	  ;; Remove opened buffer in the process.
+	  (unless markerp (kill-buffer buffer))))
+    (error "org-id-find-remote:  reference to missing file %s" file)))
+
 ;;;###autoload
 (defun org-id-find (id &optional markerp)
   "Return the location of the entry with the id ID.
@@ -346,16 +380,19 @@ With optional argument MARKERP, return the position as a new marker."
   (cond
    ((symbolp id) (setq id (symbol-name id)))
    ((numberp id) (setq id (number-to-string id))))
-  (let ((file (org-id-find-id-file id))
-	org-agenda-new-buffers where)
-    (when file
-      (setq where (org-id-find-id-in-file id file markerp)))
-    (unless where
-      (org-id-update-id-locations nil t)
-      (setq file (org-id-find-id-file id))
-      (when file
-	(setq where (org-id-find-id-in-file id file markerp))))
-    where))
+  (let ((remote-match (org-id-parse-remote-table-ref id)))
+    (if remote-match
+        (org-id-find-remote (car remote-match) (cadr remote-match) markerp)
+      (let ((file (org-id-find-id-file id))
+	    org-agenda-new-buffers where)
+        (when file
+          (setq where (org-id-find-id-in-file id file markerp)))
+        (unless where
+          (org-id-update-id-locations nil t)
+          (setq file (org-id-find-id-file id))
+          (when file
+	    (setq where (org-id-find-id-in-file id file markerp))))
+        where))))
 
 ;;; Internal functions
 
diff --git a/lisp/org-table.el b/lisp/org-table.el
index ac685c41e..e894d563a 100644
--- a/lisp/org-table.el
+++ b/lisp/org-table.el
@@ -6281,7 +6281,7 @@ list of the fields in the rectangle."
     (let ((case-fold-search t) (id-loc nil)
 	  ;; Protect a bunch of variables from being overwritten by
 	  ;; the context of the remote table.
-	  org-table-column-names org-table-column-name-regexp
+          org-table-column-names (org-table-column-name-regexp org-table-column-name-regexp)
 	  org-table-local-parameters org-table-named-field-locations
 	  org-table-current-line-types
 	  org-table-current-begin-pos org-table-dlines
-- 
2.40.1


             reply	other threads:[~2023-06-06 12:44 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-05-25 12:29 Sergei Kosyrev [this message]
2023-05-27 12:51 ` [PATCH] org-id: implement arbitrary cross-file references Sergei Kosyrev
2023-05-27 13:51   ` Ruijie Yu via General discussions about Org-mode.
2023-05-27 15:19     ` Sergei Kosyrev
2023-05-29  8:52       ` Ihor Radchenko
2023-07-02 10:58         ` Ihor Radchenko
2023-07-02 13:51           ` Sergei Kosyrev
2023-07-02 15:39             ` Ihor Radchenko
2023-10-02 13:36               ` Ihor Radchenko
2024-04-07  9:52                 ` Ihor Radchenko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.orgmode.org/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='iccUHPQoQP5Ob2AmNBGngaIGkX5yXZoW_LQ6W8xBurSKjtQP-GBUlRkLEvM-Px4ywUNoK-fUqhIx4lFwNCU52wHu1yWff-zrHTvqJw_3TTg=@proton.me' \
    --to=kosejin@proton.me \
    --cc=emacs-orgmode@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).