diff options
| author | kintel <kintel@b57f626f-c46c-0410-a088-ec61d464b74c> | 2010-04-07 10:05:09 (GMT) | 
|---|---|---|
| committer | kintel <kintel@b57f626f-c46c-0410-a088-ec61d464b74c> | 2010-04-07 10:05:09 (GMT) | 
| commit | 34189d85b4d0924f732ba3940e89ca0b03730df7 (patch) | |
| tree | 2827f7368f34f26a2177bcc9fffe01c09d564535 /contrib | |
| parent | 77127b8f354498b2503e9e0677fd447fa58b4d0b (diff) | |
Emacs major mode by Len Trigg
git-svn-id: http://svn.clifford.at/openscad/trunk@512 b57f626f-c46c-0410-a088-ec61d464b74c
Diffstat (limited to 'contrib')
| -rw-r--r-- | contrib/scad.el | 205 | 
1 files changed, 205 insertions, 0 deletions
| diff --git a/contrib/scad.el b/contrib/scad.el new file mode 100644 index 0000000..1e5c9b5 --- /dev/null +++ b/contrib/scad.el @@ -0,0 +1,205 @@ +;;; scad.el --- SCAD mode derived mode + +;; Author:     Len Trigg +;; Maintainer: Len Trigg <lenbok@gmail.com> +;; Created:    March 2010 +;; Modified:   March 2010 +;; Version:    $Revision: 88 $ + +;; 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; see the file COPYING.  If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: +;; +;; This is a separate mode to implement the SCAD constructs and +;; font-locking. +;; +;; To use, insert the following into your emacs startup: +;; +;; (autoload 'scad-mode "scad" "Major mode for editing SCAD code." t) +;; (add-to-list 'auto-mode-alist '("\\.scad$" . scad-mode)) + +;;; To Do: +;; - Support for background/debug/root/disable modifiers +;; - Font lock of non-built-in function calls + +;;; Autoload mode trigger +(add-to-list 'auto-mode-alist '("\\.scad$" . scad-mode)) + +(defcustom scad-keywords +  '("return" "true" "false") +  "SCAD keywords." +  :type 'list +  :group 'scad-font-lock) + +(defcustom scad-functions +  '("cos" "acos" "sin" "asin" "tan" "atan"  +    "pow" "log" "ln" +    "abs" "min" "max" "sqrt" "round" "ceil" "floor" "lookup"  +    "str"  +    "dxf_dim" "dxf_cross" +    ) +  "SCAD functions." +  :type 'list +  :group 'scad-font-lock) + +(defcustom scad-modules +  '("for" "if" "assign" "intersection_for" +    "echo" +    "cube" "sphere" "cylinder" "polyhedron"  +    "scale" "rotate" "translate" "mirror" "multmatrix" "color" +    "union" "difference" "intersection" "render" "surface" +    "square" "circle" "polygon" "dxf_linear_extrude" "linear_extrude" "dxf_rotate_extrude" "rotate_extrude" +    "import_stl" "import_off" "import_dxf" "group" +    "projection" "minkowski" "glide" "subdiv" "child" +    ) +  "SCAD modules." +  :type 'list +  :group 'scad-font-lock) + +(defcustom scad-operators +  '("+" "-" "*" "/" "%"  +    "&&" "||" "!"  +    "<" "<=" "==" "!=" ">" ">=" +    "?" ":" "=") +  "SCAD operators." +  :type 'list +  :group 'scad-font-lock) + +(defvar scad-mode-map +  (let ((map (make-sparse-keymap))) +    (define-key map "\t" 'scad-indent-line) +    (define-key map [return] 'newline-and-indent)  +    map) +  "Keymap for `scad-mode'.") + +(defvar scad-mode-syntax-table +  (let ((st (make-syntax-table))) +    ;; support comment style: “// ...”  +    ;; support comment style: “/* ... */”  +    (modify-syntax-entry ?\/ ". 124b" st) +    (modify-syntax-entry ?\n "> b" st) +    (modify-syntax-entry ?* ". 23" st) + +    ;; Extra punctuation +    (modify-syntax-entry ?+  "." st) +    (modify-syntax-entry ?-  "." st) +    (modify-syntax-entry ?%  "." st) +    (modify-syntax-entry ?<  "." st) +    (modify-syntax-entry ?>  "." st) +    (modify-syntax-entry ?&  "." st) +    (modify-syntax-entry ?:  "." st) +    (modify-syntax-entry ?|  "." st) +    (modify-syntax-entry ?=  "." st) +    (modify-syntax-entry ?\;  "." st) + +    ;; _ allowed in word (alternatively "_" as symbol constituent?) +    (modify-syntax-entry ?_  "w" st) + +    st) +  "Syntax table for `scad-mode'.") + +(defvar scad-keywords-regexp (regexp-opt scad-keywords 'words)) +(defvar scad-modules-regexp (regexp-opt scad-modules 'words)) +(defvar scad-functions-regexp (regexp-opt scad-functions 'words)) +(defvar scad-operators-regexp (regexp-opt scad-operators)) + +(defvar scad-font-lock-keywords +  `( +    ("\\(module\\|function\\)[ \t]+\\(\\sw+\\)" (1 'font-lock-keyword-face nil) (2 'font-lock-function-name-face nil t)) +    ("<\\(\\sw+\\)>" (1 'font-lock-builtin-face nil)) +    ("$\\(\\sw+\\)" (1 'font-lock-builtin-face nil)) +    (,scad-keywords-regexp . font-lock-keyword-face) +    (,scad-modules-regexp .  font-lock-builtin-face) +    (,scad-functions-regexp .  font-lock-function-name-face) +    ;(,scad-operators-regexp .  font-lock-operator-face) ;; This actually looks pretty ugly +    ;("\\(\\<\\S +\\>\\)\\s *(" 1 font-lock-function-name-face t) ;; Seems to override other stuff (e.g. in comments and builtins) +    ) +  "Keyword highlighting specification for `scad-mode'.") + +;(defvar scad-imenu-generic-expression ...) +;(defvar scad-outline-regexp ...) + +;;;###autoload +(define-derived-mode scad-mode fundamental-mode "SCAD" +  "A major mode for editing SCAD files." +  :syntax-table scad-mode-syntax-table +  (set (make-local-variable 'font-lock-defaults) '(scad-font-lock-keywords)) +  (set (make-local-variable 'indent-line-function) 'scad-indent-line) +  ;(set (make-local-variable 'imenu-generic-expression) scad-imenu-generic-expression) +  ;(set (make-local-variable 'outline-regexp) scad-outline-regexp) +  ) + + +;;; Indentation, based on http://www.emacswiki.org/emacs/download/actionscript-mode-haas-7.0.el + +(defun scad-indent-line () +  "Indent current line of SCAD code." +  (interactive) +  (let ((savep (> (current-column) (current-indentation))) +        (indent (condition-case nil (max (scad-calculate-indentation) 0) +                  (error 0)))) +    (if savep +        (save-excursion (indent-line-to indent)) +      (indent-line-to indent)))) + +(defun scad-calculate-indentation () +  "Return the column to which the current line should be indented." +  (save-excursion +    (scad-maybe-skip-leading-close-delim) +    (let ((pos (point))) +      (beginning-of-line) +      (if (not (search-backward-regexp "[^\n\t\r ]" 1 0)) +          0 +        (progn +          (scad-maybe-skip-leading-close-delim) +          (+ (current-indentation) (* standard-indent (scad-count-scope-depth (point) pos)))))))) + +(defun scad-maybe-skip-leading-close-delim () +  (beginning-of-line) +  (forward-to-indentation 0) +  (if (looking-at "\\s)") +      (forward-char) +    (beginning-of-line))) + +(defun scad-face-at-point (pos) +  "Return face descriptor for char at point." +  (plist-get (text-properties-at pos) 'face)) + +(defun scad-count-scope-depth (rstart rend) +  "Return difference between open and close scope delimeters." +  (save-excursion +    (goto-char rstart) +    (let ((open-count 0) +          (close-count 0) +          opoint) +      (while (and (< (point) rend) +                  (progn (setq opoint (point)) +                         (re-search-forward "\\s)\\|\\s(" rend t))) +        (if (= opoint (point)) +            (forward-char 1) +          (cond +           ;; Don't count if in string or comment. +           ((scad-face-at-point (- (point) 1))) +           ((looking-back "\\s)") +            (incf close-count)) +           ((looking-back "\\s(") +            (incf open-count)) +           ))) +      (- open-count close-count)))) + + +(provide 'scad) +;;; scad.el ends here | 
