OpenSCAD mode for emacs
... my hack.
;;scad.el --- Major mode for editing SCAD files ;; Original author: Len Trigg <lenbok@gmail.com> ;; Maintainer: This hack is maintained by tca <tca@diale.org> ;; Created: 20141107 ;; Modified: 20141107 ;; Keywords: OpenSCAD, emacs, mode ;; URL: http://diale.org/scad.el.html ;; Version: 0.1 ;; Comments: Added a bunch of skeletons and keymaps. ;; ;; 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 major-mode to implement the SCAD constructs and ;; font-locking for openscad ;;; Code: ;;;###autoload (add-to-list 'auto-mode-alist '("\\.scad$" . scad-mode)) (defcustom scad-command '"~/Downloads/openscad-2014.03/local_inst/bin/openscad" "Path to openscad executable" :type 'string) (defcustom scad-keywords '("return" "true" "false") "SCAD keywords." :type 'list :group 'scad-font-lock) (defcustom scad-functions '("cos" "acos" "sin" "asin" "tan" "atan" "atan2" "abs" "sign" "rands" "min" "max" "round" "ceil" "floor" "pow" "sqrt" "exp" "log" "ln" "str" "lookup" "version" "version_num" "len" "search" "dxf_dim" "dxf_cross") "SCAD functions." :type 'list :group 'scad-font-lock) (defcustom scad-modules '("child" "children" "echo" "assign" "for" "intersection_for" "if" "else" "cube" "sphere" "cylinder" "polyhedron" "square" "circle" "polygon" "scale" "rotate" "translate" "mirror" "multmatrix" "union" "difference" "intersection" "render" "color" "surface" "dxf_linear_extrude" "linear_extrude" "dxf_rotate_extrude" "rotate_extrude" "import_stl" "import_off" "import_dxf" "import" "group" "projection""minkowski" "glide" "subdiv" "hull" "resize") "SCAD modules." :type 'list :group 'scad-font-lock) (defcustom scad-operators '("+" "-" "*" "/" "%" "&&" "||" "!" "<" "<=" "==" "!=" ">" ">=" "?" ":" "=") "SCAD operators." :type 'list :group 'scad-font-lock) ;; "C-c letter" are reserved for users (defvar scad-mode-map (let ((map (make-sparse-keymap))) (define-key map "\t" 'scad-indent-line) (define-key map (kbd "C-c C-v") 'scad-open-current-buffer) (define-key map (kbd "C-c C-c") 'scad-output-stl) ;; s for solid (define-key map (kbd "C-c C-s c") 'scad-cylinder) (define-key map (kbd "C-c C-s u") 'scad-cube) (define-key map (kbd "C-c C-s y") 'scad-cylinder) (define-key map (kbd "C-c C-s p") 'scad-polyhedron) ;; b for Boolean (define-key map (kbd "C-c C-b u") 'scad-union) (define-key map (kbd "C-c C-b d") 'scad-difference) (define-key map (kbd "C-c C-b i") 'scad-intersection) ;; t for transformations (define-key map (kbd "C-c C-t t") 'scad-translate) (define-key map (kbd "C-c C-t r") 'scad-rotate) (define-key map (kbd "C-c C-t s") 'scad-scale) (define-key map (kbd "C-c C-t z") 'scad-resize) (define-key map (kbd "C-c C-t m") 'scad-mirror) (define-key map (kbd "C-c C-t x") 'scad-multmatrix) (define-key map (kbd "C-c C-t c") 'scad-color) (define-key map (kbd "C-c C-t h") 'scad-hull) (define-key map (kbd "C-c C-t k") 'scad-minkowski) ;; s for syntax (define-key map (kbd "C-c C-s m") 'scad-module) (define-key map (kbd "C-c C-s f") 'scad-function) (define-key map (kbd "C-c C-s i") 'scad-include) (define-key map (kbd "C-c C-s u") 'scad-use) ;; m for math ;; Is this really needed;) ;; f for functions (define-key map (kbd "C-c C-f l") 'scad-lookup) (define-key map (kbd "C-c C-f r") 'scad-str) (define-key map (kbd "C-c C-f c") 'scad-chr) (define-key map (kbd "C-c C-f s") 'scad-search) (define-key map (kbd "C-c C-f n") 'scad-version-num) (define-key map (kbd "C-c C-f n") 'scad-norm ) (define-key map (kbd "C-c C-f c") 'scad-cross) (define-key map (kbd "C-c C-f m") 'scad-parent-module) ;; o for others (define-key map (kbd "C-c C-o r") 'scad-render) (define-key map (kbd "C-c C-o f") 'scad-for) (define-key map (kbd "C-c C-o t") 'scad-intersection-for) (define-key map (kbd "C-c C-o i") 'scad-if) (define-key map (kbd "C-c C-o a") 'scad-assign) (define-key map (kbd "C-c C-o m") 'scad-import) (define-key map (kbd "C-c C-o x") 'scad-linear-extrude) (define-key map (kbd "C-c C-o o") 'scad-rotate-extrude) (define-key map (kbd "C-c C-o s") 'scad-surface) (define-key map (kbd "C-c C-o p") 'scad-projection) (define-key map (kbd "C-c C-o c") 'scad-children) ;; p for on the plane (define-key map (kbd "C-c C-p c") 'scad-circle) (define-key map (kbd "C-c C-p s") 'scad-square) (define-key map (kbd "C-c C-p p") 'scad-polygon) (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)) ("\\(use\\|include\\)[ \t]*<\\([^>]+\\)>" (1 'font-lock-preprocessor-face nil) (2 'font-lock-type-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) ;; set comment styles for scad mode (set (make-local-variable 'comment-start) "//") (set (make-local-variable 'comment-end) "") (set (make-local-variable 'block-comment-start) "/*") (set (make-local-variable 'block-comment-end) "*/")) ;; From: http://stackoverflow.com/questions/14520073/add-words-for-dynamic-expansion-to-emacs-mode (defun scad-prime-dabbrev () "Makes a hidden scad-mode buffer containing all the scad keywords, so dabbrev expansion just works." (unless (get-buffer " *scad words*") (with-current-buffer (get-buffer-create " *scad words*") (scad-mode) (insert "module function use include") ; Explicitly add these -- they're not in the below vars (insert (mapconcat 'identity (append scad-keywords scad-functions scad-modules) " "))))) (add-hook 'scad-mode-hook 'scad-prime-dabbrev) ;;; 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 (max (scad-calculate-indentation) 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)") (setq close-count (+ close-count 1))) ((looking-back "\\s(") (setq open-count (+ open-count 1))) ))) (- open-count close-count)))) (defun scad-open-current-buffer () (interactive) (call-process scad-command nil 0 nil (buffer-file-name))) (defun scad-output-stl () (interactive) (async-shell-command (concat scad-command " -o " (buffer-file-name) ".stl " (buffer-file-name)))) ;; Skeleton for easy editing ;; 3D (define-skeleton scad-sphere "Insert sphere." "Sphere:" "sphere:(" str ");") (define-skeleton scad-cube "Insert cube." "Cube:" "cube:(" str ");") (define-skeleton scad-cylinder "Insert cylinder." "Cylinder:" "cylinder(" str ");") (define-skeleton scad-polyhedron "Insert polyhedron." "Polyhedron:" "polyhedron(" str ");") ;; 2D (define-skeleton scad-circle "Insert square." "Square:" "square(" str ");") (define-skeleton scad-square "Insert square ." "Square:" "square(" str ");") (define-skeleton scad-polygon "Insert polygon." "Polygon:" "Polygon(" str ");") ;; Transformations (define-skeleton scad-translate "Insert translate." "translate:" "translate(" str "){"_"}") (define-skeleton scad-rotate "Insert rotate." "rotate:" "rotate(" str "){"_"}") (define-skeleton scad-scale "Insert scale." "Scale:" "scale(" str "){"_"}") (define-skeleton scad-resize "Insert resize." "Resize:" "resize(" str "){"_"}") (define-skeleton scad-mirror "Insert mirror." "Mirror:" "mirror(" str "){"_"}") (define-skeleton scad-multmatrix "Insert multmatrix." "Multmatrix:" "multmatrix:(" str "){"_"}") (define-skeleton scad-color "Insert color." "Color:" "color(" str "){"_"}") (define-skeleton scad-hull "Insert hull." "Hull:" "hull(" str "){"_"}") (define-skeleton scad-minkowski "Insert minkowski." "Minkowski:" "minkowski(){"_"}") ;; Boolean (define-skeleton scad-union "Insert union." "Union:" "union(){}") (define-skeleton scad-difference "Insert difference." "Difference:" "difference(){"_"}") (define-skeleton scad-intersection "Insert intersection." "Intersection:" "intersection(){"_"}") ;; Syntax (define-skeleton scad-module "Insert module." "Module:" "module " str "("_"){}") (define-skeleton scad-function "Insert function." "Function:" "function " str "("_"){}") (define-skeleton scad-include "Insert include." "Include:" "include <" str ".scad>") (define-skeleton scad-use "Insert use." "Use:" "use <" str ".scad>") ;; Other (define-skeleton scad-render "Insert render." "Render:" "render(){"_"}") (define-skeleton scad-translate "Insert translate." "translate:" "translate(" str "){"_"}") (define-skeleton scad-rotate "Insert rotate." "rotate:" "rotate(" str "){"_"}") (define-skeleton scad-scale "Insert scale." "Scale:" "scale(" str "){"_"}") (define-skeleton scad-resize "Insert resize." "Resize:" "resize(" str "){"_"}") (define-skeleton scad-mirror "Insert mirror." "Mirror:" "mirror(" str "){"_"}") (define-skeleton scad-multmatrix "Insert multmatrix." "Multmatrix:" "multmatrix:(" str "){"_"}") (define-skeleton scad-color "Insert color." "Color:" "color(" str "){"_"}") (define-skeleton scad-hull "Insert hull." "Hull:" "hull(" str "){"_"}") (define-skeleton scad-minkowski "Insert minkowski." "Minkowski:" "minkowski(){"_"}") ;; Boolean (define-skeleton scad-union "Insert union." "Union:" "union(){}") (define-skeleton scad-difference "Insert difference." "Difference:" "difference(){"_"}") (define-skeleton scad-intersection "Insert intersection." "Intersection:" "intersection(){"_"}") ;; Syntax (define-skeleton scad-module "Insert module." "Module:" "module " str "("_"){}") (define-skeleton scad-function "Insert function." "Function:" "function " str "("_"){}") (define-skeleton scad-include "Insert include." "Include:" "include <" str ".scad>") (define-skeleton scad-use "Insert use." "Use:" "use <" str ".scad>") ;; Other (define-skeleton scad-render "Insert render." "Render:" "render(){"_"}") (define-skeleton scad-for "Insert for." "For:" "for (i=" str ")" "{" _ "}") ;; (define-skeleton scad- ;; "Insert ." ;; ":" ;; "(" str ");") (provide 'scad) ;;; scad-mode.el ends here
Enjoy.
Palavras chave/keywords: emacs, openscadCriado/Created: NaN
Última actualização/Last updated: 10-10-2022 [14:26]
(c) Tiago Charters de Azevedo