Many thanks for the pointers, Ihor!

The instructions were clear and concise, so the patch creation went
smoothly. Results attached below.

I cloned the Org repository from git://git.sv.gnu.org/emacs/org-mode.git
and followed the instructions at
https://orgmode.org/worg/org-contribute.html#first-patch. I hope I
succeeded for most part. ;-)

`make compile` didn't complain at all, and `make test` ended with the
following:

---------------------------- Begin Quote -----------------------------
Ran 1254 tests, 1238 results as expected, 4 unexpected, 12 skipped (2024-04-15 
18:39:50+0200, 57.383197 sec)
2 expected failures

4 unexpected results:
   FAILED  ob-calc/matrix-inversion  ((should (equal "[[-1, 0.625, -0.125], 
[0.25, -0.5, 0.25], [0.5, 0.125, -0.125]]" (org-babel-execute-src-block))) 
:form (equal "[[-1, 0.625, -0.125], [0.25, -0.5, 0.25], [0.5, 0.125, -0.125]]" 
"[[-1, 625e-3, -125e-3], [250e-3, -500e-3, 250e-3], [500e-3, 125e-3, 
-125e-3]]") :value nil :explanation (arrays-of-different-length 63 77 "[[-1, 
0.625, -0.125], [0.25, -0.5, 0.25], [0.5, 0.125, -0.125]]" "[[-1, 625e-3, 
-125e-3], [250e-3, -500e-3, 250e-3], [500e-3, 125e-3, -125e-3]]" 
first-mismatch-at 6))
   FAILED  test-ob-shell/bash-uses-assoc-arrays  ((should (equal "two" 
(org-trim (org-babel-execute-src-block)))) :form (equal "two" "three") :value 
nil :explanation (arrays-of-different-length 3 5 "two" "three" 
first-mismatch-at 1))
   FAILED  test-ob-shell/bash-uses-assoc-arrays-with-lists  ((should (equal "20 
cm" (org-trim (org-babel-execute-src-block)))) :form (equal "20 cm" "50 dl") 
:value nil :explanation (array-elt 0 (different-atoms (50 "#x32" "?2") (53 
"#x35" "?5"))))
   FAILED  test-org-table/sort-lines  ((should (equal "| a | x |\n| B | 4 |\n| 
c | 3 |\n" (org-test-with-temp-text "| <point>a | x |\n| c | 3 |\n| B | 4 |\n" 
(org-table-sort-lines nil 97) (buffer-string)))) :form (equal "| a | x |\n| B | 
4 |\n| c | 3 |\n" #("| B | 4 |\n| a | x |\n| c | 3 |\n" 0 9 (face org-table) 9 
10 (face org-table-row) 10 19 (face org-table) 19 20 (face org-table-row) 20 29 
(face org-table) 29 30 (face org-table-row))) :value nil :explanation 
(array-elt 2 (different-atoms (97 "#x61" "?a") (66 "#x42" "?B"))))

12 skipped results:
  SKIPPED  org-missing-dependency/test-ob-R  ((skip-unless nil) :form nil 
:value nil)
  SKIPPED  org-missing-dependency/test-ob-clojure  ((skip-unless nil) :form nil 
:value nil)
  SKIPPED  org-missing-dependency/test-ob-haskell-ghci  ((skip-unless nil) 
:form nil :value nil)
  SKIPPED  org-missing-dependency/test-ob-julia  ((skip-unless nil) :form nil 
:value nil)
  SKIPPED  org-missing-dependency/test-ob-lua  ((skip-unless nil) :form nil 
:value nil)
  SKIPPED  org-missing-dependency/test-ob-maxima  ((skip-unless nil) :form nil 
:value nil)
  SKIPPED  org-missing-dependency/test-ob-octave  ((skip-unless nil) :form nil 
:value nil)
  SKIPPED  org-missing-dependency/test-ob-python  ((skip-unless nil) :form nil 
:value nil)
  SKIPPED  org-missing-dependency/test-ob-ruby  ((skip-unless nil) :form nil 
:value nil)
  SKIPPED  org-missing-dependency/test-ob-scheme  ((skip-unless nil) :form nil 
:value nil)
  SKIPPED  org-missing-dependency/test-org-attach-git  ((skip-unless nil) :form 
nil :value nil)
  SKIPPED  test-org-fold/org-fold-display-inline-images  ((skip-unless (not 
noninteractive)) :form (not t) :value nil)

make: *** [test] Error 1
----------------------------- End Quote ------------------------------

At first glance, nothing seems to point into a direction suggesting that
I had broken anything (i.e. nothing about any breakage relating to
columnview)?


Many thanks and looking forward to your thoughts,

  --alexander


>From c21b18475dd154eed8d3f2489daa5a468531dc82 Mon Sep 17 00:00:00 2001
From: Alexander Adolf <alexander.ad...@condition-alpha.com>
Date: Sun, 14 Apr 2024 18:14:05 +0200
Subject: [PATCH 1/2] lisp/org-colview.el: add formatter parameter to colview
 dynamic block

* lisp/org-colview.el (org-dblock-write:column view): Factor out the
existing formatting code to new function
org-columns-dblock-write-default, and honour new dblock parameter
:formatter for specifying a different formatting function.
(org-columns-dblock-write-default): New function with current
formatting code.
(org-columns--capture-view): Amend docstring to better explain the
format of the data being passed to the formatting function.
(org-clock-clocktable-formatter): New option to define a global
default formatting function, defaulting to the current behaviour.
* doc/org-manual.org (Capturing column view): Describe new :formatter
parameter.
* etc/ORG-NEWS (New option ~org-columns-dblock-formatter~): Announce
new option.
(=colview= dynamic block supports custom formatting function):
Describe new custom formatting function feature.
---
 doc/org-manual.org  |  6 ++++++
 etc/ORG-NEWS        | 26 ++++++++++++++++++++++++++
 lisp/org-colview.el | 38 ++++++++++++++++++++++++++++++++------
 3 files changed, 64 insertions(+), 6 deletions(-)

diff --git a/doc/org-manual.org b/doc/org-manual.org
index 6c699ae1e..e66e48cda 100644
--- a/doc/org-manual.org
+++ b/doc/org-manual.org
@@ -6012,6 +6012,12 @@ This dynamic block has the following parameters:
   Specify a column attribute (see [[*Column attributes]]) for the dynamic
   block.
 
+- =:formatter= ::
+
+  A function for formatting the data in the dynamic block, overriding
+  the default formatting function set in
+  ~org-columns-dblock-formatter~.
+
 The following commands insert or update the dynamic block:
 
 - ~org-columns-insert-dblock~ ::
diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index e61bd6988..eab181bc3 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -999,6 +999,16 @@ even though it does not have its own ID.  By giving files top-level id
 properties, links to headlines in the file can also be made more
 robust by using the file id instead of the file path.
 
+*** New option ~org-columns-dblock-formatter~
+
+=colview= dynamic blocks now understand a new ~:formatter~ parameter
+to use a specific function for formatting the contents of the dynamic
+block. This new option can be used to set the global default
+formatting function that will be used for =colview= dynamic blocks
+that do not specify any ~:formatter~ parameter. Its default value (the
+new function ~org-columns-dblock-write-default~) yields the previous
+(fixed) formatting behaviour.
+
 ** New features
 *** =colview= dynamic block now writes column width specifications
 
@@ -1030,6 +1040,22 @@ Example:
 : | PROYECTO EMACS |
 : #+END:
 
+*** =colview= dynamic block supports custom formatting function
+
+The =colview= dynamic block understands a new ~:formatter~ parameter,
+which specifies a user-supplied function to format the data in the
+dynamic block.
+
+A global default formatting function for =colview= dynamic blocks can
+be set via the new option ~org-columns-dblock-formatter~ which
+defaults to the new function ~org-columns-dblock-write-default~, that
+implements the previous (fixed) formatting behaviour. Hence, the
+default behaviour is identical to previous versions.
+
+The global default function can be overridden for any given =colview=
+dynamic block individually by specifying a custom formatter function
+using the new ~:formatter~ parameter on the block's =BEGIN= line.
+
 *** =ob-tangle.el=: New flag to remove tangle targets before writing
 
 When ~org-babel-tangle-remove-file-before-write~ is set to ~t~ the
diff --git a/lisp/org-colview.el b/lisp/org-colview.el
index 4718d1db7..5c908affe 100644
--- a/lisp/org-colview.el
+++ b/lisp/org-colview.el
@@ -123,6 +123,13 @@ in `org-columns-summary-types-default', which see."
 			      (function :tag "Summarize")
 			      (function :tag "Collect")))))
 
+(defcustom org-columns-dblock-formatter #'org-columns-dblock-write-default
+  "Function to format data in column view dynamic blocks.
+For more information, see `org-columns-dblock-write-default'."
+  :group 'org-properties
+  :version "30.0"
+  :package-version '(Org . "9.7")
+  :type 'function)
 
 
 ;;; Column View
@@ -1442,9 +1449,13 @@ that will be excluded from the resulting view.  FORMAT is a
 format string for columns, or nil.  When LOCAL is non-nil, only
 capture headings in current subtree.
 
-This function returns a list containing the title row and all
-other rows.  Each row is a list of fields, as strings, or
-`hline'."
+This function returns a list containing the title row and all other
+rows.  Each row is either a list, or the symbol `hline'.  The first list
+is the heading row as a list of strings with the column titles according
+to FORMAT.  All subsequent lists each represent a body row as a list
+whose first element is an integer indicating the outline level of the
+entry, and whose remaining elements are strings with the contents for
+the columns according to FORMAT."
   (org-columns (not local) format)
   (goto-char org-columns-top-level-marker)
   (let ((columns (length org-columns-current-fmt-compiled))
@@ -1545,8 +1556,13 @@ PARAMS is a property list of parameters:
 `:vlines'
 
     When non-nil, make each column a column group to enforce
-    vertical lines."
-  (let ((table
+    vertical lines.
+
+`:formatter'
+
+    A function to format the data and insert it into the buffer."
+  (let ((insert-pos (point))
+        (table
 	 (let ((id (plist-get params :id))
 	       view-file view-pos)
 	   (pcase id
@@ -1573,7 +1589,17 @@ PARAMS is a property list of parameters:
 					 (plist-get params :exclude-tags)
 					 (plist-get params :format)
 					 view-pos)))))
-        (width-specs
+        (formatter (or (plist-get params :formatter)
+                       org-columns-dblock-formatter
+                       #'org-columns-dblock-write-default)))
+    (funcall formatter insert-pos table params)))
+
+(defun org-columns-dblock-write-default (ipos table params)
+  "Write out a columnview table at position IPOS in the current buffer.
+TABLE is a table with data as produced by `org-columns--capture-view'.
+PARAMS is the parameter property list obtained from the dynamic block
+definition."
+  (let ((width-specs
          (mapcar (lambda (spec) (nth 2 spec))
                  org-columns-current-fmt-compiled)))
     (when table
-- 
2.39.3 (Apple Git-146)

>From 4d69c3407c7c00fe0a1f52c383ced572f3524076 Mon Sep 17 00:00:00 2001
From: Alexander Adolf <alexander.ad...@condition-alpha.com>
Date: Mon, 15 Apr 2024 18:01:40 +0200
Subject: [PATCH 2/2] lisp/org-colview.el: add link parameter to colview
 dynamic block

* lisp/org-colview.el (org-columns--capture-view): Add new link
parameter, which when non-nil causes ITEM headlines to be linked to
their origins.
(org-dblock-write:columnview): Pass new link parameter to
org-columns--capture-view, and explain its use in the docstring.
* doc/org-manual.org (Capturing column view): Describe new :link
parameter.
* etc/ORG-NEWS (=colview= dynamic block can link to headlines):
Describe new link feature.
---
 doc/org-manual.org  |  5 +++++
 etc/ORG-NEWS        |  6 ++++++
 lisp/org-colview.el | 34 ++++++++++++++++++++++++----------
 3 files changed, 35 insertions(+), 10 deletions(-)

diff --git a/doc/org-manual.org b/doc/org-manual.org
index e66e48cda..5e2549f49 100644
--- a/doc/org-manual.org
+++ b/doc/org-manual.org
@@ -6007,6 +6007,11 @@ This dynamic block has the following parameters:
 
   When non-~nil~, indent each =ITEM= field according to its level.
 
+- =:link= ::
+
+  When non-~nil~, link the =ITEM= headlines in the table to their
+  origins.
+
 - =:format= ::
 
   Specify a column attribute (see [[*Column attributes]]) for the dynamic
diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index eab181bc3..449487ac0 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -1056,6 +1056,12 @@ The global default function can be overridden for any given =colview=
 dynamic block individually by specifying a custom formatter function
 using the new ~:formatter~ parameter on the block's =BEGIN= line.
 
+*** =colview= dynamic block can link to headlines
+
+The =colview= dynamic block understands a new ~:link~ parameter, which
+when non-~nil~ causes =ITEM= headlines in the table to be linked to
+their origins.
+
 *** =ob-tangle.el=: New flag to remove tangle targets before writing
 
 When ~org-babel-tangle-remove-file-before-write~ is set to ~t~ the
diff --git a/lisp/org-colview.el b/lisp/org-colview.el
index 5c908affe..1771283f2 100644
--- a/lisp/org-colview.el
+++ b/lisp/org-colview.el
@@ -1439,15 +1439,15 @@ and variances (respectively) of the individual estimates."
 
 ;;; Dynamic block for Column view
 
-(defun org-columns--capture-view (maxlevel match skip-empty exclude-tags format local)
+(defun org-columns--capture-view (maxlevel match skip-empty exclude-tags link format local)
   "Get the column view of the current buffer.
 
-MAXLEVEL sets the level limit.  SKIP-EMPTY tells whether to skip
-empty rows, an empty row being one where all the column view
-specifiers but ITEM are empty.  EXCLUDE-TAGS is a list of tags
-that will be excluded from the resulting view.  FORMAT is a
-format string for columns, or nil.  When LOCAL is non-nil, only
-capture headings in current subtree.
+MAXLEVEL sets the level limit.  SKIP-EMPTY tells whether to skip empty
+rows, an empty row being one where all the column view specifiers but
+ITEM are empty.  EXCLUDE-TAGS is a list of tags that will be excluded
+from the resulting view.  When LINK is non-nil, item headlines will be
+linked to their origins.  FORMAT is a format string for columns, or nil.
+When LOCAL is non-nil, only capture headings in current subtree.
 
 This function returns a list containing the title row and all other
 rows.  Each row is either a list, or the symbol `hline'.  The first list
@@ -1467,12 +1467,21 @@ the columns according to FORMAT."
 	 (let (row)
 	   (dotimes (i columns)
 	     (let* ((col (+ (line-beginning-position) i))
-		    (p (get-char-property col 'org-columns-key)))
-	       (push (org-quote-vert
+		    (p (get-char-property col 'org-columns-key))
+		    (cell-content
+		     (org-quote-vert
 		      (get-char-property col
 					 (if (string= p "ITEM")
 					     'org-columns-value
-					   'org-columns-value-modified)))
+					   'org-columns-value-modified)))))
+	       (push (if (and link (string= p "ITEM"))
+			 (let ((search (org-link-heading-search-string
+					cell-content)))
+			   (org-link-make-string
+			    (if (not (buffer-file-name)) search
+			      (format "file:%s::%s" (buffer-file-name) search))
+			    cell-content))
+		       cell-content)
 		     row)))
 	   (unless (or
 		    (and skip-empty
@@ -1558,6 +1567,10 @@ PARAMS is a property list of parameters:
     When non-nil, make each column a column group to enforce
     vertical lines.
 
+`:link'
+
+    Link the item headlines in the table to their origins.
+
 `:formatter'
 
     A function to format the data and insert it into the buffer."
@@ -1587,6 +1600,7 @@ PARAMS is a property list of parameters:
 					 (plist-get params :match)
 					 (plist-get params :skip-empty-rows)
 					 (plist-get params :exclude-tags)
+					 (plist-get params :link)
 					 (plist-get params :format)
 					 view-pos)))))
         (formatter (or (plist-get params :formatter)
-- 
2.39.3 (Apple Git-146)

Reply via email to