adamc@350: ;;; urweb-util.el --- Utility functions for urweb-mode adamc@350: adamc@350: ;; Based on sml-mode: adamc@350: ;; Copyright (C) 1999-2000 Stefan Monnier adamc@350: ;; adamc@350: ;; Modified for urweb-mode: adamc@350: ;; Copyright (C) 2008 Adam Chlipala adamc@350: ;; adamc@350: ;; This program is free software; you can redistribute it and/or modify adamc@350: ;; it under the terms of the GNU General Public License as published by adamc@350: ;; the Free Software Foundation; either version 2 of the License, or adamc@350: ;; (at your option) any later version. adamc@350: ;; adamc@350: ;; This program is distributed in the hope that it will be useful, adamc@350: ;; but WITHOUT ANY WARRANTY; without even the implied warranty of adamc@350: ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the adamc@350: ;; GNU General Public License for more details. adamc@350: ;; adamc@350: ;; You should have received a copy of the GNU General Public License adamc@350: ;; along with this program; if not, write to the Free Software adamc@350: ;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. adamc@350: adamc@350: adamc@350: ;;; Commentary: adamc@350: adamc@350: ;;; Code: adamc@350: adamc@350: (require 'cl) ;for `reduce' adamc@350: (require 'urweb-compat) adamc@350: adamc@350: ;; adamc@350: adamc@350: (defun flatten (ls &optional acc) adamc@350: (if (null ls) acc adamc@350: (let ((rest (flatten (cdr ls) acc)) adamc@350: (head (car ls))) adamc@350: (if (listp head) adamc@350: (flatten head rest) adamc@350: (cons head rest))))) adamc@350: adamc@350: (defun urweb-preproc-alist (al) adamc@350: "Expand an alist AL where keys can be lists of keys into a normal one." adamc@350: (reduce (lambda (x al) adamc@350: (let ((k (car x)) adamc@350: (v (cdr x))) adamc@350: (if (consp k) adamc@350: (append (mapcar (lambda (y) (cons y v)) k) al) adamc@350: (cons x al)))) adamc@350: al adamc@350: :initial-value nil adamc@350: :from-end t)) adamc@350: adamc@350: ;;; adamc@350: ;;; defmap adamc@350: ;;; adamc@350: adamc@350: (defun custom-create-map (m bs args) adamc@350: (let (inherit dense suppress) adamc@350: (while args adamc@350: (let ((key (first args)) adamc@350: (val (second args))) adamc@350: (cond adamc@350: ((eq key :dense) (setq dense val)) adamc@350: ((eq key :inherit) (setq inherit val)) adamc@350: ((eq key :group) ) adamc@350: ;;((eq key :suppress) (setq suppress val)) adamc@350: (t (message "Uknown argument %s in defmap" key)))) adamc@350: (setq args (cddr args))) adamc@350: (unless (keymapp m) adamc@350: (setq bs (append m bs)) adamc@350: (setq m (if dense (make-keymap) (make-sparse-keymap)))) adamc@350: (dolist (b bs) adamc@350: (let ((keys (car b)) adamc@350: (binding (cdr b))) adamc@350: (dolist (key (if (consp keys) keys (list keys))) adamc@350: (cond adamc@350: ((symbolp key) adamc@350: (substitute-key-definition key binding m global-map)) adamc@350: ((null binding) adamc@350: (unless (keymapp (lookup-key m key)) (define-key m key binding))) adamc@350: ((let ((o (lookup-key m key))) adamc@350: (or (null o) (numberp o) (eq o 'undefined))) adamc@350: (define-key m key binding)))))) adamc@350: (cond adamc@350: ((keymapp inherit) (set-keymap-parent m inherit)) adamc@350: ((consp inherit) (set-keymap-parents m inherit))) adamc@350: m)) adamc@350: adamc@350: (defmacro defmap (m bs doc &rest args) adamc@350: `(defconst ,m adamc@350: (custom-create-map (if (boundp ',m) ,m) ,bs ,(cons 'list args)) adamc@350: ,doc)) adamc@350: adamc@350: ;; defsyntax ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; adamc@350: adamc@350: (defun custom-create-syntax (css args) adamc@350: (let ((st (make-syntax-table (cadr (memq :copy args))))) adamc@350: (dolist (cs css) adamc@350: (let ((char (car cs)) adamc@350: (syntax (cdr cs))) adamc@350: (if (sequencep char) adamc@350: (mapcar* (lambda (c) (modify-syntax-entry c syntax st)) char) adamc@350: (modify-syntax-entry char syntax st)))) adamc@350: st)) adamc@350: adamc@350: (defmacro defsyntax (st css doc &rest args) adamc@350: `(defconst ,st (custom-create-syntax ,css ,(cons 'list args)) ,doc)) adamc@350: adamc@350: ;;;; adamc@350: ;;;; Compatibility info adamc@350: ;;;; adamc@350: adamc@350: (defvar urweb-builtin-nested-comments-flag adamc@350: (ignore-errors adamc@350: (not (equal (let ((st (make-syntax-table))) adamc@350: (modify-syntax-entry ?\* ". 23n" st) st) adamc@350: (let ((st (make-syntax-table))) adamc@350: (modify-syntax-entry ?\* ". 23" st) st)))) adamc@350: "Non-nil means this Emacs understands the `n' in syntax entries.") adamc@350: adamc@350: (provide 'urweb-util) adamc@350: adamc@350: ;;; urweb-util.el ends here