#! /bin/sh '': "-*-emacs-lisp-*-"; exec emacs --no-site-file --batch --load "$0" -- "$@" ;;; ;;; Look things up in the Common Lisp Hyperspec. ;;; ;;; (c) 2008 Mark Wooding ;;; ;;;----- Licensing notice --------------------------------------------------- ;;; ;;; This program is free software; you can redistribute it and/or modify ;;; it under the terms of the GNU General Public License as published by ;;; the Free Software Foundation; either version 2 of the License, or ;;; (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA ;;;-------------------------------------------------------------------------- ;;; External dependencies. ;; We need the hyperspec library, obviously. (require 'hyperspec) ;; The init file probably has customizations for the Hyperspec library, in ;; particular where the local Hyperspec files are. ;; ;; Hacking here to suppress messages from the init file, and also to protect ;; us from errors in it. (setq mdw-fast-startup t) (let ((original-message (symbol-function 'message))) (unwind-protect (progn (fset 'message #'(lambda (&rest hunoz) nil)) (condition-case signal (load-file "~/.emacs") (error (funcall original-message "hyperspec (warning): .emacs erred: %s." signal)))) (fset 'message original-message))) ;;;-------------------------------------------------------------------------- ;;; Utilities. (defvar quis "hyperspec") (defun die (&rest format-args) (message "%s: %s" quis (apply #'format format-args)) (kill-emacs 1)) (defvar usage-string "Usage: hyperspec -l | KEY") (defun die-usage () (message "%s" usage-string) (kill-emacs 1)) ;;;-------------------------------------------------------------------------- ;;; Look up a string and find its URL in the Hyperspec. (defun hyperspec-urls (key) "Return a list of hyperspec URLs corresponding to KEY." (let ((urls nil) (lookups (list (list (downcase key) common-lisp-hyperspec-symbols #'(lambda (values) (mapcar (lambda (value) (concat common-lisp-hyperspec-root "Body/" value)) values))) (list (downcase key) common-lisp-hyperspec-issuex-symbols #'(lambda (value) (list (concat common-lisp-hyperspec-root "Issues/" value))))))) (when (= (aref key 0) ?~) (push (list (substring key 1) common-lisp-hyperspec-format-characters #'(lambda (values) (mapcar #'common-lisp-hyperspec-section values))) lookups)) (dolist (lookup lookups) (let* ((name (car lookup)) (obarray (cadr lookup)) (format (car (cddr lookup))) (symbol (intern-soft name obarray))) (when (and symbol (boundp symbol)) (setq urls (nconc urls (funcall format (symbol-value symbol))))))) urls)) (defun good-symbols (obarray &optional filter) "Return the list of bound symbols in OBARRAY for which FILTER returns non-nil; FILTER defaults to always-true if unspecified." (let ((syms nil)) (mapatoms (lambda (sym) (when (and (boundp sym) (or (not filter) (funcall filter sym))) (setq syms (cons sym syms)))) obarray) (sort syms #'string<))) (defun hyperspec-keys () "Return the list of all valid hyperspec lookup keys. Useful for completion." (nconc (good-symbols common-lisp-hyperspec-symbols) (mapcar #'(lambda (name) (format "~%s" name)) (good-symbols common-lisp-hyperspec-format-characters #'(lambda (sym) (= (length (symbol-name sym)) 1)))) (good-symbols common-lisp-hyperspec-issuex-symbols))) ;;;-------------------------------------------------------------------------- ;;; Parse the command line. (defvar key nil) (defvar mode 'url) (defvar options '((("-h" "--help") . help) (("-l" "--list") . (lambda () (setq mode 'list))))) (defun help () (princ usage-string) (princ " Write to stdout a URL to the Hyperspec page describing KEY. Options: -h, --help Show this help message. -l, --list Write to stdout a list of acceptable KEYS. ") (kill-emacs)) ;; Parse the command-line options. (pop command-line-args-left) (catch 'done (while t (unless command-line-args-left (throw 'done nil)) (let ((opt (pop command-line-args-left))) (cond ((string= opt "--") (throw 'done nil)) ((not (eq (aref opt 0) ?-)) (push opt command-line-args-left) (throw 'done nil)) (t (catch 'found (dolist (def options) (when (member opt (car def)) (funcall (cdr def)) (throw 'found nil))) (die "Unknown option `%s'." opt))))))) ;; Check the non-option arguments. (cond ((eq mode 'url) (unless (= (length command-line-args-left) 1) (die-usage)) (let* ((key (car command-line-args-left)) (urls (hyperspec-urls key))) (mapcar #'(lambda (url) (princ url) (terpri)) urls))) ((eq mode 'list) (unless (null command-line-args-left) (die-usage)) (mapc (lambda (item) (princ item) (terpri)) (hyperspec-keys)))) ;;;----- That's all, folks --------------------------------------------------