Merge branch 'master' of orgmode.org:org-mode

This commit is contained in:
Carsten Dominik 2017-06-14 05:46:17 +02:00
commit feed16e1ed
8 changed files with 248 additions and 121 deletions

View File

@ -10411,14 +10411,14 @@ override options set at a more general level.
@cindex #+SETUPFILE @cindex #+SETUPFILE
In-buffer settings may appear anywhere in the file, either directly or In-buffer settings may appear anywhere in the file, either directly or
indirectly through a file included using @samp{#+SETUPFILE: filename} syntax. indirectly through a file included using @samp{#+SETUPFILE: filename or URL}
Option keyword sets tailored to a particular back-end can be inserted from syntax. Option keyword sets tailored to a particular back-end can be
the export dispatcher (@pxref{The export dispatcher}) using the @code{Insert inserted from the export dispatcher (@pxref{The export dispatcher}) using the
template} command by pressing @key{#}. To insert keywords individually, @code{Insert template} command by pressing @key{#}. To insert keywords
a good way to make sure the keyword is correct is to type @code{#+} and then individually, a good way to make sure the keyword is correct is to type
to use @kbd{M-@key{TAB}}@footnote{Many desktops intercept @kbd{M-TAB} to @code{#+} and then to use @kbd{M-@key{TAB}}@footnote{Many desktops intercept
switch windows. Use @kbd{C-M-i} or @kbd{@key{ESC} @key{TAB}} instead.} for @kbd{M-TAB} to switch windows. Use @kbd{C-M-i} or @kbd{@key{ESC} @key{TAB}}
completion. instead.} for completion.
The export keywords available for every back-end, and their equivalent global The export keywords available for every back-end, and their equivalent global
variables, include: variables, include:
@ -17179,14 +17179,16 @@ have a lower ASCII number than the lowest priority.
This line sets a default inheritance value for entries in the current This line sets a default inheritance value for entries in the current
buffer, most useful for specifying the allowed values of a property. buffer, most useful for specifying the allowed values of a property.
@cindex #+SETUPFILE @cindex #+SETUPFILE
@item #+SETUPFILE: file @item #+SETUPFILE: file or URL
The setup file is for additional in-buffer settings. Org loads this file and The setup file or a URL pointing to such file is for additional in-buffer
parses it for any settings in it only when Org opens the main file. @kbd{C-c settings. Org loads this file and parses it for any settings in it only when
C-c} on the settings line will also parse and load. Org also parses and Org opens the main file. If URL is specified, the contents are downloaded
loads the file during normal exporting process. Org parses the contents of and stored in a temporary file cache. @kbd{C-c C-c} on the settings line
this file as if it was included in the buffer. It can be another Org file. will parse and load the file, and also reset the temporary file cache. Org
To visit the file, @kbd{C-c '} while the cursor is on the line with the file also parses and loads the document during normal exporting process. Org
name. parses the contents of this document as if it was included in the buffer. It
can be another Org file. To visit the file (not a URL), @kbd{C-c '} while
the cursor is on the line with the file name.
@item #+STARTUP: @item #+STARTUP:
@cindex #+STARTUP @cindex #+STARTUP
Startup options Org uses when first visiting a file. Startup options Org uses when first visiting a file.
@ -17427,7 +17429,9 @@ If any highlights shown in the buffer from the creation of a sparse tree, or
from clock display, remove such highlights. from clock display, remove such highlights.
@item @item
If the cursor is in one of the special @code{#+KEYWORD} lines, scan the If the cursor is in one of the special @code{#+KEYWORD} lines, scan the
buffer for these lines and update the information. buffer for these lines and update the information. Also reset the Org file
cache used to temporary store the contents of URLs used as values for
keywords like @code{#+SETUPFILE}.
@item @item
If the cursor is inside a table, realign the table. The table realigns even If the cursor is inside a table, realign the table. The table realigns even
if automatic table editor is turned off. if automatic table editor is turned off.

View File

@ -203,7 +203,7 @@ manual for details.
**** Add global macros through ~org-export-global-macros~ **** Add global macros through ~org-export-global-macros~
With this variable, one can define macros available for all documents. With this variable, one can define macros available for all documents.
**** New keyword ~#+EXPORT_FILE_NAME~ **** New keyword ~#+EXPORT_FILE_NAME~
Simiralry to ~:EXPORT_FILE_NAME:~ property, this keyword allows the Similarly to ~:EXPORT_FILE_NAME:~ property, this keyword allows the
user to specify the name of the output file upon exporting the user to specify the name of the output file upon exporting the
document. This also has an effect on publishing. document. This also has an effect on publishing.
**** Horizontal rules are no longer ignored in LaTeX table math mode **** Horizontal rules are no longer ignored in LaTeX table math mode
@ -240,6 +240,16 @@ which causes refile targets to be prefixed with the buffers
name. This is particularly useful when used in conjunction with name. This is particularly useful when used in conjunction with
~uniquify.el~. ~uniquify.el~.
*** ~org-file-contents~ now allows the FILE argument to be a URL.
This allows ~#+SETUPFILE:~ to accept a URL instead of a local file
path. The URL contents are auto-downloaded and saved to a temporary
cache ~org--file-cache~. A new optional argument ~NOCACHE~ is added
to ~org-file-contents~.
*** ~org-mode-restart~ now resets the newly added ~org--file-cache~.
Using ~C-c C-c~ on any keyword (like ~#+SETUPFILE~) will reset the
that file cache.
** Removed functions ** Removed functions
*** Org Timeline *** Org Timeline

View File

@ -22,79 +22,21 @@
;;; Commentary: ;;; Commentary:
;; ;;
;; Org syntax can be divided into three categories: "Greater ;; See <http://orgmode.org/worg/dev/org-syntax.html> for details about
;; elements", "Elements" and "Objects". ;; Org syntax.
;; ;;
;; Elements are related to the structure of the document. Indeed, all ;; Lisp-wise, a syntax object can be represented as a list.
;; elements are a cover for the document: each position within belongs
;; to at least one element.
;;
;; An element always starts and ends at the beginning of a line. With
;; a few exceptions (`clock', `headline', `inlinetask', `item',
;; `planning', `property-drawer', `node-property', `section' and
;; `table-row' types), it can also accept a fixed set of keywords as
;; attributes. Those are called "affiliated keywords" to distinguish
;; them from other keywords, which are full-fledged elements. Almost
;; all affiliated keywords are referenced in
;; `org-element-affiliated-keywords'; the others are export attributes
;; and start with "ATTR_" prefix.
;;
;; Element containing other elements (and only elements) are called
;; greater elements. Concerned types are: `center-block', `drawer',
;; `dynamic-block', `footnote-definition', `headline', `inlinetask',
;; `item', `plain-list', `property-drawer', `quote-block', `section'
;; and `special-block'.
;;
;; Other element types are: `babel-call', `clock', `comment',
;; `comment-block', `diary-sexp', `example-block', `export-block',
;; `fixed-width', `horizontal-rule', `keyword', `latex-environment',
;; `node-property', `paragraph', `planning', `src-block', `table',
;; `table-row' and `verse-block'. Among them, `paragraph' and
;; `verse-block' types can contain Org objects and plain text.
;;
;; Objects are related to document's contents. Some of them are
;; recursive. Associated types are of the following: `bold', `code',
;; `entity', `export-snippet', `footnote-reference',
;; `inline-babel-call', `inline-src-block', `italic',
;; `latex-fragment', `line-break', `link', `macro', `radio-target',
;; `statistics-cookie', `strike-through', `subscript', `superscript',
;; `table-cell', `target', `timestamp', `underline' and `verbatim'.
;;
;; Some elements also have special properties whose value can hold
;; objects themselves (e.g. an item tag or a headline name). Such
;; values are called "secondary strings". Any object belongs to
;; either an element or a secondary string.
;;
;; Notwithstanding affiliated keywords, each greater element, element
;; and object has a fixed set of properties attached to it. Among
;; them, four are shared by all types: `:begin' and `:end', which
;; refer to the beginning and ending buffer positions of the
;; considered element or object, `:post-blank', which holds the number
;; of blank lines, or white spaces, at its end and `:parent' which
;; refers to the element or object containing it. Greater elements,
;; elements and objects containing objects will also have
;; `:contents-begin' and `:contents-end' properties to delimit
;; contents. Eventually, All elements have a `:post-affiliated'
;; property referring to the buffer position after all affiliated
;; keywords, if any, or to their beginning position otherwise.
;;
;; At the lowest level, a `:parent' property is also attached to any
;; string, as a text property.
;;
;; Lisp-wise, an element or an object can be represented as a list.
;; It follows the pattern (TYPE PROPERTIES CONTENTS), where: ;; It follows the pattern (TYPE PROPERTIES CONTENTS), where:
;; TYPE is a symbol describing the Org element or object. ;; TYPE is a symbol describing the object.
;; PROPERTIES is the property list attached to it. See docstring of ;; PROPERTIES is the property list attached to it. See docstring of
;; appropriate parsing function to get an exhaustive ;; appropriate parsing function to get an exhaustive list.
;; list. ;; CONTENTS is a list of syntax objects or raw strings contained
;; CONTENTS is a list of elements, objects or raw strings contained ;; in the current object, when applicable.
;; in the current element or object, when applicable.
;; ;;
;; An Org buffer is a nested list of such elements and objects, whose ;; For the whole document, TYPE is `org-data' and PROPERTIES is nil.
;; type is `org-data' and properties is nil.
;; ;;
;; The first part of this file defines Org syntax, while the second ;; The first part of this file defines constants for the Org syntax,
;; one provide accessors and setters functions. ;; while the second one provide accessors and setters functions.
;; ;;
;; The next part implements a parser and an interpreter for each ;; The next part implements a parser and an interpreter for each
;; element and object type in Org syntax. ;; element and object type in Org syntax.

View File

@ -55,7 +55,8 @@
(declare-function org-element-macro-parser "org-element" ()) (declare-function org-element-macro-parser "org-element" ())
(declare-function org-element-property "org-element" (property element)) (declare-function org-element-property "org-element" (property element))
(declare-function org-element-type "org-element" (element)) (declare-function org-element-type "org-element" (element))
(declare-function org-file-contents "org" (file &optional noerror)) (declare-function org-file-contents "org" (file &optional noerror nocache))
(declare-function org-file-url-p "org" (file))
(declare-function org-in-commented-heading-p "org" (&optional no-inheritance)) (declare-function org-in-commented-heading-p "org" (&optional no-inheritance))
(declare-function org-mode "org" ()) (declare-function org-mode "org" ())
(declare-function vc-backend "vc-hooks" (f)) (declare-function vc-backend "vc-hooks" (f))
@ -102,16 +103,21 @@ Return an alist containing all macro templates found."
(if old-cell (setcdr old-cell template) (if old-cell (setcdr old-cell template)
(push (cons name template) templates)))) (push (cons name template) templates))))
;; Enter setup file. ;; Enter setup file.
(let ((file (expand-file-name (let* ((uri (org-unbracket-string "\"" "\"" (org-trim val)))
(org-unbracket-string "\"" "\"" val)))) (uri-is-url (org-file-url-p uri))
(unless (member file files) (uri (if uri-is-url
uri
(expand-file-name uri))))
;; Avoid circular dependencies.
(unless (member uri files)
(with-temp-buffer (with-temp-buffer
(setq default-directory (unless uri-is-url
(file-name-directory file)) (setq default-directory
(file-name-directory uri)))
(org-mode) (org-mode)
(insert (org-file-contents file 'noerror)) (insert (org-file-contents uri 'noerror))
(setq templates (setq templates
(funcall collect-macros (cons file files) (funcall collect-macros (cons uri files)
templates))))))))))) templates)))))))))))
templates)))) templates))))
(funcall collect-macros nil nil))) (funcall collect-macros nil nil)))

View File

@ -181,6 +181,8 @@ Stars are put in group 1 and the trimmed body in group 2.")
(declare-function org-export-get-environment "ox" (&optional backend subtreep ext-plist)) (declare-function org-export-get-environment "ox" (&optional backend subtreep ext-plist))
(declare-function org-latex-make-preamble "ox-latex" (info &optional template snippet?)) (declare-function org-latex-make-preamble "ox-latex" (info &optional template snippet?))
(defvar ffap-url-regexp) ;Silence byte-compiler
(defsubst org-uniquify (list) (defsubst org-uniquify (list)
"Non-destructively remove duplicate elements from LIST." "Non-destructively remove duplicate elements from LIST."
(let ((res (copy-sequence list))) (delete-dups res))) (let ((res (copy-sequence list))) (delete-dups res)))
@ -5280,17 +5282,62 @@ a string, summarizing TAGS, as a list of strings."
(setq current-group (list tag)))) (setq current-group (list tag))))
(_ nil))))) (_ nil)))))
(defun org-file-contents (file &optional noerror) (defvar org--file-cache (make-hash-table :test #'equal)
"Return the contents of FILE, as a string." "Hash table to store contents of files referenced via a URL.
(if (and file (file-readable-p file)) This is the cache of file URLs read using `org-file-contents'.")
(defun org-reset-file-cache ()
"Reset the cache of files downloaded by `org-file-contents'."
(clrhash org--file-cache))
(defun org-file-url-p (file)
"Non-nil if FILE is a URL."
(require 'ffap)
(string-match-p ffap-url-regexp file))
(defun org-file-contents (file &optional noerror nocache)
"Return the contents of FILE, as a string.
FILE can be a file name or URL.
If FILE is a URL, download the contents. If the URL contents are
already cached in the `org--file-cache' hash table, the download step
is skipped.
If NOERROR is non-nil, ignore the error when unable to read the FILE
from file or URL.
If NOCACHE is non-nil, do a fresh fetch of FILE even if cached version
is available. This option applies only if FILE is a URL."
(let* ((is-url (org-file-url-p file))
(cache (and is-url
(not nocache)
(gethash file org--file-cache))))
(cond
(cache)
(is-url
(with-current-buffer (url-retrieve-synchronously file)
(goto-char (point-min))
;; Move point to after the url-retrieve header.
(search-forward "\n\n" nil :move)
;; Search for the success code only in the url-retrieve header.
(if (save-excursion (re-search-backward "HTTP.*\\s-+200\\s-OK" nil :noerror))
;; Update the cache `org--file-cache' and return contents.
(puthash file
(buffer-substring-no-properties (point) (point-max))
org--file-cache)
(funcall (if noerror #'message #'user-error)
"Unable to fetch file from %S"
file))))
(t
(with-temp-buffer (with-temp-buffer
(insert-file-contents file) (condition-case err
(buffer-string)) (progn
(funcall (if noerror 'message 'error) (insert-file-contents file)
"Cannot read file \"%s\"%s" (buffer-string))
file (file-error
(let ((from (buffer-file-name (buffer-base-buffer)))) (funcall (if noerror #'message #'user-error)
(if from (concat " (referenced in file \"" from "\")") ""))))) (error-message-string err)))))))))
(defun org-extract-log-state-settings (x) (defun org-extract-log-state-settings (x)
"Extract the log state setting from a TODO keyword string. "Extract the log state setting from a TODO keyword string.
@ -20687,7 +20734,9 @@ Otherwise, return a user error."
(format "[[%s]]" (format "[[%s]]"
(expand-file-name (expand-file-name
(let ((value (org-element-property :value element))) (let ((value (org-element-property :value element)))
(cond ((not (org-string-nw-p value)) (cond ((org-file-url-p value)
(user-error "The file is specified as a URL, cannot be edited"))
((not (org-string-nw-p value))
(user-error "No file to edit")) (user-error "No file to edit"))
((string-match "\\`\"\\(.*?\\)\"" value) ((string-match "\\`\"\\(.*?\\)\"" value)
(match-string 1 value)) (match-string 1 value))
@ -20951,7 +21000,8 @@ Use `\\[org-edit-special]' to edit table.el tables"))
(funcall major-mode) (funcall major-mode)
(hack-local-variables) (hack-local-variables)
(when (and indent-status (not (bound-and-true-p org-indent-mode))) (when (and indent-status (not (bound-and-true-p org-indent-mode)))
(org-indent-mode -1))) (org-indent-mode -1))
(org-reset-file-cache))
(message "%s restarted" major-mode)) (message "%s restarted" major-mode))
(defun org-kill-note-or-show-branches () (defun org-kill-note-or-show-branches ()

View File

@ -1499,17 +1499,20 @@ Assume buffer is in Org mode. Narrowing, if any, is ignored."
(cond (cond
;; Options in `org-export-special-keywords'. ;; Options in `org-export-special-keywords'.
((equal key "SETUPFILE") ((equal key "SETUPFILE")
(let ((file (let* ((uri (org-unbracket-string "\"" "\"" (org-trim val)))
(expand-file-name (uri-is-url (org-file-url-p uri))
(org-unbracket-string "\"" "\"" (org-trim val))))) (uri (if uri-is-url
uri
(expand-file-name uri))))
;; Avoid circular dependencies. ;; Avoid circular dependencies.
(unless (member file files) (unless (member uri files)
(with-temp-buffer (with-temp-buffer
(setq default-directory (unless uri-is-url
(file-name-directory file)) (setq default-directory
(insert (org-file-contents file 'noerror)) (file-name-directory uri)))
(insert (org-file-contents uri 'noerror))
(let ((org-inhibit-startup t)) (org-mode)) (let ((org-inhibit-startup t)) (org-mode))
(funcall get-options (cons file files)))))) (funcall get-options (cons uri files))))))
((equal key "OPTIONS") ((equal key "OPTIONS")
(setq plist (setq plist
(org-combine-plists (org-combine-plists
@ -1647,17 +1650,22 @@ an alist where associations are (VARIABLE-NAME VALUE)."
"BIND") "BIND")
(push (read (format "(%s)" val)) alist) (push (read (format "(%s)" val)) alist)
;; Enter setup file. ;; Enter setup file.
(let ((file (expand-file-name (let* ((uri (org-unbracket-string "\"" "\"" val))
(org-unbracket-string "\"" "\"" val)))) (uri-is-url (org-file-url-p uri))
(unless (member file files) (uri (if uri-is-url
uri
(expand-file-name uri))))
;; Avoid circular dependencies.
(unless (member uri files)
(with-temp-buffer (with-temp-buffer
(setq default-directory (unless uri-is-url
(file-name-directory file)) (setq default-directory
(file-name-directory uri)))
(let ((org-inhibit-startup t)) (org-mode)) (let ((org-inhibit-startup t)) (org-mode))
(insert (org-file-contents file 'noerror)) (insert (org-file-contents uri 'noerror))
(setq alist (setq alist
(funcall collect-bind (funcall collect-bind
(cons file files) (cons uri files)
alist)))))))))) alist))))))))))
alist))))) alist)))))
;; Return value in appropriate order of appearance. ;; Return value in appropriate order of appearance.

View File

@ -6498,6 +6498,81 @@ Paragraph<point>"
(org-show-set-visibility 'minimal) (org-show-set-visibility 'minimal)
(org-invisible-p2)))) (org-invisible-p2))))
(ert-deftest test-org/org-file-contents-file ()
"Test `org-file-contents' with a file as input."
(should
(string= "#+BIND: variable value
#+DESCRIPTION: l2
#+LANGUAGE: en
#+SELECT_TAGS: b
#+TITLE: b
#+PROPERTY: a 1
" (org-file-contents (expand-file-name "setupfile3.org"
(concat org-test-dir "examples/")))))
(let ((invalid-file "this-file-must-not-exist"))
;; Throw error when trying to access an invalid file.
(should-error
(org-file-contents invalid-file))
;; Try to access an invalid file, but do not throw an error.
(should
(string-match-p "\\`Opening input file: No such file or directory"
(org-file-contents invalid-file :noerror)))))
(ert-deftest test-org/org-file-contents-url ()
"Test `org-file-contents' with a URL as input."
(should
(string= "foo"
(let ((buffer (generate-new-buffer "url-retrieve-output")))
(unwind-protect
;; Simulate successful retrieval of a URL.
(cl-letf (((symbol-function 'url-retrieve-synchronously)
(lambda (&rest_)
(with-current-buffer buffer
(insert "HTTP/1.1 200 OK\n\nfoo"))
buffer)))
(org-file-contents "http://some-valid-url"))
(kill-buffer buffer)))))
(let ((invalid-url "http://this-url-must-not-exist"))
;; Throw error when trying to access an invalid URL.
(should-error
(let ((buffer (generate-new-buffer "url-retrieve-output")))
(unwind-protect
;; Simulate unsuccessful retrieval of a URL.
(cl-letf (((symbol-function 'url-retrieve-synchronously)
(lambda (&rest_)
(with-current-buffer buffer
(insert "HTTP/1.1 404 Not found\n\ndoes not matter"))
buffer)))
(org-file-contents invalid-url))
(kill-buffer buffer))))
;; Try to access an invalid URL, but do not throw an error.
(should-error
(let ((buffer (generate-new-buffer "url-retrieve-output")))
(unwind-protect
;; Simulate unsuccessful retrieval of a URL.
(cl-letf (((symbol-function 'url-retrieve-synchronously)
(lambda (&rest_)
(with-current-buffer buffer
(insert "HTTP/1.1 404 Not found\n\ndoes not matter"))
buffer)))
(org-file-contents invalid-url))
(kill-buffer buffer))))
(should
(string=
(format "Unable to fetch file from \"%s\"" invalid-url)
(let ((buffer (generate-new-buffer "url-retrieve-output")))
(unwind-protect
;; Simulate unsuccessful retrieval of a URL.
(cl-letf (((symbol-function 'url-retrieve-synchronously)
(lambda (&rest_)
(with-current-buffer buffer
(insert "HTTP/1.1 404 Not found\n\ndoes not matter"))
buffer)))
(org-file-contents invalid-url :noerror))
(kill-buffer buffer)))))))
(provide 'test-org) (provide 'test-org)

View File

@ -232,6 +232,38 @@ num:2 <:active")))
org-test-dir) org-test-dir)
(org-export--get-inbuffer-options)) (org-export--get-inbuffer-options))
'(:language "fr" :select-tags ("a" "b" "c") :title ("a b c")))) '(:language "fr" :select-tags ("a" "b" "c") :title ("a b c"))))
;; Options set through SETUPFILE specified using a URL.
(let ((buffer (generate-new-buffer "url-retrieve-output")))
(unwind-protect
;; Simulate successful retrieval of a setupfile from URL.
(cl-letf (((symbol-function 'url-retrieve-synchronously)
(lambda (&rest_)
(with-current-buffer buffer
(insert "HTTP/1.1 200 OK
# Contents of http://link-to-my-setupfile.org
#+BIND: variable value
#+DESCRIPTION: l2
#+LANGUAGE: en
#+SELECT_TAGS: b
#+TITLE: b
#+PROPERTY: a 1
"))
buffer)))
(should
(equal
(org-test-with-temp-text
"#+DESCRIPTION: l1
#+LANGUAGE: es
#+SELECT_TAGS: a
#+TITLE: a
#+SETUPFILE: \"http://link-to-my-setupfile.org\"
#+LANGUAGE: fr
#+SELECT_TAGS: c
#+TITLE: c"
(org-export--get-inbuffer-options))
'(:language "fr" :select-tags ("a" "b" "c") :title ("a b c")))))
(kill-buffer buffer)))
;; More than one property can refer to the same buffer keyword. ;; More than one property can refer to the same buffer keyword.
(should (should
(equal '(:k2 "value" :k1 "value") (equal '(:k2 "value" :k1 "value")