]> code.delx.au - gnu-emacs-elpa/blob - packages/jgraph-mode/jgraph-mode.el
Merge commit '0cda39255827f283e7578cd469ae42daad9556a2' from js2-mode
[gnu-emacs-elpa] / packages / jgraph-mode / jgraph-mode.el
1 ;;; jgraph-mode.el --- Major mode for Jgraph files -*- lexical-binding:t -*-
2
3 ;; Copyright (C) 2006, 2011-2012, 2014, 2015 Free Software Foundation, Inc
4
5 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
6 ;; Version: 1.1
7 ;; Package-Requires: ((cl-lib "0.5"))
8 ;; Keywords: tex, wp
9
10 ;; This file is part of GNU Emacs.
11
12 ;; GNU Emacs is free software: you can redistribute it and/or modify
13 ;; it under the terms of the GNU General Public License as published by
14 ;; the Free Software Foundation, either version 3 of the License, or
15 ;; (at your option) any later version.
16
17 ;; GNU Emacs is distributed in the hope that it will be useful,
18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 ;; GNU General Public License for more details.
21
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
24
25 ;;; Commentary:
26
27 ;; Simple editing mode for the Jgraph graph plotting tool.
28 ;; You can find more info at http://web.eecs.utk.edu/~plank/plank/jgraph/jgraph.html
29
30 ;;; Code:
31
32 (eval-when-compile (require 'cl-lib))
33
34 (defgroup jgraph-mode ()
35 "Major mode for Jgraph files."
36 :group 'tools)
37
38 (defvar jgraph-mode-map
39 (let ((map (make-sparse-keymap)))
40 map)
41 "Keymap for `jgraph-mode'.")
42
43 ;; (easy-menu-define jgraph-mode-menu jgraph-mode-map
44 ;; "Menu for `jgraph-mode'."
45 ;; '("Jgraph"
46 ;; ["Do some stuff" jgraph-do-bar :active mark-active]
47 ;; "..."
48 ;; ["Do some other" jgraph-do-foo]
49 ;; ("Sub-jgraph"
50 ;; ["Haha" jgraph-crash])
51 ;; ...))
52
53 (defvar jgraph-mode-syntax-table
54 (let ((st (make-syntax-table)))
55 ;; tokens are made of any non-whitespace chars.
56 (map-char-table (lambda (c v) (if (not (memq (car v) '(0 2 3)))
57 (modify-syntax-entry c "_" st)))
58 st)
59 (modify-syntax-entry ?\( "_ 1n" st)
60 (modify-syntax-entry ?\) "_ 4n" st)
61 (modify-syntax-entry ?\* "_ 23" st)
62 st)
63 "Syntax table for `jgraph-mode'.")
64
65 (defun jgraph-extract-commands ()
66 (let ((sections nil)
67 (tok-cmds nil))
68 (goto-char (point-min))
69 (while (and (re-search-forward "^\\.RE" nil t)
70 (re-search-forward "^\\.B \\(.*\\)" nil t))
71 (let ((section (downcase (match-string 1)))
72 (commands nil)
73 (end (save-excursion
74 (and (re-search-forward "^\\.RE" nil t)
75 (match-beginning 0)))))
76 (setq section (replace-regexp-in-string "simple" "" section))
77 (setq section (replace-regexp-in-string "advanced" "" section))
78 (setq section (replace-regexp-in-string "editing" "" section))
79 (setq section (replace-regexp-in-string "commands" "" section))
80 (setq section (replace-regexp-in-string "\\\\" "" section))
81 (setq section (replace-regexp-in-string "\\` *" "" section))
82 (setq section (replace-regexp-in-string " *\\'" "" section))
83 (setq section (replace-regexp-in-string " " "-" section))
84 (setq section (intern section))
85 (while (re-search-forward "^\\.TP\n\\(?:\\.B \\|\\\\fB\\)\\([^ :\t\n\\]+\\)\\([ {\\fI]*token\\)?" end 'move)
86 (let ((cmd (match-string-no-properties 1)))
87 (if (match-end 2) (cl-pushnew cmd tok-cmds :test #'equal))
88 (cl-pushnew cmd commands :test #'equal)))
89 (setq commands (nreverse commands))
90 (let ((sec (assoc section sections)))
91 (if sec (nconc sec commands)
92 (push (cons section commands) sections)))))
93 (nreverse (cons (cons 'token tok-cmds) sections))))
94
95 (defconst jgraph-commands
96 ;; Obtained by running (jgraph-extract-commands) in the jgraph.1 nroff doc.
97 '((top-level-description "newgraph" "graph" "copygraph" "newpage" "X" "Y"
98 "bbox" "preamble" "epilogue")
99 (graph "xaxis" "yaxis" "newcurve" "curve" "newline" "copycurve" "title"
100 "legend" "newstring" "string" "copystring" "border" "noborder"
101 "clip" "noclip" "inherit_axes" "x_translate" "y_translate" "X" "Y")
102 (axis "linear" "log" "min" "max" "size" "log_base" "hash" "shash" "mhash"
103 "precision" "hash_format" "label" "draw_at" "nodraw" "draw"
104 "grid_lines" "no_grid_lines" "mgrid_lines" "no_mgrid_lines" "gray"
105 "color" "grid_gray" "grid_color" "mgrid_gray" "mgrid_color" "hash_at"
106 "mhash_at" "hash_label" "hash_labels" "hash_scale"
107 "draw_hash_marks_at" "draw_hash_labels_at" "auto_hash_marks"
108 "no_auto_hash_marks" "auto_hash_labels" "no_auto_hash_labels"
109 "draw_axis" "no_draw_axis" "draw_axis_label" "no_draw_axis_label"
110 "draw_hash_marks" "no_draw_hash_marks" "draw_hash_labels"
111 "no_draw_hash_labels")
112 (curve "pts" "x_epts" "y_epts" "marktype" "marksize" "mrotate" "gray"
113 "color" "fill" "cfill" "pattern" "poly" "nopoly" "pfill" "pcfill"
114 "ppattern" "gmarks" "postscript" "eps" "larrows" "rarrows"
115 "nolarrows" "norarrows" "larrow" "rarrow" "nolarrow" "norarrow"
116 "asize" "afill" "apattern" "linetype" "glines" "linethickness"
117 "bezier" "nobezier" "clip" "noclip" "label")
118 (label "x" "y" "font" "fontsize" "linesep" "hjl" "hjc" "hjr" "vjt" "vjc"
119 "vjb" "rotate" "lgray" "lcolor")
120 (legend "on" "off" "linelength" "linebreak" "midspace" "defaults" "left"
121 "top" "bottom" "x" "y" "custom")
122 (hash-label "at")
123 ;; Commands that can be followed by a token.
124 (token "apattern" "eps" "postscript" "ppattern" "pattern" "hash_format"
125 "epilogue" "preamble")))
126
127 (defconst jgraph-file-include-commands
128 '("include" "preamble" "epilogue" "postscript" "eps"))
129
130 (defvar jgraph-font-lock-keywords
131 `((,(concat "\\_<" (regexp-opt jgraph-file-include-commands)
132 "[ \t]+\\(\\sw+\\)")
133 (1 font-lock-constant-face))
134 (,(concat "^" (regexp-opt
135 (cdr (assoc 'top-level-description jgraph-commands)))
136 "\\_>")
137 . font-lock-function-name-face)
138 (,(concat "\\_<"
139 (regexp-opt (cons "include"
140 (apply 'append (mapcar 'cdr jgraph-commands))))
141 "\\_>")
142 . font-lock-keyword-face)
143 )
144 "Keyword highlighting specification for `jgraph-mode'.")
145
146 ;; (defvar jgraph-imenu-generic-expression
147 ;; '(("Vars" "^defvar[ \t]+\\(\\(\\sw\\|\\s_\\)+\\)" 1)
148 ;; (nil "^function[ \t]+\\(\\(\\sw\\|\\s_\\)+\\)" 1)
149 ;; ...)
150 ;; "Regex patterns for the index menu of `jgraph-mode'.")
151
152 ;; (defvar jgraph-outline-regexp "(\\|;;;+"
153 ;; "Regexp for `outline-minor-mode' in `jgraph-mode'.")
154
155 ;; Abbreviations and Skeletons
156
157 ;; (define-skeleton jgraph-insert-if
158 ;; "Jgraph mode skeleton for if..then expressions."
159 ;; nil
160 ;; "if " _ \n "then " _ \n "else " _ \n "fi" \n)
161
162 ;; (define-skeleton jgraph-insert-begend
163 ;; "Jgraph mode skeleton for begin<x>...end<x> expressions."
164 ;; "Block name: "
165 ;; "begin<" str ">" \n _ \n "end<" str ">" \n)
166
167 ;; (define-abbrev-table 'jgraph-mode-abbrev-table
168 ;; '(("if" "" jgraph-insert-if nil t)
169 ;; ("cwcc" "call-with-current-continuation" nil nil t)
170 ;; ("begin" "" jgraph-insert-begend nil t)
171 ;; ))
172
173 ;;;###autoload
174 (add-to-list 'auto-mode-alist '("\\.jgr\\'" . jgraph-mode))
175
176 (defun jgraph--syntax-end-of-string (limit)
177 (when (eq t (nth 3 (syntax-ppss)))
178 (when (re-search-forward "\\(?:\\=\\|[^\\]\\)\\(\n\\)" limit t)
179 (put-text-property (match-beginning 1) (match-end 1)
180 'syntax-table (string-to-syntax "|")))))
181
182 (defun jgraph--syntax-propertize (start end)
183 (goto-char start)
184 (jgraph--syntax-end-of-string end)
185 (funcall
186 (syntax-propertize-rules
187 ("\\s-:\\(\\s-\\)" (1 (prog1 "|" (jgraph--syntax-end-of-string end)))))
188 start end))
189
190 ;;;###autoload
191 (define-derived-mode jgraph-mode prog-mode "Jgraph"
192 "A major mode for editing Jgraph files."
193 (set (make-local-variable 'comment-start) "(* ")
194 (set (make-local-variable 'comment-start-skip) "\\_<(\\*\\_>[ \t]*")
195 (set (make-local-variable 'comment-end) " *)")
196 (set (make-local-variable 'comment-start-skip) "[ \t]*\\_<\\*)\\_>")
197 (set (make-local-variable 'font-lock-defaults)
198 '(jgraph-font-lock-keywords))
199 (set (make-local-variable 'syntax-propertize-function)
200 #'jgraph--syntax-propertize)
201 (set (make-local-variable 'indent-line-function) 'jgraph-indent-line)
202 ;; (set (make-local-variable 'imenu-generic-expression)
203 ;; jgraph-imenu-generic-expression)
204 ;; (set (make-local-variable 'outline-regexp) jgraph-outline-regexp)
205 )
206
207 ;;; Indentation
208
209 (defcustom jgraph-indent-offset 4
210 "Basic indentation step size in `jgraph-mode'."
211 :type 'integer)
212
213 (defun jgraph-indent-line ()
214 "Indent current line of Jgraph code."
215 (interactive)
216 (let* ((savep (point))
217 (indent (or (with-demoted-errors
218 (save-excursion
219 (forward-line 0)
220 (skip-chars-forward " \t")
221 (if (>= (point) savep) (setq savep nil))
222 (jgraph-indent-calculate)))
223 'noindent)))
224 (if (not (numberp indent))
225 indent
226 (setq indent (max indent 0))
227 (if savep
228 (save-excursion (indent-line-to indent))
229 (indent-line-to indent)))))
230
231 (defun jgraph-indent-calculate ()
232 "Return the column to which the current line should be indented."
233 (save-excursion
234 (skip-chars-forward " \t")
235 (or (when (looking-at (concat (regexp-opt
236 (cdr (assoc 'top-level-description
237 jgraph-commands)))
238 "\\_>"))
239 0)
240 'noindent)))
241
242 (provide 'jgraph-mode)
243 ;;; jgraph-mode.el ends here