From: Nicolas Goaziou <mail@nicolasgoaziou.fr>
To: Rasmus <rasmus@gmx.us>
Cc: emacs-orgmode@gnu.org
Subject: Re: [ox-publish, patch] More flexible sitemaps
Date: Mon, 23 May 2016 00:58:14 +0200 [thread overview]
Message-ID: <87twhpk8e1.fsf@saiph.selenimh> (raw)
In-Reply-To: <87eg8ydpli.fsf@gmx.us> (rasmus@gmx.us's message of "Thu, 19 May 2016 17:39:21 +0200")
Hello,
Rasmus <rasmus@gmx.us> writes:
> I've long wanted to use ox to auto-generate something that looks like a
> blog index.
>
> This patch makes ox sitemaps a bit more flexible. For instance, it would
> allow me to use something like this for ‘:sitemap-file-entry-format’,
>
> :sitemap-file-entry-format "* [[file:%l][%t]]
> #+include: \"%f::lead\"
>
> [[file:%l][Read more]]"
>
> Which would come out as;
>
> * [[file:link][Title]]
> #+Include: "file.org::lead"
>
> [[File:link][Read more]]
>
> For the tests I did, it matches the "old" sitemap for list and tree.
>
> WDYT?
It sounds interesting. Usual nitpicking follows.
> * lisp/ox-publish.el (org-publish-sitemap-file-entry-format): Support
> more formatters.
> (org-publish-sitemap-dir-entry-format): New defcustom.
> (org-publish-org-sitemap): Use new variables and functions.
> (org-publish-org-sitemap-as-list): New function.
> (org-publish--tree-assoc): New function.
> (org-pubish--order-files-by-dir-tree): New function.
> (org-publish-find-title): New function.
This is not a new function.
> (org-publish-find-subtitle): New function.
> (org-publish-org-sitemap-as-tree): New function.
> (org-publish--find-property): Find arbirary property.
> (org-publish-project-alist): Document changes.
> * doc/org.texi (Sitemap): Update documentation.
All in all, I think this deserves to be split into 3 patches: one for
the preamble-postamble feature, another one for implementing
`org-publish--find-property' and associated refactoring, and the latter
for the sitemap itself.
> +(autoload 'message-flatten-list "message")
> +(autoload 'dired-tree-lessp "dired-aux")
I hope we can avoid these. In particular, why are you using
`dired-tree-lessp' instead of `org-publish-compare-directory-files'?
> @@ -399,6 +469,7 @@ This splices all the components into the list."
> (defvar org-publish-sitemap-requested)
> (defvar org-publish-sitemap-date-format)
> (defvar org-publish-sitemap-file-entry-format)
> +(defvar org-publish-sitemap-dir-entry-format)
The above is not necessary.
> + (files (nreverse
> + ;; Sitemap shouldn't list itself.
> + (cl-delete-if (lambda (f)
> + (equal (file-truename f)
> + (file-truename sitemap-filename)))
See `file-equal-p'.
> + (org-publish-get-base-files
> + project
> + (plist-get project-plist :exclude)))))
> (sitemap-title (or (plist-get project-plist :sitemap-title)
> - (concat "Sitemap for project " (car project))))
> - (sitemap-style (or (plist-get project-plist :sitemap-style)
> - 'tree))
> - (sitemap-sans-extension
> - (plist-get project-plist :sitemap-sans-extension))
> + (concat "Sitemap for project " (car project))))
> (visiting (find-buffer-visiting sitemap-filename))
> - file sitemap-buffer)
> - (with-current-buffer
> - (let ((org-inhibit-startup t))
> - (setq sitemap-buffer
> - (or visiting (find-file sitemap-filename))))
> + (sitemap-buffer (or visiting (find-file sitemap-filename)))
> + (insert-pre-or-postamble (function (lambda (pre-or-postamble)
No need to wrap `function' around `lambda'. Also, it doesn't "insert"
anything, does it? IOW, isn't the name a bit confusing ?
> + (when pre-or-postamble
You can include the `when' in the cond:
(cond ((not pre-or-postamble) nil)
((stringp pre-or-postamble) ...)
...)
> + (cond ((stringp pre-or-postamble) pre-or-postamble)
> + ((listp pre-or-postamble)
> + (mapconcat 'identity preamble "\n"))
> + ((functionp pre-or-postamble)
> + (funcall pre-or-postamble project-plist))
> + (t (error (concat "unknown `:sitemap-preamble' or "
> + "`:sitemap-postamble' format")))))))))
> + (with-current-buffer (let ((org-inhibit-startup t)) sitemap-buffer)
You can drop the `let' part, which is a no-op here.
> + ;; Insert sitemap-preamble.
> + (funcall insert-pre-or-postamble
> + (plist-get project-plist :sitemap-preamble))
> + ;; Call function to build sitemap based on files and the project-plist.
> + (insert (funcall (intern
> + (concat "org-publish-org-sitemap-as-"
> + (symbol-name (or (plist-get project-plist :sitemap-style) 'tree))))
> + files project-plist))
(intern (format "org-publish-org-sitemap-as-%s" (or (plist-get ...) 'tree))
You may want to check that it does exist before and raise an error
otherwise.
> + ;; Insert sitemap-postamble.
> + (funcall insert-pre-or-postamble
> + (plist-get project-plist :sitemap-postamble))
> (save-buffer))
Not directly related, but `save-buffer' here is suspicious. It may be
better to use `with-temp-file' instead.
> +(defun org-publish-org-sitemap-as-list (files project-plist)
> + "Insert FILES as simple list separated by newlines.
> +PROJECT-PLIST holds the project information."
> + (mapconcat
> + (lambda (file) (org-publish-format-file-entry
> + org-publish-sitemap-file-entry-format
> + file project-plist))
> + files "\n"))
Mind indentation
(lambda (file)
(org-publish-format-file-entry ...))
> +(defun org-publish--dir-parent (dir)
> + "Return directory parent of DIR"
> + (let ((dir (file-name-directory dir)))
> + (substring dir 0 (string-match-p "[^/]+/?\\'" dir))))
(file-name-directory (directory-file-name dir))
> +(defun org-publish--tree-assoc (key tree)
> + "Traverse TREE to find list for which the car is `equal' to KEY."
> + (and (consp tree)
> + (cl-destructuring-bind (tree-car . tree-cdr) tree
> + (if (equal tree-car key) tree
> + (or (org-publish--tree-assoc key tree-car)
> + (org-publish--tree-assoc key tree-cdr))))))
> +
> +(defun org-pubish--order-files-by-dir-tree (files)
> + "Order FILES according to the file tree."
> + (let* ((dirs (sort
> + (delq nil (delete-dups (mapcar 'file-name-directory files)))
> + 'dired-tree-lessp))
> + (file-list (list (pop dirs))))
> + (dolist (dir dirs)
> + (or (nconc (org-publish--tree-assoc
> + (org-publish--dir-parent dir)
> + file-list)
> + (list (list dir)))
> + (nconc file-list dir)))
> + (dolist (file files)
> + (nconc (org-publish--tree-assoc
> + (file-name-directory file) file-list)
> + (list file)))
> + (message-flatten-list file-list)))
I don't understand why you need the 2 functions above. You are working
with plain lists, not nested ones. Besides, once the file name are
standardized, isn't tree order equivalent to lexicographic one?
> + (let ((basedir (file-truename (plist-get project-plist :base-directory))))
> + (when (and (file-exists-p file)
> + (not (equal file basedir)))
`file-equal-p'
> + (let* ((filename (file-relative-name file basedir))
> + (dirname (file-name-directory filename))
> + (depth (if (or (eq 'list (plist-get project-plist :sitemap-style))
> + (not dirname))
> + 1
> + (+ (if (not (directory-name-p filename)) 1 0)
> + (length (split-string (file-name-directory filename) "/" t)))))
> + (link (funcall (if (plist-get project-plist :sitemap-sans-extension)
> + 'file-name-sans-extension
> + 'identity)
#'file-name-sans-extension and #'identity
> + (format-spec
> + fmt
> + `((?t . ,(and (not (directory-name-p file)) (org-publish-find-title file t)))
> + (?s . ,(and (not (directory-name-p file)) (org-publish-find-subtitle file t)))
> + (?f . ,filename)
> + (?F . ,(directory-file-name
> + (if (directory-name-p filename)
> + (file-relative-name
> + dirname (org-publish--dir-parent dirname))
> + (file-relative-name filename dirname))))
> + (?l . ,link)
> + (?h . ,(concat (make-string depth ?*)))
> + (?i . ,(concat (make-string (* 2 depth) ? ) "-"))
(make-string (* 2 depth) ?\s)
> + (?d . ,(and (not (directory-name-p file))
> + (format-time-string
> + (or (plist-get project-plist :sitemap-date-format)
> + org-publish-sitemap-date-format)
> + (org-publish-find-date file))))
> + (?a . ,(or (plist-get project-plist :author) user-full-name))))))))
> +
> +(defun org-publish-find-subtitle (file &optional reset)
> + "Find the title of FILE in project."
> + (org-publish--find-property file :subtitle reset))
I don't think this would work. :subtitle is not defined in default
export properties, it is back-end specific. `org-export-get-environment'
without any argument, doesn't catch these. You need to somehow provide
it the back-end.
Regards,
--
Nicolas Goaziou
next prev parent reply other threads:[~2016-05-22 22:58 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-05-19 15:39 [ox-publish, patch] More flexible sitemaps Rasmus
2016-05-22 22:58 ` Nicolas Goaziou [this message]
2016-05-27 16:41 ` Rasmus
2016-06-01 15:34 ` Nicolas Goaziou
2016-07-05 11:08 ` Robert Klein
2016-07-06 11:17 ` Rasmus
2016-07-07 9:03 ` Rasmus
2016-07-20 7:56 ` 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=87twhpk8e1.fsf@saiph.selenimh \
--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).