X-Git-Url: https://git.korewanetadesu.com/?p=pelican-mode.git;a=blobdiff_plain;f=pelican-mode.el;h=e0f522338c998099ddabbf37814a26d849a34629;hp=f82be8a09194fafdf26ff9620673a965d0da00c2;hb=51d1a9224c25a4b579e63c57ef2d272c0b538a67;hpb=3315a18243301484682db5648146579430001772 diff --git a/pelican-mode.el b/pelican-mode.el index f82be8a..e0f5223 100644 --- a/pelican-mode.el +++ b/pelican-mode.el @@ -29,18 +29,35 @@ ;;; Code: +(require 'seq) (require 'subr-x) + (defun pelican-timestamp (&optional time) "Generate a Pelican-compatible timestamp for TIME." (format-time-string "%Y-%m-%d %H:%M" time)) -(defun pelican-is-markdown () - "Check if the buffer is likely using Markdown." - (derived-mode-p 'markdown-mode)) - (defun pelican-field (name value) - "Format a line for a field NAME with a VALUE." + "Format a line for a field NAME with a VALUE. + +NAME may be a string or a symbol; if it is a symbol, the +symbol name is used (removing a leading ':' if present). + +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-timestamp'. + +- `slug' means the file's path relative to the document root sans + extension; see `pelican-default-slug'. + +- nil means return an empty string, without any name or value." + (setq value (pcase value + ('now (pelican-timestamp)) + ('slug (pelican-default-slug)) + (_ value))) + (when (symbolp name) + (setq name (string-remove-prefix ":" (symbol-name name)))) (if value (cond ((derived-mode-p 'markdown-mode) (format "%s: %s\n" (capitalize name) value)) @@ -49,48 +66,54 @@ (t (error "Unsupported major mode %S" major-mode))) "")) +(defun pelican-rst-title (title) + "Create a ReSt version of TITLE." + (concat title "\n" (make-string (string-width title) ?#) "\n\n")) + (defun pelican-title (title) "Format a TITLE for the current document, according to major mode." (cond ((derived-mode-p 'markdown-mode) (pelican-field "title" title)) ((derived-mode-p 'rst-mode) - (concat title "\n" (make-string (string-width title) ?#) "\n")) + (pelican-rst-title title)) (t (error "Unsupported major mode %S" major-mode)))) -(defun pelican-header (title date status category tags slug) - "Create a Pelican header." - ;; TODO: Use a property list (-> alist via seq-partition) instead. - (when (eq date t) - (setq date (pelican-timestamp))) - +(defun pelican-header (title &rest fields) + "Generate a Pelican header for a post with a TITLE and metadata FIELDS." (concat (pelican-title title) - (pelican-field "date" date) - (pelican-field "status" status) - (pelican-field "tags" tags) - (pelican-field "category" category) - (pelican-field "slug" slug) + (mapconcat (apply-partially #'apply #'pelican-field) + (seq-partition fields 2) "") "\n")) +(defun pelican-insert-header (title &rest fields) + "Insert a Pelican header for a post with a TITLE and metadata FIELDS." + (save-excursion + (goto-char 0) + (insert (apply #'pelican-header (cons title fields))))) + (defun pelican-insert-draft-post-header (title tags) - "Insert a Pelican header for a draft post." + "Insert a Pelican header for a draft with a TITLE and TAGS." (interactive "sPost title: \nsTags: ") - (let ((slug (pelican-default-slug))) - (save-excursion - (goto-char 0) - (insert (pelican-header title 't "draft" nil tags slug))))) - -(defun pelican-insert-page-header (title hidden) - "Insert a Pelican header for a page." + (save-excursion + (goto-char 0) + (insert (pelican-header title + :date 'now + :status "draft" + :tags tags + :slug 'slug)))) + +(defun pelican-insert-page-header (title &optional hidden) + "Insert a Pelican header for a page with a TITLE, potentially HIDDEN." (interactive (list (read-string "Page title: ") (y-or-n-p "Hidden? "))) - (let ((slug (pelican-default-slug)) - (hidden (if hidden "hidden" nil))) - (save-excursion - (goto-char 0) - (insert (pelican-header title nil hidden nil nil slug))))) + (save-excursion + (goto-char 0) + (insert (pelican-header title + :status (when hidden "hidden") + :slug 'slug)))) -(defun pelican-insert-header () +(defun pelican-insert-auto-header () "Insert a Pelican header for a page or post." (interactive) (call-interactively (if (pelican-is-page) @@ -99,13 +122,28 @@ (defun pelican-set-field (field value) "Set FIELD to VALUE." + (interactive "sField: \nsValue: ") (save-excursion (goto-char 0) (if (re-search-forward (concat "^" (pelican-field field ".+*")) nil t) (replace-match (pelican-field field value)) + (re-search-forward "#") + (forward-line 2) (re-search-forward "^$") (replace-match (pelican-field field value))))) +(defun pelican-set-title (title) + "Set the title to TITLE." + (interactive "sTitle: ") + (if (derived-mode-p 'markdown-mode) + (pelican-set-field "title" title) + (save-excursion + (goto-char 0) + (let ((header (pelican-rst-title title))) + (if (looking-at ".*\n#+\n+") + (replace-match header) + (insert header)))))) + (defun pelican-update-date () "Update a Pelican date header." (interactive) @@ -157,20 +195,12 @@ "Check if this buffer is under a Pelican site." (not (null (pelican-find-root)))) -(defun pelican-enable-if-site () - "Enable `pelican-mode' if this buffer is under a Pelican site." - (when (pelican-is-in-site) - (pelican-mode 1))) - (defun pelican-make (target) "Execute TARGET in a Makefile at the root of the site." (interactive "sMake Pelican target: ") - (if-let ((default-directory (pelican-find-root))) - (let ((output (get-buffer-create "*Pelican Output*"))) - (display-buffer output) - (pop-to-buffer output) - (compilation-mode) - (start-process "Pelican Makefile" output "make" target)) + (if-let (default-directory (pelican-find-root)) + (compilation-start (format "make %s" target) + nil (lambda (_) "*pelican*")) (message "This doesn't look like a Pelican site."))) (defun pelican-make-html () @@ -186,7 +216,7 @@ (defconst pelican-keymap (make-sparse-keymap) "The default keymap used in Pelican mode.") (define-key pelican-keymap (kbd "C-c P n") - 'pelican-insert-header) + 'pelican-insert-auto-header) (define-key pelican-keymap (kbd "C-c P p") 'pelican-publish-draft) (define-key pelican-keymap (kbd "C-c P t") @@ -202,12 +232,17 @@ "Toggle Pelican mode. Interactively with no argument, this command toggles the mode. -to show buffer size and position in mode-line." +for editing Pelican site files." :init-value nil :lighter " Pelican" :keymap pelican-keymap :group 'pelican) +;;;###autoload +(defun pelican-enable-if-site () + "Enable `pelican-mode' if this buffer is under a Pelican site." + (when (pelican-is-in-site) + (pelican-mode 1))) ;;;###autoload (add-hook 'markdown-mode-hook 'pelican-enable-if-site)