[macemacsjp-cvs 65] CVS update: CarbonEmacsPackage/GPL/css-mode

Back to archive index

Seiji Zenitani zenit****@users*****
2005年 10月 23日 (日) 13:18:04 JST


Index: CarbonEmacsPackage/GPL/css-mode/css-mode-simple.el
diff -u /dev/null CarbonEmacsPackage/GPL/css-mode/css-mode-simple.el:1.1
--- /dev/null	Sun Oct 23 13:18:04 2005
+++ CarbonEmacsPackage/GPL/css-mode/css-mode-simple.el	Sun Oct 23 13:18:04 2005
@@ -0,0 +1,248 @@
+;;; css-mode-simple.el --- A (very) minimal CSS mode.
+
+;; Copyright 2002  Lawrence Mitchell
+;; Copyright 2005  Alex Schroeder
+
+;; 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
+
+;;; Commentary:
+
+;; A (very) minimal CSS mode.  Does indentation, some font-locking and
+;; nothing more.
+
+;;; Code:
+
+(eval-when-compile
+  (defvar comment-quote-nested))
+
+(defvar css-mode-map nil
+  "Keymap for `css-mode'.")
+
+(defvar css-mode-indent-depth 4
+  "*Depth of indentation.")
+
+(defvar css-mode-font-lock-keywords-1
+  (eval-when-compile
+    (let ((keywords (regexp-opt
+                     '("a" "abbr" "acronym" "address" "applet" "area" "b"
+                       "base" "basefont" "bdo" "big" "blockquote" "body" "br"
+                       "button" "caption" "center" "cite" "code" "col"
+                       "colgroup" "dd" "del" "dfn" "dir" "div" "dl" "dt" "em"
+                       "fieldset" "font" "form" "frame" "frameset" "h1" "h2"
+                       "h3" "h4" "h5" "h6" "head" "hr" "html" "i" "iframe"
+                       "img" "input" "ins" "isindex" "kbd" "label" "legend"
+                       "li" "link" "map" "menu" "meta" "noframes" "noscript"
+                       "object" "ol" "optgroup" "option" "p" "param" "pre" "q"
+                       "s" "samp" "script" "select" "small" "span" "strike"
+                       "strong" "style" "sub" "sup" "table" "tbody" "td"
+                       "textarea" "tfoot" "th" "thead" "title" "tr" "tt" "u"
+                       "ul" "var"))))
+      (list
+       (list
+        (concat "\\b\\(" keywords "\\)[]{. \t]")
+        1 'font-lock-keyword-face))))
+  "Normal level higlighting for `css-mode'.")
+
+(defvar css-mode-font-lock-keywords-2
+  (append css-mode-font-lock-keywords-1
+          (eval-when-compile
+            (let ((keywords (regexp-opt
+                             '("azimuth" "background" "background-attachment" "background-color"
+                               "background-image" "background-position" "background-repeat"
+                               "border" "border-collapse" "border-color" "border-spacing"
+                               "border-style" "border-top" "border-right" "border-bottom"
+                               "border-left" "border-top-color" "border-right-color"
+                               "border-bottom-color" "border-left-color" "border-top-style"
+                               "border-right-style" "border-bottom-style" "border-left-style"
+                               "border-top-width" "border-right-width" "border-bottom-width"
+                               "border-left-width" "border-width" "bottom" "caption-side"
+                               "clear" "clip" "color" "content" "counter-increment"
+                               "counter-reset" "cue" "cue-after" "cue-before" "cursor"
+                               "direction" "display" "elevation" "empty-cells" "float" "font"
+                               "font-family" "font-size" "font-size-adjust" "font-stretch"
+                               "font-style" "font-variant" "font-weight" "height" "left"
+                               "letter-spacing" "line-height" "list-style" "list-style-image"
+                               "list-style-position" "list-style-type" "margin" "margin-top"
+                               "margin-right" "margin-bottom" "margin-left" "marker-offset"
+                               "marks" "max-height" "max-width" "min-height" "min-width"
+                               "orphans" "outline" "outline-color" "outline-style"
+                               "outline-width" "overflow" "padding" "padding-top"
+                               "padding-right" "padding-bottom" "padding-left" "page"
+                               "page-break-after" "page-break-before" "page-break-inside"
+                               "pause" "pause-after" "pause-before" "pitch" "pitch-range"
+                               "play-during" "position" "quotes" "richness" "right" "size"
+                               "speak" "speak-header" "speak-numeral" "speak-punctuation"
+                               "speech-rate" "stress" "table-layout" "text-align"
+                               "text-decoration" "text-indent" "text-shadow" "text-transform"
+                               "top" "unicode-bidi" "vertical-align" "visibility" "voice-family"
+                               "volume" "white-space" "widows" "width" "word-spacing"
+                               "z-index"))))
+              (list
+               (list
+                (concat "\\<\\("
+                        keywords
+                        "\\)\\>[ \t]*:")
+                1 'font-lock-type-face)))))
+  "Gaudy level highlighting for `css-mode'.")
+
+;; this is too excessive.
+;; (defvar css-mode-font-lock-keywords-3
+;;   (append css-mode-font-lock-keywords-2
+;;           (eval-when-compile
+;;             (list
+;;              (list
+;;               ":[ \t]*\\(.*\\);"
+;;               1 'font-lock-variable-name-face)
+;;              (list
+;;               ":[ \t]*\\(rgb\\)([ \t]*[0-9]+[ \t]*,[ \t]*[0-9]+[ \t]*,[ \t]*[0-9]+[ \t]*)"
+;;               1 'font-lock-function-name-face 'prepend))))
+;;   "Incredibly over-the-top highlighting for `css-mode'.")
+              
+(defvar css-mode-font-lock-keywords css-mode-font-lock-keywords-1
+  "Default expressions to highlight in `css-mode'.")
+
+(defvar css-mode-syntax-table nil
+  "Syntax table for `css-mode'.")
+
+(defun css-mode ()
+  "Major mode for editing Cascading StyleSheets."
+  (interactive)
+  (kill-all-local-variables)
+  (setq major-mode 'css-mode
+        mode-name "CSS")
+  (use-local-map css-mode-map)
+  ;; set up syntax table.
+  (if css-mode-syntax-table
+      ()
+    (setq css-mode-syntax-table
+          (let ((table (make-syntax-table)))
+            ;; comment characters.
+            (modify-syntax-entry ?/  ". 14" table)
+            (modify-syntax-entry ?*  ". 23"   table)
+            table)))
+  (set-syntax-table css-mode-syntax-table)
+  (make-local-variable 'comment-start)
+  (setq comment-start "/* ")
+  (make-local-variable 'comment-end)
+  (setq comment-end " */")
+  (make-local-variable 'comment-multi-line)
+  (setq comment-multi-line t)
+  (make-local-variable 'comment-quote-nested)
+  (setq comment-quote-nested t)
+  (make-local-variable 'comment-start-skip)
+  (setq comment-start-skip "/\\*+ *")
+  (make-local-variable 'comment-style)
+  (setq comment-style 'extra-line)
+  (make-local-variable 'fill-paragraph-function)
+  (setq fill-paragraph-function 'css-fill)
+  ;; (make-local-variable 'comment-indent-function)
+  ;; (setq comment-indent-function 'css-mode-indent-comment)
+  (setq indent-line-function 'css-mode-indent-line)
+  (setq font-lock-defaults '((css-mode-font-lock-keywords
+                              css-mode-font-lock-keywords-1
+                              css-mode-font-lock-keywords-2))))
+
+;; set up keymap
+(if css-mode-map
+    ()
+  (setq css-mode-map (make-sparse-keymap))
+  (define-key css-mode-map (kbd "RET") 'css-mode-newline-and-indent)
+  (define-key css-mode-map [(tab)] 'css-mode-indent-line)
+  (define-key css-mode-map [(})] 'css-mode-electric-insert-close-brace))
+
+(defun css-mode-calc-indent-level ()
+  "Calculate the indent level for the current line."
+  ;; This counts indentation level based on parenthesis (the first
+  ;; value in the list returned by parse-partial-sexp).  It then
+  ;; corrects as follows: If we're on a line with a closing
+  ;; parenthesis, outdent.  If we're inside a comment, indent by
+  ;; three, unless the line starts with the closing comment sequence.
+  (let* ((indent-data (parse-partial-sexp (point-min)
+					  (line-beginning-position)))
+	 (indent (car indent-data))
+	 (in-comment (nth 4 indent-data))
+	 close-block
+	 close-comment
+	 pos)
+    (save-excursion
+      (back-to-indentation)
+      (setq close-block (looking-at "}")
+	    close-comment (looking-at "\\*/")))
+    (when close-block
+      (setq indent (1- indent)))
+    (setq pos (* indent css-mode-indent-depth))
+    (if (and in-comment (not close-comment))
+	(+ 3 pos)
+      pos)))
+      
+(defun css-mode-indent-line (&optional indent)
+  "Indent the current line.
+
+If optional INDENT is non-nil, use that instead of calculating the
+indent level."
+  (interactive)
+  (let ((indent (or indent (css-mode-calc-indent-level)))
+	pos)
+    (save-excursion
+      (back-to-indentation)
+      (delete-region (point-at-bol) (point))
+      (indent-to indent)
+      (setq pos (point)))
+    (when (> pos (point))
+      (goto-char pos)))); move only forward after indenting
+
+(defun css-mode-newline-and-indent ()
+  "Insert a newline and indent."
+  (interactive)
+  (newline)
+  (css-mode-indent-line))
+
+(defun css-mode-electric-insert-close-brace ()
+  "Insert a closing brace }."
+  (interactive)
+  (insert "}")
+  (css-mode-indent-line)
+  (forward-char))
+
+(defun css-fill (&rest ignore)
+  "Lay out CSS expressions."
+  (interactive)
+  (condition-case data
+      (progn
+	(backward-up-list 1)
+	(forward-char 1)
+	(newline-and-indent)
+	(catch 'done
+	  (let ((start (point)))
+	    (while (re-search-forward "\n\\|;")
+	      (let* ((data (save-excursion
+			     (parse-partial-sexp start (point))))
+		     (depth (nth 0 data))
+		     (in-string (nth 3 data))
+		     (in-comment (nth 4 data)))
+		(when (< depth 0)
+		  (throw 'done t))
+		(when (and (= depth 0)
+			   (not (or in-string in-comment)))
+		  (if (string= (match-string 0) "\n")
+		      (replace-match "")
+		    (newline-and-indent))))))))
+    (scan-error
+     (search-forward "{"))))
+
+(provide 'css-mode)
+
+;;; css-mode-simple.el ends here
Index: CarbonEmacsPackage/GPL/css-mode/css-mode.el
diff -u /dev/null CarbonEmacsPackage/GPL/css-mode/css-mode.el:1.1
--- /dev/null	Sun Oct 23 13:18:04 2005
+++ CarbonEmacsPackage/GPL/css-mode/css-mode.el	Sun Oct 23 13:18:04 2005
@@ -0,0 +1,469 @@
+;;;; A major mode for editing CSS.
+
+;;; Adds font locking, some rather primitive indentation handling and
+;;; some typing help.
+;;;
+(defvar cssm-version "0.11"
+  "The current version number of css-mode.")
+;;; copyright (c) 1998 Lars Marius Garshol, larsg****@ifi*****
+;;; $Id: css-mode.el,v 1.1 2005/10/23 04:18:04 zenitani Exp $
+
+;;; css-mode 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, or (at your
+;;; option) any later version.
+;;;
+;;; css-mode 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 GNU Emacs; see the file COPYING.  If not, write to the
+;;; Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+; Send me an email if you want new features (or if you add them yourself).
+; I will do my best to preserve the API to functions not explicitly marked
+; as internal and variables shown as customizable. I make no promises about
+; the rest.
+
+; Bug reports are very welcome. New versions of the package will appear at
+; http://www.stud.ifi.uio.no/~larsga/download/css-mode.html
+; You can register at the same address if you want to be notified when a
+; new version appears.
+
+; Thanks to Philippe Le Hegaret, Kjetil Kjernsmo, Alf-Ivar Holm and
+; Alfred Correira for much useful feedback. Alf-Ivar Holm also contributed
+; patches.
+
+; To install, put this in your .emacs:
+;
+; (autoload 'css-mode "css-mode")
+; (setq auto-mode-alist       
+;      (cons '("\\.css\\'" . css-mode) auto-mode-alist))
+
+;; Todo:
+
+; - must not color URL file name extensions as class selectors (*.css)
+; - color [] and url() constructs correctly, even if quoted strings present
+; - disregard anything inside strings
+
+;; Possible later additions:
+;
+; - forward/backward style/@media rule commands
+; - more complete syntax table
+
+;; Required modules
+
+(require 'apropos)
+(require 'font-lock)
+(require 'cl)
+
+;;; The code itself
+
+; Customizable variables:
+
+(defvar cssm-indent-level 2 "The indentation level inside @media rules.")
+(defvar cssm-mirror-mode t
+  "Whether brackets, quotes etc should be mirrored automatically on
+  insertion.")
+(defvar cssm-newline-before-closing-bracket nil
+  "In mirror-mode, controls whether a newline should be inserted before the
+closing bracket or not.")
+(defvar cssm-indent-function #'cssm-old-style-indenter
+  "Which function to use when deciding which column to indent to. To get
+C-style indentation, use cssm-c-style-indenter.")
+  
+; The rest of the code:
+
+(defvar cssm-properties
+  '("font-family" "font-style" "font-variant" "font-weight"
+    "font-size" "font" "background-color" "background-image"
+    "background-repeat" "background-attachment" "background-position"
+    "color" "background" "word-spacing" "letter-spacing"
+    "border-top-width" "border-right-width" "border-left-width"
+    "border-bottom-width" "border-width" "list-style-type"
+    "list-style-image" "list-style-position" "text-decoration"
+    "vertical-align" "text-transform" "text-align" "text-indent"
+    "line-height" "margin-top" "margin-right" "margin-bottom"
+    "margin-left" "margin" "padding-top" "padding-right" "padding-bottom"
+    "padding-left" "padding" "border-top" "border-right" "border-bottom"
+    "border-left" "border" "width" "height" "float" "clear" "display"
+    "list-style" "white-space" "border-style" "border-color"
+
+    ; CSS level 2:
+
+    "azimuth" "border-bottom-color" "border-bottom-style"
+    "border-collapse" "border-left-color" "border-left-style"
+    "border-right-color" "border-right-style" "border-top-color"
+    "border-top-style" "caption-side" "cell-spacing" "clip" "column-span"
+    "content" "cue" "cue-after" "cue-before" "cursor" "direction"
+    "elevation" "font-size-adjust" "left" "marks" "max-height" "max-width"
+    "min-height" "min-width" "orphans" "overflow" "page-break-after"
+    "page-break-before" "pause" "pause-after" "pause-before" "pitch"
+    "pitch-range" "play-during" "position" "richness" "right" "row-span"
+    "size" "speak" "speak-date" "speak-header" "speak-punctuation"
+    "speak-time" "speech-rate" "stress" "table-layout" "text-shadow" "top"
+    "visibility" "voice-family" "volume" "widows" "z-index")
+  "A list of all CSS properties.")
+
+(defvar cssm-properties-alist
+  (mapcar (lambda(prop)
+	    (cons (concat prop ":") nil)) cssm-properties)
+  "An association list of the CSS properties for completion use.")
+
+(defvar cssm-keywords 
+  (append '("!\\s-*important"
+    
+	  ; CSS level 2:
+
+	    "@media" "@import" "@page" "@font-face")
+	  (mapcar (lambda(property)
+		    (concat property "\\s-*:"))
+		  cssm-properties))
+  "A list of all CSS keywords.")
+
+(defvar cssm-pseudos
+  '("link" "visited" "active" "first-line" "first-letter"
+
+    ; CSS level 2
+    "first-child" "before" "after" "hover")
+  "A list of all CSS pseudo-classes.")
+
+; internal
+(defun cssm-list-2-regexp(altlist)
+  "Takes a list and returns the regexp \\(elem1\\|elem2\\|...\\)"
+  (let ((regexp "\\("))
+    (mapcar (lambda(elem)
+	      (setq regexp (concat regexp elem "\\|")))
+	    altlist)
+    (concat (substring regexp 0 -2) ; cutting the last "\\|"
+	    "\\)")
+    ))
+
+(defvar cssm-font-lock-keywords
+  (list
+   (cons (cssm-list-2-regexp cssm-keywords) font-lock-keyword-face)
+   (cons "\\.[a-zA-Z][-a-zA-Z0-9.]+" font-lock-variable-name-face)
+   (cons (concat ":" (cssm-list-2-regexp cssm-pseudos))
+	 font-lock-variable-name-face)
+   (cons "#[a-fA-F0-9][a-fA-F0-9][a-fA-F0-9]\\([a-fA-F0-9][a-fA-F0-9][a-fA-F0-9]\\)?"
+	 font-lock-reference-face)
+   (cons "\\[.*\\]" font-lock-variable-name-face)
+   (cons "#[-a-zA-Z0-9]*" font-lock-function-name-face)
+   (cons "rgb(\\s-*[0-9]+\\(\\.[0-9]+\\s-*%\\s-*\\)?\\s-*,\\s-*[0-9]+\\(\\.[0-9]+\\s-*%\\s-*\\)?\\s-*,\\s-*[0-9]+\\(\\.[0-9]+\\s-*%\\s-*\\)?\\s-*)"
+	 font-lock-reference-face)
+   )
+  "Rules for highlighting CSS style sheets.")
+
+(defvar cssm-mode-map ()
+  "Keymap used in CSS mode.")
+(when (not cssm-mode-map)
+  (setq cssm-mode-map (make-sparse-keymap))
+  (define-key cssm-mode-map (read-kbd-macro "C-c C-c") 'cssm-insert-comment)
+  (define-key cssm-mode-map (read-kbd-macro "C-c C-u") 'cssm-insert-url)
+  (define-key cssm-mode-map (read-kbd-macro "}") 'cssm-insert-right-brace-and-indent)
+  (define-key cssm-mode-map (read-kbd-macro "M-TAB") 'cssm-complete-property))
+
+;;; Cross-version compatibility layer
+
+(when (not (or (apropos-macrop 'kbd)
+	     (fboundp 'kbd)))
+    (defmacro kbd (keys)
+      "Convert KEYS to the internal Emacs key representation.
+KEYS should be a string constant in the format used for
+saving keyboard macros (see `insert-kbd-macro')."
+      (read-kbd-macro keys)))
+
+;;; Auto-indentation support
+
+; internal
+(defun cssm-insert-right-brace-and-indent()
+  (interactive)
+  (insert "}")
+  (cssm-indent-line))
+
+; internal
+(defun cssm-inside-atmedia-rule()
+  "Decides if point is currently inside an @media rule."
+  (let ((orig-pos (point))
+	(atmedia (re-search-backward "@media" 0 t))
+	(balance 1)   ; used to keep the {} balance, 1 because we start on a {
+	)
+     ; Going to the accompanying {
+    (re-search-forward "{" (point-max) t)
+    (if (null atmedia)
+	nil  ; no @media before this point => not inside
+      (while (and (< (point) orig-pos)
+		  (< 0 balance))
+	(if (null (re-search-forward "[{}]" (point-max) 0))
+	    (goto-char (point-max)) ; break
+	  (setq balance
+		(if (string= (match-string 0) "{")
+		    (+ balance 1)
+		  (- balance 1)))))
+      (= balance 1))
+    ))
+
+; internal
+(defun cssm-rule-is-atmedia()
+  "Decides if point is currently on the { of an @media or ordinary style rule."
+  (let ((result (re-search-backward "[@}{]" 0 t)))
+    (if (null result)
+	nil
+      (string= (match-string 0) "@"))))
+
+; internal
+(defun cssm-find-column(first-char)
+  "Find which column to indent to." 
+
+  ; Find out where to indent to by looking at previous lines
+  ; spinning backwards over comments
+  (let (pos)
+    (while (and (setq pos (re-search-backward (cssm-list-2-regexp
+					       '("/\\*" "\\*/" "{" "}"))
+					      (point-min) t))
+		(string= (match-string 0) "*/"))
+      (search-backward "/*" (point-min) t))
+
+    ; did the last search find anything?
+    (if pos
+	(save-excursion
+	  (let ((construct      (match-string 0))
+		(column         (current-column)))
+	    (apply cssm-indent-function
+		   (list (cond
+			  ((string= construct "{")
+			   (cond
+			    ((cssm-rule-is-atmedia)
+			     'inside-atmedia)
+			    ((cssm-inside-atmedia-rule)
+			     'inside-rule-and-atmedia)
+			    (t
+			     'inside-rule)))
+			  ((string= construct "/*")
+			   'inside-comment)
+			  ((string= construct "}")
+			   (if (cssm-inside-atmedia-rule)
+			       'inside-atmedia
+			     'outside))
+			  (t 'outside))
+			 column
+			 first-char))))
+      
+      (apply cssm-indent-function
+	     (list 'outside
+		   (current-column)
+		   first-char)))))
+
+(defun cssm-indent-line()
+  "Indents the current line."
+  (interactive)
+  (beginning-of-line)
+  (let* ((beg-of-line (point))
+	 (pos (re-search-forward "[]@#a-zA-Z0-9;,.\"{}/*\n:[]" (point-max) t))
+	 (first (match-string 0))
+	 (start (match-beginning 0)))
+
+    (goto-char beg-of-line)
+
+    (let ((indent-column (cssm-find-column first)))
+      (goto-char beg-of-line)
+
+      ; Remove all leading whitespace on this line (
+      (if (not (or (null pos)
+		   (= beg-of-line start)))
+	  (kill-region beg-of-line start))
+
+      (goto-char beg-of-line)
+    
+      ; Indent
+      (while (< 0 indent-column)
+	(insert " ")
+	(setq indent-column (- indent-column 1))))))
+
+;;; Indent-style functions
+
+(defun cssm-old-style-indenter(position column first-char-on-line)
+  (cond
+   ((eq position 'inside-atmedia)
+    (if (string= "}" first-char-on-line)
+	0
+      cssm-indent-level))
+   
+   ((eq position 'inside-rule)
+    (+ column 2))
+
+   ((eq position 'inside-rule-and-atmedia)
+    (+ column 2))
+
+   ((eq position 'inside-comment)
+    (+ column 3))
+
+   ((eq position 'outside)
+    0)))
+
+(defun cssm-c-style-indenter(position column first-char-on-line)
+  (cond
+   ((or (eq position 'inside-atmedia)
+	(eq position 'inside-rule))
+    (if (string= "}" first-char-on-line)
+	0
+      cssm-indent-level))
+
+   ((eq position 'inside-rule-and-atmedia)
+    (if (string= "}" first-char-on-line)
+	cssm-indent-level
+      (* 2 cssm-indent-level)))
+
+   ((eq position 'inside-comment)
+    (+ column 3))
+
+   ((eq position 'outside)
+    0)))
+
+;;; Typing shortcuts
+
+(define-skeleton cssm-insert-curlies
+  "Inserts a pair of matching curly parenthesises." nil
+  "{ " _ (if cssm-newline-before-closing-bracket "\n" " ")
+  "}")
+
+(define-skeleton cssm-insert-quotes
+  "Inserts a pair of matching quotes." nil
+  "\"" _ "\"")
+
+(define-skeleton cssm-insert-parenthesises
+  "Inserts a pair of matching parenthesises." nil
+  "(" _ ")")
+
+(define-skeleton cssm-insert-comment
+  "Inserts a full comment." nil
+  "/* " _ " */")
+
+(define-skeleton cssm-insert-url
+  "Inserts a URL." nil
+  "url(" _ ")")
+
+(define-skeleton cssm-insert-brackets
+  "Inserts a pair of matching brackets." nil
+  "[" _ "]")
+
+(defun cssm-enter-mirror-mode()
+  "Turns on mirror mode, where quotes, brackets etc are mirrored automatically
+  on insertion."
+  (interactive)
+  (define-key cssm-mode-map (read-kbd-macro "{")  'cssm-insert-curlies)
+  (define-key cssm-mode-map (read-kbd-macro "\"") 'cssm-insert-quotes)
+  (define-key cssm-mode-map (read-kbd-macro "(")  'cssm-insert-parenthesises)
+  (define-key cssm-mode-map (read-kbd-macro "[")  'cssm-insert-brackets))
+
+(defun cssm-leave-mirror-mode()
+  "Turns off mirror mode."
+  (interactive)
+  (define-key cssm-mode-map (read-kbd-macro "{")  'self-insert-command)
+  (define-key cssm-mode-map (read-kbd-macro "\"") 'self-insert-command)
+  (define-key cssm-mode-map (read-kbd-macro "(")  'self-insert-command)
+  (define-key cssm-mode-map (read-kbd-macro "[")  'self-insert-command))
+
+;;; Property completion
+
+(defun cssm-property-at-point()
+  "If point is at the end of a property name: returns it."
+  (let ((end (point))
+	(start (+ (re-search-backward "[^-A-Za-z]") 1)))
+    (goto-char end)
+    (buffer-substring start end)))
+
+; internal
+(defun cssm-maximum-common(alt1 alt2)
+  "Returns the maximum common starting substring of alt1 and alt2."
+  (let* ((maxlen (min (length alt1) (length alt2)))
+	 (alt1 (substring alt1 0 maxlen))
+	 (alt2 (substring alt2 0 maxlen)))
+    (while (not (string= (substring alt1 0 maxlen)
+			 (substring alt2 0 maxlen)))
+      (setq maxlen (- maxlen 1)))
+    (substring alt1 0 maxlen)))
+
+; internal
+(defun cssm-common-beginning(alts)
+  "Returns the maximum common starting substring of all alts elements."
+  (let ((common (car alts)))
+    (dolist (alt (cdr alts) common)
+      (setq common (cssm-maximum-common alt common)))))
+
+(defun cssm-complete-property-frame(completions)
+  ; This code stolen from message.el. Kudos to larsi.
+  (let ((cur (current-buffer)))
+    (pop-to-buffer "*Completions*")
+    (buffer-disable-undo (current-buffer))
+    (let ((buffer-read-only nil))
+      (erase-buffer)
+      (let ((standard-output (current-buffer)))
+	(display-completion-list (sort completions 'string<)))
+      (goto-char (point-min))
+      (pop-to-buffer cur))))
+
+(defun cssm-complete-property()
+  "Completes the CSS property being typed at point."
+  (interactive)
+  (let* ((prop   (cssm-property-at-point))
+	 (alts   (all-completions prop cssm-properties-alist))
+	 (proplen (length prop)))
+    (if (= (length alts) 1)
+	(insert (substring (car alts) proplen))
+      (let ((beg (cssm-common-beginning alts)))
+	(if (not (string= beg prop))
+	    (insert (substring beg proplen))
+	  (insert (substring
+		   (completing-read "Property: " cssm-properties-alist nil
+				    nil prop)
+		   proplen)))))))
+
+(defun css-mode()
+  "Major mode for editing CSS style sheets.
+\\{cssm-mode-map}"
+  (interactive)
+
+  ; Initializing
+  (kill-all-local-variables)
+
+  ; Setting up indentation handling
+  (make-local-variable 'indent-line-function)
+  (setq indent-line-function 'cssm-indent-line)
+  
+  ; Setting up font-locking
+  (make-local-variable 'font-lock-defaults)
+  (setq font-lock-defaults '(cssm-font-lock-keywords nil t nil nil))
+
+  ; Setting up typing shortcuts
+  (make-local-variable 'skeleton-end-hook)
+  (setq skeleton-end-hook nil)
+  
+  (when cssm-mirror-mode
+    (cssm-enter-mirror-mode))
+  
+  (use-local-map cssm-mode-map)
+  
+  ; Setting up syntax recognition
+  (make-local-variable 'comment-start)
+  (make-local-variable 'comment-end)
+  (make-local-variable 'comment-start-skip)
+
+  (setq comment-start "/* "
+	comment-end " */"
+	comment-start-skip "/\\*[ \n\t]+")
+
+  ; Setting up syntax table
+  (modify-syntax-entry ?* ". 23")
+  (modify-syntax-entry ?/ ". 14")
+  
+  ; Final stuff, then we're done
+  (setq mode-name "CSS"
+	major-mode 'css-mode)
+  (run-hooks 'css-mode-hook))
+
+(provide 'css-mode)
+
+;; CSS-mode ends here
\ No newline at end of file


macemacsjp-cvs メーリングリストの案内
Back to archive index