emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/embark ac79525732: Initial version of embark-org


From: ELPA Syncer
Subject: [elpa] externals/embark ac79525732: Initial version of embark-org
Date: Wed, 4 May 2022 20:57:31 -0400 (EDT)

branch: externals/embark
commit ac7952573272d05f150917cfeab6d0a4cef39a9a
Author: Omar Antolín <omar.antolin@gmail.com>
Commit: Omar Antolín <omar.antolin@gmail.com>

    Initial version of embark-org
---
 embark-org.el | 240 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 240 insertions(+)

diff --git a/embark-org.el b/embark-org.el
new file mode 100644
index 0000000000..30d76364af
--- /dev/null
+++ b/embark-org.el
@@ -0,0 +1,240 @@
+;;; embark-org.el --- Embark targets and actions for Org Mode  -*- 
lexical-binding: t; -*-
+
+;; Copyright (C) 2021  Omar Antolín Camarena
+
+;; Author: Omar Antolín Camarena <omar@matem.unam.mx>
+;; Keywords: convenience
+
+;; This program 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 program 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 program.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This package configures the Embark package for use in Org Mode
+;; buffers. It teaches Embark a number of Org related targets and
+;; appropriate actions. Currently it has table cells, whole tables,
+;; and links. Targets to add: headings (Embark already has generic
+;; support for outlines, so we just nee to add Org specific actions),
+;; dates, source blocks, etc.
+
+;;; Code:
+
+(require 'embark)
+(require 'org)
+
+;;; Tables
+
+;; We define both cell and table targets
+
+(defun embark-org-target-cell ()
+  "Target contents of Org table cell at point."
+  (when (and (derived-mode-p 'org-mode) (org-at-table-p))
+    `(org-table-cell
+      ,(save-excursion (string-trim (org-table-get-field)))
+      . (,(save-excursion (skip-chars-backward "^|") (point))
+         . ,(save-excursion (skip-chars-forward "^|") (point))))))
+
+(defun embark-org-target-table ()
+  "Target entire Org table at point."
+  (when (and (derived-mode-p 'org-mode) (org-at-table-p))
+    `(org-table
+      ,(buffer-substring (org-table-begin) (org-table-end))
+      . (,(org-table-begin) . ,(org-table-end)))))
+
+(dolist (motion '(org-table-move-cell-up org-table-move-cell-down
+                  org-table-move-cell-left org-table-move-cell-right))
+  (add-to-list 'embark-repeat-actions motion))
+
+(push 'embark--ignore-target
+      (alist-get 'org-table-edit-field embark-target-injection-hooks))
+
+(embark-define-keymap embark-org-table-cell-map
+  "Keymap for actions the current cells, column or row of an Org table."
+  ("<up>"    org-table-move-cell-up)
+  ("<down>"  org-table-move-cell-down)
+  ("<left>"  org-table-move-cell-left)
+  ("<right>" org-table-move-cell-right)
+  ("=" org-table-eval-formula)
+  ("e" org-table-edit-field)
+  ("g" org-table-recalculate))
+
+(embark-define-keymap embark-org-table-map
+  "Keymap for actions on entire Org table."
+  ("=" org-table-edit-formulas)
+  ("c" org-table-convert)
+  ("t" org-table-transpose-table-at-point)
+  ("f" org-table-follow-field-mode)
+  ("y" org-table-paste-rectangle)
+  ("d" org-table-toggle-formula-debugger)
+  ("i" org-table-iterate)
+  ("e" org-table-export))
+
+(add-to-list 'embark-target-finders #'embark-org-target-table)
+(add-to-list 'embark-keymap-alist '(org-table . embark-org-table-map))
+
+(add-to-list 'embark-target-finders #'embark-org-target-cell)
+(add-to-list 'embark-keymap-alist '(org-table-cell . 
embark-org-table-cell-map))
+
+;;; Links
+
+;; The link support has a slightly complicated design in order to
+;; achieve the following goals:
+
+;; 1. RET should simply be org-open-at-point
+
+;; 2. When the link is to a file, URL, email address or elisp
+;;    expression or command, we want to offer the user actions for
+;;    that underlying type.
+
+;; 3. Even in those cases, we still want some actions to apply to the
+;;    entire link including description: actions to copy the link as
+;;    markdown, or just the link description or target.
+
+;; So the strategy is as follows (illustrated with file links):
+
+;; - The target will be just the file, without the description and
+;;   also without the "file:" prefix nor the "::line-number or search"
+;;   suffix.  That way, file actions will correctly apply to it.
+
+;; - The type will not be 'file, but 'org-file-link that way we can
+;;   register a keymap for 'org-file-link that inherits from both
+;;   embark-org-link-map (with RET bound to org-open-at-point and a
+;;   few other generic link actions) and embark-file-map.
+
+;; - The commands to copy the link at point in some format will be
+;;   written as commands that act on the Org link at point.  This way
+;;   they are independently (plausibly) useful, and we circumvent the
+;;   problem that the whole Org link is not actually the target (just
+;;   the inner file is!).
+
+;; Alternative design I considered: separate each target into two, a
+;; whole link target which includes the description and brackets and
+;; what not; and an "inner target" which is just the file or URL or
+;; whatever.  Cons of this approach: much target cycling is required!
+;; First of all, an unadorned embark-dwim definitely should be
+;; org-open-at-point, which means the whole link target would need
+;; priority. That means that any file, URL, etc. actions would require
+;; you to cycle first.  This sounds very inconvenient, the above
+;; slightly more complex design allows both whole-link and inner
+;; target actions to work without cycling.
+
+(defun embark-org-target-link ()
+  "Target destination of Org link."
+  (when (and (derived-mode-p 'org-mode 'org-agenda-mode)
+             (org-in-regexp org-link-any-re))
+    (let ((target (or (match-string-no-properties 2)
+                      (match-string-no-properties 0))))
+      (append
+       (cond
+        ((string-prefix-p "http" target)
+         (list 'org-url-link target))
+        ((string-prefix-p "mailto:"; target)
+         (list 'org-email-link (string-remove-prefix "mailto:"; target)))
+        ((string-prefix-p "file:" target)
+         (list 'org-file-link
+               (replace-regexp-in-string
+                "::.*" "" (string-remove-prefix "file:" target))))
+        ((string-match-p "^[./]" target)
+         (list 'org-file-link (abbreviate-file-name (expand-file-name 
target))))
+        ((string-prefix-p "elisp:(" target)
+         (list 'org-expression-link (string-remove-prefix "elisp:" target)))
+        ((string-prefix-p "elisp:" target)
+         (list 'command (string-remove-prefix "elisp:" target)))
+        (t (list 'org-link target)))
+       (cons (match-beginning 0) (match-end 0))))))
+
+(add-to-list 'embark-target-finders #'embark-org-target-link)
+
+(defmacro embark-org-define-link-copier (name formula description)
+  "Define a command that copies the Org link at point according to FORMULA.
+The command's name is formed by appending NAME to
+embark-org-copy-link.  The docstring includes the DESCRIPTION of
+what part or in what format the link is copied."
+  `(defun ,(intern (format "embark-org-copy-link-%s" name)) ()
+     ,(format "Copy to the kill-ring the Org link at point%s." description)
+     (interactive)
+     (when (org-in-regexp org-link-any-re)
+       (let* ((full (match-string-no-properties 0))
+              (target (or (match-string-no-properties 2)
+                          (match-string-no-properties 0)))
+              (description (match-string-no-properties 3))
+              (kill ,formula))
+         (ignore full target description)
+         (when kill
+           (message "Saved '%s'" kill)
+           (kill-new kill))))))
+
+(embark-org-define-link-copier in-full full " in full")
+(embark-org-define-link-copier description description "'s description")
+(embark-org-define-link-copier target target "'s target")
+(embark-org-define-link-copier
+ as-markdown (format "[%s](%s)" description target) "as Markdown")
+
+(fset 'embark-org-copy-link-inner-target 'embark-copy-as-kill)
+(put 'embark-org-copy-link-inner-target 'function-documentation
+      "Copy 'inner part' of the Org link at point's target.
+For mailto and elisp links, the inner part is the portion of the
+target after 'mailto:' or 'elisp:'.
+
+For file links the inner part is the file name, without the
+'file:' prefix and without '::' suffix (used for line numbers,
+IDs or search terms).
+
+For URLs the inner part is the whole target including the 'http:'
+or 'https:' prefix.")
+
+(embark-define-keymap embark-org-copy-map
+  "Keymap for different ways to copy Org links to the kill-ring."
+  :parent nil
+  ("w" embark-org-copy-link-in-full)
+  ("d" embark-org-copy-link-description)
+  ("t" embark-org-copy-link-target)
+  ("i" embark-org-copy-link-inner-target)
+  ("m" embark-org-copy-link-as-markdown))
+
+(fset 'embark-org-copy-map embark-org-copy-map)
+
+(embark-define-keymap embark-org-link-map
+  "Keymap for actions on Org links"
+  ("RET" org-open-at-point)
+  ("TAB" org-insert-link)
+  ("w" 'embark-org-copy-map))
+
+(defmacro embark-org-define-link-keymap (type)
+  "Define a keymap for Org link of given TYPE.
+The keymap will inherit from `embark-org-link-map' and from
+`embark-TYPE-map' in that order."
+  `(defvar ,(intern (format "embark-org-%s-link-map" type))
+     (make-composed-keymap embark-org-link-map
+                           ,(intern (format "embark-%s-map" type)))
+     ,(format "Keymap for Embark actions on Org %s links" type)))
+
+;; The reason for this is left as an exercise to the reader.
+;; Solution: Na ryvfc gnetrg znl cebzcg gur hfre sbe fbzrguvat!
+(push 'embark--ignore-target
+      (alist-get 'org-open-at-point embark-target-injection-hooks))
+
+(embark-org-define-link-keymap url)
+(embark-org-define-link-keymap file)
+(embark-org-define-link-keymap email)
+(embark-org-define-link-keymap expression)
+
+(add-to-list 'embark-keymap-alist '(org-link . embark-org-link-map))
+(add-to-list 'embark-keymap-alist '(org-url-link . embark-org-url-link-map))
+(add-to-list 'embark-keymap-alist '(org-email-link . 
embark-org-email-link-map))
+(add-to-list 'embark-keymap-alist '(org-file-link . embark-org-file-link-map))
+(add-to-list 'embark-keymap-alist
+             '(org-expression-link . embark-org-expression-link-map))
+
+(provide 'embark-org)
+;;; embark-org.el ends here



reply via email to

[Prev in Thread] Current Thread [Next in Thread]