Static Websites Management Functions
These functions complement
org-mode publishing features by adding
a local preview and a deploy function using
website-server-start(and corresponding stop function)
Projects managed with these functions need to be declared in a association list using:
Project Specification Association List
Previewing and deploying are managed with emacs-lisp functions which allows to select the project to preview or publish.
The following code builds an association list with all the information required to preview and publish a website, namely:
( project-name (:port project-port :dir project-dir :deploy-dir deploy-cmd :no-sources no-sources) )
Note that since
project-name is a reference to a project defined
org-publish-project-alist (and, as such, it allows us to get
information about source directory, etc.)
(defvar website-alist nil "List of websites managed with functions defined in this file") (defun website-add (name preview-port local-dest deploy-dest &optional no-sources) "Add a website specification to the list of managed websites. Arguments: - name (name of project) - preview-port (local port used for previewing) - local-dest (directory in which html files are placed) - deploy-dest (directory where html files are deployed)" (setq website-alist (cons (cons name `(:port ,preview-port :dir ,local-dest :deploy-dir ,deploy-dest :no-sources ,no-sources)) website-alist))) (defun website-remove (name) "Delete website specification =name= from the list of managed websites. Useful if you want to reload a configuration." (setq website-alist (assoc-delete-all name website-alist))) ;; (boundp (quote website-alist))
This is syntactic sugar, since
org-mode already provides these
(defun website-build (project &optional force async) "Build a website (invoke org-publish)" (interactive (list (assoc (completing-read "Publish project: " website-alist nil t) website-alist) current-prefix-arg)) (org-publish (car project) force async))
Define two functions which start and stop a webserver serving
website whose specification is stored in
The elnode tutorial provides the example code for starting and
stopping the server.
These functions can be safely moved to the Emacs initialization file, especially when there is more than one project:
(require 'elnode nil t) (defun website-server-start () "Ask for a project name and start previewing it" (interactive) (let* ( (project-name (completing-read "Website to start previewing: " (mapcar (lambda (x) (car x)) website-alist))) ) (website-server-start-ll project-name))) (defalias 'website-preview 'website-server-start) (defun website-server-start-ll (project-name) "Start previewing a project whose name is passed as argument" (let ( (port (plist-get (cdr (assoc project-name website-alist)) :port)) (dir (plist-get (cdr (assoc project-name website-alist)) :dir)) ) (progn (elnode-start (elnode-webserver-handler-maker dir) :port port :host "localhost") (message "Started serving directory %s on port %s" dir port)))) (defun website-server-stop () "Stop previewing a project" (interactive) (let* ( (project-name (completing-read "Website to stop previewing: " (mapcar (lambda (x) (car x)) website-alist))) ) (website-server-stop-ll project-name))) (defun website-server-stop-ll (project-name) "Stop previewing a project passed as argument" (let ( (port (plist-get (cdr (assoc project-name website-alist)) :port)) ) (elnode-stop port)))
Define a function which invokes the deploy command for the project.
All project specifications are stored in
The code for deploying has been taken from:
A more structured solution probably uses
call-process, but I did not
want to have to manage shell expansions.
This function can be safely moved to the Emacs initialization file, especially when there is more than one project:
(defun website-deploy () (interactive) (let* ( (webserver (completing-read "Website to deploy: " (mapcar (lambda (x) (car x)) website-alist))) (local-dir (plist-get (cdr (assoc webserver website-alist)) :dir)) (deploy-dir (plist-get (cdr (assoc webserver website-alist)) :deploy-dir)) (exclude-sources (plist-get (cdr (assoc webserver website-alist)) :no-sources)) (buffer (get-buffer-create (concat "*rsync-buffer for " webserver "*"))) ) (if deploy-dir (progn (display-buffer buffer) (start-process "process-name" buffer "/usr/bin/rsync" "-crvz" "--exclude=*~" "--exclude=.git" "--exclude=_*" (if exclude-sources "--exclude=*.org" "--include=*.org") "--delete" "--delete-excluded" (file-name-as-directory local-dir) ; add a final slash (otherwise local-dir might be created on the server instead) deploy-dir)) (message "No deployment command specified for %s" webserver))))
What do we provide?