From 2442f07f94c4b90bceae26d04fa593d3a9eba3ff Mon Sep 17 00:00:00 2001 From: Joe Wreschnig Date: Mon, 7 Aug 2017 13:14:04 +0200 Subject: [PATCH] Put public interest points near the top of the file. Change the date keybind to `C-c P d`. --- README.md | 2 +- pelican-mode.el | 299 ++++++++++++++++++++++++++---------------------- 2 files changed, 162 insertions(+), 139 deletions(-) diff --git a/README.md b/README.md index 8ab9c6a..0869e4b 100644 --- a/README.md +++ b/README.md @@ -23,11 +23,11 @@ To enable by default on all text files in a Pelican site: Or, register `pelican-mode` or `pelican-mode-enable-if-site` as hook functions for more direct control. +* `C-c P d` - Update the document’s date * `C-c P f` - Set a metadata field (title, category, etc.) * `C-c P h` - Generate HTML output for a site (equivalent to `make html`) * `C-c P n` - Insert a post or page header * `C-c P p` - Remove draft status from a post (i.e. publish it) -* `C-c P t` - Update the date field in a post/page header * `C-c P u` - Upload a site using rsync (equivalent to `make rsync_upload`) diff --git a/pelican-mode.el b/pelican-mode.el index f7fe300..85d2be9 100644 --- a/pelican-mode.el +++ b/pelican-mode.el @@ -20,6 +20,7 @@ ;; You should have received a copy of the GNU General Public License ;; along with this program. If not, see . + ;;; Commentary: ;; @@ -47,12 +48,78 @@ ;; Or, register `pelican-mode' or `pelican-mode-enable-if-site' ;; as hook functions for more direct control. + ;;; Code: (require 'seq) (require 'subr-x) +;; Mode Definition + +;;;###autoload +(define-minor-mode pelican-mode + "Toggle Pelican mode. +With a prefix argument ARG, enable Pelican mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +Pelican is a static site generator which can process a variety of +text file formats. For more information, see URL +https://blog.getpelican.com/. + +Rather than manually enabling this mode, you may wish to use +`pelican-global-mode' or `pelican-mode-enable-if-site'. + +When Pelican mode is enabled, additional commands are available +for editing articles or pages: + +\\{pelican-mode-map}" + :lighter " Pelican" + :keymap `((,(kbd "C-c P d") . pelican-mode-update-date) + (,(kbd "C-c P f") . pelican-set-field) + (,(kbd "C-c P h") . pelican-make-html) + (,(kbd "C-c P n") . pelican-mode-insert-header) + (,(kbd "C-c P p") . pelican-mode-publish-draft) + (,(kbd "C-c P u") . pelican-make-rsync-upload))) + +;;;###autoload +(define-minor-mode pelican-global-mode + "Toggle Pelican global mode. +With a prefix argument ARG, enable Pelican global mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +Pelican is a static site generator which can process a variety of +text file formats. For more information, see URL +https://blog.getpelican.com/. + +When Pelican global mode is enabled, text files which seem to +be part of a Pelican site will have `pelican-mode' automatically +enabled. + +If you disable this, you may still enable `pelican-mode' manually +or add `pelican-mode-enable-if-site' to more specific mode +hooks." + :global t + :group 'pelican-mode + (if pelican-global-mode + (add-hook 'text-mode-hook #'pelican-mode-enable-if-site) + (remove-hook 'text-mode-hook #'pelican-mode-enable-if-site))) + +;;;###autoload +(defun pelican-mode-enable-if-site () + "Enable `pelican-mode' if this buffer is part of a Pelican site. + +Pelican sites are detected by looking for a file named `pelicanconf.py' +in an ancestor directory." + (when (pelican-mode-find-root) + (pelican-mode))) + + + +;; Customizations + (defgroup pelican-mode nil "Support for Pelican articles and pages. @@ -78,8 +145,8 @@ about metadata fields and special values." :type '(plist)) (defcustom pelican-mode-formats - '((markdown-mode . pelican-mode-set-field-markdown-mode) - (adoc-mode . pelican-mode-set-field-adoc-mode) + '((adoc-mode . pelican-mode-set-field-adoc-mode) + (markdown-mode . pelican-mode-set-field-markdown-mode) (org-mode . pelican-mode-set-field-org-mode) (rst-mode . pelican-mode-set-field-rst-mode)) "Functions to handle setting metadata, based on major mode. @@ -89,14 +156,68 @@ arguments, field and value strings." :group 'pelican-mode :type '(alist :key-type function :value-type function)) -(defun pelican-mode-timestamp (&optional time) - "Generate a pelican-mode-compatible timestamp for TIME." - (format-time-string "%Y-%m-%d %H:%M" time)) + -(defun pelican-mode-set-fields (&rest fields) - "Insert a Pelican header for an article with metadata FIELDS." - (mapc (apply-partially #'apply #'pelican-mode-set-field) - (seq-partition fields 2))) +;; User Commands + +(defun pelican-mode-set-field (field value) + "Set FIELD to VALUE. + +FIELD may be a string or a symbol; if it is a symbol, the +symbol name is used (removing a leading ':' if present). + +When called from Lisp, VALUE may be any value; except for the +following special values, the unquoted printed representation of +it is used: + +- `now' means the current time; see `pelican-mode-timestamp'. + +- `slug' means the file's path relative to the document root sans + extension; see `pelican-mode-default-slug'. + +- nil or an empty string removes the field. + +The buffer must be in a format listed in `pelican-mode-formats' +for this function to work correctly." + (interactive "sField: \nsValue: ") + (setq value (pcase value + ('now (pelican-mode-timestamp)) + ('slug (pelican-mode-default-slug)) + ('"" nil) + (_ value))) + (when (symbolp field) + (setq field (string-remove-prefix ":" (symbol-name field)))) + (let ((set-field + (assoc-default nil pelican-mode-formats #'derived-mode-p))) + (unless set-field + (error "Unsupported major mode %S" major-mode)) + (save-excursion + (goto-char 0) + (funcall set-field field value)))) + +(defun pelican-mode-remove-field (field) + "Remove FIELD." + (interactive "sField: ") + (pelican-mode-set-field field nil)) + +(defun pelican-mode-set-title (title) + "Set the title to TITLE." + (interactive "sTitle: ") + (pelican-mode-set-field :title title)) + +(defun pelican-mode-update-date (&optional original) + "Update the document's modification date. + +If ORIGINAL is non-nil, the publication date is updated rather +than the modification date." + (interactive "P") + (pelican-mode-set-field (if original :date :modified) 'now)) + +(defun pelican-mode-publish-draft () + "Remove draft status from a Pelican article." + (interactive) + (pelican-mode-remove-field :status) + (pelican-mode-update-date :date)) (defun pelican-mode-insert-draft-article-header (title tags) "Insert a Pelican header for a draft with a TITLE and TAGS." @@ -125,6 +246,35 @@ has no status." #'pelican-mode-insert-page-header #'pelican-mode-insert-draft-article-header))) +(defun pelican-make (target) + "Execute TARGET in a Makefile at the root of the site." + (interactive "sMake Pelican target: ") + (if-let (default-directory (pelican-mode-find-root)) + (compilation-start (format "make %s" target) + nil (lambda (_) "*pelican*")) + (user-error "No Pelican site root could be found"))) + +(defun pelican-make-html () + "Generate HTML via a Makefile at the root of the site." + (interactive) + (pelican-make "html")) + +(defun pelican-make-rsync-upload () + "Upload with rsync via a Makefile at the root of the site." + (interactive) + (pelican-make "rsync_upload")) + + + +(defun pelican-mode-timestamp (&optional time) + "Generate a pelican-mode-compatible timestamp for TIME." + (format-time-string "%Y-%m-%d %H:%M" time)) + +(defun pelican-mode-set-fields (&rest fields) + "Insert a Pelican header for an article with metadata FIELDS." + (mapc (apply-partially #'apply #'pelican-mode-set-field) + (seq-partition fields 2))) + (defun pelican-mode-set-field-rst-mode (field value) "Set reStructuredText metadata FIELD to VALUE." (setq field (downcase field)) @@ -191,61 +341,6 @@ has no status." (replace-match text) (insert text)))))) -(defun pelican-mode-set-field (field value) - "Set FIELD to VALUE. - -FIELD may be a string or a symbol; if it is a symbol, the -symbol name is used (removing a leading ':' if present). - -When called from Lisp, VALUE may be any value; except for the -following special values, the unquoted printed representation of -it is used: - -- `now' means the current time; see `pelican-mode-timestamp'. - -- `slug' means the file's path relative to the document root sans - extension; see `pelican-mode-default-slug'. - -- nil or an empty string removes the field. - -The buffer must be in a format listed in `pelican-mode-formats' -for this function to work correctly." - (interactive "sField: \nsValue: ") - (setq value (pcase value - ('now (pelican-mode-timestamp)) - ('slug (pelican-mode-default-slug)) - ('"" nil) - (_ value))) - (when (symbolp field) - (setq field (string-remove-prefix ":" (symbol-name field)))) - (let ((set-field - (assoc-default nil pelican-mode-formats #'derived-mode-p))) - (unless set-field - (error "Unsupported major mode %S" major-mode)) - (save-excursion - (goto-char 0) - (funcall set-field field value)))) - -(defun pelican-mode-remove-field (field) - "Remove FIELD." - (pelican-mode-set-field field nil)) - -(defun pelican-mode-set-title (title) - "Set the title to TITLE." - (interactive "sTitle: ") - (pelican-mode-set-field :title title)) - -(defun pelican-mode-update-date () - "Update a Pelican date header." - (interactive) - (pelican-mode-set-field :date 'now)) - -(defun pelican-mode-publish-draft () - "Remove draft status from a Pelican article." - (interactive) - (pelican-mode-remove-field :status) - (pelican-mode-update-date)) - (defun pelican-mode-page-p () "Return non-nil the current buffer is a Pelican page." (when-let (pelican-mode-base (pelican-mode-find-root)) @@ -269,83 +364,11 @@ for this function to work correctly." "Return the root of the buffer's Pelican site, or nil." (locate-dominating-file default-directory "pelicanconf.py")) -(defun pelican-make (target) - "Execute TARGET in a Makefile at the root of the site." - (interactive "sMake Pelican target: ") - (if-let (default-directory (pelican-mode-find-root)) - (compilation-start (format "make %s" target) - nil (lambda (_) "*pelican*")) - (user-error "No Pelican site root could be found"))) - -(defun pelican-make-html () - "Generate HTML via a Makefile at the root of the site." - (interactive) - (pelican-make "html")) - -(defun pelican-make-rsync-upload () - "Upload with rsync via a Makefile at the root of the site." - (interactive) - (pelican-make "rsync_upload")) - -;;;###autoload -(define-minor-mode pelican-mode - "Toggle Pelican mode. -With a prefix argument ARG, enable Pelican mode if ARG is -positive, and disable it otherwise. If called from Lisp, enable -the mode if ARG is omitted or nil. - -Pelican is a static site generator which can process a variety of -text file formats. For more information, see URL -https://blog.getpelican.com/. - -Rather than manually enabling this mode, you may wish to use -`pelican-global-mode' or `pelican-mode-enable-if-site'. - -When Pelican mode is enabled, additional commands are available -for editing articles or pages: - -\\{pelican-mode-map}" - :lighter " Pelican" - :keymap `((,(kbd "C-c P f") . pelican-set-field) - (,(kbd "C-c P h") . pelican-make-html) - (,(kbd "C-c P n") . pelican-mode-insert-header) - (,(kbd "C-c P p") . pelican-mode-publish-draft) - (,(kbd "C-c P t") . pelican-mode-update-date) - (,(kbd "C-c P u") . pelican-make-rsync-upload))) - -;;;###autoload -(define-minor-mode pelican-global-mode - "Toggle Pelican global mode. -With a prefix argument ARG, enable Pelican global mode if ARG is -positive, and disable it otherwise. If called from Lisp, enable -the mode if ARG is omitted or nil. - -Pelican is a static site generator which can process a variety of -text file formats. For more information, see URL -https://blog.getpelican.com/. - -When Pelican global mode is enabled, text files which seem to -be part of a Pelican site will have `pelican-mode' automatically -enabled. - -If you disable this, you may still enable `pelican-mode' manually -or add `pelican-mode-enable-if-site' to more specific mode -hooks." - :global t - :group 'pelican-mode - (if pelican-global-mode - (add-hook 'text-mode-hook #'pelican-mode-enable-if-site) - (remove-hook 'text-mode-hook #'pelican-mode-enable-if-site))) - -;;;###autoload -(defun pelican-mode-enable-if-site () - "Enable `pelican-mode' if this buffer is part of a Pelican site." - (when (pelican-mode-find-root) - (pelican-mode 1))) - (provide 'pelican-mode) ;;; pelican-mode.el ends here + + ;; Local Variables: ;; sentence-end-double-space: t ;; End: -- 2.20.1