From: Nicolas Goaziou <mail@nicolasgoaziou.fr>
To: Rasmus <rasmus@gmx.us>
Cc: emacs-orgmode@gnu.org
Subject: Re: [RFC] Draft mode
Date: Sat, 10 Oct 2015 16:21:12 +0200 [thread overview]
Message-ID: <871td29547.fsf@nicolasgoaziou.fr> (raw)
In-Reply-To: <87vbagqxby.fsf@gmx.us> (rasmus@gmx.us's message of "Fri, 09 Oct 2015 10:07:29 +0200")
[-- Attachment #1: Type: text/plain, Size: 669 bytes --]
Rasmus <rasmus@gmx.us> writes:
> While I agree that options such as 't:·', '^:·', 'h:·' are bad, I think
> 'barf:·' is nice. It's short and precise, much like 'num:·'.
>
> Something like 'barf-on-invalid-link' is very easy to mistype or forget.
> And yes, I mostly type options by hand.
Here's another take on this, which is quite different from the original
draft mode. Now, behaviour on broken links is controlled with
`org-export-with-broken-links' or its OPTIONS counterpart
"broken-links".
It is possible to either error on a broken link, ignore it, or mark it
with an obnoxious string in the output.
Feedback welcome.
Regards,
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-ox-Add-an-option-to-ignore-broken-links.patch --]
[-- Type: text/x-diff, Size: 11552 bytes --]
From 0508461b2d57629e1c391c57a7326093f61b07e6 Mon Sep 17 00:00:00 2001
From: Nicolas Goaziou <mail@nicolasgoaziou.fr>
Date: Sat, 10 Oct 2015 16:03:05 +0200
Subject: [PATCH] ox: Add an option to ignore broken links
* lisp/ox.el (org-export-with-broken-links): New variable.
(org-export-options-alist): Add new OPTIONS item.
(broken-link): New error type.
(org-export-resolve-coderef):
(org-export-resolve-fuzzy-link):
(org-export-resolve-id-link): Raise appropriate error symbol when a link
cannot be resolved.
(org-export-data): Handle new error type.
---
lisp/ox.el | 221 ++++++++++++++++++++++++++++++++++++-------------------------
1 file changed, 132 insertions(+), 89 deletions(-)
diff --git a/lisp/ox.el b/lisp/ox.el
index d140f17..d74f48b 100644
--- a/lisp/ox.el
+++ b/lisp/ox.el
@@ -112,6 +112,7 @@
(:time-stamp-file nil "timestamp" org-export-time-stamp-file)
(:with-archived-trees nil "arch" org-export-with-archived-trees)
(:with-author nil "author" org-export-with-author)
+ (:with-broken-links nil "broken-links" org-export-with-broken-links)
(:with-clocks nil "c" org-export-with-clocks)
(:with-creator nil "creator" org-export-with-creator)
(:with-date nil "date" org-export-with-date)
@@ -797,6 +798,27 @@ is nil. You can also allow them through local buffer variables."
:package-version '(Org . "8.0")
:type 'boolean)
+(defcustom org-export-with-broken-links nil
+ "Non-nil means do not raise an error on broken links.
+
+When this variable is non-nil, broken links are ignored, without
+stopping the export process. If it is set to `mark', broken
+links are marked as such in the output, with a string like
+
+ [BROKEN LINK: path]
+
+where PATH is the un-resolvable reference.
+
+This option can also be set with the OPTIONS keyword, e.g.,
+\"broken-links:mark\"."
+ :group 'org-export-general
+ :version "25.1"
+ :package-version '(Org . "8.4")
+ :type '(choice
+ (const :tag "Ignore broken links" t)
+ (const :tag "Mark broken links in output" mark)
+ (const :tag "Raise an error" nil)))
+
(defcustom org-export-snippet-translation-alist nil
"Alist between export snippets back-ends and exporter back-ends.
@@ -1851,91 +1873,106 @@ string. INFO is a plist holding export options.
Return a string."
(or (gethash data (plist-get info :exported-data))
- (let* ((type (org-element-type data))
- (results
- (cond
- ;; Ignored element/object.
- ((memq data (plist-get info :ignore-list)) nil)
- ;; Plain text.
- ((eq type 'plain-text)
- (org-export-filter-apply-functions
- (plist-get info :filter-plain-text)
- (let ((transcoder (org-export-transcoder data info)))
- (if transcoder (funcall transcoder data info) data))
- info))
- ;; Secondary string.
- ((not type)
- (mapconcat (lambda (obj) (org-export-data obj info)) data ""))
- ;; Element/Object without contents or, as a special
- ;; case, headline with archive tag and archived trees
- ;; restricted to title only.
- ((or (not (org-element-contents data))
- (and (eq type 'headline)
- (eq (plist-get info :with-archived-trees) 'headline)
- (org-element-property :archivedp data)))
- (let ((transcoder (org-export-transcoder data info)))
- (or (and (functionp transcoder)
- (funcall transcoder data nil info))
- ;; Export snippets never return a nil value so
- ;; that white spaces following them are never
- ;; ignored.
- (and (eq type 'export-snippet) ""))))
- ;; Element/Object with contents.
- (t
- (let ((transcoder (org-export-transcoder data info)))
- (when transcoder
- (let* ((greaterp (memq type org-element-greater-elements))
- (objectp
- (and (not greaterp)
- (memq type org-element-recursive-objects)))
- (contents
- (mapconcat
- (lambda (element) (org-export-data element info))
- (org-element-contents
- (if (or greaterp objectp) data
- ;; Elements directly containing
- ;; objects must have their indentation
- ;; normalized first.
- (org-element-normalize-contents
- data
- ;; When normalizing contents of the
- ;; first paragraph in an item or
- ;; a footnote definition, ignore
- ;; first line's indentation: there is
- ;; none and it might be misleading.
- (when (eq type 'paragraph)
- (let ((parent (org-export-get-parent data)))
- (and
- (eq (car (org-element-contents parent))
- data)
- (memq (org-element-type parent)
- '(footnote-definition item))))))))
- "")))
- (funcall transcoder data
- (if (not greaterp) contents
- (org-element-normalize-string contents))
- info))))))))
- ;; Final result will be memoized before being returned.
- (puthash
- data
- (cond
- ((not results) "")
- ((memq type '(org-data plain-text nil)) results)
- ;; Append the same white space between elements or objects
- ;; as in the original buffer, and call appropriate filters.
- (t
- (let ((results
+ ;; Handle broken links according to
+ ;; `org-export-with-broken-links'.
+ (cl-macrolet
+ ((broken-link-handler
+ (&rest body)
+ `(condition-case err
+ (progn ,@body)
+ (broken-link
+ (pcase (plist-get info :with-broken-links)
+ (`nil (user-error "Unable to resolve link: %S" (nth 1 err)))
+ (`mark (org-export-data
+ (format "[BROKEN LINK: %s]" (nth 1 err)) info))
+ (_ nil))))))
+ (let* ((type (org-element-type data))
+ (results
+ (cond
+ ;; Ignored element/object.
+ ((memq data (plist-get info :ignore-list)) nil)
+ ;; Plain text.
+ ((eq type 'plain-text)
(org-export-filter-apply-functions
- (plist-get info (intern (format ":filter-%s" type)))
- (let ((post-blank (or (org-element-property :post-blank data)
- 0)))
- (if (memq type org-element-all-elements)
- (concat (org-element-normalize-string results)
- (make-string post-blank ?\n))
- (concat results (make-string post-blank ?\s))))
- info)))
- results)))
- (plist-get info :exported-data)))))
+ (plist-get info :filter-plain-text)
+ (let ((transcoder (org-export-transcoder data info)))
+ (if transcoder (funcall transcoder data info) data))
+ info))
+ ;; Secondary string.
+ ((not type)
+ (mapconcat (lambda (obj) (org-export-data obj info)) data ""))
+ ;; Element/Object without contents or, as a special
+ ;; case, headline with archive tag and archived trees
+ ;; restricted to title only.
+ ((or (not (org-element-contents data))
+ (and (eq type 'headline)
+ (eq (plist-get info :with-archived-trees) 'headline)
+ (org-element-property :archivedp data)))
+ (let ((transcoder (org-export-transcoder data info)))
+ (or (and (functionp transcoder)
+ (broken-link-handler
+ (funcall transcoder data nil info)))
+ ;; Export snippets never return a nil value so
+ ;; that white spaces following them are never
+ ;; ignored.
+ (and (eq type 'export-snippet) ""))))
+ ;; Element/Object with contents.
+ (t
+ (let ((transcoder (org-export-transcoder data info)))
+ (when transcoder
+ (let* ((greaterp (memq type org-element-greater-elements))
+ (objectp
+ (and (not greaterp)
+ (memq type org-element-recursive-objects)))
+ (contents
+ (mapconcat
+ (lambda (element) (org-export-data element info))
+ (org-element-contents
+ (if (or greaterp objectp) data
+ ;; Elements directly containing
+ ;; objects must have their indentation
+ ;; normalized first.
+ (org-element-normalize-contents
+ data
+ ;; When normalizing contents of the
+ ;; first paragraph in an item or
+ ;; a footnote definition, ignore
+ ;; first line's indentation: there is
+ ;; none and it might be misleading.
+ (when (eq type 'paragraph)
+ (let ((parent (org-export-get-parent data)))
+ (and
+ (eq (car (org-element-contents parent))
+ data)
+ (memq (org-element-type parent)
+ '(footnote-definition item))))))))
+ "")))
+ (broken-link-handler
+ (funcall transcoder data
+ (if (not greaterp) contents
+ (org-element-normalize-string contents))
+ info)))))))))
+ ;; Final result will be memoized before being returned.
+ (puthash
+ data
+ (cond
+ ((not results) "")
+ ((memq type '(org-data plain-text nil)) results)
+ ;; Append the same white space between elements or objects
+ ;; as in the original buffer, and call appropriate filters.
+ (t
+ (let ((results
+ (org-export-filter-apply-functions
+ (plist-get info (intern (format ":filter-%s" type)))
+ (let ((post-blank (or (org-element-property :post-blank data)
+ 0)))
+ (if (memq type org-element-all-elements)
+ (concat (org-element-normalize-string results)
+ (make-string post-blank ?\n))
+ (concat results (make-string post-blank ?\s))))
+ info)))
+ results)))
+ (plist-get info :exported-data))))))
(defun org-export-data-with-backend (data backend info)
"Convert DATA into BACKEND format.
@@ -3990,11 +4027,11 @@ meant to be translated with `org-export-data' or alike."
;;
;; `org-export-resolve-fuzzy-link' searches destination of fuzzy links
;; (i.e. links with "fuzzy" as type) within the parsed tree, and
-;; returns an appropriate unique identifier when found, or nil.
+;; returns an appropriate unique identifier.
;;
;; `org-export-resolve-id-link' returns the first headline with
;; specified id or custom-id in parse tree, the path to the external
-;; file with the id or nil when neither was found.
+;; file with the id.
;;
;; `org-export-resolve-coderef' associates a reference to a line
;; number in the element it belongs, or returns the reference itself
@@ -4002,6 +4039,12 @@ meant to be translated with `org-export-data' or alike."
;;
;; `org-export-file-uri' expands a filename as stored in :path value
;; of a "file" link into a file URI.
+;;
+;; Broken links raise a `broken-link' error, which is caught by
+;; `org-export-data' for further processing, depending on
+;; `org-export-with-broken-links' value.
+
+(define-error 'broken-link "Unable to resolve link; aborting")
(defun org-export-custom-protocol-maybe (link desc backend)
"Try exporting LINK with a dedicated function.
@@ -4083,7 +4126,7 @@ error if no block contains REF."
(+ (org-export-get-loc el info) (line-number-at-pos)))
(t (line-number-at-pos)))))))
info 'first-match)
- (user-error "Unable to resolve code reference: %s" ref)))
+ (signal 'broken-link (list ref))))
(defun org-export-resolve-fuzzy-link (link info)
"Return LINK destination.
@@ -4151,7 +4194,7 @@ significant."
path)
h))
info 'first-match))
- (t (user-error "Unable to resolve link \"%s\"" raw-path)))
+ (t (signal 'broken-link (list raw-path))))
link-cache)))))
(defun org-export-resolve-id-link (link info)
@@ -4172,7 +4215,7 @@ tree or a file name. Assume LINK type is either \"id\" or
info 'first-match)
;; Otherwise, look for external files.
(cdr (assoc id (plist-get info :id-alist)))
- (user-error "Unable to resolve ID \"%s\"" id))))
+ (signal 'broken-link (list id)))))
(defun org-export-resolve-radio-link (link info)
"Return radio-target object referenced as LINK destination.
--
2.6.1
next prev parent reply other threads:[~2015-10-10 14:19 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-09-27 9:38 [RFC] Draft mode Nicolas Goaziou
2015-09-27 11:37 ` Nicolas Goaziou
2015-09-27 16:31 ` Charles C. Berry
2015-09-28 20:56 ` Aaron Ecay
2015-10-07 20:22 ` Nicolas Goaziou
2015-09-27 18:39 ` Rasmus
2015-09-27 20:01 ` Marcin Borkowski
2015-10-07 20:12 ` Nicolas Goaziou
2015-10-08 14:23 ` Rasmus
2015-10-08 16:36 ` Thomas S. Dye
2015-10-08 16:54 ` Rasmus
2015-10-08 16:57 ` Eric Abrahamsen
2015-10-08 17:00 ` Nicolas Goaziou
2015-10-08 19:38 ` Eric S Fraga
2015-10-08 20:59 ` Nick Dokos
2015-10-09 8:07 ` Rasmus
2015-10-10 14:21 ` Nicolas Goaziou [this message]
2015-10-11 12:34 ` Rasmus
2015-10-17 12:54 ` Nicolas Goaziou
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=871td29547.fsf@nicolasgoaziou.fr \
--to=mail@nicolasgoaziou.fr \
--cc=emacs-orgmode@gnu.org \
--cc=rasmus@gmx.us \
/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).