On Thu, Dec 8, 2016 at 5:40 PM Nicolas Goaziou <address@hidden
Kaushal Modi <address@hidden> writes:
You can use something like `url-insert' and `url-retrieve' or
Thanks. I am using url-retrieve-synchronously.
Sure, but SETUPFILE still accepts local file names. So I was pointing
out that you need to check if the URL is a local file name before
proceeding. In particular, this check needs to happen when using "C-c '"
(which may display URL contents in a read-only buffer, BTW).
Understood. I might need some help when baking this into org.el, org-macros.el, etc.
Is it necessary? File contents could be stored in, e.g., a hash table,
url being the key. The file is downloaded only if the entry doesn't
exist in the table and the user didn't force download.-
Correct. Thanks for the idea. I am now using hash table for this.
Here is my implementation.. it is still not baked into org.el, etc and provided as a complete patch; I have some questions..
(defvar org-setupfile-ht (make-hash-table :test 'equal)
"Hash table to store the org SETUPFILE.
This acts as a cache of setup files read using `org-insert-setupfile-contents'.")
(defun org-setupfile-clear-cache ()
"Clear the SETUPFILE cache stored in `org-setupfile-ht'."
(defun org-insert-setupfile-contents (setupfile &optional nocache noerror)
"Insert the contents of SETUPFILE.
SETUPFILE can be a file path or URL.
If SETUPFILE is a file path, use `org-file-contents' to get the file contents.
If it is a URL instead, download the contents. If the URL contents are already
cached in the `org-setupfile-ht' hash table, the download step is skipped.
If NOCACHE is non-nil, do a fresh fetch of SETUPFILE even if cached version is
available. This option applies only if SETUPFILE is a URL.
If NOERROR is non-nil, ignore the error when unable to read the SETUPFILE from
file or URL."
(require 'ffap) ;for `ffap-url-regexp'
(let* ((is-url (string-match-p ffap-url-regexp setupfile))
(cache (when (and is-url (not nocache))
(gethash setupfile org-setupfile-ht)))
(contents (when (and is-url cache) cache)))
(with-current-buffer (url-retrieve-synchronously setupfile)
;; Take point to after the url-retrieve header
(re-search-forward "\n\n") ; 2 consecutive new-line chars
(setq url-retrieve-header (buffer-substring-no-properties
(message url-retrieve-header) ;Dump the URL retrieve header to *Messages*
(if (string-match-p "HTTP.*\\s-+200\\s-OK" url-retrieve-header) ;URL retrieved correctly
(setq contents (buffer-substring-no-properties (point) (point-max)))
;; Update the cache `org-setupfile-ht'
(puthash setupfile contents org-setupfile-ht))
(funcall (if noerror 'message 'error)
"Unable to fetch SETUPFILE from `%s'" setupfile)))))
(setq contents (org-file-contents setupfile noerror)))
- All the places where the content of SETUPFILE is inserted in a temp buffer, it is assumed that the file is retrieved from disk and not from URL.
Example in ox.el:
((equal key "SETUPFILE")
(org-unbracket-string "\"" "\"" (org-trim val)))))
;; Avoid circular dependencies.
(unless (member file files)
(insert (org-file-contents file 'noerror))
(let ((org-inhibit-startup t)) (org-mode))
(funcall get-options (cons file files))))))
Note the use of expand-file-name, (member file files), default-directory, (funcall get-options (cons file files)).
How do we deal with those parts of the code when the 'file' is a URL.
Using my implementation above,
(org-insert-setupfile-contents "/file/path/or/url" nil :noerror)
works the same way as
(insert (org-file-contents "/file/path" 'noerror))
So org-insert-setupfile-contents can replace (insert (org-file-contents ..)) easily. The unknown is how to deal with the surrounding code that deals with
> expand-file-name, (member file files), default-directory, (funcall get-options (cons file files)).
Here's a similar code snippet around setupfile insertion in ox.el again, in org-export--list-bound-variables: