Mercurial > emacs
annotate lisp/progmodes/vhdl-mode.el @ 21940:f7e788ea680b
new version
author | Michael Kifer <kifer@cs.stonybrook.edu> |
---|---|
date | Mon, 04 May 1998 22:42:59 +0000 |
parents | e95a88dc6110 |
children | e03f87c938ca |
rev | line source |
---|---|
20665 | 1 ;;; vhdl-mode.el --- major mode for editing VHDL code |
2 | |
3 ;; Copyright (C) 1992, 93, 94, 95, 96, 1997 Free Software Foundation, Inc. | |
4 | |
5 ;; Authors: Reto Zimmermann <mailto:Reto.Zimmermann@iaeth.ch> | |
6 ;; <http://www.iis.ee.ethz.ch/~zimmi/> | |
7 ;; Rodney J. Whitby <mailto:rwhitby@geocities.com> | |
8 ;; <http://www.geocities.com/SiliconValley/Park/8287/> | |
9 ;; Maintainer: vhdl-mode@geocities.com | |
10 ;; Maintainers' Version: 3.19 | |
11 ;; Keywords: languages vhdl | |
12 | |
13 ;; This file is part of GNU Emacs. | |
14 | |
15 ;; GNU Emacs is free software; you can redistribute it and/or modify | |
16 ;; it under the terms of the GNU General Public License as published by | |
17 ;; the Free Software Foundation; either version 2, or (at your option) | |
18 ;; any later version. | |
19 | |
20 ;; GNU Emacs is distributed in the hope that it will be useful, | |
21 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
22 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
23 ;; GNU General Public License for more details. | |
24 | |
25 ;; You should have received a copy of the GNU General Public License | |
26 ;; along with GNU Emacs; see the file COPYING. If not, write to the | |
27 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
28 ;; Boston, MA 02111-1307, USA. | |
29 | |
30 ;; ############################################################################ | |
31 ;;; Commentary: | |
32 ;; ############################################################################ | |
33 | |
34 ;; This package provides an Emacs major mode for editing VHDL code. | |
35 ;; It includes the following features: | |
36 | |
37 ;; - Highlighting of VHDL syntax | |
38 ;; - Indentation based on versatile syntax analysis | |
39 ;; - Template insertion (electrification) for most VHDL constructs | |
40 ;; - Insertion of customizable VHDL file headers | |
41 ;; - Word completion (dynamic abbreviations) | |
42 ;; - Menu containing all VHDL Mode commands | |
43 ;; - Index menu (jump index to main units and blocks in a file) | |
44 ;; - Source file menu (menu of all source files in current directory) | |
45 ;; - Source file compilation (syntax analysis) | |
46 ;; - Postscript printing with fontification | |
47 ;; - Lower and upper case keywords | |
48 ;; - Hiding blocks of code | |
49 ;; - Alignment functions | |
50 ;; - Easy customization | |
51 ;; - Works under GNU Emacs and XEmacs | |
52 | |
53 ;; ############################################################################ | |
54 ;; Usage | |
55 ;; ############################################################################ | |
56 | |
57 ;; see below (comment in vhdl-mode function) or type `C-c C-h' in Emacs. | |
58 | |
59 ;; ############################################################################ | |
60 ;; Emacs Versions | |
61 ;; ############################################################################ | |
62 | |
63 ;; - Emacs 20 | |
64 ;; - XEmacs 19.15 | |
65 ;; - This version does not support Emacs 19 (use VHDL Mode 3.10 instead) | |
66 | |
67 | |
68 ;; ############################################################################ | |
69 ;; Acknowledgements | |
70 ;; ############################################################################ | |
71 | |
72 ;; Electrification ideas by Bob Pack <rlpst@cislabs.pitt.edu> | |
73 ;; and Steve Grout | |
74 | |
75 ;; Fontification approach suggested by Ken Wood <ken@eda.com.au> | |
76 ;; Source file menu suggested by Michael Laajanen <mila@enea.se> | |
77 ;; Ideas about alignment from John Wiegley <johnw@borland.com> | |
78 | |
79 ;; Many thanks to all the users who sent me bug reports and enhancement | |
80 ;; requests. | |
81 ;; Special thanks go to Dan Nicolaescu <done@ece.arizona.edu> for reviewing | |
82 ;; the code and for his valuable hints. | |
83 | |
84 ;;; Code: | |
85 | |
86 ;; ############################################################################ | |
87 ;; User definable variables | |
88 ;; ############################################################################ | |
89 | |
90 ;; ############################################################################ | |
91 ;; Variables for customization | |
92 | |
93 (defgroup vhdl nil | |
94 "Customizations for VHDL Mode." | |
95 :prefix "vhdl-" | |
21651
86fcccceba7b
*** empty log message ***
Dan Nicolaescu <done@ece.arizona.edu>
parents:
21466
diff
changeset
|
96 :group 'languages |
86fcccceba7b
*** empty log message ***
Dan Nicolaescu <done@ece.arizona.edu>
parents:
21466
diff
changeset
|
97 :version "20.3") |
20665 | 98 |
99 | |
100 (defgroup vhdl-mode nil | |
101 "Customizations for modes." | |
102 :group 'vhdl) | |
103 | |
104 (defcustom vhdl-electric-mode t | |
105 "*If non-nil, electrification (automatic template generation) is enabled. | |
106 If nil, template generators can still be invoked through key bindings | |
107 and menu. Can be toggled by `\\[vhdl-electric-mode]'." | |
108 :type 'boolean | |
109 :group 'vhdl-mode) | |
110 | |
111 (defcustom vhdl-stutter-mode t | |
112 "*If non-nil, stuttering is enabled. | |
113 Can be toggled by `\\[vhdl-stutter-mode]'." | |
114 :type 'boolean | |
115 :group 'vhdl-mode) | |
116 | |
117 (defcustom vhdl-indent-tabs-mode t | |
118 "*Indentation can insert tabs if this is non-nil. | |
119 Overrides local variable `indent-tabs-mode'." | |
120 :type 'boolean | |
121 :group 'vhdl-mode) | |
122 | |
123 | |
124 (defgroup vhdl-compile nil | |
125 "Customizations for compilation." | |
126 :group 'vhdl) | |
127 | |
128 (defcustom vhdl-compiler 'v-system | |
129 "*VHDL compiler to be used for syntax analysis. | |
130 cadence Cadence Design Systems (`cv -file') | |
131 ikos Ikos Voyager (`analyze') | |
132 quickhdl QuickHDL, Mentor Graphics (`qvhcom') | |
133 synopsys Synopsys, VHDL Analyzer (`vhdlan') | |
134 vantage Vantage Analysis Systems (`analyze -libfile vsslib.ini -src') | |
135 viewlogic Viewlogic (`analyze -libfile vsslib.ini -src') | |
136 v-system V-System, Model Technology (`vcom') | |
137 For incorporation of additional compilers, please send me their command syntax | |
138 and some example error messages." | |
139 :type '(choice | |
140 (const cadence) | |
141 (const ikos) | |
142 (const quickhdl) | |
143 (const synopsys) | |
144 (const vantage) | |
145 (const viewlogic) | |
146 (const v-system) | |
147 ) | |
148 :group 'vhdl-compile) | |
149 | |
150 (defcustom vhdl-compiler-options "" | |
151 "*Options to be added to the compile command." | |
152 :type 'string | |
153 :group 'vhdl-compile) | |
154 | |
155 | |
156 (defgroup vhdl-style nil | |
157 "Customizations for code styles." | |
158 :group 'vhdl) | |
159 | |
160 (defcustom vhdl-basic-offset 4 | |
161 "*Amount of basic offset used for indentation. | |
162 This value is used by + and - symbols in `vhdl-offsets-alist'." | |
163 :type 'integer | |
164 :group 'vhdl-style) | |
165 | |
166 | |
167 (defgroup vhdl-word-case nil | |
168 "Customizations for case of VHDL words." | |
169 :group 'vhdl-style) | |
170 | |
171 (defcustom vhdl-upper-case-keywords nil | |
172 "*If non-nil, keywords are converted to upper case | |
173 when typed or by the fix case functions." | |
174 :type 'boolean | |
175 :group 'vhdl-word-case) | |
176 | |
177 (defcustom vhdl-upper-case-types nil | |
178 "*If non-nil, standardized types are converted to upper case | |
179 by the fix case functions." | |
180 :type 'boolean | |
181 :group 'vhdl-word-case) | |
182 | |
183 (defcustom vhdl-upper-case-attributes nil | |
184 "*If non-nil, standardized attributes are converted to upper case | |
185 by the fix case functions." | |
186 :type 'boolean | |
187 :group 'vhdl-word-case) | |
188 | |
189 (defcustom vhdl-upper-case-enum-values nil | |
190 "*If non-nil, standardized enumeration values are converted to upper case | |
191 by the fix case functions." | |
192 :type 'boolean | |
193 :group 'vhdl-word-case) | |
194 | |
195 | |
196 (defgroup vhdl-electric nil | |
197 "Customizations for comments." | |
198 :group 'vhdl) | |
199 | |
200 (defcustom vhdl-auto-align nil | |
201 "*If non-nil, some templates are automatically aligned after generation." | |
202 :type 'boolean | |
203 :group 'vhdl-electric) | |
204 | |
205 (defcustom vhdl-additional-empty-lines t | |
206 "*If non-nil, additional empty lines are inserted in some templates. | |
207 This improves readability of code." | |
208 :type 'boolean | |
209 :group 'vhdl-electric) | |
210 | |
211 (defcustom vhdl-argument-list-indent t | |
212 "*If non-nil, argument lists are indented relative to the opening paren. | |
213 Normal indentation is applied otherwise." | |
214 :type 'boolean | |
215 :group 'vhdl-electric) | |
216 | |
217 (defcustom vhdl-conditions-in-parenthesis nil | |
218 "*If non-nil, parenthesis are placed around condition expressions." | |
219 :type 'boolean | |
220 :group 'vhdl-electric) | |
221 | |
222 (defcustom vhdl-date-format 'scientific | |
223 "*Specifies date format to be used in header. | |
224 Date formats are: | |
225 american (09/17/1997) | |
226 european (17.09.1997) | |
227 scientific (1997/09/17)" | |
228 :type '(choice (const american) | |
229 (const european) | |
230 (const scientific)) | |
231 :group 'vhdl-electric) | |
232 | |
233 (defcustom vhdl-header-file nil | |
234 "*Pathname/filename of the file to be inserted as header. | |
235 If the header contains RCS keywords, they may be written as <RCS>Keyword<RCS> | |
236 if the header needs to be version controlled. | |
237 | |
238 The following keywords for template generation are supported: | |
239 <filename> : replaced by the name of the buffer | |
240 <author> : replaced by the user name and email address | |
241 <date> : replaced by the current date | |
242 <... string> : replaced by a prompted string (... is the prompt word) | |
243 <cursor> : final cursor position | |
244 | |
245 Example: | |
246 ----------------------------------------- | |
247 -- Title : <title string> | |
248 -- File : <filename> | |
249 -- Author : <author> | |
250 -- Created : <date> | |
251 -- Description : <cursor> | |
252 -----------------------------------------" | |
253 :type 'string | |
254 :group 'vhdl-electric) | |
255 | |
256 (defcustom vhdl-modify-date-prefix-string "-- Last modified : " | |
257 "*Prefix string of modification date in VHDL file header. | |
258 If actualization of the modification date is called (menu, `\\[vhdl-modify]'), | |
259 this string is searched and the rest of the line replaced by the current date." | |
260 :type 'string | |
261 :group 'vhdl-electric) | |
262 | |
263 (defcustom vhdl-zero-string "'0'" | |
264 "*String to use for a logic zero." | |
265 :type 'string | |
266 :group 'vhdl-electric) | |
267 | |
268 (defcustom vhdl-one-string "'1'" | |
269 "*String to use for a logic one." | |
270 :type 'string | |
271 :group 'vhdl-electric) | |
272 | |
273 | |
274 (defgroup vhdl-comment nil | |
275 "Customizations for comments." | |
276 :group 'vhdl-electric) | |
277 | |
278 (defcustom vhdl-self-insert-comments t | |
279 "*If non-nil, variables templates automatically insert help comments." | |
280 :type 'boolean | |
281 :group 'vhdl-comment) | |
282 | |
283 (defcustom vhdl-prompt-for-comments t | |
284 "*If non-nil, various templates prompt for user definable comments." | |
285 :type 'boolean | |
286 :group 'vhdl-comment) | |
287 | |
288 (defcustom vhdl-comment-column 40 | |
289 "*Column to indent right-margin comments to. | |
290 Overrides local variable `comment-column'." | |
291 :type 'integer | |
292 :group 'vhdl-comment) | |
293 | |
294 (defcustom vhdl-end-comment-column 79 | |
295 "*End of comment column." | |
296 :type 'integer | |
297 :group 'vhdl-comment) | |
298 | |
299 (defvar end-comment-column 79 | |
300 "*End of comment column.") | |
301 | |
302 | |
303 (defgroup vhdl-highlight nil | |
304 "Customizations for highlighting." | |
305 :group 'vhdl) | |
306 | |
307 (defcustom vhdl-highlight-names t | |
308 "*If non-nil, unit names, subprogram names, and labels are highlighted." | |
309 :type 'boolean | |
310 :group 'vhdl-highlight) | |
311 | |
312 (defcustom vhdl-highlight-keywords t | |
313 "*If non-nil, VHDL keywords and other predefined words are highlighted. | |
314 That is, keywords, predefined types, predefined attributes, and predefined | |
315 enumeration values are highlighted." | |
316 :type 'boolean | |
317 :group 'vhdl-highlight) | |
318 | |
319 (defcustom vhdl-highlight-signals nil | |
320 "*If non-nil, signals of different classes are highlighted using colors. | |
321 Signal classes are: clock, reset, status/control, data, and test." | |
322 :type 'boolean | |
323 :group 'vhdl-highlight) | |
324 | |
325 (defcustom vhdl-highlight-case-sensitive nil | |
326 "*If non-nil, case is considered for highlighting. | |
327 Possible trade-off: | |
328 non-nil also upper-case VHDL words are highlighted, but case of signal names | |
329 is not considered (may lead to highlighting of unwanted words), | |
330 nil only lower-case VHDL words are highlighted, but case of signal names | |
331 is considered. | |
332 Overrides local variable `font-lock-keywords-case-fold-search'." | |
333 :type 'boolean | |
334 :group 'vhdl-highlight) | |
335 | |
336 (defcustom vhdl-use-default-colors nil | |
337 "*If non-nil, the default colors are taken for syntax highlighting. | |
338 If nil, all colors are customized in VHDL Mode for better matching with the | |
339 additional signal colors." | |
340 :type 'boolean | |
341 :group 'vhdl-highlight) | |
342 | |
343 (defcustom vhdl-use-default-faces nil | |
344 "*If non-nil, the default faces are taken for syntax highlighting. | |
345 If nil, all faces are customized for better matching with the additional faces | |
346 used in VHDL Mode. This variable comes only into effect if no colors are used | |
347 for highlighting or printing (i.e. variable `ps-print-color-p' is nil)." | |
348 :type 'boolean | |
349 :group 'vhdl-highlight) | |
350 | |
351 | |
352 (defgroup vhdl-signal-syntax nil | |
353 "Customizations of signal syntax for highlighting." | |
354 :group 'vhdl-highlight) | |
355 | |
356 (defcustom vhdl-signal-syntax-doc-string " | |
357 Must be of the form \"\\ \<\\\(...\\\)\\\>\", where ... specifies the actual syntax. | |
358 (delete this space ^ , it's only a workaround to get this doc string.) | |
359 The basic regexp elements are: | |
360 [A-Z] any upper case letter | |
361 [A-Za-z] any letter | |
362 [0-9] any digit | |
363 \\w any letter or digit (corresponds to [A-Za-z0-9]) | |
364 [XY] letter \"X\" or \"Y\" | |
365 [^XY] neither letter \"X\" nor \"Y\" | |
366 x letter \"x\" | |
367 * postfix operator for matching previous regexp element any times | |
368 + postfix operator for matching previous regexp element at least once | |
369 ? postfix operator for matching previous regexp element at most once" | |
370 "Common document string used for the custom variables below. Must be | |
371 defined as custom variable due to a bug in XEmacs.") | |
372 | |
373 (defcustom vhdl-clock-signal-syntax "\\<\\([A-Z]\\w*xC\\w*\\)\\>" | |
374 (concat | |
375 "*Regular expression (regexp) for syntax of clock signals." | |
376 vhdl-signal-syntax-doc-string) | |
377 :type 'regexp | |
378 :group 'vhdl-signal-syntax) | |
379 | |
380 (defcustom vhdl-reset-signal-syntax "\\<\\([A-Z]\\w*xR\\w*\\)\\>" | |
381 (concat | |
382 "*Regular expression (regexp) for syntax of (asynchronous) reset signals." | |
383 vhdl-signal-syntax-doc-string) | |
384 :type 'regexp | |
385 :group 'vhdl-signal-syntax) | |
386 | |
387 (defcustom vhdl-control-signal-syntax "\\<\\([A-Z]\\w*x[IS]\\w*\\)\\>" | |
388 (concat | |
389 "*Regular expression (regexp) for syntax of status/control signals." | |
390 vhdl-signal-syntax-doc-string) | |
391 :type 'regexp | |
392 :group 'vhdl-signal-syntax) | |
393 | |
394 (defcustom vhdl-data-signal-syntax "\\<\\([A-Z]\\w*xD\\w*\\)\\>" | |
395 (concat | |
396 "*Regular expression (regexp) for syntax of data signals." | |
397 vhdl-signal-syntax-doc-string) | |
398 :type 'regexp | |
399 :group 'vhdl-signal-syntax) | |
400 | |
401 (defcustom vhdl-test-signal-syntax "\\<\\([A-Z]\\w*xT\\w*\\)\\>" | |
402 (concat | |
403 "*Regular expression (regexp) for syntax of test signals." | |
404 vhdl-signal-syntax-doc-string) | |
405 :type 'regexp | |
406 :group 'vhdl-signal-syntax) | |
407 | |
408 | |
409 (defgroup vhdl-menu nil | |
410 "Customizations for menues." | |
411 :group 'vhdl) | |
412 | |
413 (defcustom vhdl-source-file-menu t | |
414 "*If non-nil, a menu of all source files in the current directory is created." | |
415 :type 'boolean | |
416 :group 'vhdl-menu) | |
417 | |
418 (defcustom vhdl-index-menu t | |
419 "*If non-nil, an index menu for the current source file is created." | |
420 :type 'boolean | |
421 :group 'vhdl-menu) | |
422 | |
423 (defcustom vhdl-hideshow-menu (not (string-match "XEmacs" emacs-version)) | |
424 "*If non-nil, hideshow menu and functionality is added. | |
425 Hideshow allows hiding code of VHDL processes and blocks. | |
426 (Does not work under XEmacs.)" | |
427 :type 'boolean | |
428 :group 'vhdl-menu) | |
429 | |
430 | |
431 (defgroup vhdl-print nil | |
432 "Customizations for printing." | |
433 :group 'vhdl) | |
434 | |
435 (defcustom vhdl-print-two-column t | |
436 "*If non-nil, code is printed in two columns and landscape format." | |
437 :type 'boolean | |
438 :group 'vhdl-print) | |
439 | |
440 | |
441 (defgroup vhdl-misc nil | |
442 "Miscellaneous customizations." | |
443 :group 'vhdl) | |
444 | |
445 (defcustom vhdl-intelligent-tab t | |
446 "*If non-nil, `TAB' does indentation, word completion, and tab insertion. | |
447 That is, if preceeding character is part of a word then complete word, | |
448 else if not at beginning of line then insert tab, | |
449 else if last command was a `TAB' or `RET' then dedent one step, | |
450 else indent current line (i.e. `TAB' is bound to `vhdl-tab'). | |
451 If nil, TAB always indents current line (i.e. `TAB' is bound to | |
452 `vhdl-indent-line')." | |
453 :type 'boolean | |
454 :group 'vhdl-misc) | |
455 | |
456 (defcustom vhdl-template-key-binding-prefix "\C-t" | |
457 "*`C-c' plus this key gives the key binding prefix for all VHDL templates. | |
458 Default key binding prefix for templates is `C-c C-t' (example: architecture | |
459 `C-c C-t a'). If you have no own `C-c LETTER' bindings, you can shorten the | |
460 template key binding prefix to `C-c' (example: architecture `C-c a') by | |
461 assigning the empty character (\"\") to this variable. The syntax to enter | |
462 control keys is \"\\C-t\"." | |
463 :type 'sexp | |
464 :group 'vhdl-misc) | |
465 | |
466 (defcustom vhdl-word-completion-in-minibuffer t | |
467 "*If non-nil, word completion works in minibuffer (for template prompts)." | |
468 :type 'boolean | |
469 :group 'vhdl-misc) | |
470 | |
471 (defcustom vhdl-underscore-is-part-of-word nil | |
472 "*If non-nil, the underscore character `_' is considered as part of word. | |
473 An identifier containing underscores is then treated as a single word in | |
474 select and move operations. All parts of an identifier separated by underscore | |
475 are treated as single words otherwise." | |
476 :type 'boolean | |
477 :group 'vhdl-misc) | |
478 | |
479 ;; ############################################################################ | |
480 ;; Other variables | |
481 | |
482 (defvar vhdl-inhibit-startup-warnings-p nil | |
483 "*If non-nil, inhibits start up compatibility warnings.") | |
484 | |
485 (defvar vhdl-strict-syntax-p nil | |
486 "*If non-nil, all syntactic symbols must be found in `vhdl-offsets-alist'. | |
487 If the syntactic symbol for a particular line does not match a symbol | |
488 in the offsets alist, an error is generated, otherwise no error is | |
489 reported and the syntactic symbol is ignored.") | |
490 | |
491 (defvar vhdl-echo-syntactic-information-p nil | |
492 "*If non-nil, syntactic info is echoed when the line is indented.") | |
493 | |
494 (defconst vhdl-offsets-alist-default | |
495 '((string . -1000) | |
496 (block-open . 0) | |
497 (block-close . 0) | |
498 (statement . 0) | |
499 (statement-cont . vhdl-lineup-statement-cont) | |
500 (statement-block-intro . +) | |
501 (statement-case-intro . +) | |
502 (case-alternative . +) | |
503 (comment . vhdl-lineup-comment) | |
504 (arglist-intro . +) | |
505 (arglist-cont . 0) | |
506 (arglist-cont-nonempty . vhdl-lineup-arglist) | |
507 (arglist-close . vhdl-lineup-arglist) | |
508 (entity . 0) | |
509 (configuration . 0) | |
510 (package . 0) | |
511 (architecture . 0) | |
512 (package-body . 0) | |
513 ) | |
514 "Default settings for offsets of syntactic elements. | |
515 Do not change this constant! See the variable `vhdl-offsets-alist' for | |
516 more information.") | |
517 | |
518 (defvar vhdl-offsets-alist (copy-alist vhdl-offsets-alist-default) | |
519 "*Association list of syntactic element symbols and indentation offsets. | |
520 As described below, each cons cell in this list has the form: | |
521 | |
522 (SYNTACTIC-SYMBOL . OFFSET) | |
523 | |
524 When a line is indented, vhdl-mode first determines the syntactic | |
525 context of the line by generating a list of symbols called syntactic | |
526 elements. This list can contain more than one syntactic element and | |
527 the global variable `vhdl-syntactic-context' contains the context list | |
528 for the line being indented. Each element in this list is actually a | |
529 cons cell of the syntactic symbol and a buffer position. This buffer | |
530 position is call the relative indent point for the line. Some | |
531 syntactic symbols may not have a relative indent point associated with | |
532 them. | |
533 | |
534 After the syntactic context list for a line is generated, vhdl-mode | |
535 calculates the absolute indentation for the line by looking at each | |
536 syntactic element in the list. First, it compares the syntactic | |
537 element against the SYNTACTIC-SYMBOL's in `vhdl-offsets-alist'. When it | |
538 finds a match, it adds the OFFSET to the column of the relative indent | |
539 point. The sum of this calculation for each element in the syntactic | |
540 list is the absolute offset for line being indented. | |
541 | |
542 If the syntactic element does not match any in the `vhdl-offsets-alist', | |
543 an error is generated if `vhdl-strict-syntax-p' is non-nil, otherwise | |
544 the element is ignored. | |
545 | |
546 Actually, OFFSET can be an integer, a function, a variable, or one of | |
547 the following symbols: `+', `-', `++', or `--'. These latter | |
548 designate positive or negative multiples of `vhdl-basic-offset', | |
549 respectively: *1, *-1, *2, and *-2. If OFFSET is a function, it is | |
550 called with a single argument containing the cons of the syntactic | |
551 element symbol and the relative indent point. The function should | |
552 return an integer offset. | |
553 | |
554 Here is the current list of valid syntactic element symbols: | |
555 | |
556 string -- inside multi-line string | |
557 block-open -- statement block open | |
558 block-close -- statement block close | |
559 statement -- a VHDL statement | |
560 statement-cont -- a continuation of a VHDL statement | |
561 statement-block-intro -- the first line in a new statement block | |
562 statement-case-intro -- the first line in a case alternative block | |
563 case-alternative -- a case statement alternative clause | |
564 comment -- a line containing only a comment | |
565 arglist-intro -- the first line in an argument list | |
566 arglist-cont -- subsequent argument list lines when no | |
567 arguments follow on the same line as the | |
568 the arglist opening paren | |
569 arglist-cont-nonempty -- subsequent argument list lines when at | |
570 least one argument follows on the same | |
571 line as the arglist opening paren | |
572 arglist-close -- the solo close paren of an argument list | |
573 entity -- inside an entity declaration | |
574 configuration -- inside a configuration declaration | |
575 package -- inside a package declaration | |
576 architecture -- inside an architecture body | |
577 package-body -- inside a package body | |
578 ") | |
579 | |
580 (defvar vhdl-comment-only-line-offset 0 | |
581 "*Extra offset for line which contains only the start of a comment. | |
582 Can contain an integer or a cons cell of the form: | |
583 | |
584 (NON-ANCHORED-OFFSET . ANCHORED-OFFSET) | |
585 | |
586 Where NON-ANCHORED-OFFSET is the amount of offset given to | |
587 non-column-zero anchored comment-only lines, and ANCHORED-OFFSET is | |
588 the amount of offset to give column-zero anchored comment-only lines. | |
589 Just an integer as value is equivalent to (<val> . 0)") | |
590 | |
591 (defvar vhdl-special-indent-hook nil | |
592 "*Hook for user defined special indentation adjustments. | |
593 This hook gets called after a line is indented by the mode.") | |
594 | |
595 (defvar vhdl-style-alist | |
596 '(("IEEE" | |
597 (vhdl-basic-offset . 4) | |
598 (vhdl-offsets-alist . ()) | |
599 ) | |
600 ) | |
601 "Styles of Indentation. | |
602 Elements of this alist are of the form: | |
603 | |
604 (STYLE-STRING (VARIABLE . VALUE) [(VARIABLE . VALUE) ...]) | |
605 | |
606 where STYLE-STRING is a short descriptive string used to select a | |
607 style, VARIABLE is any vhdl-mode variable, and VALUE is the intended | |
608 value for that variable when using the selected style. | |
609 | |
610 There is one special case when VARIABLE is `vhdl-offsets-alist'. In this | |
611 case, the VALUE is a list containing elements of the form: | |
612 | |
613 (SYNTACTIC-SYMBOL . VALUE) | |
614 | |
615 as described in `vhdl-offsets-alist'. These are passed directly to | |
616 `vhdl-set-offset' so there is no need to set every syntactic symbol in | |
617 your style, only those that are different from the default.") | |
618 | |
619 ;; dynamically append the default value of most variables | |
620 (or (assoc "Default" vhdl-style-alist) | |
621 (let* ((varlist '(vhdl-inhibit-startup-warnings-p | |
622 vhdl-strict-syntax-p | |
623 vhdl-echo-syntactic-information-p | |
624 vhdl-basic-offset | |
625 vhdl-offsets-alist | |
626 vhdl-comment-only-line-offset)) | |
627 (default (cons "Default" | |
628 (mapcar | |
629 (function | |
630 (lambda (var) | |
631 (cons var (symbol-value var)) | |
632 )) | |
633 varlist)))) | |
634 (setq vhdl-style-alist (cons default vhdl-style-alist)))) | |
635 | |
636 (defvar vhdl-mode-hook nil | |
637 "*Hook called by `vhdl-mode'.") | |
638 | |
639 | |
640 ;; ############################################################################ | |
641 ;; Emacs variant handling | |
642 ;; ############################################################################ | |
643 | |
644 ;; active regions | |
645 | |
646 (defun vhdl-keep-region-active () | |
647 ;; do whatever is necessary to keep the region active in XEmacs | |
648 ;; (formerly Lucid). ignore byte-compiler warnings you might see | |
649 (and (boundp 'zmacs-region-stays) | |
650 (setq zmacs-region-stays t))) | |
651 | |
652 (defconst vhdl-emacs-features | |
653 (let ((major (and (boundp 'emacs-major-version) | |
654 emacs-major-version)) | |
655 (minor (and (boundp 'emacs-minor-version) | |
656 emacs-minor-version)) | |
657 flavor) | |
658 ;; figure out version numbers if not already discovered | |
659 (and (or (not major) (not minor)) | |
660 (string-match "\\([0-9]+\\).\\([0-9]+\\)" emacs-version) | |
661 (setq major (string-to-int (substring emacs-version | |
662 (match-beginning 1) | |
663 (match-end 1))) | |
664 minor (string-to-int (substring emacs-version | |
665 (match-beginning 2) | |
666 (match-end 2))))) | |
667 (if (not (and major minor)) | |
668 (error "Cannot figure out the major and minor version numbers.")) | |
669 ;; calculate the major version | |
670 (cond | |
671 ((= major 18) (setq major 'v18)) ;Emacs 18 | |
672 ((= major 4) (setq major 'v18)) ;Epoch 4 | |
673 ((= major 19) (setq major 'v19 ;Emacs 19 | |
674 flavor (cond | |
675 ((string-match "Win-Emacs" emacs-version) | |
676 'Win-Emacs) | |
677 ((or (string-match "Lucid" emacs-version) | |
678 (string-match "XEmacs" emacs-version)) | |
679 'XEmacs) | |
680 (t | |
681 t)))) | |
682 ((= major 20) (setq major 'v20 ;Emacs 20 | |
683 flavor (cond | |
684 ((string-match "Win-Emacs" emacs-version) | |
685 'Win-Emacs) | |
686 ((or (string-match "Lucid" emacs-version) | |
687 (string-match "XEmacs" emacs-version)) | |
688 'XEmacs) | |
689 (t | |
690 t)))) | |
691 ;; I don't know | |
692 (t (error "Cannot recognize major version number: %s" major))) | |
693 ;; lets do some minimal sanity checking. | |
694 (if (and (or | |
695 ;; Emacs 18 is brain dead | |
696 (eq major 'v18) | |
697 ;; Lemacs before 19.6 had bugs | |
698 (and (eq major 'v19) (eq flavor 'XEmacs) (< minor 6)) | |
699 ;; Emacs 19 before 19.21 had bugs | |
700 (and (eq major 'v19) (eq flavor t) (< minor 21))) | |
701 (not vhdl-inhibit-startup-warnings-p)) | |
702 (with-output-to-temp-buffer "*vhdl-mode warnings*" | |
703 (print (format | |
704 "The version of Emacs that you are running, %s, | |
705 has known bugs in its syntax.c parsing routines which will affect the | |
706 performance of vhdl-mode. You should strongly consider upgrading to the | |
707 latest available version. vhdl-mode may continue to work, after a | |
708 fashion, but strange indentation errors could be encountered." | |
709 emacs-version)))) | |
710 (list major flavor)) | |
711 "A list of features extant in the Emacs you are using. | |
712 There are many flavors of Emacs out there, each with different | |
713 features supporting those needed by vhdl-mode. Here's the current | |
714 supported list, along with the values for this variable: | |
715 | |
716 Emacs 18/Epoch 4: (v18) | |
717 XEmacs (formerly Lucid) 19: (v19 XEmacs) | |
718 Win-Emacs 1.35: (V19 Win-Emacs) | |
719 Emacs 19: (v19 t) | |
720 Emacs 20: (v20 t).") | |
721 | |
722 | |
723 ;; ############################################################################ | |
724 ;; Bindings | |
725 ;; ############################################################################ | |
726 | |
727 ;; ############################################################################ | |
728 ;; Key bindings | |
729 | |
730 (defvar vhdl-template-map () | |
731 "Keymap for VHDL templates.") | |
732 | |
733 (if vhdl-template-map () | |
734 (setq vhdl-template-map (make-sparse-keymap)) | |
735 ;; key bindings for VHDL templates | |
736 (define-key vhdl-template-map "\M-A" 'vhdl-alias) | |
737 (define-key vhdl-template-map "a" 'vhdl-architecture) | |
738 (define-key vhdl-template-map "A" 'vhdl-array) | |
739 (define-key vhdl-template-map "\M-a" 'vhdl-assert) | |
740 (define-key vhdl-template-map "b" 'vhdl-block) | |
741 (define-key vhdl-template-map "c" 'vhdl-case) | |
742 (define-key vhdl-template-map "\M-c" 'vhdl-component) | |
743 (define-key vhdl-template-map "I" 'vhdl-component-instance) | |
744 (define-key vhdl-template-map "\M-s" 'vhdl-concurrent-signal-assignment) | |
745 (define-key vhdl-template-map "\M-Cb"'vhdl-block-configuration) | |
746 (define-key vhdl-template-map "\M-Cc"'vhdl-component-configuration) | |
747 (define-key vhdl-template-map "\M-Cd"'vhdl-configuration-decl) | |
748 (define-key vhdl-template-map "\M-Cs"'vhdl-configuration-spec) | |
749 (define-key vhdl-template-map "C" 'vhdl-constant) | |
750 (define-key vhdl-template-map "d" 'vhdl-disconnect) | |
751 (define-key vhdl-template-map "\M-e" 'vhdl-else) | |
752 (define-key vhdl-template-map "E" 'vhdl-elsif) | |
753 (define-key vhdl-template-map "e" 'vhdl-entity) | |
754 (define-key vhdl-template-map "x" 'vhdl-exit) | |
755 (define-key vhdl-template-map "f" 'vhdl-for) | |
756 (define-key vhdl-template-map "F" 'vhdl-function) | |
757 (define-key vhdl-template-map "g" 'vhdl-generate) | |
758 (define-key vhdl-template-map "G" 'vhdl-generic) | |
759 (define-key vhdl-template-map "h" 'vhdl-header) | |
760 (define-key vhdl-template-map "i" 'vhdl-if) | |
761 (define-key vhdl-template-map "L" 'vhdl-library) | |
762 (define-key vhdl-template-map "l" 'vhdl-loop) | |
763 (define-key vhdl-template-map "m" 'vhdl-modify) | |
764 (define-key vhdl-template-map "M" 'vhdl-map) | |
765 (define-key vhdl-template-map "n" 'vhdl-next) | |
766 (define-key vhdl-template-map "k" 'vhdl-package) | |
767 (define-key vhdl-template-map "(" 'vhdl-paired-parens) | |
768 (define-key vhdl-template-map "\M-p" 'vhdl-port) | |
769 (define-key vhdl-template-map "p" 'vhdl-procedure) | |
770 (define-key vhdl-template-map "P" 'vhdl-process) | |
771 (define-key vhdl-template-map "R" 'vhdl-record) | |
772 (define-key vhdl-template-map "r" 'vhdl-return-value) | |
773 (define-key vhdl-template-map "\M-S" 'vhdl-selected-signal-assignment) | |
774 (define-key vhdl-template-map "s" 'vhdl-signal) | |
775 (define-key vhdl-template-map "S" 'vhdl-subtype) | |
776 (define-key vhdl-template-map "t" 'vhdl-type) | |
777 (define-key vhdl-template-map "u" 'vhdl-use) | |
778 (define-key vhdl-template-map "v" 'vhdl-variable) | |
779 (define-key vhdl-template-map "W" 'vhdl-wait) | |
780 (define-key vhdl-template-map "w" 'vhdl-while-loop) | |
781 (define-key vhdl-template-map "\M-w" 'vhdl-with) | |
782 (define-key vhdl-template-map "\M-W" 'vhdl-clocked-wait) | |
783 (define-key vhdl-template-map "Kb" 'vhdl-package-numeric-bit) | |
784 (define-key vhdl-template-map "Kn" 'vhdl-package-numeric-std) | |
785 (define-key vhdl-template-map "Ks" 'vhdl-package-std-logic-1164) | |
786 (define-key vhdl-template-map "Kt" 'vhdl-package-textio) | |
787 ) | |
788 | |
789 (defvar vhdl-mode-map () | |
790 "Keymap for VHDL Mode.") | |
791 | |
792 (if vhdl-mode-map () | |
793 (setq vhdl-mode-map (make-sparse-keymap)) | |
794 ;; key bindings for templates | |
795 (define-key vhdl-mode-map | |
796 (concat "\C-c" vhdl-template-key-binding-prefix) vhdl-template-map) | |
797 ;; standard key bindings | |
798 (define-key vhdl-mode-map "\M-a" 'vhdl-beginning-of-statement) | |
799 (define-key vhdl-mode-map "\M-e" 'vhdl-end-of-statement) | |
800 (define-key vhdl-mode-map "\M-\C-f" 'vhdl-forward-sexp) | |
801 (define-key vhdl-mode-map "\M-\C-b" 'vhdl-backward-sexp) | |
802 (define-key vhdl-mode-map "\M-\C-u" 'vhdl-backward-up-list) | |
803 ;(define-key vhdl-mode-map "\M-\C-d" 'vhdl-down-list) | |
804 (define-key vhdl-mode-map "\M-\C-a" 'vhdl-beginning-of-defun) | |
805 (define-key vhdl-mode-map "\M-\C-e" 'vhdl-end-of-defun) | |
806 (define-key vhdl-mode-map "\M-\C-h" 'vhdl-mark-defun) | |
807 (define-key vhdl-mode-map "\M-\C-q" 'vhdl-indent-sexp) | |
808 (define-key vhdl-mode-map "\177" 'backward-delete-char-untabify) | |
809 (define-key vhdl-mode-map "\r" 'vhdl-return) | |
810 (if vhdl-intelligent-tab | |
811 (define-key vhdl-mode-map "\t" 'vhdl-tab) | |
812 (define-key vhdl-mode-map "\t" 'vhdl-indent-line)) | |
813 (define-key vhdl-mode-map " " 'vhdl-outer-space) | |
814 ;; new key bindings for VHDL Mode, with no counterpart to BOCM | |
815 (define-key vhdl-mode-map "\C-c\C-e" 'vhdl-electric-mode) | |
816 (define-key vhdl-mode-map "\C-c\C-s" 'vhdl-stutter-mode) | |
817 (define-key vhdl-mode-map "\C-c\C-u" 'vhdl-fix-case-buffer) | |
818 (define-key vhdl-mode-map "\C-c\C-f" 'font-lock-fontify-buffer) | |
819 (define-key vhdl-mode-map "\C-c\C-x" 'vhdl-show-syntactic-information) | |
820 (define-key vhdl-mode-map "\C-c\C-r" 'vhdl-regress-line) | |
821 (define-key vhdl-mode-map "\C-c\C-i" 'vhdl-indent-line) | |
822 (define-key vhdl-mode-map "\C-c\C-a" 'vhdl-align-noindent-region) | |
823 (define-key vhdl-mode-map "\C-c\M-\C-a" 'vhdl-align-comment-region) | |
824 (define-key vhdl-mode-map "\C-c\C-c" 'vhdl-comment-uncomment-region) | |
825 (define-key vhdl-mode-map "\C-c-" 'vhdl-inline-comment) | |
826 (define-key vhdl-mode-map "\C-c\M--" 'vhdl-display-comment-line) | |
827 (define-key vhdl-mode-map "\C-c\C-o" 'vhdl-open-line) | |
828 (define-key vhdl-mode-map "\C-c\C-g" 'goto-line) | |
829 (define-key vhdl-mode-map "\C-c\C-d" 'vhdl-kill-line) | |
830 (define-key vhdl-mode-map "\C-c\C-h" 'vhdl-help) | |
831 (define-key vhdl-mode-map "\C-c\C-v" 'vhdl-version) | |
832 (define-key vhdl-mode-map "\C-c\C-b" 'vhdl-submit-bug-report) | |
833 (define-key vhdl-mode-map "\C-c\C-k" 'vhdl-compile) | |
834 (define-key vhdl-mode-map "\C-c\M-\C-k" 'vhdl-make) | |
835 (define-key vhdl-mode-map "\M-\t" 'tab-to-tab-stop) | |
836 ;; key bindings for stuttering | |
837 (define-key vhdl-mode-map "-" 'vhdl-stutter-mode-dash) | |
838 (define-key vhdl-mode-map "'" 'vhdl-stutter-mode-quote) | |
839 (define-key vhdl-mode-map ";" 'vhdl-stutter-mode-semicolon) | |
840 (define-key vhdl-mode-map "[" 'vhdl-stutter-mode-open-bracket) | |
841 (define-key vhdl-mode-map "]" 'vhdl-stutter-mode-close-bracket) | |
842 (define-key vhdl-mode-map "." 'vhdl-stutter-mode-period) | |
843 (define-key vhdl-mode-map "," 'vhdl-stutter-mode-comma) | |
844 (let ((c 97)) | |
845 (while (< c 123) ; for little a-z | |
846 (define-key vhdl-mode-map (char-to-string c) 'vhdl-stutter-mode-caps) | |
847 (setq c (1+ c)) | |
848 )) | |
849 ) | |
850 | |
851 ;; define special minibuffer keymap for enabling word completion in minibuffer | |
852 ;; (useful in template generator prompts) | |
853 (defvar vhdl-minibuffer-local-map (copy-keymap minibuffer-local-map) | |
854 "Keymap for minibuffer used in VHDL Mode.") | |
855 | |
856 (define-key vhdl-minibuffer-local-map "\t" 'vhdl-minibuffer-tab) | |
857 | |
858 (defvar vhdl-mode-syntax-table nil | |
859 "Syntax table used in vhdl-mode buffers.") | |
860 | |
861 (if vhdl-mode-syntax-table () | |
862 (setq vhdl-mode-syntax-table (make-syntax-table)) | |
863 ;; DO NOT TRY TO SET _ (UNDERSCORE) TO WORD CLASS! | |
864 ;; why not? (is left to the user here) | |
865 (if vhdl-underscore-is-part-of-word | |
866 (modify-syntax-entry ?_ "w" vhdl-mode-syntax-table)) | |
867 (modify-syntax-entry ?\" "\"" vhdl-mode-syntax-table) | |
868 (modify-syntax-entry ?\$ "." vhdl-mode-syntax-table) | |
869 (modify-syntax-entry ?\% "." vhdl-mode-syntax-table) | |
870 (modify-syntax-entry ?\& "." vhdl-mode-syntax-table) | |
871 (modify-syntax-entry ?\' "." vhdl-mode-syntax-table) | |
872 (modify-syntax-entry ?\( "()" vhdl-mode-syntax-table) | |
873 (modify-syntax-entry ?\) ")(" vhdl-mode-syntax-table) | |
874 (modify-syntax-entry ?\* "." vhdl-mode-syntax-table) | |
875 (modify-syntax-entry ?\+ "." vhdl-mode-syntax-table) | |
876 (modify-syntax-entry ?\. "." vhdl-mode-syntax-table) | |
877 (modify-syntax-entry ?\/ "." vhdl-mode-syntax-table) | |
878 (modify-syntax-entry ?\: "." vhdl-mode-syntax-table) | |
879 (modify-syntax-entry ?\; "." vhdl-mode-syntax-table) | |
880 (modify-syntax-entry ?\< "." vhdl-mode-syntax-table) | |
881 (modify-syntax-entry ?\= "." vhdl-mode-syntax-table) | |
882 (modify-syntax-entry ?\> "." vhdl-mode-syntax-table) | |
883 (modify-syntax-entry ?\[ "(]" vhdl-mode-syntax-table) | |
884 (modify-syntax-entry ?\\ "\\" vhdl-mode-syntax-table) | |
885 (modify-syntax-entry ?\] ")[" vhdl-mode-syntax-table) | |
886 (modify-syntax-entry ?\{ "(}" vhdl-mode-syntax-table) | |
887 (modify-syntax-entry ?\| "." vhdl-mode-syntax-table) | |
888 (modify-syntax-entry ?\} "){" vhdl-mode-syntax-table) | |
889 ;; add comment syntax | |
890 (modify-syntax-entry ?\- ". 12" vhdl-mode-syntax-table) | |
891 (modify-syntax-entry ?\n ">" vhdl-mode-syntax-table) | |
892 (modify-syntax-entry ?\^M ">" vhdl-mode-syntax-table)) | |
893 | |
894 (defvar vhdl-syntactic-context nil | |
895 "Buffer local variable containing syntactic analysis list.") | |
896 (make-variable-buffer-local 'vhdl-syntactic-context) | |
897 | |
898 ;; ############################################################################ | |
899 ;; Abbrev hook bindings | |
900 | |
901 (defvar vhdl-mode-abbrev-table nil | |
902 "Abbrev table in use in vhdl-mode buffers.") | |
903 | |
904 (define-abbrev-table 'vhdl-mode-abbrev-table | |
905 '( | |
906 ("--" "" vhdl-display-comment-hook 0) | |
907 ("abs" "" vhdl-default-hook 0) | |
908 ("access" "" vhdl-default-hook 0) | |
909 ("after" "" vhdl-default-hook 0) | |
910 ("alias" "" vhdl-alias-hook 0) | |
911 ("all" "" vhdl-default-hook 0) | |
912 ("and" "" vhdl-default-hook 0) | |
913 ("arch" "" vhdl-architecture-hook 0) | |
914 ("architecture" "" vhdl-architecture-hook 0) | |
915 ("array" "" vhdl-array-hook 0) | |
916 ("assert" "" vhdl-assert-hook 0) | |
917 ("attr" "" vhdl-attribute-hook 0) | |
918 ("attribute" "" vhdl-attribute-hook 0) | |
919 ("begin" "" vhdl-default-indent-hook 0) | |
920 ("block" "" vhdl-block-hook 0) | |
921 ("body" "" vhdl-default-hook 0) | |
922 ("buffer" "" vhdl-default-hook 0) | |
923 ("bus" "" vhdl-default-hook 0) | |
924 ("case" "" vhdl-case-hook 0) | |
925 ("comp" "" vhdl-component-hook 0) | |
926 ("component" "" vhdl-component-hook 0) | |
927 ("conc" "" vhdl-concurrent-signal-assignment-hook 0) | |
928 ("concurrent" "" vhdl-concurrent-signal-assignment-hook 0) | |
929 ("conf" "" vhdl-configuration-hook 0) | |
930 ("configuration" "" vhdl-configuration-hook 0) | |
931 ("cons" "" vhdl-constant-hook 0) | |
932 ("constant" "" vhdl-constant-hook 0) | |
933 ("disconnect" "" vhdl-disconnect-hook 0) | |
934 ("downto" "" vhdl-default-hook 0) | |
935 ("else" "" vhdl-else-hook 0) | |
936 ("elseif" "" vhdl-elsif-hook 0) | |
937 ("elsif" "" vhdl-elsif-hook 0) | |
938 ("end" "" vhdl-default-indent-hook 0) | |
939 ("entity" "" vhdl-entity-hook 0) | |
940 ("exit" "" vhdl-exit-hook 0) | |
941 ("file" "" vhdl-default-hook 0) | |
942 ("for" "" vhdl-for-hook 0) | |
943 ("func" "" vhdl-function-hook 0) | |
944 ("function" "" vhdl-function-hook 0) | |
945 ("gen" "" vhdl-generate-hook 0) | |
946 ("generate" "" vhdl-generate-hook 0) | |
947 ("generic" "" vhdl-generic-hook 0) | |
948 ("group" "" vhdl-default-hook 0) | |
949 ("guarded" "" vhdl-default-hook 0) | |
950 ("header" "" vhdl-header-hook 0) | |
951 ("if" "" vhdl-if-hook 0) | |
952 ("impure" "" vhdl-default-hook 0) | |
953 ("in" "" vhdl-default-hook 0) | |
954 ("inertial" "" vhdl-default-hook 0) | |
955 ("inout" "" vhdl-default-hook 0) | |
956 ("inst" "" vhdl-component-instance-hook 0) | |
957 ("instance" "" vhdl-component-instance-hook 0) | |
958 ("is" "" vhdl-default-hook 0) | |
959 ("label" "" vhdl-default-hook 0) | |
960 ("library" "" vhdl-library-hook 0) | |
961 ("linkage" "" vhdl-default-hook 0) | |
962 ("literal" "" vhdl-default-hook 0) | |
963 ("loop" "" vhdl-loop-hook 0) | |
964 ("map" "" vhdl-map-hook 0) | |
965 ("mod" "" vhdl-default-hook 0) | |
966 ("modify" "" vhdl-modify-hook 0) | |
967 ("nand" "" vhdl-default-hook 0) | |
968 ("new" "" vhdl-default-hook 0) | |
969 ("next" "" vhdl-next-hook 0) | |
970 ("nor" "" vhdl-default-hook 0) | |
971 ("not" "" vhdl-default-hook 0) | |
972 ("null" "" vhdl-default-hook 0) | |
973 ("of" "" vhdl-default-hook 0) | |
974 ("on" "" vhdl-default-hook 0) | |
975 ("open" "" vhdl-default-hook 0) | |
976 ("or" "" vhdl-default-hook 0) | |
977 ("others" "" vhdl-default-hook 0) | |
978 ("out" "" vhdl-default-hook 0) | |
979 ("pack" "" vhdl-package-hook 0) | |
980 ("package" "" vhdl-package-hook 0) | |
981 ("port" "" vhdl-port-hook 0) | |
982 ("postponed" "" vhdl-default-hook 0) | |
983 ("procedure" "" vhdl-procedure-hook 0) | |
984 ("process" "" vhdl-process-hook 0) | |
985 ("pure" "" vhdl-default-hook 0) | |
986 ("range" "" vhdl-default-hook 0) | |
987 ("record" "" vhdl-record-hook 0) | |
988 ("register" "" vhdl-default-hook 0) | |
989 ("reject" "" vhdl-default-hook 0) | |
990 ("rem" "" vhdl-default-hook 0) | |
991 ("report" "" vhdl-default-hook 0) | |
992 ("ret" "" vhdl-return-hook 0) | |
993 ("return" "" vhdl-return-hook 0) | |
994 ("rol" "" vhdl-default-hook 0) | |
995 ("ror" "" vhdl-default-hook 0) | |
996 ("select" "" vhdl-selected-signal-assignment-hook 0) | |
997 ("severity" "" vhdl-default-hook 0) | |
998 ("shared" "" vhdl-default-hook 0) | |
999 ("sig" "" vhdl-signal-hook 0) | |
1000 ("signal" "" vhdl-signal-hook 0) | |
1001 ("sla" "" vhdl-default-hook 0) | |
1002 ("sll" "" vhdl-default-hook 0) | |
1003 ("sra" "" vhdl-default-hook 0) | |
1004 ("srl" "" vhdl-default-hook 0) | |
1005 ("sub" "" vhdl-subtype-hook 0) | |
1006 ("subtype" "" vhdl-subtype-hook 0) | |
1007 ("then" "" vhdl-default-hook 0) | |
1008 ("to" "" vhdl-default-hook 0) | |
1009 ("transport" "" vhdl-default-hook 0) | |
1010 ("type" "" vhdl-type-hook 0) | |
1011 ("unaffected" "" vhdl-default-hook 0) | |
1012 ("units" "" vhdl-default-hook 0) | |
1013 ("until" "" vhdl-default-hook 0) | |
1014 ("use" "" vhdl-use-hook 0) | |
1015 ("var" "" vhdl-variable-hook 0) | |
1016 ("variable" "" vhdl-variable-hook 0) | |
1017 ("wait" "" vhdl-wait-hook 0) | |
1018 ("warning" "" vhdl-default-hook 0) | |
1019 ("when" "" vhdl-when-hook 0) | |
1020 ("while" "" vhdl-while-loop-hook 0) | |
1021 ("with" "" vhdl-selected-signal-assignment-hook 0) | |
1022 ("xnor" "" vhdl-default-hook 0) | |
1023 ("xor" "" vhdl-default-hook 0) | |
1024 )) | |
1025 | |
1026 | |
1027 ;; ############################################################################ | |
1028 ;; Menues | |
1029 ;; ############################################################################ | |
1030 | |
1031 ;; ############################################################################ | |
1032 ;; VHDL menu (using `easy-menu.el') | |
1033 | |
1034 ;; `customize-menu-create' is included in `cus-edit.el' version 1.9954, | |
1035 ;; which is not yet distributed with XEmacs 19.15 | |
1036 (defun vhdl-customize-menu-create (symbol &optional name) | |
1037 "Return a customize menu for customization group SYMBOL. | |
1038 If optional NAME is given, use that as the name of the menu. | |
1039 Otherwise the menu will be named `Customize'. | |
1040 The format is suitable for use with `easy-menu-define'." | |
1041 (unless name | |
1042 (setq name "Customize")) | |
1043 (if (memq 'XEmacs vhdl-emacs-features) | |
1044 ;; We can delay it under XEmacs. | |
1045 `(,name | |
1046 :filter (lambda (&rest junk) | |
1047 (cdr (custom-menu-create ',symbol)))) | |
1048 ;; But we must create it now under Emacs. | |
1049 (cons name (cdr (custom-menu-create symbol))))) | |
1050 | |
1051 (defvar vhdl-mode-menu | |
1052 (append | |
1053 '("VHDL" | |
1054 ("Mode" | |
1055 ["Electric" vhdl-electric-mode :style toggle :selected vhdl-electric-mode] | |
1056 ["Stutter" vhdl-stutter-mode :style toggle :selected vhdl-stutter-mode] | |
1057 ) | |
1058 "--" | |
1059 ("Compile" | |
1060 ["Compile Buffer" vhdl-compile t] | |
1061 ["Stop Compilation" kill-compilation t] | |
1062 "--" | |
1063 ["Make" vhdl-make t] | |
1064 ["Generate Makefile" vhdl-generate-makefile t] | |
1065 "--" | |
1066 ["Next Error" next-error t] | |
1067 ["Previous Error" previous-error t] | |
1068 ["First Error" first-error t] | |
1069 ) | |
1070 "--" | |
1071 ("Template" | |
1072 ("VHDL Construct 1" | |
1073 ["Alias" vhdl-alias t] | |
1074 ["Architecture" vhdl-architecture t] | |
1075 ["Array" vhdl-array t] | |
1076 ["Assert" vhdl-assert t] | |
1077 ["Attribute" vhdl-attribute t] | |
1078 ["Block" vhdl-block t] | |
1079 ["Case" vhdl-case t] | |
1080 ["Component" vhdl-component t] | |
1081 ["Concurrent (Signal Asst)" vhdl-concurrent-signal-assignment t] | |
1082 ["Configuration (Block)" vhdl-block-configuration t] | |
1083 ["Configuration (Comp)" vhdl-component-configuration t] | |
1084 ["Configuration (Decl)" vhdl-configuration-decl t] | |
1085 ["Configuration (Spec)" vhdl-configuration-spec t] | |
1086 ["Constant" vhdl-constant t] | |
1087 ["Disconnect" vhdl-disconnect t] | |
1088 ["Else" vhdl-else t] | |
1089 ["Elsif" vhdl-elsif t] | |
1090 ["Entity" vhdl-entity t] | |
1091 ["Exit" vhdl-exit t] | |
1092 ["For (Loop)" vhdl-for t] | |
1093 ["Function" vhdl-function t] | |
1094 ["(For/If) Generate" vhdl-generate t] | |
1095 ["Generic" vhdl-generic t] | |
1096 ) | |
1097 ("VHDL Construct 2" | |
1098 ["If" vhdl-if t] | |
1099 ["Instance" vhdl-component-instance t] | |
1100 ["Library" vhdl-library t] | |
1101 ["Loop" vhdl-loop t] | |
1102 ["Map" vhdl-map t] | |
1103 ["Next" vhdl-next t] | |
1104 ["Package" vhdl-package t] | |
1105 ["Port" vhdl-port t] | |
1106 ["Procedure" vhdl-procedure t] | |
1107 ["Process" vhdl-process t] | |
1108 ["Record" vhdl-record t] | |
1109 ["Return" vhdl-return-value t] | |
1110 ["Select" vhdl-selected-signal-assignment t] | |
1111 ["Signal" vhdl-signal t] | |
1112 ["Subtype" vhdl-subtype t] | |
1113 ["Type" vhdl-type t] | |
1114 ["Use" vhdl-use t] | |
1115 ["Variable" vhdl-variable t] | |
1116 ["Wait" vhdl-wait t] | |
1117 ["(Clocked Wait)" vhdl-clocked-wait t] | |
1118 ["When" vhdl-when t] | |
1119 ["While (Loop)" vhdl-while-loop t] | |
1120 ["With" vhdl-with t] | |
1121 ) | |
1122 ("Standard Package" | |
1123 ["numeric_bit" vhdl-package-numeric-bit t] | |
1124 ["numeric_std" vhdl-package-numeric-std t] | |
1125 ["std_logic_1164" vhdl-package-std-logic-1164 t] | |
1126 ["textio" vhdl-package-textio t] | |
1127 ) | |
1128 ["Header" vhdl-header t] | |
1129 ["Modify (Date)" vhdl-modify t] | |
1130 ) | |
1131 ("Comment" | |
1132 ["(Un)Comment Out Region" vhdl-comment-uncomment-region (mark)] | |
1133 ["Insert Inline Comment" vhdl-inline-comment t] | |
1134 ["Insert Horizontal Line" vhdl-display-comment-line t] | |
1135 ["Insert Display Comment" vhdl-display-comment t] | |
1136 ["Fill Comment" fill-paragraph t] | |
1137 ["Fill Comment Region" fill-region (mark)] | |
1138 ) | |
1139 ("Indent" | |
1140 ["Line" vhdl-indent-line t] | |
1141 ["Region" indent-region (mark)] | |
1142 ["Buffer" vhdl-indent-buffer t] | |
1143 ) | |
1144 ("Align" | |
1145 ["Region" vhdl-align-noindent-region (mark)] | |
1146 ["Comment Region" vhdl-align-comment-region (mark)] | |
1147 ) | |
1148 ("Line" | |
1149 ["Open" vhdl-open-line t] | |
1150 ["Delete" vhdl-kill-line t] | |
1151 ["Join" delete-indentation t] | |
1152 ["Goto" goto-line t] | |
1153 ) | |
1154 ("Move" | |
1155 ["Forward Statement" vhdl-end-of-statement t] | |
1156 ["Backward Statement" vhdl-beginning-of-statement t] | |
1157 ["Forward Expression" vhdl-forward-sexp t] | |
1158 ["Backward Expression" vhdl-backward-sexp t] | |
1159 ["Forward Function" vhdl-end-of-defun t] | |
1160 ["Backward Function" vhdl-beginning-of-defun t] | |
1161 ) | |
1162 "--" | |
1163 ("Fix Case" | |
1164 ["Buffer" vhdl-fix-case-buffer t] | |
1165 ["Region" vhdl-fix-case-region (mark)] | |
1166 ) | |
1167 ["Fontify Buffer" font-lock-fontify-buffer t] | |
1168 ["Syntactic Info" vhdl-show-syntactic-information t] | |
1169 "--" | |
1170 ["Help" vhdl-help t] | |
1171 ["Version" vhdl-version t] | |
1172 ["Bug Report" vhdl-submit-bug-report t] | |
1173 "--" | |
1174 ) | |
1175 (list (vhdl-customize-menu-create 'vhdl)) | |
1176 )) | |
1177 | |
1178 (require 'easymenu) | |
1179 | |
1180 ;; ############################################################################ | |
1181 ;; Index menu (using `imenu.el') | |
1182 | |
1183 (defvar vhdl-imenu-generic-expression | |
1184 '( | |
1185 ("Entity" | |
1186 "^\\s-*\\(entity\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\)" | |
1187 2) | |
1188 ("Architecture" | |
1189 "^\\s-*\\(architecture\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\s-+of\\s-+\\(\\w\\|\\s_\\)+\\)" | |
1190 2) | |
1191 ("Configuration" | |
1192 "^\\s-*\\(configuration\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\s-+of\\s-+\\(\\w\\|\\s_\\)+\\)" | |
1193 2) | |
1194 ("Package Body" | |
1195 "^\\s-*\\(package body\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\)" | |
1196 2) | |
1197 ("Package" | |
1198 "^\\s-*\\(package\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\)" | |
1199 2) | |
1200 ("Type" | |
1201 "^\\s-*\\(sub\\)?type\\s-+\\(\\(\\w\\|\\s_\\)+\\)" | |
1202 2) | |
1203 ("Component" | |
1204 "^\\s-*\\(component\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\)" | |
1205 2) | |
1206 ("Function / Procedure" | |
1207 "^\\s-*\\(procedure\\|function\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\)" | |
1208 2) | |
1209 ("Process / Block" | |
1210 "^\\s-*\\(\\(\\w\\|\\s_\\)+\\)\\s-*:\\(\\s-\\|\n\\)*\\(process\\|block\\)" | |
1211 1) | |
1212 ("Instance" | |
1213 "^\\s-*\\(\\(\\w\\|\\s_\\)+\\s-*:\\(\\s-\\|\n\\)*\\(\\w\\|\\s_\\)+\\)\\(\\s-\\|\n\\)+\\(generic\\|port\\)\\s-+map\\>" | |
1214 1) | |
1215 ) | |
1216 "Imenu generic expression for VHDL Mode. See `imenu-generic-expression'.") | |
1217 | |
1218 (defun vhdl-add-index-menu () | |
1219 (make-local-variable 'imenu-generic-expression) | |
1220 (setq imenu-generic-expression vhdl-imenu-generic-expression) | |
1221 (imenu-add-to-menubar "Index")) | |
1222 | |
1223 ;; ############################################################################ | |
1224 ;; Source file menu (using `easy-menu.el') | |
1225 | |
1226 (defvar vhdl-extlist '("[A-Za-z0-9_.]*.vhdl?$")) | |
1227 (defvar vhdl-filelist-menu nil) | |
1228 | |
1229 (defun vhdl-add-source-files-menu () | |
1230 "Scan directory of current source file for all VHDL source files, and | |
1231 generate menu." | |
1232 (interactive) | |
1233 (message "Scanning directory for source files ...") | |
1234 (let (filelist menulist tmpextlist found | |
1235 (newmap (current-local-map))) | |
1236 (cd (file-name-directory (buffer-file-name))) | |
1237 ;; find files | |
1238 (setq menulist '()) | |
1239 (setq tmpextlist vhdl-extlist) | |
1240 (while tmpextlist | |
1241 (setq filelist (nreverse (directory-files | |
1242 (file-name-directory (buffer-file-name)) | |
1243 nil (car tmpextlist) nil))) | |
1244 ;; Create list for menu | |
1245 (setq found nil) | |
1246 (while filelist | |
1247 (setq found t) | |
1248 (setq menulist (cons (vector (car filelist) | |
1249 (list 'find-file (car filelist)) t) | |
1250 menulist)) | |
1251 (setq filelist (cdr filelist))) | |
1252 (setq menulist (vhdl-menu-split menulist 25)) | |
1253 (if found | |
1254 (setq menulist (cons "--" menulist))) | |
1255 (setq tmpextlist (cdr tmpextlist))) | |
1256 (setq menulist (cons ["*Rescan*" vhdl-add-source-files-menu t] menulist)) | |
1257 (setq menulist (cons "Sources" menulist)) | |
1258 ;; Create menu | |
1259 (easy-menu-add menulist) | |
1260 (easy-menu-define vhdl-filelist-menu newmap | |
1261 "VHDL source files menu" menulist) | |
1262 ; (use-local-map (append (current-local-map) newmap)) | |
1263 ; (use-local-map newmap) | |
1264 ) | |
1265 (message "")) | |
1266 | |
1267 (defun vhdl-menu-split (list n) | |
1268 "Split menu into several submenues, if number of elements > n." | |
1269 (if (> (length list) n) | |
1270 (let ((remain list) | |
1271 (result '()) | |
1272 (sublist '()) | |
1273 (menuno 1) | |
1274 (i 0)) | |
1275 (while remain | |
1276 (setq sublist (cons (car remain) sublist)) | |
1277 (setq remain (cdr remain)) | |
1278 (setq i (+ i 1)) | |
1279 (if (= i n) | |
1280 (progn | |
1281 (setq result (cons (cons (format "Sources %s" menuno) | |
1282 (nreverse sublist)) result)) | |
1283 (setq i 0) | |
1284 (setq menuno (+ menuno 1)) | |
1285 (setq sublist '())))) | |
1286 (and sublist | |
1287 (setq result (cons (cons (format "Sources %s" menuno) | |
1288 (nreverse sublist)) result))) | |
1289 (nreverse result)) | |
1290 list)) | |
1291 | |
1292 | |
1293 ;; ############################################################################ | |
1294 ;; VHDL Mode definition | |
1295 ;; ############################################################################ | |
21446
830023d4cec6
*** empty log message ***
Dan Nicolaescu <done@ece.arizona.edu>
parents:
20665
diff
changeset
|
1296 ;;;###autoload |
20665 | 1297 (defun vhdl-mode () |
1298 "Major mode for editing VHDL code. | |
1299 | |
1300 Usage: | |
1301 ------ | |
1302 | |
1303 - TEMPLATE INSERTION (electrification) (`\\[vhdl-outer-space]'): After typing | |
1304 a VHDL keyword and entering `\\[vhdl-outer-space]', you are prompted for | |
1305 arguments while a template is generated for that VHDL construct. Typing | |
1306 `\\[vhdl-return]' (or `\\[keyboard-quit]' in yes-no queries) at the first | |
1307 prompt aborts the current template generation. Typing `\\[just-one-space]' | |
1308 after a keyword inserts a space without calling the template generator. | |
1309 Automatic calling of the template generators (i.e. electrification) can be | |
1310 disabled (enabled) by setting the variable `vhdl-electric-mode' to nil | |
1311 (non-nil) or by typing `\\[vhdl-electric-mode]' (toggles electrification | |
1312 mode). | |
1313 Template generators can be called using the VHDL menu, the key bindings, or | |
1314 by typing the keyword (first word of menu entry not in parenthesis) and | |
1315 `\\[vhdl-outer-space]'. The following abbreviations can also be used: | |
1316 arch, attr, conc, conf, comp, cons, func, inst, pack, ret, sig, sub, var. | |
1317 | |
1318 - HEADER INSERTION (`\\[vhdl-header]'): A customized header can be inserted | |
1319 including the actual file name, user name, and current date as well as | |
1320 prompted title strings. A custom header can be defined in a separate file | |
1321 (see custom variable `vhdl-header-file'). | |
1322 | |
1323 - STUTTERING (double strike): Double striking of some keys inserts cumbersome | |
1324 VHDL syntax elements. Stuttering can be disabled by variable | |
1325 `vhdl-stutter-mode' and be toggled by typing `\\[vhdl-stutter-mode]'. | |
1326 '' --> \" [ --> ( -- --> comment | |
1327 ;; --> \" : \" [[ --> [ --CR --> comment-out code | |
1328 ;;; --> \" := \" ] --> ) --- --> horizontal line | |
1329 .. --> \" => \" ]] --> ] ---- --> display comment | |
1330 ,, --> \" <= \" aa --> A - zz --> Z | |
1331 | |
1332 - WORD COMPLETION (`\\[vhdl-tab]'): Typing `\\[vhdl-tab]' after a (not | |
1333 completed) word looks for a word in the buffer that starts alike and | |
1334 inserts it. Re-typing `\\[vhdl-tab]' toggles through alternative word | |
1335 completions. This also works in the minibuffer (i.e. in template generator | |
1336 prompts). | |
1337 | |
1338 Typing `\\[vhdl-tab]' after a non-word character indents the line if at the | |
1339 beginning of a line (i.e. no preceding non-blank characters), and inserts a | |
1340 tabulator stop otherwise. `\\[tab-to-tab-stop]' always inserts a tabulator | |
1341 stop. | |
1342 | |
1343 - COMMENTS (`--', `---', `----', `--CR'): | |
1344 `--' puts a single comment. | |
1345 `---' draws a horizontal line for separating code segments. | |
1346 `----' inserts a display comment, i.e. two horizontal lines with a | |
1347 comment in between. | |
1348 `--CR' comments out code on that line. Re-hitting CR comments out | |
1349 following lines. | |
1350 `\\[vhdl-comment-uncomment-region]' comments out a region if not | |
1351 commented out, uncomments out a region if already | |
1352 commented out. | |
1353 | |
1354 You are prompted for comments after object definitions (i.e. signals, | |
1355 variables, constants, ports) and after subprogram and process specifications | |
1356 if variable `vhdl-prompt-for-comments' is non-nil. Comments are | |
1357 automatically inserted as additional labels (e.g. after begin statements) | |
1358 and help comments if `vhdl-self-insert-comments' is non-nil. | |
1359 Inline comments (i.e. comments after a piece of code on the same line) are | |
1360 indented at least to `vhdl-comment-column'. Comments go at maximum to | |
1361 `vhdl-end-comment-column'. `\\[vhdl-return]' after a space in a comment will | |
1362 open a new comment line. Typing beyond `vhdl-end-comment-column' in a | |
1363 comment automatically opens a new comment line. `\\[fill-paragraph]' | |
1364 re-fills multi-line comments. | |
1365 | |
1366 - INDENTATION: `\\[vhdl-tab]' indents a line if at the beginning of the line. | |
1367 The amount of indentation is specified by variable `vhdl-basic-offset'. | |
1368 `\\[vhdl-indent-line]' always indents the current line (is bound to `TAB' | |
1369 if variable `vhdl-intelligent-tab' is nil). Indentation can be done for | |
1370 an entire region (`\\[indent-region]') or buffer (menu). Argument and | |
1371 port lists are indented normally (nil) or relative to the opening | |
1372 parenthesis (non-nil) according to variable `vhdl-argument-list-indent'. | |
1373 If variable `vhdl-indent-tabs-mode' is nil, spaces are used instead of tabs. | |
1374 `\\[tabify]' and `\\[untabify]' allow to convert spaces to tabs and vice | |
1375 versa. | |
1376 | |
1377 - ALIGNMENT: `\\[vhdl-align-noindent-region]' aligns port maps, signal and | |
1378 variable assignments, inline comments, some keywords, etc., on consecutive | |
1379 lines relative to each other within a defined region. | |
1380 `\\[vhdl-align-comment-region]' only aligns inline comments (i.e. comments | |
1381 that are at the end of a line of code). Some templates are automatically | |
1382 aligned after generation if custom variable `vhdl-auto-align' is non-nil. | |
1383 | |
1384 - KEY BINDINGS: Key bindings (`C-c ...') exist for most commands (see in menu). | |
1385 | |
1386 - VHDL MENU: All commands can be called from the VHDL menu. | |
1387 | |
1388 - INDEX MENU: For each VHDL source file, an index of the contained entities, | |
1389 architectures, packages, procedures, processes, etc., is created as a menu. | |
1390 Selecting a meny entry causes the cursor to jump to the corresponding | |
1391 position in the file. Controlled by variable `vhdl-index-menu'. | |
1392 | |
1393 - SOURCE FILE MENU: A menu containing all VHDL source files in the directory | |
1394 of the current file is generated. Selecting a menu entry loads the file. | |
1395 Controlled by variable `vhdl-source-file-menu'. | |
1396 | |
1397 - SOURCE FILE COMPILATION: The syntax of the current buffer can be analyzed | |
1398 by calling a VHDL compiler (menu, `\\[vhdl-compile]'). The compiler to be | |
1399 used is defined by variable `vhdl-compiler'. Currently supported are | |
1400 `cadence', `ikos', `quickhdl', `synopsys', `vantage', `viewlogic', and | |
1401 `v-system'. Not all compilers are tested. Please contact me for | |
1402 incorporating additional VHDL compilers. An entire hierarchy of source | |
1403 files can be compiled by the `make' command (menu, `\\[vhdl-make]'). | |
1404 This only works if an appropriate `Makefile' exists. Compiler options can | |
1405 be defined by variable `vhdl-compiler-options'. | |
1406 | |
1407 - KEYWORD CASE: Lower and upper case for keywords, predefined types, predefined | |
1408 attributes, and predefined enumeration values is supported. If the variable | |
1409 `vhdl-upper-case-keywords' is set to non-nil, keywords can be typed in | |
1410 lower case and are converted into upper case automatically (not for types, | |
1411 attributes, and enumeration values). The case of keywords, types, | |
1412 attributes, and enumeration values can be fixed for an entire region (menu) | |
1413 or buffer (`\\[vhdl-fix-case-buffer]') according to the variables | |
1414 `vhdl-upper-case-{keywords,types,attributes,enum-values}'. | |
1415 | |
1416 - HIGHLIGHTING (fontification): Keywords, predefined types, predefined | |
1417 attributes, and predefined enumeration values (controlled by variable | |
1418 `vhdl-highlight-keywords'), as well as comments, strings, and template | |
1419 prompts are highlighted using different colors. Unit and subprogram names | |
1420 as well as labels are highlighted if variable `vhdl-highlight-names' is | |
1421 non-nil. The default colors from `font-lock.el' are used if variable | |
1422 `vhdl-use-default-colors' is non-nil. Otherwise, an optimized set of colors | |
1423 is taken, which uses bright colors for signals and muted colors for | |
1424 everything else. Variable `vhdl-use-default-faces' does the same on | |
1425 monochrome monitors. | |
1426 | |
1427 Signal highlighting allows distinction between clock, reset, | |
1428 status/control, data, and test signals according to some signal | |
1429 naming convention. Their syntax is defined by variables | |
1430 `vhdl-{clock,reset,control,data,test}-signal-syntax'. Signal coloring | |
1431 is controlled by the variable `vhdl-highlight-signals'. The default | |
1432 signal naming convention is as follows: | |
1433 | |
1434 Signal attributes: | |
1435 C clock S control and status | |
1436 R asynchronous reset D data and address | |
1437 I synchronous reset T test | |
1438 | |
1439 Syntax: | |
1440 signal name ::= \"[A-Z][a-zA-Z0-9]*x[CRISDT][a-zA-Z0-9]*\" | |
1441 signal identifier -^^^^^^^^^^^^^^^^^ | |
1442 delimiter --------------------------^ | |
1443 above signal attributes -------------^^^^^^^^ | |
1444 additional attributes -----------------------^^^^^^^^^^^^ | |
1445 | |
1446 (`x' is used as delimiter because `_' is reserved by the VITAL standard.) | |
1447 Examples: ClkxCfast, ResetxRB, ClearxI, SelectDataxS, DataxD, ScanEnablexT. | |
1448 | |
1449 If all VHDL words are written in lower case (i.e. variables | |
1450 `vhdl-upper-case-{keywords,types,attributes,enum-values}' are set to nil), | |
1451 make highlighting case sensitive by setting variable | |
1452 `vhdl-highlight-case-sensitive' to non-nil. This way, only names fulfilling | |
1453 the above signal syntax including case are highlighted. | |
1454 | |
1455 - HIDE/SHOW: The code of entire VHDL processes or blocks can be hidden using | |
1456 the `Hide/Show' menu or by pressing `S-mouse-2' within the code | |
1457 (not in XEmacs). | |
1458 | |
1459 - PRINTING: Postscript printing with different fonts (`ps-print-color-p' is | |
1460 nil, default faces from `font-lock.el' used if `vhdl-use-default-faces' is | |
1461 non-nil) or colors (`ps-print-color-p' is non-nil) is possible using the | |
1462 standard Emacs postscript printing commands. Variable `vhdl-print-two-column' | |
1463 defines appropriate default settings for nice landscape two-column printing. | |
1464 The paper format can be set by variable `ps-paper-type'. | |
1465 | |
1466 - CUSTOMIZATION: All variables can easily be customized using the `Customize' | |
1467 menu entry. For some variables, customization only takes effect after | |
1468 re-starting Emacs. Customization can also be done globally (i.e. site-wide, | |
1469 read INSTALL file). Variables of VHDL Mode must NOT be set using the | |
1470 `vhdl-mode-hook' in the .emacs file anymore (delete them if they still are). | |
1471 | |
1472 | |
1473 Maintenance: | |
1474 ------------ | |
1475 | |
1476 To submit a bug report, enter `\\[vhdl-submit-bug-report]' within VHDL Mode. | |
1477 Add a description of the problem and include a reproducible test case. | |
1478 | |
1479 Questions and enhancement requests can be sent to <vhdl-mode@geocities.com>. | |
1480 | |
1481 The `vhdl-mode-announce' mailing list informs about new VHDL Mode releases. | |
1482 The `vhdl-mode-victims' mailing list informs about new VHDL Mode beta releases. | |
1483 You are kindly invited to participate in beta testing. Subscribe to above | |
1484 mailing lists by sending an email to <vhdl-mode@geocities.com>. | |
1485 | |
1486 The archive with the latest version is located at | |
1487 <http://www.geocities.com/SiliconValley/Peaks/8287>. | |
1488 | |
1489 | |
1490 Bugs and Limitations: | |
1491 --------------------- | |
1492 | |
1493 - Index menu does not work under XEmacs (limitation of XEmacs ?!). | |
1494 | |
1495 - Re-indenting large regions or expressions can be slow. | |
1496 | |
1497 - Hideshow does not work under XEmacs. | |
1498 | |
1499 - Parsing compilation error messages for Ikos and Vantage VHDL compilers | |
1500 does not work under XEmacs. | |
1501 | |
1502 | |
1503 Key bindings: | |
1504 ------------- | |
1505 | |
1506 \\{vhdl-mode-map}" | |
1507 (interactive) | |
1508 (kill-all-local-variables) | |
1509 (set-syntax-table vhdl-mode-syntax-table) | |
1510 (setq major-mode 'vhdl-mode) | |
1511 (setq mode-name "VHDL") | |
1512 (setq local-abbrev-table vhdl-mode-abbrev-table) | |
1513 (use-local-map vhdl-mode-map) | |
1514 ;; set local variable values | |
1515 (set (make-local-variable 'paragraph-start) "\\s-*\\(---\\|[a-zA-Z]\\|$\\)") | |
1516 (set (make-local-variable 'paragraph-separate) paragraph-start) | |
1517 (set (make-local-variable 'paragraph-ignore-fill-prefix) t) | |
1518 (set (make-local-variable 'require-final-newline) t) | |
1519 (set (make-local-variable 'parse-sexp-ignore-comments) t) | |
1520 (set (make-local-variable 'indent-line-function) 'vhdl-indent-line) | |
1521 (set (make-local-variable 'comment-start) "--") | |
1522 (set (make-local-variable 'comment-end) "") | |
1523 (set (make-local-variable 'comment-column) vhdl-comment-column) | |
1524 (set (make-local-variable 'end-comment-column) vhdl-end-comment-column) | |
1525 (set (make-local-variable 'comment-start-skip) "--+\\s-*") | |
1526 (set (make-local-variable 'dabbrev-case-fold-search) nil) | |
1527 (set (make-local-variable 'indent-tabs-mode) vhdl-indent-tabs-mode) | |
1528 | |
1529 ;; setup the comment indent variable in a Emacs version portable way | |
1530 ;; ignore any byte compiler warnings you might get here | |
1531 (if (boundp 'comment-indent-function) | |
1532 (progn (make-local-variable 'comment-indent-function) | |
1533 (setq comment-indent-function 'vhdl-comment-indent))) | |
1534 | |
1535 ;; initialize font locking | |
1536 (require 'font-lock) | |
1537 (vhdl-font-lock-init) | |
1538 (make-local-variable 'font-lock-defaults) | |
1539 (setq font-lock-defaults (list 'vhdl-font-lock-keywords nil | |
1540 (not vhdl-highlight-case-sensitive) | |
1541 '((?\_ . "w")))) | |
1542 (turn-on-font-lock) | |
1543 | |
1544 ;; variables for source file compilation | |
1545 (make-local-variable 'compile-command) | |
1546 (set (make-local-variable 'compilation-error-regexp-alist) | |
1547 vhdl-compilation-error-regexp-alist) | |
1548 | |
1549 ;; add menus | |
1550 (if vhdl-index-menu | |
1551 (if (or (not (consp font-lock-maximum-size)) | |
1552 (> font-lock-maximum-size (buffer-size))) | |
1553 (vhdl-add-index-menu) | |
1554 (message "Scanning buffer for index...buffer too big"))) | |
1555 (if vhdl-source-file-menu (vhdl-add-source-files-menu)) | |
1556 (easy-menu-add vhdl-mode-menu) | |
1557 (easy-menu-define vhdl-mode-easy-menu vhdl-mode-map | |
1558 "Menu keymap for VHDL Mode." vhdl-mode-menu) | |
1559 (run-hooks 'menu-bar-update-hook) | |
1560 | |
1561 ;; initialize hideshow and add menu | |
1562 (if vhdl-hideshow-menu (hs-minor-mode)) | |
1563 | |
1564 ;; initialize postscript printing | |
1565 (vhdl-ps-init) | |
1566 | |
1567 (setq mode-name (if vhdl-electric-mode "Electric VHDL" "VHDL")) | |
1568 (message "Type C-c C-h for VHDL Mode documentation.") | |
1569 | |
1570 (run-hooks 'vhdl-mode-hook) | |
1571 ) | |
1572 | |
1573 | |
1574 ;; ############################################################################ | |
1575 ;; Keywords and predefined words in VHDL'93 | |
1576 ;; ############################################################################ | |
1577 | |
1578 ;; `regexp-opt' was not used at this place because it is not yet implemented | |
1579 ;; in XEmacs and because it resulted in SLOWER regexps!! | |
1580 | |
1581 (defconst vhdl-93-keywords-regexp | |
1582 (eval-when-compile | |
1583 (concat | |
1584 "\\<\\(" | |
1585 (mapconcat | |
1586 'identity | |
1587 '( | |
1588 "abs" "access" "after" "alias" "all" "and" "architecture" "array" | |
1589 "assert" "attribute" | |
1590 "begin" "block" "body" "buffer" "bus" | |
1591 "case" "component" "configuration" "constant" | |
1592 "disconnect" "downto" | |
1593 "else" "elsif" "end" "entity" "exit" | |
1594 "file" "for" "function" | |
1595 "generate" "generic" "group" "guarded" | |
1596 "if" "impure" "in" "inertial" "inout" "is" | |
1597 "label" "library" "linkage" "literal" "loop" | |
1598 "map" "mod" | |
1599 "nand" "new" "next" "nor" "not" "null" | |
1600 "of" "on" "open" "or" "others" "out" | |
1601 "package" "port" "postponed" "procedure" "process" "pure" | |
1602 "range" "record" "register" "reject" "rem" "report" "return" | |
1603 "rol" "ror" | |
1604 "select" "severity" "shared" "signal" "sla" "sll" "sra" "srl" "subtype" | |
1605 "then" "to" "transport" "type" | |
1606 "unaffected" "units" "until" "use" | |
1607 "variable" | |
1608 "wait" "warning" "when" "while" "with" | |
1609 "xnor" "xor" | |
1610 ) | |
1611 "\\|") | |
1612 "\\)\\>")) | |
1613 "Regexp for VHDL'93 keywords.") | |
1614 | |
1615 (defconst vhdl-93-types-regexp | |
1616 (eval-when-compile | |
1617 (concat | |
1618 "\\<\\(" | |
1619 (mapconcat | |
1620 'identity | |
1621 '( | |
1622 "boolean" "bit" "bit_vector" "character" "severity_level" "integer" | |
1623 "real" "time" "natural" "positive" "string" "text" "line" | |
1624 "unsigned" "signed" | |
1625 "std_logic" "std_logic_vector" | |
1626 "std_ulogic" "std_ulogic_vector" | |
1627 ) | |
1628 "\\|") | |
1629 "\\)\\>")) | |
1630 "Regexp for VHDL'93 standardized types.") | |
1631 | |
1632 (defconst vhdl-93-attributes-regexp | |
1633 (eval-when-compile | |
1634 (concat | |
1635 "\\<\\(" | |
1636 (mapconcat | |
1637 'identity | |
1638 '( | |
1639 "base" "left" "right" "high" "low" "pos" "val" "succ" | |
1640 "pred" "leftof" "rightof" "range" "reverse_range" | |
1641 "length" "delayed" "stable" "quiet" "transaction" | |
1642 "event" "active" "last_event" "last_active" "last_value" | |
1643 "driving" "driving_value" "ascending" "value" "image" | |
1644 "simple_name" "instance_name" "path_name" | |
1645 "foreign" | |
1646 ) | |
1647 "\\|") | |
1648 "\\)\\>")) | |
1649 "Regexp for VHDL'93 standardized attributes.") | |
1650 | |
1651 (defconst vhdl-93-enum-values-regexp | |
1652 (eval-when-compile | |
1653 (concat | |
1654 "\\<\\(" | |
1655 (mapconcat | |
1656 'identity | |
1657 '( | |
1658 "true" "false" | |
1659 "note" "warning" "error" "failure" | |
1660 "fs" "ps" "ns" "us" "ms" "sec" "min" "hr" | |
1661 ) | |
1662 "\\|") | |
1663 "\\)\\>")) | |
1664 "Regexp for VHDL'93 standardized enumeration values.") | |
1665 | |
1666 | |
1667 ;; ############################################################################ | |
1668 ;; Syntax analysis and indentation | |
1669 ;; ############################################################################ | |
1670 | |
1671 ;; ############################################################################ | |
1672 ;; Syntax analysis | |
1673 | |
1674 ;; constant regular expressions for looking at various constructs | |
1675 | |
1676 (defconst vhdl-symbol-key "\\(\\w\\|\\s_\\)+" | |
1677 "Regexp describing a VHDL symbol. | |
1678 We cannot use just `word' syntax class since `_' cannot be in word | |
1679 class. Putting underscore in word class breaks forward word movement | |
1680 behavior that users are familiar with.") | |
1681 | |
1682 (defconst vhdl-case-header-key "case[( \t\n][^;=>]+[) \t\n]is" | |
1683 "Regexp describing a case statement header key.") | |
1684 | |
1685 (defconst vhdl-label-key | |
1686 (concat "\\(" vhdl-symbol-key "\\s-*:\\)[^=]") | |
1687 "Regexp describing a VHDL label.") | |
1688 | |
1689 ;; Macro definitions: | |
1690 | |
1691 (defmacro vhdl-point (position) | |
1692 ;; Returns the value of point at certain commonly referenced POSITIONs. | |
1693 ;; POSITION can be one of the following symbols: | |
1694 ;; | |
1695 ;; bol -- beginning of line | |
1696 ;; eol -- end of line | |
1697 ;; bod -- beginning of defun | |
1698 ;; boi -- back to indentation | |
1699 ;; eoi -- last whitespace on line | |
1700 ;; ionl -- indentation of next line | |
1701 ;; iopl -- indentation of previous line | |
1702 ;; bonl -- beginning of next line | |
1703 ;; bopl -- beginning of previous line | |
1704 ;; | |
1705 ;; This function does not modify point or mark. | |
1706 (or (and (eq 'quote (car-safe position)) | |
1707 (null (cdr (cdr position)))) | |
1708 (error "bad buffer position requested: %s" position)) | |
1709 (setq position (nth 1 position)) | |
1710 (` (let ((here (point))) | |
1711 (,@ (cond | |
1712 ((eq position 'bol) '((beginning-of-line))) | |
1713 ((eq position 'eol) '((end-of-line))) | |
1714 ((eq position 'bod) '((save-match-data | |
1715 (vhdl-beginning-of-defun)))) | |
1716 ((eq position 'boi) '((back-to-indentation))) | |
1717 ((eq position 'eoi) '((end-of-line)(skip-chars-backward " \t"))) | |
1718 ((eq position 'bonl) '((forward-line 1))) | |
1719 ((eq position 'bopl) '((forward-line -1))) | |
1720 ((eq position 'iopl) | |
1721 '((forward-line -1) | |
1722 (back-to-indentation))) | |
1723 ((eq position 'ionl) | |
1724 '((forward-line 1) | |
1725 (back-to-indentation))) | |
1726 (t (error "unknown buffer position requested: %s" position)) | |
1727 )) | |
1728 (prog1 | |
1729 (point) | |
1730 (goto-char here)) | |
1731 ;; workaround for an Emacs18 bug -- blech! Well, at least it | |
1732 ;; doesn't hurt for v19 | |
1733 (,@ nil) | |
1734 ))) | |
1735 | |
1736 (defmacro vhdl-safe (&rest body) | |
1737 ;; safely execute BODY, return nil if an error occurred | |
1738 (` (condition-case nil | |
1739 (progn (,@ body)) | |
1740 (error nil)))) | |
1741 | |
1742 (defmacro vhdl-add-syntax (symbol &optional relpos) | |
1743 ;; a simple macro to append the syntax in symbol to the syntax list. | |
1744 ;; try to increase performance by using this macro | |
1745 (` (setq vhdl-syntactic-context | |
1746 (cons (cons (, symbol) (, relpos)) vhdl-syntactic-context)))) | |
1747 | |
1748 (defmacro vhdl-has-syntax (symbol) | |
1749 ;; a simple macro to return check the syntax list. | |
1750 ;; try to increase performance by using this macro | |
1751 (` (assoc (, symbol) vhdl-syntactic-context))) | |
1752 | |
1753 ;; Syntactic element offset manipulation: | |
1754 | |
1755 (defun vhdl-read-offset (langelem) | |
1756 ;; read new offset value for LANGELEM from minibuffer. return a | |
1757 ;; legal value only | |
1758 (let ((oldoff (format "%s" (cdr-safe (assq langelem vhdl-offsets-alist)))) | |
1759 (errmsg "Offset must be int, func, var, or one of +, -, ++, --: ") | |
1760 (prompt "Offset: ") | |
1761 offset input interned) | |
1762 (while (not offset) | |
1763 (setq input (read-string prompt oldoff) | |
1764 offset (cond ((string-equal "+" input) '+) | |
1765 ((string-equal "-" input) '-) | |
1766 ((string-equal "++" input) '++) | |
1767 ((string-equal "--" input) '--) | |
1768 ((string-match "^-?[0-9]+$" input) | |
1769 (string-to-int input)) | |
1770 ((fboundp (setq interned (intern input))) | |
1771 interned) | |
1772 ((boundp interned) interned) | |
1773 ;; error, but don't signal one, keep trying | |
1774 ;; to read an input value | |
1775 (t (ding) | |
1776 (setq prompt errmsg) | |
1777 nil)))) | |
1778 offset)) | |
1779 | |
1780 (defun vhdl-set-offset (symbol offset &optional add-p) | |
1781 "Change the value of a syntactic element symbol in `vhdl-offsets-alist'. | |
1782 SYMBOL is the syntactic element symbol to change and OFFSET is the new | |
1783 offset for that syntactic element. Optional ADD says to add SYMBOL to | |
1784 `vhdl-offsets-alist' if it doesn't already appear there." | |
1785 (interactive | |
1786 (let* ((langelem | |
1787 (intern (completing-read | |
1788 (concat "Syntactic symbol to change" | |
1789 (if current-prefix-arg " or add" "") | |
1790 ": ") | |
1791 (mapcar | |
1792 (function | |
1793 (lambda (langelem) | |
1794 (cons (format "%s" (car langelem)) nil))) | |
1795 vhdl-offsets-alist) | |
1796 nil (not current-prefix-arg) | |
1797 ;; initial contents tries to be the last element | |
1798 ;; on the syntactic analysis list for the current | |
1799 ;; line | |
1800 (let* ((syntax (vhdl-get-syntactic-context)) | |
1801 (len (length syntax)) | |
1802 (ic (format "%s" (car (nth (1- len) syntax))))) | |
1803 (if (memq 'v19 vhdl-emacs-features) | |
1804 (cons ic 0) | |
1805 ic)) | |
1806 ))) | |
1807 (offset (vhdl-read-offset langelem))) | |
1808 (list langelem offset current-prefix-arg))) | |
1809 ;; sanity check offset | |
1810 (or (eq offset '+) | |
1811 (eq offset '-) | |
1812 (eq offset '++) | |
1813 (eq offset '--) | |
1814 (integerp offset) | |
1815 (fboundp offset) | |
1816 (boundp offset) | |
1817 (error "Offset must be int, func, var, or one of +, -, ++, --: %s" | |
1818 offset)) | |
1819 (let ((entry (assq symbol vhdl-offsets-alist))) | |
1820 (if entry | |
1821 (setcdr entry offset) | |
1822 (if add-p | |
1823 (setq vhdl-offsets-alist (cons (cons symbol offset) vhdl-offsets-alist)) | |
1824 (error "%s is not a valid syntactic symbol." symbol)))) | |
1825 (vhdl-keep-region-active)) | |
1826 | |
1827 (defun vhdl-set-style (style &optional local) | |
1828 "Set vhdl-mode variables to use one of several different indentation styles. | |
1829 STYLE is a string representing the desired style and optional LOCAL is | |
1830 a flag which, if non-nil, means to make the style variables being | |
1831 changed buffer local, instead of the default, which is to set the | |
1832 global variables. Interactively, the flag comes from the prefix | |
1833 argument. The styles are chosen from the `vhdl-style-alist' variable." | |
1834 (interactive (list (completing-read "Use which VHDL indentation style? " | |
1835 vhdl-style-alist nil t) | |
1836 current-prefix-arg)) | |
1837 (let ((vars (cdr (assoc style vhdl-style-alist)))) | |
1838 (or vars | |
1839 (error "Invalid VHDL indentation style `%s'" style)) | |
1840 ;; set all the variables | |
1841 (mapcar | |
1842 (function | |
1843 (lambda (varentry) | |
1844 (let ((var (car varentry)) | |
1845 (val (cdr varentry))) | |
1846 (and local | |
1847 (make-local-variable var)) | |
1848 ;; special case for vhdl-offsets-alist | |
1849 (if (not (eq var 'vhdl-offsets-alist)) | |
1850 (set var val) | |
1851 ;; reset vhdl-offsets-alist to the default value first | |
1852 (setq vhdl-offsets-alist (copy-alist vhdl-offsets-alist-default)) | |
1853 ;; now set the langelems that are different | |
1854 (mapcar | |
1855 (function | |
1856 (lambda (langentry) | |
1857 (let ((langelem (car langentry)) | |
1858 (offset (cdr langentry))) | |
1859 (vhdl-set-offset langelem offset) | |
1860 ))) | |
1861 val)) | |
1862 ))) | |
1863 vars)) | |
1864 (vhdl-keep-region-active)) | |
1865 | |
1866 (defun vhdl-get-offset (langelem) | |
1867 ;; Get offset from LANGELEM which is a cons cell of the form: | |
1868 ;; (SYMBOL . RELPOS). The symbol is matched against | |
1869 ;; vhdl-offsets-alist and the offset found there is either returned, | |
1870 ;; or added to the indentation at RELPOS. If RELPOS is nil, then | |
1871 ;; the offset is simply returned. | |
1872 (let* ((symbol (car langelem)) | |
1873 (relpos (cdr langelem)) | |
1874 (match (assq symbol vhdl-offsets-alist)) | |
1875 (offset (cdr-safe match))) | |
1876 ;; offset can be a number, a function, a variable, or one of the | |
1877 ;; symbols + or - | |
1878 (cond | |
1879 ((not match) | |
1880 (if vhdl-strict-syntax-p | |
1881 (error "don't know how to indent a %s" symbol) | |
1882 (setq offset 0 | |
1883 relpos 0))) | |
1884 ((eq offset '+) (setq offset vhdl-basic-offset)) | |
1885 ((eq offset '-) (setq offset (- vhdl-basic-offset))) | |
1886 ((eq offset '++) (setq offset (* 2 vhdl-basic-offset))) | |
1887 ((eq offset '--) (setq offset (* 2 (- vhdl-basic-offset)))) | |
1888 ((and (not (numberp offset)) | |
1889 (fboundp offset)) | |
1890 (setq offset (funcall offset langelem))) | |
1891 ((not (numberp offset)) | |
1892 (setq offset (eval offset))) | |
1893 ) | |
1894 (+ (if (and relpos | |
1895 (< relpos (vhdl-point 'bol))) | |
1896 (save-excursion | |
1897 (goto-char relpos) | |
1898 (current-column)) | |
1899 0) | |
1900 offset))) | |
1901 | |
1902 ;; Syntactic support functions: | |
1903 | |
1904 ;; Returns `comment' if in a comment, `string' if in a string literal, | |
1905 ;; or nil if not in a literal at all. Optional LIM is used as the | |
1906 ;; backward limit of the search. If omitted, or nil, (point-min) is | |
1907 ;; used. | |
1908 | |
1909 (defun vhdl-in-literal (&optional lim) | |
1910 ;; Determine if point is in a VHDL literal. | |
1911 (save-excursion | |
1912 (let* ((lim (or lim (point-min))) | |
1913 (state (parse-partial-sexp lim (point)))) | |
1914 (cond | |
1915 ((nth 3 state) 'string) | |
1916 ((nth 4 state) 'comment) | |
1917 (t nil))) | |
1918 )) | |
1919 | |
1920 ;; This is the best we can do in Win-Emacs. | |
1921 (defun vhdl-win-il (&optional lim) | |
1922 ;; Determine if point is in a VHDL literal | |
1923 (save-excursion | |
1924 (let* ((here (point)) | |
1925 (state nil) | |
1926 (match nil) | |
1927 (lim (or lim (vhdl-point 'bod)))) | |
1928 (goto-char lim ) | |
1929 (while (< (point) here) | |
1930 (setq match | |
1931 (and (re-search-forward "--\\|[\"']" | |
1932 here 'move) | |
1933 (buffer-substring (match-beginning 0) (match-end 0)))) | |
1934 (setq state | |
1935 (cond | |
1936 ;; no match | |
1937 ((null match) nil) | |
1938 ;; looking at the opening of a VHDL style comment | |
1939 ((string= "--" match) | |
1940 (if (<= here (progn (end-of-line) (point))) 'comment)) | |
1941 ;; looking at the opening of a double quote string | |
1942 ((string= "\"" match) | |
1943 (if (not (save-restriction | |
1944 ;; this seems to be necessary since the | |
1945 ;; re-search-forward will not work without it | |
1946 (narrow-to-region (point) here) | |
1947 (re-search-forward | |
1948 ;; this regexp matches a double quote | |
1949 ;; which is preceded by an even number | |
1950 ;; of backslashes, including zero | |
1951 "\\([^\\]\\|^\\)\\(\\\\\\\\\\)*\"" here 'move))) | |
1952 'string)) | |
1953 ;; looking at the opening of a single quote string | |
1954 ((string= "'" match) | |
1955 (if (not (save-restriction | |
1956 ;; see comments from above | |
1957 (narrow-to-region (point) here) | |
1958 (re-search-forward | |
1959 ;; this matches a single quote which is | |
1960 ;; preceded by zero or two backslashes. | |
1961 "\\([^\\]\\|^\\)\\(\\\\\\\\\\)?'" | |
1962 here 'move))) | |
1963 'string)) | |
1964 (t nil))) | |
1965 ) ; end-while | |
1966 state))) | |
1967 | |
1968 (and (memq 'Win-Emacs vhdl-emacs-features) | |
1969 (fset 'vhdl-in-literal 'vhdl-win-il)) | |
1970 | |
1971 ;; Skipping of "syntactic whitespace". Syntactic whitespace is | |
1972 ;; defined as lexical whitespace or comments. Search no farther back | |
1973 ;; or forward than optional LIM. If LIM is omitted, (point-min) is | |
1974 ;; used for backward skipping, (point-max) is used for forward | |
1975 ;; skipping. | |
1976 | |
1977 (defun vhdl-forward-syntactic-ws (&optional lim) | |
1978 ;; Forward skip of syntactic whitespace. | |
1979 (save-restriction | |
1980 (let* ((lim (or lim (point-max))) | |
1981 (here lim) | |
1982 (hugenum (point-max))) | |
1983 (narrow-to-region lim (point)) | |
1984 (while (/= here (point)) | |
1985 (setq here (point)) | |
1986 (forward-comment hugenum)) | |
1987 ))) | |
1988 | |
1989 ;; This is the best we can do in Win-Emacs. | |
1990 (defun vhdl-win-fsws (&optional lim) | |
1991 ;; Forward skip syntactic whitespace for Win-Emacs. | |
1992 (let ((lim (or lim (point-max))) | |
1993 stop) | |
1994 (while (not stop) | |
1995 (skip-chars-forward " \t\n\r\f" lim) | |
1996 (cond | |
1997 ;; vhdl comment | |
1998 ((looking-at "--") (end-of-line)) | |
1999 ;; none of the above | |
2000 (t (setq stop t)) | |
2001 )))) | |
2002 | |
2003 (and (memq 'Win-Emacs vhdl-emacs-features) | |
2004 (fset 'vhdl-forward-syntactic-ws 'vhdl-win-fsws)) | |
2005 | |
2006 (defun vhdl-backward-syntactic-ws (&optional lim) | |
2007 ;; Backward skip over syntactic whitespace. | |
2008 (save-restriction | |
2009 (let* ((lim (or lim (point-min))) | |
2010 (here lim) | |
2011 (hugenum (- (point-max)))) | |
2012 (if (< lim (point)) | |
2013 (progn | |
2014 (narrow-to-region lim (point)) | |
2015 (while (/= here (point)) | |
2016 (setq here (point)) | |
2017 (forward-comment hugenum) | |
2018 ))) | |
2019 ))) | |
2020 | |
2021 ;; This is the best we can do in Win-Emacs. | |
2022 (defun vhdl-win-bsws (&optional lim) | |
2023 ;; Backward skip syntactic whitespace for Win-Emacs. | |
2024 (let ((lim (or lim (vhdl-point 'bod))) | |
2025 stop) | |
2026 (while (not stop) | |
2027 (skip-chars-backward " \t\n\r\f" lim) | |
2028 (cond | |
2029 ;; vhdl comment | |
2030 ((eq (vhdl-in-literal lim) 'comment) | |
2031 (skip-chars-backward "^-" lim) | |
2032 (skip-chars-backward "-" lim) | |
2033 (while (not (or (and (= (following-char) ?-) | |
2034 (= (char-after (1+ (point))) ?-)) | |
2035 (<= (point) lim))) | |
2036 (skip-chars-backward "^-" lim) | |
2037 (skip-chars-backward "-" lim))) | |
2038 ;; none of the above | |
2039 (t (setq stop t)) | |
2040 )))) | |
2041 | |
2042 (and (memq 'Win-Emacs vhdl-emacs-features) | |
2043 (fset 'vhdl-backward-syntactic-ws 'vhdl-win-bsws)) | |
2044 | |
2045 ;; Functions to help finding the correct indentation column: | |
2046 | |
2047 (defun vhdl-first-word (point) | |
2048 "If the keyword at POINT is at boi, then return (current-column) at | |
2049 that point, else nil." | |
2050 (save-excursion | |
2051 (and (goto-char point) | |
2052 (eq (point) (vhdl-point 'boi)) | |
2053 (current-column)))) | |
2054 | |
2055 (defun vhdl-last-word (point) | |
2056 "If the keyword at POINT is at eoi, then return (current-column) at | |
2057 that point, else nil." | |
2058 (save-excursion | |
2059 (and (goto-char point) | |
2060 (save-excursion (or (eq (progn (forward-sexp) (point)) | |
2061 (vhdl-point 'eoi)) | |
2062 (looking-at "\\s-*\\(--\\)?"))) | |
2063 (current-column)))) | |
2064 | |
2065 ;; Core syntactic evaluation functions: | |
2066 | |
2067 (defconst vhdl-libunit-re | |
2068 "\\b\\(architecture\\|configuration\\|entity\\|package\\)\\b[^_]") | |
2069 | |
2070 (defun vhdl-libunit-p () | |
2071 (and | |
2072 (save-excursion | |
2073 (forward-sexp) | |
2074 (skip-chars-forward " \t\n") | |
2075 (not (looking-at "is\\b[^_]"))) | |
2076 (save-excursion | |
2077 (backward-sexp) | |
2078 (and (not (looking-at "use\\b[^_]")) | |
2079 (progn | |
2080 (forward-sexp) | |
2081 (vhdl-forward-syntactic-ws) | |
2082 (/= (following-char) ?:)))) | |
2083 )) | |
2084 | |
2085 (defconst vhdl-defun-re | |
2086 "\\b\\(architecture\\|block\\|configuration\\|entity\\|package\\|process\\|procedure\\|function\\)\\b[^_]") | |
2087 | |
2088 (defun vhdl-defun-p () | |
2089 (save-excursion | |
2090 (if (looking-at "block\\|process") | |
2091 ;; "block", "process": | |
2092 (save-excursion | |
2093 (backward-sexp) | |
2094 (not (looking-at "end\\s-+\\w"))) | |
2095 ;; "architecture", "configuration", "entity", | |
2096 ;; "package", "procedure", "function": | |
2097 t))) | |
2098 | |
2099 (defun vhdl-corresponding-defun () | |
2100 "If the word at the current position corresponds to a \"defun\" | |
2101 keyword, then return a string that can be used to find the | |
2102 corresponding \"begin\" keyword, else return nil." | |
2103 (save-excursion | |
2104 (and (looking-at vhdl-defun-re) | |
2105 (vhdl-defun-p) | |
2106 (if (looking-at "block\\|process") | |
2107 ;; "block", "process": | |
2108 (buffer-substring (match-beginning 0) (match-end 0)) | |
2109 ;; "architecture", "configuration", "entity", "package", | |
2110 ;; "procedure", "function": | |
2111 "is")))) | |
2112 | |
2113 (defconst vhdl-begin-fwd-re | |
2114 "\\b\\(is\\|begin\\|block\\|component\\|generate\\|then\\|else\\|loop\\|process\\|units\\|record\\|for\\)\\b\\([^_]\\|\\'\\)" | |
2115 "A regular expression for searching forward that matches all known | |
2116 \"begin\" keywords.") | |
2117 | |
2118 (defconst vhdl-begin-bwd-re | |
2119 "\\b\\(is\\|begin\\|block\\|component\\|generate\\|then\\|else\\|loop\\|process\\|units\\|record\\|for\\)\\b[^_]" | |
2120 "A regular expression for searching backward that matches all known | |
2121 \"begin\" keywords.") | |
2122 | |
2123 (defun vhdl-begin-p (&optional lim) | |
2124 "Return t if we are looking at a real \"begin\" keyword. | |
2125 Assumes that the caller will make sure that we are looking at | |
2126 vhdl-begin-fwd-re, and are not inside a literal, and that we are not in | |
2127 the middle of an identifier that just happens to contain a \"begin\" | |
2128 keyword." | |
2129 (cond | |
2130 ;; "[architecture|case|configuration|entity|package| | |
2131 ;; procedure|function] ... is": | |
2132 ((and (looking-at "i") | |
2133 (save-excursion | |
2134 ;; Skip backward over first sexp (needed to skip over a | |
2135 ;; procedure interface list, and is harmless in other | |
2136 ;; situations). Note that we need "return" in the | |
2137 ;; following search list so that we don't run into | |
2138 ;; semicolons in the function interface list. | |
2139 (backward-sexp) | |
2140 (let (foundp) | |
2141 (while (and (not foundp) | |
2142 (re-search-backward | |
2143 ";\\|\\b\\(architecture\\|case\\|configuration\\|entity\\|package\\|procedure\\|return\\|is\\|begin\\|process\\|block\\)\\b[^_]" | |
2144 lim 'move)) | |
2145 (if (or (= (preceding-char) ?_) | |
2146 (vhdl-in-literal lim)) | |
2147 (backward-char) | |
2148 (setq foundp t)))) | |
2149 (and (/= (following-char) ?\;) | |
2150 (not (looking-at "is\\|begin\\|process\\|block"))))) | |
2151 t) | |
2152 ;; "begin", "then": | |
2153 ((looking-at "be\\|t") | |
2154 t) | |
2155 ;; "else": | |
2156 ((and (looking-at "e") | |
2157 ;; make sure that the "else" isn't inside a | |
2158 ;; conditional signal assignment. | |
2159 (save-excursion | |
2160 (re-search-backward ";\\|\\bwhen\\b[^_]" lim 'move) | |
2161 (or (eq (following-char) ?\;) | |
2162 (eq (point) lim)))) | |
2163 t) | |
2164 ;; "block", "generate", "loop", "process", | |
2165 ;; "units", "record": | |
2166 ((and (looking-at "bl\\|[glpur]") | |
2167 (save-excursion | |
2168 (backward-sexp) | |
2169 (not (looking-at "end\\s-+\\w")))) | |
2170 t) | |
2171 ;; "component": | |
2172 ((and (looking-at "c") | |
2173 (save-excursion | |
2174 (backward-sexp) | |
2175 (not (looking-at "end\\s-+\\w"))) | |
2176 ;; look out for the dreaded entity class in an attribute | |
2177 (save-excursion | |
2178 (vhdl-backward-syntactic-ws lim) | |
2179 (/= (preceding-char) ?:))) | |
2180 t) | |
2181 ;; "for" (inside configuration declaration): | |
2182 ((and (looking-at "f") | |
2183 (save-excursion | |
2184 (backward-sexp) | |
2185 (not (looking-at "end\\s-+\\w"))) | |
2186 (vhdl-has-syntax 'configuration)) | |
2187 t) | |
2188 )) | |
2189 | |
2190 (defun vhdl-corresponding-mid (&optional lim) | |
2191 (cond | |
2192 ((looking-at "is\\|block\\|process") | |
2193 "begin") | |
2194 ((looking-at "then") | |
2195 "<else>") | |
2196 (t | |
2197 "end"))) | |
2198 | |
2199 (defun vhdl-corresponding-end (&optional lim) | |
2200 "If the word at the current position corresponds to a \"begin\" | |
2201 keyword, then return a vector containing enough information to find | |
2202 the corresponding \"end\" keyword, else return nil. The keyword to | |
2203 search forward for is aref 0. The column in which the keyword must | |
2204 appear is aref 1 or nil if any column is suitable. | |
2205 Assumes that the caller will make sure that we are not in the middle | |
2206 of an identifier that just happens to contain a \"begin\" keyword." | |
2207 (save-excursion | |
2208 (and (looking-at vhdl-begin-fwd-re) | |
2209 (/= (preceding-char) ?_) | |
2210 (not (vhdl-in-literal lim)) | |
2211 (vhdl-begin-p lim) | |
2212 (cond | |
2213 ;; "is", "generate", "loop": | |
2214 ((looking-at "[igl]") | |
2215 (vector "end" | |
2216 (and (vhdl-last-word (point)) | |
2217 (or (vhdl-first-word (point)) | |
2218 (save-excursion | |
2219 (vhdl-beginning-of-statement-1 lim) | |
2220 (vhdl-backward-skip-label lim) | |
2221 (vhdl-first-word (point))))))) | |
2222 ;; "begin", "else", "for": | |
2223 ((looking-at "be\\|[ef]") | |
2224 (vector "end" | |
2225 (and (vhdl-last-word (point)) | |
2226 (or (vhdl-first-word (point)) | |
2227 (save-excursion | |
2228 (vhdl-beginning-of-statement-1 lim) | |
2229 (vhdl-backward-skip-label lim) | |
2230 (vhdl-first-word (point))))))) | |
2231 ;; "component", "units", "record": | |
2232 ((looking-at "[cur]") | |
2233 ;; The first end found will close the block | |
2234 (vector "end" nil)) | |
2235 ;; "block", "process": | |
2236 ((looking-at "bl\\|p") | |
2237 (vector "end" | |
2238 (or (vhdl-first-word (point)) | |
2239 (save-excursion | |
2240 (vhdl-beginning-of-statement-1 lim) | |
2241 (vhdl-backward-skip-label lim) | |
2242 (vhdl-first-word (point)))))) | |
2243 ;; "then": | |
2244 ((looking-at "t") | |
2245 (vector "elsif\\|else\\|end\\s-+if" | |
2246 (and (vhdl-last-word (point)) | |
2247 (or (vhdl-first-word (point)) | |
2248 (save-excursion | |
2249 (vhdl-beginning-of-statement-1 lim) | |
2250 (vhdl-backward-skip-label lim) | |
2251 (vhdl-first-word (point))))))) | |
2252 )))) | |
2253 | |
2254 (defconst vhdl-end-fwd-re "\\b\\(end\\|else\\|elsif\\)\\b\\([^_]\\|\\'\\)") | |
2255 | |
2256 (defconst vhdl-end-bwd-re "\\b\\(end\\|else\\|elsif\\)\\b[^_]") | |
2257 | |
2258 (defun vhdl-end-p (&optional lim) | |
2259 "Return t if we are looking at a real \"end\" keyword. | |
2260 Assumes that the caller will make sure that we are looking at | |
2261 vhdl-end-fwd-re, and are not inside a literal, and that we are not in | |
2262 the middle of an identifier that just happens to contain an \"end\" | |
2263 keyword." | |
2264 (or (not (looking-at "else")) | |
2265 ;; make sure that the "else" isn't inside a conditional signal | |
2266 ;; assignment. | |
2267 (save-excursion | |
2268 (re-search-backward ";\\|\\bwhen\\b[^_]" lim 'move) | |
2269 (or (eq (following-char) ?\;) | |
2270 (eq (point) lim))))) | |
2271 | |
2272 (defun vhdl-corresponding-begin (&optional lim) | |
2273 "If the word at the current position corresponds to an \"end\" | |
2274 keyword, then return a vector containing enough information to find | |
2275 the corresponding \"begin\" keyword, else return nil. The keyword to | |
2276 search backward for is aref 0. The column in which the keyword must | |
2277 appear is aref 1 or nil if any column is suitable. The supplementary | |
2278 keyword to search forward for is aref 2 or nil if this is not | |
2279 required. If aref 3 is t, then the \"begin\" keyword may be found in | |
2280 the middle of a statement. | |
2281 Assumes that the caller will make sure that we are not in the middle | |
2282 of an identifier that just happens to contain an \"end\" keyword." | |
2283 (save-excursion | |
2284 (let (pos) | |
2285 (if (and (looking-at vhdl-end-fwd-re) | |
2286 (not (vhdl-in-literal lim)) | |
2287 (vhdl-end-p lim)) | |
2288 (if (looking-at "el") | |
2289 ;; "else", "elsif": | |
2290 (vector "if\\|elsif" (vhdl-first-word (point)) "then" nil) | |
2291 ;; "end ...": | |
2292 (setq pos (point)) | |
2293 (forward-sexp) | |
2294 (skip-chars-forward " \t\n") | |
2295 (cond | |
2296 ;; "end if": | |
2297 ((looking-at "if\\b[^_]") | |
2298 (vector "else\\|elsif\\|if" | |
2299 (vhdl-first-word pos) | |
2300 "else\\|then" nil)) | |
2301 ;; "end component": | |
2302 ((looking-at "component\\b[^_]") | |
2303 (vector (buffer-substring (match-beginning 1) | |
2304 (match-end 1)) | |
2305 (vhdl-first-word pos) | |
2306 nil nil)) | |
2307 ;; "end units", "end record": | |
2308 ((looking-at "\\(units\\|record\\)\\b[^_]") | |
2309 (vector (buffer-substring (match-beginning 1) | |
2310 (match-end 1)) | |
2311 (vhdl-first-word pos) | |
2312 nil t)) | |
2313 ;; "end block", "end process": | |
2314 ((looking-at "\\(block\\|process\\)\\b[^_]") | |
2315 (vector "begin" (vhdl-first-word pos) nil nil)) | |
2316 ;; "end case": | |
2317 ((looking-at "case\\b[^_]") | |
2318 (vector "case" (vhdl-first-word pos) "is" nil)) | |
2319 ;; "end generate": | |
2320 ((looking-at "generate\\b[^_]") | |
2321 (vector "generate\\|for\\|if" | |
2322 (vhdl-first-word pos) | |
2323 "generate" nil)) | |
2324 ;; "end loop": | |
2325 ((looking-at "loop\\b[^_]") | |
2326 (vector "loop\\|while\\|for" | |
2327 (vhdl-first-word pos) | |
2328 "loop" nil)) | |
2329 ;; "end for" (inside configuration declaration): | |
2330 ((looking-at "for\\b[^_]") | |
2331 (vector "for" (vhdl-first-word pos) nil nil)) | |
2332 ;; "end [id]": | |
2333 (t | |
2334 (vector "begin\\|architecture\\|configuration\\|entity\\|package\\|procedure\\|function" | |
2335 (vhdl-first-word pos) | |
2336 ;; return an alist of (statement . keyword) mappings | |
2337 '( | |
2338 ;; "begin ... end [id]": | |
2339 ("begin" . nil) | |
2340 ;; "architecture ... is ... begin ... end [id]": | |
2341 ("architecture" . "is") | |
2342 ;; "configuration ... is ... end [id]": | |
2343 ("configuration" . "is") | |
2344 ;; "entity ... is ... end [id]": | |
2345 ("entity" . "is") | |
2346 ;; "package ... is ... end [id]": | |
2347 ("package" . "is") | |
2348 ;; "procedure ... is ... begin ... end [id]": | |
2349 ("procedure" . "is") | |
2350 ;; "function ... is ... begin ... end [id]": | |
2351 ("function" . "is") | |
2352 ) | |
2353 nil)) | |
2354 ))) ; "end ..." | |
2355 ))) | |
2356 | |
2357 (defconst vhdl-leader-re | |
2358 "\\b\\(block\\|component\\|process\\|for\\)\\b[^_]") | |
2359 | |
2360 (defun vhdl-end-of-leader () | |
2361 (save-excursion | |
2362 (cond ((looking-at "block\\|process") | |
2363 (if (save-excursion | |
2364 (forward-sexp) | |
2365 (skip-chars-forward " \t\n") | |
2366 (= (following-char) ?\()) | |
2367 (forward-sexp 2) | |
2368 (forward-sexp)) | |
2369 (point)) | |
2370 ((looking-at "component") | |
2371 (forward-sexp 2) | |
2372 (point)) | |
2373 ((looking-at "for") | |
2374 (forward-sexp 2) | |
2375 (skip-chars-forward " \t\n") | |
2376 (while (looking-at "[,:(]") | |
2377 (forward-sexp) | |
2378 (skip-chars-forward " \t\n")) | |
2379 (point)) | |
2380 (t nil) | |
2381 ))) | |
2382 | |
2383 (defconst vhdl-trailer-re | |
2384 "\\b\\(is\\|then\\|generate\\|loop\\)\\b[^_]") | |
2385 | |
2386 (defconst vhdl-statement-fwd-re | |
2387 "\\b\\(if\\|for\\|while\\)\\b\\([^_]\\|\\'\\)" | |
2388 "A regular expression for searching forward that matches all known | |
2389 \"statement\" keywords.") | |
2390 | |
2391 (defconst vhdl-statement-bwd-re | |
2392 "\\b\\(if\\|for\\|while\\)\\b[^_]" | |
2393 "A regular expression for searching backward that matches all known | |
2394 \"statement\" keywords.") | |
2395 | |
2396 (defun vhdl-statement-p (&optional lim) | |
2397 "Return t if we are looking at a real \"statement\" keyword. | |
2398 Assumes that the caller will make sure that we are looking at | |
2399 vhdl-statement-fwd-re, and are not inside a literal, and that we are not in | |
2400 the middle of an identifier that just happens to contain a \"statement\" | |
2401 keyword." | |
2402 (cond | |
2403 ;; "for" ... "generate": | |
2404 ((and (looking-at "f") | |
2405 ;; Make sure it's the start of a parameter specification. | |
2406 (save-excursion | |
2407 (forward-sexp 2) | |
2408 (skip-chars-forward " \t\n") | |
2409 (looking-at "in\\b[^_]")) | |
2410 ;; Make sure it's not an "end for". | |
2411 (save-excursion | |
2412 (backward-sexp) | |
2413 (not (looking-at "end\\s-+\\w")))) | |
2414 t) | |
2415 ;; "if" ... "then", "if" ... "generate", "if" ... "loop": | |
2416 ((and (looking-at "i") | |
2417 ;; Make sure it's not an "end if". | |
2418 (save-excursion | |
2419 (backward-sexp) | |
2420 (not (looking-at "end\\s-+\\w")))) | |
2421 t) | |
2422 ;; "while" ... "loop": | |
2423 ((looking-at "w") | |
2424 t) | |
2425 )) | |
2426 | |
2427 (defconst vhdl-case-alternative-re "when[( \t\n][^;=>]+=>" | |
2428 "Regexp describing a case statement alternative key.") | |
2429 | |
2430 (defun vhdl-case-alternative-p (&optional lim) | |
2431 "Return t if we are looking at a real case alternative. | |
2432 Assumes that the caller will make sure that we are looking at | |
2433 vhdl-case-alternative-re, and are not inside a literal, and that | |
2434 we are not in the middle of an identifier that just happens to | |
2435 contain a \"when\" keyword." | |
2436 (save-excursion | |
2437 (let (foundp) | |
2438 (while (and (not foundp) | |
2439 (re-search-backward ";\\|<=" lim 'move)) | |
2440 (if (or (= (preceding-char) ?_) | |
2441 (vhdl-in-literal lim)) | |
2442 (backward-char) | |
2443 (setq foundp t))) | |
2444 (or (eq (following-char) ?\;) | |
2445 (eq (point) lim))) | |
2446 )) | |
2447 | |
2448 ;; Core syntactic movement functions: | |
2449 | |
2450 (defconst vhdl-b-t-b-re | |
2451 (concat vhdl-begin-bwd-re "\\|" vhdl-end-bwd-re)) | |
2452 | |
2453 (defun vhdl-backward-to-block (&optional lim) | |
2454 "Move backward to the previous \"begin\" or \"end\" keyword." | |
2455 (let (foundp) | |
2456 (while (and (not foundp) | |
2457 (re-search-backward vhdl-b-t-b-re lim 'move)) | |
2458 (if (or (= (preceding-char) ?_) | |
2459 (vhdl-in-literal lim)) | |
2460 (backward-char) | |
2461 (cond | |
2462 ;; "begin" keyword: | |
2463 ((and (looking-at vhdl-begin-fwd-re) | |
2464 (/= (preceding-char) ?_) | |
2465 (vhdl-begin-p lim)) | |
2466 (setq foundp 'begin)) | |
2467 ;; "end" keyword: | |
2468 ((and (looking-at vhdl-end-fwd-re) | |
2469 (/= (preceding-char) ?_) | |
2470 (vhdl-end-p lim)) | |
2471 (setq foundp 'end)) | |
2472 )) | |
2473 ) | |
2474 foundp | |
2475 )) | |
2476 | |
2477 (defun vhdl-forward-sexp (&optional count lim) | |
2478 "Move forward across one balanced expression (sexp). | |
2479 With COUNT, do it that many times." | |
2480 (interactive "p") | |
2481 (let ((count (or count 1)) | |
2482 (case-fold-search t) | |
2483 end-vec target) | |
2484 (save-excursion | |
2485 (while (> count 0) | |
2486 ;; skip whitespace | |
2487 (skip-chars-forward " \t\n") | |
2488 ;; Check for an unbalanced "end" keyword | |
2489 (if (and (looking-at vhdl-end-fwd-re) | |
2490 (/= (preceding-char) ?_) | |
2491 (not (vhdl-in-literal lim)) | |
2492 (vhdl-end-p lim) | |
2493 (not (looking-at "else"))) | |
2494 (error | |
2495 "Containing expression ends prematurely in vhdl-forward-sexp")) | |
2496 ;; If the current keyword is a "begin" keyword, then find the | |
2497 ;; corresponding "end" keyword. | |
2498 (if (setq end-vec (vhdl-corresponding-end lim)) | |
2499 (let ( | |
2500 ;; end-re is the statement keyword to search for | |
2501 (end-re | |
2502 (concat "\\b\\(" (aref end-vec 0) "\\)\\b\\([^_]\\|\\'\\)")) | |
2503 ;; column is either the statement keyword target column | |
2504 ;; or nil | |
2505 (column (aref end-vec 1)) | |
2506 (eol (vhdl-point 'eol)) | |
2507 foundp literal placeholder) | |
2508 ;; Look for the statement keyword. | |
2509 (while (and (not foundp) | |
2510 (re-search-forward end-re nil t) | |
2511 (setq placeholder (match-end 1)) | |
2512 (goto-char (match-beginning 0))) | |
2513 ;; If we are in a literal, or not in the right target | |
2514 ;; column and not on the same line as the begin, then | |
2515 ;; try again. | |
2516 (if (or (and column | |
2517 (/= (current-indentation) column) | |
2518 (> (point) eol)) | |
2519 (= (preceding-char) ?_) | |
2520 (setq literal (vhdl-in-literal lim))) | |
2521 (if (eq literal 'comment) | |
2522 (end-of-line) | |
2523 (forward-char)) | |
2524 ;; An "else" keyword corresponds to both the opening brace | |
2525 ;; of the following sexp and the closing brace of the | |
2526 ;; previous sexp. | |
2527 (if (not (looking-at "else")) | |
2528 (goto-char placeholder)) | |
2529 (setq foundp t)) | |
2530 ) | |
2531 (if (not foundp) | |
2532 (error "Unbalanced keywords in vhdl-forward-sexp")) | |
2533 ) | |
2534 ;; If the current keyword is not a "begin" keyword, then just | |
2535 ;; perform the normal forward-sexp. | |
2536 (forward-sexp) | |
2537 ) | |
2538 (setq count (1- count)) | |
2539 ) | |
2540 (setq target (point))) | |
2541 (goto-char target) | |
2542 nil)) | |
2543 | |
2544 (defun vhdl-backward-sexp (&optional count lim) | |
2545 "Move backward across one balanced expression (sexp). | |
2546 With COUNT, do it that many times. LIM bounds any required backward | |
2547 searches." | |
2548 (interactive "p") | |
2549 (let ((count (or count 1)) | |
2550 (case-fold-search t) | |
2551 begin-vec target) | |
2552 (save-excursion | |
2553 (while (> count 0) | |
2554 ;; Perform the normal backward-sexp, unless we are looking at | |
2555 ;; "else" - an "else" keyword corresponds to both the opening brace | |
2556 ;; of the following sexp and the closing brace of the previous sexp. | |
2557 (if (and (looking-at "else\\b\\([^_]\\|\\'\\)") | |
2558 (/= (preceding-char) ?_) | |
2559 (not (vhdl-in-literal lim))) | |
2560 nil | |
2561 (backward-sexp) | |
2562 (if (and (looking-at vhdl-begin-fwd-re) | |
2563 (/= (preceding-char) ?_) | |
2564 (not (vhdl-in-literal lim)) | |
2565 (vhdl-begin-p lim)) | |
2566 (error "Containing expression ends prematurely in vhdl-backward-sexp"))) | |
2567 ;; If the current keyword is an "end" keyword, then find the | |
2568 ;; corresponding "begin" keyword. | |
2569 (if (and (setq begin-vec (vhdl-corresponding-begin lim)) | |
2570 (/= (preceding-char) ?_)) | |
2571 (let ( | |
2572 ;; begin-re is the statement keyword to search for | |
2573 (begin-re | |
2574 (concat "\\b\\(" (aref begin-vec 0) "\\)\\b[^_]")) | |
2575 ;; column is either the statement keyword target column | |
2576 ;; or nil | |
2577 (column (aref begin-vec 1)) | |
2578 ;; internal-p controls where the statement keyword can | |
2579 ;; be found. | |
2580 (internal-p (aref begin-vec 3)) | |
2581 (last-backward (point)) last-forward | |
2582 foundp literal keyword) | |
2583 ;; Look for the statement keyword. | |
2584 (while (and (not foundp) | |
2585 (re-search-backward begin-re lim t) | |
2586 (setq keyword | |
2587 (buffer-substring (match-beginning 1) | |
2588 (match-end 1)))) | |
2589 ;; If we are in a literal or in the wrong column, | |
2590 ;; then try again. | |
2591 (if (or (and column | |
2592 (and (/= (current-indentation) column) | |
2593 ;; possibly accept current-column as | |
2594 ;; well as current-indentation. | |
2595 (or (not internal-p) | |
2596 (/= (current-column) column)))) | |
2597 (= (preceding-char) ?_) | |
2598 (vhdl-in-literal lim)) | |
2599 (backward-char) | |
2600 ;; If there is a supplementary keyword, then | |
2601 ;; search forward for it. | |
2602 (if (and (setq begin-re (aref begin-vec 2)) | |
2603 (or (not (listp begin-re)) | |
2604 ;; If begin-re is an alist, then find the | |
2605 ;; element corresponding to the actual | |
2606 ;; keyword that we found. | |
2607 (progn | |
2608 (setq begin-re | |
2609 (assoc keyword begin-re)) | |
2610 (and begin-re | |
2611 (setq begin-re (cdr begin-re)))))) | |
2612 (and | |
2613 (setq begin-re | |
2614 (concat "\\b\\(" begin-re "\\)\\b[^_]")) | |
2615 (save-excursion | |
2616 (setq last-forward (point)) | |
2617 ;; Look for the supplementary keyword | |
2618 ;; (bounded by the backward search start | |
2619 ;; point). | |
2620 (while (and (not foundp) | |
2621 (re-search-forward begin-re | |
2622 last-backward t) | |
2623 (goto-char (match-beginning 1))) | |
2624 ;; If we are in a literal, then try again. | |
2625 (if (or (= (preceding-char) ?_) | |
2626 (setq literal | |
2627 (vhdl-in-literal last-forward))) | |
2628 (if (eq literal 'comment) | |
2629 (goto-char | |
2630 (min (vhdl-point 'eol) last-backward)) | |
2631 (forward-char)) | |
2632 ;; We have found the supplementary keyword. | |
2633 ;; Save the position of the keyword in foundp. | |
2634 (setq foundp (point))) | |
2635 ) | |
2636 foundp) | |
2637 ;; If the supplementary keyword was found, then | |
2638 ;; move point to the supplementary keyword. | |
2639 (goto-char foundp)) | |
2640 ;; If there was no supplementary keyword, then | |
2641 ;; point is already at the statement keyword. | |
2642 (setq foundp t))) | |
2643 ) ; end of the search for the statement keyword | |
2644 (if (not foundp) | |
2645 (error "Unbalanced keywords in vhdl-backward-sexp")) | |
2646 )) | |
2647 (setq count (1- count)) | |
2648 ) | |
2649 (setq target (point))) | |
2650 (goto-char target) | |
2651 nil)) | |
2652 | |
2653 (defun vhdl-backward-up-list (&optional count limit) | |
2654 "Move backward out of one level of blocks. | |
2655 With argument, do this that many times." | |
2656 (interactive "p") | |
2657 (let ((count (or count 1)) | |
2658 target) | |
2659 (save-excursion | |
2660 (while (> count 0) | |
2661 (if (looking-at vhdl-defun-re) | |
2662 (error "Unbalanced blocks")) | |
2663 (vhdl-backward-to-block limit) | |
2664 (setq count (1- count))) | |
2665 (setq target (point))) | |
2666 (goto-char target))) | |
2667 | |
2668 (defun vhdl-end-of-defun (&optional count) | |
2669 "Move forward to the end of a VHDL defun." | |
2670 (interactive) | |
2671 (let ((case-fold-search t)) | |
2672 (vhdl-beginning-of-defun) | |
2673 (if (not (looking-at "block\\|process")) | |
2674 (re-search-forward "\\bis\\b")) | |
2675 (vhdl-forward-sexp))) | |
2676 | |
2677 (defun vhdl-mark-defun () | |
2678 "Put mark at end of this \"defun\", point at beginning." | |
2679 (interactive) | |
2680 (let ((case-fold-search t)) | |
2681 (push-mark) | |
2682 (vhdl-beginning-of-defun) | |
2683 (push-mark) | |
2684 (if (not (looking-at "block\\|process")) | |
2685 (re-search-forward "\\bis\\b")) | |
2686 (vhdl-forward-sexp) | |
2687 (exchange-point-and-mark))) | |
2688 | |
2689 (defun vhdl-beginning-of-libunit () | |
2690 "Move backward to the beginning of a VHDL library unit. | |
2691 Returns the location of the corresponding begin keyword, unless search | |
2692 stops due to beginning or end of buffer." | |
2693 ;; Note that if point is between the "libunit" keyword and the | |
2694 ;; corresponding "begin" keyword, then that libunit will not be | |
2695 ;; recognised, and the search will continue backwards. If point is | |
2696 ;; at the "begin" keyword, then the defun will be recognised. The | |
2697 ;; returned point is at the first character of the "libunit" keyword. | |
2698 (let ((last-forward (point)) | |
2699 (last-backward | |
2700 ;; Just in case we are actually sitting on the "begin" | |
2701 ;; keyword, allow for the keyword and an extra character, | |
2702 ;; as this will be used when looking forward for the | |
2703 ;; "begin" keyword. | |
2704 (save-excursion (forward-word 1) (1+ (point)))) | |
2705 foundp literal placeholder) | |
2706 ;; Find the "libunit" keyword. | |
2707 (while (and (not foundp) | |
2708 (re-search-backward vhdl-libunit-re nil 'move)) | |
2709 ;; If we are in a literal, or not at a real libunit, then try again. | |
2710 (if (or (= (preceding-char) ?_) | |
2711 (vhdl-in-literal (point-min)) | |
2712 (not (vhdl-libunit-p))) | |
2713 (backward-char) | |
2714 ;; Find the corresponding "begin" keyword. | |
2715 (setq last-forward (point)) | |
2716 (while (and (not foundp) | |
2717 (re-search-forward "\\bis\\b[^_]" last-backward t) | |
2718 (setq placeholder (match-beginning 0))) | |
2719 (if (or (= (preceding-char) ?_) | |
2720 (setq literal (vhdl-in-literal last-forward))) | |
2721 ;; It wasn't a real keyword, so keep searching. | |
2722 (if (eq literal 'comment) | |
2723 (goto-char | |
2724 (min (vhdl-point 'eol) last-backward)) | |
2725 (forward-char)) | |
2726 ;; We have found the begin keyword, loop will exit. | |
2727 (setq foundp placeholder))) | |
2728 ;; Go back to the libunit keyword | |
2729 (goto-char last-forward))) | |
2730 foundp)) | |
2731 | |
2732 (defun vhdl-beginning-of-defun (&optional count) | |
2733 "Move backward to the beginning of a VHDL defun. | |
2734 With argument, do it that many times. | |
2735 Returns the location of the corresponding begin keyword, unless search | |
2736 stops due to beginning or end of buffer." | |
2737 ;; Note that if point is between the "defun" keyword and the | |
2738 ;; corresponding "begin" keyword, then that defun will not be | |
2739 ;; recognised, and the search will continue backwards. If point is | |
2740 ;; at the "begin" keyword, then the defun will be recognised. The | |
2741 ;; returned point is at the first character of the "defun" keyword. | |
2742 (interactive "p") | |
2743 (let ((count (or count 1)) | |
2744 (case-fold-search t) | |
2745 (last-forward (point)) | |
2746 foundp) | |
2747 (while (> count 0) | |
2748 (setq foundp nil) | |
2749 (goto-char last-forward) | |
2750 (let ((last-backward | |
2751 ;; Just in case we are actually sitting on the "begin" | |
2752 ;; keyword, allow for the keyword and an extra character, | |
2753 ;; as this will be used when looking forward for the | |
2754 ;; "begin" keyword. | |
2755 (save-excursion (forward-word 1) (1+ (point)))) | |
2756 begin-string literal) | |
2757 (while (and (not foundp) | |
2758 (re-search-backward vhdl-defun-re nil 'move)) | |
2759 ;; If we are in a literal, then try again. | |
2760 (if (or (= (preceding-char) ?_) | |
2761 (vhdl-in-literal (point-min))) | |
2762 (backward-char) | |
2763 (if (setq begin-string (vhdl-corresponding-defun)) | |
2764 ;; This is a real defun keyword. | |
2765 ;; Find the corresponding "begin" keyword. | |
2766 ;; Look for the begin keyword. | |
2767 (progn | |
2768 ;; Save the search start point. | |
2769 (setq last-forward (point)) | |
2770 (while (and (not foundp) | |
2771 (search-forward begin-string last-backward t)) | |
2772 (if (or (= (preceding-char) ?_) | |
2773 (save-match-data | |
2774 (setq literal (vhdl-in-literal last-forward)))) | |
2775 ;; It wasn't a real keyword, so keep searching. | |
2776 (if (eq literal 'comment) | |
2777 (goto-char | |
2778 (min (vhdl-point 'eol) last-backward)) | |
2779 (forward-char)) | |
2780 ;; We have found the begin keyword, loop will exit. | |
2781 (setq foundp (match-beginning 0))) | |
2782 ) | |
2783 ;; Go back to the defun keyword | |
2784 (goto-char last-forward)) ; end search for begin keyword | |
2785 )) | |
2786 ) ; end of the search for the defun keyword | |
2787 ) | |
2788 (setq count (1- count)) | |
2789 ) | |
2790 (vhdl-keep-region-active) | |
2791 foundp)) | |
2792 | |
2793 (defun vhdl-beginning-of-statement (&optional count lim) | |
2794 "Go to the beginning of the innermost VHDL statement. | |
2795 With prefix arg, go back N - 1 statements. If already at the | |
2796 beginning of a statement then go to the beginning of the preceding | |
2797 one. If within a string or comment, or next to a comment (only | |
2798 whitespace between), move by sentences instead of statements. | |
2799 | |
2800 When called from a program, this function takes 2 optional args: the | |
2801 prefix arg, and a buffer position limit which is the farthest back to | |
2802 search." | |
2803 (interactive "p") | |
2804 (let ((count (or count 1)) | |
2805 (case-fold-search t) | |
2806 (lim (or lim (point-min))) | |
2807 (here (point)) | |
2808 state) | |
2809 (save-excursion | |
2810 (goto-char lim) | |
2811 (setq state (parse-partial-sexp (point) here nil nil))) | |
2812 (if (and (interactive-p) | |
2813 (or (nth 3 state) | |
2814 (nth 4 state) | |
2815 (looking-at (concat "[ \t]*" comment-start-skip)))) | |
2816 (forward-sentence (- count)) | |
2817 (while (> count 0) | |
2818 (vhdl-beginning-of-statement-1 lim) | |
2819 (setq count (1- count)))) | |
2820 ;; its possible we've been left up-buf of lim | |
2821 (goto-char (max (point) lim)) | |
2822 ) | |
2823 (vhdl-keep-region-active)) | |
2824 | |
2825 (defconst vhdl-e-o-s-re | |
2826 (concat ";\\|" vhdl-begin-fwd-re "\\|" vhdl-statement-fwd-re)) | |
2827 | |
2828 (defun vhdl-end-of-statement () | |
2829 "Very simple implementation." | |
2830 (interactive) | |
2831 (re-search-forward vhdl-e-o-s-re)) | |
2832 | |
2833 (defconst vhdl-b-o-s-re | |
2834 (concat ";\\|\(\\|\)\\|\\bwhen\\b[^_]\\|" | |
2835 vhdl-begin-bwd-re "\\|" vhdl-statement-bwd-re)) | |
2836 | |
2837 (defun vhdl-beginning-of-statement-1 (&optional lim) | |
2838 ;; move to the start of the current statement, or the previous | |
2839 ;; statement if already at the beginning of one. | |
2840 (let ((lim (or lim (point-min))) | |
2841 (here (point)) | |
2842 (pos (point)) | |
2843 donep) | |
2844 ;; go backwards one balanced expression, but be careful of | |
2845 ;; unbalanced paren being reached | |
2846 (if (not (vhdl-safe (progn (backward-sexp) t))) | |
2847 (progn | |
2848 (backward-up-list 1) | |
2849 (forward-char) | |
2850 (vhdl-forward-syntactic-ws here) | |
2851 (setq donep t))) | |
2852 (while (and (not donep) | |
2853 (not (bobp)) | |
2854 ;; look backwards for a statement boundary | |
2855 (re-search-backward vhdl-b-o-s-re lim 'move)) | |
2856 (if (or (= (preceding-char) ?_) | |
2857 (vhdl-in-literal lim)) | |
2858 (backward-char) | |
2859 (cond | |
2860 ;; If we are looking at an open paren, then stop after it | |
2861 ((eq (following-char) ?\() | |
2862 (forward-char) | |
2863 (vhdl-forward-syntactic-ws here) | |
2864 (setq donep t)) | |
2865 ;; If we are looking at a close paren, then skip it | |
2866 ((eq (following-char) ?\)) | |
2867 (forward-char) | |
2868 (setq pos (point)) | |
2869 (backward-sexp) | |
2870 (if (< (point) lim) | |
2871 (progn (goto-char pos) | |
2872 (vhdl-forward-syntactic-ws here) | |
2873 (setq donep t)))) | |
2874 ;; If we are looking at a semicolon, then stop | |
2875 ((eq (following-char) ?\;) | |
2876 (progn | |
2877 (forward-char) | |
2878 (vhdl-forward-syntactic-ws here) | |
2879 (setq donep t))) | |
2880 ;; If we are looking at a "begin", then stop | |
2881 ((and (looking-at vhdl-begin-fwd-re) | |
2882 (/= (preceding-char) ?_) | |
2883 (vhdl-begin-p nil)) | |
2884 ;; If it's a leader "begin", then find the | |
2885 ;; right place | |
2886 (if (looking-at vhdl-leader-re) | |
2887 (save-excursion | |
2888 ;; set a default stop point at the begin | |
2889 (setq pos (point)) | |
2890 ;; is the start point inside the leader area ? | |
2891 (goto-char (vhdl-end-of-leader)) | |
2892 (vhdl-forward-syntactic-ws here) | |
2893 (if (< (point) here) | |
2894 ;; start point was not inside leader area | |
2895 ;; set stop point at word after leader | |
2896 (setq pos (point)))) | |
2897 (forward-word 1) | |
2898 (vhdl-forward-syntactic-ws here) | |
2899 (setq pos (point))) | |
2900 (goto-char pos) | |
2901 (setq donep t)) | |
2902 ;; If we are looking at a "statement", then stop | |
2903 ((and (looking-at vhdl-statement-fwd-re) | |
2904 (/= (preceding-char) ?_) | |
2905 (vhdl-statement-p nil)) | |
2906 (setq donep t)) | |
2907 ;; If we are looking at a case alternative key, then stop | |
2908 ((and (looking-at vhdl-case-alternative-re) | |
2909 (vhdl-case-alternative-p lim)) | |
2910 (save-excursion | |
2911 ;; set a default stop point at the when | |
2912 (setq pos (point)) | |
2913 ;; is the start point inside the case alternative key ? | |
2914 (looking-at vhdl-case-alternative-re) | |
2915 (goto-char (match-end 0)) | |
2916 (vhdl-forward-syntactic-ws here) | |
2917 (if (< (point) here) | |
2918 ;; start point was not inside the case alternative key | |
2919 ;; set stop point at word after case alternative keyleader | |
2920 (setq pos (point)))) | |
2921 (goto-char pos) | |
2922 (setq donep t)) | |
2923 ;; Bogus find, continue | |
2924 (t | |
2925 (backward-char))))) | |
2926 )) | |
2927 | |
2928 ;; Defuns for calculating the current syntactic state: | |
2929 | |
2930 (defun vhdl-get-library-unit (bod placeholder) | |
2931 ;; If there is an enclosing library unit at bod, with it's \"begin\" | |
2932 ;; keyword at placeholder, then return the library unit type. | |
2933 (let ((here (vhdl-point 'bol))) | |
2934 (if (save-excursion | |
2935 (goto-char placeholder) | |
2936 (vhdl-safe (vhdl-forward-sexp 1 bod)) | |
2937 (<= here (point))) | |
2938 (save-excursion | |
2939 (goto-char bod) | |
2940 (cond | |
2941 ((looking-at "e") 'entity) | |
2942 ((looking-at "a") 'architecture) | |
2943 ((looking-at "c") 'configuration) | |
2944 ((looking-at "p") | |
2945 (save-excursion | |
2946 (goto-char bod) | |
2947 (forward-sexp) | |
2948 (vhdl-forward-syntactic-ws here) | |
2949 (if (looking-at "body\\b[^_]") | |
2950 'package-body 'package)))))) | |
2951 )) | |
2952 | |
2953 (defun vhdl-get-block-state (&optional lim) | |
2954 ;; Finds and records all the closest opens. | |
2955 ;; lim is the furthest back we need to search (it should be the | |
2956 ;; previous libunit keyword). | |
2957 (let ((here (point)) | |
2958 (lim (or lim (point-min))) | |
2959 keyword sexp-start sexp-mid sexp-end | |
2960 preceding-sexp containing-sexp | |
2961 containing-begin containing-mid containing-paren) | |
2962 (save-excursion | |
2963 ;; Find the containing-paren, and use that as the limit | |
2964 (if (setq containing-paren | |
2965 (save-restriction | |
2966 (narrow-to-region lim (point)) | |
2967 (vhdl-safe (scan-lists (point) -1 1)))) | |
2968 (setq lim containing-paren)) | |
2969 ;; Look backwards for "begin" and "end" keywords. | |
2970 (while (and (> (point) lim) | |
2971 (not containing-sexp)) | |
2972 (setq keyword (vhdl-backward-to-block lim)) | |
2973 (cond | |
2974 ((eq keyword 'begin) | |
2975 ;; Found a "begin" keyword | |
2976 (setq sexp-start (point)) | |
2977 (setq sexp-mid (vhdl-corresponding-mid lim)) | |
2978 (setq sexp-end (vhdl-safe | |
2979 (save-excursion | |
2980 (vhdl-forward-sexp 1 lim) (point)))) | |
2981 (if (and sexp-end (<= sexp-end here)) | |
2982 ;; we want to record this sexp, but we only want to | |
2983 ;; record the last-most of any of them before here | |
2984 (or preceding-sexp | |
2985 (setq preceding-sexp sexp-start)) | |
2986 ;; we're contained in this sexp so put sexp-start on | |
2987 ;; front of list | |
2988 (setq containing-sexp sexp-start) | |
2989 (setq containing-mid sexp-mid) | |
2990 (setq containing-begin t))) | |
2991 ((eq keyword 'end) | |
2992 ;; Found an "end" keyword | |
2993 (forward-sexp) | |
2994 (setq sexp-end (point)) | |
2995 (setq sexp-mid nil) | |
2996 (setq sexp-start | |
2997 (or (vhdl-safe (vhdl-backward-sexp 1 lim) (point)) | |
2998 (progn (backward-sexp) (point)))) | |
2999 ;; we want to record this sexp, but we only want to | |
3000 ;; record the last-most of any of them before here | |
3001 (or preceding-sexp | |
3002 (setq preceding-sexp sexp-start))) | |
3003 ))) | |
3004 ;; Check if the containing-paren should be the containing-sexp | |
3005 (if (and containing-paren | |
3006 (or (null containing-sexp) | |
3007 (< containing-sexp containing-paren))) | |
3008 (setq containing-sexp containing-paren | |
3009 preceding-sexp nil | |
3010 containing-begin nil | |
3011 containing-mid nil)) | |
3012 (vector containing-sexp preceding-sexp containing-begin containing-mid) | |
3013 )) | |
3014 | |
3015 | |
3016 (defconst vhdl-s-c-a-re | |
3017 (concat vhdl-case-alternative-re "\\|" vhdl-case-header-key)) | |
3018 | |
3019 (defun vhdl-skip-case-alternative (&optional lim) | |
3020 ;; skip forward over case/when bodies, with optional maximal | |
3021 ;; limit. if no next case alternative is found, nil is returned and point | |
3022 ;; is not moved | |
3023 (let ((lim (or lim (point-max))) | |
3024 (here (point)) | |
3025 donep foundp) | |
3026 (while (and (< (point) lim) | |
3027 (not donep)) | |
3028 (if (and (re-search-forward vhdl-s-c-a-re lim 'move) | |
3029 (save-match-data | |
3030 (not (vhdl-in-literal))) | |
3031 (/= (match-beginning 0) here)) | |
3032 (progn | |
3033 (goto-char (match-beginning 0)) | |
3034 (cond | |
3035 ((and (looking-at "case") | |
3036 (re-search-forward "\\bis[^_]" lim t)) | |
3037 (backward-sexp) | |
3038 (vhdl-forward-sexp)) | |
3039 (t | |
3040 (setq donep t | |
3041 foundp t)))))) | |
3042 (if (not foundp) | |
3043 (goto-char here)) | |
3044 foundp)) | |
3045 | |
3046 (defun vhdl-backward-skip-label (&optional lim) | |
3047 ;; skip backward over a label, with optional maximal | |
3048 ;; limit. if label is not found, nil is returned and point | |
3049 ;; is not moved | |
3050 (let ((lim (or lim (point-min))) | |
3051 placeholder) | |
3052 (if (save-excursion | |
3053 (vhdl-backward-syntactic-ws lim) | |
3054 (and (eq (preceding-char) ?:) | |
3055 (progn | |
3056 (backward-sexp) | |
3057 (setq placeholder (point)) | |
3058 (looking-at vhdl-label-key)))) | |
3059 (goto-char placeholder)) | |
3060 )) | |
3061 | |
3062 (defun vhdl-forward-skip-label (&optional lim) | |
3063 ;; skip forward over a label, with optional maximal | |
3064 ;; limit. if label is not found, nil is returned and point | |
3065 ;; is not moved | |
3066 (let ((lim (or lim (point-max)))) | |
3067 (if (looking-at vhdl-label-key) | |
3068 (progn | |
3069 (goto-char (match-end 0)) | |
3070 (vhdl-forward-syntactic-ws lim))) | |
3071 )) | |
3072 | |
3073 (defun vhdl-get-syntactic-context () | |
3074 ;; guess the syntactic description of the current line of VHDL code. | |
3075 (save-excursion | |
3076 (save-restriction | |
3077 (beginning-of-line) | |
3078 (let* ((indent-point (point)) | |
3079 (case-fold-search t) | |
3080 vec literal containing-sexp preceding-sexp | |
3081 containing-begin containing-mid containing-leader | |
3082 char-before-ip char-after-ip begin-after-ip end-after-ip | |
3083 placeholder lim library-unit | |
3084 ) | |
3085 | |
3086 ;; Reset the syntactic context | |
3087 (setq vhdl-syntactic-context nil) | |
3088 | |
3089 (save-excursion | |
3090 ;; Move to the start of the previous library unit, and | |
3091 ;; record the position of the "begin" keyword. | |
3092 (setq placeholder (vhdl-beginning-of-libunit)) | |
3093 ;; The position of the "libunit" keyword gives us a gross | |
3094 ;; limit point. | |
3095 (setq lim (point)) | |
3096 ) | |
3097 | |
3098 ;; If there is a previous library unit, and we are enclosed by | |
3099 ;; it, then set the syntax accordingly. | |
3100 (and placeholder | |
3101 (setq library-unit (vhdl-get-library-unit lim placeholder)) | |
3102 (vhdl-add-syntax library-unit lim)) | |
3103 | |
3104 ;; Find the surrounding state. | |
3105 (if (setq vec (vhdl-get-block-state lim)) | |
3106 (progn | |
3107 (setq containing-sexp (aref vec 0)) | |
3108 (setq preceding-sexp (aref vec 1)) | |
3109 (setq containing-begin (aref vec 2)) | |
3110 (setq containing-mid (aref vec 3)) | |
3111 )) | |
3112 | |
3113 ;; set the limit on the farthest back we need to search | |
3114 (setq lim (if containing-sexp | |
3115 (save-excursion | |
3116 (goto-char containing-sexp) | |
3117 ;; set containing-leader if required | |
3118 (if (looking-at vhdl-leader-re) | |
3119 (setq containing-leader (vhdl-end-of-leader))) | |
3120 (vhdl-point 'bol)) | |
3121 (point-min))) | |
3122 | |
3123 ;; cache char before and after indent point, and move point to | |
3124 ;; the most likely position to perform the majority of tests | |
3125 (goto-char indent-point) | |
3126 (skip-chars-forward " \t") | |
3127 (setq literal (vhdl-in-literal lim)) | |
3128 (setq char-after-ip (following-char)) | |
3129 (setq begin-after-ip (and | |
3130 (not literal) | |
3131 (looking-at vhdl-begin-fwd-re) | |
3132 (vhdl-begin-p))) | |
3133 (setq end-after-ip (and | |
3134 (not literal) | |
3135 (looking-at vhdl-end-fwd-re) | |
3136 (vhdl-end-p))) | |
3137 (vhdl-backward-syntactic-ws lim) | |
3138 (setq char-before-ip (preceding-char)) | |
3139 (goto-char indent-point) | |
3140 (skip-chars-forward " \t") | |
3141 | |
3142 ;; now figure out syntactic qualities of the current line | |
3143 (cond | |
3144 ;; CASE 1: in a string or comment. | |
3145 ((memq literal '(string comment)) | |
3146 (vhdl-add-syntax literal (vhdl-point 'bopl))) | |
3147 ;; CASE 2: Line is at top level. | |
3148 ((null containing-sexp) | |
3149 ;; Find the point to which indentation will be relative | |
3150 (save-excursion | |
3151 (if (null preceding-sexp) | |
3152 ;; CASE 2X.1 | |
3153 ;; no preceding-sexp -> use the preceding statement | |
3154 (vhdl-beginning-of-statement-1 lim) | |
3155 ;; CASE 2X.2 | |
3156 ;; if there is a preceding-sexp then indent relative to it | |
3157 (goto-char preceding-sexp) | |
3158 ;; if not at boi, then the block-opening keyword is | |
3159 ;; probably following a label, so we need a different | |
3160 ;; relpos | |
3161 (if (/= (point) (vhdl-point 'boi)) | |
3162 ;; CASE 2X.3 | |
3163 (vhdl-beginning-of-statement-1 lim))) | |
3164 ;; v-b-o-s could have left us at point-min | |
3165 (and (bobp) | |
3166 ;; CASE 2X.4 | |
3167 (vhdl-forward-syntactic-ws indent-point)) | |
3168 (setq placeholder (point))) | |
3169 (cond | |
3170 ;; CASE 2A : we are looking at a block-open | |
3171 (begin-after-ip | |
3172 (vhdl-add-syntax 'block-open placeholder)) | |
3173 ;; CASE 2B: we are looking at a block-close | |
3174 (end-after-ip | |
3175 (vhdl-add-syntax 'block-close placeholder)) | |
3176 ;; CASE 2C: we are looking at a top-level statement | |
3177 ((progn | |
3178 (vhdl-backward-syntactic-ws lim) | |
3179 (or (bobp) | |
3180 (= (preceding-char) ?\;))) | |
3181 (vhdl-add-syntax 'statement placeholder)) | |
3182 ;; CASE 2D: we are looking at a top-level statement-cont | |
3183 (t | |
3184 (vhdl-beginning-of-statement-1 lim) | |
3185 ;; v-b-o-s could have left us at point-min | |
3186 (and (bobp) | |
3187 ;; CASE 2D.1 | |
3188 (vhdl-forward-syntactic-ws indent-point)) | |
3189 (vhdl-add-syntax 'statement-cont (point))) | |
3190 )) ; end CASE 2 | |
3191 ;; CASE 3: line is inside parentheses. Most likely we are | |
3192 ;; either in a subprogram argument (interface) list, or a | |
3193 ;; continued expression containing parentheses. | |
3194 ((null containing-begin) | |
3195 (vhdl-backward-syntactic-ws containing-sexp) | |
3196 (cond | |
3197 ;; CASE 3A: we are looking at the arglist closing paren | |
3198 ((eq char-after-ip ?\)) | |
3199 (goto-char containing-sexp) | |
3200 (vhdl-add-syntax 'arglist-close (vhdl-point 'boi))) | |
3201 ;; CASE 3B: we are looking at the first argument in an empty | |
3202 ;; argument list. | |
3203 ((eq char-before-ip ?\() | |
3204 (goto-char containing-sexp) | |
3205 (vhdl-add-syntax 'arglist-intro (vhdl-point 'boi))) | |
3206 ;; CASE 3C: we are looking at an arglist continuation line, | |
3207 ;; but the preceding argument is on the same line as the | |
3208 ;; opening paren. This case includes multi-line | |
3209 ;; expression paren groupings. | |
3210 ((and (save-excursion | |
3211 (goto-char (1+ containing-sexp)) | |
3212 (skip-chars-forward " \t") | |
3213 (not (eolp)) | |
3214 (not (looking-at "--"))) | |
3215 (save-excursion | |
3216 (vhdl-beginning-of-statement-1 containing-sexp) | |
3217 (skip-chars-backward " \t(") | |
3218 (<= (point) containing-sexp))) | |
3219 (goto-char containing-sexp) | |
3220 (vhdl-add-syntax 'arglist-cont-nonempty (vhdl-point 'boi))) | |
3221 ;; CASE 3D: we are looking at just a normal arglist | |
3222 ;; continuation line | |
3223 (t (vhdl-beginning-of-statement-1 containing-sexp) | |
3224 (vhdl-forward-syntactic-ws indent-point) | |
3225 (vhdl-add-syntax 'arglist-cont (vhdl-point 'boi))) | |
3226 )) | |
3227 ;; CASE 4: A block mid open | |
3228 ((and begin-after-ip | |
3229 (looking-at containing-mid)) | |
3230 (goto-char containing-sexp) | |
3231 ;; If the \"begin\" keyword is a trailer, then find v-b-o-s | |
3232 (if (looking-at vhdl-trailer-re) | |
3233 ;; CASE 4.1 | |
3234 (progn (forward-sexp) (vhdl-beginning-of-statement-1 nil))) | |
3235 (vhdl-backward-skip-label (vhdl-point 'boi)) | |
3236 (vhdl-add-syntax 'block-open (point))) | |
3237 ;; CASE 5: block close brace | |
3238 (end-after-ip | |
3239 (goto-char containing-sexp) | |
3240 ;; If the \"begin\" keyword is a trailer, then find v-b-o-s | |
3241 (if (looking-at vhdl-trailer-re) | |
3242 ;; CASE 5.1 | |
3243 (progn (forward-sexp) (vhdl-beginning-of-statement-1 nil))) | |
3244 (vhdl-backward-skip-label (vhdl-point 'boi)) | |
3245 (vhdl-add-syntax 'block-close (point))) | |
3246 ;; CASE 6: A continued statement | |
3247 ((and (/= char-before-ip ?\;) | |
3248 ;; check it's not a trailer begin keyword, or a begin | |
3249 ;; keyword immediately following a label. | |
3250 (not (and begin-after-ip | |
3251 (or (looking-at vhdl-trailer-re) | |
3252 (save-excursion | |
3253 (vhdl-backward-skip-label containing-sexp))))) | |
3254 ;; check it's not a statement keyword | |
3255 (not (and (looking-at vhdl-statement-fwd-re) | |
3256 (vhdl-statement-p))) | |
3257 ;; see if the b-o-s is before the indent point | |
3258 (> indent-point | |
3259 (save-excursion | |
3260 (vhdl-beginning-of-statement-1 containing-sexp) | |
3261 ;; If we ended up after a leader, then this will | |
3262 ;; move us forward to the start of the first | |
3263 ;; statement. Note that a containing sexp here is | |
3264 ;; always a keyword, not a paren, so this will | |
3265 ;; have no effect if we hit the containing-sexp. | |
3266 (vhdl-forward-syntactic-ws indent-point) | |
3267 (setq placeholder (point)))) | |
3268 ;; check it's not a block-intro | |
3269 (/= placeholder containing-sexp) | |
3270 ;; check it's not a case block-intro | |
3271 (save-excursion | |
3272 (goto-char placeholder) | |
3273 (or (not (looking-at vhdl-case-alternative-re)) | |
3274 (> (match-end 0) indent-point)))) | |
3275 ;; Make placeholder skip a label, but only if it puts us | |
3276 ;; before the indent point at the start of a line. | |
3277 (let ((new placeholder)) | |
3278 (if (and (> indent-point | |
3279 (save-excursion | |
3280 (goto-char placeholder) | |
3281 (vhdl-forward-skip-label indent-point) | |
3282 (setq new (point)))) | |
3283 (save-excursion | |
3284 (goto-char new) | |
3285 (eq new (progn (back-to-indentation) (point))))) | |
3286 (setq placeholder new))) | |
3287 (vhdl-add-syntax 'statement-cont placeholder) | |
3288 (if begin-after-ip | |
3289 (vhdl-add-syntax 'block-open))) | |
3290 ;; Statement. But what kind? | |
3291 ;; CASE 7: A case alternative key | |
3292 ((and (looking-at vhdl-case-alternative-re) | |
3293 (vhdl-case-alternative-p containing-sexp)) | |
3294 ;; for a case alternative key, we set relpos to the first | |
3295 ;; non-whitespace char on the line containing the "case" | |
3296 ;; keyword. | |
3297 (goto-char containing-sexp) | |
3298 ;; If the \"begin\" keyword is a trailer, then find v-b-o-s | |
3299 (if (looking-at vhdl-trailer-re) | |
3300 (progn (forward-sexp) (vhdl-beginning-of-statement-1 nil))) | |
3301 (vhdl-add-syntax 'case-alternative (vhdl-point 'boi))) | |
3302 ;; CASE 8: statement catchall | |
3303 (t | |
3304 ;; we know its a statement, but we need to find out if it is | |
3305 ;; the first statement in a block | |
3306 (if containing-leader | |
3307 (goto-char containing-leader) | |
3308 (goto-char containing-sexp) | |
3309 ;; Note that a containing sexp here is always a keyword, | |
3310 ;; not a paren, so skip over the keyword. | |
3311 (forward-sexp)) | |
3312 ;; move to the start of the first statement | |
3313 (vhdl-forward-syntactic-ws indent-point) | |
3314 (setq placeholder (point)) | |
3315 ;; we want to ignore case alternatives keys when skipping forward | |
3316 (let (incase-p) | |
3317 (while (looking-at vhdl-case-alternative-re) | |
3318 (setq incase-p (point)) | |
3319 ;; we also want to skip over the body of the | |
3320 ;; case/when statement if that doesn't put us at | |
3321 ;; after the indent-point | |
3322 (while (vhdl-skip-case-alternative indent-point)) | |
3323 ;; set up the match end | |
3324 (looking-at vhdl-case-alternative-re) | |
3325 (goto-char (match-end 0)) | |
3326 ;; move to the start of the first case alternative statement | |
3327 (vhdl-forward-syntactic-ws indent-point) | |
3328 (setq placeholder (point))) | |
3329 (cond | |
3330 ;; CASE 8A: we saw a case/when statement so we must be | |
3331 ;; in a switch statement. find out if we are at the | |
3332 ;; statement just after a case alternative key | |
3333 ((and incase-p | |
3334 (= (point) indent-point)) | |
3335 ;; relpos is the "when" keyword | |
3336 (vhdl-add-syntax 'statement-case-intro incase-p)) | |
3337 ;; CASE 8B: any old statement | |
3338 ((< (point) indent-point) | |
3339 ;; relpos is the first statement of the block | |
3340 (vhdl-add-syntax 'statement placeholder) | |
3341 (if begin-after-ip | |
3342 (vhdl-add-syntax 'block-open))) | |
3343 ;; CASE 8C: first statement in a block | |
3344 (t | |
3345 (goto-char containing-sexp) | |
3346 ;; If the \"begin\" keyword is a trailer, then find v-b-o-s | |
3347 (if (looking-at vhdl-trailer-re) | |
3348 (progn (forward-sexp) (vhdl-beginning-of-statement-1 nil))) | |
3349 (vhdl-backward-skip-label (vhdl-point 'boi)) | |
3350 (vhdl-add-syntax 'statement-block-intro (point)) | |
3351 (if begin-after-ip | |
3352 (vhdl-add-syntax 'block-open))) | |
3353 ))) | |
3354 ) | |
3355 | |
3356 ;; now we need to look at any modifiers | |
3357 (goto-char indent-point) | |
3358 (skip-chars-forward " \t") | |
3359 (if (looking-at "--") | |
3360 (vhdl-add-syntax 'comment)) | |
3361 ;; return the syntax | |
3362 vhdl-syntactic-context)))) | |
3363 | |
3364 ;; Standard indentation line-ups: | |
3365 | |
3366 (defun vhdl-lineup-arglist (langelem) | |
3367 ;; lineup the current arglist line with the arglist appearing just | |
3368 ;; after the containing paren which starts the arglist. | |
3369 (save-excursion | |
3370 (let* ((containing-sexp | |
3371 (save-excursion | |
3372 ;; arglist-cont-nonempty gives relpos == | |
3373 ;; to boi of containing-sexp paren. This | |
3374 ;; is good when offset is +, but bad | |
3375 ;; when it is vhdl-lineup-arglist, so we | |
3376 ;; have to special case a kludge here. | |
3377 (if (memq (car langelem) '(arglist-intro arglist-cont-nonempty)) | |
3378 (progn | |
3379 (beginning-of-line) | |
3380 (backward-up-list 1) | |
3381 (skip-chars-forward " \t" (vhdl-point 'eol))) | |
3382 (goto-char (cdr langelem))) | |
3383 (point))) | |
3384 (cs-curcol (save-excursion | |
3385 (goto-char (cdr langelem)) | |
3386 (current-column)))) | |
3387 (if (save-excursion | |
3388 (beginning-of-line) | |
3389 (looking-at "[ \t]*)")) | |
3390 (progn (goto-char (match-end 0)) | |
3391 (backward-sexp) | |
3392 (forward-char) | |
3393 (vhdl-forward-syntactic-ws) | |
3394 (- (current-column) cs-curcol)) | |
3395 (goto-char containing-sexp) | |
3396 (or (eolp) | |
3397 (let ((eol (vhdl-point 'eol)) | |
3398 (here (progn | |
3399 (forward-char) | |
3400 (skip-chars-forward " \t") | |
3401 (point)))) | |
3402 (vhdl-forward-syntactic-ws) | |
3403 (if (< (point) eol) | |
3404 (goto-char here)))) | |
3405 (- (current-column) cs-curcol) | |
3406 )))) | |
3407 | |
3408 (defun vhdl-lineup-arglist-intro (langelem) | |
3409 ;; lineup an arglist-intro line to just after the open paren | |
3410 (save-excursion | |
3411 (let ((cs-curcol (save-excursion | |
3412 (goto-char (cdr langelem)) | |
3413 (current-column))) | |
3414 (ce-curcol (save-excursion | |
3415 (beginning-of-line) | |
3416 (backward-up-list 1) | |
3417 (skip-chars-forward " \t" (vhdl-point 'eol)) | |
3418 (current-column)))) | |
3419 (- ce-curcol cs-curcol -1)))) | |
3420 | |
3421 (defun vhdl-lineup-comment (langelem) | |
3422 ;; support old behavior for comment indentation. we look at | |
3423 ;; vhdl-comment-only-line-offset to decide how to indent comment | |
3424 ;; only-lines | |
3425 (save-excursion | |
3426 (back-to-indentation) | |
3427 ;; at or to the right of comment-column | |
3428 (if (>= (current-column) comment-column) | |
3429 (vhdl-comment-indent) | |
3430 ;; otherwise, indent as specified by vhdl-comment-only-line-offset | |
3431 (if (not (bolp)) | |
3432 (or (car-safe vhdl-comment-only-line-offset) | |
3433 vhdl-comment-only-line-offset) | |
3434 (or (cdr-safe vhdl-comment-only-line-offset) | |
3435 (car-safe vhdl-comment-only-line-offset) | |
3436 -1000 ;jam it against the left side | |
3437 ))))) | |
3438 | |
3439 (defun vhdl-lineup-statement-cont (langelem) | |
3440 ;; line up statement-cont after the assignment operator | |
3441 (save-excursion | |
3442 (let* ((relpos (cdr langelem)) | |
3443 (assignp (save-excursion | |
3444 (goto-char (vhdl-point 'boi)) | |
3445 (and (re-search-forward "\\(<\\|:\\)=" | |
3446 (vhdl-point 'eol) t) | |
3447 (- (point) (vhdl-point 'boi))))) | |
3448 (curcol (progn | |
3449 (goto-char relpos) | |
3450 (current-column))) | |
3451 foundp) | |
3452 (while (and (not foundp) | |
3453 (< (point) (vhdl-point 'eol))) | |
3454 (re-search-forward "\\(<\\|:\\)=\\|(" (vhdl-point 'eol) 'move) | |
3455 (if (vhdl-in-literal (cdr langelem)) | |
3456 (forward-char) | |
3457 (if (= (preceding-char) ?\() | |
3458 ;; skip over any parenthesized expressions | |
3459 (goto-char (min (vhdl-point 'eol) | |
3460 (scan-lists (point) 1 1))) | |
3461 ;; found an assignment operator (not at eol) | |
3462 (setq foundp (not (looking-at "\\s-*$")))))) | |
3463 (if (not foundp) | |
3464 ;; there's no assignment operator on the line | |
3465 vhdl-basic-offset | |
3466 ;; calculate indentation column after assign and ws, unless | |
3467 ;; our line contains an assignment operator | |
3468 (if (not assignp) | |
3469 (progn | |
3470 (forward-char) | |
3471 (skip-chars-forward " \t") | |
3472 (setq assignp 0))) | |
3473 (- (current-column) assignp curcol)) | |
3474 ))) | |
3475 | |
3476 ;; ############################################################################ | |
3477 ;; Indentation commands | |
3478 | |
3479 (defun vhdl-tab (&optional pre-arg) | |
3480 "If preceeding character is part of a word then dabbrev-expand, | |
3481 else if right of non whitespace on line then tab-to-tab-stop, | |
3482 else if last command was a tab or return then dedent one step, | |
3483 else indent `correctly'." | |
3484 (interactive "*P") | |
3485 (cond ((= (char-syntax (preceding-char)) ?w) | |
3486 (let ((case-fold-search nil)) (dabbrev-expand pre-arg))) | |
3487 ((> (current-column) (current-indentation)) | |
3488 (tab-to-tab-stop)) | |
3489 ((and (or (eq last-command 'vhdl-tab) | |
3490 (eq last-command 'vhdl-return)) | |
3491 (/= 0 (current-indentation))) | |
3492 (backward-delete-char-untabify vhdl-basic-offset nil)) | |
3493 ((vhdl-indent-line)) | |
3494 ) | |
3495 (setq this-command 'vhdl-tab) | |
3496 ) | |
3497 | |
3498 (defun vhdl-untab () | |
3499 "Delete backwards to previous tab stop." | |
3500 (interactive) | |
3501 (backward-delete-char-untabify vhdl-basic-offset nil) | |
3502 ) | |
3503 | |
3504 (defun vhdl-return () | |
3505 "newline-and-indent or indent-new-comment-line if in comment and preceding | |
3506 character is a space." | |
3507 (interactive) | |
3508 (if (and (= (preceding-char) ? ) (vhdl-in-comment-p)) | |
3509 (indent-new-comment-line) | |
3510 (newline-and-indent) | |
3511 ) | |
3512 ) | |
3513 | |
3514 (defun vhdl-indent-line () | |
3515 "Indent the current line as VHDL code. Returns the amount of | |
3516 indentation change." | |
3517 (interactive) | |
3518 (let* ((syntax (vhdl-get-syntactic-context)) | |
3519 (pos (- (point-max) (point))) | |
3520 (indent (apply '+ (mapcar 'vhdl-get-offset syntax))) | |
3521 (shift-amt (- (current-indentation) indent))) | |
3522 (and vhdl-echo-syntactic-information-p | |
3523 (message "syntax: %s, indent= %d" syntax indent)) | |
3524 (if (zerop shift-amt) | |
3525 nil | |
3526 (delete-region (vhdl-point 'bol) (vhdl-point 'boi)) | |
3527 (beginning-of-line) | |
3528 (indent-to indent)) | |
3529 (if (< (point) (vhdl-point 'boi)) | |
3530 (back-to-indentation) | |
3531 ;; If initial point was within line's indentation, position after | |
3532 ;; the indentation. Else stay at same point in text. | |
3533 (if (> (- (point-max) pos) (point)) | |
3534 (goto-char (- (point-max) pos))) | |
3535 ) | |
3536 (run-hooks 'vhdl-special-indent-hook) | |
3537 shift-amt)) | |
3538 | |
3539 (defun vhdl-indent-buffer () | |
3540 "Indent whole buffer as VHDL code." | |
3541 (interactive) | |
3542 (indent-region (point-min) (point-max) nil) | |
3543 ) | |
3544 | |
3545 (defun vhdl-indent-sexp (&optional endpos) | |
3546 "Indent each line of the list starting just after point. | |
3547 If optional arg ENDPOS is given, indent each line, stopping when | |
3548 ENDPOS is encountered." | |
3549 (interactive) | |
3550 (save-excursion | |
3551 (let ((beg (point)) | |
3552 (end (progn | |
3553 (vhdl-forward-sexp nil endpos) | |
3554 (point)))) | |
3555 (indent-region beg end nil)))) | |
3556 | |
3557 ;; ############################################################################ | |
3558 ;; Miscellaneous commands | |
3559 | |
3560 (defun vhdl-show-syntactic-information () | |
3561 "Show syntactic information for current line." | |
3562 (interactive) | |
3563 (message "syntactic analysis: %s" (vhdl-get-syntactic-context)) | |
3564 (vhdl-keep-region-active)) | |
3565 | |
3566 ;; Verification and regression functions: | |
3567 | |
3568 (defun vhdl-regress-line (&optional arg) | |
3569 "Check syntactic information for current line." | |
3570 (interactive "P") | |
3571 (let ((expected (save-excursion | |
3572 (end-of-line) | |
3573 (if (search-backward " -- ((" (vhdl-point 'bol) t) | |
3574 (progn | |
3575 (forward-char 4) | |
3576 (read (current-buffer)))))) | |
3577 (actual (vhdl-get-syntactic-context)) | |
3578 (expurgated)) | |
3579 ;; remove the library unit symbols | |
3580 (mapcar | |
3581 (function | |
3582 (lambda (elt) | |
3583 (if (memq (car elt) '(entity configuration package | |
3584 package-body architecture)) | |
3585 nil | |
3586 (setq expurgated (append expurgated (list elt)))))) | |
3587 actual) | |
3588 (if (and (not arg) expected (listp expected)) | |
3589 (if (not (equal expected expurgated)) | |
3590 (error "Should be: %s, is: %s" expected expurgated)) | |
3591 (save-excursion | |
3592 (beginning-of-line) | |
3593 (if (not (looking-at "^\\s-*\\(--.*\\)?$")) | |
3594 (progn | |
3595 (end-of-line) | |
3596 (if (search-backward " -- ((" (vhdl-point 'bol) t) | |
3597 (kill-line)) | |
3598 (insert " -- ") | |
3599 (insert (format "%s" expurgated))))))) | |
3600 (vhdl-keep-region-active)) | |
3601 | |
3602 | |
3603 ;; ############################################################################ | |
3604 ;; Alignment | |
3605 ;; ############################################################################ | |
3606 | |
3607 (defvar vhdl-align-alist | |
3608 '( | |
3609 ;; after some keywords | |
3610 (vhdl-mode "\\<\\(alias\\|constant\\|signal\\|subtype\\|type\\|variable\\)[ \t]" | |
3611 "\\<\\(alias\\|constant\\|signal\\|subtype\\|type\\|variable\\)\\([ \t]+\\)" 2) | |
3612 ;; before ':' | |
3613 (vhdl-mode ":[^=]" "[^ \t]\\([ \t]*\\):[^=]") | |
3614 ;; after ':' | |
3615 (vhdl-mode ":[^=]" ":\\([ \t]*\\)[^=]" 1) | |
3616 ;; after direction specifications | |
3617 (vhdl-mode ":[ \t]*\\(in\\|out\\|inout\\|buffer\\)\\>" | |
3618 ":[ \t]*\\(in\\|out\\|inout\\|buffer\\)\\([ \t]+\\)" 2) | |
3619 ;; before "<=", "=>", and ":=" | |
3620 (vhdl-mode "<=" "[^ \t]\\([ \t]*\\)<=" 1) | |
3621 (vhdl-mode "=>" "[^ \t]\\([ \t]*\\)=>" 1) | |
3622 (vhdl-mode ":=" "[^ \t]\\([ \t]*\\):=" 1) | |
3623 ;; after "<=", "=>", and ":=" | |
3624 (vhdl-mode "<=" "<=\\([ \t]*\\)" 1) | |
3625 (vhdl-mode "=>" "=>\\([ \t]*\\)" 1) | |
3626 (vhdl-mode ":=" ":=\\([ \t]*\\)" 1) | |
3627 ;; before some keywords | |
3628 (vhdl-mode "[ \t]after\\>" "[^ \t]\\([ \t]+\\)after\\>" 1) | |
3629 (vhdl-mode "[ \t]\\(fs\\|ps\\|ns\\|us\\|ms\\|sec\\|min\\|hr\\)\\>" | |
3630 "[^ \t]\\([ \t]+\\)\\(fs\\|ps\\|ns\\|us\\|ms\\|sec\\|min\\|hr\\)\\>" 1) | |
3631 (vhdl-mode "[ \t]when\\>" "[^ \t]\\([ \t]+\\)when\\>" 1) | |
3632 (vhdl-mode "[ \t]else\\>" "[^ \t]\\([ \t]+\\)else\\>" 1) | |
3633 (vhdl-mode "[ \t]is\\>" "[^ \t]\\([ \t]+\\)is\\>" 1) | |
3634 (vhdl-mode "[ \t]of\\>" "[^ \t]\\([ \t]+\\)of\\>" 1) | |
3635 (vhdl-mode "[ \t]use\\>" "[^ \t]\\([ \t]+\\)use\\>" 1) | |
3636 ;; before comments (two steps required for correct insertion of two spaces) | |
3637 (vhdl-mode "--" "[^ \t]\\([ \t]*\\)--" 1) | |
3638 (vhdl-mode "--" "[^ \t][ \t]\\([ \t]*\\)--" 1) | |
3639 ) | |
3640 "The format of this alist is | |
3641 (MODES [or MODE] REGEXP ALIGN-PATTERN SUBEXP). | |
3642 It is searched in order. If REGEXP is found anywhere in the first | |
3643 line of a region to be aligned, ALIGN-PATTERN will be used for that | |
3644 region. ALIGN-PATTERN must include the whitespace to be expanded or | |
3645 contracted. It may also provide regexps for the text surrounding the | |
3646 whitespace. SUBEXP specifies which sub-expression of | |
3647 ALIGN-PATTERN matches the white space to be expanded/contracted.") | |
3648 | |
3649 (defvar vhdl-align-try-all-clauses t | |
3650 "If REGEXP is not found on the first line of the region that clause | |
3651 is ignored. If this variable is non-nil, then the clause is tried anyway.") | |
3652 | |
3653 (defun vhdl-align (begin end spacing &optional alignment-list quick) | |
3654 "Attempt to align a range of lines based on the content of the | |
3655 lines. The definition of 'alignment-list' determines the matching | |
3656 order and the manner in which the lines are aligned. If ALIGNMENT-LIST | |
3657 is not specified 'vhdl-align-alist' is used. If QUICK is non-nil, no | |
3658 indentation is done before aligning." | |
3659 (interactive "r\np") | |
3660 (if (not alignment-list) | |
3661 (setq alignment-list vhdl-align-alist)) | |
3662 (if (not spacing) | |
3663 (setq spacing 1)) | |
3664 (save-excursion | |
3665 (let (bol indent) | |
3666 (goto-char end) | |
3667 (setq end (point-marker)) | |
3668 (goto-char begin) | |
3669 (setq bol | |
3670 (setq begin (progn (beginning-of-line) (point)))) | |
3671 (untabify bol end) | |
3672 (if quick | |
3673 nil | |
3674 (indent-region bol end nil)))) | |
3675 (let ((copy (copy-alist alignment-list))) | |
3676 (while copy | |
3677 (save-excursion | |
3678 (goto-char begin) | |
3679 (let (element | |
3680 (eol (save-excursion (progn (end-of-line) (point))))) | |
3681 (setq element (nth 0 copy)) | |
3682 (if (and (or (and (listp (car element)) | |
3683 (memq major-mode (car element))) | |
3684 (eq major-mode (car element))) | |
3685 (or vhdl-align-try-all-clauses | |
3686 (re-search-forward (car (cdr element)) eol t))) | |
3687 (progn | |
3688 (vhdl-align-region begin end (car (cdr (cdr element))) | |
3689 (car (cdr (cdr (cdr element)))) spacing))) | |
3690 (setq copy (cdr copy))))))) | |
3691 | |
3692 (defun vhdl-align-region (begin end match &optional substr spacing) | |
3693 "Align a range of lines from BEGIN to END. The regular expression | |
3694 MATCH must match exactly one fields: the whitespace to be | |
3695 contracted/expanded. The alignment column will equal the | |
3696 rightmost column of the widest whitespace block. SPACING is | |
3697 the amount of extra spaces to add to the calculated maximum required. | |
3698 SPACING defaults to 1 so that at least one space is inserted after | |
3699 the token in MATCH." | |
3700 (if (not spacing) | |
3701 (setq spacing 1)) | |
3702 (if (not substr) | |
3703 (setq substr 1)) | |
3704 (save-excursion | |
3705 (let (distance (max 0) (lines 0) bol eol width) | |
3706 ;; Determine the greatest whitespace distance to the alignment | |
3707 ;; character | |
3708 (goto-char begin) | |
3709 (setq eol (progn (end-of-line) (point)) | |
3710 bol (setq begin (progn (beginning-of-line) (point)))) | |
3711 (while (< bol end) | |
3712 (save-excursion | |
3713 (if (re-search-forward match eol t) | |
3714 (progn | |
3715 (setq distance (- (match-beginning substr) bol)) | |
3716 (if (> distance max) | |
3717 (setq max distance))))) | |
3718 (forward-line) | |
3719 (setq bol (point) | |
3720 eol (save-excursion | |
3721 (end-of-line) | |
3722 (point))) | |
3723 (setq lines (1+ lines))) | |
3724 ;; Now insert enough maxs to push each assignment operator to | |
3725 ;; the same column. We need to use 'lines' as a counter, since | |
3726 ;; the location of the mark may change | |
3727 (goto-char (setq bol begin)) | |
3728 (setq eol (save-excursion | |
3729 (end-of-line) | |
3730 (point))) | |
3731 (while (> lines 0) | |
3732 (if (re-search-forward match eol t) | |
3733 (progn | |
3734 (setq width (- (match-end substr) (match-beginning substr))) | |
3735 (setq distance (- (match-beginning substr) bol)) | |
3736 (goto-char (match-beginning substr)) | |
3737 (delete-char width) | |
3738 (insert-char ? (+ (- max distance) spacing)))) | |
3739 (beginning-of-line) | |
3740 (forward-line) | |
3741 (setq bol (point) | |
3742 eol (save-excursion | |
3743 (end-of-line) | |
3744 (point))) | |
3745 (setq lines (1- lines)) | |
3746 )))) | |
3747 | |
3748 (defun vhdl-align-comment-region (begin end spacing) | |
3749 "Aligns inline comments within a region relative to first comment." | |
3750 (interactive "r\nP") | |
3751 (vhdl-align begin end (or spacing 2) | |
3752 `((vhdl-mode "--" "[^ \t]\\([ \t]*\\)--" 1)) t)) | |
3753 | |
3754 (defun vhdl-align-noindent-region (begin end spacing) | |
3755 "Align without indentation." | |
3756 (interactive "r\nP") | |
3757 (vhdl-align begin end spacing nil t) | |
3758 ) | |
3759 | |
3760 | |
3761 ;; ############################################################################ | |
3762 ;; VHDL electrification | |
3763 ;; ############################################################################ | |
3764 | |
3765 ;; ############################################################################ | |
3766 ;; Stuttering | |
3767 | |
3768 (defun vhdl-stutter-mode-caps (count) | |
3769 "Double first letters of a word replaced by a single capital of the letter." | |
3770 (interactive "p") | |
3771 (if vhdl-stutter-mode | |
3772 (if (and | |
3773 (= (preceding-char) last-input-char) ; doubled | |
3774 (or (= (point) 2) ; beginning of buffer | |
3775 (/= (char-syntax (char-after (- (point) 2))) ?w) ;not mid-word | |
3776 (< (char-after (- (point) 2)) ?A))) ;alfa-numeric | |
3777 (progn (delete-char -1) (insert-char (- last-input-char 32) count)) | |
3778 (self-insert-command count)) | |
3779 (self-insert-command count) | |
3780 )) | |
3781 | |
3782 (defun vhdl-stutter-mode-close-bracket (count) " ']' --> ')', ')]' --> ']'" | |
3783 (interactive "p") | |
3784 (if (and vhdl-stutter-mode (= count 1)) | |
3785 (progn | |
3786 (if (= (preceding-char) 41) ; close-paren | |
3787 (progn (delete-char -1) (insert-char 93 1)) ; close-bracket | |
3788 (insert-char 41 1) ; close-paren | |
3789 ) | |
3790 (blink-matching-open)) | |
3791 (self-insert-command count) | |
3792 )) | |
3793 | |
3794 (defun vhdl-stutter-mode-semicolon (count) " ';;' --> ' : ', ': ;' --> ' := '" | |
3795 (interactive "p") | |
3796 (if (and vhdl-stutter-mode (= count 1)) | |
3797 (progn | |
3798 (cond ((= (preceding-char) last-input-char) | |
3799 (progn (delete-char -1) | |
3800 (if (not (eq (preceding-char) ? )) (insert " ")) | |
3801 (insert ": "))) | |
3802 ((and | |
3803 (eq last-command 'vhdl-stutter-mode-colon) (= (preceding-char) ? )) | |
3804 (progn (delete-char -1) (insert "= "))) | |
3805 (t | |
3806 (insert-char 59 1)) ; semi-colon | |
3807 ) | |
3808 (setq this-command 'vhdl-stutter-mode-colon)) | |
3809 (self-insert-command count) | |
3810 )) | |
3811 | |
3812 (defun vhdl-stutter-mode-open-bracket (count) " '[' --> '(', '([' --> '['" | |
3813 (interactive "p") | |
3814 (if (and vhdl-stutter-mode (= count 1)) | |
3815 (if (= (preceding-char) 40) ; open-paren | |
3816 (progn (delete-char -1) (insert-char 91 1)) ; open-bracket | |
3817 (insert-char 40 1)) ; open-paren | |
3818 (self-insert-command count) | |
3819 )) | |
3820 | |
3821 (defun vhdl-stutter-mode-quote (count) " '' --> \"" | |
3822 (interactive "p") | |
3823 (if (and vhdl-stutter-mode (= count 1)) | |
3824 (if (= (preceding-char) last-input-char) | |
3825 (progn (delete-backward-char 1) (insert-char 34 1)) ; double-quote | |
3826 (insert-char 39 1)) ; single-quote | |
3827 (self-insert-command count) | |
3828 )) | |
3829 | |
3830 (defun vhdl-stutter-mode-comma (count) " ',,' --> ' <= '" | |
3831 (interactive "p") | |
3832 (if (and vhdl-stutter-mode (= count 1)) | |
3833 (cond ((= (preceding-char) last-input-char) | |
3834 (progn (delete-char -1) | |
3835 (if (not (eq (preceding-char) ? )) (insert " ")) | |
3836 (insert "<= "))) | |
3837 (t | |
3838 (insert-char 44 1))) ; comma | |
3839 (self-insert-command count) | |
3840 )) | |
3841 | |
3842 (defun vhdl-stutter-mode-period (count) " '..' --> ' => '" | |
3843 (interactive "p") | |
3844 (if (and vhdl-stutter-mode (= count 1)) | |
3845 (cond ((= (preceding-char) last-input-char) | |
3846 (progn (delete-char -1) | |
3847 (if (not (eq (preceding-char) ? )) (insert " ")) | |
3848 (insert "=> "))) | |
3849 (t | |
3850 (insert-char 46 1))) ; period | |
3851 (self-insert-command count) | |
3852 )) | |
3853 | |
3854 (defun vhdl-paired-parens () | |
3855 "Insert a pair of round parentheses, placing point between them." | |
3856 (interactive) | |
3857 (insert "()") | |
3858 (backward-char) | |
3859 ) | |
3860 | |
3861 (defun vhdl-stutter-mode-dash (count) | |
3862 "-- starts a comment, --- draws a horizontal line, | |
3863 ---- starts a display comment" | |
3864 (interactive "p") | |
3865 (if vhdl-stutter-mode | |
3866 (cond ((and abbrev-start-location (= abbrev-start-location (point))) | |
3867 (setq abbrev-start-location nil) | |
3868 (goto-char last-abbrev-location) | |
3869 (beginning-of-line nil) | |
3870 (vhdl-display-comment)) | |
3871 ((/= (preceding-char) ?-) ; standard dash (minus) | |
3872 (self-insert-command count)) | |
3873 (t | |
3874 (self-insert-command count) | |
3875 (message "Enter - for horiz. line, CR for commenting-out code, else 1st char of comment") | |
3876 (let ((next-input (read-char))) | |
3877 (if (= next-input ?-) ; triple dash | |
3878 (progn | |
3879 (vhdl-display-comment-line) | |
3880 (message | |
3881 "Enter - for display comment, else continue with coding") | |
3882 (let ((next-input (read-char))) | |
3883 (if (= next-input ?-) ; four dashes | |
3884 (vhdl-display-comment t) | |
3885 (setq unread-command-events ;pushback the char | |
3886 (list | |
3887 (vhdl-character-to-event-hack next-input))) | |
3888 ))) | |
3889 (setq unread-command-events ;pushback the char | |
3890 (list (vhdl-character-to-event-hack next-input))) | |
3891 (vhdl-inline-comment) | |
3892 )))) | |
3893 (self-insert-command count) | |
3894 )) | |
3895 | |
3896 ;; ############################################################################ | |
3897 ;; VHDL templates | |
3898 | |
3899 (defun vhdl-alias () | |
3900 "Insert alias declaration." | |
3901 (interactive) | |
3902 (vhdl-insert-keyword "ALIAS ") | |
3903 (if (equal (vhdl-field "name") "") | |
3904 nil | |
3905 (insert " : ") | |
3906 (vhdl-field "type") | |
3907 (vhdl-insert-keyword " IS ") | |
3908 (vhdl-field "name" ";") | |
3909 (vhdl-declaration-comment) | |
3910 )) | |
3911 | |
3912 (defun vhdl-architecture () | |
3913 "Insert architecture template." | |
3914 (interactive) | |
3915 (let ((margin (current-column)) | |
3916 (vhdl-architecture-name) | |
3917 (position) | |
3918 (entity-exists) | |
3919 (string) | |
3920 (case-fold-search t)) | |
3921 (vhdl-insert-keyword "ARCHITECTURE ") | |
3922 (if (equal (setq vhdl-architecture-name (vhdl-field "name")) "") | |
3923 nil | |
3924 (vhdl-insert-keyword " OF ") | |
3925 (setq position (point)) | |
3926 (setq entity-exists | |
3927 (re-search-backward "entity \\(\\(\\w\\|\\s_\\)+\\) is" nil t)) | |
3928 (setq string (match-string 1)) | |
3929 (goto-char position) | |
3930 (if (and entity-exists (not (equal string ""))) | |
3931 (insert string) | |
3932 (vhdl-field "entity name")) | |
3933 (vhdl-insert-keyword " IS") | |
3934 (vhdl-begin-end (cons vhdl-architecture-name margin)) | |
3935 (vhdl-block-comment) | |
3936 ))) | |
3937 | |
3938 | |
3939 (defun vhdl-array () | |
3940 "Insert array type definition." | |
3941 (interactive) | |
3942 (vhdl-insert-keyword "ARRAY (") | |
3943 (if (equal (vhdl-field "range") "") | |
3944 (delete-char -1) | |
3945 (vhdl-insert-keyword ") OF ") | |
3946 (vhdl-field "type") | |
3947 (vhdl-insert-keyword ";") | |
3948 )) | |
3949 | |
3950 (defun vhdl-assert () | |
3951 "Inserts a assertion statement." | |
3952 (interactive) | |
3953 (vhdl-insert-keyword "ASSERT ") | |
3954 (if vhdl-conditions-in-parenthesis (insert "(")) | |
3955 (if (equal (vhdl-field "condition (negated)") "") | |
3956 (progn (undo 0) (insert " ")) | |
3957 (if vhdl-conditions-in-parenthesis (insert ")")) | |
3958 (vhdl-insert-keyword " REPORT \"") | |
3959 (vhdl-field "string-expression" "\" ") | |
3960 (vhdl-insert-keyword "SEVERITY ") | |
3961 (if (equal (vhdl-field "[note | warning | error | failure]") "") | |
3962 (delete-char -10)) | |
3963 (insert ";") | |
3964 )) | |
3965 | |
3966 (defun vhdl-attribute () | |
3967 "Inserts an attribute declaration or specification." | |
3968 (interactive) | |
3969 (vhdl-insert-keyword "ATTRIBUTE ") | |
3970 (if (y-or-n-p "declaration (or specification)? ") | |
3971 (progn | |
3972 (vhdl-field "name" " : ") | |
3973 (vhdl-field "type" ";") | |
3974 (vhdl-declaration-comment)) | |
3975 (vhdl-field "name") | |
3976 (vhdl-insert-keyword " OF ") | |
3977 (vhdl-field "entity name" " : ") | |
3978 (vhdl-field "entity class") | |
3979 (vhdl-insert-keyword " IS ") | |
3980 (vhdl-field "expression" ";") | |
3981 )) | |
3982 | |
3983 (defun vhdl-block () | |
3984 "Insert a block template." | |
3985 (interactive) | |
3986 (let ((position (point))) | |
3987 (vhdl-insert-keyword " : BLOCK ") | |
3988 (goto-char position)) | |
3989 (let* ((margin (current-column)) | |
3990 (name (vhdl-field "label"))) | |
3991 (if (equal name "") | |
3992 (progn (undo 0) (insert " ")) | |
3993 (end-of-line) | |
3994 (insert "(") | |
3995 (if (equal (vhdl-field "[guard expression]") "") | |
3996 (delete-char -2) | |
3997 (insert ")")) | |
3998 (vhdl-begin-end (cons (concat (vhdl-case-keyword "BLOCK ") name) margin)) | |
3999 (vhdl-block-comment) | |
4000 ))) | |
4001 | |
4002 (defun vhdl-block-configuration () | |
4003 "Insert a block configuration statement." | |
4004 (interactive) | |
4005 (let ((margin (current-column))) | |
4006 (vhdl-insert-keyword "FOR ") | |
4007 (if (equal (setq name (vhdl-field "block specification")) "") | |
4008 nil | |
4009 (vhdl-insert-keyword "\n\n") | |
4010 (indent-to margin) | |
4011 (vhdl-insert-keyword "END FOR;") | |
4012 (end-of-line 0) | |
4013 (indent-to (+ margin vhdl-basic-offset)) | |
4014 ))) | |
4015 | |
4016 (defun vhdl-case () | |
4017 "Inserts a case statement." | |
4018 (interactive) | |
4019 (let ((margin (current-column)) | |
4020 (name)) | |
4021 (vhdl-insert-keyword "CASE ") | |
4022 (if (equal (setq name (vhdl-field "expression")) "") | |
4023 nil | |
4024 (vhdl-insert-keyword " IS\n\n") | |
4025 (indent-to margin) | |
4026 (vhdl-insert-keyword "END CASE;") | |
4027 ; (if vhdl-self-insert-comments (insert " -- " name)) | |
4028 (forward-line -1) | |
4029 (indent-to (+ margin vhdl-basic-offset)) | |
4030 (vhdl-insert-keyword "WHEN => ") | |
4031 (backward-char 4) | |
4032 ))) | |
4033 | |
4034 (defun vhdl-component () | |
4035 "Inserts a component declaration." | |
4036 (interactive) | |
4037 (let ((margin (current-column))) | |
4038 (vhdl-insert-keyword "COMPONENT ") | |
4039 (if (equal (vhdl-field "name") "") | |
4040 nil | |
4041 (insert "\n\n") | |
4042 (indent-to margin) | |
4043 (vhdl-insert-keyword "END COMPONENT;") | |
4044 (end-of-line -0) | |
4045 (indent-to (+ margin vhdl-basic-offset)) | |
4046 (vhdl-insert-keyword "GENERIC (") | |
4047 (vhdl-get-generic t t) | |
4048 (insert "\n") | |
4049 (indent-to (+ margin vhdl-basic-offset)) | |
4050 (vhdl-insert-keyword "PORT (") | |
4051 (vhdl-get-port t t) | |
4052 (forward-line 1)) | |
4053 )) | |
4054 | |
4055 (defun vhdl-component-configuration () | |
4056 "Inserts a component configuration (uses `vhdl-configuration-spec' since | |
4057 these are almost equivalent)." | |
4058 (interactive) | |
4059 (let ((margin (current-column))) | |
4060 (vhdl-configuration-spec) | |
4061 (insert "\n") | |
4062 (indent-to margin) | |
4063 (vhdl-insert-keyword "END FOR;") | |
4064 )) | |
4065 | |
4066 (defun vhdl-component-instance () | |
4067 "Inserts a component instantiation statement." | |
4068 (interactive) | |
4069 (let ((margin (current-column))) | |
4070 (if (equal (vhdl-field "instance label") "") | |
4071 nil | |
4072 (insert " : ") | |
4073 (vhdl-field "component name" "\n") | |
4074 (indent-to (+ margin vhdl-basic-offset)) | |
4075 (let ((position (point))) | |
4076 (vhdl-insert-keyword "GENERIC MAP (") | |
4077 (if (equal (vhdl-field "[association list]") "") | |
4078 (progn (goto-char position) | |
4079 (kill-line)) | |
4080 (insert ")\n") | |
4081 (indent-to (+ margin vhdl-basic-offset)))) | |
4082 (vhdl-insert-keyword "PORT MAP (") | |
4083 (vhdl-field "association list" ");") | |
4084 ))) | |
4085 | |
4086 (defun vhdl-concurrent-signal-assignment () | |
4087 "Inserts a concurrent signal assignment." | |
4088 (interactive) | |
4089 (if (equal (vhdl-field "target signal") "") | |
4090 nil | |
4091 (insert " <= ") | |
4092 ; (if (not (equal (vhdl-field "[GUARDED] [TRANSPORT]") "")) | |
4093 ; (insert " ")) | |
4094 (let ((margin (current-column)) | |
4095 (start (point))) | |
4096 (vhdl-field "waveform") | |
4097 (vhdl-insert-keyword " WHEN ") | |
4098 (if vhdl-conditions-in-parenthesis (insert "(")) | |
4099 (while (not (equal (vhdl-field "[condition]") "")) | |
4100 (if vhdl-conditions-in-parenthesis (insert ")")) | |
4101 (vhdl-insert-keyword " ELSE") | |
4102 (insert "\n") | |
4103 (indent-to margin) | |
4104 (vhdl-field "waveform") | |
4105 (vhdl-insert-keyword " WHEN ") | |
4106 (if vhdl-conditions-in-parenthesis (insert "("))) | |
4107 (delete-char -6) | |
4108 (if vhdl-conditions-in-parenthesis (delete-char -1)) | |
4109 (insert ";") | |
4110 (if vhdl-auto-align (vhdl-align start (point) 1)) | |
4111 ))) | |
4112 | |
4113 (defun vhdl-configuration () | |
4114 "Inserts a configuration specification if within an architecture, | |
4115 a block or component configuration if within a configuration declaration, | |
4116 a configuration declaration if not within a design unit." | |
4117 (interactive) | |
4118 (cond ((equal (car (car (cdr (vhdl-get-syntactic-context)))) 'architecture) | |
4119 (vhdl-configuration-spec)) | |
4120 ((equal (car (car (cdr (vhdl-get-syntactic-context)))) 'configuration) | |
4121 (if (y-or-n-p "block configuration (or component configuration)? ") | |
4122 (vhdl-block-configuration) | |
4123 (vhdl-component-configuration))) | |
4124 (t (vhdl-configuration-decl))) | |
4125 ) | |
4126 | |
4127 (defun vhdl-configuration-spec () | |
4128 "Inserts a configuration specification." | |
4129 (interactive) | |
4130 (let ((margin (current-column))) | |
4131 (vhdl-insert-keyword "FOR ") | |
4132 (if (equal (vhdl-field "(component names | ALL)" " : ") "") | |
4133 (progn (undo 0) (insert " ")) | |
4134 (vhdl-field "component type" "\n") | |
4135 (indent-to (+ margin vhdl-basic-offset)) | |
4136 (vhdl-insert-keyword "USE ENTITY ") | |
4137 (vhdl-field "library name" ".") | |
4138 (vhdl-field "entity name" "(") | |
4139 (if (equal (vhdl-field "[architecture name]") "") | |
4140 (delete-char -1) | |
4141 (insert ")")) | |
4142 (insert "\n") | |
4143 (indent-to (+ margin vhdl-basic-offset)) | |
4144 (vhdl-insert-keyword "GENERIC MAP (") | |
4145 (if (equal (vhdl-field "[association list]") "") | |
4146 (progn (kill-line -0) | |
4147 (indent-to (+ margin vhdl-basic-offset))) | |
4148 (insert ")\n") | |
4149 (indent-to (+ margin vhdl-basic-offset))) | |
4150 (vhdl-insert-keyword "PORT MAP (") | |
4151 (if (equal (vhdl-field "[association list]") "") | |
4152 (progn (kill-line -0) | |
4153 (delete-char -1)) | |
4154 (insert ")")) | |
4155 (insert ";") | |
4156 ))) | |
4157 | |
4158 (defun vhdl-configuration-decl () | |
4159 "Inserts a configuration declaration." | |
4160 (interactive) | |
4161 (let ((margin (current-column)) | |
4162 (position) | |
4163 (entity-exists) | |
4164 (string) | |
4165 (name)) | |
4166 (vhdl-insert-keyword "CONFIGURATION ") | |
4167 (if (equal (setq name (vhdl-field "name")) "") | |
4168 nil | |
4169 (vhdl-insert-keyword " OF ") | |
4170 (setq position (point)) | |
4171 (setq entity-exists | |
4172 (re-search-backward "entity \\(\\(\\w\\|\\s_\\)*\\) is" nil t)) | |
4173 (setq string (match-string 1)) | |
4174 (goto-char position) | |
4175 (if (and entity-exists (not (equal string ""))) | |
4176 (insert string) | |
4177 (vhdl-field "entity name")) | |
4178 (vhdl-insert-keyword " IS\n\n") | |
4179 (indent-to margin) | |
4180 (vhdl-insert-keyword "END ") | |
4181 (insert name ";") | |
4182 (end-of-line 0) | |
4183 (indent-to (+ margin vhdl-basic-offset)) | |
4184 ))) | |
4185 | |
4186 (defun vhdl-constant () | |
4187 "Inserts a constant declaration." | |
4188 (interactive) | |
4189 (vhdl-insert-keyword "CONSTANT ") | |
4190 (let ((in-arglist (string-match "arglist" | |
4191 (format "%s" (car (car (vhdl-get-syntactic-context))))))) | |
4192 (if (not in-arglist) | |
4193 (let ((opoint (point))) | |
4194 (beginning-of-line) | |
4195 (setq in-arglist (looking-at ".*(")) | |
4196 (goto-char opoint))) | |
4197 (if (equal (vhdl-field "name") "") | |
4198 nil | |
4199 (insert " : ") | |
4200 (if in-arglist (vhdl-insert-keyword "IN ")) | |
4201 (vhdl-field "type") | |
4202 (if in-arglist | |
4203 (insert ";") | |
4204 (let ((position (point))) | |
4205 (insert " := ") | |
4206 (if (equal (vhdl-field "[initialization]" ";") "") | |
4207 (progn (goto-char position) (kill-line) (insert ";"))) | |
4208 (vhdl-declaration-comment)) | |
4209 )))) | |
4210 | |
4211 (defun vhdl-default () | |
4212 "Insert nothing." | |
4213 (interactive) | |
4214 (insert " ") | |
4215 (unexpand-abbrev) | |
4216 (backward-word 1) | |
4217 (vhdl-case-word 1) | |
4218 (forward-char 1) | |
4219 ) | |
4220 | |
4221 (defun vhdl-default-indent () | |
4222 "Insert nothing and indent." | |
4223 (interactive) | |
4224 (insert " ") | |
4225 (unexpand-abbrev) | |
4226 (backward-word 1) | |
4227 (vhdl-case-word 1) | |
4228 (forward-char 1) | |
4229 (vhdl-indent-line) | |
4230 ) | |
4231 | |
4232 (defun vhdl-disconnect () | |
4233 "Insert a disconnect statement." | |
4234 (interactive) | |
4235 (vhdl-insert-keyword "DISCONNECT ") | |
4236 (if (equal (vhdl-field "guarded signal specification") "") | |
4237 nil | |
4238 (vhdl-insert-keyword " AFTER ") | |
4239 (vhdl-field "time expression" ";") | |
4240 )) | |
4241 | |
4242 (defun vhdl-else () | |
4243 "Insert an else statement." | |
4244 (interactive) | |
4245 (let ((margin)) | |
4246 (vhdl-insert-keyword "ELSE") | |
4247 (if (not (equal 'block-close (car (car (vhdl-get-syntactic-context))))) | |
4248 (insert " ") | |
4249 (vhdl-indent-line) | |
4250 (setq margin (current-indentation)) | |
4251 (insert "\n") | |
4252 (indent-to (+ margin vhdl-basic-offset)) | |
4253 ))) | |
4254 | |
4255 (defun vhdl-elsif () | |
4256 "Insert an elsif statement." | |
4257 (interactive) | |
4258 (let ((margin)) | |
4259 (vhdl-insert-keyword "ELSIF ") | |
4260 (if vhdl-conditions-in-parenthesis (insert "(")) | |
4261 (if (equal (vhdl-field "condition") "") | |
4262 (progn (undo 0) (insert " ")) | |
4263 (if vhdl-conditions-in-parenthesis (insert ")")) | |
4264 (vhdl-indent-line) | |
4265 (setq margin (current-indentation)) | |
4266 (vhdl-insert-keyword " THEN\n") | |
4267 (indent-to (+ margin vhdl-basic-offset)) | |
4268 ))) | |
4269 | |
4270 (defun vhdl-entity () | |
4271 "Insert an entity template." | |
4272 (interactive) | |
4273 (let ((margin (current-column)) | |
4274 (vhdl-entity-name)) | |
4275 (vhdl-insert-keyword "ENTITY ") | |
4276 (if (equal (setq vhdl-entity-name (vhdl-field "entity name")) "") | |
4277 nil | |
4278 (vhdl-insert-keyword " IS\n\n") | |
4279 (indent-to margin) | |
4280 (vhdl-insert-keyword "END ") | |
4281 (insert vhdl-entity-name ";") | |
4282 (end-of-line -0) | |
4283 (indent-to (+ margin vhdl-basic-offset)) | |
4284 (vhdl-entity-body) | |
4285 ))) | |
4286 | |
4287 (defun vhdl-entity-body () | |
4288 "Insert an entity body." | |
4289 (interactive) | |
4290 (let ((margin (current-column))) | |
4291 (if vhdl-additional-empty-lines (insert "\n")) | |
4292 (indent-to margin) | |
4293 (vhdl-insert-keyword "GENERIC (") | |
4294 (if (vhdl-get-generic t) | |
4295 (if vhdl-additional-empty-lines (insert "\n"))) | |
4296 (insert "\n") | |
4297 (indent-to margin) | |
4298 (vhdl-insert-keyword "PORT (") | |
4299 (if (vhdl-get-port t) | |
4300 (if vhdl-additional-empty-lines (insert "\n"))) | |
4301 (end-of-line 2) | |
4302 )) | |
4303 | |
4304 (defun vhdl-exit () | |
4305 "Insert an exit statement." | |
4306 (interactive) | |
4307 (vhdl-insert-keyword "EXIT ") | |
4308 (if (string-equal (vhdl-field "[loop label]") "") | |
4309 (delete-char -1)) | |
4310 (let ((opoint (point))) | |
4311 (vhdl-insert-keyword " WHEN ") | |
4312 (if vhdl-conditions-in-parenthesis (insert "(")) | |
4313 (if (equal (vhdl-field "[condition]") "") | |
4314 (progn (goto-char opoint) | |
4315 (kill-line)) | |
4316 (if vhdl-conditions-in-parenthesis (insert ")")))) | |
4317 (insert ";") | |
4318 ) | |
4319 | |
4320 (defun vhdl-for () | |
4321 "Inserts a block or component configuration if within a configuration | |
4322 declaration, a for loop otherwise." | |
4323 (interactive) | |
4324 (if (equal (car (car (cdr (vhdl-get-syntactic-context)))) 'configuration) | |
4325 (if (y-or-n-p "block configuration (or component configuration)? ") | |
4326 (vhdl-block-configuration) | |
4327 (vhdl-component-configuration)) | |
4328 (vhdl-for-loop))) | |
4329 | |
4330 (defun vhdl-for-loop () | |
4331 "Insert a for loop template." | |
4332 (interactive) | |
4333 (let ((position (point))) | |
4334 (vhdl-insert-keyword " : FOR ") | |
4335 (goto-char position)) | |
4336 (let* ((margin (current-column)) | |
4337 (name (vhdl-field "[label]")) | |
4338 (named (not (string-equal name ""))) | |
4339 (index)) | |
4340 (if (not named) (delete-char 3)) | |
4341 (end-of-line) | |
4342 (if (equal (setq index (vhdl-field "loop variable")) "") | |
4343 nil | |
4344 (vhdl-insert-keyword " IN ") | |
4345 (vhdl-field "range") | |
4346 (vhdl-insert-keyword " LOOP\n\n") | |
4347 (indent-to margin) | |
4348 (vhdl-insert-keyword "END LOOP") | |
4349 (if named (insert " " name ";") | |
4350 (insert ";") | |
4351 (if vhdl-self-insert-comments (insert " -- " index))) | |
4352 (forward-line -1) | |
4353 (indent-to (+ margin vhdl-basic-offset)) | |
4354 ))) | |
4355 | |
4356 (defun vhdl-function () | |
4357 "Insert function specification or body template." | |
4358 (interactive) | |
4359 (let ((margin (current-column)) | |
4360 (name)) | |
4361 (vhdl-insert-keyword "FUNCTION ") | |
4362 (if (equal (setq name (vhdl-field "name")) "") | |
4363 nil | |
4364 (vhdl-get-arg-list) | |
4365 (vhdl-insert-keyword " RETURN ") | |
4366 (vhdl-field "type" " ") | |
4367 (if (y-or-n-p "insert body? ") | |
4368 (progn (vhdl-insert-keyword "IS") | |
4369 (vhdl-begin-end (cons name margin)) | |
4370 (vhdl-block-comment)) | |
4371 (delete-char -1) | |
4372 (insert ";\n") | |
4373 (indent-to margin))) | |
4374 )) | |
4375 | |
4376 (defun vhdl-generate () | |
4377 "Insert a generate template." | |
4378 (interactive) | |
4379 (let ((position (point))) | |
4380 (vhdl-insert-keyword " GENERATE") | |
4381 (goto-char position)) | |
4382 (let ((margin (current-column)) | |
4383 (label (vhdl-field "label")) | |
4384 (string)) | |
4385 (if (equal label "") | |
4386 (progn (undo 0) (insert " ")) | |
4387 (insert " : ") | |
4388 (setq string (vhdl-field "(FOR | IF)")) | |
4389 (insert " ") | |
4390 (if (equal (upcase string) "IF") | |
4391 (progn | |
4392 (if vhdl-conditions-in-parenthesis (insert "(")) | |
4393 (vhdl-field "condition") | |
4394 (if vhdl-conditions-in-parenthesis (insert ")"))) | |
4395 (vhdl-field "loop variable") | |
4396 (vhdl-insert-keyword " IN ") | |
4397 (vhdl-field "range")) | |
4398 (end-of-line) | |
4399 (insert "\n\n") | |
4400 (indent-to margin) | |
4401 (vhdl-insert-keyword "END GENERATE ") | |
4402 (insert label ";") | |
4403 (end-of-line 0) | |
4404 (indent-to (+ margin vhdl-basic-offset)) | |
4405 ))) | |
4406 | |
4407 (defun vhdl-generic () | |
4408 "Insert generic declaration, or generic map in instantiation statements." | |
4409 (interactive) | |
4410 (vhdl-insert-keyword "GENERIC (") | |
4411 (cond ((equal (car (car (cdr (vhdl-get-syntactic-context)))) 'entity) | |
4412 (vhdl-get-generic nil)) | |
4413 ((or (equal 'statement-cont (car (car (vhdl-get-syntactic-context)))) | |
4414 (save-excursion | |
4415 (and (backward-word 2) (skip-chars-backward " ") | |
4416 (eq (preceding-char) ?:)))) | |
4417 (delete-char -1) (vhdl-map)) | |
4418 (t (vhdl-get-generic nil t)))) | |
4419 | |
4420 (defun vhdl-header () | |
4421 "Insert a VHDL file header." | |
4422 (interactive) | |
4423 (let (eot) | |
4424 (save-excursion | |
4425 (save-restriction | |
4426 (widen) | |
4427 (goto-char (point-min)) | |
4428 (if vhdl-header-file | |
4429 (setq eot (car (cdr (insert-file-contents vhdl-header-file)))) | |
4430 ; insert default header | |
4431 (insert "\ | |
4432 ------------------------------------------------------------------------------- | |
4433 -- Title : <title string> | |
4434 -- Project : <project string> | |
4435 ------------------------------------------------------------------------------- | |
4436 -- File : <filename> | |
4437 -- Author : <author> | |
4438 -- Created : <date> | |
4439 -- Last modified : <date> | |
4440 ------------------------------------------------------------------------------- | |
4441 -- Description : | |
4442 -- <cursor> | |
4443 ------------------------------------------------------------------------------- | |
4444 -- Modification history : | |
4445 -- <date> : created | |
4446 ------------------------------------------------------------------------------- | |
4447 | |
4448 ") | |
4449 (setq eot (point))) | |
4450 (narrow-to-region (point-min) eot) | |
4451 (goto-char (point-min)) | |
4452 (while (search-forward "<filename>" nil t) | |
4453 (replace-match (buffer-name) t t)) | |
4454 (goto-char (point-min)) | |
4455 (while (search-forward "<author>" nil t) | |
4456 (replace-match "" t t) | |
4457 (insert (user-full-name) " <" user-mail-address ">")) | |
4458 (goto-char (point-min)) | |
4459 ;; Replace <RCS> with $, so that RCS for the source is | |
4460 ;; not over-enthusiastic with replacements | |
4461 (while (search-forward "<RCS>" nil t) | |
4462 (replace-match "$" nil t)) | |
4463 (goto-char (point-min)) | |
4464 (while (search-forward "<date>" nil t) | |
4465 (replace-match "" t t) | |
4466 (vhdl-insert-date)) | |
4467 (goto-char (point-min)) | |
4468 (let (string) | |
4469 (while (re-search-forward "<\\(\\w*\\) string>" nil t) | |
4470 (setq string (read-string (concat (match-string 1) ": "))) | |
4471 (replace-match string t t))))) | |
4472 (goto-char (point-min)) | |
4473 (if (search-forward "<cursor>" nil t) | |
4474 (replace-match "" t t)))) | |
4475 | |
4476 (defun vhdl-if () | |
4477 "Insert an if statement template." | |
4478 (interactive) | |
4479 (let ((margin (current-column))) | |
4480 (vhdl-insert-keyword "IF ") | |
4481 (if vhdl-conditions-in-parenthesis (insert "(")) | |
4482 (if (equal (vhdl-field "condition") "") | |
4483 (progn (undo 0) (insert " ")) | |
4484 (if vhdl-conditions-in-parenthesis (insert ")")) | |
4485 (vhdl-insert-keyword " THEN\n\n") | |
4486 (indent-to margin) | |
4487 (vhdl-insert-keyword "END IF;") | |
4488 (forward-line -1) | |
4489 (indent-to (+ margin vhdl-basic-offset)) | |
4490 ))) | |
4491 | |
4492 (defun vhdl-library () | |
4493 "Insert a library specification." | |
4494 (interactive) | |
4495 (let ((margin (current-column)) | |
4496 (lib-name)) | |
4497 (vhdl-insert-keyword "LIBRARY ") | |
4498 (if (equal (setq lib-name (vhdl-field "library name")) "") | |
4499 nil | |
4500 (insert ";\n") | |
4501 (indent-to margin) | |
4502 (vhdl-insert-keyword "USE ") | |
4503 (insert lib-name) | |
4504 (vhdl-insert-keyword "..ALL;") | |
4505 (backward-char 5) | |
4506 (if (equal (vhdl-field "package name") "") | |
4507 (progn (vhdl-kill-entire-line) | |
4508 (end-of-line -0)) | |
4509 (end-of-line) | |
4510 )))) | |
4511 | |
4512 (defun vhdl-loop () | |
4513 "Insert a loop template." | |
4514 (interactive) | |
4515 (let ((position (point))) | |
4516 (vhdl-insert-keyword " : LOOP") | |
4517 (goto-char position)) | |
4518 (let* ((margin (current-column)) | |
4519 (name (vhdl-field "[label]")) | |
4520 (named (not (string-equal name "")))) | |
4521 (if (not named) (delete-char 3)) | |
4522 (end-of-line) | |
4523 (insert "\n\n") | |
4524 (indent-to margin) | |
4525 (vhdl-insert-keyword "END LOOP") | |
21466
98b189f8975f
(vhdl-loop, vhdl-while-loop): Add backslash.
Karl Heuer <kwzh@gnu.org>
parents:
21446
diff
changeset
|
4526 (insert (if named (concat " " name ";") ?\;)) |
20665 | 4527 (forward-line -1) |
4528 (indent-to (+ margin vhdl-basic-offset)) | |
4529 )) | |
4530 | |
4531 (defun vhdl-map () | |
4532 "Insert a map specification." | |
4533 (interactive) | |
4534 (vhdl-insert-keyword "MAP (") | |
4535 (if (equal (vhdl-field "[association list]") "") | |
4536 (progn (undo 0) (insert " ")) | |
4537 (insert ")") | |
4538 )) | |
4539 | |
4540 (defun vhdl-modify () | |
4541 "Actualize modification date." | |
4542 (interactive) | |
4543 (goto-char (point-min)) | |
4544 (if (search-forward vhdl-modify-date-prefix-string nil t) | |
4545 (progn (kill-line) | |
4546 (vhdl-insert-date)) | |
4547 (message (concat "Modification date prefix string \"" | |
4548 vhdl-modify-date-prefix-string | |
4549 "\" not found!")) | |
4550 (beep))) | |
4551 | |
4552 (defun vhdl-next () | |
4553 "Inserts a next statement." | |
4554 (interactive) | |
4555 (vhdl-insert-keyword "NEXT ") | |
4556 (if (string-equal (vhdl-field "[loop label]") "") | |
4557 (delete-char -1)) | |
4558 (let ((opoint (point))) | |
4559 (vhdl-insert-keyword " WHEN ") | |
4560 (if vhdl-conditions-in-parenthesis (insert "(")) | |
4561 (if (equal (vhdl-field "[condition]") "") | |
4562 (progn (goto-char opoint) | |
4563 (kill-line)) | |
4564 (if vhdl-conditions-in-parenthesis (insert ")")))) | |
4565 (insert ";") | |
4566 ) | |
4567 | |
4568 (defun vhdl-package () | |
4569 "Insert a package specification or body." | |
4570 (interactive) | |
4571 (let ((margin (current-column)) | |
4572 (name)) | |
4573 (vhdl-insert-keyword "PACKAGE ") | |
4574 (if (y-or-n-p "body? ") | |
4575 (vhdl-insert-keyword "BODY ")) | |
4576 (setq name (vhdl-field "name" " is\n\n")) | |
4577 (indent-to margin) | |
4578 (vhdl-insert-keyword "END ") | |
4579 (insert name ";") | |
4580 (forward-line -1) | |
4581 (indent-to (+ margin vhdl-basic-offset)) | |
4582 )) | |
4583 | |
4584 (defun vhdl-port () | |
4585 "Insert a port declaration, or port map in instantiation statements." | |
4586 (interactive) | |
4587 (vhdl-insert-keyword "PORT (") | |
4588 (cond ((equal (car (car (cdr (vhdl-get-syntactic-context)))) 'entity) | |
4589 (vhdl-get-port nil)) | |
4590 ((or (equal 'statement-cont (car (car (vhdl-get-syntactic-context)))) | |
4591 (save-excursion | |
4592 (and (backward-word 2) (skip-chars-backward " ") | |
4593 (eq (preceding-char) ?:)))) | |
4594 (delete-char -1) (vhdl-map)) | |
4595 (t (vhdl-get-port nil t)))) | |
4596 | |
4597 (defun vhdl-procedure () | |
4598 "Insert a procedure specification or body template." | |
4599 (interactive) | |
4600 (let ((margin (current-column)) | |
4601 (name)) | |
4602 (vhdl-insert-keyword "PROCEDURE ") | |
4603 (if (equal (setq name (vhdl-field "name")) "") | |
4604 nil | |
4605 (vhdl-get-arg-list) | |
4606 (insert " ") | |
4607 (if (y-or-n-p "insert body? ") | |
4608 (progn (vhdl-insert-keyword "IS") | |
4609 (vhdl-begin-end (cons name margin)) | |
4610 (vhdl-block-comment)) | |
4611 (delete-char -1) | |
4612 (insert ";\n") | |
4613 (indent-to margin) | |
4614 )))) | |
4615 | |
4616 (defun vhdl-process () | |
4617 "Insert a process template." | |
4618 (interactive) | |
4619 (let ((clocked)) | |
4620 (let ((position (point))) | |
4621 (vhdl-insert-keyword "PROCESS") | |
4622 (setq clocked (y-or-n-p "clocked process? ")) | |
4623 (goto-char position) | |
4624 (insert " : ") | |
4625 (goto-char position)) | |
4626 (let* ((margin (current-column)) | |
4627 (finalline) | |
4628 (name (vhdl-field "[label]")) | |
4629 (named (not (string-equal name ""))) | |
4630 (clock) (reset) | |
4631 (case-fold-search t)) | |
4632 (if (not named) (delete-char 3)) | |
4633 (end-of-line) | |
4634 (insert " (") | |
4635 (if (not clocked) | |
4636 (if (equal (vhdl-field "[sensitivity list]" ")") "") | |
4637 (delete-char -3)) | |
4638 (setq clock (vhdl-field "clock name" ", ")) | |
4639 (setq reset (vhdl-field "reset name" ")"))) | |
4640 (vhdl-begin-end (cons (concat (vhdl-case-keyword "PROCESS") | |
4641 (if named (concat " " name))) margin)) | |
4642 (if clocked (vhdl-clock-async-reset clock reset)) | |
4643 (if vhdl-prompt-for-comments | |
4644 (progn | |
4645 (setq finalline (vhdl-current-line)) | |
4646 (if (and (re-search-backward "\\<begin\\>" nil t) | |
4647 (re-search-backward "\\<process\\>" nil t)) | |
4648 (progn | |
4649 (end-of-line -0) | |
4650 (insert "\n") | |
4651 (indent-to margin) | |
4652 (insert "-- purpose: ") | |
4653 (if (equal (vhdl-field "description") "") | |
4654 (vhdl-kill-entire-line) | |
4655 (newline) | |
4656 (indent-to margin) | |
4657 (insert "-- type: ") | |
4658 (insert (if clocked "memorizing" "memoryless") "\n") | |
4659 (indent-to margin) | |
4660 (insert "-- inputs: ") | |
4661 (if clocked | |
4662 (insert clock ", " reset ", ")) | |
4663 (if (and (equal (vhdl-field "signal names") "") | |
4664 clocked) | |
4665 (delete-char -2)) | |
4666 (insert "\n") | |
4667 (indent-to margin) | |
4668 (insert "-- outputs: ") | |
4669 (vhdl-field "signal names") | |
4670 (setq finalline (+ finalline 4))))) | |
4671 (goto-line finalline) | |
4672 (end-of-line) | |
4673 ))))) | |
4674 | |
4675 (defun vhdl-record () | |
4676 "Insert a record type declaration." | |
4677 (interactive) | |
4678 (let ((margin (current-column)) | |
4679 (start (point)) | |
4680 (first t)) | |
4681 (vhdl-insert-keyword "RECORD\n") | |
4682 (indent-to (+ margin vhdl-basic-offset)) | |
4683 (if (equal (vhdl-field "identifiers") "") | |
4684 (progn (kill-line -0) | |
4685 (delete-char -1) | |
4686 (insert " ")) | |
4687 (while (or first (not (equal (vhdl-field "[identifiers]") ""))) | |
4688 (insert " : ") | |
4689 (vhdl-field "type" ";") | |
4690 (vhdl-declaration-comment) | |
4691 (newline) | |
4692 (indent-to (+ margin vhdl-basic-offset)) | |
4693 (setq first nil)) | |
4694 (kill-line -0) | |
4695 (indent-to margin) | |
4696 (vhdl-insert-keyword "END RECORD;") | |
4697 (if vhdl-auto-align (vhdl-align start (point) 1)) | |
4698 ))) | |
4699 | |
4700 (defun vhdl-return-value () | |
4701 "Insert a return statement." | |
4702 (interactive) | |
4703 (vhdl-insert-keyword "RETURN ") | |
4704 (if (equal (vhdl-field "[expression]") "") | |
4705 (delete-char -1)) | |
4706 (insert ";") | |
4707 ) | |
4708 | |
4709 (defun vhdl-selected-signal-assignment () | |
4710 "Insert a selected signal assignment." | |
4711 (interactive) | |
4712 (let ((margin (current-column)) | |
4713 (start (point))) | |
4714 (let ((position (point))) | |
4715 (vhdl-insert-keyword " SELECT") | |
4716 (goto-char position)) | |
4717 (vhdl-insert-keyword "WITH ") | |
4718 (if (equal (vhdl-field "selector expression") "") | |
4719 (progn (undo 0) (insert " ")) | |
4720 (end-of-line) | |
4721 (insert "\n") | |
4722 (indent-to (+ margin vhdl-basic-offset)) | |
4723 (vhdl-field "target signal" " <= ") | |
4724 ; (vhdl-field "[GUARDED] [TRANSPORT]") | |
4725 (insert "\n") | |
4726 (indent-to (+ margin vhdl-basic-offset)) | |
4727 (while (not (equal (vhdl-field "[waveform]") "")) | |
4728 (vhdl-insert-keyword " WHEN ") | |
4729 (vhdl-field "choices" ",") | |
4730 (newline) | |
4731 (indent-to (+ margin vhdl-basic-offset))) | |
4732 (if (not (equal (vhdl-field "[alternative waveform]") "")) | |
4733 (vhdl-insert-keyword " WHEN OTHERS") | |
4734 (fixup-whitespace) | |
4735 (delete-char -2)) | |
4736 (insert ";") | |
4737 (if vhdl-auto-align (vhdl-align start (point) 1)) | |
4738 ))) | |
4739 | |
4740 (defun vhdl-signal () | |
4741 "Insert a signal declaration." | |
4742 (interactive) | |
4743 (vhdl-insert-keyword "SIGNAL ") | |
4744 (let ((in-arglist (string-match "arglist" | |
4745 (format "%s" (car (car (vhdl-get-syntactic-context))))))) | |
4746 (if (not in-arglist) | |
4747 (let ((opoint (point))) | |
4748 (beginning-of-line) | |
4749 (setq in-arglist (looking-at ".*(")) | |
4750 (goto-char opoint))) | |
4751 (if (equal (vhdl-field "names") "") | |
4752 nil | |
4753 (insert " : ") | |
4754 (if in-arglist | |
4755 (progn (vhdl-field "direction") | |
4756 (insert " "))) | |
4757 (vhdl-field "type") | |
4758 (if in-arglist | |
4759 (insert ";") | |
4760 (let ((position (point))) | |
4761 (insert " := ") | |
4762 (if (equal (vhdl-field "[initialization]" ";") "") | |
4763 (progn (goto-char position) (kill-line) (insert ";"))) | |
4764 (vhdl-declaration-comment)) | |
4765 )))) | |
4766 | |
4767 (defun vhdl-subtype () | |
4768 "Insert a subtype declaration." | |
4769 (interactive) | |
4770 (vhdl-insert-keyword "SUBTYPE ") | |
4771 (if (equal (vhdl-field "name") "") | |
4772 nil | |
4773 (vhdl-insert-keyword " IS ") | |
4774 (vhdl-field "type" " ") | |
4775 (if (equal (vhdl-field "[RANGE value range | ( index range )]") "") | |
4776 (delete-char -1)) | |
4777 (insert ";") | |
4778 (vhdl-declaration-comment) | |
4779 )) | |
4780 | |
4781 (defun vhdl-type () | |
4782 "Insert a type declaration." | |
4783 (interactive) | |
4784 (vhdl-insert-keyword "TYPE ") | |
4785 (if (equal (vhdl-field "name") "") | |
4786 nil | |
4787 (vhdl-insert-keyword " IS ") | |
4788 (let ((definition (upcase (vhdl-field "(scalar type | ARRAY | RECORD | ACCESS | FILE)")))) | |
4789 (cond ((equal definition "ARRAY") | |
4790 (kill-word -1) (vhdl-array)) | |
4791 ((equal definition "RECORD") | |
4792 (kill-word -1) (vhdl-record)) | |
4793 ((equal definition "ACCESS") | |
4794 (insert " ") (vhdl-field "type" ";")) | |
4795 ((equal definition "FILE") | |
4796 (vhdl-insert-keyword " OF ") (vhdl-field "type" ";")) | |
4797 (t (insert ";"))) | |
4798 (vhdl-declaration-comment) | |
4799 ))) | |
4800 | |
4801 (defun vhdl-use () | |
4802 "Insert a use clause." | |
4803 (interactive) | |
4804 (vhdl-insert-keyword "USE ..ALL;") | |
4805 (backward-char 6) | |
4806 (if (equal (vhdl-field "library name") "") | |
4807 (progn (undo 0) (insert " ")) | |
4808 (forward-char 1) | |
4809 (vhdl-field "package name") | |
4810 (end-of-line) | |
4811 )) | |
4812 | |
4813 (defun vhdl-variable () | |
4814 "Insert a variable declaration." | |
4815 (interactive) | |
4816 (vhdl-insert-keyword "VARIABLE ") | |
4817 (let ((in-arglist (string-match "arglist" | |
4818 (format "%s" (car (car (vhdl-get-syntactic-context))))))) | |
4819 (if (not in-arglist) | |
4820 (let ((opoint (point))) | |
4821 (beginning-of-line) | |
4822 (setq in-arglist (looking-at ".*(")) | |
4823 (goto-char opoint))) | |
4824 (if (equal (vhdl-field "names") "") | |
4825 nil | |
4826 (insert " : ") | |
4827 (if in-arglist | |
4828 (progn (vhdl-field "direction") | |
4829 (insert " "))) | |
4830 (vhdl-field "type") | |
4831 (if in-arglist | |
4832 (insert ";") | |
4833 (let ((position (point))) | |
4834 (insert " := ") | |
4835 (if (equal (vhdl-field "[initialization]" ";") "") | |
4836 (progn (goto-char position) (kill-line) (insert ";"))) | |
4837 (vhdl-declaration-comment)) | |
4838 )))) | |
4839 | |
4840 (defun vhdl-wait () | |
4841 "Insert a wait statement." | |
4842 (interactive) | |
4843 (vhdl-insert-keyword "WAIT ") | |
4844 (if (equal (vhdl-field | |
4845 "[ON sensitivity list] [UNTIL condition] [FOR time expression]") | |
4846 "") | |
4847 (delete-char -1)) | |
4848 (insert ";") | |
4849 ) | |
4850 | |
4851 (defun vhdl-when () | |
4852 "Indent correctly if within a case statement." | |
4853 (interactive) | |
4854 (let ((position (point)) | |
4855 (margin)) | |
4856 (if (and (re-search-forward "\\<end\\>" nil t) | |
4857 (looking-at "\\s-*\\<case\\>")) | |
4858 (progn | |
4859 (setq margin (current-indentation)) | |
4860 (goto-char position) | |
4861 (delete-horizontal-space) | |
4862 (indent-to (+ margin vhdl-basic-offset))) | |
4863 (goto-char position) | |
4864 ) | |
4865 (vhdl-insert-keyword "WHEN ") | |
4866 )) | |
4867 | |
4868 (defun vhdl-while-loop () | |
4869 "Insert a while loop template." | |
4870 (interactive) | |
4871 (let ((position (point))) | |
4872 (vhdl-insert-keyword " : WHILE ") | |
4873 (goto-char position)) | |
4874 (let* ((margin (current-column)) | |
4875 (name (vhdl-field "[label]")) | |
4876 (named (not (string-equal name "")))) | |
4877 (if (not named) (delete-char 3)) | |
4878 (end-of-line) | |
4879 (if vhdl-conditions-in-parenthesis (insert "(")) | |
4880 (if (equal (vhdl-field "condition") "") | |
4881 (progn (undo 0) (insert " ")) | |
4882 (if vhdl-conditions-in-parenthesis (insert ")")) | |
4883 (vhdl-insert-keyword " LOOP\n\n") | |
4884 (indent-to margin) | |
4885 (vhdl-insert-keyword "END LOOP") | |
21466
98b189f8975f
(vhdl-loop, vhdl-while-loop): Add backslash.
Karl Heuer <kwzh@gnu.org>
parents:
21446
diff
changeset
|
4886 (insert (if named (concat " " name ";") ?\;)) |
20665 | 4887 (forward-line -1) |
4888 (indent-to (+ margin vhdl-basic-offset)) | |
4889 ))) | |
4890 | |
4891 (defun vhdl-with () | |
4892 "Insert a with statement (i.e. selected signal assignment)." | |
4893 (interactive) | |
4894 (vhdl-selected-signal-assignment) | |
4895 ) | |
4896 | |
4897 ;; ############################################################################ | |
4898 ;; Custom functions | |
4899 | |
4900 (defun vhdl-clocked-wait () | |
4901 "Insert a wait statement for rising clock edge." | |
4902 (interactive) | |
4903 (vhdl-insert-keyword "WAIT UNTIL ") | |
4904 (let* ((clock (vhdl-field "clock name"))) | |
4905 (insert "'event") | |
4906 (vhdl-insert-keyword " AND ") | |
4907 (insert clock) | |
4908 (insert " = " vhdl-one-string ";") | |
4909 )) | |
4910 | |
4911 (defun vhdl-clock-async-reset (clock reset) | |
4912 "Insert a template reacting on asynchronous reset and rising clock edge | |
4913 for inside a memorizing processes." | |
4914 (interactive) | |
4915 (let* ( (margin (current-column)) | |
4916 (opoint)) | |
4917 (if vhdl-self-insert-comments | |
4918 (insert "-- activities triggered by asynchronous reset (active low)\n")) | |
4919 (indent-to margin) | |
4920 (vhdl-insert-keyword "IF ") | |
4921 (insert reset " = " vhdl-zero-string) | |
4922 (vhdl-insert-keyword " THEN\n") | |
4923 (indent-to (+ margin vhdl-basic-offset)) | |
4924 (setq opoint (point)) | |
4925 (newline) | |
4926 (indent-to margin) | |
4927 (if vhdl-self-insert-comments | |
4928 (insert "-- activities triggered by rising edge of clock\n")) | |
4929 (indent-to margin) | |
4930 (vhdl-insert-keyword "ELSIF ") | |
4931 (insert clock "'event") | |
4932 (vhdl-insert-keyword " AND ") | |
4933 (insert clock " = " vhdl-one-string) | |
4934 (vhdl-insert-keyword " THEN\n") | |
4935 (indent-to (+ margin vhdl-basic-offset)) | |
4936 (newline) | |
4937 (indent-to margin) | |
4938 (vhdl-insert-keyword "END IF;") | |
4939 ; (if vhdl-self-insert-comments (insert " -- " clock)) | |
4940 (goto-char opoint) | |
4941 )) | |
4942 | |
4943 (defun vhdl-standard-package (library package) | |
4944 "Insert specification of a standard package." | |
4945 (interactive) | |
4946 (let ((margin (current-column))) | |
4947 (vhdl-insert-keyword "LIBRARY ") | |
4948 (insert library ";\n") | |
4949 (indent-to margin) | |
4950 (vhdl-insert-keyword "USE ") | |
4951 (insert library "." package) | |
4952 (vhdl-insert-keyword ".ALL;") | |
4953 )) | |
4954 | |
4955 (defun vhdl-package-numeric-bit () | |
4956 "Insert specification of 'numeric_bit' package." | |
4957 (interactive) | |
4958 (vhdl-standard-package "ieee" "numeric_bit")) | |
4959 | |
4960 (defun vhdl-package-numeric-std () | |
4961 "Insert specification of 'numeric_std' package." | |
4962 (interactive) | |
4963 (vhdl-standard-package "ieee" "numeric_std")) | |
4964 | |
4965 (defun vhdl-package-std-logic-1164 () | |
4966 "Insert specification of 'std_logic_1164' package." | |
4967 (interactive) | |
4968 (vhdl-standard-package "ieee" "std_logic_1164")) | |
4969 | |
4970 (defun vhdl-package-textio () | |
4971 "Insert specification of 'textio' package." | |
4972 (interactive) | |
4973 (vhdl-standard-package "std" "textio")) | |
4974 | |
4975 ;; ############################################################################ | |
4976 ;; Comment functions | |
4977 | |
4978 (defun vhdl-comment-indent () | |
4979 (let* ((opoint (point)) | |
4980 (col (progn | |
4981 (forward-line -1) | |
4982 (if (re-search-forward "--" opoint t) | |
4983 (- (current-column) 2) ;Existing comment at bol stays there. | |
4984 (goto-char opoint) | |
4985 (skip-chars-backward " \t") | |
4986 (max comment-column ;else indent to comment column | |
4987 (1+ (current-column))) ;except leave at least one space. | |
4988 )))) | |
4989 (goto-char opoint) | |
4990 col | |
4991 )) | |
4992 | |
4993 (defun vhdl-inline-comment () | |
4994 "Start a comment at the end of the line. | |
4995 if on line with code, indent at least comment-column. | |
4996 if starting after end-comment-column, start a new line." | |
4997 (interactive) | |
4998 (if (> (current-column) end-comment-column) (newline-and-indent)) | |
4999 (if (or (looking-at "\\s-*$") ;end of line | |
5000 (and (not unread-command-events) ; called with key binding or menu | |
5001 (not (end-of-line)))) | |
5002 (let ((margin)) | |
5003 (while (= (preceding-char) ?-) (delete-char -1)) | |
5004 (setq margin (current-column)) | |
5005 (delete-horizontal-space) | |
5006 (if (bolp) | |
5007 (progn (indent-to margin) (insert "--")) | |
5008 (insert " ") | |
5009 (indent-to comment-column) | |
5010 (insert "--")) | |
5011 (if (not unread-command-events) (insert " "))) | |
5012 ; else code following current point implies commenting out code | |
5013 (let (next-input code) | |
5014 (while (= (preceding-char) ?-) (delete-char -2)) | |
5015 (while (= (setq next-input (read-char)) 13) ; CR | |
5016 (insert "--"); or have a space after it? | |
5017 (forward-char -2) | |
5018 (forward-line 1) | |
5019 (message "Enter CR if commenting out a line of code.") | |
5020 (setq code t) | |
5021 ) | |
5022 (if (not code) (progn | |
5023 ; (indent-to comment-column) | |
5024 (insert "--") ;hardwire to 1 space or use vhdl-basic-offset? | |
5025 )) | |
5026 (setq unread-command-events | |
5027 (list (vhdl-character-to-event-hack next-input))) ;pushback the char | |
5028 ))) | |
5029 | |
5030 (defun vhdl-display-comment (&optional line-exists) | |
5031 "Add 2 comment lines at the current indent, making a display comment." | |
5032 (interactive) | |
5033 (if (not line-exists) | |
5034 (vhdl-display-comment-line)) | |
5035 (let* ((col (current-column)) | |
5036 (len (- end-comment-column col))) | |
5037 (insert "\n") | |
5038 (insert-char ? col) | |
5039 (insert-char ?- len) | |
5040 (insert "\n") | |
5041 (insert-char ? col) | |
5042 (end-of-line -1) | |
5043 ) | |
5044 (insert "-- ") | |
5045 ) | |
5046 | |
5047 (defun vhdl-display-comment-line () | |
5048 "Displays one line of dashes." | |
5049 (interactive) | |
5050 (while (= (preceding-char) ?-) (delete-char -2)) | |
5051 (let* ((col (current-column)) | |
5052 (len (- end-comment-column col))) | |
5053 (insert-char ?- len) | |
5054 (insert-char ?\n 1) | |
5055 (insert-char ? col) | |
5056 )) | |
5057 | |
5058 (defun vhdl-declaration-comment () | |
5059 (if vhdl-prompt-for-comments | |
5060 (let ((position (point))) | |
5061 (insert " ") | |
5062 (indent-to comment-column) | |
5063 (insert "-- ") | |
5064 (if (equal (vhdl-field "comment") "") | |
5065 (progn (goto-char position) (kill-line)) | |
5066 )))) | |
5067 | |
5068 (defun vhdl-block-comment () | |
5069 (if vhdl-prompt-for-comments | |
5070 (let ((finalline (vhdl-current-line)) | |
5071 (case-fold-search t)) | |
5072 (beginning-of-line -0) | |
5073 (if (re-search-backward "\\<\\(architecture\\|block\\|function\\|procedure\\|process\\)\\>" nil t) | |
5074 (let ((margin)) | |
5075 (back-to-indentation) | |
5076 (setq margin (current-column)) | |
5077 (end-of-line -0) | |
5078 (insert "\n") | |
5079 (indent-to margin) | |
5080 (insert "-- purpose: ") | |
5081 (if (equal (vhdl-field "description") "") | |
5082 (vhdl-kill-entire-line) | |
5083 (setq finalline (+ finalline 1))))) | |
5084 (goto-line finalline) | |
5085 (end-of-line) | |
5086 ))) | |
5087 | |
5088 (defun vhdl-comment-uncomment-region (beg end &optional arg) | |
5089 "Comment out region if not commented out, uncomment out region if already | |
5090 commented out." | |
5091 (interactive "r\nP") | |
5092 (goto-char beg) | |
5093 (if (looking-at comment-start) | |
5094 (comment-region beg end -1) | |
5095 (comment-region beg end) | |
5096 )) | |
5097 | |
5098 ;; ############################################################################ | |
5099 ;; Help functions | |
5100 | |
5101 (defun vhdl-outer-space (count) | |
5102 "Expand abbreviations and self-insert space(s), do indent-new-comment-line | |
5103 if in comment and past end-comment-column." | |
5104 (interactive "p") | |
5105 (if (or (and (>= (preceding-char) ?a) (<= (preceding-char) ?z)) | |
5106 (and (>= (preceding-char) ?A) (<= (preceding-char) ?Z))) | |
5107 (expand-abbrev)) | |
5108 (if (not (vhdl-in-comment-p)) | |
5109 (self-insert-command count) | |
5110 (if (< (current-column) end-comment-column) | |
5111 (self-insert-command count) | |
5112 (while (> (current-column) end-comment-column) (forward-word -1)) | |
5113 (while (> (preceding-char) ? ) (forward-word -1)) | |
5114 (delete-horizontal-space) | |
5115 (indent-new-comment-line) | |
5116 (end-of-line nil) | |
5117 (insert-char ? count) | |
5118 ))) | |
5119 | |
5120 (defun vhdl-field (prompt &optional following-string) | |
5121 "Prompt for string and insert it in buffer with optional following-string." | |
5122 (let ((opoint (point))) | |
5123 (insert "<" prompt ">") | |
5124 (let ((string (read-from-minibuffer (concat prompt ": ") "" | |
5125 vhdl-minibuffer-local-map))) | |
5126 (delete-region opoint (point)) | |
5127 (insert string (or following-string "")) | |
5128 (if vhdl-upper-case-keywords | |
5129 (vhdl-fix-case-region-1 | |
5130 opoint (point) t vhdl-93-keywords-regexp)) | |
5131 string | |
5132 ))) | |
5133 | |
5134 (defun vhdl-in-comment-p () | |
5135 "Check if point is to right of beginning comment delimiter." | |
5136 (interactive) | |
5137 (let ((opoint (point))) | |
5138 (save-excursion ; finds an unquoted comment | |
5139 (beginning-of-line) | |
5140 (re-search-forward "^\\([^\"]*\"[^\"]*\"\\)*[^\"]*--" opoint t) | |
5141 ))) | |
5142 | |
5143 (defun vhdl-in-string-p () | |
5144 "Check if point is in a string." | |
5145 (interactive) | |
5146 (let ((opoint (point))) | |
5147 (save-excursion ; preceeded by odd number of string delimiters? | |
5148 (beginning-of-line) | |
5149 (equal | |
5150 opoint | |
5151 (re-search-forward "^\\([^\"]*\"[^\"]*\"\\)*[^\"]*\"[^\"]*" opoint t)) | |
5152 ))) | |
5153 | |
5154 (defun vhdl-begin-end (list) | |
5155 "Insert a begin ... end pair with optional name after the end. | |
5156 Point is left between them." | |
5157 (let ((return) | |
5158 (name (car list)) | |
5159 (margin (cdr list))) | |
5160 (if vhdl-additional-empty-lines | |
5161 (progn | |
5162 (insert "\n") | |
5163 (indent-to (+ margin vhdl-basic-offset)))) | |
5164 (insert "\n") | |
5165 (indent-to margin) | |
5166 (vhdl-insert-keyword "BEGIN") | |
5167 (if vhdl-self-insert-comments | |
5168 (insert (and name (concat " -- " name)))) | |
5169 (insert "\n") | |
5170 (indent-to (+ margin vhdl-basic-offset)) | |
5171 (setq return (point)) | |
5172 (newline) | |
5173 (indent-to margin) | |
5174 (vhdl-insert-keyword "END") | |
5175 (insert (and name (concat " " name)) ";") | |
5176 (goto-char return) | |
5177 )) | |
5178 | |
5179 (defun vhdl-get-arg-list () | |
5180 "Read from user a procedure or function argument list." | |
5181 (insert " (") | |
5182 (let ((margin (current-column))) | |
5183 (if (not vhdl-argument-list-indent) | |
5184 (let ((opoint (point))) | |
5185 (back-to-indentation) | |
5186 (setq margin (+ (current-column) vhdl-basic-offset)) | |
5187 (goto-char opoint) | |
5188 (newline) | |
5189 (indent-to margin))) | |
5190 (let (not-empty interface) | |
5191 (setq interface (vhdl-field "[CONSTANT] [SIGNAL] [VARIABLE]")) | |
5192 (if (not (equal interface "")) | |
5193 (insert " ")) | |
5194 (while (not (string-equal (vhdl-field "[names]") "")) | |
5195 (setq not-empty t) | |
5196 (insert " : ") | |
5197 (if (not (equal (vhdl-field "[direction]") "")) | |
5198 (insert " ")) | |
5199 (vhdl-field "type" ";\n") | |
5200 (indent-to margin) | |
5201 (setq interface (vhdl-field "[CONSTANT] [SIGNAL] [VARIABLE]")) | |
5202 (if (not (equal interface "")) | |
5203 (insert " "))) | |
5204 (if not-empty | |
5205 (progn (kill-line -0) | |
5206 (delete-char -2) | |
5207 (if (not vhdl-argument-list-indent) | |
5208 (progn (insert "\n") (indent-to margin))) | |
5209 (insert ")")) | |
5210 (if vhdl-argument-list-indent | |
5211 (backward-delete-char 2) | |
5212 (kill-line -0) | |
5213 (backward-delete-char 3))) | |
5214 ; (while (string-match "[,;]$" args) | |
5215 ; (newline) | |
5216 ; (indent-to margin) (setq args (vhdl-field "next argument"))) | |
5217 ; (insert 41) ;close-paren | |
5218 ))) | |
5219 | |
5220 (defun vhdl-get-port (optional &optional no-comment) | |
5221 "Read from user a port spec argument list." | |
5222 (let ((margin (current-column)) | |
5223 (start (point))) | |
5224 (if (not vhdl-argument-list-indent) | |
5225 (let ((opoint (point))) | |
5226 (back-to-indentation) | |
5227 (setq margin (+ (current-column) vhdl-basic-offset)) | |
5228 (goto-char opoint) | |
5229 (newline) | |
5230 (indent-to margin))) | |
5231 (let ((vhdl-ports (vhdl-field "[names]"))) | |
5232 (if (string-equal vhdl-ports "") | |
5233 (if optional | |
5234 (progn (vhdl-kill-entire-line) (forward-line -1) | |
5235 (if (not vhdl-argument-list-indent) | |
5236 (progn (vhdl-kill-entire-line) (forward-line -1)))) | |
5237 (progn (undo 0) (insert " ")) | |
5238 nil ) | |
5239 (insert " : ") | |
5240 (progn | |
5241 (let ((semicolon-pos)) | |
5242 (while (not (string-equal "" vhdl-ports)) | |
5243 (vhdl-field "direction") | |
5244 (insert " ") | |
5245 (vhdl-field "type") | |
5246 (setq semicolon-pos (point)) | |
5247 (insert ";") | |
5248 (if (not no-comment) | |
5249 (vhdl-declaration-comment)) | |
5250 (newline) | |
5251 (indent-to margin) | |
5252 (setq vhdl-ports (vhdl-field "[names]" " : "))) | |
5253 (goto-char semicolon-pos) | |
5254 (if (not vhdl-argument-list-indent) | |
5255 (progn (insert "\n") (indent-to margin))) | |
5256 (insert ")") | |
5257 (forward-char 1) | |
5258 (if (= (following-char) ? ) | |
5259 (delete-char 1)) | |
5260 (forward-line 1) | |
5261 (vhdl-kill-entire-line) | |
5262 (end-of-line -0) | |
5263 (if vhdl-auto-align (vhdl-align start (point) 1)) | |
5264 t)))))) | |
5265 | |
5266 (defun vhdl-get-generic (optional &optional no-value ) | |
5267 "Read from user a generic spec argument list." | |
5268 (let ((margin (current-column)) | |
5269 (start (point))) | |
5270 (if (not vhdl-argument-list-indent) | |
5271 (let ((opoint (point))) | |
5272 (back-to-indentation) | |
5273 (setq margin (+ (current-column) vhdl-basic-offset)) | |
5274 (goto-char opoint) | |
5275 (newline) | |
5276 (indent-to margin))) | |
5277 (let ((vhdl-generic)) | |
5278 (if no-value | |
5279 (setq vhdl-generic (vhdl-field "[names]")) | |
5280 (setq vhdl-generic (vhdl-field "[name]"))) | |
5281 (if (string-equal vhdl-generic "") | |
5282 (if optional | |
5283 (progn (vhdl-kill-entire-line) (end-of-line -0) | |
5284 (if (not vhdl-argument-list-indent) | |
5285 (progn (vhdl-kill-entire-line) (end-of-line -0)))) | |
5286 (progn (undo 0) (insert " ")) | |
5287 nil ) | |
5288 (insert " : ") | |
5289 (progn | |
5290 (let ((semicolon-pos)) | |
5291 (while (not(string-equal "" vhdl-generic)) | |
5292 (vhdl-field "type") | |
5293 (if no-value | |
5294 (progn (setq semicolon-pos (point)) | |
5295 (insert ";")) | |
5296 (insert " := ") | |
5297 (if (equal (vhdl-field "[value]") "") | |
5298 (delete-char -4)) | |
5299 (setq semicolon-pos (point)) | |
5300 (insert ";") | |
5301 (vhdl-declaration-comment)) | |
5302 (newline) | |
5303 (indent-to margin) | |
5304 (if no-value | |
5305 (setq vhdl-generic (vhdl-field "[names]" " : ")) | |
5306 (setq vhdl-generic (vhdl-field "[name]" " : ")))) | |
5307 (goto-char semicolon-pos) | |
5308 (if (not vhdl-argument-list-indent) | |
5309 (progn (insert "\n") (indent-to margin))) | |
5310 (insert ")") | |
5311 (forward-char 1) | |
5312 (if (= (following-char) ? ) | |
5313 (delete-char 1)) | |
5314 (forward-line 1) | |
5315 (vhdl-kill-entire-line) | |
5316 (end-of-line -0) | |
5317 (if vhdl-auto-align (vhdl-align start (point) 1)) | |
5318 t)))))) | |
5319 | |
5320 (defun vhdl-insert-date () | |
5321 "Insert date in appropriate format." | |
5322 (interactive) | |
5323 (insert | |
5324 (cond | |
5325 ((eq vhdl-date-format 'american) (format-time-string "%m/%d/%Y" nil)) | |
5326 ((eq vhdl-date-format 'european) (format-time-string "%d.%m.%Y" nil)) | |
5327 ((eq vhdl-date-format 'scientific) (format-time-string "%Y/%m/%d" nil)) | |
5328 ))) | |
5329 | |
5330 (defun vhdl-insert-keyword (keyword) | |
5331 (insert (if vhdl-upper-case-keywords (upcase keyword) (downcase keyword))) | |
5332 ) | |
5333 | |
5334 (defun vhdl-case-keyword (keyword) | |
5335 (if vhdl-upper-case-keywords (upcase keyword) (downcase keyword)) | |
5336 ) | |
5337 | |
5338 (defun vhdl-case-word (num) | |
5339 (if vhdl-upper-case-keywords (upcase-word num) (downcase-word num)) | |
5340 ) | |
5341 | |
5342 (defun vhdl-fix-case-region-1 (beg end upper-case word-regexp &optional count) | |
5343 "Convert all words matching word-regexp in region to lower or upper case, | |
5344 depending on parameter upper-case." | |
5345 (let ((case-fold-search t) | |
5346 (case-replace nil) | |
5347 (busy-counter 0)) | |
5348 (modify-syntax-entry ?_ "w" vhdl-mode-syntax-table) | |
5349 (save-excursion | |
5350 (goto-char beg) | |
5351 (while (re-search-forward word-regexp end t) | |
5352 (or (vhdl-in-comment-p) | |
5353 (vhdl-in-string-p) | |
5354 (if upper-case | |
5355 (upcase-word -1) | |
5356 (downcase-word -1))) | |
5357 (if (and count | |
5358 (/= busy-counter (setq busy-counter | |
5359 (+ (* count 25) (/ (* 25 (- (point) beg)) (- end beg)))))) | |
5360 (message (format "Fixing case ... (%2d%s)" busy-counter "%%")))) | |
5361 (goto-char end)) | |
5362 (if (not vhdl-underscore-is-part-of-word) | |
5363 (modify-syntax-entry ?_ "_" vhdl-mode-syntax-table)) | |
5364 (message "") | |
5365 )) | |
5366 | |
5367 (defun vhdl-fix-case-region (beg end &optional arg) | |
5368 "Convert all VHDL words in region to lower or upper case, depending on | |
5369 variables vhdl-upper-case-{keywords,types,attributes,enum-values}." | |
5370 (interactive "r\nP") | |
5371 (vhdl-fix-case-region-1 | |
5372 beg end vhdl-upper-case-keywords vhdl-93-keywords-regexp 0) | |
5373 (vhdl-fix-case-region-1 | |
5374 beg end vhdl-upper-case-types vhdl-93-types-regexp 1) | |
5375 (vhdl-fix-case-region-1 | |
5376 beg end vhdl-upper-case-attributes vhdl-93-attributes-regexp 2) | |
5377 (vhdl-fix-case-region-1 | |
5378 beg end vhdl-upper-case-enum-values vhdl-93-enum-values-regexp 3) | |
5379 ) | |
5380 | |
5381 (defun vhdl-fix-case-buffer () | |
5382 "Convert all VHDL words in buffer to lower or upper case, depending on | |
5383 variables vhdl-upper-case-{keywords,types,attributes,enum-values}." | |
5384 (interactive) | |
5385 (vhdl-fix-case-region (point-min) (point-max)) | |
5386 ) | |
5387 | |
5388 (defun vhdl-minibuffer-tab (&optional prefix-arg) | |
5389 "If preceeding character is part of a word then dabbrev-expand, | |
5390 else if right of non whitespace on line then tab-to-tab-stop, | |
5391 else indent line in proper way for current major mode | |
5392 (used for word completion in VHDL minibuffer)." | |
5393 (interactive "P") | |
5394 (cond ((= (char-syntax (preceding-char)) ?w) | |
5395 (let ((case-fold-search nil)) (dabbrev-expand prefix-arg))) | |
5396 ((> (current-column) (current-indentation)) | |
5397 (tab-to-tab-stop)) | |
5398 (t | |
5399 (if (eq indent-line-function 'indent-to-left-margin) | |
5400 (insert-tab prefix-arg) | |
5401 (if prefix-arg | |
5402 (funcall indent-line-function prefix-arg) | |
5403 (funcall indent-line-function)))))) | |
5404 | |
5405 (defun vhdl-help () | |
5406 "Display help information in '*Help*' buffer ." | |
5407 (interactive) | |
5408 (with-output-to-temp-buffer "*Help*" | |
5409 (princ mode-name) | |
5410 (princ " mode:\n") | |
5411 (princ (documentation major-mode)) | |
5412 (save-excursion | |
5413 (set-buffer standard-output) | |
5414 (help-mode)) | |
5415 (print-help-return-message))) | |
5416 | |
5417 (defun vhdl-current-line () | |
5418 "Return the line number of the line containing point." | |
5419 (save-restriction | |
5420 (widen) | |
5421 (save-excursion | |
5422 (beginning-of-line) | |
5423 (1+ (count-lines 1 (point))))) | |
5424 ) | |
5425 | |
5426 (defun vhdl-kill-entire-line () | |
5427 "Delete entire line." | |
5428 (interactive) | |
5429 (end-of-line) | |
5430 (kill-line -0) | |
5431 (delete-char 1) | |
5432 ) | |
5433 | |
5434 (defun vhdl-open-line () | |
5435 "Open a new line and indent." | |
5436 (interactive) | |
5437 (end-of-line) | |
5438 (newline-and-indent) | |
5439 ) | |
5440 | |
5441 (defun vhdl-kill-line () | |
5442 "Kill current line." | |
5443 (interactive) | |
5444 (vhdl-kill-entire-line) | |
5445 ) | |
5446 | |
5447 (defun vhdl-character-to-event-hack (char) | |
5448 (if (memq 'XEmacs vhdl-emacs-features) | |
5449 (character-to-event char) | |
5450 char)) | |
5451 | |
5452 ;; ############################################################################ | |
5453 ;; Abbrev hooks | |
5454 | |
5455 (defun vhdl-electric-mode () | |
5456 "Toggle VHDL Electric mode." | |
5457 (interactive) | |
5458 (setq vhdl-electric-mode (not vhdl-electric-mode)) | |
5459 (setq mode-name (if vhdl-electric-mode "Electric VHDL" "VHDL")) | |
5460 (force-mode-line-update) | |
5461 ) | |
5462 | |
5463 (defun vhdl-stutter-mode () | |
5464 "Toggle VHDL Stuttering mode." | |
5465 (interactive) | |
5466 (setq vhdl-stutter-mode (not vhdl-stutter-mode)) | |
5467 ) | |
5468 | |
5469 (defun vhdl-hooked-abbrev (fun) | |
5470 "Do function, if syntax says abbrev is a keyword, invoked by hooked abbrev, | |
5471 but not if inside a comment or quote)" | |
5472 (if (or (vhdl-in-comment-p) | |
5473 (vhdl-in-string-p) | |
5474 (save-excursion (forward-word -1) (looking-at "end"))) | |
5475 (progn | |
5476 (insert " ") | |
5477 (unexpand-abbrev) | |
5478 (delete-char -1)) | |
5479 (if (not vhdl-electric-mode) | |
5480 (progn | |
5481 (insert " ") | |
5482 (unexpand-abbrev) | |
5483 (backward-word 1) | |
5484 (vhdl-case-word 1) | |
5485 (delete-char 1) | |
5486 ) | |
5487 (let ((invoke-char last-command-char) (abbrev-mode -1)) | |
5488 (funcall fun) | |
5489 (if (= invoke-char ?-) (setq abbrev-start-location (point))) | |
5490 ;; delete CR which is still in event queue | |
5491 (if (memq 'XEmacs vhdl-emacs-features) | |
5492 (enqueue-eval-event 'delete-char -1) | |
5493 (setq unread-command-events ; push back a delete char | |
5494 (list (vhdl-character-to-event-hack ?\177)))) | |
5495 )))) | |
5496 | |
5497 (defun vhdl-alias-hook () "hooked version of vhdl-alias." | |
5498 (vhdl-hooked-abbrev 'vhdl-alias)) | |
5499 (defun vhdl-architecture-hook () "hooked version of vhdl-architecture." | |
5500 (vhdl-hooked-abbrev 'vhdl-architecture)) | |
5501 (defun vhdl-array-hook () "hooked version of vhdl-array." | |
5502 (vhdl-hooked-abbrev 'vhdl-array)) | |
5503 (defun vhdl-assert-hook () "hooked version of vhdl-assert." | |
5504 (vhdl-hooked-abbrev 'vhdl-assert)) | |
5505 (defun vhdl-attribute-hook () "hooked version of vhdl-attribute." | |
5506 (vhdl-hooked-abbrev 'vhdl-attribute)) | |
5507 (defun vhdl-block-hook () "hooked version of vhdl-block." | |
5508 (vhdl-hooked-abbrev 'vhdl-block)) | |
5509 (defun vhdl-case-hook () "hooked version of vhdl-case." | |
5510 (vhdl-hooked-abbrev 'vhdl-case)) | |
5511 (defun vhdl-component-hook () "hooked version of vhdl-component." | |
5512 (vhdl-hooked-abbrev 'vhdl-component)) | |
5513 (defun vhdl-component-instance-hook () | |
5514 "hooked version of vhdl-component-instance." | |
5515 (vhdl-hooked-abbrev 'vhdl-component-instance)) | |
5516 (defun vhdl-concurrent-signal-assignment-hook () | |
5517 "hooked version of vhdl-concurrent-signal-assignment." | |
5518 (vhdl-hooked-abbrev 'vhdl-concurrent-signal-assignment)) | |
5519 (defun vhdl-configuration-hook () | |
5520 "hooked version of vhdl-configuration." | |
5521 (vhdl-hooked-abbrev 'vhdl-configuration)) | |
5522 (defun vhdl-constant-hook () "hooked version of vhdl-constant." | |
5523 (vhdl-hooked-abbrev 'vhdl-constant)) | |
5524 (defun vhdl-disconnect-hook () "hooked version of vhdl-disconnect." | |
5525 (vhdl-hooked-abbrev 'vhdl-disconnect)) | |
5526 (defun vhdl-display-comment-hook () "hooked version of vhdl-display-comment." | |
5527 (vhdl-hooked-abbrev 'vhdl-display-comment)) | |
5528 (defun vhdl-else-hook () "hooked version of vhdl-else." | |
5529 (vhdl-hooked-abbrev 'vhdl-else)) | |
5530 (defun vhdl-elsif-hook () "hooked version of vhdl-elsif." | |
5531 (vhdl-hooked-abbrev 'vhdl-elsif)) | |
5532 (defun vhdl-entity-hook () "hooked version of vhdl-entity." | |
5533 (vhdl-hooked-abbrev 'vhdl-entity)) | |
5534 (defun vhdl-exit-hook () "hooked version of vhdl-exit." | |
5535 (vhdl-hooked-abbrev 'vhdl-exit)) | |
5536 (defun vhdl-for-hook () "hooked version of vhdl-for." | |
5537 (vhdl-hooked-abbrev 'vhdl-for)) | |
5538 (defun vhdl-function-hook () "hooked version of vhdl-function." | |
5539 (vhdl-hooked-abbrev 'vhdl-function)) | |
5540 (defun vhdl-generate-hook () "hooked version of vhdl-generate." | |
5541 (vhdl-hooked-abbrev 'vhdl-generate)) | |
5542 (defun vhdl-generic-hook () "hooked version of vhdl-generic." | |
5543 (vhdl-hooked-abbrev 'vhdl-generic)) | |
5544 (defun vhdl-library-hook () "hooked version of vhdl-library." | |
5545 (vhdl-hooked-abbrev 'vhdl-library)) | |
5546 (defun vhdl-header-hook () "hooked version of vhdl-header." | |
5547 (vhdl-hooked-abbrev 'vhdl-header)) | |
5548 (defun vhdl-if-hook () "hooked version of vhdl-if." | |
5549 (vhdl-hooked-abbrev 'vhdl-if)) | |
5550 (defun vhdl-loop-hook () "hooked version of vhdl-loop." | |
5551 (vhdl-hooked-abbrev 'vhdl-loop)) | |
5552 (defun vhdl-map-hook () "hooked version of vhdl-map." | |
5553 (vhdl-hooked-abbrev 'vhdl-map)) | |
5554 (defun vhdl-modify-hook () "hooked version of vhdl-modify." | |
5555 (vhdl-hooked-abbrev 'vhdl-modify)) | |
5556 (defun vhdl-next-hook () "hooked version of vhdl-next." | |
5557 (vhdl-hooked-abbrev 'vhdl-next)) | |
5558 (defun vhdl-package-hook () "hooked version of vhdl-package." | |
5559 (vhdl-hooked-abbrev 'vhdl-package)) | |
5560 (defun vhdl-port-hook () "hooked version of vhdl-port." | |
5561 (vhdl-hooked-abbrev 'vhdl-port)) | |
5562 (defun vhdl-procedure-hook () "hooked version of vhdl-procedure." | |
5563 (vhdl-hooked-abbrev 'vhdl-procedure)) | |
5564 (defun vhdl-process-hook () "hooked version of vhdl-process." | |
5565 (vhdl-hooked-abbrev 'vhdl-process)) | |
5566 (defun vhdl-record-hook () "hooked version of vhdl-record." | |
5567 (vhdl-hooked-abbrev 'vhdl-record)) | |
5568 (defun vhdl-return-hook () "hooked version of vhdl-return-value." | |
5569 (vhdl-hooked-abbrev 'vhdl-return-value)) | |
5570 (defun vhdl-selected-signal-assignment-hook () | |
5571 "hooked version of vhdl-selected-signal-assignment." | |
5572 (vhdl-hooked-abbrev 'vhdl-selected-signal-assignment)) | |
5573 (defun vhdl-signal-hook () "hooked version of vhdl-signal." | |
5574 (vhdl-hooked-abbrev 'vhdl-signal)) | |
5575 (defun vhdl-subtype-hook () "hooked version of vhdl-subtype." | |
5576 (vhdl-hooked-abbrev 'vhdl-subtype)) | |
5577 (defun vhdl-type-hook () "hooked version of vhdl-type." | |
5578 (vhdl-hooked-abbrev 'vhdl-type)) | |
5579 (defun vhdl-use-hook () "hooked version of vhdl-use." | |
5580 (vhdl-hooked-abbrev 'vhdl-use)) | |
5581 (defun vhdl-variable-hook () "hooked version of vhdl-variable." | |
5582 (vhdl-hooked-abbrev 'vhdl-variable)) | |
5583 (defun vhdl-wait-hook () "hooked version of vhdl-wait." | |
5584 (vhdl-hooked-abbrev 'vhdl-wait)) | |
5585 (defun vhdl-when-hook () "hooked version of vhdl-when." | |
5586 (vhdl-hooked-abbrev 'vhdl-when)) | |
5587 (defun vhdl-while-loop-hook () "hooked version of vhdl-while-loop." | |
5588 (vhdl-hooked-abbrev 'vhdl-while-loop)) | |
5589 (defun vhdl-and-hook () "hooked version of vhdl-and." | |
5590 (vhdl-hooked-abbrev 'vhdl-and)) | |
5591 (defun vhdl-or-hook () "hooked version of vhdl-or." | |
5592 (vhdl-hooked-abbrev 'vhdl-or)) | |
5593 (defun vhdl-nand-hook () "hooked version of vhdl-nand." | |
5594 (vhdl-hooked-abbrev 'vhdl-nand)) | |
5595 (defun vhdl-nor-hook () "hooked version of vhdl-nor." | |
5596 (vhdl-hooked-abbrev 'vhdl-nor)) | |
5597 (defun vhdl-xor-hook () "hooked version of vhdl-xor." | |
5598 (vhdl-hooked-abbrev 'vhdl-xor)) | |
5599 (defun vhdl-xnor-hook () "hooked version of vhdl-xnor." | |
5600 (vhdl-hooked-abbrev 'vhdl-xnor)) | |
5601 (defun vhdl-not-hook () "hooked version of vhdl-not." | |
5602 (vhdl-hooked-abbrev 'vhdl-not)) | |
5603 | |
5604 (defun vhdl-default-hook () "hooked version of vhdl-default." | |
5605 (vhdl-hooked-abbrev 'vhdl-default)) | |
5606 (defun vhdl-default-indent-hook () "hooked version of vhdl-default-indent." | |
5607 (vhdl-hooked-abbrev 'vhdl-default-indent)) | |
5608 | |
5609 | |
5610 ;; ############################################################################ | |
5611 ;; Font locking | |
5612 ;; ############################################################################ | |
5613 ;; (using `font-lock.el') | |
5614 | |
5615 ;; ############################################################################ | |
5616 ;; Syntax definitions | |
5617 | |
5618 (defvar vhdl-font-lock-keywords nil | |
5619 "Regular expressions to highlight in VHDL Mode.") | |
5620 | |
5621 (defconst vhdl-font-lock-keywords-0 | |
5622 (list | |
5623 ;; highlight template prompts | |
5624 '("\\(^\\|[ (.\t]\\)\\(<[^ =].*[^ =]>\\)\\([ .]\\|$\\)" | |
5625 2 vhdl-font-lock-prompt-face) | |
5626 | |
5627 ;; highlight character literals | |
5628 '("'\\(.\\)'" 1 'font-lock-string-face) | |
5629 ) | |
5630 "For consideration as a value of `vhdl-font-lock-keywords'. | |
5631 This does highlighting of template prompts and character literals.") | |
5632 | |
5633 (defconst vhdl-font-lock-keywords-1 | |
5634 (list | |
5635 ;; highlight names of units, subprograms, and components when declared | |
5636 (list | |
5637 (concat | |
5638 "^\\s-*\\(" | |
5639 "architecture\\|configuration\\|entity\\|package\\(\\s-+body\\|\\)\\|" | |
5640 "function\\|procedure\\|component" | |
5641 "\\)\\s-+\\(\\w+\\)") | |
5642 3 'font-lock-function-name-face) | |
5643 | |
5644 ;; highlight labels of common constructs | |
5645 (list | |
5646 (concat | |
5647 "^\\s-*\\(\\w+\\)\\s-*:\\(\\s-\\|\n\\)*\\(" | |
5648 "assert\\|block\\|case\\|exit\\|for\\|if\\|loop\\|" | |
5649 "next\\|null\\|process\\| with\\|while\\|" | |
5650 "\\w+\\(\\s-\\|\n\\)+\\(generic\\|port\\)\\s-+map" | |
5651 "\\)\\>") | |
5652 1 'font-lock-function-name-face) | |
5653 | |
5654 ;; highlight entity names of architectures and configurations | |
5655 (list | |
5656 "^\\s-*\\(architecture\\|configuration\\)\\s-+\\w+\\s-+of\\s-+\\(\\w+\\)" | |
5657 2 'font-lock-function-name-face) | |
5658 | |
5659 ;; highlight names and labels at end of constructs | |
5660 (list | |
5661 (concat | |
5662 "^\\s-*end\\s-+\\(" | |
5663 "\\(block\\|case\\|component\\|for\\|generate\\|if\\|loop\\|" | |
5664 "process\\|record\\|units\\)\\>\\|" | |
5665 "\\)\\s-*\\(\\w*\\)") | |
5666 3 'font-lock-function-name-face) | |
5667 ) | |
5668 "For consideration as a value of `vhdl-font-lock-keywords'. | |
5669 This does highlighting of names and labels.") | |
5670 | |
5671 (defconst vhdl-font-lock-keywords-2 | |
5672 (list | |
5673 ;; highlight keywords, and types, standardized attributes, enumeration values | |
5674 (list (concat "'" vhdl-93-attributes-regexp) | |
5675 1 'vhdl-font-lock-attribute-face) | |
5676 (list vhdl-93-types-regexp 1 'font-lock-type-face) | |
5677 (list vhdl-93-enum-values-regexp 1 'vhdl-font-lock-value-face) | |
5678 (list vhdl-93-keywords-regexp 1 'font-lock-keyword-face) | |
5679 ) | |
5680 "For consideration as a value of `vhdl-font-lock-keywords'. | |
5681 This does highlighting of comments, keywords, and standard types.") | |
5682 | |
5683 (defconst vhdl-font-lock-keywords-3 | |
5684 (list | |
5685 ;; highlight clock signals. | |
5686 (cons vhdl-clock-signal-syntax 'vhdl-font-lock-clock-signal-face) | |
5687 (cons vhdl-reset-signal-syntax 'vhdl-font-lock-reset-signal-face) | |
5688 (cons vhdl-control-signal-syntax 'vhdl-font-lock-control-signal-face) | |
5689 (cons vhdl-data-signal-syntax 'vhdl-font-lock-data-signal-face) | |
5690 (cons vhdl-test-signal-syntax 'vhdl-font-lock-test-signal-face) | |
5691 ) | |
5692 "For consideration as a value of `vhdl-font-lock-keywords'. | |
5693 This does highlighting of signal names with specific syntax.") | |
5694 | |
5695 ;; ############################################################################ | |
5696 ;; Font and color definitions | |
5697 | |
5698 (defvar vhdl-font-lock-prompt-face 'vhdl-font-lock-prompt-face | |
5699 "Face name to use for prompts.") | |
5700 | |
5701 (defvar vhdl-font-lock-attribute-face 'vhdl-font-lock-attribute-face | |
5702 "Face name to use for attributes.") | |
5703 | |
5704 (defvar vhdl-font-lock-value-face 'vhdl-font-lock-value-face | |
5705 "Face name to use for enumeration values.") | |
5706 | |
5707 (defvar vhdl-font-lock-clock-signal-face 'vhdl-font-lock-clock-signal-face | |
5708 "Face name to use for clock signals.") | |
5709 | |
5710 (defvar vhdl-font-lock-reset-signal-face 'vhdl-font-lock-reset-signal-face | |
5711 "Face name to use for reset signals.") | |
5712 | |
5713 (defvar vhdl-font-lock-control-signal-face 'vhdl-font-lock-control-signal-face | |
5714 "Face name to use for control signals.") | |
5715 | |
5716 (defvar vhdl-font-lock-data-signal-face 'vhdl-font-lock-data-signal-face | |
5717 "Face name to use for data signals.") | |
5718 | |
5719 (defvar vhdl-font-lock-test-signal-face 'vhdl-font-lock-test-signal-face | |
5720 "Face name to use for test signals.") | |
5721 | |
5722 (defface vhdl-font-lock-prompt-face | |
5723 '((((class color) (background light)) (:foreground "Red")) | |
5724 (((class color) (background dark)) (:foreground "Red")) | |
5725 (t (:inverse-video t))) | |
5726 "Font Lock mode face used to highlight prompts." | |
5727 :group 'font-lock-highlighting-faces) | |
5728 | |
5729 (defface vhdl-font-lock-attribute-face | |
5730 '((((class color) (background light)) (:foreground "CadetBlue")) | |
5731 (((class color) (background dark)) (:foreground "CadetBlue")) | |
5732 (t (:italic t :bold t))) | |
5733 "Font Lock mode face used to highlight attributes." | |
5734 :group 'font-lock-highlighting-faces) | |
5735 | |
5736 (defface vhdl-font-lock-value-face | |
5737 '((((class color) (background light)) (:foreground "DarkGoldenrod")) | |
5738 (((class color) (background dark)) (:foreground "DarkGoldenrod")) | |
5739 (t (:italic t :bold t))) | |
5740 "Font Lock mode face used to highlight enumeration values." | |
5741 :group 'font-lock-highlighting-faces) | |
5742 | |
5743 (defface vhdl-font-lock-clock-signal-face | |
5744 '((((class color) (background light)) (:foreground "LimeGreen")) | |
5745 (((class color) (background dark)) (:foreground "LimeGreen")) | |
5746 (t ())) | |
5747 "Font Lock mode face used to highlight clock signals." | |
5748 :group 'font-lock-highlighting-faces) | |
5749 | |
5750 (defface vhdl-font-lock-reset-signal-face | |
5751 '((((class color) (background light)) (:foreground "Red")) | |
5752 (((class color) (background dark)) (:foreground "Red")) | |
5753 (t ())) | |
5754 "Font Lock mode face used to highlight reset signals." | |
5755 :group 'font-lock-highlighting-faces) | |
5756 | |
5757 (defface vhdl-font-lock-control-signal-face | |
5758 '((((class color) (background light)) (:foreground "Blue")) | |
5759 (((class color) (background dark)) (:foreground "Blue")) | |
5760 (t ())) | |
5761 "Font Lock mode face used to highlight control signals." | |
5762 :group 'font-lock-highlighting-faces) | |
5763 | |
5764 (defface vhdl-font-lock-data-signal-face | |
5765 '((((class color) (background light)) (:foreground "Black")) | |
5766 (((class color) (background dark)) (:foreground "Black")) | |
5767 (t ())) | |
5768 "Font Lock mode face used to highlight data signals." | |
5769 :group 'font-lock-highlighting-faces) | |
5770 | |
5771 (defface vhdl-font-lock-test-signal-face | |
5772 '((((class color) (background light)) (:foreground "Gold")) | |
5773 (((class color) (background dark)) (:foreground "Gold")) | |
5774 (t ())) | |
5775 "Font Lock mode face used to highlight test signals." | |
5776 :group 'font-lock-highlighting-faces) | |
5777 | |
5778 ;; Custom color definitions for existing faces | |
5779 (defun vhdl-set-face-foreground () | |
5780 (set-face-foreground 'font-lock-comment-face "IndianRed") | |
5781 (set-face-foreground 'font-lock-function-name-face "MediumOrchid") | |
5782 (set-face-foreground 'font-lock-keyword-face "SlateBlue") | |
5783 (set-face-foreground 'font-lock-string-face "RosyBrown") | |
5784 (set-face-foreground 'font-lock-type-face "ForestGreen") | |
5785 ) | |
5786 | |
5787 (defun vhdl-set-face-grayscale () | |
5788 (interactive) | |
5789 (set-face-bold-p 'font-lock-comment-face nil) | |
5790 (set-face-inverse-video-p 'font-lock-comment-face nil) | |
5791 (set-face-italic-p 'font-lock-comment-face t) | |
5792 (set-face-underline-p 'font-lock-comment-face nil) | |
5793 | |
5794 (set-face-bold-p 'font-lock-function-name-face nil) | |
5795 (set-face-inverse-video-p 'font-lock-function-name-face nil) | |
5796 (set-face-italic-p 'font-lock-function-name-face t) | |
5797 (set-face-underline-p 'font-lock-function-name-face nil) | |
5798 | |
5799 (set-face-bold-p 'font-lock-keyword-face t) | |
5800 (set-face-inverse-video-p 'font-lock-keyword-face nil) | |
5801 (set-face-italic-p 'font-lock-keyword-face nil) | |
5802 (set-face-underline-p 'font-lock-keyword-face nil) | |
5803 | |
5804 (set-face-bold-p 'font-lock-string-face nil) | |
5805 (set-face-inverse-video-p 'font-lock-string-face nil) | |
5806 (set-face-italic-p 'font-lock-string-face nil) | |
5807 (set-face-underline-p 'font-lock-string-face t) | |
5808 | |
5809 (set-face-bold-p 'font-lock-type-face t) | |
5810 (set-face-inverse-video-p 'font-lock-type-face nil) | |
5811 (set-face-italic-p 'font-lock-type-face t) | |
5812 (set-face-underline-p 'font-lock-type-face nil) | |
5813 ) | |
5814 | |
5815 ;; ############################################################################ | |
5816 ;; Font lock initialization | |
5817 | |
5818 (defun vhdl-font-lock-init () | |
5819 "Initializes fontification." | |
5820 (setq vhdl-font-lock-keywords | |
5821 (append vhdl-font-lock-keywords-0 | |
5822 (if vhdl-highlight-names vhdl-font-lock-keywords-1) | |
5823 (if vhdl-highlight-keywords vhdl-font-lock-keywords-2) | |
5824 (if (and vhdl-highlight-signals (x-display-color-p)) | |
5825 vhdl-font-lock-keywords-3))) | |
5826 (if (x-display-color-p) | |
5827 (if (not vhdl-use-default-colors) (vhdl-set-face-foreground)) | |
5828 (if (not vhdl-use-default-faces) (vhdl-set-face-grayscale)) | |
5829 )) | |
5830 | |
5831 ;; ############################################################################ | |
5832 ;; Fontification for postscript printing | |
5833 | |
5834 (defun vhdl-ps-init () | |
5835 "Initializes face and page settings for postscript printing." | |
5836 (require 'ps-print) | |
5837 (unless (or vhdl-use-default-faces | |
5838 ps-print-color-p) | |
5839 (set (make-local-variable 'ps-bold-faces) | |
5840 '(font-lock-keyword-face | |
5841 font-lock-type-face | |
5842 vhdl-font-lock-attribute-face | |
5843 vhdl-font-lock-value-face)) | |
5844 (set (make-local-variable 'ps-italic-faces) | |
5845 '(font-lock-comment-face | |
5846 font-lock-function-name-face | |
5847 font-lock-type-face | |
5848 vhdl-font-lock-prompt-face | |
5849 vhdl-font-lock-attribute-face | |
5850 vhdl-font-lock-value-face)) | |
5851 (set (make-local-variable 'ps-underlined-faces) | |
5852 '(font-lock-string-face)) | |
5853 ) | |
5854 ;; define page settings, so that a line containing 79 characters (default) | |
5855 ;; fits into one column | |
5856 (if vhdl-print-two-column | |
5857 (progn | |
5858 (set (make-local-variable 'ps-landscape-mode) t) | |
5859 (set (make-local-variable 'ps-number-of-columns) 2) | |
5860 (set (make-local-variable 'ps-font-size) 7.0) | |
5861 (set (make-local-variable 'ps-header-title-font-size) 10.0) | |
5862 (set (make-local-variable 'ps-header-font-size) 9.0) | |
5863 (set (make-local-variable 'ps-header-offset) 12.0) | |
5864 (if (eq ps-paper-type 'letter) | |
5865 (progn | |
5866 (set (make-local-variable 'ps-inter-column) 40.0) | |
5867 (set (make-local-variable 'ps-left-margin) 40.0) | |
5868 (set (make-local-variable 'ps-right-margin) 40.0) | |
5869 ))))) | |
5870 | |
5871 | |
5872 ;; ############################################################################ | |
5873 ;; Hideshow | |
5874 ;; ############################################################################ | |
5875 ;; (using `hideshow.el') | |
5876 | |
5877 (defun vhdl-forward-sexp-function (&optional count) | |
5878 "Find begin and end of VHDL process or block (for hideshow)." | |
5879 (interactive "p") | |
5880 (let (name | |
5881 (case-fold-search t)) | |
5882 (end-of-line) | |
5883 (if (< count 0) | |
5884 (re-search-backward "\\s-*\\(\\w\\|\\s_\\)+\\s-*:\\s-*\\(process\\|block\\)\\>" nil t) | |
5885 (re-search-forward "\\s-*\\<end\\s-+\\(process\\|block\\)\\>" nil t) | |
5886 ))) | |
5887 | |
21653
e95a88dc6110
*** empty log message ***
Dan Nicolaescu <done@ece.arizona.edu>
parents:
21651
diff
changeset
|
5888 ;; Not needed `hs-special-modes-alist' is autoloaded. |
e95a88dc6110
*** empty log message ***
Dan Nicolaescu <done@ece.arizona.edu>
parents:
21651
diff
changeset
|
5889 ;(require 'hideshow) |
20665 | 5890 |
5891 (unless (assq 'vhdl-mode hs-special-modes-alist) | |
5892 (setq hs-special-modes-alist | |
5893 (cons | |
5894 '(vhdl-mode | |
5895 "\\s-*\\(\\w\\|\\s_\\)+\\s-*:\\s-*\\(process\\|PROCESS\\|block\\|BLOCK\\)\\>" | |
5896 "\\s-*\\<\\(end\\|END\\)\\s-+\\(process\\|PROCESS\\|block\\|BLOCK\\)\\>" | |
5897 "-- " | |
5898 vhdl-forward-sexp-function) | |
5899 hs-special-modes-alist))) | |
5900 | |
5901 | |
5902 ;; ############################################################################ | |
5903 ;; Compilation | |
5904 ;; ############################################################################ | |
5905 ;; (using `compile.el') | |
5906 | |
5907 (defvar vhdl-compile-commands | |
5908 '( | |
5909 (cadence "cv -file" nil) | |
5910 (ikos "analyze" nil) | |
5911 (quickhdl "qvhcom" nil) | |
5912 (synopsys "vhdlan" nil) | |
5913 (vantage "analyze -libfile vsslib.ini -src" nil) | |
5914 (viewlogic "analyze -libfile vsslib.ini -src" nil) | |
5915 (v-system "vcom" "vmake > Makefile") | |
5916 ) | |
5917 "Commands to be called in the shell for compilation (syntax analysis) of a | |
5918 single buffer and `Makefile' generation for different tools. First item is tool | |
5919 identifier, second item is shell command for compilation, and third item is | |
5920 shell command for `Makefile' generation. A tool is specified by assigning a | |
5921 tool identifier to variable `vhdl-compiler'.") | |
5922 | |
5923 (defvar vhdl-compilation-error-regexp-alist | |
5924 (list | |
5925 ;; Cadence Design Systems: cv -file test.vhd | |
5926 ;; duluth: *E,430 (test.vhd,13): identifier (POSITIV) is not declared | |
5927 '("duluth: \\*E,[0-9]+ (\\(.+\\),\\([0-9]+\\)):" 1 2) | |
5928 | |
5929 ;; Ikos Voyager: analyze test.vhd | |
5930 ;; E L4/C5: this library unit is inaccessible | |
5931 ; Xemacs does not support error messages without included file name | |
5932 (if (not (memq 'XEmacs vhdl-emacs-features)) | |
5933 '("E L\\([0-9]+\\)/C[0-9]+:" nil 1) | |
5934 '("E L\\([0-9]+\\)/C[0-9]+:" 2 1) | |
5935 ) | |
5936 | |
5937 ;; QuickHDL, Mentor Graphics: qvhcom test.vhd | |
5938 ;; ERROR: test.vhd(24): near "dnd": expecting: END | |
5939 '("ERROR: \\(.+\\)(\\([0-9]+\\)):" 1 2) | |
5940 | |
5941 ;; Synopsys, VHDL Analyzer: vhdlan test.vhd | |
5942 ;; **Error: vhdlan,703 test.vhd(22): OTHERS is not legal in this context. | |
5943 '("\\*\\*Error: vhdlan,[0-9]+ \\(.+\\)(\\([0-9]+\\)):" 1 2) | |
5944 | |
5945 ;; Vantage Analysis Systems: analyze -libfile vsslib.ini -src test.vhd | |
5946 ;; **Error: LINE 499 *** No aggregate value is valid in this context. | |
5947 ; Xemacs does not support error messages without included file name | |
5948 (if (not (memq 'XEmacs vhdl-emacs-features)) | |
5949 '("\\*\\*Error: LINE \\([0-9]+\\) \\*\\*\\*" nil 1) | |
5950 '("\\*\\*Error: LINE \\([0-9]+\\) \\*\\*\\*" 2 1) | |
5951 ) | |
5952 | |
5953 ;; Viewlogic: analyze -libfile vsslib.ini -src test.vhd | |
5954 ;; **Error: LINE 499 *** No aggregate value is valid in this context. | |
5955 ;; same regexp as for Vantage | |
5956 | |
5957 ;; V-System, Model Technology: vcom test.vhd | |
5958 ;; ERROR: test.vhd(14): Unknown identifier: positiv | |
5959 ;; same regexp as for QuickHDL | |
5960 | |
5961 ) "Alist that specifies how to match errors in VHDL compiler output.") | |
5962 | |
5963 (defvar compilation-file-regexp-alist | |
5964 '( | |
5965 ;; Ikos Voyager: analyze -libfile vsslib.ini -src test.vhd | |
5966 ;; analyze sdrctl.vhd | |
5967 ("^analyze +\\(.+ +\\)*\\(.+\\)$" 2) | |
5968 | |
5969 ;; Vantage Analysis Systems: analyze -libfile vsslib.ini -src test.vhd | |
5970 ;; Compiling "pcu.vhd" line 1... | |
5971 (" *Compiling \"\\(.+\\)\" " 1) | |
5972 | |
5973 ;; Viewlogic: analyze -libfile vsslib.ini -src test.vhd | |
5974 ;; Compiling "pcu.vhd" line 1... | |
5975 ;; same regexp as for Vantage | |
5976 | |
5977 ) "Alist specifying how to match lines that indicate a new current file. | |
5978 Used for compilers with no file name in the error messages.") | |
5979 | |
5980 (defun vhdl-compile () | |
5981 "Compile current buffer using the VHDL compiler specified in | |
5982 `vhdl-compiler'." | |
5983 (interactive) | |
5984 (let ((command-list vhdl-compile-commands) | |
5985 command) | |
5986 (while command-list | |
5987 (if (eq vhdl-compiler (car (car command-list))) | |
5988 (setq command (car (cdr (car command-list))))) | |
5989 (setq command-list (cdr command-list))) | |
5990 (if command | |
5991 (compile (concat command " " vhdl-compiler-options | |
5992 (if (not (string-equal vhdl-compiler-options "")) " ") | |
5993 (file-name-nondirectory (buffer-file-name))))))) | |
5994 | |
5995 (defun vhdl-make () | |
5996 "Call make command for compilation of all updated source files | |
5997 (requires `Makefile')." | |
5998 (interactive) | |
5999 (compile "make")) | |
6000 | |
6001 (defun vhdl-generate-makefile () | |
6002 "Generate new `Makefile'." | |
6003 (interactive) | |
6004 (let ((command-list vhdl-compile-commands) | |
6005 command) | |
6006 (while command-list | |
6007 (if (eq vhdl-compiler (car (car command-list))) | |
6008 (setq command (car (cdr (cdr (car command-list)))))) | |
6009 (setq command-list (cdr command-list))) | |
6010 (if command | |
6011 (compile command ) | |
6012 (message (format "Not implemented for `%s'!" vhdl-compiler)) | |
6013 (beep)))) | |
6014 | |
6015 | |
6016 ;; ############################################################################ | |
6017 ;; Bug reports | |
6018 ;; ############################################################################ | |
6019 ;; (using `reporter.el') | |
6020 | |
6021 (defconst vhdl-version "3.19" | |
6022 "VHDL Mode version number.") | |
6023 | |
6024 (defconst vhdl-mode-help-address "vhdl-mode@geocities.com" | |
6025 "Address for VHDL Mode bug reports.") | |
6026 | |
6027 (defun vhdl-version () | |
6028 "Echo the current version of VHDL Mode in the minibuffer." | |
6029 (interactive) | |
6030 (message "Using VHDL Mode version %s" vhdl-version) | |
6031 (vhdl-keep-region-active)) | |
6032 | |
6033 ;; get reporter-submit-bug-report when byte-compiling | |
6034 (and (fboundp 'eval-when-compile) | |
6035 (eval-when-compile | |
6036 (require 'reporter))) | |
6037 | |
6038 (defun vhdl-submit-bug-report () | |
6039 "Submit via mail a bug report on VHDL Mode." | |
6040 (interactive) | |
6041 ;; load in reporter | |
6042 (and | |
6043 (y-or-n-p "Do you want to submit a report on VHDL Mode? ") | |
6044 (require 'reporter) | |
6045 (reporter-submit-bug-report | |
6046 vhdl-mode-help-address | |
6047 (concat "VHDL Mode " vhdl-version) | |
6048 (list | |
6049 ;; report all important variables | |
6050 'vhdl-basic-offset | |
6051 'vhdl-offsets-alist | |
6052 'vhdl-comment-only-line-offset | |
6053 'tab-width | |
6054 'vhdl-electric-mode | |
6055 'vhdl-stutter-mode | |
6056 'vhdl-indent-tabs-mode | |
6057 'vhdl-compiler | |
6058 'vhdl-compiler-options | |
6059 'vhdl-upper-case-keywords | |
6060 'vhdl-upper-case-types | |
6061 'vhdl-upper-case-attributes | |
6062 'vhdl-upper-case-enum-values | |
6063 'vhdl-auto-align | |
6064 'vhdl-additional-empty-lines | |
6065 'vhdl-argument-list-indent | |
6066 'vhdl-conditions-in-parenthesis | |
6067 'vhdl-date-format | |
6068 'vhdl-header-file | |
6069 'vhdl-modify-date-prefix-string | |
6070 'vhdl-zero-string | |
6071 'vhdl-one-string | |
6072 'vhdl-self-insert-comments | |
6073 'vhdl-prompt-for-comments | |
6074 'vhdl-comment-column | |
6075 'vhdl-end-comment-column | |
6076 'vhdl-highlight-names | |
6077 'vhdl-highlight-keywords | |
6078 'vhdl-highlight-signals | |
6079 'vhdl-highlight-case-sensitive | |
6080 'vhdl-use-default-colors | |
6081 'vhdl-use-default-faces | |
6082 'vhdl-clock-signal-syntax | |
6083 'vhdl-reset-signal-syntax | |
6084 'vhdl-control-signal-syntax | |
6085 'vhdl-data-signal-syntax | |
6086 'vhdl-test-signal-syntax | |
6087 'vhdl-source-file-menu | |
6088 'vhdl-index-menu | |
6089 'vhdl-hideshow-menu | |
6090 'vhdl-print-two-column | |
6091 'vhdl-intelligent-tab | |
6092 'vhdl-template-key-binding-prefix | |
6093 'vhdl-word-completion-in-minibuffer | |
6094 'vhdl-underscore-is-part-of-word | |
6095 'vhdl-mode-hook | |
6096 ) | |
6097 (function | |
6098 (lambda () | |
6099 (insert | |
6100 (if vhdl-special-indent-hook | |
6101 (concat "\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" | |
6102 "vhdl-special-indent-hook is set to '" | |
6103 (format "%s" vhdl-special-indent-hook) | |
6104 ".\nPerhaps this is your problem?\n" | |
6105 "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n\n") | |
6106 "\n") | |
6107 (format "vhdl-emacs-features: %s\n" vhdl-emacs-features) | |
6108 ))) | |
6109 nil | |
6110 "Dear VHDL Mode maintainers," | |
6111 ))) | |
6112 | |
6113 | |
6114 ;; ############################################################################ | |
6115 | |
6116 (provide 'vhdl-mode) | |
6117 | |
6118 ;;; vhdl-mode.el ends here |