mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-12-17 10:06:13 +00:00
6117 lines
207 KiB
EmacsLisp
6117 lines
207 KiB
EmacsLisp
;;; vhdl-mode.el --- major mode for editing VHDL code
|
|
|
|
;; Copyright (C) 1992, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
|
|
|
|
;; Authors: Reto Zimmermann <mailto:Reto.Zimmermann@iaeth.ch>
|
|
;; <http://www.iis.ee.ethz.ch/~zimmi/>
|
|
;; Rodney J. Whitby <mailto:rwhitby@geocities.com>
|
|
;; <http://www.geocities.com/SiliconValley/Park/8287/>
|
|
;; Maintainer: vhdl-mode@geocities.com
|
|
;; Maintainers' Version: 3.19
|
|
;; Keywords: languages vhdl
|
|
|
|
;; This file is part of GNU Emacs.
|
|
|
|
;; GNU Emacs is free software; you can redistribute it and/or modify
|
|
;; it under the terms of the GNU General Public License as published by
|
|
;; the Free Software Foundation; either version 2, or (at your option)
|
|
;; any later version.
|
|
|
|
;; GNU Emacs is distributed in the hope that it will be useful,
|
|
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
;; GNU General Public License for more details.
|
|
|
|
;; You should have received a copy of the GNU General Public License
|
|
;; along with GNU Emacs; see the file COPYING. If not, write to the
|
|
;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
;; Boston, MA 02111-1307, USA.
|
|
|
|
;; ############################################################################
|
|
;;; Commentary:
|
|
;; ############################################################################
|
|
|
|
;; This package provides an Emacs major mode for editing VHDL code.
|
|
;; It includes the following features:
|
|
|
|
;; - Highlighting of VHDL syntax
|
|
;; - Indentation based on versatile syntax analysis
|
|
;; - Template insertion (electrification) for most VHDL constructs
|
|
;; - Insertion of customizable VHDL file headers
|
|
;; - Word completion (dynamic abbreviations)
|
|
;; - Menu containing all VHDL Mode commands
|
|
;; - Index menu (jump index to main units and blocks in a file)
|
|
;; - Source file menu (menu of all source files in current directory)
|
|
;; - Source file compilation (syntax analysis)
|
|
;; - Postscript printing with fontification
|
|
;; - Lower and upper case keywords
|
|
;; - Hiding blocks of code
|
|
;; - Alignment functions
|
|
;; - Easy customization
|
|
;; - Works under GNU Emacs and XEmacs
|
|
|
|
;; ############################################################################
|
|
;; Usage
|
|
;; ############################################################################
|
|
|
|
;; see below (comment in vhdl-mode function) or type `C-c C-h' in Emacs.
|
|
|
|
;; ############################################################################
|
|
;; Emacs Versions
|
|
;; ############################################################################
|
|
|
|
;; - Emacs 20
|
|
;; - XEmacs 19.15
|
|
;; - This version does not support Emacs 19 (use VHDL Mode 3.10 instead)
|
|
|
|
|
|
;; ############################################################################
|
|
;; Acknowledgements
|
|
;; ############################################################################
|
|
|
|
;; Electrification ideas by Bob Pack <rlpst@cislabs.pitt.edu>
|
|
;; and Steve Grout
|
|
|
|
;; Fontification approach suggested by Ken Wood <ken@eda.com.au>
|
|
;; Source file menu suggested by Michael Laajanen <mila@enea.se>
|
|
;; Ideas about alignment from John Wiegley <johnw@borland.com>
|
|
|
|
;; Many thanks to all the users who sent me bug reports and enhancement
|
|
;; requests.
|
|
;; Special thanks go to Dan Nicolaescu <done@ece.arizona.edu> for reviewing
|
|
;; the code and for his valuable hints.
|
|
|
|
;;; Code:
|
|
|
|
;; ############################################################################
|
|
;; User definable variables
|
|
;; ############################################################################
|
|
|
|
;; ############################################################################
|
|
;; Variables for customization
|
|
|
|
(defgroup vhdl nil
|
|
"Customizations for VHDL Mode."
|
|
:prefix "vhdl-"
|
|
:group 'languages)
|
|
|
|
|
|
(defgroup vhdl-mode nil
|
|
"Customizations for modes."
|
|
:group 'vhdl)
|
|
|
|
(defcustom vhdl-electric-mode t
|
|
"*If non-nil, electrification (automatic template generation) is enabled.
|
|
If nil, template generators can still be invoked through key bindings
|
|
and menu. Can be toggled by `\\[vhdl-electric-mode]'."
|
|
:type 'boolean
|
|
:group 'vhdl-mode)
|
|
|
|
(defcustom vhdl-stutter-mode t
|
|
"*If non-nil, stuttering is enabled.
|
|
Can be toggled by `\\[vhdl-stutter-mode]'."
|
|
:type 'boolean
|
|
:group 'vhdl-mode)
|
|
|
|
(defcustom vhdl-indent-tabs-mode t
|
|
"*Indentation can insert tabs if this is non-nil.
|
|
Overrides local variable `indent-tabs-mode'."
|
|
:type 'boolean
|
|
:group 'vhdl-mode)
|
|
|
|
|
|
(defgroup vhdl-compile nil
|
|
"Customizations for compilation."
|
|
:group 'vhdl)
|
|
|
|
(defcustom vhdl-compiler 'v-system
|
|
"*VHDL compiler to be used for syntax analysis.
|
|
cadence Cadence Design Systems (`cv -file')
|
|
ikos Ikos Voyager (`analyze')
|
|
quickhdl QuickHDL, Mentor Graphics (`qvhcom')
|
|
synopsys Synopsys, VHDL Analyzer (`vhdlan')
|
|
vantage Vantage Analysis Systems (`analyze -libfile vsslib.ini -src')
|
|
viewlogic Viewlogic (`analyze -libfile vsslib.ini -src')
|
|
v-system V-System, Model Technology (`vcom')
|
|
For incorporation of additional compilers, please send me their command syntax
|
|
and some example error messages."
|
|
:type '(choice
|
|
(const cadence)
|
|
(const ikos)
|
|
(const quickhdl)
|
|
(const synopsys)
|
|
(const vantage)
|
|
(const viewlogic)
|
|
(const v-system)
|
|
)
|
|
:group 'vhdl-compile)
|
|
|
|
(defcustom vhdl-compiler-options ""
|
|
"*Options to be added to the compile command."
|
|
:type 'string
|
|
:group 'vhdl-compile)
|
|
|
|
|
|
(defgroup vhdl-style nil
|
|
"Customizations for code styles."
|
|
:group 'vhdl)
|
|
|
|
(defcustom vhdl-basic-offset 4
|
|
"*Amount of basic offset used for indentation.
|
|
This value is used by + and - symbols in `vhdl-offsets-alist'."
|
|
:type 'integer
|
|
:group 'vhdl-style)
|
|
|
|
|
|
(defgroup vhdl-word-case nil
|
|
"Customizations for case of VHDL words."
|
|
:group 'vhdl-style)
|
|
|
|
(defcustom vhdl-upper-case-keywords nil
|
|
"*If non-nil, keywords are converted to upper case
|
|
when typed or by the fix case functions."
|
|
:type 'boolean
|
|
:group 'vhdl-word-case)
|
|
|
|
(defcustom vhdl-upper-case-types nil
|
|
"*If non-nil, standardized types are converted to upper case
|
|
by the fix case functions."
|
|
:type 'boolean
|
|
:group 'vhdl-word-case)
|
|
|
|
(defcustom vhdl-upper-case-attributes nil
|
|
"*If non-nil, standardized attributes are converted to upper case
|
|
by the fix case functions."
|
|
:type 'boolean
|
|
:group 'vhdl-word-case)
|
|
|
|
(defcustom vhdl-upper-case-enum-values nil
|
|
"*If non-nil, standardized enumeration values are converted to upper case
|
|
by the fix case functions."
|
|
:type 'boolean
|
|
:group 'vhdl-word-case)
|
|
|
|
|
|
(defgroup vhdl-electric nil
|
|
"Customizations for comments."
|
|
:group 'vhdl)
|
|
|
|
(defcustom vhdl-auto-align nil
|
|
"*If non-nil, some templates are automatically aligned after generation."
|
|
:type 'boolean
|
|
:group 'vhdl-electric)
|
|
|
|
(defcustom vhdl-additional-empty-lines t
|
|
"*If non-nil, additional empty lines are inserted in some templates.
|
|
This improves readability of code."
|
|
:type 'boolean
|
|
:group 'vhdl-electric)
|
|
|
|
(defcustom vhdl-argument-list-indent t
|
|
"*If non-nil, argument lists are indented relative to the opening paren.
|
|
Normal indentation is applied otherwise."
|
|
:type 'boolean
|
|
:group 'vhdl-electric)
|
|
|
|
(defcustom vhdl-conditions-in-parenthesis nil
|
|
"*If non-nil, parenthesis are placed around condition expressions."
|
|
:type 'boolean
|
|
:group 'vhdl-electric)
|
|
|
|
(defcustom vhdl-date-format 'scientific
|
|
"*Specifies date format to be used in header.
|
|
Date formats are:
|
|
american (09/17/1997)
|
|
european (17.09.1997)
|
|
scientific (1997/09/17)"
|
|
:type '(choice (const american)
|
|
(const european)
|
|
(const scientific))
|
|
:group 'vhdl-electric)
|
|
|
|
(defcustom vhdl-header-file nil
|
|
"*Pathname/filename of the file to be inserted as header.
|
|
If the header contains RCS keywords, they may be written as <RCS>Keyword<RCS>
|
|
if the header needs to be version controlled.
|
|
|
|
The following keywords for template generation are supported:
|
|
<filename> : replaced by the name of the buffer
|
|
<author> : replaced by the user name and email address
|
|
<date> : replaced by the current date
|
|
<... string> : replaced by a prompted string (... is the prompt word)
|
|
<cursor> : final cursor position
|
|
|
|
Example:
|
|
-----------------------------------------
|
|
-- Title : <title string>
|
|
-- File : <filename>
|
|
-- Author : <author>
|
|
-- Created : <date>
|
|
-- Description : <cursor>
|
|
-----------------------------------------"
|
|
:type 'string
|
|
:group 'vhdl-electric)
|
|
|
|
(defcustom vhdl-modify-date-prefix-string "-- Last modified : "
|
|
"*Prefix string of modification date in VHDL file header.
|
|
If actualization of the modification date is called (menu, `\\[vhdl-modify]'),
|
|
this string is searched and the rest of the line replaced by the current date."
|
|
:type 'string
|
|
:group 'vhdl-electric)
|
|
|
|
(defcustom vhdl-zero-string "'0'"
|
|
"*String to use for a logic zero."
|
|
:type 'string
|
|
:group 'vhdl-electric)
|
|
|
|
(defcustom vhdl-one-string "'1'"
|
|
"*String to use for a logic one."
|
|
:type 'string
|
|
:group 'vhdl-electric)
|
|
|
|
|
|
(defgroup vhdl-comment nil
|
|
"Customizations for comments."
|
|
:group 'vhdl-electric)
|
|
|
|
(defcustom vhdl-self-insert-comments t
|
|
"*If non-nil, variables templates automatically insert help comments."
|
|
:type 'boolean
|
|
:group 'vhdl-comment)
|
|
|
|
(defcustom vhdl-prompt-for-comments t
|
|
"*If non-nil, various templates prompt for user definable comments."
|
|
:type 'boolean
|
|
:group 'vhdl-comment)
|
|
|
|
(defcustom vhdl-comment-column 40
|
|
"*Column to indent right-margin comments to.
|
|
Overrides local variable `comment-column'."
|
|
:type 'integer
|
|
:group 'vhdl-comment)
|
|
|
|
(defcustom vhdl-end-comment-column 79
|
|
"*End of comment column."
|
|
:type 'integer
|
|
:group 'vhdl-comment)
|
|
|
|
(defvar end-comment-column 79
|
|
"*End of comment column.")
|
|
|
|
|
|
(defgroup vhdl-highlight nil
|
|
"Customizations for highlighting."
|
|
:group 'vhdl)
|
|
|
|
(defcustom vhdl-highlight-names t
|
|
"*If non-nil, unit names, subprogram names, and labels are highlighted."
|
|
:type 'boolean
|
|
:group 'vhdl-highlight)
|
|
|
|
(defcustom vhdl-highlight-keywords t
|
|
"*If non-nil, VHDL keywords and other predefined words are highlighted.
|
|
That is, keywords, predefined types, predefined attributes, and predefined
|
|
enumeration values are highlighted."
|
|
:type 'boolean
|
|
:group 'vhdl-highlight)
|
|
|
|
(defcustom vhdl-highlight-signals nil
|
|
"*If non-nil, signals of different classes are highlighted using colors.
|
|
Signal classes are: clock, reset, status/control, data, and test."
|
|
:type 'boolean
|
|
:group 'vhdl-highlight)
|
|
|
|
(defcustom vhdl-highlight-case-sensitive nil
|
|
"*If non-nil, case is considered for highlighting.
|
|
Possible trade-off:
|
|
non-nil also upper-case VHDL words are highlighted, but case of signal names
|
|
is not considered (may lead to highlighting of unwanted words),
|
|
nil only lower-case VHDL words are highlighted, but case of signal names
|
|
is considered.
|
|
Overrides local variable `font-lock-keywords-case-fold-search'."
|
|
:type 'boolean
|
|
:group 'vhdl-highlight)
|
|
|
|
(defcustom vhdl-use-default-colors nil
|
|
"*If non-nil, the default colors are taken for syntax highlighting.
|
|
If nil, all colors are customized in VHDL Mode for better matching with the
|
|
additional signal colors."
|
|
:type 'boolean
|
|
:group 'vhdl-highlight)
|
|
|
|
(defcustom vhdl-use-default-faces nil
|
|
"*If non-nil, the default faces are taken for syntax highlighting.
|
|
If nil, all faces are customized for better matching with the additional faces
|
|
used in VHDL Mode. This variable comes only into effect if no colors are used
|
|
for highlighting or printing (i.e. variable `ps-print-color-p' is nil)."
|
|
:type 'boolean
|
|
:group 'vhdl-highlight)
|
|
|
|
|
|
(defgroup vhdl-signal-syntax nil
|
|
"Customizations of signal syntax for highlighting."
|
|
:group 'vhdl-highlight)
|
|
|
|
(defcustom vhdl-signal-syntax-doc-string "
|
|
Must be of the form \"\\ \<\\\(...\\\)\\\>\", where ... specifies the actual syntax.
|
|
(delete this space ^ , it's only a workaround to get this doc string.)
|
|
The basic regexp elements are:
|
|
[A-Z] any upper case letter
|
|
[A-Za-z] any letter
|
|
[0-9] any digit
|
|
\\w any letter or digit (corresponds to [A-Za-z0-9])
|
|
[XY] letter \"X\" or \"Y\"
|
|
[^XY] neither letter \"X\" nor \"Y\"
|
|
x letter \"x\"
|
|
* postfix operator for matching previous regexp element any times
|
|
+ postfix operator for matching previous regexp element at least once
|
|
? postfix operator for matching previous regexp element at most once"
|
|
"Common document string used for the custom variables below. Must be
|
|
defined as custom variable due to a bug in XEmacs.")
|
|
|
|
(defcustom vhdl-clock-signal-syntax "\\<\\([A-Z]\\w*xC\\w*\\)\\>"
|
|
(concat
|
|
"*Regular expression (regexp) for syntax of clock signals."
|
|
vhdl-signal-syntax-doc-string)
|
|
:type 'regexp
|
|
:group 'vhdl-signal-syntax)
|
|
|
|
(defcustom vhdl-reset-signal-syntax "\\<\\([A-Z]\\w*xR\\w*\\)\\>"
|
|
(concat
|
|
"*Regular expression (regexp) for syntax of (asynchronous) reset signals."
|
|
vhdl-signal-syntax-doc-string)
|
|
:type 'regexp
|
|
:group 'vhdl-signal-syntax)
|
|
|
|
(defcustom vhdl-control-signal-syntax "\\<\\([A-Z]\\w*x[IS]\\w*\\)\\>"
|
|
(concat
|
|
"*Regular expression (regexp) for syntax of status/control signals."
|
|
vhdl-signal-syntax-doc-string)
|
|
:type 'regexp
|
|
:group 'vhdl-signal-syntax)
|
|
|
|
(defcustom vhdl-data-signal-syntax "\\<\\([A-Z]\\w*xD\\w*\\)\\>"
|
|
(concat
|
|
"*Regular expression (regexp) for syntax of data signals."
|
|
vhdl-signal-syntax-doc-string)
|
|
:type 'regexp
|
|
:group 'vhdl-signal-syntax)
|
|
|
|
(defcustom vhdl-test-signal-syntax "\\<\\([A-Z]\\w*xT\\w*\\)\\>"
|
|
(concat
|
|
"*Regular expression (regexp) for syntax of test signals."
|
|
vhdl-signal-syntax-doc-string)
|
|
:type 'regexp
|
|
:group 'vhdl-signal-syntax)
|
|
|
|
|
|
(defgroup vhdl-menu nil
|
|
"Customizations for menues."
|
|
:group 'vhdl)
|
|
|
|
(defcustom vhdl-source-file-menu t
|
|
"*If non-nil, a menu of all source files in the current directory is created."
|
|
:type 'boolean
|
|
:group 'vhdl-menu)
|
|
|
|
(defcustom vhdl-index-menu t
|
|
"*If non-nil, an index menu for the current source file is created."
|
|
:type 'boolean
|
|
:group 'vhdl-menu)
|
|
|
|
(defcustom vhdl-hideshow-menu (not (string-match "XEmacs" emacs-version))
|
|
"*If non-nil, hideshow menu and functionality is added.
|
|
Hideshow allows hiding code of VHDL processes and blocks.
|
|
(Does not work under XEmacs.)"
|
|
:type 'boolean
|
|
:group 'vhdl-menu)
|
|
|
|
|
|
(defgroup vhdl-print nil
|
|
"Customizations for printing."
|
|
:group 'vhdl)
|
|
|
|
(defcustom vhdl-print-two-column t
|
|
"*If non-nil, code is printed in two columns and landscape format."
|
|
:type 'boolean
|
|
:group 'vhdl-print)
|
|
|
|
|
|
(defgroup vhdl-misc nil
|
|
"Miscellaneous customizations."
|
|
:group 'vhdl)
|
|
|
|
(defcustom vhdl-intelligent-tab t
|
|
"*If non-nil, `TAB' does indentation, word completion, and tab insertion.
|
|
That is, if preceeding character is part of a word then complete word,
|
|
else if not at beginning of line then insert tab,
|
|
else if last command was a `TAB' or `RET' then dedent one step,
|
|
else indent current line (i.e. `TAB' is bound to `vhdl-tab').
|
|
If nil, TAB always indents current line (i.e. `TAB' is bound to
|
|
`vhdl-indent-line')."
|
|
:type 'boolean
|
|
:group 'vhdl-misc)
|
|
|
|
(defcustom vhdl-template-key-binding-prefix "\C-t"
|
|
"*`C-c' plus this key gives the key binding prefix for all VHDL templates.
|
|
Default key binding prefix for templates is `C-c C-t' (example: architecture
|
|
`C-c C-t a'). If you have no own `C-c LETTER' bindings, you can shorten the
|
|
template key binding prefix to `C-c' (example: architecture `C-c a') by
|
|
assigning the empty character (\"\") to this variable. The syntax to enter
|
|
control keys is \"\\C-t\"."
|
|
:type 'sexp
|
|
:group 'vhdl-misc)
|
|
|
|
(defcustom vhdl-word-completion-in-minibuffer t
|
|
"*If non-nil, word completion works in minibuffer (for template prompts)."
|
|
:type 'boolean
|
|
:group 'vhdl-misc)
|
|
|
|
(defcustom vhdl-underscore-is-part-of-word nil
|
|
"*If non-nil, the underscore character `_' is considered as part of word.
|
|
An identifier containing underscores is then treated as a single word in
|
|
select and move operations. All parts of an identifier separated by underscore
|
|
are treated as single words otherwise."
|
|
:type 'boolean
|
|
:group 'vhdl-misc)
|
|
|
|
;; ############################################################################
|
|
;; Other variables
|
|
|
|
(defvar vhdl-inhibit-startup-warnings-p nil
|
|
"*If non-nil, inhibits start up compatibility warnings.")
|
|
|
|
(defvar vhdl-strict-syntax-p nil
|
|
"*If non-nil, all syntactic symbols must be found in `vhdl-offsets-alist'.
|
|
If the syntactic symbol for a particular line does not match a symbol
|
|
in the offsets alist, an error is generated, otherwise no error is
|
|
reported and the syntactic symbol is ignored.")
|
|
|
|
(defvar vhdl-echo-syntactic-information-p nil
|
|
"*If non-nil, syntactic info is echoed when the line is indented.")
|
|
|
|
(defconst vhdl-offsets-alist-default
|
|
'((string . -1000)
|
|
(block-open . 0)
|
|
(block-close . 0)
|
|
(statement . 0)
|
|
(statement-cont . vhdl-lineup-statement-cont)
|
|
(statement-block-intro . +)
|
|
(statement-case-intro . +)
|
|
(case-alternative . +)
|
|
(comment . vhdl-lineup-comment)
|
|
(arglist-intro . +)
|
|
(arglist-cont . 0)
|
|
(arglist-cont-nonempty . vhdl-lineup-arglist)
|
|
(arglist-close . vhdl-lineup-arglist)
|
|
(entity . 0)
|
|
(configuration . 0)
|
|
(package . 0)
|
|
(architecture . 0)
|
|
(package-body . 0)
|
|
)
|
|
"Default settings for offsets of syntactic elements.
|
|
Do not change this constant! See the variable `vhdl-offsets-alist' for
|
|
more information.")
|
|
|
|
(defvar vhdl-offsets-alist (copy-alist vhdl-offsets-alist-default)
|
|
"*Association list of syntactic element symbols and indentation offsets.
|
|
As described below, each cons cell in this list has the form:
|
|
|
|
(SYNTACTIC-SYMBOL . OFFSET)
|
|
|
|
When a line is indented, vhdl-mode first determines the syntactic
|
|
context of the line by generating a list of symbols called syntactic
|
|
elements. This list can contain more than one syntactic element and
|
|
the global variable `vhdl-syntactic-context' contains the context list
|
|
for the line being indented. Each element in this list is actually a
|
|
cons cell of the syntactic symbol and a buffer position. This buffer
|
|
position is call the relative indent point for the line. Some
|
|
syntactic symbols may not have a relative indent point associated with
|
|
them.
|
|
|
|
After the syntactic context list for a line is generated, vhdl-mode
|
|
calculates the absolute indentation for the line by looking at each
|
|
syntactic element in the list. First, it compares the syntactic
|
|
element against the SYNTACTIC-SYMBOL's in `vhdl-offsets-alist'. When it
|
|
finds a match, it adds the OFFSET to the column of the relative indent
|
|
point. The sum of this calculation for each element in the syntactic
|
|
list is the absolute offset for line being indented.
|
|
|
|
If the syntactic element does not match any in the `vhdl-offsets-alist',
|
|
an error is generated if `vhdl-strict-syntax-p' is non-nil, otherwise
|
|
the element is ignored.
|
|
|
|
Actually, OFFSET can be an integer, a function, a variable, or one of
|
|
the following symbols: `+', `-', `++', or `--'. These latter
|
|
designate positive or negative multiples of `vhdl-basic-offset',
|
|
respectively: *1, *-1, *2, and *-2. If OFFSET is a function, it is
|
|
called with a single argument containing the cons of the syntactic
|
|
element symbol and the relative indent point. The function should
|
|
return an integer offset.
|
|
|
|
Here is the current list of valid syntactic element symbols:
|
|
|
|
string -- inside multi-line string
|
|
block-open -- statement block open
|
|
block-close -- statement block close
|
|
statement -- a VHDL statement
|
|
statement-cont -- a continuation of a VHDL statement
|
|
statement-block-intro -- the first line in a new statement block
|
|
statement-case-intro -- the first line in a case alternative block
|
|
case-alternative -- a case statement alternative clause
|
|
comment -- a line containing only a comment
|
|
arglist-intro -- the first line in an argument list
|
|
arglist-cont -- subsequent argument list lines when no
|
|
arguments follow on the same line as the
|
|
the arglist opening paren
|
|
arglist-cont-nonempty -- subsequent argument list lines when at
|
|
least one argument follows on the same
|
|
line as the arglist opening paren
|
|
arglist-close -- the solo close paren of an argument list
|
|
entity -- inside an entity declaration
|
|
configuration -- inside a configuration declaration
|
|
package -- inside a package declaration
|
|
architecture -- inside an architecture body
|
|
package-body -- inside a package body
|
|
")
|
|
|
|
(defvar vhdl-comment-only-line-offset 0
|
|
"*Extra offset for line which contains only the start of a comment.
|
|
Can contain an integer or a cons cell of the form:
|
|
|
|
(NON-ANCHORED-OFFSET . ANCHORED-OFFSET)
|
|
|
|
Where NON-ANCHORED-OFFSET is the amount of offset given to
|
|
non-column-zero anchored comment-only lines, and ANCHORED-OFFSET is
|
|
the amount of offset to give column-zero anchored comment-only lines.
|
|
Just an integer as value is equivalent to (<val> . 0)")
|
|
|
|
(defvar vhdl-special-indent-hook nil
|
|
"*Hook for user defined special indentation adjustments.
|
|
This hook gets called after a line is indented by the mode.")
|
|
|
|
(defvar vhdl-style-alist
|
|
'(("IEEE"
|
|
(vhdl-basic-offset . 4)
|
|
(vhdl-offsets-alist . ())
|
|
)
|
|
)
|
|
"Styles of Indentation.
|
|
Elements of this alist are of the form:
|
|
|
|
(STYLE-STRING (VARIABLE . VALUE) [(VARIABLE . VALUE) ...])
|
|
|
|
where STYLE-STRING is a short descriptive string used to select a
|
|
style, VARIABLE is any vhdl-mode variable, and VALUE is the intended
|
|
value for that variable when using the selected style.
|
|
|
|
There is one special case when VARIABLE is `vhdl-offsets-alist'. In this
|
|
case, the VALUE is a list containing elements of the form:
|
|
|
|
(SYNTACTIC-SYMBOL . VALUE)
|
|
|
|
as described in `vhdl-offsets-alist'. These are passed directly to
|
|
`vhdl-set-offset' so there is no need to set every syntactic symbol in
|
|
your style, only those that are different from the default.")
|
|
|
|
;; dynamically append the default value of most variables
|
|
(or (assoc "Default" vhdl-style-alist)
|
|
(let* ((varlist '(vhdl-inhibit-startup-warnings-p
|
|
vhdl-strict-syntax-p
|
|
vhdl-echo-syntactic-information-p
|
|
vhdl-basic-offset
|
|
vhdl-offsets-alist
|
|
vhdl-comment-only-line-offset))
|
|
(default (cons "Default"
|
|
(mapcar
|
|
(function
|
|
(lambda (var)
|
|
(cons var (symbol-value var))
|
|
))
|
|
varlist))))
|
|
(setq vhdl-style-alist (cons default vhdl-style-alist))))
|
|
|
|
(defvar vhdl-mode-hook nil
|
|
"*Hook called by `vhdl-mode'.")
|
|
|
|
|
|
;; ############################################################################
|
|
;; Emacs variant handling
|
|
;; ############################################################################
|
|
|
|
;; active regions
|
|
|
|
(defun vhdl-keep-region-active ()
|
|
;; do whatever is necessary to keep the region active in XEmacs
|
|
;; (formerly Lucid). ignore byte-compiler warnings you might see
|
|
(and (boundp 'zmacs-region-stays)
|
|
(setq zmacs-region-stays t)))
|
|
|
|
(defconst vhdl-emacs-features
|
|
(let ((major (and (boundp 'emacs-major-version)
|
|
emacs-major-version))
|
|
(minor (and (boundp 'emacs-minor-version)
|
|
emacs-minor-version))
|
|
flavor)
|
|
;; figure out version numbers if not already discovered
|
|
(and (or (not major) (not minor))
|
|
(string-match "\\([0-9]+\\).\\([0-9]+\\)" emacs-version)
|
|
(setq major (string-to-int (substring emacs-version
|
|
(match-beginning 1)
|
|
(match-end 1)))
|
|
minor (string-to-int (substring emacs-version
|
|
(match-beginning 2)
|
|
(match-end 2)))))
|
|
(if (not (and major minor))
|
|
(error "Cannot figure out the major and minor version numbers."))
|
|
;; calculate the major version
|
|
(cond
|
|
((= major 18) (setq major 'v18)) ;Emacs 18
|
|
((= major 4) (setq major 'v18)) ;Epoch 4
|
|
((= major 19) (setq major 'v19 ;Emacs 19
|
|
flavor (cond
|
|
((string-match "Win-Emacs" emacs-version)
|
|
'Win-Emacs)
|
|
((or (string-match "Lucid" emacs-version)
|
|
(string-match "XEmacs" emacs-version))
|
|
'XEmacs)
|
|
(t
|
|
t))))
|
|
((= major 20) (setq major 'v20 ;Emacs 20
|
|
flavor (cond
|
|
((string-match "Win-Emacs" emacs-version)
|
|
'Win-Emacs)
|
|
((or (string-match "Lucid" emacs-version)
|
|
(string-match "XEmacs" emacs-version))
|
|
'XEmacs)
|
|
(t
|
|
t))))
|
|
;; I don't know
|
|
(t (error "Cannot recognize major version number: %s" major)))
|
|
;; lets do some minimal sanity checking.
|
|
(if (and (or
|
|
;; Emacs 18 is brain dead
|
|
(eq major 'v18)
|
|
;; Lemacs before 19.6 had bugs
|
|
(and (eq major 'v19) (eq flavor 'XEmacs) (< minor 6))
|
|
;; Emacs 19 before 19.21 had bugs
|
|
(and (eq major 'v19) (eq flavor t) (< minor 21)))
|
|
(not vhdl-inhibit-startup-warnings-p))
|
|
(with-output-to-temp-buffer "*vhdl-mode warnings*"
|
|
(print (format
|
|
"The version of Emacs that you are running, %s,
|
|
has known bugs in its syntax.c parsing routines which will affect the
|
|
performance of vhdl-mode. You should strongly consider upgrading to the
|
|
latest available version. vhdl-mode may continue to work, after a
|
|
fashion, but strange indentation errors could be encountered."
|
|
emacs-version))))
|
|
(list major flavor))
|
|
"A list of features extant in the Emacs you are using.
|
|
There are many flavors of Emacs out there, each with different
|
|
features supporting those needed by vhdl-mode. Here's the current
|
|
supported list, along with the values for this variable:
|
|
|
|
Emacs 18/Epoch 4: (v18)
|
|
XEmacs (formerly Lucid) 19: (v19 XEmacs)
|
|
Win-Emacs 1.35: (V19 Win-Emacs)
|
|
Emacs 19: (v19 t)
|
|
Emacs 20: (v20 t).")
|
|
|
|
|
|
;; ############################################################################
|
|
;; Bindings
|
|
;; ############################################################################
|
|
|
|
;; ############################################################################
|
|
;; Key bindings
|
|
|
|
(defvar vhdl-template-map ()
|
|
"Keymap for VHDL templates.")
|
|
|
|
(if vhdl-template-map ()
|
|
(setq vhdl-template-map (make-sparse-keymap))
|
|
;; key bindings for VHDL templates
|
|
(define-key vhdl-template-map "\M-A" 'vhdl-alias)
|
|
(define-key vhdl-template-map "a" 'vhdl-architecture)
|
|
(define-key vhdl-template-map "A" 'vhdl-array)
|
|
(define-key vhdl-template-map "\M-a" 'vhdl-assert)
|
|
(define-key vhdl-template-map "b" 'vhdl-block)
|
|
(define-key vhdl-template-map "c" 'vhdl-case)
|
|
(define-key vhdl-template-map "\M-c" 'vhdl-component)
|
|
(define-key vhdl-template-map "I" 'vhdl-component-instance)
|
|
(define-key vhdl-template-map "\M-s" 'vhdl-concurrent-signal-assignment)
|
|
(define-key vhdl-template-map "\M-Cb"'vhdl-block-configuration)
|
|
(define-key vhdl-template-map "\M-Cc"'vhdl-component-configuration)
|
|
(define-key vhdl-template-map "\M-Cd"'vhdl-configuration-decl)
|
|
(define-key vhdl-template-map "\M-Cs"'vhdl-configuration-spec)
|
|
(define-key vhdl-template-map "C" 'vhdl-constant)
|
|
(define-key vhdl-template-map "d" 'vhdl-disconnect)
|
|
(define-key vhdl-template-map "\M-e" 'vhdl-else)
|
|
(define-key vhdl-template-map "E" 'vhdl-elsif)
|
|
(define-key vhdl-template-map "e" 'vhdl-entity)
|
|
(define-key vhdl-template-map "x" 'vhdl-exit)
|
|
(define-key vhdl-template-map "f" 'vhdl-for)
|
|
(define-key vhdl-template-map "F" 'vhdl-function)
|
|
(define-key vhdl-template-map "g" 'vhdl-generate)
|
|
(define-key vhdl-template-map "G" 'vhdl-generic)
|
|
(define-key vhdl-template-map "h" 'vhdl-header)
|
|
(define-key vhdl-template-map "i" 'vhdl-if)
|
|
(define-key vhdl-template-map "L" 'vhdl-library)
|
|
(define-key vhdl-template-map "l" 'vhdl-loop)
|
|
(define-key vhdl-template-map "m" 'vhdl-modify)
|
|
(define-key vhdl-template-map "M" 'vhdl-map)
|
|
(define-key vhdl-template-map "n" 'vhdl-next)
|
|
(define-key vhdl-template-map "k" 'vhdl-package)
|
|
(define-key vhdl-template-map "(" 'vhdl-paired-parens)
|
|
(define-key vhdl-template-map "\M-p" 'vhdl-port)
|
|
(define-key vhdl-template-map "p" 'vhdl-procedure)
|
|
(define-key vhdl-template-map "P" 'vhdl-process)
|
|
(define-key vhdl-template-map "R" 'vhdl-record)
|
|
(define-key vhdl-template-map "r" 'vhdl-return-value)
|
|
(define-key vhdl-template-map "\M-S" 'vhdl-selected-signal-assignment)
|
|
(define-key vhdl-template-map "s" 'vhdl-signal)
|
|
(define-key vhdl-template-map "S" 'vhdl-subtype)
|
|
(define-key vhdl-template-map "t" 'vhdl-type)
|
|
(define-key vhdl-template-map "u" 'vhdl-use)
|
|
(define-key vhdl-template-map "v" 'vhdl-variable)
|
|
(define-key vhdl-template-map "W" 'vhdl-wait)
|
|
(define-key vhdl-template-map "w" 'vhdl-while-loop)
|
|
(define-key vhdl-template-map "\M-w" 'vhdl-with)
|
|
(define-key vhdl-template-map "\M-W" 'vhdl-clocked-wait)
|
|
(define-key vhdl-template-map "Kb" 'vhdl-package-numeric-bit)
|
|
(define-key vhdl-template-map "Kn" 'vhdl-package-numeric-std)
|
|
(define-key vhdl-template-map "Ks" 'vhdl-package-std-logic-1164)
|
|
(define-key vhdl-template-map "Kt" 'vhdl-package-textio)
|
|
)
|
|
|
|
(defvar vhdl-mode-map ()
|
|
"Keymap for VHDL Mode.")
|
|
|
|
(if vhdl-mode-map ()
|
|
(setq vhdl-mode-map (make-sparse-keymap))
|
|
;; key bindings for templates
|
|
(define-key vhdl-mode-map
|
|
(concat "\C-c" vhdl-template-key-binding-prefix) vhdl-template-map)
|
|
;; standard key bindings
|
|
(define-key vhdl-mode-map "\M-a" 'vhdl-beginning-of-statement)
|
|
(define-key vhdl-mode-map "\M-e" 'vhdl-end-of-statement)
|
|
(define-key vhdl-mode-map "\M-\C-f" 'vhdl-forward-sexp)
|
|
(define-key vhdl-mode-map "\M-\C-b" 'vhdl-backward-sexp)
|
|
(define-key vhdl-mode-map "\M-\C-u" 'vhdl-backward-up-list)
|
|
;(define-key vhdl-mode-map "\M-\C-d" 'vhdl-down-list)
|
|
(define-key vhdl-mode-map "\M-\C-a" 'vhdl-beginning-of-defun)
|
|
(define-key vhdl-mode-map "\M-\C-e" 'vhdl-end-of-defun)
|
|
(define-key vhdl-mode-map "\M-\C-h" 'vhdl-mark-defun)
|
|
(define-key vhdl-mode-map "\M-\C-q" 'vhdl-indent-sexp)
|
|
(define-key vhdl-mode-map "\177" 'backward-delete-char-untabify)
|
|
(define-key vhdl-mode-map "\r" 'vhdl-return)
|
|
(if vhdl-intelligent-tab
|
|
(define-key vhdl-mode-map "\t" 'vhdl-tab)
|
|
(define-key vhdl-mode-map "\t" 'vhdl-indent-line))
|
|
(define-key vhdl-mode-map " " 'vhdl-outer-space)
|
|
;; new key bindings for VHDL Mode, with no counterpart to BOCM
|
|
(define-key vhdl-mode-map "\C-c\C-e" 'vhdl-electric-mode)
|
|
(define-key vhdl-mode-map "\C-c\C-s" 'vhdl-stutter-mode)
|
|
(define-key vhdl-mode-map "\C-c\C-u" 'vhdl-fix-case-buffer)
|
|
(define-key vhdl-mode-map "\C-c\C-f" 'font-lock-fontify-buffer)
|
|
(define-key vhdl-mode-map "\C-c\C-x" 'vhdl-show-syntactic-information)
|
|
(define-key vhdl-mode-map "\C-c\C-r" 'vhdl-regress-line)
|
|
(define-key vhdl-mode-map "\C-c\C-i" 'vhdl-indent-line)
|
|
(define-key vhdl-mode-map "\C-c\C-a" 'vhdl-align-noindent-region)
|
|
(define-key vhdl-mode-map "\C-c\M-\C-a" 'vhdl-align-comment-region)
|
|
(define-key vhdl-mode-map "\C-c\C-c" 'vhdl-comment-uncomment-region)
|
|
(define-key vhdl-mode-map "\C-c-" 'vhdl-inline-comment)
|
|
(define-key vhdl-mode-map "\C-c\M--" 'vhdl-display-comment-line)
|
|
(define-key vhdl-mode-map "\C-c\C-o" 'vhdl-open-line)
|
|
(define-key vhdl-mode-map "\C-c\C-g" 'goto-line)
|
|
(define-key vhdl-mode-map "\C-c\C-d" 'vhdl-kill-line)
|
|
(define-key vhdl-mode-map "\C-c\C-h" 'vhdl-help)
|
|
(define-key vhdl-mode-map "\C-c\C-v" 'vhdl-version)
|
|
(define-key vhdl-mode-map "\C-c\C-b" 'vhdl-submit-bug-report)
|
|
(define-key vhdl-mode-map "\C-c\C-k" 'vhdl-compile)
|
|
(define-key vhdl-mode-map "\C-c\M-\C-k" 'vhdl-make)
|
|
(define-key vhdl-mode-map "\M-\t" 'tab-to-tab-stop)
|
|
;; key bindings for stuttering
|
|
(define-key vhdl-mode-map "-" 'vhdl-stutter-mode-dash)
|
|
(define-key vhdl-mode-map "'" 'vhdl-stutter-mode-quote)
|
|
(define-key vhdl-mode-map ";" 'vhdl-stutter-mode-semicolon)
|
|
(define-key vhdl-mode-map "[" 'vhdl-stutter-mode-open-bracket)
|
|
(define-key vhdl-mode-map "]" 'vhdl-stutter-mode-close-bracket)
|
|
(define-key vhdl-mode-map "." 'vhdl-stutter-mode-period)
|
|
(define-key vhdl-mode-map "," 'vhdl-stutter-mode-comma)
|
|
(let ((c 97))
|
|
(while (< c 123) ; for little a-z
|
|
(define-key vhdl-mode-map (char-to-string c) 'vhdl-stutter-mode-caps)
|
|
(setq c (1+ c))
|
|
))
|
|
)
|
|
|
|
;; define special minibuffer keymap for enabling word completion in minibuffer
|
|
;; (useful in template generator prompts)
|
|
(defvar vhdl-minibuffer-local-map (copy-keymap minibuffer-local-map)
|
|
"Keymap for minibuffer used in VHDL Mode.")
|
|
|
|
(define-key vhdl-minibuffer-local-map "\t" 'vhdl-minibuffer-tab)
|
|
|
|
(defvar vhdl-mode-syntax-table nil
|
|
"Syntax table used in vhdl-mode buffers.")
|
|
|
|
(if vhdl-mode-syntax-table ()
|
|
(setq vhdl-mode-syntax-table (make-syntax-table))
|
|
;; DO NOT TRY TO SET _ (UNDERSCORE) TO WORD CLASS!
|
|
;; why not? (is left to the user here)
|
|
(if vhdl-underscore-is-part-of-word
|
|
(modify-syntax-entry ?_ "w" vhdl-mode-syntax-table))
|
|
(modify-syntax-entry ?\" "\"" vhdl-mode-syntax-table)
|
|
(modify-syntax-entry ?\$ "." vhdl-mode-syntax-table)
|
|
(modify-syntax-entry ?\% "." vhdl-mode-syntax-table)
|
|
(modify-syntax-entry ?\& "." vhdl-mode-syntax-table)
|
|
(modify-syntax-entry ?\' "." vhdl-mode-syntax-table)
|
|
(modify-syntax-entry ?\( "()" vhdl-mode-syntax-table)
|
|
(modify-syntax-entry ?\) ")(" vhdl-mode-syntax-table)
|
|
(modify-syntax-entry ?\* "." vhdl-mode-syntax-table)
|
|
(modify-syntax-entry ?\+ "." vhdl-mode-syntax-table)
|
|
(modify-syntax-entry ?\. "." vhdl-mode-syntax-table)
|
|
(modify-syntax-entry ?\/ "." vhdl-mode-syntax-table)
|
|
(modify-syntax-entry ?\: "." vhdl-mode-syntax-table)
|
|
(modify-syntax-entry ?\; "." vhdl-mode-syntax-table)
|
|
(modify-syntax-entry ?\< "." vhdl-mode-syntax-table)
|
|
(modify-syntax-entry ?\= "." vhdl-mode-syntax-table)
|
|
(modify-syntax-entry ?\> "." vhdl-mode-syntax-table)
|
|
(modify-syntax-entry ?\[ "(]" vhdl-mode-syntax-table)
|
|
(modify-syntax-entry ?\\ "\\" vhdl-mode-syntax-table)
|
|
(modify-syntax-entry ?\] ")[" vhdl-mode-syntax-table)
|
|
(modify-syntax-entry ?\{ "(}" vhdl-mode-syntax-table)
|
|
(modify-syntax-entry ?\| "." vhdl-mode-syntax-table)
|
|
(modify-syntax-entry ?\} "){" vhdl-mode-syntax-table)
|
|
;; add comment syntax
|
|
(modify-syntax-entry ?\- ". 12" vhdl-mode-syntax-table)
|
|
(modify-syntax-entry ?\n ">" vhdl-mode-syntax-table)
|
|
(modify-syntax-entry ?\^M ">" vhdl-mode-syntax-table))
|
|
|
|
(defvar vhdl-syntactic-context nil
|
|
"Buffer local variable containing syntactic analysis list.")
|
|
(make-variable-buffer-local 'vhdl-syntactic-context)
|
|
|
|
;; ############################################################################
|
|
;; Abbrev hook bindings
|
|
|
|
(defvar vhdl-mode-abbrev-table nil
|
|
"Abbrev table in use in vhdl-mode buffers.")
|
|
|
|
(define-abbrev-table 'vhdl-mode-abbrev-table
|
|
'(
|
|
("--" "" vhdl-display-comment-hook 0)
|
|
("abs" "" vhdl-default-hook 0)
|
|
("access" "" vhdl-default-hook 0)
|
|
("after" "" vhdl-default-hook 0)
|
|
("alias" "" vhdl-alias-hook 0)
|
|
("all" "" vhdl-default-hook 0)
|
|
("and" "" vhdl-default-hook 0)
|
|
("arch" "" vhdl-architecture-hook 0)
|
|
("architecture" "" vhdl-architecture-hook 0)
|
|
("array" "" vhdl-array-hook 0)
|
|
("assert" "" vhdl-assert-hook 0)
|
|
("attr" "" vhdl-attribute-hook 0)
|
|
("attribute" "" vhdl-attribute-hook 0)
|
|
("begin" "" vhdl-default-indent-hook 0)
|
|
("block" "" vhdl-block-hook 0)
|
|
("body" "" vhdl-default-hook 0)
|
|
("buffer" "" vhdl-default-hook 0)
|
|
("bus" "" vhdl-default-hook 0)
|
|
("case" "" vhdl-case-hook 0)
|
|
("comp" "" vhdl-component-hook 0)
|
|
("component" "" vhdl-component-hook 0)
|
|
("conc" "" vhdl-concurrent-signal-assignment-hook 0)
|
|
("concurrent" "" vhdl-concurrent-signal-assignment-hook 0)
|
|
("conf" "" vhdl-configuration-hook 0)
|
|
("configuration" "" vhdl-configuration-hook 0)
|
|
("cons" "" vhdl-constant-hook 0)
|
|
("constant" "" vhdl-constant-hook 0)
|
|
("disconnect" "" vhdl-disconnect-hook 0)
|
|
("downto" "" vhdl-default-hook 0)
|
|
("else" "" vhdl-else-hook 0)
|
|
("elseif" "" vhdl-elsif-hook 0)
|
|
("elsif" "" vhdl-elsif-hook 0)
|
|
("end" "" vhdl-default-indent-hook 0)
|
|
("entity" "" vhdl-entity-hook 0)
|
|
("exit" "" vhdl-exit-hook 0)
|
|
("file" "" vhdl-default-hook 0)
|
|
("for" "" vhdl-for-hook 0)
|
|
("func" "" vhdl-function-hook 0)
|
|
("function" "" vhdl-function-hook 0)
|
|
("gen" "" vhdl-generate-hook 0)
|
|
("generate" "" vhdl-generate-hook 0)
|
|
("generic" "" vhdl-generic-hook 0)
|
|
("group" "" vhdl-default-hook 0)
|
|
("guarded" "" vhdl-default-hook 0)
|
|
("header" "" vhdl-header-hook 0)
|
|
("if" "" vhdl-if-hook 0)
|
|
("impure" "" vhdl-default-hook 0)
|
|
("in" "" vhdl-default-hook 0)
|
|
("inertial" "" vhdl-default-hook 0)
|
|
("inout" "" vhdl-default-hook 0)
|
|
("inst" "" vhdl-component-instance-hook 0)
|
|
("instance" "" vhdl-component-instance-hook 0)
|
|
("is" "" vhdl-default-hook 0)
|
|
("label" "" vhdl-default-hook 0)
|
|
("library" "" vhdl-library-hook 0)
|
|
("linkage" "" vhdl-default-hook 0)
|
|
("literal" "" vhdl-default-hook 0)
|
|
("loop" "" vhdl-loop-hook 0)
|
|
("map" "" vhdl-map-hook 0)
|
|
("mod" "" vhdl-default-hook 0)
|
|
("modify" "" vhdl-modify-hook 0)
|
|
("nand" "" vhdl-default-hook 0)
|
|
("new" "" vhdl-default-hook 0)
|
|
("next" "" vhdl-next-hook 0)
|
|
("nor" "" vhdl-default-hook 0)
|
|
("not" "" vhdl-default-hook 0)
|
|
("null" "" vhdl-default-hook 0)
|
|
("of" "" vhdl-default-hook 0)
|
|
("on" "" vhdl-default-hook 0)
|
|
("open" "" vhdl-default-hook 0)
|
|
("or" "" vhdl-default-hook 0)
|
|
("others" "" vhdl-default-hook 0)
|
|
("out" "" vhdl-default-hook 0)
|
|
("pack" "" vhdl-package-hook 0)
|
|
("package" "" vhdl-package-hook 0)
|
|
("port" "" vhdl-port-hook 0)
|
|
("postponed" "" vhdl-default-hook 0)
|
|
("procedure" "" vhdl-procedure-hook 0)
|
|
("process" "" vhdl-process-hook 0)
|
|
("pure" "" vhdl-default-hook 0)
|
|
("range" "" vhdl-default-hook 0)
|
|
("record" "" vhdl-record-hook 0)
|
|
("register" "" vhdl-default-hook 0)
|
|
("reject" "" vhdl-default-hook 0)
|
|
("rem" "" vhdl-default-hook 0)
|
|
("report" "" vhdl-default-hook 0)
|
|
("ret" "" vhdl-return-hook 0)
|
|
("return" "" vhdl-return-hook 0)
|
|
("rol" "" vhdl-default-hook 0)
|
|
("ror" "" vhdl-default-hook 0)
|
|
("select" "" vhdl-selected-signal-assignment-hook 0)
|
|
("severity" "" vhdl-default-hook 0)
|
|
("shared" "" vhdl-default-hook 0)
|
|
("sig" "" vhdl-signal-hook 0)
|
|
("signal" "" vhdl-signal-hook 0)
|
|
("sla" "" vhdl-default-hook 0)
|
|
("sll" "" vhdl-default-hook 0)
|
|
("sra" "" vhdl-default-hook 0)
|
|
("srl" "" vhdl-default-hook 0)
|
|
("sub" "" vhdl-subtype-hook 0)
|
|
("subtype" "" vhdl-subtype-hook 0)
|
|
("then" "" vhdl-default-hook 0)
|
|
("to" "" vhdl-default-hook 0)
|
|
("transport" "" vhdl-default-hook 0)
|
|
("type" "" vhdl-type-hook 0)
|
|
("unaffected" "" vhdl-default-hook 0)
|
|
("units" "" vhdl-default-hook 0)
|
|
("until" "" vhdl-default-hook 0)
|
|
("use" "" vhdl-use-hook 0)
|
|
("var" "" vhdl-variable-hook 0)
|
|
("variable" "" vhdl-variable-hook 0)
|
|
("wait" "" vhdl-wait-hook 0)
|
|
("warning" "" vhdl-default-hook 0)
|
|
("when" "" vhdl-when-hook 0)
|
|
("while" "" vhdl-while-loop-hook 0)
|
|
("with" "" vhdl-selected-signal-assignment-hook 0)
|
|
("xnor" "" vhdl-default-hook 0)
|
|
("xor" "" vhdl-default-hook 0)
|
|
))
|
|
|
|
|
|
;; ############################################################################
|
|
;; Menues
|
|
;; ############################################################################
|
|
|
|
;; ############################################################################
|
|
;; VHDL menu (using `easy-menu.el')
|
|
|
|
;; `customize-menu-create' is included in `cus-edit.el' version 1.9954,
|
|
;; which is not yet distributed with XEmacs 19.15
|
|
(defun vhdl-customize-menu-create (symbol &optional name)
|
|
"Return a customize menu for customization group SYMBOL.
|
|
If optional NAME is given, use that as the name of the menu.
|
|
Otherwise the menu will be named `Customize'.
|
|
The format is suitable for use with `easy-menu-define'."
|
|
(unless name
|
|
(setq name "Customize"))
|
|
(if (memq 'XEmacs vhdl-emacs-features)
|
|
;; We can delay it under XEmacs.
|
|
`(,name
|
|
:filter (lambda (&rest junk)
|
|
(cdr (custom-menu-create ',symbol))))
|
|
;; But we must create it now under Emacs.
|
|
(cons name (cdr (custom-menu-create symbol)))))
|
|
|
|
(defvar vhdl-mode-menu
|
|
(append
|
|
'("VHDL"
|
|
("Mode"
|
|
["Electric" vhdl-electric-mode :style toggle :selected vhdl-electric-mode]
|
|
["Stutter" vhdl-stutter-mode :style toggle :selected vhdl-stutter-mode]
|
|
)
|
|
"--"
|
|
("Compile"
|
|
["Compile Buffer" vhdl-compile t]
|
|
["Stop Compilation" kill-compilation t]
|
|
"--"
|
|
["Make" vhdl-make t]
|
|
["Generate Makefile" vhdl-generate-makefile t]
|
|
"--"
|
|
["Next Error" next-error t]
|
|
["Previous Error" previous-error t]
|
|
["First Error" first-error t]
|
|
)
|
|
"--"
|
|
("Template"
|
|
("VHDL Construct 1"
|
|
["Alias" vhdl-alias t]
|
|
["Architecture" vhdl-architecture t]
|
|
["Array" vhdl-array t]
|
|
["Assert" vhdl-assert t]
|
|
["Attribute" vhdl-attribute t]
|
|
["Block" vhdl-block t]
|
|
["Case" vhdl-case t]
|
|
["Component" vhdl-component t]
|
|
["Concurrent (Signal Asst)" vhdl-concurrent-signal-assignment t]
|
|
["Configuration (Block)" vhdl-block-configuration t]
|
|
["Configuration (Comp)" vhdl-component-configuration t]
|
|
["Configuration (Decl)" vhdl-configuration-decl t]
|
|
["Configuration (Spec)" vhdl-configuration-spec t]
|
|
["Constant" vhdl-constant t]
|
|
["Disconnect" vhdl-disconnect t]
|
|
["Else" vhdl-else t]
|
|
["Elsif" vhdl-elsif t]
|
|
["Entity" vhdl-entity t]
|
|
["Exit" vhdl-exit t]
|
|
["For (Loop)" vhdl-for t]
|
|
["Function" vhdl-function t]
|
|
["(For/If) Generate" vhdl-generate t]
|
|
["Generic" vhdl-generic t]
|
|
)
|
|
("VHDL Construct 2"
|
|
["If" vhdl-if t]
|
|
["Instance" vhdl-component-instance t]
|
|
["Library" vhdl-library t]
|
|
["Loop" vhdl-loop t]
|
|
["Map" vhdl-map t]
|
|
["Next" vhdl-next t]
|
|
["Package" vhdl-package t]
|
|
["Port" vhdl-port t]
|
|
["Procedure" vhdl-procedure t]
|
|
["Process" vhdl-process t]
|
|
["Record" vhdl-record t]
|
|
["Return" vhdl-return-value t]
|
|
["Select" vhdl-selected-signal-assignment t]
|
|
["Signal" vhdl-signal t]
|
|
["Subtype" vhdl-subtype t]
|
|
["Type" vhdl-type t]
|
|
["Use" vhdl-use t]
|
|
["Variable" vhdl-variable t]
|
|
["Wait" vhdl-wait t]
|
|
["(Clocked Wait)" vhdl-clocked-wait t]
|
|
["When" vhdl-when t]
|
|
["While (Loop)" vhdl-while-loop t]
|
|
["With" vhdl-with t]
|
|
)
|
|
("Standard Package"
|
|
["numeric_bit" vhdl-package-numeric-bit t]
|
|
["numeric_std" vhdl-package-numeric-std t]
|
|
["std_logic_1164" vhdl-package-std-logic-1164 t]
|
|
["textio" vhdl-package-textio t]
|
|
)
|
|
["Header" vhdl-header t]
|
|
["Modify (Date)" vhdl-modify t]
|
|
)
|
|
("Comment"
|
|
["(Un)Comment Out Region" vhdl-comment-uncomment-region (mark)]
|
|
["Insert Inline Comment" vhdl-inline-comment t]
|
|
["Insert Horizontal Line" vhdl-display-comment-line t]
|
|
["Insert Display Comment" vhdl-display-comment t]
|
|
["Fill Comment" fill-paragraph t]
|
|
["Fill Comment Region" fill-region (mark)]
|
|
)
|
|
("Indent"
|
|
["Line" vhdl-indent-line t]
|
|
["Region" indent-region (mark)]
|
|
["Buffer" vhdl-indent-buffer t]
|
|
)
|
|
("Align"
|
|
["Region" vhdl-align-noindent-region (mark)]
|
|
["Comment Region" vhdl-align-comment-region (mark)]
|
|
)
|
|
("Line"
|
|
["Open" vhdl-open-line t]
|
|
["Delete" vhdl-kill-line t]
|
|
["Join" delete-indentation t]
|
|
["Goto" goto-line t]
|
|
)
|
|
("Move"
|
|
["Forward Statement" vhdl-end-of-statement t]
|
|
["Backward Statement" vhdl-beginning-of-statement t]
|
|
["Forward Expression" vhdl-forward-sexp t]
|
|
["Backward Expression" vhdl-backward-sexp t]
|
|
["Forward Function" vhdl-end-of-defun t]
|
|
["Backward Function" vhdl-beginning-of-defun t]
|
|
)
|
|
"--"
|
|
("Fix Case"
|
|
["Buffer" vhdl-fix-case-buffer t]
|
|
["Region" vhdl-fix-case-region (mark)]
|
|
)
|
|
["Fontify Buffer" font-lock-fontify-buffer t]
|
|
["Syntactic Info" vhdl-show-syntactic-information t]
|
|
"--"
|
|
["Help" vhdl-help t]
|
|
["Version" vhdl-version t]
|
|
["Bug Report" vhdl-submit-bug-report t]
|
|
"--"
|
|
)
|
|
(list (vhdl-customize-menu-create 'vhdl))
|
|
))
|
|
|
|
(require 'easymenu)
|
|
|
|
;; ############################################################################
|
|
;; Index menu (using `imenu.el')
|
|
|
|
(defvar vhdl-imenu-generic-expression
|
|
'(
|
|
("Entity"
|
|
"^\\s-*\\(entity\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\)"
|
|
2)
|
|
("Architecture"
|
|
"^\\s-*\\(architecture\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\s-+of\\s-+\\(\\w\\|\\s_\\)+\\)"
|
|
2)
|
|
("Configuration"
|
|
"^\\s-*\\(configuration\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\s-+of\\s-+\\(\\w\\|\\s_\\)+\\)"
|
|
2)
|
|
("Package Body"
|
|
"^\\s-*\\(package body\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\)"
|
|
2)
|
|
("Package"
|
|
"^\\s-*\\(package\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\)"
|
|
2)
|
|
("Type"
|
|
"^\\s-*\\(sub\\)?type\\s-+\\(\\(\\w\\|\\s_\\)+\\)"
|
|
2)
|
|
("Component"
|
|
"^\\s-*\\(component\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\)"
|
|
2)
|
|
("Function / Procedure"
|
|
"^\\s-*\\(procedure\\|function\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\)"
|
|
2)
|
|
("Process / Block"
|
|
"^\\s-*\\(\\(\\w\\|\\s_\\)+\\)\\s-*:\\(\\s-\\|\n\\)*\\(process\\|block\\)"
|
|
1)
|
|
("Instance"
|
|
"^\\s-*\\(\\(\\w\\|\\s_\\)+\\s-*:\\(\\s-\\|\n\\)*\\(\\w\\|\\s_\\)+\\)\\(\\s-\\|\n\\)+\\(generic\\|port\\)\\s-+map\\>"
|
|
1)
|
|
)
|
|
"Imenu generic expression for VHDL Mode. See `imenu-generic-expression'.")
|
|
|
|
(defun vhdl-add-index-menu ()
|
|
(make-local-variable 'imenu-generic-expression)
|
|
(setq imenu-generic-expression vhdl-imenu-generic-expression)
|
|
(imenu-add-to-menubar "Index"))
|
|
|
|
;; ############################################################################
|
|
;; Source file menu (using `easy-menu.el')
|
|
|
|
(defvar vhdl-extlist '("[A-Za-z0-9_.]*.vhdl?$"))
|
|
(defvar vhdl-filelist-menu nil)
|
|
|
|
(defun vhdl-add-source-files-menu ()
|
|
"Scan directory of current source file for all VHDL source files, and
|
|
generate menu."
|
|
(interactive)
|
|
(message "Scanning directory for source files ...")
|
|
(let (filelist menulist tmpextlist found
|
|
(newmap (current-local-map)))
|
|
(cd (file-name-directory (buffer-file-name)))
|
|
;; find files
|
|
(setq menulist '())
|
|
(setq tmpextlist vhdl-extlist)
|
|
(while tmpextlist
|
|
(setq filelist (nreverse (directory-files
|
|
(file-name-directory (buffer-file-name))
|
|
nil (car tmpextlist) nil)))
|
|
;; Create list for menu
|
|
(setq found nil)
|
|
(while filelist
|
|
(setq found t)
|
|
(setq menulist (cons (vector (car filelist)
|
|
(list 'find-file (car filelist)) t)
|
|
menulist))
|
|
(setq filelist (cdr filelist)))
|
|
(setq menulist (vhdl-menu-split menulist 25))
|
|
(if found
|
|
(setq menulist (cons "--" menulist)))
|
|
(setq tmpextlist (cdr tmpextlist)))
|
|
(setq menulist (cons ["*Rescan*" vhdl-add-source-files-menu t] menulist))
|
|
(setq menulist (cons "Sources" menulist))
|
|
;; Create menu
|
|
(easy-menu-add menulist)
|
|
(easy-menu-define vhdl-filelist-menu newmap
|
|
"VHDL source files menu" menulist)
|
|
; (use-local-map (append (current-local-map) newmap))
|
|
; (use-local-map newmap)
|
|
)
|
|
(message ""))
|
|
|
|
(defun vhdl-menu-split (list n)
|
|
"Split menu into several submenues, if number of elements > n."
|
|
(if (> (length list) n)
|
|
(let ((remain list)
|
|
(result '())
|
|
(sublist '())
|
|
(menuno 1)
|
|
(i 0))
|
|
(while remain
|
|
(setq sublist (cons (car remain) sublist))
|
|
(setq remain (cdr remain))
|
|
(setq i (+ i 1))
|
|
(if (= i n)
|
|
(progn
|
|
(setq result (cons (cons (format "Sources %s" menuno)
|
|
(nreverse sublist)) result))
|
|
(setq i 0)
|
|
(setq menuno (+ menuno 1))
|
|
(setq sublist '()))))
|
|
(and sublist
|
|
(setq result (cons (cons (format "Sources %s" menuno)
|
|
(nreverse sublist)) result)))
|
|
(nreverse result))
|
|
list))
|
|
|
|
|
|
;; ############################################################################
|
|
;; VHDL Mode definition
|
|
;; ############################################################################
|
|
|
|
(defun vhdl-mode ()
|
|
"Major mode for editing VHDL code.
|
|
|
|
Usage:
|
|
------
|
|
|
|
- TEMPLATE INSERTION (electrification) (`\\[vhdl-outer-space]'): After typing
|
|
a VHDL keyword and entering `\\[vhdl-outer-space]', you are prompted for
|
|
arguments while a template is generated for that VHDL construct. Typing
|
|
`\\[vhdl-return]' (or `\\[keyboard-quit]' in yes-no queries) at the first
|
|
prompt aborts the current template generation. Typing `\\[just-one-space]'
|
|
after a keyword inserts a space without calling the template generator.
|
|
Automatic calling of the template generators (i.e. electrification) can be
|
|
disabled (enabled) by setting the variable `vhdl-electric-mode' to nil
|
|
(non-nil) or by typing `\\[vhdl-electric-mode]' (toggles electrification
|
|
mode).
|
|
Template generators can be called using the VHDL menu, the key bindings, or
|
|
by typing the keyword (first word of menu entry not in parenthesis) and
|
|
`\\[vhdl-outer-space]'. The following abbreviations can also be used:
|
|
arch, attr, conc, conf, comp, cons, func, inst, pack, ret, sig, sub, var.
|
|
|
|
- HEADER INSERTION (`\\[vhdl-header]'): A customized header can be inserted
|
|
including the actual file name, user name, and current date as well as
|
|
prompted title strings. A custom header can be defined in a separate file
|
|
(see custom variable `vhdl-header-file').
|
|
|
|
- STUTTERING (double strike): Double striking of some keys inserts cumbersome
|
|
VHDL syntax elements. Stuttering can be disabled by variable
|
|
`vhdl-stutter-mode' and be toggled by typing `\\[vhdl-stutter-mode]'.
|
|
'' --> \" [ --> ( -- --> comment
|
|
;; --> \" : \" [[ --> [ --CR --> comment-out code
|
|
;;; --> \" := \" ] --> ) --- --> horizontal line
|
|
.. --> \" => \" ]] --> ] ---- --> display comment
|
|
,, --> \" <= \" aa --> A - zz --> Z
|
|
|
|
- WORD COMPLETION (`\\[vhdl-tab]'): Typing `\\[vhdl-tab]' after a (not
|
|
completed) word looks for a word in the buffer that starts alike and
|
|
inserts it. Re-typing `\\[vhdl-tab]' toggles through alternative word
|
|
completions. This also works in the minibuffer (i.e. in template generator
|
|
prompts).
|
|
|
|
Typing `\\[vhdl-tab]' after a non-word character indents the line if at the
|
|
beginning of a line (i.e. no preceding non-blank characters), and inserts a
|
|
tabulator stop otherwise. `\\[tab-to-tab-stop]' always inserts a tabulator
|
|
stop.
|
|
|
|
- COMMENTS (`--', `---', `----', `--CR'):
|
|
`--' puts a single comment.
|
|
`---' draws a horizontal line for separating code segments.
|
|
`----' inserts a display comment, i.e. two horizontal lines with a
|
|
comment in between.
|
|
`--CR' comments out code on that line. Re-hitting CR comments out
|
|
following lines.
|
|
`\\[vhdl-comment-uncomment-region]' comments out a region if not
|
|
commented out, uncomments out a region if already
|
|
commented out.
|
|
|
|
You are prompted for comments after object definitions (i.e. signals,
|
|
variables, constants, ports) and after subprogram and process specifications
|
|
if variable `vhdl-prompt-for-comments' is non-nil. Comments are
|
|
automatically inserted as additional labels (e.g. after begin statements)
|
|
and help comments if `vhdl-self-insert-comments' is non-nil.
|
|
Inline comments (i.e. comments after a piece of code on the same line) are
|
|
indented at least to `vhdl-comment-column'. Comments go at maximum to
|
|
`vhdl-end-comment-column'. `\\[vhdl-return]' after a space in a comment will
|
|
open a new comment line. Typing beyond `vhdl-end-comment-column' in a
|
|
comment automatically opens a new comment line. `\\[fill-paragraph]'
|
|
re-fills multi-line comments.
|
|
|
|
- INDENTATION: `\\[vhdl-tab]' indents a line if at the beginning of the line.
|
|
The amount of indentation is specified by variable `vhdl-basic-offset'.
|
|
`\\[vhdl-indent-line]' always indents the current line (is bound to `TAB'
|
|
if variable `vhdl-intelligent-tab' is nil). Indentation can be done for
|
|
an entire region (`\\[indent-region]') or buffer (menu). Argument and
|
|
port lists are indented normally (nil) or relative to the opening
|
|
parenthesis (non-nil) according to variable `vhdl-argument-list-indent'.
|
|
If variable `vhdl-indent-tabs-mode' is nil, spaces are used instead of tabs.
|
|
`\\[tabify]' and `\\[untabify]' allow to convert spaces to tabs and vice
|
|
versa.
|
|
|
|
- ALIGNMENT: `\\[vhdl-align-noindent-region]' aligns port maps, signal and
|
|
variable assignments, inline comments, some keywords, etc., on consecutive
|
|
lines relative to each other within a defined region.
|
|
`\\[vhdl-align-comment-region]' only aligns inline comments (i.e. comments
|
|
that are at the end of a line of code). Some templates are automatically
|
|
aligned after generation if custom variable `vhdl-auto-align' is non-nil.
|
|
|
|
- KEY BINDINGS: Key bindings (`C-c ...') exist for most commands (see in menu).
|
|
|
|
- VHDL MENU: All commands can be called from the VHDL menu.
|
|
|
|
- INDEX MENU: For each VHDL source file, an index of the contained entities,
|
|
architectures, packages, procedures, processes, etc., is created as a menu.
|
|
Selecting a meny entry causes the cursor to jump to the corresponding
|
|
position in the file. Controlled by variable `vhdl-index-menu'.
|
|
|
|
- SOURCE FILE MENU: A menu containing all VHDL source files in the directory
|
|
of the current file is generated. Selecting a menu entry loads the file.
|
|
Controlled by variable `vhdl-source-file-menu'.
|
|
|
|
- SOURCE FILE COMPILATION: The syntax of the current buffer can be analyzed
|
|
by calling a VHDL compiler (menu, `\\[vhdl-compile]'). The compiler to be
|
|
used is defined by variable `vhdl-compiler'. Currently supported are
|
|
`cadence', `ikos', `quickhdl', `synopsys', `vantage', `viewlogic', and
|
|
`v-system'. Not all compilers are tested. Please contact me for
|
|
incorporating additional VHDL compilers. An entire hierarchy of source
|
|
files can be compiled by the `make' command (menu, `\\[vhdl-make]').
|
|
This only works if an appropriate `Makefile' exists. Compiler options can
|
|
be defined by variable `vhdl-compiler-options'.
|
|
|
|
- KEYWORD CASE: Lower and upper case for keywords, predefined types, predefined
|
|
attributes, and predefined enumeration values is supported. If the variable
|
|
`vhdl-upper-case-keywords' is set to non-nil, keywords can be typed in
|
|
lower case and are converted into upper case automatically (not for types,
|
|
attributes, and enumeration values). The case of keywords, types,
|
|
attributes, and enumeration values can be fixed for an entire region (menu)
|
|
or buffer (`\\[vhdl-fix-case-buffer]') according to the variables
|
|
`vhdl-upper-case-{keywords,types,attributes,enum-values}'.
|
|
|
|
- HIGHLIGHTING (fontification): Keywords, predefined types, predefined
|
|
attributes, and predefined enumeration values (controlled by variable
|
|
`vhdl-highlight-keywords'), as well as comments, strings, and template
|
|
prompts are highlighted using different colors. Unit and subprogram names
|
|
as well as labels are highlighted if variable `vhdl-highlight-names' is
|
|
non-nil. The default colors from `font-lock.el' are used if variable
|
|
`vhdl-use-default-colors' is non-nil. Otherwise, an optimized set of colors
|
|
is taken, which uses bright colors for signals and muted colors for
|
|
everything else. Variable `vhdl-use-default-faces' does the same on
|
|
monochrome monitors.
|
|
|
|
Signal highlighting allows distinction between clock, reset,
|
|
status/control, data, and test signals according to some signal
|
|
naming convention. Their syntax is defined by variables
|
|
`vhdl-{clock,reset,control,data,test}-signal-syntax'. Signal coloring
|
|
is controlled by the variable `vhdl-highlight-signals'. The default
|
|
signal naming convention is as follows:
|
|
|
|
Signal attributes:
|
|
C clock S control and status
|
|
R asynchronous reset D data and address
|
|
I synchronous reset T test
|
|
|
|
Syntax:
|
|
signal name ::= \"[A-Z][a-zA-Z0-9]*x[CRISDT][a-zA-Z0-9]*\"
|
|
signal identifier -^^^^^^^^^^^^^^^^^
|
|
delimiter --------------------------^
|
|
above signal attributes -------------^^^^^^^^
|
|
additional attributes -----------------------^^^^^^^^^^^^
|
|
|
|
(`x' is used as delimiter because `_' is reserved by the VITAL standard.)
|
|
Examples: ClkxCfast, ResetxRB, ClearxI, SelectDataxS, DataxD, ScanEnablexT.
|
|
|
|
If all VHDL words are written in lower case (i.e. variables
|
|
`vhdl-upper-case-{keywords,types,attributes,enum-values}' are set to nil),
|
|
make highlighting case sensitive by setting variable
|
|
`vhdl-highlight-case-sensitive' to non-nil. This way, only names fulfilling
|
|
the above signal syntax including case are highlighted.
|
|
|
|
- HIDE/SHOW: The code of entire VHDL processes or blocks can be hidden using
|
|
the `Hide/Show' menu or by pressing `S-mouse-2' within the code
|
|
(not in XEmacs).
|
|
|
|
- PRINTING: Postscript printing with different fonts (`ps-print-color-p' is
|
|
nil, default faces from `font-lock.el' used if `vhdl-use-default-faces' is
|
|
non-nil) or colors (`ps-print-color-p' is non-nil) is possible using the
|
|
standard Emacs postscript printing commands. Variable `vhdl-print-two-column'
|
|
defines appropriate default settings for nice landscape two-column printing.
|
|
The paper format can be set by variable `ps-paper-type'.
|
|
|
|
- CUSTOMIZATION: All variables can easily be customized using the `Customize'
|
|
menu entry. For some variables, customization only takes effect after
|
|
re-starting Emacs. Customization can also be done globally (i.e. site-wide,
|
|
read INSTALL file). Variables of VHDL Mode must NOT be set using the
|
|
`vhdl-mode-hook' in the .emacs file anymore (delete them if they still are).
|
|
|
|
|
|
Maintenance:
|
|
------------
|
|
|
|
To submit a bug report, enter `\\[vhdl-submit-bug-report]' within VHDL Mode.
|
|
Add a description of the problem and include a reproducible test case.
|
|
|
|
Questions and enhancement requests can be sent to <vhdl-mode@geocities.com>.
|
|
|
|
The `vhdl-mode-announce' mailing list informs about new VHDL Mode releases.
|
|
The `vhdl-mode-victims' mailing list informs about new VHDL Mode beta releases.
|
|
You are kindly invited to participate in beta testing. Subscribe to above
|
|
mailing lists by sending an email to <vhdl-mode@geocities.com>.
|
|
|
|
The archive with the latest version is located at
|
|
<http://www.geocities.com/SiliconValley/Peaks/8287>.
|
|
|
|
|
|
Bugs and Limitations:
|
|
---------------------
|
|
|
|
- Index menu does not work under XEmacs (limitation of XEmacs ?!).
|
|
|
|
- Re-indenting large regions or expressions can be slow.
|
|
|
|
- Hideshow does not work under XEmacs.
|
|
|
|
- Parsing compilation error messages for Ikos and Vantage VHDL compilers
|
|
does not work under XEmacs.
|
|
|
|
|
|
Key bindings:
|
|
-------------
|
|
|
|
\\{vhdl-mode-map}"
|
|
(interactive)
|
|
(kill-all-local-variables)
|
|
(set-syntax-table vhdl-mode-syntax-table)
|
|
(setq major-mode 'vhdl-mode)
|
|
(setq mode-name "VHDL")
|
|
(setq local-abbrev-table vhdl-mode-abbrev-table)
|
|
(use-local-map vhdl-mode-map)
|
|
;; set local variable values
|
|
(set (make-local-variable 'paragraph-start) "\\s-*\\(---\\|[a-zA-Z]\\|$\\)")
|
|
(set (make-local-variable 'paragraph-separate) paragraph-start)
|
|
(set (make-local-variable 'paragraph-ignore-fill-prefix) t)
|
|
(set (make-local-variable 'require-final-newline) t)
|
|
(set (make-local-variable 'parse-sexp-ignore-comments) t)
|
|
(set (make-local-variable 'indent-line-function) 'vhdl-indent-line)
|
|
(set (make-local-variable 'comment-start) "--")
|
|
(set (make-local-variable 'comment-end) "")
|
|
(set (make-local-variable 'comment-column) vhdl-comment-column)
|
|
(set (make-local-variable 'end-comment-column) vhdl-end-comment-column)
|
|
(set (make-local-variable 'comment-start-skip) "--+\\s-*")
|
|
(set (make-local-variable 'dabbrev-case-fold-search) nil)
|
|
(set (make-local-variable 'indent-tabs-mode) vhdl-indent-tabs-mode)
|
|
|
|
;; setup the comment indent variable in a Emacs version portable way
|
|
;; ignore any byte compiler warnings you might get here
|
|
(if (boundp 'comment-indent-function)
|
|
(progn (make-local-variable 'comment-indent-function)
|
|
(setq comment-indent-function 'vhdl-comment-indent)))
|
|
|
|
;; initialize font locking
|
|
(require 'font-lock)
|
|
(vhdl-font-lock-init)
|
|
(make-local-variable 'font-lock-defaults)
|
|
(setq font-lock-defaults (list 'vhdl-font-lock-keywords nil
|
|
(not vhdl-highlight-case-sensitive)
|
|
'((?\_ . "w"))))
|
|
(turn-on-font-lock)
|
|
|
|
;; variables for source file compilation
|
|
(make-local-variable 'compile-command)
|
|
(set (make-local-variable 'compilation-error-regexp-alist)
|
|
vhdl-compilation-error-regexp-alist)
|
|
|
|
;; add menus
|
|
(if vhdl-index-menu
|
|
(if (or (not (consp font-lock-maximum-size))
|
|
(> font-lock-maximum-size (buffer-size)))
|
|
(vhdl-add-index-menu)
|
|
(message "Scanning buffer for index...buffer too big")))
|
|
(if vhdl-source-file-menu (vhdl-add-source-files-menu))
|
|
(easy-menu-add vhdl-mode-menu)
|
|
(easy-menu-define vhdl-mode-easy-menu vhdl-mode-map
|
|
"Menu keymap for VHDL Mode." vhdl-mode-menu)
|
|
(run-hooks 'menu-bar-update-hook)
|
|
|
|
;; initialize hideshow and add menu
|
|
(if vhdl-hideshow-menu (hs-minor-mode))
|
|
|
|
;; initialize postscript printing
|
|
(vhdl-ps-init)
|
|
|
|
(setq mode-name (if vhdl-electric-mode "Electric VHDL" "VHDL"))
|
|
(message "Type C-c C-h for VHDL Mode documentation.")
|
|
|
|
(run-hooks 'vhdl-mode-hook)
|
|
)
|
|
|
|
|
|
;; ############################################################################
|
|
;; Keywords and predefined words in VHDL'93
|
|
;; ############################################################################
|
|
|
|
;; `regexp-opt' was not used at this place because it is not yet implemented
|
|
;; in XEmacs and because it resulted in SLOWER regexps!!
|
|
|
|
(defconst vhdl-93-keywords-regexp
|
|
(eval-when-compile
|
|
(concat
|
|
"\\<\\("
|
|
(mapconcat
|
|
'identity
|
|
'(
|
|
"abs" "access" "after" "alias" "all" "and" "architecture" "array"
|
|
"assert" "attribute"
|
|
"begin" "block" "body" "buffer" "bus"
|
|
"case" "component" "configuration" "constant"
|
|
"disconnect" "downto"
|
|
"else" "elsif" "end" "entity" "exit"
|
|
"file" "for" "function"
|
|
"generate" "generic" "group" "guarded"
|
|
"if" "impure" "in" "inertial" "inout" "is"
|
|
"label" "library" "linkage" "literal" "loop"
|
|
"map" "mod"
|
|
"nand" "new" "next" "nor" "not" "null"
|
|
"of" "on" "open" "or" "others" "out"
|
|
"package" "port" "postponed" "procedure" "process" "pure"
|
|
"range" "record" "register" "reject" "rem" "report" "return"
|
|
"rol" "ror"
|
|
"select" "severity" "shared" "signal" "sla" "sll" "sra" "srl" "subtype"
|
|
"then" "to" "transport" "type"
|
|
"unaffected" "units" "until" "use"
|
|
"variable"
|
|
"wait" "warning" "when" "while" "with"
|
|
"xnor" "xor"
|
|
)
|
|
"\\|")
|
|
"\\)\\>"))
|
|
"Regexp for VHDL'93 keywords.")
|
|
|
|
(defconst vhdl-93-types-regexp
|
|
(eval-when-compile
|
|
(concat
|
|
"\\<\\("
|
|
(mapconcat
|
|
'identity
|
|
'(
|
|
"boolean" "bit" "bit_vector" "character" "severity_level" "integer"
|
|
"real" "time" "natural" "positive" "string" "text" "line"
|
|
"unsigned" "signed"
|
|
"std_logic" "std_logic_vector"
|
|
"std_ulogic" "std_ulogic_vector"
|
|
)
|
|
"\\|")
|
|
"\\)\\>"))
|
|
"Regexp for VHDL'93 standardized types.")
|
|
|
|
(defconst vhdl-93-attributes-regexp
|
|
(eval-when-compile
|
|
(concat
|
|
"\\<\\("
|
|
(mapconcat
|
|
'identity
|
|
'(
|
|
"base" "left" "right" "high" "low" "pos" "val" "succ"
|
|
"pred" "leftof" "rightof" "range" "reverse_range"
|
|
"length" "delayed" "stable" "quiet" "transaction"
|
|
"event" "active" "last_event" "last_active" "last_value"
|
|
"driving" "driving_value" "ascending" "value" "image"
|
|
"simple_name" "instance_name" "path_name"
|
|
"foreign"
|
|
)
|
|
"\\|")
|
|
"\\)\\>"))
|
|
"Regexp for VHDL'93 standardized attributes.")
|
|
|
|
(defconst vhdl-93-enum-values-regexp
|
|
(eval-when-compile
|
|
(concat
|
|
"\\<\\("
|
|
(mapconcat
|
|
'identity
|
|
'(
|
|
"true" "false"
|
|
"note" "warning" "error" "failure"
|
|
"fs" "ps" "ns" "us" "ms" "sec" "min" "hr"
|
|
)
|
|
"\\|")
|
|
"\\)\\>"))
|
|
"Regexp for VHDL'93 standardized enumeration values.")
|
|
|
|
|
|
;; ############################################################################
|
|
;; Syntax analysis and indentation
|
|
;; ############################################################################
|
|
|
|
;; ############################################################################
|
|
;; Syntax analysis
|
|
|
|
;; constant regular expressions for looking at various constructs
|
|
|
|
(defconst vhdl-symbol-key "\\(\\w\\|\\s_\\)+"
|
|
"Regexp describing a VHDL symbol.
|
|
We cannot use just `word' syntax class since `_' cannot be in word
|
|
class. Putting underscore in word class breaks forward word movement
|
|
behavior that users are familiar with.")
|
|
|
|
(defconst vhdl-case-header-key "case[( \t\n][^;=>]+[) \t\n]is"
|
|
"Regexp describing a case statement header key.")
|
|
|
|
(defconst vhdl-label-key
|
|
(concat "\\(" vhdl-symbol-key "\\s-*:\\)[^=]")
|
|
"Regexp describing a VHDL label.")
|
|
|
|
;; Macro definitions:
|
|
|
|
(defmacro vhdl-point (position)
|
|
;; Returns the value of point at certain commonly referenced POSITIONs.
|
|
;; POSITION can be one of the following symbols:
|
|
;;
|
|
;; bol -- beginning of line
|
|
;; eol -- end of line
|
|
;; bod -- beginning of defun
|
|
;; boi -- back to indentation
|
|
;; eoi -- last whitespace on line
|
|
;; ionl -- indentation of next line
|
|
;; iopl -- indentation of previous line
|
|
;; bonl -- beginning of next line
|
|
;; bopl -- beginning of previous line
|
|
;;
|
|
;; This function does not modify point or mark.
|
|
(or (and (eq 'quote (car-safe position))
|
|
(null (cdr (cdr position))))
|
|
(error "bad buffer position requested: %s" position))
|
|
(setq position (nth 1 position))
|
|
(` (let ((here (point)))
|
|
(,@ (cond
|
|
((eq position 'bol) '((beginning-of-line)))
|
|
((eq position 'eol) '((end-of-line)))
|
|
((eq position 'bod) '((save-match-data
|
|
(vhdl-beginning-of-defun))))
|
|
((eq position 'boi) '((back-to-indentation)))
|
|
((eq position 'eoi) '((end-of-line)(skip-chars-backward " \t")))
|
|
((eq position 'bonl) '((forward-line 1)))
|
|
((eq position 'bopl) '((forward-line -1)))
|
|
((eq position 'iopl)
|
|
'((forward-line -1)
|
|
(back-to-indentation)))
|
|
((eq position 'ionl)
|
|
'((forward-line 1)
|
|
(back-to-indentation)))
|
|
(t (error "unknown buffer position requested: %s" position))
|
|
))
|
|
(prog1
|
|
(point)
|
|
(goto-char here))
|
|
;; workaround for an Emacs18 bug -- blech! Well, at least it
|
|
;; doesn't hurt for v19
|
|
(,@ nil)
|
|
)))
|
|
|
|
(defmacro vhdl-safe (&rest body)
|
|
;; safely execute BODY, return nil if an error occurred
|
|
(` (condition-case nil
|
|
(progn (,@ body))
|
|
(error nil))))
|
|
|
|
(defmacro vhdl-add-syntax (symbol &optional relpos)
|
|
;; a simple macro to append the syntax in symbol to the syntax list.
|
|
;; try to increase performance by using this macro
|
|
(` (setq vhdl-syntactic-context
|
|
(cons (cons (, symbol) (, relpos)) vhdl-syntactic-context))))
|
|
|
|
(defmacro vhdl-has-syntax (symbol)
|
|
;; a simple macro to return check the syntax list.
|
|
;; try to increase performance by using this macro
|
|
(` (assoc (, symbol) vhdl-syntactic-context)))
|
|
|
|
;; Syntactic element offset manipulation:
|
|
|
|
(defun vhdl-read-offset (langelem)
|
|
;; read new offset value for LANGELEM from minibuffer. return a
|
|
;; legal value only
|
|
(let ((oldoff (format "%s" (cdr-safe (assq langelem vhdl-offsets-alist))))
|
|
(errmsg "Offset must be int, func, var, or one of +, -, ++, --: ")
|
|
(prompt "Offset: ")
|
|
offset input interned)
|
|
(while (not offset)
|
|
(setq input (read-string prompt oldoff)
|
|
offset (cond ((string-equal "+" input) '+)
|
|
((string-equal "-" input) '-)
|
|
((string-equal "++" input) '++)
|
|
((string-equal "--" input) '--)
|
|
((string-match "^-?[0-9]+$" input)
|
|
(string-to-int input))
|
|
((fboundp (setq interned (intern input)))
|
|
interned)
|
|
((boundp interned) interned)
|
|
;; error, but don't signal one, keep trying
|
|
;; to read an input value
|
|
(t (ding)
|
|
(setq prompt errmsg)
|
|
nil))))
|
|
offset))
|
|
|
|
(defun vhdl-set-offset (symbol offset &optional add-p)
|
|
"Change the value of a syntactic element symbol in `vhdl-offsets-alist'.
|
|
SYMBOL is the syntactic element symbol to change and OFFSET is the new
|
|
offset for that syntactic element. Optional ADD says to add SYMBOL to
|
|
`vhdl-offsets-alist' if it doesn't already appear there."
|
|
(interactive
|
|
(let* ((langelem
|
|
(intern (completing-read
|
|
(concat "Syntactic symbol to change"
|
|
(if current-prefix-arg " or add" "")
|
|
": ")
|
|
(mapcar
|
|
(function
|
|
(lambda (langelem)
|
|
(cons (format "%s" (car langelem)) nil)))
|
|
vhdl-offsets-alist)
|
|
nil (not current-prefix-arg)
|
|
;; initial contents tries to be the last element
|
|
;; on the syntactic analysis list for the current
|
|
;; line
|
|
(let* ((syntax (vhdl-get-syntactic-context))
|
|
(len (length syntax))
|
|
(ic (format "%s" (car (nth (1- len) syntax)))))
|
|
(if (memq 'v19 vhdl-emacs-features)
|
|
(cons ic 0)
|
|
ic))
|
|
)))
|
|
(offset (vhdl-read-offset langelem)))
|
|
(list langelem offset current-prefix-arg)))
|
|
;; sanity check offset
|
|
(or (eq offset '+)
|
|
(eq offset '-)
|
|
(eq offset '++)
|
|
(eq offset '--)
|
|
(integerp offset)
|
|
(fboundp offset)
|
|
(boundp offset)
|
|
(error "Offset must be int, func, var, or one of +, -, ++, --: %s"
|
|
offset))
|
|
(let ((entry (assq symbol vhdl-offsets-alist)))
|
|
(if entry
|
|
(setcdr entry offset)
|
|
(if add-p
|
|
(setq vhdl-offsets-alist (cons (cons symbol offset) vhdl-offsets-alist))
|
|
(error "%s is not a valid syntactic symbol." symbol))))
|
|
(vhdl-keep-region-active))
|
|
|
|
(defun vhdl-set-style (style &optional local)
|
|
"Set vhdl-mode variables to use one of several different indentation styles.
|
|
STYLE is a string representing the desired style and optional LOCAL is
|
|
a flag which, if non-nil, means to make the style variables being
|
|
changed buffer local, instead of the default, which is to set the
|
|
global variables. Interactively, the flag comes from the prefix
|
|
argument. The styles are chosen from the `vhdl-style-alist' variable."
|
|
(interactive (list (completing-read "Use which VHDL indentation style? "
|
|
vhdl-style-alist nil t)
|
|
current-prefix-arg))
|
|
(let ((vars (cdr (assoc style vhdl-style-alist))))
|
|
(or vars
|
|
(error "Invalid VHDL indentation style `%s'" style))
|
|
;; set all the variables
|
|
(mapcar
|
|
(function
|
|
(lambda (varentry)
|
|
(let ((var (car varentry))
|
|
(val (cdr varentry)))
|
|
(and local
|
|
(make-local-variable var))
|
|
;; special case for vhdl-offsets-alist
|
|
(if (not (eq var 'vhdl-offsets-alist))
|
|
(set var val)
|
|
;; reset vhdl-offsets-alist to the default value first
|
|
(setq vhdl-offsets-alist (copy-alist vhdl-offsets-alist-default))
|
|
;; now set the langelems that are different
|
|
(mapcar
|
|
(function
|
|
(lambda (langentry)
|
|
(let ((langelem (car langentry))
|
|
(offset (cdr langentry)))
|
|
(vhdl-set-offset langelem offset)
|
|
)))
|
|
val))
|
|
)))
|
|
vars))
|
|
(vhdl-keep-region-active))
|
|
|
|
(defun vhdl-get-offset (langelem)
|
|
;; Get offset from LANGELEM which is a cons cell of the form:
|
|
;; (SYMBOL . RELPOS). The symbol is matched against
|
|
;; vhdl-offsets-alist and the offset found there is either returned,
|
|
;; or added to the indentation at RELPOS. If RELPOS is nil, then
|
|
;; the offset is simply returned.
|
|
(let* ((symbol (car langelem))
|
|
(relpos (cdr langelem))
|
|
(match (assq symbol vhdl-offsets-alist))
|
|
(offset (cdr-safe match)))
|
|
;; offset can be a number, a function, a variable, or one of the
|
|
;; symbols + or -
|
|
(cond
|
|
((not match)
|
|
(if vhdl-strict-syntax-p
|
|
(error "don't know how to indent a %s" symbol)
|
|
(setq offset 0
|
|
relpos 0)))
|
|
((eq offset '+) (setq offset vhdl-basic-offset))
|
|
((eq offset '-) (setq offset (- vhdl-basic-offset)))
|
|
((eq offset '++) (setq offset (* 2 vhdl-basic-offset)))
|
|
((eq offset '--) (setq offset (* 2 (- vhdl-basic-offset))))
|
|
((and (not (numberp offset))
|
|
(fboundp offset))
|
|
(setq offset (funcall offset langelem)))
|
|
((not (numberp offset))
|
|
(setq offset (eval offset)))
|
|
)
|
|
(+ (if (and relpos
|
|
(< relpos (vhdl-point 'bol)))
|
|
(save-excursion
|
|
(goto-char relpos)
|
|
(current-column))
|
|
0)
|
|
offset)))
|
|
|
|
;; Syntactic support functions:
|
|
|
|
;; Returns `comment' if in a comment, `string' if in a string literal,
|
|
;; or nil if not in a literal at all. Optional LIM is used as the
|
|
;; backward limit of the search. If omitted, or nil, (point-min) is
|
|
;; used.
|
|
|
|
(defun vhdl-in-literal (&optional lim)
|
|
;; Determine if point is in a VHDL literal.
|
|
(save-excursion
|
|
(let* ((lim (or lim (point-min)))
|
|
(state (parse-partial-sexp lim (point))))
|
|
(cond
|
|
((nth 3 state) 'string)
|
|
((nth 4 state) 'comment)
|
|
(t nil)))
|
|
))
|
|
|
|
;; This is the best we can do in Win-Emacs.
|
|
(defun vhdl-win-il (&optional lim)
|
|
;; Determine if point is in a VHDL literal
|
|
(save-excursion
|
|
(let* ((here (point))
|
|
(state nil)
|
|
(match nil)
|
|
(lim (or lim (vhdl-point 'bod))))
|
|
(goto-char lim )
|
|
(while (< (point) here)
|
|
(setq match
|
|
(and (re-search-forward "--\\|[\"']"
|
|
here 'move)
|
|
(buffer-substring (match-beginning 0) (match-end 0))))
|
|
(setq state
|
|
(cond
|
|
;; no match
|
|
((null match) nil)
|
|
;; looking at the opening of a VHDL style comment
|
|
((string= "--" match)
|
|
(if (<= here (progn (end-of-line) (point))) 'comment))
|
|
;; looking at the opening of a double quote string
|
|
((string= "\"" match)
|
|
(if (not (save-restriction
|
|
;; this seems to be necessary since the
|
|
;; re-search-forward will not work without it
|
|
(narrow-to-region (point) here)
|
|
(re-search-forward
|
|
;; this regexp matches a double quote
|
|
;; which is preceded by an even number
|
|
;; of backslashes, including zero
|
|
"\\([^\\]\\|^\\)\\(\\\\\\\\\\)*\"" here 'move)))
|
|
'string))
|
|
;; looking at the opening of a single quote string
|
|
((string= "'" match)
|
|
(if (not (save-restriction
|
|
;; see comments from above
|
|
(narrow-to-region (point) here)
|
|
(re-search-forward
|
|
;; this matches a single quote which is
|
|
;; preceded by zero or two backslashes.
|
|
"\\([^\\]\\|^\\)\\(\\\\\\\\\\)?'"
|
|
here 'move)))
|
|
'string))
|
|
(t nil)))
|
|
) ; end-while
|
|
state)))
|
|
|
|
(and (memq 'Win-Emacs vhdl-emacs-features)
|
|
(fset 'vhdl-in-literal 'vhdl-win-il))
|
|
|
|
;; Skipping of "syntactic whitespace". Syntactic whitespace is
|
|
;; defined as lexical whitespace or comments. Search no farther back
|
|
;; or forward than optional LIM. If LIM is omitted, (point-min) is
|
|
;; used for backward skipping, (point-max) is used for forward
|
|
;; skipping.
|
|
|
|
(defun vhdl-forward-syntactic-ws (&optional lim)
|
|
;; Forward skip of syntactic whitespace.
|
|
(save-restriction
|
|
(let* ((lim (or lim (point-max)))
|
|
(here lim)
|
|
(hugenum (point-max)))
|
|
(narrow-to-region lim (point))
|
|
(while (/= here (point))
|
|
(setq here (point))
|
|
(forward-comment hugenum))
|
|
)))
|
|
|
|
;; This is the best we can do in Win-Emacs.
|
|
(defun vhdl-win-fsws (&optional lim)
|
|
;; Forward skip syntactic whitespace for Win-Emacs.
|
|
(let ((lim (or lim (point-max)))
|
|
stop)
|
|
(while (not stop)
|
|
(skip-chars-forward " \t\n\r\f" lim)
|
|
(cond
|
|
;; vhdl comment
|
|
((looking-at "--") (end-of-line))
|
|
;; none of the above
|
|
(t (setq stop t))
|
|
))))
|
|
|
|
(and (memq 'Win-Emacs vhdl-emacs-features)
|
|
(fset 'vhdl-forward-syntactic-ws 'vhdl-win-fsws))
|
|
|
|
(defun vhdl-backward-syntactic-ws (&optional lim)
|
|
;; Backward skip over syntactic whitespace.
|
|
(save-restriction
|
|
(let* ((lim (or lim (point-min)))
|
|
(here lim)
|
|
(hugenum (- (point-max))))
|
|
(if (< lim (point))
|
|
(progn
|
|
(narrow-to-region lim (point))
|
|
(while (/= here (point))
|
|
(setq here (point))
|
|
(forward-comment hugenum)
|
|
)))
|
|
)))
|
|
|
|
;; This is the best we can do in Win-Emacs.
|
|
(defun vhdl-win-bsws (&optional lim)
|
|
;; Backward skip syntactic whitespace for Win-Emacs.
|
|
(let ((lim (or lim (vhdl-point 'bod)))
|
|
stop)
|
|
(while (not stop)
|
|
(skip-chars-backward " \t\n\r\f" lim)
|
|
(cond
|
|
;; vhdl comment
|
|
((eq (vhdl-in-literal lim) 'comment)
|
|
(skip-chars-backward "^-" lim)
|
|
(skip-chars-backward "-" lim)
|
|
(while (not (or (and (= (following-char) ?-)
|
|
(= (char-after (1+ (point))) ?-))
|
|
(<= (point) lim)))
|
|
(skip-chars-backward "^-" lim)
|
|
(skip-chars-backward "-" lim)))
|
|
;; none of the above
|
|
(t (setq stop t))
|
|
))))
|
|
|
|
(and (memq 'Win-Emacs vhdl-emacs-features)
|
|
(fset 'vhdl-backward-syntactic-ws 'vhdl-win-bsws))
|
|
|
|
;; Functions to help finding the correct indentation column:
|
|
|
|
(defun vhdl-first-word (point)
|
|
"If the keyword at POINT is at boi, then return (current-column) at
|
|
that point, else nil."
|
|
(save-excursion
|
|
(and (goto-char point)
|
|
(eq (point) (vhdl-point 'boi))
|
|
(current-column))))
|
|
|
|
(defun vhdl-last-word (point)
|
|
"If the keyword at POINT is at eoi, then return (current-column) at
|
|
that point, else nil."
|
|
(save-excursion
|
|
(and (goto-char point)
|
|
(save-excursion (or (eq (progn (forward-sexp) (point))
|
|
(vhdl-point 'eoi))
|
|
(looking-at "\\s-*\\(--\\)?")))
|
|
(current-column))))
|
|
|
|
;; Core syntactic evaluation functions:
|
|
|
|
(defconst vhdl-libunit-re
|
|
"\\b\\(architecture\\|configuration\\|entity\\|package\\)\\b[^_]")
|
|
|
|
(defun vhdl-libunit-p ()
|
|
(and
|
|
(save-excursion
|
|
(forward-sexp)
|
|
(skip-chars-forward " \t\n")
|
|
(not (looking-at "is\\b[^_]")))
|
|
(save-excursion
|
|
(backward-sexp)
|
|
(and (not (looking-at "use\\b[^_]"))
|
|
(progn
|
|
(forward-sexp)
|
|
(vhdl-forward-syntactic-ws)
|
|
(/= (following-char) ?:))))
|
|
))
|
|
|
|
(defconst vhdl-defun-re
|
|
"\\b\\(architecture\\|block\\|configuration\\|entity\\|package\\|process\\|procedure\\|function\\)\\b[^_]")
|
|
|
|
(defun vhdl-defun-p ()
|
|
(save-excursion
|
|
(if (looking-at "block\\|process")
|
|
;; "block", "process":
|
|
(save-excursion
|
|
(backward-sexp)
|
|
(not (looking-at "end\\s-+\\w")))
|
|
;; "architecture", "configuration", "entity",
|
|
;; "package", "procedure", "function":
|
|
t)))
|
|
|
|
(defun vhdl-corresponding-defun ()
|
|
"If the word at the current position corresponds to a \"defun\"
|
|
keyword, then return a string that can be used to find the
|
|
corresponding \"begin\" keyword, else return nil."
|
|
(save-excursion
|
|
(and (looking-at vhdl-defun-re)
|
|
(vhdl-defun-p)
|
|
(if (looking-at "block\\|process")
|
|
;; "block", "process":
|
|
(buffer-substring (match-beginning 0) (match-end 0))
|
|
;; "architecture", "configuration", "entity", "package",
|
|
;; "procedure", "function":
|
|
"is"))))
|
|
|
|
(defconst vhdl-begin-fwd-re
|
|
"\\b\\(is\\|begin\\|block\\|component\\|generate\\|then\\|else\\|loop\\|process\\|units\\|record\\|for\\)\\b\\([^_]\\|\\'\\)"
|
|
"A regular expression for searching forward that matches all known
|
|
\"begin\" keywords.")
|
|
|
|
(defconst vhdl-begin-bwd-re
|
|
"\\b\\(is\\|begin\\|block\\|component\\|generate\\|then\\|else\\|loop\\|process\\|units\\|record\\|for\\)\\b[^_]"
|
|
"A regular expression for searching backward that matches all known
|
|
\"begin\" keywords.")
|
|
|
|
(defun vhdl-begin-p (&optional lim)
|
|
"Return t if we are looking at a real \"begin\" keyword.
|
|
Assumes that the caller will make sure that we are looking at
|
|
vhdl-begin-fwd-re, and are not inside a literal, and that we are not in
|
|
the middle of an identifier that just happens to contain a \"begin\"
|
|
keyword."
|
|
(cond
|
|
;; "[architecture|case|configuration|entity|package|
|
|
;; procedure|function] ... is":
|
|
((and (looking-at "i")
|
|
(save-excursion
|
|
;; Skip backward over first sexp (needed to skip over a
|
|
;; procedure interface list, and is harmless in other
|
|
;; situations). Note that we need "return" in the
|
|
;; following search list so that we don't run into
|
|
;; semicolons in the function interface list.
|
|
(backward-sexp)
|
|
(let (foundp)
|
|
(while (and (not foundp)
|
|
(re-search-backward
|
|
";\\|\\b\\(architecture\\|case\\|configuration\\|entity\\|package\\|procedure\\|return\\|is\\|begin\\|process\\|block\\)\\b[^_]"
|
|
lim 'move))
|
|
(if (or (= (preceding-char) ?_)
|
|
(vhdl-in-literal lim))
|
|
(backward-char)
|
|
(setq foundp t))))
|
|
(and (/= (following-char) ?\;)
|
|
(not (looking-at "is\\|begin\\|process\\|block")))))
|
|
t)
|
|
;; "begin", "then":
|
|
((looking-at "be\\|t")
|
|
t)
|
|
;; "else":
|
|
((and (looking-at "e")
|
|
;; make sure that the "else" isn't inside a
|
|
;; conditional signal assignment.
|
|
(save-excursion
|
|
(re-search-backward ";\\|\\bwhen\\b[^_]" lim 'move)
|
|
(or (eq (following-char) ?\;)
|
|
(eq (point) lim))))
|
|
t)
|
|
;; "block", "generate", "loop", "process",
|
|
;; "units", "record":
|
|
((and (looking-at "bl\\|[glpur]")
|
|
(save-excursion
|
|
(backward-sexp)
|
|
(not (looking-at "end\\s-+\\w"))))
|
|
t)
|
|
;; "component":
|
|
((and (looking-at "c")
|
|
(save-excursion
|
|
(backward-sexp)
|
|
(not (looking-at "end\\s-+\\w")))
|
|
;; look out for the dreaded entity class in an attribute
|
|
(save-excursion
|
|
(vhdl-backward-syntactic-ws lim)
|
|
(/= (preceding-char) ?:)))
|
|
t)
|
|
;; "for" (inside configuration declaration):
|
|
((and (looking-at "f")
|
|
(save-excursion
|
|
(backward-sexp)
|
|
(not (looking-at "end\\s-+\\w")))
|
|
(vhdl-has-syntax 'configuration))
|
|
t)
|
|
))
|
|
|
|
(defun vhdl-corresponding-mid (&optional lim)
|
|
(cond
|
|
((looking-at "is\\|block\\|process")
|
|
"begin")
|
|
((looking-at "then")
|
|
"<else>")
|
|
(t
|
|
"end")))
|
|
|
|
(defun vhdl-corresponding-end (&optional lim)
|
|
"If the word at the current position corresponds to a \"begin\"
|
|
keyword, then return a vector containing enough information to find
|
|
the corresponding \"end\" keyword, else return nil. The keyword to
|
|
search forward for is aref 0. The column in which the keyword must
|
|
appear is aref 1 or nil if any column is suitable.
|
|
Assumes that the caller will make sure that we are not in the middle
|
|
of an identifier that just happens to contain a \"begin\" keyword."
|
|
(save-excursion
|
|
(and (looking-at vhdl-begin-fwd-re)
|
|
(/= (preceding-char) ?_)
|
|
(not (vhdl-in-literal lim))
|
|
(vhdl-begin-p lim)
|
|
(cond
|
|
;; "is", "generate", "loop":
|
|
((looking-at "[igl]")
|
|
(vector "end"
|
|
(and (vhdl-last-word (point))
|
|
(or (vhdl-first-word (point))
|
|
(save-excursion
|
|
(vhdl-beginning-of-statement-1 lim)
|
|
(vhdl-backward-skip-label lim)
|
|
(vhdl-first-word (point)))))))
|
|
;; "begin", "else", "for":
|
|
((looking-at "be\\|[ef]")
|
|
(vector "end"
|
|
(and (vhdl-last-word (point))
|
|
(or (vhdl-first-word (point))
|
|
(save-excursion
|
|
(vhdl-beginning-of-statement-1 lim)
|
|
(vhdl-backward-skip-label lim)
|
|
(vhdl-first-word (point)))))))
|
|
;; "component", "units", "record":
|
|
((looking-at "[cur]")
|
|
;; The first end found will close the block
|
|
(vector "end" nil))
|
|
;; "block", "process":
|
|
((looking-at "bl\\|p")
|
|
(vector "end"
|
|
(or (vhdl-first-word (point))
|
|
(save-excursion
|
|
(vhdl-beginning-of-statement-1 lim)
|
|
(vhdl-backward-skip-label lim)
|
|
(vhdl-first-word (point))))))
|
|
;; "then":
|
|
((looking-at "t")
|
|
(vector "elsif\\|else\\|end\\s-+if"
|
|
(and (vhdl-last-word (point))
|
|
(or (vhdl-first-word (point))
|
|
(save-excursion
|
|
(vhdl-beginning-of-statement-1 lim)
|
|
(vhdl-backward-skip-label lim)
|
|
(vhdl-first-word (point)))))))
|
|
))))
|
|
|
|
(defconst vhdl-end-fwd-re "\\b\\(end\\|else\\|elsif\\)\\b\\([^_]\\|\\'\\)")
|
|
|
|
(defconst vhdl-end-bwd-re "\\b\\(end\\|else\\|elsif\\)\\b[^_]")
|
|
|
|
(defun vhdl-end-p (&optional lim)
|
|
"Return t if we are looking at a real \"end\" keyword.
|
|
Assumes that the caller will make sure that we are looking at
|
|
vhdl-end-fwd-re, and are not inside a literal, and that we are not in
|
|
the middle of an identifier that just happens to contain an \"end\"
|
|
keyword."
|
|
(or (not (looking-at "else"))
|
|
;; make sure that the "else" isn't inside a conditional signal
|
|
;; assignment.
|
|
(save-excursion
|
|
(re-search-backward ";\\|\\bwhen\\b[^_]" lim 'move)
|
|
(or (eq (following-char) ?\;)
|
|
(eq (point) lim)))))
|
|
|
|
(defun vhdl-corresponding-begin (&optional lim)
|
|
"If the word at the current position corresponds to an \"end\"
|
|
keyword, then return a vector containing enough information to find
|
|
the corresponding \"begin\" keyword, else return nil. The keyword to
|
|
search backward for is aref 0. The column in which the keyword must
|
|
appear is aref 1 or nil if any column is suitable. The supplementary
|
|
keyword to search forward for is aref 2 or nil if this is not
|
|
required. If aref 3 is t, then the \"begin\" keyword may be found in
|
|
the middle of a statement.
|
|
Assumes that the caller will make sure that we are not in the middle
|
|
of an identifier that just happens to contain an \"end\" keyword."
|
|
(save-excursion
|
|
(let (pos)
|
|
(if (and (looking-at vhdl-end-fwd-re)
|
|
(not (vhdl-in-literal lim))
|
|
(vhdl-end-p lim))
|
|
(if (looking-at "el")
|
|
;; "else", "elsif":
|
|
(vector "if\\|elsif" (vhdl-first-word (point)) "then" nil)
|
|
;; "end ...":
|
|
(setq pos (point))
|
|
(forward-sexp)
|
|
(skip-chars-forward " \t\n")
|
|
(cond
|
|
;; "end if":
|
|
((looking-at "if\\b[^_]")
|
|
(vector "else\\|elsif\\|if"
|
|
(vhdl-first-word pos)
|
|
"else\\|then" nil))
|
|
;; "end component":
|
|
((looking-at "component\\b[^_]")
|
|
(vector (buffer-substring (match-beginning 1)
|
|
(match-end 1))
|
|
(vhdl-first-word pos)
|
|
nil nil))
|
|
;; "end units", "end record":
|
|
((looking-at "\\(units\\|record\\)\\b[^_]")
|
|
(vector (buffer-substring (match-beginning 1)
|
|
(match-end 1))
|
|
(vhdl-first-word pos)
|
|
nil t))
|
|
;; "end block", "end process":
|
|
((looking-at "\\(block\\|process\\)\\b[^_]")
|
|
(vector "begin" (vhdl-first-word pos) nil nil))
|
|
;; "end case":
|
|
((looking-at "case\\b[^_]")
|
|
(vector "case" (vhdl-first-word pos) "is" nil))
|
|
;; "end generate":
|
|
((looking-at "generate\\b[^_]")
|
|
(vector "generate\\|for\\|if"
|
|
(vhdl-first-word pos)
|
|
"generate" nil))
|
|
;; "end loop":
|
|
((looking-at "loop\\b[^_]")
|
|
(vector "loop\\|while\\|for"
|
|
(vhdl-first-word pos)
|
|
"loop" nil))
|
|
;; "end for" (inside configuration declaration):
|
|
((looking-at "for\\b[^_]")
|
|
(vector "for" (vhdl-first-word pos) nil nil))
|
|
;; "end [id]":
|
|
(t
|
|
(vector "begin\\|architecture\\|configuration\\|entity\\|package\\|procedure\\|function"
|
|
(vhdl-first-word pos)
|
|
;; return an alist of (statement . keyword) mappings
|
|
'(
|
|
;; "begin ... end [id]":
|
|
("begin" . nil)
|
|
;; "architecture ... is ... begin ... end [id]":
|
|
("architecture" . "is")
|
|
;; "configuration ... is ... end [id]":
|
|
("configuration" . "is")
|
|
;; "entity ... is ... end [id]":
|
|
("entity" . "is")
|
|
;; "package ... is ... end [id]":
|
|
("package" . "is")
|
|
;; "procedure ... is ... begin ... end [id]":
|
|
("procedure" . "is")
|
|
;; "function ... is ... begin ... end [id]":
|
|
("function" . "is")
|
|
)
|
|
nil))
|
|
))) ; "end ..."
|
|
)))
|
|
|
|
(defconst vhdl-leader-re
|
|
"\\b\\(block\\|component\\|process\\|for\\)\\b[^_]")
|
|
|
|
(defun vhdl-end-of-leader ()
|
|
(save-excursion
|
|
(cond ((looking-at "block\\|process")
|
|
(if (save-excursion
|
|
(forward-sexp)
|
|
(skip-chars-forward " \t\n")
|
|
(= (following-char) ?\())
|
|
(forward-sexp 2)
|
|
(forward-sexp))
|
|
(point))
|
|
((looking-at "component")
|
|
(forward-sexp 2)
|
|
(point))
|
|
((looking-at "for")
|
|
(forward-sexp 2)
|
|
(skip-chars-forward " \t\n")
|
|
(while (looking-at "[,:(]")
|
|
(forward-sexp)
|
|
(skip-chars-forward " \t\n"))
|
|
(point))
|
|
(t nil)
|
|
)))
|
|
|
|
(defconst vhdl-trailer-re
|
|
"\\b\\(is\\|then\\|generate\\|loop\\)\\b[^_]")
|
|
|
|
(defconst vhdl-statement-fwd-re
|
|
"\\b\\(if\\|for\\|while\\)\\b\\([^_]\\|\\'\\)"
|
|
"A regular expression for searching forward that matches all known
|
|
\"statement\" keywords.")
|
|
|
|
(defconst vhdl-statement-bwd-re
|
|
"\\b\\(if\\|for\\|while\\)\\b[^_]"
|
|
"A regular expression for searching backward that matches all known
|
|
\"statement\" keywords.")
|
|
|
|
(defun vhdl-statement-p (&optional lim)
|
|
"Return t if we are looking at a real \"statement\" keyword.
|
|
Assumes that the caller will make sure that we are looking at
|
|
vhdl-statement-fwd-re, and are not inside a literal, and that we are not in
|
|
the middle of an identifier that just happens to contain a \"statement\"
|
|
keyword."
|
|
(cond
|
|
;; "for" ... "generate":
|
|
((and (looking-at "f")
|
|
;; Make sure it's the start of a parameter specification.
|
|
(save-excursion
|
|
(forward-sexp 2)
|
|
(skip-chars-forward " \t\n")
|
|
(looking-at "in\\b[^_]"))
|
|
;; Make sure it's not an "end for".
|
|
(save-excursion
|
|
(backward-sexp)
|
|
(not (looking-at "end\\s-+\\w"))))
|
|
t)
|
|
;; "if" ... "then", "if" ... "generate", "if" ... "loop":
|
|
((and (looking-at "i")
|
|
;; Make sure it's not an "end if".
|
|
(save-excursion
|
|
(backward-sexp)
|
|
(not (looking-at "end\\s-+\\w"))))
|
|
t)
|
|
;; "while" ... "loop":
|
|
((looking-at "w")
|
|
t)
|
|
))
|
|
|
|
(defconst vhdl-case-alternative-re "when[( \t\n][^;=>]+=>"
|
|
"Regexp describing a case statement alternative key.")
|
|
|
|
(defun vhdl-case-alternative-p (&optional lim)
|
|
"Return t if we are looking at a real case alternative.
|
|
Assumes that the caller will make sure that we are looking at
|
|
vhdl-case-alternative-re, and are not inside a literal, and that
|
|
we are not in the middle of an identifier that just happens to
|
|
contain a \"when\" keyword."
|
|
(save-excursion
|
|
(let (foundp)
|
|
(while (and (not foundp)
|
|
(re-search-backward ";\\|<=" lim 'move))
|
|
(if (or (= (preceding-char) ?_)
|
|
(vhdl-in-literal lim))
|
|
(backward-char)
|
|
(setq foundp t)))
|
|
(or (eq (following-char) ?\;)
|
|
(eq (point) lim)))
|
|
))
|
|
|
|
;; Core syntactic movement functions:
|
|
|
|
(defconst vhdl-b-t-b-re
|
|
(concat vhdl-begin-bwd-re "\\|" vhdl-end-bwd-re))
|
|
|
|
(defun vhdl-backward-to-block (&optional lim)
|
|
"Move backward to the previous \"begin\" or \"end\" keyword."
|
|
(let (foundp)
|
|
(while (and (not foundp)
|
|
(re-search-backward vhdl-b-t-b-re lim 'move))
|
|
(if (or (= (preceding-char) ?_)
|
|
(vhdl-in-literal lim))
|
|
(backward-char)
|
|
(cond
|
|
;; "begin" keyword:
|
|
((and (looking-at vhdl-begin-fwd-re)
|
|
(/= (preceding-char) ?_)
|
|
(vhdl-begin-p lim))
|
|
(setq foundp 'begin))
|
|
;; "end" keyword:
|
|
((and (looking-at vhdl-end-fwd-re)
|
|
(/= (preceding-char) ?_)
|
|
(vhdl-end-p lim))
|
|
(setq foundp 'end))
|
|
))
|
|
)
|
|
foundp
|
|
))
|
|
|
|
(defun vhdl-forward-sexp (&optional count lim)
|
|
"Move forward across one balanced expression (sexp).
|
|
With COUNT, do it that many times."
|
|
(interactive "p")
|
|
(let ((count (or count 1))
|
|
(case-fold-search t)
|
|
end-vec target)
|
|
(save-excursion
|
|
(while (> count 0)
|
|
;; skip whitespace
|
|
(skip-chars-forward " \t\n")
|
|
;; Check for an unbalanced "end" keyword
|
|
(if (and (looking-at vhdl-end-fwd-re)
|
|
(/= (preceding-char) ?_)
|
|
(not (vhdl-in-literal lim))
|
|
(vhdl-end-p lim)
|
|
(not (looking-at "else")))
|
|
(error
|
|
"Containing expression ends prematurely in vhdl-forward-sexp"))
|
|
;; If the current keyword is a "begin" keyword, then find the
|
|
;; corresponding "end" keyword.
|
|
(if (setq end-vec (vhdl-corresponding-end lim))
|
|
(let (
|
|
;; end-re is the statement keyword to search for
|
|
(end-re
|
|
(concat "\\b\\(" (aref end-vec 0) "\\)\\b\\([^_]\\|\\'\\)"))
|
|
;; column is either the statement keyword target column
|
|
;; or nil
|
|
(column (aref end-vec 1))
|
|
(eol (vhdl-point 'eol))
|
|
foundp literal placeholder)
|
|
;; Look for the statement keyword.
|
|
(while (and (not foundp)
|
|
(re-search-forward end-re nil t)
|
|
(setq placeholder (match-end 1))
|
|
(goto-char (match-beginning 0)))
|
|
;; If we are in a literal, or not in the right target
|
|
;; column and not on the same line as the begin, then
|
|
;; try again.
|
|
(if (or (and column
|
|
(/= (current-indentation) column)
|
|
(> (point) eol))
|
|
(= (preceding-char) ?_)
|
|
(setq literal (vhdl-in-literal lim)))
|
|
(if (eq literal 'comment)
|
|
(end-of-line)
|
|
(forward-char))
|
|
;; An "else" keyword corresponds to both the opening brace
|
|
;; of the following sexp and the closing brace of the
|
|
;; previous sexp.
|
|
(if (not (looking-at "else"))
|
|
(goto-char placeholder))
|
|
(setq foundp t))
|
|
)
|
|
(if (not foundp)
|
|
(error "Unbalanced keywords in vhdl-forward-sexp"))
|
|
)
|
|
;; If the current keyword is not a "begin" keyword, then just
|
|
;; perform the normal forward-sexp.
|
|
(forward-sexp)
|
|
)
|
|
(setq count (1- count))
|
|
)
|
|
(setq target (point)))
|
|
(goto-char target)
|
|
nil))
|
|
|
|
(defun vhdl-backward-sexp (&optional count lim)
|
|
"Move backward across one balanced expression (sexp).
|
|
With COUNT, do it that many times. LIM bounds any required backward
|
|
searches."
|
|
(interactive "p")
|
|
(let ((count (or count 1))
|
|
(case-fold-search t)
|
|
begin-vec target)
|
|
(save-excursion
|
|
(while (> count 0)
|
|
;; Perform the normal backward-sexp, unless we are looking at
|
|
;; "else" - an "else" keyword corresponds to both the opening brace
|
|
;; of the following sexp and the closing brace of the previous sexp.
|
|
(if (and (looking-at "else\\b\\([^_]\\|\\'\\)")
|
|
(/= (preceding-char) ?_)
|
|
(not (vhdl-in-literal lim)))
|
|
nil
|
|
(backward-sexp)
|
|
(if (and (looking-at vhdl-begin-fwd-re)
|
|
(/= (preceding-char) ?_)
|
|
(not (vhdl-in-literal lim))
|
|
(vhdl-begin-p lim))
|
|
(error "Containing expression ends prematurely in vhdl-backward-sexp")))
|
|
;; If the current keyword is an "end" keyword, then find the
|
|
;; corresponding "begin" keyword.
|
|
(if (and (setq begin-vec (vhdl-corresponding-begin lim))
|
|
(/= (preceding-char) ?_))
|
|
(let (
|
|
;; begin-re is the statement keyword to search for
|
|
(begin-re
|
|
(concat "\\b\\(" (aref begin-vec 0) "\\)\\b[^_]"))
|
|
;; column is either the statement keyword target column
|
|
;; or nil
|
|
(column (aref begin-vec 1))
|
|
;; internal-p controls where the statement keyword can
|
|
;; be found.
|
|
(internal-p (aref begin-vec 3))
|
|
(last-backward (point)) last-forward
|
|
foundp literal keyword)
|
|
;; Look for the statement keyword.
|
|
(while (and (not foundp)
|
|
(re-search-backward begin-re lim t)
|
|
(setq keyword
|
|
(buffer-substring (match-beginning 1)
|
|
(match-end 1))))
|
|
;; If we are in a literal or in the wrong column,
|
|
;; then try again.
|
|
(if (or (and column
|
|
(and (/= (current-indentation) column)
|
|
;; possibly accept current-column as
|
|
;; well as current-indentation.
|
|
(or (not internal-p)
|
|
(/= (current-column) column))))
|
|
(= (preceding-char) ?_)
|
|
(vhdl-in-literal lim))
|
|
(backward-char)
|
|
;; If there is a supplementary keyword, then
|
|
;; search forward for it.
|
|
(if (and (setq begin-re (aref begin-vec 2))
|
|
(or (not (listp begin-re))
|
|
;; If begin-re is an alist, then find the
|
|
;; element corresponding to the actual
|
|
;; keyword that we found.
|
|
(progn
|
|
(setq begin-re
|
|
(assoc keyword begin-re))
|
|
(and begin-re
|
|
(setq begin-re (cdr begin-re))))))
|
|
(and
|
|
(setq begin-re
|
|
(concat "\\b\\(" begin-re "\\)\\b[^_]"))
|
|
(save-excursion
|
|
(setq last-forward (point))
|
|
;; Look for the supplementary keyword
|
|
;; (bounded by the backward search start
|
|
;; point).
|
|
(while (and (not foundp)
|
|
(re-search-forward begin-re
|
|
last-backward t)
|
|
(goto-char (match-beginning 1)))
|
|
;; If we are in a literal, then try again.
|
|
(if (or (= (preceding-char) ?_)
|
|
(setq literal
|
|
(vhdl-in-literal last-forward)))
|
|
(if (eq literal 'comment)
|
|
(goto-char
|
|
(min (vhdl-point 'eol) last-backward))
|
|
(forward-char))
|
|
;; We have found the supplementary keyword.
|
|
;; Save the position of the keyword in foundp.
|
|
(setq foundp (point)))
|
|
)
|
|
foundp)
|
|
;; If the supplementary keyword was found, then
|
|
;; move point to the supplementary keyword.
|
|
(goto-char foundp))
|
|
;; If there was no supplementary keyword, then
|
|
;; point is already at the statement keyword.
|
|
(setq foundp t)))
|
|
) ; end of the search for the statement keyword
|
|
(if (not foundp)
|
|
(error "Unbalanced keywords in vhdl-backward-sexp"))
|
|
))
|
|
(setq count (1- count))
|
|
)
|
|
(setq target (point)))
|
|
(goto-char target)
|
|
nil))
|
|
|
|
(defun vhdl-backward-up-list (&optional count limit)
|
|
"Move backward out of one level of blocks.
|
|
With argument, do this that many times."
|
|
(interactive "p")
|
|
(let ((count (or count 1))
|
|
target)
|
|
(save-excursion
|
|
(while (> count 0)
|
|
(if (looking-at vhdl-defun-re)
|
|
(error "Unbalanced blocks"))
|
|
(vhdl-backward-to-block limit)
|
|
(setq count (1- count)))
|
|
(setq target (point)))
|
|
(goto-char target)))
|
|
|
|
(defun vhdl-end-of-defun (&optional count)
|
|
"Move forward to the end of a VHDL defun."
|
|
(interactive)
|
|
(let ((case-fold-search t))
|
|
(vhdl-beginning-of-defun)
|
|
(if (not (looking-at "block\\|process"))
|
|
(re-search-forward "\\bis\\b"))
|
|
(vhdl-forward-sexp)))
|
|
|
|
(defun vhdl-mark-defun ()
|
|
"Put mark at end of this \"defun\", point at beginning."
|
|
(interactive)
|
|
(let ((case-fold-search t))
|
|
(push-mark)
|
|
(vhdl-beginning-of-defun)
|
|
(push-mark)
|
|
(if (not (looking-at "block\\|process"))
|
|
(re-search-forward "\\bis\\b"))
|
|
(vhdl-forward-sexp)
|
|
(exchange-point-and-mark)))
|
|
|
|
(defun vhdl-beginning-of-libunit ()
|
|
"Move backward to the beginning of a VHDL library unit.
|
|
Returns the location of the corresponding begin keyword, unless search
|
|
stops due to beginning or end of buffer."
|
|
;; Note that if point is between the "libunit" keyword and the
|
|
;; corresponding "begin" keyword, then that libunit will not be
|
|
;; recognised, and the search will continue backwards. If point is
|
|
;; at the "begin" keyword, then the defun will be recognised. The
|
|
;; returned point is at the first character of the "libunit" keyword.
|
|
(let ((last-forward (point))
|
|
(last-backward
|
|
;; Just in case we are actually sitting on the "begin"
|
|
;; keyword, allow for the keyword and an extra character,
|
|
;; as this will be used when looking forward for the
|
|
;; "begin" keyword.
|
|
(save-excursion (forward-word 1) (1+ (point))))
|
|
foundp literal placeholder)
|
|
;; Find the "libunit" keyword.
|
|
(while (and (not foundp)
|
|
(re-search-backward vhdl-libunit-re nil 'move))
|
|
;; If we are in a literal, or not at a real libunit, then try again.
|
|
(if (or (= (preceding-char) ?_)
|
|
(vhdl-in-literal (point-min))
|
|
(not (vhdl-libunit-p)))
|
|
(backward-char)
|
|
;; Find the corresponding "begin" keyword.
|
|
(setq last-forward (point))
|
|
(while (and (not foundp)
|
|
(re-search-forward "\\bis\\b[^_]" last-backward t)
|
|
(setq placeholder (match-beginning 0)))
|
|
(if (or (= (preceding-char) ?_)
|
|
(setq literal (vhdl-in-literal last-forward)))
|
|
;; It wasn't a real keyword, so keep searching.
|
|
(if (eq literal 'comment)
|
|
(goto-char
|
|
(min (vhdl-point 'eol) last-backward))
|
|
(forward-char))
|
|
;; We have found the begin keyword, loop will exit.
|
|
(setq foundp placeholder)))
|
|
;; Go back to the libunit keyword
|
|
(goto-char last-forward)))
|
|
foundp))
|
|
|
|
(defun vhdl-beginning-of-defun (&optional count)
|
|
"Move backward to the beginning of a VHDL defun.
|
|
With argument, do it that many times.
|
|
Returns the location of the corresponding begin keyword, unless search
|
|
stops due to beginning or end of buffer."
|
|
;; Note that if point is between the "defun" keyword and the
|
|
;; corresponding "begin" keyword, then that defun will not be
|
|
;; recognised, and the search will continue backwards. If point is
|
|
;; at the "begin" keyword, then the defun will be recognised. The
|
|
;; returned point is at the first character of the "defun" keyword.
|
|
(interactive "p")
|
|
(let ((count (or count 1))
|
|
(case-fold-search t)
|
|
(last-forward (point))
|
|
foundp)
|
|
(while (> count 0)
|
|
(setq foundp nil)
|
|
(goto-char last-forward)
|
|
(let ((last-backward
|
|
;; Just in case we are actually sitting on the "begin"
|
|
;; keyword, allow for the keyword and an extra character,
|
|
;; as this will be used when looking forward for the
|
|
;; "begin" keyword.
|
|
(save-excursion (forward-word 1) (1+ (point))))
|
|
begin-string literal)
|
|
(while (and (not foundp)
|
|
(re-search-backward vhdl-defun-re nil 'move))
|
|
;; If we are in a literal, then try again.
|
|
(if (or (= (preceding-char) ?_)
|
|
(vhdl-in-literal (point-min)))
|
|
(backward-char)
|
|
(if (setq begin-string (vhdl-corresponding-defun))
|
|
;; This is a real defun keyword.
|
|
;; Find the corresponding "begin" keyword.
|
|
;; Look for the begin keyword.
|
|
(progn
|
|
;; Save the search start point.
|
|
(setq last-forward (point))
|
|
(while (and (not foundp)
|
|
(search-forward begin-string last-backward t))
|
|
(if (or (= (preceding-char) ?_)
|
|
(save-match-data
|
|
(setq literal (vhdl-in-literal last-forward))))
|
|
;; It wasn't a real keyword, so keep searching.
|
|
(if (eq literal 'comment)
|
|
(goto-char
|
|
(min (vhdl-point 'eol) last-backward))
|
|
(forward-char))
|
|
;; We have found the begin keyword, loop will exit.
|
|
(setq foundp (match-beginning 0)))
|
|
)
|
|
;; Go back to the defun keyword
|
|
(goto-char last-forward)) ; end search for begin keyword
|
|
))
|
|
) ; end of the search for the defun keyword
|
|
)
|
|
(setq count (1- count))
|
|
)
|
|
(vhdl-keep-region-active)
|
|
foundp))
|
|
|
|
(defun vhdl-beginning-of-statement (&optional count lim)
|
|
"Go to the beginning of the innermost VHDL statement.
|
|
With prefix arg, go back N - 1 statements. If already at the
|
|
beginning of a statement then go to the beginning of the preceding
|
|
one. If within a string or comment, or next to a comment (only
|
|
whitespace between), move by sentences instead of statements.
|
|
|
|
When called from a program, this function takes 2 optional args: the
|
|
prefix arg, and a buffer position limit which is the farthest back to
|
|
search."
|
|
(interactive "p")
|
|
(let ((count (or count 1))
|
|
(case-fold-search t)
|
|
(lim (or lim (point-min)))
|
|
(here (point))
|
|
state)
|
|
(save-excursion
|
|
(goto-char lim)
|
|
(setq state (parse-partial-sexp (point) here nil nil)))
|
|
(if (and (interactive-p)
|
|
(or (nth 3 state)
|
|
(nth 4 state)
|
|
(looking-at (concat "[ \t]*" comment-start-skip))))
|
|
(forward-sentence (- count))
|
|
(while (> count 0)
|
|
(vhdl-beginning-of-statement-1 lim)
|
|
(setq count (1- count))))
|
|
;; its possible we've been left up-buf of lim
|
|
(goto-char (max (point) lim))
|
|
)
|
|
(vhdl-keep-region-active))
|
|
|
|
(defconst vhdl-e-o-s-re
|
|
(concat ";\\|" vhdl-begin-fwd-re "\\|" vhdl-statement-fwd-re))
|
|
|
|
(defun vhdl-end-of-statement ()
|
|
"Very simple implementation."
|
|
(interactive)
|
|
(re-search-forward vhdl-e-o-s-re))
|
|
|
|
(defconst vhdl-b-o-s-re
|
|
(concat ";\\|\(\\|\)\\|\\bwhen\\b[^_]\\|"
|
|
vhdl-begin-bwd-re "\\|" vhdl-statement-bwd-re))
|
|
|
|
(defun vhdl-beginning-of-statement-1 (&optional lim)
|
|
;; move to the start of the current statement, or the previous
|
|
;; statement if already at the beginning of one.
|
|
(let ((lim (or lim (point-min)))
|
|
(here (point))
|
|
(pos (point))
|
|
donep)
|
|
;; go backwards one balanced expression, but be careful of
|
|
;; unbalanced paren being reached
|
|
(if (not (vhdl-safe (progn (backward-sexp) t)))
|
|
(progn
|
|
(backward-up-list 1)
|
|
(forward-char)
|
|
(vhdl-forward-syntactic-ws here)
|
|
(setq donep t)))
|
|
(while (and (not donep)
|
|
(not (bobp))
|
|
;; look backwards for a statement boundary
|
|
(re-search-backward vhdl-b-o-s-re lim 'move))
|
|
(if (or (= (preceding-char) ?_)
|
|
(vhdl-in-literal lim))
|
|
(backward-char)
|
|
(cond
|
|
;; If we are looking at an open paren, then stop after it
|
|
((eq (following-char) ?\()
|
|
(forward-char)
|
|
(vhdl-forward-syntactic-ws here)
|
|
(setq donep t))
|
|
;; If we are looking at a close paren, then skip it
|
|
((eq (following-char) ?\))
|
|
(forward-char)
|
|
(setq pos (point))
|
|
(backward-sexp)
|
|
(if (< (point) lim)
|
|
(progn (goto-char pos)
|
|
(vhdl-forward-syntactic-ws here)
|
|
(setq donep t))))
|
|
;; If we are looking at a semicolon, then stop
|
|
((eq (following-char) ?\;)
|
|
(progn
|
|
(forward-char)
|
|
(vhdl-forward-syntactic-ws here)
|
|
(setq donep t)))
|
|
;; If we are looking at a "begin", then stop
|
|
((and (looking-at vhdl-begin-fwd-re)
|
|
(/= (preceding-char) ?_)
|
|
(vhdl-begin-p nil))
|
|
;; If it's a leader "begin", then find the
|
|
;; right place
|
|
(if (looking-at vhdl-leader-re)
|
|
(save-excursion
|
|
;; set a default stop point at the begin
|
|
(setq pos (point))
|
|
;; is the start point inside the leader area ?
|
|
(goto-char (vhdl-end-of-leader))
|
|
(vhdl-forward-syntactic-ws here)
|
|
(if (< (point) here)
|
|
;; start point was not inside leader area
|
|
;; set stop point at word after leader
|
|
(setq pos (point))))
|
|
(forward-word 1)
|
|
(vhdl-forward-syntactic-ws here)
|
|
(setq pos (point)))
|
|
(goto-char pos)
|
|
(setq donep t))
|
|
;; If we are looking at a "statement", then stop
|
|
((and (looking-at vhdl-statement-fwd-re)
|
|
(/= (preceding-char) ?_)
|
|
(vhdl-statement-p nil))
|
|
(setq donep t))
|
|
;; If we are looking at a case alternative key, then stop
|
|
((and (looking-at vhdl-case-alternative-re)
|
|
(vhdl-case-alternative-p lim))
|
|
(save-excursion
|
|
;; set a default stop point at the when
|
|
(setq pos (point))
|
|
;; is the start point inside the case alternative key ?
|
|
(looking-at vhdl-case-alternative-re)
|
|
(goto-char (match-end 0))
|
|
(vhdl-forward-syntactic-ws here)
|
|
(if (< (point) here)
|
|
;; start point was not inside the case alternative key
|
|
;; set stop point at word after case alternative keyleader
|
|
(setq pos (point))))
|
|
(goto-char pos)
|
|
(setq donep t))
|
|
;; Bogus find, continue
|
|
(t
|
|
(backward-char)))))
|
|
))
|
|
|
|
;; Defuns for calculating the current syntactic state:
|
|
|
|
(defun vhdl-get-library-unit (bod placeholder)
|
|
;; If there is an enclosing library unit at bod, with it's \"begin\"
|
|
;; keyword at placeholder, then return the library unit type.
|
|
(let ((here (vhdl-point 'bol)))
|
|
(if (save-excursion
|
|
(goto-char placeholder)
|
|
(vhdl-safe (vhdl-forward-sexp 1 bod))
|
|
(<= here (point)))
|
|
(save-excursion
|
|
(goto-char bod)
|
|
(cond
|
|
((looking-at "e") 'entity)
|
|
((looking-at "a") 'architecture)
|
|
((looking-at "c") 'configuration)
|
|
((looking-at "p")
|
|
(save-excursion
|
|
(goto-char bod)
|
|
(forward-sexp)
|
|
(vhdl-forward-syntactic-ws here)
|
|
(if (looking-at "body\\b[^_]")
|
|
'package-body 'package))))))
|
|
))
|
|
|
|
(defun vhdl-get-block-state (&optional lim)
|
|
;; Finds and records all the closest opens.
|
|
;; lim is the furthest back we need to search (it should be the
|
|
;; previous libunit keyword).
|
|
(let ((here (point))
|
|
(lim (or lim (point-min)))
|
|
keyword sexp-start sexp-mid sexp-end
|
|
preceding-sexp containing-sexp
|
|
containing-begin containing-mid containing-paren)
|
|
(save-excursion
|
|
;; Find the containing-paren, and use that as the limit
|
|
(if (setq containing-paren
|
|
(save-restriction
|
|
(narrow-to-region lim (point))
|
|
(vhdl-safe (scan-lists (point) -1 1))))
|
|
(setq lim containing-paren))
|
|
;; Look backwards for "begin" and "end" keywords.
|
|
(while (and (> (point) lim)
|
|
(not containing-sexp))
|
|
(setq keyword (vhdl-backward-to-block lim))
|
|
(cond
|
|
((eq keyword 'begin)
|
|
;; Found a "begin" keyword
|
|
(setq sexp-start (point))
|
|
(setq sexp-mid (vhdl-corresponding-mid lim))
|
|
(setq sexp-end (vhdl-safe
|
|
(save-excursion
|
|
(vhdl-forward-sexp 1 lim) (point))))
|
|
(if (and sexp-end (<= sexp-end here))
|
|
;; we want to record this sexp, but we only want to
|
|
;; record the last-most of any of them before here
|
|
(or preceding-sexp
|
|
(setq preceding-sexp sexp-start))
|
|
;; we're contained in this sexp so put sexp-start on
|
|
;; front of list
|
|
(setq containing-sexp sexp-start)
|
|
(setq containing-mid sexp-mid)
|
|
(setq containing-begin t)))
|
|
((eq keyword 'end)
|
|
;; Found an "end" keyword
|
|
(forward-sexp)
|
|
(setq sexp-end (point))
|
|
(setq sexp-mid nil)
|
|
(setq sexp-start
|
|
(or (vhdl-safe (vhdl-backward-sexp 1 lim) (point))
|
|
(progn (backward-sexp) (point))))
|
|
;; we want to record this sexp, but we only want to
|
|
;; record the last-most of any of them before here
|
|
(or preceding-sexp
|
|
(setq preceding-sexp sexp-start)))
|
|
)))
|
|
;; Check if the containing-paren should be the containing-sexp
|
|
(if (and containing-paren
|
|
(or (null containing-sexp)
|
|
(< containing-sexp containing-paren)))
|
|
(setq containing-sexp containing-paren
|
|
preceding-sexp nil
|
|
containing-begin nil
|
|
containing-mid nil))
|
|
(vector containing-sexp preceding-sexp containing-begin containing-mid)
|
|
))
|
|
|
|
|
|
(defconst vhdl-s-c-a-re
|
|
(concat vhdl-case-alternative-re "\\|" vhdl-case-header-key))
|
|
|
|
(defun vhdl-skip-case-alternative (&optional lim)
|
|
;; skip forward over case/when bodies, with optional maximal
|
|
;; limit. if no next case alternative is found, nil is returned and point
|
|
;; is not moved
|
|
(let ((lim (or lim (point-max)))
|
|
(here (point))
|
|
donep foundp)
|
|
(while (and (< (point) lim)
|
|
(not donep))
|
|
(if (and (re-search-forward vhdl-s-c-a-re lim 'move)
|
|
(save-match-data
|
|
(not (vhdl-in-literal)))
|
|
(/= (match-beginning 0) here))
|
|
(progn
|
|
(goto-char (match-beginning 0))
|
|
(cond
|
|
((and (looking-at "case")
|
|
(re-search-forward "\\bis[^_]" lim t))
|
|
(backward-sexp)
|
|
(vhdl-forward-sexp))
|
|
(t
|
|
(setq donep t
|
|
foundp t))))))
|
|
(if (not foundp)
|
|
(goto-char here))
|
|
foundp))
|
|
|
|
(defun vhdl-backward-skip-label (&optional lim)
|
|
;; skip backward over a label, with optional maximal
|
|
;; limit. if label is not found, nil is returned and point
|
|
;; is not moved
|
|
(let ((lim (or lim (point-min)))
|
|
placeholder)
|
|
(if (save-excursion
|
|
(vhdl-backward-syntactic-ws lim)
|
|
(and (eq (preceding-char) ?:)
|
|
(progn
|
|
(backward-sexp)
|
|
(setq placeholder (point))
|
|
(looking-at vhdl-label-key))))
|
|
(goto-char placeholder))
|
|
))
|
|
|
|
(defun vhdl-forward-skip-label (&optional lim)
|
|
;; skip forward over a label, with optional maximal
|
|
;; limit. if label is not found, nil is returned and point
|
|
;; is not moved
|
|
(let ((lim (or lim (point-max))))
|
|
(if (looking-at vhdl-label-key)
|
|
(progn
|
|
(goto-char (match-end 0))
|
|
(vhdl-forward-syntactic-ws lim)))
|
|
))
|
|
|
|
(defun vhdl-get-syntactic-context ()
|
|
;; guess the syntactic description of the current line of VHDL code.
|
|
(save-excursion
|
|
(save-restriction
|
|
(beginning-of-line)
|
|
(let* ((indent-point (point))
|
|
(case-fold-search t)
|
|
vec literal containing-sexp preceding-sexp
|
|
containing-begin containing-mid containing-leader
|
|
char-before-ip char-after-ip begin-after-ip end-after-ip
|
|
placeholder lim library-unit
|
|
)
|
|
|
|
;; Reset the syntactic context
|
|
(setq vhdl-syntactic-context nil)
|
|
|
|
(save-excursion
|
|
;; Move to the start of the previous library unit, and
|
|
;; record the position of the "begin" keyword.
|
|
(setq placeholder (vhdl-beginning-of-libunit))
|
|
;; The position of the "libunit" keyword gives us a gross
|
|
;; limit point.
|
|
(setq lim (point))
|
|
)
|
|
|
|
;; If there is a previous library unit, and we are enclosed by
|
|
;; it, then set the syntax accordingly.
|
|
(and placeholder
|
|
(setq library-unit (vhdl-get-library-unit lim placeholder))
|
|
(vhdl-add-syntax library-unit lim))
|
|
|
|
;; Find the surrounding state.
|
|
(if (setq vec (vhdl-get-block-state lim))
|
|
(progn
|
|
(setq containing-sexp (aref vec 0))
|
|
(setq preceding-sexp (aref vec 1))
|
|
(setq containing-begin (aref vec 2))
|
|
(setq containing-mid (aref vec 3))
|
|
))
|
|
|
|
;; set the limit on the farthest back we need to search
|
|
(setq lim (if containing-sexp
|
|
(save-excursion
|
|
(goto-char containing-sexp)
|
|
;; set containing-leader if required
|
|
(if (looking-at vhdl-leader-re)
|
|
(setq containing-leader (vhdl-end-of-leader)))
|
|
(vhdl-point 'bol))
|
|
(point-min)))
|
|
|
|
;; cache char before and after indent point, and move point to
|
|
;; the most likely position to perform the majority of tests
|
|
(goto-char indent-point)
|
|
(skip-chars-forward " \t")
|
|
(setq literal (vhdl-in-literal lim))
|
|
(setq char-after-ip (following-char))
|
|
(setq begin-after-ip (and
|
|
(not literal)
|
|
(looking-at vhdl-begin-fwd-re)
|
|
(vhdl-begin-p)))
|
|
(setq end-after-ip (and
|
|
(not literal)
|
|
(looking-at vhdl-end-fwd-re)
|
|
(vhdl-end-p)))
|
|
(vhdl-backward-syntactic-ws lim)
|
|
(setq char-before-ip (preceding-char))
|
|
(goto-char indent-point)
|
|
(skip-chars-forward " \t")
|
|
|
|
;; now figure out syntactic qualities of the current line
|
|
(cond
|
|
;; CASE 1: in a string or comment.
|
|
((memq literal '(string comment))
|
|
(vhdl-add-syntax literal (vhdl-point 'bopl)))
|
|
;; CASE 2: Line is at top level.
|
|
((null containing-sexp)
|
|
;; Find the point to which indentation will be relative
|
|
(save-excursion
|
|
(if (null preceding-sexp)
|
|
;; CASE 2X.1
|
|
;; no preceding-sexp -> use the preceding statement
|
|
(vhdl-beginning-of-statement-1 lim)
|
|
;; CASE 2X.2
|
|
;; if there is a preceding-sexp then indent relative to it
|
|
(goto-char preceding-sexp)
|
|
;; if not at boi, then the block-opening keyword is
|
|
;; probably following a label, so we need a different
|
|
;; relpos
|
|
(if (/= (point) (vhdl-point 'boi))
|
|
;; CASE 2X.3
|
|
(vhdl-beginning-of-statement-1 lim)))
|
|
;; v-b-o-s could have left us at point-min
|
|
(and (bobp)
|
|
;; CASE 2X.4
|
|
(vhdl-forward-syntactic-ws indent-point))
|
|
(setq placeholder (point)))
|
|
(cond
|
|
;; CASE 2A : we are looking at a block-open
|
|
(begin-after-ip
|
|
(vhdl-add-syntax 'block-open placeholder))
|
|
;; CASE 2B: we are looking at a block-close
|
|
(end-after-ip
|
|
(vhdl-add-syntax 'block-close placeholder))
|
|
;; CASE 2C: we are looking at a top-level statement
|
|
((progn
|
|
(vhdl-backward-syntactic-ws lim)
|
|
(or (bobp)
|
|
(= (preceding-char) ?\;)))
|
|
(vhdl-add-syntax 'statement placeholder))
|
|
;; CASE 2D: we are looking at a top-level statement-cont
|
|
(t
|
|
(vhdl-beginning-of-statement-1 lim)
|
|
;; v-b-o-s could have left us at point-min
|
|
(and (bobp)
|
|
;; CASE 2D.1
|
|
(vhdl-forward-syntactic-ws indent-point))
|
|
(vhdl-add-syntax 'statement-cont (point)))
|
|
)) ; end CASE 2
|
|
;; CASE 3: line is inside parentheses. Most likely we are
|
|
;; either in a subprogram argument (interface) list, or a
|
|
;; continued expression containing parentheses.
|
|
((null containing-begin)
|
|
(vhdl-backward-syntactic-ws containing-sexp)
|
|
(cond
|
|
;; CASE 3A: we are looking at the arglist closing paren
|
|
((eq char-after-ip ?\))
|
|
(goto-char containing-sexp)
|
|
(vhdl-add-syntax 'arglist-close (vhdl-point 'boi)))
|
|
;; CASE 3B: we are looking at the first argument in an empty
|
|
;; argument list.
|
|
((eq char-before-ip ?\()
|
|
(goto-char containing-sexp)
|
|
(vhdl-add-syntax 'arglist-intro (vhdl-point 'boi)))
|
|
;; CASE 3C: we are looking at an arglist continuation line,
|
|
;; but the preceding argument is on the same line as the
|
|
;; opening paren. This case includes multi-line
|
|
;; expression paren groupings.
|
|
((and (save-excursion
|
|
(goto-char (1+ containing-sexp))
|
|
(skip-chars-forward " \t")
|
|
(not (eolp))
|
|
(not (looking-at "--")))
|
|
(save-excursion
|
|
(vhdl-beginning-of-statement-1 containing-sexp)
|
|
(skip-chars-backward " \t(")
|
|
(<= (point) containing-sexp)))
|
|
(goto-char containing-sexp)
|
|
(vhdl-add-syntax 'arglist-cont-nonempty (vhdl-point 'boi)))
|
|
;; CASE 3D: we are looking at just a normal arglist
|
|
;; continuation line
|
|
(t (vhdl-beginning-of-statement-1 containing-sexp)
|
|
(vhdl-forward-syntactic-ws indent-point)
|
|
(vhdl-add-syntax 'arglist-cont (vhdl-point 'boi)))
|
|
))
|
|
;; CASE 4: A block mid open
|
|
((and begin-after-ip
|
|
(looking-at containing-mid))
|
|
(goto-char containing-sexp)
|
|
;; If the \"begin\" keyword is a trailer, then find v-b-o-s
|
|
(if (looking-at vhdl-trailer-re)
|
|
;; CASE 4.1
|
|
(progn (forward-sexp) (vhdl-beginning-of-statement-1 nil)))
|
|
(vhdl-backward-skip-label (vhdl-point 'boi))
|
|
(vhdl-add-syntax 'block-open (point)))
|
|
;; CASE 5: block close brace
|
|
(end-after-ip
|
|
(goto-char containing-sexp)
|
|
;; If the \"begin\" keyword is a trailer, then find v-b-o-s
|
|
(if (looking-at vhdl-trailer-re)
|
|
;; CASE 5.1
|
|
(progn (forward-sexp) (vhdl-beginning-of-statement-1 nil)))
|
|
(vhdl-backward-skip-label (vhdl-point 'boi))
|
|
(vhdl-add-syntax 'block-close (point)))
|
|
;; CASE 6: A continued statement
|
|
((and (/= char-before-ip ?\;)
|
|
;; check it's not a trailer begin keyword, or a begin
|
|
;; keyword immediately following a label.
|
|
(not (and begin-after-ip
|
|
(or (looking-at vhdl-trailer-re)
|
|
(save-excursion
|
|
(vhdl-backward-skip-label containing-sexp)))))
|
|
;; check it's not a statement keyword
|
|
(not (and (looking-at vhdl-statement-fwd-re)
|
|
(vhdl-statement-p)))
|
|
;; see if the b-o-s is before the indent point
|
|
(> indent-point
|
|
(save-excursion
|
|
(vhdl-beginning-of-statement-1 containing-sexp)
|
|
;; If we ended up after a leader, then this will
|
|
;; move us forward to the start of the first
|
|
;; statement. Note that a containing sexp here is
|
|
;; always a keyword, not a paren, so this will
|
|
;; have no effect if we hit the containing-sexp.
|
|
(vhdl-forward-syntactic-ws indent-point)
|
|
(setq placeholder (point))))
|
|
;; check it's not a block-intro
|
|
(/= placeholder containing-sexp)
|
|
;; check it's not a case block-intro
|
|
(save-excursion
|
|
(goto-char placeholder)
|
|
(or (not (looking-at vhdl-case-alternative-re))
|
|
(> (match-end 0) indent-point))))
|
|
;; Make placeholder skip a label, but only if it puts us
|
|
;; before the indent point at the start of a line.
|
|
(let ((new placeholder))
|
|
(if (and (> indent-point
|
|
(save-excursion
|
|
(goto-char placeholder)
|
|
(vhdl-forward-skip-label indent-point)
|
|
(setq new (point))))
|
|
(save-excursion
|
|
(goto-char new)
|
|
(eq new (progn (back-to-indentation) (point)))))
|
|
(setq placeholder new)))
|
|
(vhdl-add-syntax 'statement-cont placeholder)
|
|
(if begin-after-ip
|
|
(vhdl-add-syntax 'block-open)))
|
|
;; Statement. But what kind?
|
|
;; CASE 7: A case alternative key
|
|
((and (looking-at vhdl-case-alternative-re)
|
|
(vhdl-case-alternative-p containing-sexp))
|
|
;; for a case alternative key, we set relpos to the first
|
|
;; non-whitespace char on the line containing the "case"
|
|
;; keyword.
|
|
(goto-char containing-sexp)
|
|
;; If the \"begin\" keyword is a trailer, then find v-b-o-s
|
|
(if (looking-at vhdl-trailer-re)
|
|
(progn (forward-sexp) (vhdl-beginning-of-statement-1 nil)))
|
|
(vhdl-add-syntax 'case-alternative (vhdl-point 'boi)))
|
|
;; CASE 8: statement catchall
|
|
(t
|
|
;; we know its a statement, but we need to find out if it is
|
|
;; the first statement in a block
|
|
(if containing-leader
|
|
(goto-char containing-leader)
|
|
(goto-char containing-sexp)
|
|
;; Note that a containing sexp here is always a keyword,
|
|
;; not a paren, so skip over the keyword.
|
|
(forward-sexp))
|
|
;; move to the start of the first statement
|
|
(vhdl-forward-syntactic-ws indent-point)
|
|
(setq placeholder (point))
|
|
;; we want to ignore case alternatives keys when skipping forward
|
|
(let (incase-p)
|
|
(while (looking-at vhdl-case-alternative-re)
|
|
(setq incase-p (point))
|
|
;; we also want to skip over the body of the
|
|
;; case/when statement if that doesn't put us at
|
|
;; after the indent-point
|
|
(while (vhdl-skip-case-alternative indent-point))
|
|
;; set up the match end
|
|
(looking-at vhdl-case-alternative-re)
|
|
(goto-char (match-end 0))
|
|
;; move to the start of the first case alternative statement
|
|
(vhdl-forward-syntactic-ws indent-point)
|
|
(setq placeholder (point)))
|
|
(cond
|
|
;; CASE 8A: we saw a case/when statement so we must be
|
|
;; in a switch statement. find out if we are at the
|
|
;; statement just after a case alternative key
|
|
((and incase-p
|
|
(= (point) indent-point))
|
|
;; relpos is the "when" keyword
|
|
(vhdl-add-syntax 'statement-case-intro incase-p))
|
|
;; CASE 8B: any old statement
|
|
((< (point) indent-point)
|
|
;; relpos is the first statement of the block
|
|
(vhdl-add-syntax 'statement placeholder)
|
|
(if begin-after-ip
|
|
(vhdl-add-syntax 'block-open)))
|
|
;; CASE 8C: first statement in a block
|
|
(t
|
|
(goto-char containing-sexp)
|
|
;; If the \"begin\" keyword is a trailer, then find v-b-o-s
|
|
(if (looking-at vhdl-trailer-re)
|
|
(progn (forward-sexp) (vhdl-beginning-of-statement-1 nil)))
|
|
(vhdl-backward-skip-label (vhdl-point 'boi))
|
|
(vhdl-add-syntax 'statement-block-intro (point))
|
|
(if begin-after-ip
|
|
(vhdl-add-syntax 'block-open)))
|
|
)))
|
|
)
|
|
|
|
;; now we need to look at any modifiers
|
|
(goto-char indent-point)
|
|
(skip-chars-forward " \t")
|
|
(if (looking-at "--")
|
|
(vhdl-add-syntax 'comment))
|
|
;; return the syntax
|
|
vhdl-syntactic-context))))
|
|
|
|
;; Standard indentation line-ups:
|
|
|
|
(defun vhdl-lineup-arglist (langelem)
|
|
;; lineup the current arglist line with the arglist appearing just
|
|
;; after the containing paren which starts the arglist.
|
|
(save-excursion
|
|
(let* ((containing-sexp
|
|
(save-excursion
|
|
;; arglist-cont-nonempty gives relpos ==
|
|
;; to boi of containing-sexp paren. This
|
|
;; is good when offset is +, but bad
|
|
;; when it is vhdl-lineup-arglist, so we
|
|
;; have to special case a kludge here.
|
|
(if (memq (car langelem) '(arglist-intro arglist-cont-nonempty))
|
|
(progn
|
|
(beginning-of-line)
|
|
(backward-up-list 1)
|
|
(skip-chars-forward " \t" (vhdl-point 'eol)))
|
|
(goto-char (cdr langelem)))
|
|
(point)))
|
|
(cs-curcol (save-excursion
|
|
(goto-char (cdr langelem))
|
|
(current-column))))
|
|
(if (save-excursion
|
|
(beginning-of-line)
|
|
(looking-at "[ \t]*)"))
|
|
(progn (goto-char (match-end 0))
|
|
(backward-sexp)
|
|
(forward-char)
|
|
(vhdl-forward-syntactic-ws)
|
|
(- (current-column) cs-curcol))
|
|
(goto-char containing-sexp)
|
|
(or (eolp)
|
|
(let ((eol (vhdl-point 'eol))
|
|
(here (progn
|
|
(forward-char)
|
|
(skip-chars-forward " \t")
|
|
(point))))
|
|
(vhdl-forward-syntactic-ws)
|
|
(if (< (point) eol)
|
|
(goto-char here))))
|
|
(- (current-column) cs-curcol)
|
|
))))
|
|
|
|
(defun vhdl-lineup-arglist-intro (langelem)
|
|
;; lineup an arglist-intro line to just after the open paren
|
|
(save-excursion
|
|
(let ((cs-curcol (save-excursion
|
|
(goto-char (cdr langelem))
|
|
(current-column)))
|
|
(ce-curcol (save-excursion
|
|
(beginning-of-line)
|
|
(backward-up-list 1)
|
|
(skip-chars-forward " \t" (vhdl-point 'eol))
|
|
(current-column))))
|
|
(- ce-curcol cs-curcol -1))))
|
|
|
|
(defun vhdl-lineup-comment (langelem)
|
|
;; support old behavior for comment indentation. we look at
|
|
;; vhdl-comment-only-line-offset to decide how to indent comment
|
|
;; only-lines
|
|
(save-excursion
|
|
(back-to-indentation)
|
|
;; at or to the right of comment-column
|
|
(if (>= (current-column) comment-column)
|
|
(vhdl-comment-indent)
|
|
;; otherwise, indent as specified by vhdl-comment-only-line-offset
|
|
(if (not (bolp))
|
|
(or (car-safe vhdl-comment-only-line-offset)
|
|
vhdl-comment-only-line-offset)
|
|
(or (cdr-safe vhdl-comment-only-line-offset)
|
|
(car-safe vhdl-comment-only-line-offset)
|
|
-1000 ;jam it against the left side
|
|
)))))
|
|
|
|
(defun vhdl-lineup-statement-cont (langelem)
|
|
;; line up statement-cont after the assignment operator
|
|
(save-excursion
|
|
(let* ((relpos (cdr langelem))
|
|
(assignp (save-excursion
|
|
(goto-char (vhdl-point 'boi))
|
|
(and (re-search-forward "\\(<\\|:\\)="
|
|
(vhdl-point 'eol) t)
|
|
(- (point) (vhdl-point 'boi)))))
|
|
(curcol (progn
|
|
(goto-char relpos)
|
|
(current-column)))
|
|
foundp)
|
|
(while (and (not foundp)
|
|
(< (point) (vhdl-point 'eol)))
|
|
(re-search-forward "\\(<\\|:\\)=\\|(" (vhdl-point 'eol) 'move)
|
|
(if (vhdl-in-literal (cdr langelem))
|
|
(forward-char)
|
|
(if (= (preceding-char) ?\()
|
|
;; skip over any parenthesized expressions
|
|
(goto-char (min (vhdl-point 'eol)
|
|
(scan-lists (point) 1 1)))
|
|
;; found an assignment operator (not at eol)
|
|
(setq foundp (not (looking-at "\\s-*$"))))))
|
|
(if (not foundp)
|
|
;; there's no assignment operator on the line
|
|
vhdl-basic-offset
|
|
;; calculate indentation column after assign and ws, unless
|
|
;; our line contains an assignment operator
|
|
(if (not assignp)
|
|
(progn
|
|
(forward-char)
|
|
(skip-chars-forward " \t")
|
|
(setq assignp 0)))
|
|
(- (current-column) assignp curcol))
|
|
)))
|
|
|
|
;; ############################################################################
|
|
;; Indentation commands
|
|
|
|
(defun vhdl-tab (&optional pre-arg)
|
|
"If preceeding character is part of a word then dabbrev-expand,
|
|
else if right of non whitespace on line then tab-to-tab-stop,
|
|
else if last command was a tab or return then dedent one step,
|
|
else indent `correctly'."
|
|
(interactive "*P")
|
|
(cond ((= (char-syntax (preceding-char)) ?w)
|
|
(let ((case-fold-search nil)) (dabbrev-expand pre-arg)))
|
|
((> (current-column) (current-indentation))
|
|
(tab-to-tab-stop))
|
|
((and (or (eq last-command 'vhdl-tab)
|
|
(eq last-command 'vhdl-return))
|
|
(/= 0 (current-indentation)))
|
|
(backward-delete-char-untabify vhdl-basic-offset nil))
|
|
((vhdl-indent-line))
|
|
)
|
|
(setq this-command 'vhdl-tab)
|
|
)
|
|
|
|
(defun vhdl-untab ()
|
|
"Delete backwards to previous tab stop."
|
|
(interactive)
|
|
(backward-delete-char-untabify vhdl-basic-offset nil)
|
|
)
|
|
|
|
(defun vhdl-return ()
|
|
"newline-and-indent or indent-new-comment-line if in comment and preceding
|
|
character is a space."
|
|
(interactive)
|
|
(if (and (= (preceding-char) ? ) (vhdl-in-comment-p))
|
|
(indent-new-comment-line)
|
|
(newline-and-indent)
|
|
)
|
|
)
|
|
|
|
(defun vhdl-indent-line ()
|
|
"Indent the current line as VHDL code. Returns the amount of
|
|
indentation change."
|
|
(interactive)
|
|
(let* ((syntax (vhdl-get-syntactic-context))
|
|
(pos (- (point-max) (point)))
|
|
(indent (apply '+ (mapcar 'vhdl-get-offset syntax)))
|
|
(shift-amt (- (current-indentation) indent)))
|
|
(and vhdl-echo-syntactic-information-p
|
|
(message "syntax: %s, indent= %d" syntax indent))
|
|
(if (zerop shift-amt)
|
|
nil
|
|
(delete-region (vhdl-point 'bol) (vhdl-point 'boi))
|
|
(beginning-of-line)
|
|
(indent-to indent))
|
|
(if (< (point) (vhdl-point 'boi))
|
|
(back-to-indentation)
|
|
;; If initial point was within line's indentation, position after
|
|
;; the indentation. Else stay at same point in text.
|
|
(if (> (- (point-max) pos) (point))
|
|
(goto-char (- (point-max) pos)))
|
|
)
|
|
(run-hooks 'vhdl-special-indent-hook)
|
|
shift-amt))
|
|
|
|
(defun vhdl-indent-buffer ()
|
|
"Indent whole buffer as VHDL code."
|
|
(interactive)
|
|
(indent-region (point-min) (point-max) nil)
|
|
)
|
|
|
|
(defun vhdl-indent-sexp (&optional endpos)
|
|
"Indent each line of the list starting just after point.
|
|
If optional arg ENDPOS is given, indent each line, stopping when
|
|
ENDPOS is encountered."
|
|
(interactive)
|
|
(save-excursion
|
|
(let ((beg (point))
|
|
(end (progn
|
|
(vhdl-forward-sexp nil endpos)
|
|
(point))))
|
|
(indent-region beg end nil))))
|
|
|
|
;; ############################################################################
|
|
;; Miscellaneous commands
|
|
|
|
(defun vhdl-show-syntactic-information ()
|
|
"Show syntactic information for current line."
|
|
(interactive)
|
|
(message "syntactic analysis: %s" (vhdl-get-syntactic-context))
|
|
(vhdl-keep-region-active))
|
|
|
|
;; Verification and regression functions:
|
|
|
|
(defun vhdl-regress-line (&optional arg)
|
|
"Check syntactic information for current line."
|
|
(interactive "P")
|
|
(let ((expected (save-excursion
|
|
(end-of-line)
|
|
(if (search-backward " -- ((" (vhdl-point 'bol) t)
|
|
(progn
|
|
(forward-char 4)
|
|
(read (current-buffer))))))
|
|
(actual (vhdl-get-syntactic-context))
|
|
(expurgated))
|
|
;; remove the library unit symbols
|
|
(mapcar
|
|
(function
|
|
(lambda (elt)
|
|
(if (memq (car elt) '(entity configuration package
|
|
package-body architecture))
|
|
nil
|
|
(setq expurgated (append expurgated (list elt))))))
|
|
actual)
|
|
(if (and (not arg) expected (listp expected))
|
|
(if (not (equal expected expurgated))
|
|
(error "Should be: %s, is: %s" expected expurgated))
|
|
(save-excursion
|
|
(beginning-of-line)
|
|
(if (not (looking-at "^\\s-*\\(--.*\\)?$"))
|
|
(progn
|
|
(end-of-line)
|
|
(if (search-backward " -- ((" (vhdl-point 'bol) t)
|
|
(kill-line))
|
|
(insert " -- ")
|
|
(insert (format "%s" expurgated)))))))
|
|
(vhdl-keep-region-active))
|
|
|
|
|
|
;; ############################################################################
|
|
;; Alignment
|
|
;; ############################################################################
|
|
|
|
(defvar vhdl-align-alist
|
|
'(
|
|
;; after some keywords
|
|
(vhdl-mode "\\<\\(alias\\|constant\\|signal\\|subtype\\|type\\|variable\\)[ \t]"
|
|
"\\<\\(alias\\|constant\\|signal\\|subtype\\|type\\|variable\\)\\([ \t]+\\)" 2)
|
|
;; before ':'
|
|
(vhdl-mode ":[^=]" "[^ \t]\\([ \t]*\\):[^=]")
|
|
;; after ':'
|
|
(vhdl-mode ":[^=]" ":\\([ \t]*\\)[^=]" 1)
|
|
;; after direction specifications
|
|
(vhdl-mode ":[ \t]*\\(in\\|out\\|inout\\|buffer\\)\\>"
|
|
":[ \t]*\\(in\\|out\\|inout\\|buffer\\)\\([ \t]+\\)" 2)
|
|
;; before "<=", "=>", and ":="
|
|
(vhdl-mode "<=" "[^ \t]\\([ \t]*\\)<=" 1)
|
|
(vhdl-mode "=>" "[^ \t]\\([ \t]*\\)=>" 1)
|
|
(vhdl-mode ":=" "[^ \t]\\([ \t]*\\):=" 1)
|
|
;; after "<=", "=>", and ":="
|
|
(vhdl-mode "<=" "<=\\([ \t]*\\)" 1)
|
|
(vhdl-mode "=>" "=>\\([ \t]*\\)" 1)
|
|
(vhdl-mode ":=" ":=\\([ \t]*\\)" 1)
|
|
;; before some keywords
|
|
(vhdl-mode "[ \t]after\\>" "[^ \t]\\([ \t]+\\)after\\>" 1)
|
|
(vhdl-mode "[ \t]\\(fs\\|ps\\|ns\\|us\\|ms\\|sec\\|min\\|hr\\)\\>"
|
|
"[^ \t]\\([ \t]+\\)\\(fs\\|ps\\|ns\\|us\\|ms\\|sec\\|min\\|hr\\)\\>" 1)
|
|
(vhdl-mode "[ \t]when\\>" "[^ \t]\\([ \t]+\\)when\\>" 1)
|
|
(vhdl-mode "[ \t]else\\>" "[^ \t]\\([ \t]+\\)else\\>" 1)
|
|
(vhdl-mode "[ \t]is\\>" "[^ \t]\\([ \t]+\\)is\\>" 1)
|
|
(vhdl-mode "[ \t]of\\>" "[^ \t]\\([ \t]+\\)of\\>" 1)
|
|
(vhdl-mode "[ \t]use\\>" "[^ \t]\\([ \t]+\\)use\\>" 1)
|
|
;; before comments (two steps required for correct insertion of two spaces)
|
|
(vhdl-mode "--" "[^ \t]\\([ \t]*\\)--" 1)
|
|
(vhdl-mode "--" "[^ \t][ \t]\\([ \t]*\\)--" 1)
|
|
)
|
|
"The format of this alist is
|
|
(MODES [or MODE] REGEXP ALIGN-PATTERN SUBEXP).
|
|
It is searched in order. If REGEXP is found anywhere in the first
|
|
line of a region to be aligned, ALIGN-PATTERN will be used for that
|
|
region. ALIGN-PATTERN must include the whitespace to be expanded or
|
|
contracted. It may also provide regexps for the text surrounding the
|
|
whitespace. SUBEXP specifies which sub-expression of
|
|
ALIGN-PATTERN matches the white space to be expanded/contracted.")
|
|
|
|
(defvar vhdl-align-try-all-clauses t
|
|
"If REGEXP is not found on the first line of the region that clause
|
|
is ignored. If this variable is non-nil, then the clause is tried anyway.")
|
|
|
|
(defun vhdl-align (begin end spacing &optional alignment-list quick)
|
|
"Attempt to align a range of lines based on the content of the
|
|
lines. The definition of 'alignment-list' determines the matching
|
|
order and the manner in which the lines are aligned. If ALIGNMENT-LIST
|
|
is not specified 'vhdl-align-alist' is used. If QUICK is non-nil, no
|
|
indentation is done before aligning."
|
|
(interactive "r\np")
|
|
(if (not alignment-list)
|
|
(setq alignment-list vhdl-align-alist))
|
|
(if (not spacing)
|
|
(setq spacing 1))
|
|
(save-excursion
|
|
(let (bol indent)
|
|
(goto-char end)
|
|
(setq end (point-marker))
|
|
(goto-char begin)
|
|
(setq bol
|
|
(setq begin (progn (beginning-of-line) (point))))
|
|
(untabify bol end)
|
|
(if quick
|
|
nil
|
|
(indent-region bol end nil))))
|
|
(let ((copy (copy-alist alignment-list)))
|
|
(while copy
|
|
(save-excursion
|
|
(goto-char begin)
|
|
(let (element
|
|
(eol (save-excursion (progn (end-of-line) (point)))))
|
|
(setq element (nth 0 copy))
|
|
(if (and (or (and (listp (car element))
|
|
(memq major-mode (car element)))
|
|
(eq major-mode (car element)))
|
|
(or vhdl-align-try-all-clauses
|
|
(re-search-forward (car (cdr element)) eol t)))
|
|
(progn
|
|
(vhdl-align-region begin end (car (cdr (cdr element)))
|
|
(car (cdr (cdr (cdr element)))) spacing)))
|
|
(setq copy (cdr copy)))))))
|
|
|
|
(defun vhdl-align-region (begin end match &optional substr spacing)
|
|
"Align a range of lines from BEGIN to END. The regular expression
|
|
MATCH must match exactly one fields: the whitespace to be
|
|
contracted/expanded. The alignment column will equal the
|
|
rightmost column of the widest whitespace block. SPACING is
|
|
the amount of extra spaces to add to the calculated maximum required.
|
|
SPACING defaults to 1 so that at least one space is inserted after
|
|
the token in MATCH."
|
|
(if (not spacing)
|
|
(setq spacing 1))
|
|
(if (not substr)
|
|
(setq substr 1))
|
|
(save-excursion
|
|
(let (distance (max 0) (lines 0) bol eol width)
|
|
;; Determine the greatest whitespace distance to the alignment
|
|
;; character
|
|
(goto-char begin)
|
|
(setq eol (progn (end-of-line) (point))
|
|
bol (setq begin (progn (beginning-of-line) (point))))
|
|
(while (< bol end)
|
|
(save-excursion
|
|
(if (re-search-forward match eol t)
|
|
(progn
|
|
(setq distance (- (match-beginning substr) bol))
|
|
(if (> distance max)
|
|
(setq max distance)))))
|
|
(forward-line)
|
|
(setq bol (point)
|
|
eol (save-excursion
|
|
(end-of-line)
|
|
(point)))
|
|
(setq lines (1+ lines)))
|
|
;; Now insert enough maxs to push each assignment operator to
|
|
;; the same column. We need to use 'lines' as a counter, since
|
|
;; the location of the mark may change
|
|
(goto-char (setq bol begin))
|
|
(setq eol (save-excursion
|
|
(end-of-line)
|
|
(point)))
|
|
(while (> lines 0)
|
|
(if (re-search-forward match eol t)
|
|
(progn
|
|
(setq width (- (match-end substr) (match-beginning substr)))
|
|
(setq distance (- (match-beginning substr) bol))
|
|
(goto-char (match-beginning substr))
|
|
(delete-char width)
|
|
(insert-char ? (+ (- max distance) spacing))))
|
|
(beginning-of-line)
|
|
(forward-line)
|
|
(setq bol (point)
|
|
eol (save-excursion
|
|
(end-of-line)
|
|
(point)))
|
|
(setq lines (1- lines))
|
|
))))
|
|
|
|
(defun vhdl-align-comment-region (begin end spacing)
|
|
"Aligns inline comments within a region relative to first comment."
|
|
(interactive "r\nP")
|
|
(vhdl-align begin end (or spacing 2)
|
|
`((vhdl-mode "--" "[^ \t]\\([ \t]*\\)--" 1)) t))
|
|
|
|
(defun vhdl-align-noindent-region (begin end spacing)
|
|
"Align without indentation."
|
|
(interactive "r\nP")
|
|
(vhdl-align begin end spacing nil t)
|
|
)
|
|
|
|
|
|
;; ############################################################################
|
|
;; VHDL electrification
|
|
;; ############################################################################
|
|
|
|
;; ############################################################################
|
|
;; Stuttering
|
|
|
|
(defun vhdl-stutter-mode-caps (count)
|
|
"Double first letters of a word replaced by a single capital of the letter."
|
|
(interactive "p")
|
|
(if vhdl-stutter-mode
|
|
(if (and
|
|
(= (preceding-char) last-input-char) ; doubled
|
|
(or (= (point) 2) ; beginning of buffer
|
|
(/= (char-syntax (char-after (- (point) 2))) ?w) ;not mid-word
|
|
(< (char-after (- (point) 2)) ?A))) ;alfa-numeric
|
|
(progn (delete-char -1) (insert-char (- last-input-char 32) count))
|
|
(self-insert-command count))
|
|
(self-insert-command count)
|
|
))
|
|
|
|
(defun vhdl-stutter-mode-close-bracket (count) " ']' --> ')', ')]' --> ']'"
|
|
(interactive "p")
|
|
(if (and vhdl-stutter-mode (= count 1))
|
|
(progn
|
|
(if (= (preceding-char) 41) ; close-paren
|
|
(progn (delete-char -1) (insert-char 93 1)) ; close-bracket
|
|
(insert-char 41 1) ; close-paren
|
|
)
|
|
(blink-matching-open))
|
|
(self-insert-command count)
|
|
))
|
|
|
|
(defun vhdl-stutter-mode-semicolon (count) " ';;' --> ' : ', ': ;' --> ' := '"
|
|
(interactive "p")
|
|
(if (and vhdl-stutter-mode (= count 1))
|
|
(progn
|
|
(cond ((= (preceding-char) last-input-char)
|
|
(progn (delete-char -1)
|
|
(if (not (eq (preceding-char) ? )) (insert " "))
|
|
(insert ": ")))
|
|
((and
|
|
(eq last-command 'vhdl-stutter-mode-colon) (= (preceding-char) ? ))
|
|
(progn (delete-char -1) (insert "= ")))
|
|
(t
|
|
(insert-char 59 1)) ; semi-colon
|
|
)
|
|
(setq this-command 'vhdl-stutter-mode-colon))
|
|
(self-insert-command count)
|
|
))
|
|
|
|
(defun vhdl-stutter-mode-open-bracket (count) " '[' --> '(', '([' --> '['"
|
|
(interactive "p")
|
|
(if (and vhdl-stutter-mode (= count 1))
|
|
(if (= (preceding-char) 40) ; open-paren
|
|
(progn (delete-char -1) (insert-char 91 1)) ; open-bracket
|
|
(insert-char 40 1)) ; open-paren
|
|
(self-insert-command count)
|
|
))
|
|
|
|
(defun vhdl-stutter-mode-quote (count) " '' --> \""
|
|
(interactive "p")
|
|
(if (and vhdl-stutter-mode (= count 1))
|
|
(if (= (preceding-char) last-input-char)
|
|
(progn (delete-backward-char 1) (insert-char 34 1)) ; double-quote
|
|
(insert-char 39 1)) ; single-quote
|
|
(self-insert-command count)
|
|
))
|
|
|
|
(defun vhdl-stutter-mode-comma (count) " ',,' --> ' <= '"
|
|
(interactive "p")
|
|
(if (and vhdl-stutter-mode (= count 1))
|
|
(cond ((= (preceding-char) last-input-char)
|
|
(progn (delete-char -1)
|
|
(if (not (eq (preceding-char) ? )) (insert " "))
|
|
(insert "<= ")))
|
|
(t
|
|
(insert-char 44 1))) ; comma
|
|
(self-insert-command count)
|
|
))
|
|
|
|
(defun vhdl-stutter-mode-period (count) " '..' --> ' => '"
|
|
(interactive "p")
|
|
(if (and vhdl-stutter-mode (= count 1))
|
|
(cond ((= (preceding-char) last-input-char)
|
|
(progn (delete-char -1)
|
|
(if (not (eq (preceding-char) ? )) (insert " "))
|
|
(insert "=> ")))
|
|
(t
|
|
(insert-char 46 1))) ; period
|
|
(self-insert-command count)
|
|
))
|
|
|
|
(defun vhdl-paired-parens ()
|
|
"Insert a pair of round parentheses, placing point between them."
|
|
(interactive)
|
|
(insert "()")
|
|
(backward-char)
|
|
)
|
|
|
|
(defun vhdl-stutter-mode-dash (count)
|
|
"-- starts a comment, --- draws a horizontal line,
|
|
---- starts a display comment"
|
|
(interactive "p")
|
|
(if vhdl-stutter-mode
|
|
(cond ((and abbrev-start-location (= abbrev-start-location (point)))
|
|
(setq abbrev-start-location nil)
|
|
(goto-char last-abbrev-location)
|
|
(beginning-of-line nil)
|
|
(vhdl-display-comment))
|
|
((/= (preceding-char) ?-) ; standard dash (minus)
|
|
(self-insert-command count))
|
|
(t
|
|
(self-insert-command count)
|
|
(message "Enter - for horiz. line, CR for commenting-out code, else 1st char of comment")
|
|
(let ((next-input (read-char)))
|
|
(if (= next-input ?-) ; triple dash
|
|
(progn
|
|
(vhdl-display-comment-line)
|
|
(message
|
|
"Enter - for display comment, else continue with coding")
|
|
(let ((next-input (read-char)))
|
|
(if (= next-input ?-) ; four dashes
|
|
(vhdl-display-comment t)
|
|
(setq unread-command-events ;pushback the char
|
|
(list
|
|
(vhdl-character-to-event-hack next-input)))
|
|
)))
|
|
(setq unread-command-events ;pushback the char
|
|
(list (vhdl-character-to-event-hack next-input)))
|
|
(vhdl-inline-comment)
|
|
))))
|
|
(self-insert-command count)
|
|
))
|
|
|
|
;; ############################################################################
|
|
;; VHDL templates
|
|
|
|
(defun vhdl-alias ()
|
|
"Insert alias declaration."
|
|
(interactive)
|
|
(vhdl-insert-keyword "ALIAS ")
|
|
(if (equal (vhdl-field "name") "")
|
|
nil
|
|
(insert " : ")
|
|
(vhdl-field "type")
|
|
(vhdl-insert-keyword " IS ")
|
|
(vhdl-field "name" ";")
|
|
(vhdl-declaration-comment)
|
|
))
|
|
|
|
(defun vhdl-architecture ()
|
|
"Insert architecture template."
|
|
(interactive)
|
|
(let ((margin (current-column))
|
|
(vhdl-architecture-name)
|
|
(position)
|
|
(entity-exists)
|
|
(string)
|
|
(case-fold-search t))
|
|
(vhdl-insert-keyword "ARCHITECTURE ")
|
|
(if (equal (setq vhdl-architecture-name (vhdl-field "name")) "")
|
|
nil
|
|
(vhdl-insert-keyword " OF ")
|
|
(setq position (point))
|
|
(setq entity-exists
|
|
(re-search-backward "entity \\(\\(\\w\\|\\s_\\)+\\) is" nil t))
|
|
(setq string (match-string 1))
|
|
(goto-char position)
|
|
(if (and entity-exists (not (equal string "")))
|
|
(insert string)
|
|
(vhdl-field "entity name"))
|
|
(vhdl-insert-keyword " IS")
|
|
(vhdl-begin-end (cons vhdl-architecture-name margin))
|
|
(vhdl-block-comment)
|
|
)))
|
|
|
|
|
|
(defun vhdl-array ()
|
|
"Insert array type definition."
|
|
(interactive)
|
|
(vhdl-insert-keyword "ARRAY (")
|
|
(if (equal (vhdl-field "range") "")
|
|
(delete-char -1)
|
|
(vhdl-insert-keyword ") OF ")
|
|
(vhdl-field "type")
|
|
(vhdl-insert-keyword ";")
|
|
))
|
|
|
|
(defun vhdl-assert ()
|
|
"Inserts a assertion statement."
|
|
(interactive)
|
|
(vhdl-insert-keyword "ASSERT ")
|
|
(if vhdl-conditions-in-parenthesis (insert "("))
|
|
(if (equal (vhdl-field "condition (negated)") "")
|
|
(progn (undo 0) (insert " "))
|
|
(if vhdl-conditions-in-parenthesis (insert ")"))
|
|
(vhdl-insert-keyword " REPORT \"")
|
|
(vhdl-field "string-expression" "\" ")
|
|
(vhdl-insert-keyword "SEVERITY ")
|
|
(if (equal (vhdl-field "[note | warning | error | failure]") "")
|
|
(delete-char -10))
|
|
(insert ";")
|
|
))
|
|
|
|
(defun vhdl-attribute ()
|
|
"Inserts an attribute declaration or specification."
|
|
(interactive)
|
|
(vhdl-insert-keyword "ATTRIBUTE ")
|
|
(if (y-or-n-p "declaration (or specification)? ")
|
|
(progn
|
|
(vhdl-field "name" " : ")
|
|
(vhdl-field "type" ";")
|
|
(vhdl-declaration-comment))
|
|
(vhdl-field "name")
|
|
(vhdl-insert-keyword " OF ")
|
|
(vhdl-field "entity name" " : ")
|
|
(vhdl-field "entity class")
|
|
(vhdl-insert-keyword " IS ")
|
|
(vhdl-field "expression" ";")
|
|
))
|
|
|
|
(defun vhdl-block ()
|
|
"Insert a block template."
|
|
(interactive)
|
|
(let ((position (point)))
|
|
(vhdl-insert-keyword " : BLOCK ")
|
|
(goto-char position))
|
|
(let* ((margin (current-column))
|
|
(name (vhdl-field "label")))
|
|
(if (equal name "")
|
|
(progn (undo 0) (insert " "))
|
|
(end-of-line)
|
|
(insert "(")
|
|
(if (equal (vhdl-field "[guard expression]") "")
|
|
(delete-char -2)
|
|
(insert ")"))
|
|
(vhdl-begin-end (cons (concat (vhdl-case-keyword "BLOCK ") name) margin))
|
|
(vhdl-block-comment)
|
|
)))
|
|
|
|
(defun vhdl-block-configuration ()
|
|
"Insert a block configuration statement."
|
|
(interactive)
|
|
(let ((margin (current-column)))
|
|
(vhdl-insert-keyword "FOR ")
|
|
(if (equal (setq name (vhdl-field "block specification")) "")
|
|
nil
|
|
(vhdl-insert-keyword "\n\n")
|
|
(indent-to margin)
|
|
(vhdl-insert-keyword "END FOR;")
|
|
(end-of-line 0)
|
|
(indent-to (+ margin vhdl-basic-offset))
|
|
)))
|
|
|
|
(defun vhdl-case ()
|
|
"Inserts a case statement."
|
|
(interactive)
|
|
(let ((margin (current-column))
|
|
(name))
|
|
(vhdl-insert-keyword "CASE ")
|
|
(if (equal (setq name (vhdl-field "expression")) "")
|
|
nil
|
|
(vhdl-insert-keyword " IS\n\n")
|
|
(indent-to margin)
|
|
(vhdl-insert-keyword "END CASE;")
|
|
; (if vhdl-self-insert-comments (insert " -- " name))
|
|
(forward-line -1)
|
|
(indent-to (+ margin vhdl-basic-offset))
|
|
(vhdl-insert-keyword "WHEN => ")
|
|
(backward-char 4)
|
|
)))
|
|
|
|
(defun vhdl-component ()
|
|
"Inserts a component declaration."
|
|
(interactive)
|
|
(let ((margin (current-column)))
|
|
(vhdl-insert-keyword "COMPONENT ")
|
|
(if (equal (vhdl-field "name") "")
|
|
nil
|
|
(insert "\n\n")
|
|
(indent-to margin)
|
|
(vhdl-insert-keyword "END COMPONENT;")
|
|
(end-of-line -0)
|
|
(indent-to (+ margin vhdl-basic-offset))
|
|
(vhdl-insert-keyword "GENERIC (")
|
|
(vhdl-get-generic t t)
|
|
(insert "\n")
|
|
(indent-to (+ margin vhdl-basic-offset))
|
|
(vhdl-insert-keyword "PORT (")
|
|
(vhdl-get-port t t)
|
|
(forward-line 1))
|
|
))
|
|
|
|
(defun vhdl-component-configuration ()
|
|
"Inserts a component configuration (uses `vhdl-configuration-spec' since
|
|
these are almost equivalent)."
|
|
(interactive)
|
|
(let ((margin (current-column)))
|
|
(vhdl-configuration-spec)
|
|
(insert "\n")
|
|
(indent-to margin)
|
|
(vhdl-insert-keyword "END FOR;")
|
|
))
|
|
|
|
(defun vhdl-component-instance ()
|
|
"Inserts a component instantiation statement."
|
|
(interactive)
|
|
(let ((margin (current-column)))
|
|
(if (equal (vhdl-field "instance label") "")
|
|
nil
|
|
(insert " : ")
|
|
(vhdl-field "component name" "\n")
|
|
(indent-to (+ margin vhdl-basic-offset))
|
|
(let ((position (point)))
|
|
(vhdl-insert-keyword "GENERIC MAP (")
|
|
(if (equal (vhdl-field "[association list]") "")
|
|
(progn (goto-char position)
|
|
(kill-line))
|
|
(insert ")\n")
|
|
(indent-to (+ margin vhdl-basic-offset))))
|
|
(vhdl-insert-keyword "PORT MAP (")
|
|
(vhdl-field "association list" ");")
|
|
)))
|
|
|
|
(defun vhdl-concurrent-signal-assignment ()
|
|
"Inserts a concurrent signal assignment."
|
|
(interactive)
|
|
(if (equal (vhdl-field "target signal") "")
|
|
nil
|
|
(insert " <= ")
|
|
; (if (not (equal (vhdl-field "[GUARDED] [TRANSPORT]") ""))
|
|
; (insert " "))
|
|
(let ((margin (current-column))
|
|
(start (point)))
|
|
(vhdl-field "waveform")
|
|
(vhdl-insert-keyword " WHEN ")
|
|
(if vhdl-conditions-in-parenthesis (insert "("))
|
|
(while (not (equal (vhdl-field "[condition]") ""))
|
|
(if vhdl-conditions-in-parenthesis (insert ")"))
|
|
(vhdl-insert-keyword " ELSE")
|
|
(insert "\n")
|
|
(indent-to margin)
|
|
(vhdl-field "waveform")
|
|
(vhdl-insert-keyword " WHEN ")
|
|
(if vhdl-conditions-in-parenthesis (insert "(")))
|
|
(delete-char -6)
|
|
(if vhdl-conditions-in-parenthesis (delete-char -1))
|
|
(insert ";")
|
|
(if vhdl-auto-align (vhdl-align start (point) 1))
|
|
)))
|
|
|
|
(defun vhdl-configuration ()
|
|
"Inserts a configuration specification if within an architecture,
|
|
a block or component configuration if within a configuration declaration,
|
|
a configuration declaration if not within a design unit."
|
|
(interactive)
|
|
(cond ((equal (car (car (cdr (vhdl-get-syntactic-context)))) 'architecture)
|
|
(vhdl-configuration-spec))
|
|
((equal (car (car (cdr (vhdl-get-syntactic-context)))) 'configuration)
|
|
(if (y-or-n-p "block configuration (or component configuration)? ")
|
|
(vhdl-block-configuration)
|
|
(vhdl-component-configuration)))
|
|
(t (vhdl-configuration-decl)))
|
|
)
|
|
|
|
(defun vhdl-configuration-spec ()
|
|
"Inserts a configuration specification."
|
|
(interactive)
|
|
(let ((margin (current-column)))
|
|
(vhdl-insert-keyword "FOR ")
|
|
(if (equal (vhdl-field "(component names | ALL)" " : ") "")
|
|
(progn (undo 0) (insert " "))
|
|
(vhdl-field "component type" "\n")
|
|
(indent-to (+ margin vhdl-basic-offset))
|
|
(vhdl-insert-keyword "USE ENTITY ")
|
|
(vhdl-field "library name" ".")
|
|
(vhdl-field "entity name" "(")
|
|
(if (equal (vhdl-field "[architecture name]") "")
|
|
(delete-char -1)
|
|
(insert ")"))
|
|
(insert "\n")
|
|
(indent-to (+ margin vhdl-basic-offset))
|
|
(vhdl-insert-keyword "GENERIC MAP (")
|
|
(if (equal (vhdl-field "[association list]") "")
|
|
(progn (kill-line -0)
|
|
(indent-to (+ margin vhdl-basic-offset)))
|
|
(insert ")\n")
|
|
(indent-to (+ margin vhdl-basic-offset)))
|
|
(vhdl-insert-keyword "PORT MAP (")
|
|
(if (equal (vhdl-field "[association list]") "")
|
|
(progn (kill-line -0)
|
|
(delete-char -1))
|
|
(insert ")"))
|
|
(insert ";")
|
|
)))
|
|
|
|
(defun vhdl-configuration-decl ()
|
|
"Inserts a configuration declaration."
|
|
(interactive)
|
|
(let ((margin (current-column))
|
|
(position)
|
|
(entity-exists)
|
|
(string)
|
|
(name))
|
|
(vhdl-insert-keyword "CONFIGURATION ")
|
|
(if (equal (setq name (vhdl-field "name")) "")
|
|
nil
|
|
(vhdl-insert-keyword " OF ")
|
|
(setq position (point))
|
|
(setq entity-exists
|
|
(re-search-backward "entity \\(\\(\\w\\|\\s_\\)*\\) is" nil t))
|
|
(setq string (match-string 1))
|
|
(goto-char position)
|
|
(if (and entity-exists (not (equal string "")))
|
|
(insert string)
|
|
(vhdl-field "entity name"))
|
|
(vhdl-insert-keyword " IS\n\n")
|
|
(indent-to margin)
|
|
(vhdl-insert-keyword "END ")
|
|
(insert name ";")
|
|
(end-of-line 0)
|
|
(indent-to (+ margin vhdl-basic-offset))
|
|
)))
|
|
|
|
(defun vhdl-constant ()
|
|
"Inserts a constant declaration."
|
|
(interactive)
|
|
(vhdl-insert-keyword "CONSTANT ")
|
|
(let ((in-arglist (string-match "arglist"
|
|
(format "%s" (car (car (vhdl-get-syntactic-context)))))))
|
|
(if (not in-arglist)
|
|
(let ((opoint (point)))
|
|
(beginning-of-line)
|
|
(setq in-arglist (looking-at ".*("))
|
|
(goto-char opoint)))
|
|
(if (equal (vhdl-field "name") "")
|
|
nil
|
|
(insert " : ")
|
|
(if in-arglist (vhdl-insert-keyword "IN "))
|
|
(vhdl-field "type")
|
|
(if in-arglist
|
|
(insert ";")
|
|
(let ((position (point)))
|
|
(insert " := ")
|
|
(if (equal (vhdl-field "[initialization]" ";") "")
|
|
(progn (goto-char position) (kill-line) (insert ";")))
|
|
(vhdl-declaration-comment))
|
|
))))
|
|
|
|
(defun vhdl-default ()
|
|
"Insert nothing."
|
|
(interactive)
|
|
(insert " ")
|
|
(unexpand-abbrev)
|
|
(backward-word 1)
|
|
(vhdl-case-word 1)
|
|
(forward-char 1)
|
|
)
|
|
|
|
(defun vhdl-default-indent ()
|
|
"Insert nothing and indent."
|
|
(interactive)
|
|
(insert " ")
|
|
(unexpand-abbrev)
|
|
(backward-word 1)
|
|
(vhdl-case-word 1)
|
|
(forward-char 1)
|
|
(vhdl-indent-line)
|
|
)
|
|
|
|
(defun vhdl-disconnect ()
|
|
"Insert a disconnect statement."
|
|
(interactive)
|
|
(vhdl-insert-keyword "DISCONNECT ")
|
|
(if (equal (vhdl-field "guarded signal specification") "")
|
|
nil
|
|
(vhdl-insert-keyword " AFTER ")
|
|
(vhdl-field "time expression" ";")
|
|
))
|
|
|
|
(defun vhdl-else ()
|
|
"Insert an else statement."
|
|
(interactive)
|
|
(let ((margin))
|
|
(vhdl-insert-keyword "ELSE")
|
|
(if (not (equal 'block-close (car (car (vhdl-get-syntactic-context)))))
|
|
(insert " ")
|
|
(vhdl-indent-line)
|
|
(setq margin (current-indentation))
|
|
(insert "\n")
|
|
(indent-to (+ margin vhdl-basic-offset))
|
|
)))
|
|
|
|
(defun vhdl-elsif ()
|
|
"Insert an elsif statement."
|
|
(interactive)
|
|
(let ((margin))
|
|
(vhdl-insert-keyword "ELSIF ")
|
|
(if vhdl-conditions-in-parenthesis (insert "("))
|
|
(if (equal (vhdl-field "condition") "")
|
|
(progn (undo 0) (insert " "))
|
|
(if vhdl-conditions-in-parenthesis (insert ")"))
|
|
(vhdl-indent-line)
|
|
(setq margin (current-indentation))
|
|
(vhdl-insert-keyword " THEN\n")
|
|
(indent-to (+ margin vhdl-basic-offset))
|
|
)))
|
|
|
|
(defun vhdl-entity ()
|
|
"Insert an entity template."
|
|
(interactive)
|
|
(let ((margin (current-column))
|
|
(vhdl-entity-name))
|
|
(vhdl-insert-keyword "ENTITY ")
|
|
(if (equal (setq vhdl-entity-name (vhdl-field "entity name")) "")
|
|
nil
|
|
(vhdl-insert-keyword " IS\n\n")
|
|
(indent-to margin)
|
|
(vhdl-insert-keyword "END ")
|
|
(insert vhdl-entity-name ";")
|
|
(end-of-line -0)
|
|
(indent-to (+ margin vhdl-basic-offset))
|
|
(vhdl-entity-body)
|
|
)))
|
|
|
|
(defun vhdl-entity-body ()
|
|
"Insert an entity body."
|
|
(interactive)
|
|
(let ((margin (current-column)))
|
|
(if vhdl-additional-empty-lines (insert "\n"))
|
|
(indent-to margin)
|
|
(vhdl-insert-keyword "GENERIC (")
|
|
(if (vhdl-get-generic t)
|
|
(if vhdl-additional-empty-lines (insert "\n")))
|
|
(insert "\n")
|
|
(indent-to margin)
|
|
(vhdl-insert-keyword "PORT (")
|
|
(if (vhdl-get-port t)
|
|
(if vhdl-additional-empty-lines (insert "\n")))
|
|
(end-of-line 2)
|
|
))
|
|
|
|
(defun vhdl-exit ()
|
|
"Insert an exit statement."
|
|
(interactive)
|
|
(vhdl-insert-keyword "EXIT ")
|
|
(if (string-equal (vhdl-field "[loop label]") "")
|
|
(delete-char -1))
|
|
(let ((opoint (point)))
|
|
(vhdl-insert-keyword " WHEN ")
|
|
(if vhdl-conditions-in-parenthesis (insert "("))
|
|
(if (equal (vhdl-field "[condition]") "")
|
|
(progn (goto-char opoint)
|
|
(kill-line))
|
|
(if vhdl-conditions-in-parenthesis (insert ")"))))
|
|
(insert ";")
|
|
)
|
|
|
|
(defun vhdl-for ()
|
|
"Inserts a block or component configuration if within a configuration
|
|
declaration, a for loop otherwise."
|
|
(interactive)
|
|
(if (equal (car (car (cdr (vhdl-get-syntactic-context)))) 'configuration)
|
|
(if (y-or-n-p "block configuration (or component configuration)? ")
|
|
(vhdl-block-configuration)
|
|
(vhdl-component-configuration))
|
|
(vhdl-for-loop)))
|
|
|
|
(defun vhdl-for-loop ()
|
|
"Insert a for loop template."
|
|
(interactive)
|
|
(let ((position (point)))
|
|
(vhdl-insert-keyword " : FOR ")
|
|
(goto-char position))
|
|
(let* ((margin (current-column))
|
|
(name (vhdl-field "[label]"))
|
|
(named (not (string-equal name "")))
|
|
(index))
|
|
(if (not named) (delete-char 3))
|
|
(end-of-line)
|
|
(if (equal (setq index (vhdl-field "loop variable")) "")
|
|
nil
|
|
(vhdl-insert-keyword " IN ")
|
|
(vhdl-field "range")
|
|
(vhdl-insert-keyword " LOOP\n\n")
|
|
(indent-to margin)
|
|
(vhdl-insert-keyword "END LOOP")
|
|
(if named (insert " " name ";")
|
|
(insert ";")
|
|
(if vhdl-self-insert-comments (insert " -- " index)))
|
|
(forward-line -1)
|
|
(indent-to (+ margin vhdl-basic-offset))
|
|
)))
|
|
|
|
(defun vhdl-function ()
|
|
"Insert function specification or body template."
|
|
(interactive)
|
|
(let ((margin (current-column))
|
|
(name))
|
|
(vhdl-insert-keyword "FUNCTION ")
|
|
(if (equal (setq name (vhdl-field "name")) "")
|
|
nil
|
|
(vhdl-get-arg-list)
|
|
(vhdl-insert-keyword " RETURN ")
|
|
(vhdl-field "type" " ")
|
|
(if (y-or-n-p "insert body? ")
|
|
(progn (vhdl-insert-keyword "IS")
|
|
(vhdl-begin-end (cons name margin))
|
|
(vhdl-block-comment))
|
|
(delete-char -1)
|
|
(insert ";\n")
|
|
(indent-to margin)))
|
|
))
|
|
|
|
(defun vhdl-generate ()
|
|
"Insert a generate template."
|
|
(interactive)
|
|
(let ((position (point)))
|
|
(vhdl-insert-keyword " GENERATE")
|
|
(goto-char position))
|
|
(let ((margin (current-column))
|
|
(label (vhdl-field "label"))
|
|
(string))
|
|
(if (equal label "")
|
|
(progn (undo 0) (insert " "))
|
|
(insert " : ")
|
|
(setq string (vhdl-field "(FOR | IF)"))
|
|
(insert " ")
|
|
(if (equal (upcase string) "IF")
|
|
(progn
|
|
(if vhdl-conditions-in-parenthesis (insert "("))
|
|
(vhdl-field "condition")
|
|
(if vhdl-conditions-in-parenthesis (insert ")")))
|
|
(vhdl-field "loop variable")
|
|
(vhdl-insert-keyword " IN ")
|
|
(vhdl-field "range"))
|
|
(end-of-line)
|
|
(insert "\n\n")
|
|
(indent-to margin)
|
|
(vhdl-insert-keyword "END GENERATE ")
|
|
(insert label ";")
|
|
(end-of-line 0)
|
|
(indent-to (+ margin vhdl-basic-offset))
|
|
)))
|
|
|
|
(defun vhdl-generic ()
|
|
"Insert generic declaration, or generic map in instantiation statements."
|
|
(interactive)
|
|
(vhdl-insert-keyword "GENERIC (")
|
|
(cond ((equal (car (car (cdr (vhdl-get-syntactic-context)))) 'entity)
|
|
(vhdl-get-generic nil))
|
|
((or (equal 'statement-cont (car (car (vhdl-get-syntactic-context))))
|
|
(save-excursion
|
|
(and (backward-word 2) (skip-chars-backward " ")
|
|
(eq (preceding-char) ?:))))
|
|
(delete-char -1) (vhdl-map))
|
|
(t (vhdl-get-generic nil t))))
|
|
|
|
(defun vhdl-header ()
|
|
"Insert a VHDL file header."
|
|
(interactive)
|
|
(let (eot)
|
|
(save-excursion
|
|
(save-restriction
|
|
(widen)
|
|
(goto-char (point-min))
|
|
(if vhdl-header-file
|
|
(setq eot (car (cdr (insert-file-contents vhdl-header-file))))
|
|
; insert default header
|
|
(insert "\
|
|
-------------------------------------------------------------------------------
|
|
-- Title : <title string>
|
|
-- Project : <project string>
|
|
-------------------------------------------------------------------------------
|
|
-- File : <filename>
|
|
-- Author : <author>
|
|
-- Created : <date>
|
|
-- Last modified : <date>
|
|
-------------------------------------------------------------------------------
|
|
-- Description :
|
|
-- <cursor>
|
|
-------------------------------------------------------------------------------
|
|
-- Modification history :
|
|
-- <date> : created
|
|
-------------------------------------------------------------------------------
|
|
|
|
")
|
|
(setq eot (point)))
|
|
(narrow-to-region (point-min) eot)
|
|
(goto-char (point-min))
|
|
(while (search-forward "<filename>" nil t)
|
|
(replace-match (buffer-name) t t))
|
|
(goto-char (point-min))
|
|
(while (search-forward "<author>" nil t)
|
|
(replace-match "" t t)
|
|
(insert (user-full-name) " <" user-mail-address ">"))
|
|
(goto-char (point-min))
|
|
;; Replace <RCS> with $, so that RCS for the source is
|
|
;; not over-enthusiastic with replacements
|
|
(while (search-forward "<RCS>" nil t)
|
|
(replace-match "$" nil t))
|
|
(goto-char (point-min))
|
|
(while (search-forward "<date>" nil t)
|
|
(replace-match "" t t)
|
|
(vhdl-insert-date))
|
|
(goto-char (point-min))
|
|
(let (string)
|
|
(while (re-search-forward "<\\(\\w*\\) string>" nil t)
|
|
(setq string (read-string (concat (match-string 1) ": ")))
|
|
(replace-match string t t)))))
|
|
(goto-char (point-min))
|
|
(if (search-forward "<cursor>" nil t)
|
|
(replace-match "" t t))))
|
|
|
|
(defun vhdl-if ()
|
|
"Insert an if statement template."
|
|
(interactive)
|
|
(let ((margin (current-column)))
|
|
(vhdl-insert-keyword "IF ")
|
|
(if vhdl-conditions-in-parenthesis (insert "("))
|
|
(if (equal (vhdl-field "condition") "")
|
|
(progn (undo 0) (insert " "))
|
|
(if vhdl-conditions-in-parenthesis (insert ")"))
|
|
(vhdl-insert-keyword " THEN\n\n")
|
|
(indent-to margin)
|
|
(vhdl-insert-keyword "END IF;")
|
|
(forward-line -1)
|
|
(indent-to (+ margin vhdl-basic-offset))
|
|
)))
|
|
|
|
(defun vhdl-library ()
|
|
"Insert a library specification."
|
|
(interactive)
|
|
(let ((margin (current-column))
|
|
(lib-name))
|
|
(vhdl-insert-keyword "LIBRARY ")
|
|
(if (equal (setq lib-name (vhdl-field "library name")) "")
|
|
nil
|
|
(insert ";\n")
|
|
(indent-to margin)
|
|
(vhdl-insert-keyword "USE ")
|
|
(insert lib-name)
|
|
(vhdl-insert-keyword "..ALL;")
|
|
(backward-char 5)
|
|
(if (equal (vhdl-field "package name") "")
|
|
(progn (vhdl-kill-entire-line)
|
|
(end-of-line -0))
|
|
(end-of-line)
|
|
))))
|
|
|
|
(defun vhdl-loop ()
|
|
"Insert a loop template."
|
|
(interactive)
|
|
(let ((position (point)))
|
|
(vhdl-insert-keyword " : LOOP")
|
|
(goto-char position))
|
|
(let* ((margin (current-column))
|
|
(name (vhdl-field "[label]"))
|
|
(named (not (string-equal name ""))))
|
|
(if (not named) (delete-char 3))
|
|
(end-of-line)
|
|
(insert "\n\n")
|
|
(indent-to margin)
|
|
(vhdl-insert-keyword "END LOOP")
|
|
(insert (if named (concat " " name ";") ?;))
|
|
(forward-line -1)
|
|
(indent-to (+ margin vhdl-basic-offset))
|
|
))
|
|
|
|
(defun vhdl-map ()
|
|
"Insert a map specification."
|
|
(interactive)
|
|
(vhdl-insert-keyword "MAP (")
|
|
(if (equal (vhdl-field "[association list]") "")
|
|
(progn (undo 0) (insert " "))
|
|
(insert ")")
|
|
))
|
|
|
|
(defun vhdl-modify ()
|
|
"Actualize modification date."
|
|
(interactive)
|
|
(goto-char (point-min))
|
|
(if (search-forward vhdl-modify-date-prefix-string nil t)
|
|
(progn (kill-line)
|
|
(vhdl-insert-date))
|
|
(message (concat "Modification date prefix string \""
|
|
vhdl-modify-date-prefix-string
|
|
"\" not found!"))
|
|
(beep)))
|
|
|
|
(defun vhdl-next ()
|
|
"Inserts a next statement."
|
|
(interactive)
|
|
(vhdl-insert-keyword "NEXT ")
|
|
(if (string-equal (vhdl-field "[loop label]") "")
|
|
(delete-char -1))
|
|
(let ((opoint (point)))
|
|
(vhdl-insert-keyword " WHEN ")
|
|
(if vhdl-conditions-in-parenthesis (insert "("))
|
|
(if (equal (vhdl-field "[condition]") "")
|
|
(progn (goto-char opoint)
|
|
(kill-line))
|
|
(if vhdl-conditions-in-parenthesis (insert ")"))))
|
|
(insert ";")
|
|
)
|
|
|
|
(defun vhdl-package ()
|
|
"Insert a package specification or body."
|
|
(interactive)
|
|
(let ((margin (current-column))
|
|
(name))
|
|
(vhdl-insert-keyword "PACKAGE ")
|
|
(if (y-or-n-p "body? ")
|
|
(vhdl-insert-keyword "BODY "))
|
|
(setq name (vhdl-field "name" " is\n\n"))
|
|
(indent-to margin)
|
|
(vhdl-insert-keyword "END ")
|
|
(insert name ";")
|
|
(forward-line -1)
|
|
(indent-to (+ margin vhdl-basic-offset))
|
|
))
|
|
|
|
(defun vhdl-port ()
|
|
"Insert a port declaration, or port map in instantiation statements."
|
|
(interactive)
|
|
(vhdl-insert-keyword "PORT (")
|
|
(cond ((equal (car (car (cdr (vhdl-get-syntactic-context)))) 'entity)
|
|
(vhdl-get-port nil))
|
|
((or (equal 'statement-cont (car (car (vhdl-get-syntactic-context))))
|
|
(save-excursion
|
|
(and (backward-word 2) (skip-chars-backward " ")
|
|
(eq (preceding-char) ?:))))
|
|
(delete-char -1) (vhdl-map))
|
|
(t (vhdl-get-port nil t))))
|
|
|
|
(defun vhdl-procedure ()
|
|
"Insert a procedure specification or body template."
|
|
(interactive)
|
|
(let ((margin (current-column))
|
|
(name))
|
|
(vhdl-insert-keyword "PROCEDURE ")
|
|
(if (equal (setq name (vhdl-field "name")) "")
|
|
nil
|
|
(vhdl-get-arg-list)
|
|
(insert " ")
|
|
(if (y-or-n-p "insert body? ")
|
|
(progn (vhdl-insert-keyword "IS")
|
|
(vhdl-begin-end (cons name margin))
|
|
(vhdl-block-comment))
|
|
(delete-char -1)
|
|
(insert ";\n")
|
|
(indent-to margin)
|
|
))))
|
|
|
|
(defun vhdl-process ()
|
|
"Insert a process template."
|
|
(interactive)
|
|
(let ((clocked))
|
|
(let ((position (point)))
|
|
(vhdl-insert-keyword "PROCESS")
|
|
(setq clocked (y-or-n-p "clocked process? "))
|
|
(goto-char position)
|
|
(insert " : ")
|
|
(goto-char position))
|
|
(let* ((margin (current-column))
|
|
(finalline)
|
|
(name (vhdl-field "[label]"))
|
|
(named (not (string-equal name "")))
|
|
(clock) (reset)
|
|
(case-fold-search t))
|
|
(if (not named) (delete-char 3))
|
|
(end-of-line)
|
|
(insert " (")
|
|
(if (not clocked)
|
|
(if (equal (vhdl-field "[sensitivity list]" ")") "")
|
|
(delete-char -3))
|
|
(setq clock (vhdl-field "clock name" ", "))
|
|
(setq reset (vhdl-field "reset name" ")")))
|
|
(vhdl-begin-end (cons (concat (vhdl-case-keyword "PROCESS")
|
|
(if named (concat " " name))) margin))
|
|
(if clocked (vhdl-clock-async-reset clock reset))
|
|
(if vhdl-prompt-for-comments
|
|
(progn
|
|
(setq finalline (vhdl-current-line))
|
|
(if (and (re-search-backward "\\<begin\\>" nil t)
|
|
(re-search-backward "\\<process\\>" nil t))
|
|
(progn
|
|
(end-of-line -0)
|
|
(insert "\n")
|
|
(indent-to margin)
|
|
(insert "-- purpose: ")
|
|
(if (equal (vhdl-field "description") "")
|
|
(vhdl-kill-entire-line)
|
|
(newline)
|
|
(indent-to margin)
|
|
(insert "-- type: ")
|
|
(insert (if clocked "memorizing" "memoryless") "\n")
|
|
(indent-to margin)
|
|
(insert "-- inputs: ")
|
|
(if clocked
|
|
(insert clock ", " reset ", "))
|
|
(if (and (equal (vhdl-field "signal names") "")
|
|
clocked)
|
|
(delete-char -2))
|
|
(insert "\n")
|
|
(indent-to margin)
|
|
(insert "-- outputs: ")
|
|
(vhdl-field "signal names")
|
|
(setq finalline (+ finalline 4)))))
|
|
(goto-line finalline)
|
|
(end-of-line)
|
|
)))))
|
|
|
|
(defun vhdl-record ()
|
|
"Insert a record type declaration."
|
|
(interactive)
|
|
(let ((margin (current-column))
|
|
(start (point))
|
|
(first t))
|
|
(vhdl-insert-keyword "RECORD\n")
|
|
(indent-to (+ margin vhdl-basic-offset))
|
|
(if (equal (vhdl-field "identifiers") "")
|
|
(progn (kill-line -0)
|
|
(delete-char -1)
|
|
(insert " "))
|
|
(while (or first (not (equal (vhdl-field "[identifiers]") "")))
|
|
(insert " : ")
|
|
(vhdl-field "type" ";")
|
|
(vhdl-declaration-comment)
|
|
(newline)
|
|
(indent-to (+ margin vhdl-basic-offset))
|
|
(setq first nil))
|
|
(kill-line -0)
|
|
(indent-to margin)
|
|
(vhdl-insert-keyword "END RECORD;")
|
|
(if vhdl-auto-align (vhdl-align start (point) 1))
|
|
)))
|
|
|
|
(defun vhdl-return-value ()
|
|
"Insert a return statement."
|
|
(interactive)
|
|
(vhdl-insert-keyword "RETURN ")
|
|
(if (equal (vhdl-field "[expression]") "")
|
|
(delete-char -1))
|
|
(insert ";")
|
|
)
|
|
|
|
(defun vhdl-selected-signal-assignment ()
|
|
"Insert a selected signal assignment."
|
|
(interactive)
|
|
(let ((margin (current-column))
|
|
(start (point)))
|
|
(let ((position (point)))
|
|
(vhdl-insert-keyword " SELECT")
|
|
(goto-char position))
|
|
(vhdl-insert-keyword "WITH ")
|
|
(if (equal (vhdl-field "selector expression") "")
|
|
(progn (undo 0) (insert " "))
|
|
(end-of-line)
|
|
(insert "\n")
|
|
(indent-to (+ margin vhdl-basic-offset))
|
|
(vhdl-field "target signal" " <= ")
|
|
; (vhdl-field "[GUARDED] [TRANSPORT]")
|
|
(insert "\n")
|
|
(indent-to (+ margin vhdl-basic-offset))
|
|
(while (not (equal (vhdl-field "[waveform]") ""))
|
|
(vhdl-insert-keyword " WHEN ")
|
|
(vhdl-field "choices" ",")
|
|
(newline)
|
|
(indent-to (+ margin vhdl-basic-offset)))
|
|
(if (not (equal (vhdl-field "[alternative waveform]") ""))
|
|
(vhdl-insert-keyword " WHEN OTHERS")
|
|
(fixup-whitespace)
|
|
(delete-char -2))
|
|
(insert ";")
|
|
(if vhdl-auto-align (vhdl-align start (point) 1))
|
|
)))
|
|
|
|
(defun vhdl-signal ()
|
|
"Insert a signal declaration."
|
|
(interactive)
|
|
(vhdl-insert-keyword "SIGNAL ")
|
|
(let ((in-arglist (string-match "arglist"
|
|
(format "%s" (car (car (vhdl-get-syntactic-context)))))))
|
|
(if (not in-arglist)
|
|
(let ((opoint (point)))
|
|
(beginning-of-line)
|
|
(setq in-arglist (looking-at ".*("))
|
|
(goto-char opoint)))
|
|
(if (equal (vhdl-field "names") "")
|
|
nil
|
|
(insert " : ")
|
|
(if in-arglist
|
|
(progn (vhdl-field "direction")
|
|
(insert " ")))
|
|
(vhdl-field "type")
|
|
(if in-arglist
|
|
(insert ";")
|
|
(let ((position (point)))
|
|
(insert " := ")
|
|
(if (equal (vhdl-field "[initialization]" ";") "")
|
|
(progn (goto-char position) (kill-line) (insert ";")))
|
|
(vhdl-declaration-comment))
|
|
))))
|
|
|
|
(defun vhdl-subtype ()
|
|
"Insert a subtype declaration."
|
|
(interactive)
|
|
(vhdl-insert-keyword "SUBTYPE ")
|
|
(if (equal (vhdl-field "name") "")
|
|
nil
|
|
(vhdl-insert-keyword " IS ")
|
|
(vhdl-field "type" " ")
|
|
(if (equal (vhdl-field "[RANGE value range | ( index range )]") "")
|
|
(delete-char -1))
|
|
(insert ";")
|
|
(vhdl-declaration-comment)
|
|
))
|
|
|
|
(defun vhdl-type ()
|
|
"Insert a type declaration."
|
|
(interactive)
|
|
(vhdl-insert-keyword "TYPE ")
|
|
(if (equal (vhdl-field "name") "")
|
|
nil
|
|
(vhdl-insert-keyword " IS ")
|
|
(let ((definition (upcase (vhdl-field "(scalar type | ARRAY | RECORD | ACCESS | FILE)"))))
|
|
(cond ((equal definition "ARRAY")
|
|
(kill-word -1) (vhdl-array))
|
|
((equal definition "RECORD")
|
|
(kill-word -1) (vhdl-record))
|
|
((equal definition "ACCESS")
|
|
(insert " ") (vhdl-field "type" ";"))
|
|
((equal definition "FILE")
|
|
(vhdl-insert-keyword " OF ") (vhdl-field "type" ";"))
|
|
(t (insert ";")))
|
|
(vhdl-declaration-comment)
|
|
)))
|
|
|
|
(defun vhdl-use ()
|
|
"Insert a use clause."
|
|
(interactive)
|
|
(vhdl-insert-keyword "USE ..ALL;")
|
|
(backward-char 6)
|
|
(if (equal (vhdl-field "library name") "")
|
|
(progn (undo 0) (insert " "))
|
|
(forward-char 1)
|
|
(vhdl-field "package name")
|
|
(end-of-line)
|
|
))
|
|
|
|
(defun vhdl-variable ()
|
|
"Insert a variable declaration."
|
|
(interactive)
|
|
(vhdl-insert-keyword "VARIABLE ")
|
|
(let ((in-arglist (string-match "arglist"
|
|
(format "%s" (car (car (vhdl-get-syntactic-context)))))))
|
|
(if (not in-arglist)
|
|
(let ((opoint (point)))
|
|
(beginning-of-line)
|
|
(setq in-arglist (looking-at ".*("))
|
|
(goto-char opoint)))
|
|
(if (equal (vhdl-field "names") "")
|
|
nil
|
|
(insert " : ")
|
|
(if in-arglist
|
|
(progn (vhdl-field "direction")
|
|
(insert " ")))
|
|
(vhdl-field "type")
|
|
(if in-arglist
|
|
(insert ";")
|
|
(let ((position (point)))
|
|
(insert " := ")
|
|
(if (equal (vhdl-field "[initialization]" ";") "")
|
|
(progn (goto-char position) (kill-line) (insert ";")))
|
|
(vhdl-declaration-comment))
|
|
))))
|
|
|
|
(defun vhdl-wait ()
|
|
"Insert a wait statement."
|
|
(interactive)
|
|
(vhdl-insert-keyword "WAIT ")
|
|
(if (equal (vhdl-field
|
|
"[ON sensitivity list] [UNTIL condition] [FOR time expression]")
|
|
"")
|
|
(delete-char -1))
|
|
(insert ";")
|
|
)
|
|
|
|
(defun vhdl-when ()
|
|
"Indent correctly if within a case statement."
|
|
(interactive)
|
|
(let ((position (point))
|
|
(margin))
|
|
(if (and (re-search-forward "\\<end\\>" nil t)
|
|
(looking-at "\\s-*\\<case\\>"))
|
|
(progn
|
|
(setq margin (current-indentation))
|
|
(goto-char position)
|
|
(delete-horizontal-space)
|
|
(indent-to (+ margin vhdl-basic-offset)))
|
|
(goto-char position)
|
|
)
|
|
(vhdl-insert-keyword "WHEN ")
|
|
))
|
|
|
|
(defun vhdl-while-loop ()
|
|
"Insert a while loop template."
|
|
(interactive)
|
|
(let ((position (point)))
|
|
(vhdl-insert-keyword " : WHILE ")
|
|
(goto-char position))
|
|
(let* ((margin (current-column))
|
|
(name (vhdl-field "[label]"))
|
|
(named (not (string-equal name ""))))
|
|
(if (not named) (delete-char 3))
|
|
(end-of-line)
|
|
(if vhdl-conditions-in-parenthesis (insert "("))
|
|
(if (equal (vhdl-field "condition") "")
|
|
(progn (undo 0) (insert " "))
|
|
(if vhdl-conditions-in-parenthesis (insert ")"))
|
|
(vhdl-insert-keyword " LOOP\n\n")
|
|
(indent-to margin)
|
|
(vhdl-insert-keyword "END LOOP")
|
|
(insert (if named (concat " " name ";") ?;))
|
|
(forward-line -1)
|
|
(indent-to (+ margin vhdl-basic-offset))
|
|
)))
|
|
|
|
(defun vhdl-with ()
|
|
"Insert a with statement (i.e. selected signal assignment)."
|
|
(interactive)
|
|
(vhdl-selected-signal-assignment)
|
|
)
|
|
|
|
;; ############################################################################
|
|
;; Custom functions
|
|
|
|
(defun vhdl-clocked-wait ()
|
|
"Insert a wait statement for rising clock edge."
|
|
(interactive)
|
|
(vhdl-insert-keyword "WAIT UNTIL ")
|
|
(let* ((clock (vhdl-field "clock name")))
|
|
(insert "'event")
|
|
(vhdl-insert-keyword " AND ")
|
|
(insert clock)
|
|
(insert " = " vhdl-one-string ";")
|
|
))
|
|
|
|
(defun vhdl-clock-async-reset (clock reset)
|
|
"Insert a template reacting on asynchronous reset and rising clock edge
|
|
for inside a memorizing processes."
|
|
(interactive)
|
|
(let* ( (margin (current-column))
|
|
(opoint))
|
|
(if vhdl-self-insert-comments
|
|
(insert "-- activities triggered by asynchronous reset (active low)\n"))
|
|
(indent-to margin)
|
|
(vhdl-insert-keyword "IF ")
|
|
(insert reset " = " vhdl-zero-string)
|
|
(vhdl-insert-keyword " THEN\n")
|
|
(indent-to (+ margin vhdl-basic-offset))
|
|
(setq opoint (point))
|
|
(newline)
|
|
(indent-to margin)
|
|
(if vhdl-self-insert-comments
|
|
(insert "-- activities triggered by rising edge of clock\n"))
|
|
(indent-to margin)
|
|
(vhdl-insert-keyword "ELSIF ")
|
|
(insert clock "'event")
|
|
(vhdl-insert-keyword " AND ")
|
|
(insert clock " = " vhdl-one-string)
|
|
(vhdl-insert-keyword " THEN\n")
|
|
(indent-to (+ margin vhdl-basic-offset))
|
|
(newline)
|
|
(indent-to margin)
|
|
(vhdl-insert-keyword "END IF;")
|
|
; (if vhdl-self-insert-comments (insert " -- " clock))
|
|
(goto-char opoint)
|
|
))
|
|
|
|
(defun vhdl-standard-package (library package)
|
|
"Insert specification of a standard package."
|
|
(interactive)
|
|
(let ((margin (current-column)))
|
|
(vhdl-insert-keyword "LIBRARY ")
|
|
(insert library ";\n")
|
|
(indent-to margin)
|
|
(vhdl-insert-keyword "USE ")
|
|
(insert library "." package)
|
|
(vhdl-insert-keyword ".ALL;")
|
|
))
|
|
|
|
(defun vhdl-package-numeric-bit ()
|
|
"Insert specification of 'numeric_bit' package."
|
|
(interactive)
|
|
(vhdl-standard-package "ieee" "numeric_bit"))
|
|
|
|
(defun vhdl-package-numeric-std ()
|
|
"Insert specification of 'numeric_std' package."
|
|
(interactive)
|
|
(vhdl-standard-package "ieee" "numeric_std"))
|
|
|
|
(defun vhdl-package-std-logic-1164 ()
|
|
"Insert specification of 'std_logic_1164' package."
|
|
(interactive)
|
|
(vhdl-standard-package "ieee" "std_logic_1164"))
|
|
|
|
(defun vhdl-package-textio ()
|
|
"Insert specification of 'textio' package."
|
|
(interactive)
|
|
(vhdl-standard-package "std" "textio"))
|
|
|
|
;; ############################################################################
|
|
;; Comment functions
|
|
|
|
(defun vhdl-comment-indent ()
|
|
(let* ((opoint (point))
|
|
(col (progn
|
|
(forward-line -1)
|
|
(if (re-search-forward "--" opoint t)
|
|
(- (current-column) 2) ;Existing comment at bol stays there.
|
|
(goto-char opoint)
|
|
(skip-chars-backward " \t")
|
|
(max comment-column ;else indent to comment column
|
|
(1+ (current-column))) ;except leave at least one space.
|
|
))))
|
|
(goto-char opoint)
|
|
col
|
|
))
|
|
|
|
(defun vhdl-inline-comment ()
|
|
"Start a comment at the end of the line.
|
|
if on line with code, indent at least comment-column.
|
|
if starting after end-comment-column, start a new line."
|
|
(interactive)
|
|
(if (> (current-column) end-comment-column) (newline-and-indent))
|
|
(if (or (looking-at "\\s-*$") ;end of line
|
|
(and (not unread-command-events) ; called with key binding or menu
|
|
(not (end-of-line))))
|
|
(let ((margin))
|
|
(while (= (preceding-char) ?-) (delete-char -1))
|
|
(setq margin (current-column))
|
|
(delete-horizontal-space)
|
|
(if (bolp)
|
|
(progn (indent-to margin) (insert "--"))
|
|
(insert " ")
|
|
(indent-to comment-column)
|
|
(insert "--"))
|
|
(if (not unread-command-events) (insert " ")))
|
|
; else code following current point implies commenting out code
|
|
(let (next-input code)
|
|
(while (= (preceding-char) ?-) (delete-char -2))
|
|
(while (= (setq next-input (read-char)) 13) ; CR
|
|
(insert "--"); or have a space after it?
|
|
(forward-char -2)
|
|
(forward-line 1)
|
|
(message "Enter CR if commenting out a line of code.")
|
|
(setq code t)
|
|
)
|
|
(if (not code) (progn
|
|
; (indent-to comment-column)
|
|
(insert "--") ;hardwire to 1 space or use vhdl-basic-offset?
|
|
))
|
|
(setq unread-command-events
|
|
(list (vhdl-character-to-event-hack next-input))) ;pushback the char
|
|
)))
|
|
|
|
(defun vhdl-display-comment (&optional line-exists)
|
|
"Add 2 comment lines at the current indent, making a display comment."
|
|
(interactive)
|
|
(if (not line-exists)
|
|
(vhdl-display-comment-line))
|
|
(let* ((col (current-column))
|
|
(len (- end-comment-column col)))
|
|
(insert "\n")
|
|
(insert-char ? col)
|
|
(insert-char ?- len)
|
|
(insert "\n")
|
|
(insert-char ? col)
|
|
(end-of-line -1)
|
|
)
|
|
(insert "-- ")
|
|
)
|
|
|
|
(defun vhdl-display-comment-line ()
|
|
"Displays one line of dashes."
|
|
(interactive)
|
|
(while (= (preceding-char) ?-) (delete-char -2))
|
|
(let* ((col (current-column))
|
|
(len (- end-comment-column col)))
|
|
(insert-char ?- len)
|
|
(insert-char ?\n 1)
|
|
(insert-char ? col)
|
|
))
|
|
|
|
(defun vhdl-declaration-comment ()
|
|
(if vhdl-prompt-for-comments
|
|
(let ((position (point)))
|
|
(insert " ")
|
|
(indent-to comment-column)
|
|
(insert "-- ")
|
|
(if (equal (vhdl-field "comment") "")
|
|
(progn (goto-char position) (kill-line))
|
|
))))
|
|
|
|
(defun vhdl-block-comment ()
|
|
(if vhdl-prompt-for-comments
|
|
(let ((finalline (vhdl-current-line))
|
|
(case-fold-search t))
|
|
(beginning-of-line -0)
|
|
(if (re-search-backward "\\<\\(architecture\\|block\\|function\\|procedure\\|process\\)\\>" nil t)
|
|
(let ((margin))
|
|
(back-to-indentation)
|
|
(setq margin (current-column))
|
|
(end-of-line -0)
|
|
(insert "\n")
|
|
(indent-to margin)
|
|
(insert "-- purpose: ")
|
|
(if (equal (vhdl-field "description") "")
|
|
(vhdl-kill-entire-line)
|
|
(setq finalline (+ finalline 1)))))
|
|
(goto-line finalline)
|
|
(end-of-line)
|
|
)))
|
|
|
|
(defun vhdl-comment-uncomment-region (beg end &optional arg)
|
|
"Comment out region if not commented out, uncomment out region if already
|
|
commented out."
|
|
(interactive "r\nP")
|
|
(goto-char beg)
|
|
(if (looking-at comment-start)
|
|
(comment-region beg end -1)
|
|
(comment-region beg end)
|
|
))
|
|
|
|
;; ############################################################################
|
|
;; Help functions
|
|
|
|
(defun vhdl-outer-space (count)
|
|
"Expand abbreviations and self-insert space(s), do indent-new-comment-line
|
|
if in comment and past end-comment-column."
|
|
(interactive "p")
|
|
(if (or (and (>= (preceding-char) ?a) (<= (preceding-char) ?z))
|
|
(and (>= (preceding-char) ?A) (<= (preceding-char) ?Z)))
|
|
(expand-abbrev))
|
|
(if (not (vhdl-in-comment-p))
|
|
(self-insert-command count)
|
|
(if (< (current-column) end-comment-column)
|
|
(self-insert-command count)
|
|
(while (> (current-column) end-comment-column) (forward-word -1))
|
|
(while (> (preceding-char) ? ) (forward-word -1))
|
|
(delete-horizontal-space)
|
|
(indent-new-comment-line)
|
|
(end-of-line nil)
|
|
(insert-char ? count)
|
|
)))
|
|
|
|
(defun vhdl-field (prompt &optional following-string)
|
|
"Prompt for string and insert it in buffer with optional following-string."
|
|
(let ((opoint (point)))
|
|
(insert "<" prompt ">")
|
|
(let ((string (read-from-minibuffer (concat prompt ": ") ""
|
|
vhdl-minibuffer-local-map)))
|
|
(delete-region opoint (point))
|
|
(insert string (or following-string ""))
|
|
(if vhdl-upper-case-keywords
|
|
(vhdl-fix-case-region-1
|
|
opoint (point) t vhdl-93-keywords-regexp))
|
|
string
|
|
)))
|
|
|
|
(defun vhdl-in-comment-p ()
|
|
"Check if point is to right of beginning comment delimiter."
|
|
(interactive)
|
|
(let ((opoint (point)))
|
|
(save-excursion ; finds an unquoted comment
|
|
(beginning-of-line)
|
|
(re-search-forward "^\\([^\"]*\"[^\"]*\"\\)*[^\"]*--" opoint t)
|
|
)))
|
|
|
|
(defun vhdl-in-string-p ()
|
|
"Check if point is in a string."
|
|
(interactive)
|
|
(let ((opoint (point)))
|
|
(save-excursion ; preceeded by odd number of string delimiters?
|
|
(beginning-of-line)
|
|
(equal
|
|
opoint
|
|
(re-search-forward "^\\([^\"]*\"[^\"]*\"\\)*[^\"]*\"[^\"]*" opoint t))
|
|
)))
|
|
|
|
(defun vhdl-begin-end (list)
|
|
"Insert a begin ... end pair with optional name after the end.
|
|
Point is left between them."
|
|
(let ((return)
|
|
(name (car list))
|
|
(margin (cdr list)))
|
|
(if vhdl-additional-empty-lines
|
|
(progn
|
|
(insert "\n")
|
|
(indent-to (+ margin vhdl-basic-offset))))
|
|
(insert "\n")
|
|
(indent-to margin)
|
|
(vhdl-insert-keyword "BEGIN")
|
|
(if vhdl-self-insert-comments
|
|
(insert (and name (concat " -- " name))))
|
|
(insert "\n")
|
|
(indent-to (+ margin vhdl-basic-offset))
|
|
(setq return (point))
|
|
(newline)
|
|
(indent-to margin)
|
|
(vhdl-insert-keyword "END")
|
|
(insert (and name (concat " " name)) ";")
|
|
(goto-char return)
|
|
))
|
|
|
|
(defun vhdl-get-arg-list ()
|
|
"Read from user a procedure or function argument list."
|
|
(insert " (")
|
|
(let ((margin (current-column)))
|
|
(if (not vhdl-argument-list-indent)
|
|
(let ((opoint (point)))
|
|
(back-to-indentation)
|
|
(setq margin (+ (current-column) vhdl-basic-offset))
|
|
(goto-char opoint)
|
|
(newline)
|
|
(indent-to margin)))
|
|
(let (not-empty interface)
|
|
(setq interface (vhdl-field "[CONSTANT] [SIGNAL] [VARIABLE]"))
|
|
(if (not (equal interface ""))
|
|
(insert " "))
|
|
(while (not (string-equal (vhdl-field "[names]") ""))
|
|
(setq not-empty t)
|
|
(insert " : ")
|
|
(if (not (equal (vhdl-field "[direction]") ""))
|
|
(insert " "))
|
|
(vhdl-field "type" ";\n")
|
|
(indent-to margin)
|
|
(setq interface (vhdl-field "[CONSTANT] [SIGNAL] [VARIABLE]"))
|
|
(if (not (equal interface ""))
|
|
(insert " ")))
|
|
(if not-empty
|
|
(progn (kill-line -0)
|
|
(delete-char -2)
|
|
(if (not vhdl-argument-list-indent)
|
|
(progn (insert "\n") (indent-to margin)))
|
|
(insert ")"))
|
|
(if vhdl-argument-list-indent
|
|
(backward-delete-char 2)
|
|
(kill-line -0)
|
|
(backward-delete-char 3)))
|
|
; (while (string-match "[,;]$" args)
|
|
; (newline)
|
|
; (indent-to margin) (setq args (vhdl-field "next argument")))
|
|
; (insert 41) ;close-paren
|
|
)))
|
|
|
|
(defun vhdl-get-port (optional &optional no-comment)
|
|
"Read from user a port spec argument list."
|
|
(let ((margin (current-column))
|
|
(start (point)))
|
|
(if (not vhdl-argument-list-indent)
|
|
(let ((opoint (point)))
|
|
(back-to-indentation)
|
|
(setq margin (+ (current-column) vhdl-basic-offset))
|
|
(goto-char opoint)
|
|
(newline)
|
|
(indent-to margin)))
|
|
(let ((vhdl-ports (vhdl-field "[names]")))
|
|
(if (string-equal vhdl-ports "")
|
|
(if optional
|
|
(progn (vhdl-kill-entire-line) (forward-line -1)
|
|
(if (not vhdl-argument-list-indent)
|
|
(progn (vhdl-kill-entire-line) (forward-line -1))))
|
|
(progn (undo 0) (insert " "))
|
|
nil )
|
|
(insert " : ")
|
|
(progn
|
|
(let ((semicolon-pos))
|
|
(while (not (string-equal "" vhdl-ports))
|
|
(vhdl-field "direction")
|
|
(insert " ")
|
|
(vhdl-field "type")
|
|
(setq semicolon-pos (point))
|
|
(insert ";")
|
|
(if (not no-comment)
|
|
(vhdl-declaration-comment))
|
|
(newline)
|
|
(indent-to margin)
|
|
(setq vhdl-ports (vhdl-field "[names]" " : ")))
|
|
(goto-char semicolon-pos)
|
|
(if (not vhdl-argument-list-indent)
|
|
(progn (insert "\n") (indent-to margin)))
|
|
(insert ")")
|
|
(forward-char 1)
|
|
(if (= (following-char) ? )
|
|
(delete-char 1))
|
|
(forward-line 1)
|
|
(vhdl-kill-entire-line)
|
|
(end-of-line -0)
|
|
(if vhdl-auto-align (vhdl-align start (point) 1))
|
|
t))))))
|
|
|
|
(defun vhdl-get-generic (optional &optional no-value )
|
|
"Read from user a generic spec argument list."
|
|
(let ((margin (current-column))
|
|
(start (point)))
|
|
(if (not vhdl-argument-list-indent)
|
|
(let ((opoint (point)))
|
|
(back-to-indentation)
|
|
(setq margin (+ (current-column) vhdl-basic-offset))
|
|
(goto-char opoint)
|
|
(newline)
|
|
(indent-to margin)))
|
|
(let ((vhdl-generic))
|
|
(if no-value
|
|
(setq vhdl-generic (vhdl-field "[names]"))
|
|
(setq vhdl-generic (vhdl-field "[name]")))
|
|
(if (string-equal vhdl-generic "")
|
|
(if optional
|
|
(progn (vhdl-kill-entire-line) (end-of-line -0)
|
|
(if (not vhdl-argument-list-indent)
|
|
(progn (vhdl-kill-entire-line) (end-of-line -0))))
|
|
(progn (undo 0) (insert " "))
|
|
nil )
|
|
(insert " : ")
|
|
(progn
|
|
(let ((semicolon-pos))
|
|
(while (not(string-equal "" vhdl-generic))
|
|
(vhdl-field "type")
|
|
(if no-value
|
|
(progn (setq semicolon-pos (point))
|
|
(insert ";"))
|
|
(insert " := ")
|
|
(if (equal (vhdl-field "[value]") "")
|
|
(delete-char -4))
|
|
(setq semicolon-pos (point))
|
|
(insert ";")
|
|
(vhdl-declaration-comment))
|
|
(newline)
|
|
(indent-to margin)
|
|
(if no-value
|
|
(setq vhdl-generic (vhdl-field "[names]" " : "))
|
|
(setq vhdl-generic (vhdl-field "[name]" " : "))))
|
|
(goto-char semicolon-pos)
|
|
(if (not vhdl-argument-list-indent)
|
|
(progn (insert "\n") (indent-to margin)))
|
|
(insert ")")
|
|
(forward-char 1)
|
|
(if (= (following-char) ? )
|
|
(delete-char 1))
|
|
(forward-line 1)
|
|
(vhdl-kill-entire-line)
|
|
(end-of-line -0)
|
|
(if vhdl-auto-align (vhdl-align start (point) 1))
|
|
t))))))
|
|
|
|
(defun vhdl-insert-date ()
|
|
"Insert date in appropriate format."
|
|
(interactive)
|
|
(insert
|
|
(cond
|
|
((eq vhdl-date-format 'american) (format-time-string "%m/%d/%Y" nil))
|
|
((eq vhdl-date-format 'european) (format-time-string "%d.%m.%Y" nil))
|
|
((eq vhdl-date-format 'scientific) (format-time-string "%Y/%m/%d" nil))
|
|
)))
|
|
|
|
(defun vhdl-insert-keyword (keyword)
|
|
(insert (if vhdl-upper-case-keywords (upcase keyword) (downcase keyword)))
|
|
)
|
|
|
|
(defun vhdl-case-keyword (keyword)
|
|
(if vhdl-upper-case-keywords (upcase keyword) (downcase keyword))
|
|
)
|
|
|
|
(defun vhdl-case-word (num)
|
|
(if vhdl-upper-case-keywords (upcase-word num) (downcase-word num))
|
|
)
|
|
|
|
(defun vhdl-fix-case-region-1 (beg end upper-case word-regexp &optional count)
|
|
"Convert all words matching word-regexp in region to lower or upper case,
|
|
depending on parameter upper-case."
|
|
(let ((case-fold-search t)
|
|
(case-replace nil)
|
|
(busy-counter 0))
|
|
(modify-syntax-entry ?_ "w" vhdl-mode-syntax-table)
|
|
(save-excursion
|
|
(goto-char beg)
|
|
(while (re-search-forward word-regexp end t)
|
|
(or (vhdl-in-comment-p)
|
|
(vhdl-in-string-p)
|
|
(if upper-case
|
|
(upcase-word -1)
|
|
(downcase-word -1)))
|
|
(if (and count
|
|
(/= busy-counter (setq busy-counter
|
|
(+ (* count 25) (/ (* 25 (- (point) beg)) (- end beg))))))
|
|
(message (format "Fixing case ... (%2d%s)" busy-counter "%%"))))
|
|
(goto-char end))
|
|
(if (not vhdl-underscore-is-part-of-word)
|
|
(modify-syntax-entry ?_ "_" vhdl-mode-syntax-table))
|
|
(message "")
|
|
))
|
|
|
|
(defun vhdl-fix-case-region (beg end &optional arg)
|
|
"Convert all VHDL words in region to lower or upper case, depending on
|
|
variables vhdl-upper-case-{keywords,types,attributes,enum-values}."
|
|
(interactive "r\nP")
|
|
(vhdl-fix-case-region-1
|
|
beg end vhdl-upper-case-keywords vhdl-93-keywords-regexp 0)
|
|
(vhdl-fix-case-region-1
|
|
beg end vhdl-upper-case-types vhdl-93-types-regexp 1)
|
|
(vhdl-fix-case-region-1
|
|
beg end vhdl-upper-case-attributes vhdl-93-attributes-regexp 2)
|
|
(vhdl-fix-case-region-1
|
|
beg end vhdl-upper-case-enum-values vhdl-93-enum-values-regexp 3)
|
|
)
|
|
|
|
(defun vhdl-fix-case-buffer ()
|
|
"Convert all VHDL words in buffer to lower or upper case, depending on
|
|
variables vhdl-upper-case-{keywords,types,attributes,enum-values}."
|
|
(interactive)
|
|
(vhdl-fix-case-region (point-min) (point-max))
|
|
)
|
|
|
|
(defun vhdl-minibuffer-tab (&optional prefix-arg)
|
|
"If preceeding character is part of a word then dabbrev-expand,
|
|
else if right of non whitespace on line then tab-to-tab-stop,
|
|
else indent line in proper way for current major mode
|
|
(used for word completion in VHDL minibuffer)."
|
|
(interactive "P")
|
|
(cond ((= (char-syntax (preceding-char)) ?w)
|
|
(let ((case-fold-search nil)) (dabbrev-expand prefix-arg)))
|
|
((> (current-column) (current-indentation))
|
|
(tab-to-tab-stop))
|
|
(t
|
|
(if (eq indent-line-function 'indent-to-left-margin)
|
|
(insert-tab prefix-arg)
|
|
(if prefix-arg
|
|
(funcall indent-line-function prefix-arg)
|
|
(funcall indent-line-function))))))
|
|
|
|
(defun vhdl-help ()
|
|
"Display help information in '*Help*' buffer ."
|
|
(interactive)
|
|
(with-output-to-temp-buffer "*Help*"
|
|
(princ mode-name)
|
|
(princ " mode:\n")
|
|
(princ (documentation major-mode))
|
|
(save-excursion
|
|
(set-buffer standard-output)
|
|
(help-mode))
|
|
(print-help-return-message)))
|
|
|
|
(defun vhdl-current-line ()
|
|
"Return the line number of the line containing point."
|
|
(save-restriction
|
|
(widen)
|
|
(save-excursion
|
|
(beginning-of-line)
|
|
(1+ (count-lines 1 (point)))))
|
|
)
|
|
|
|
(defun vhdl-kill-entire-line ()
|
|
"Delete entire line."
|
|
(interactive)
|
|
(end-of-line)
|
|
(kill-line -0)
|
|
(delete-char 1)
|
|
)
|
|
|
|
(defun vhdl-open-line ()
|
|
"Open a new line and indent."
|
|
(interactive)
|
|
(end-of-line)
|
|
(newline-and-indent)
|
|
)
|
|
|
|
(defun vhdl-kill-line ()
|
|
"Kill current line."
|
|
(interactive)
|
|
(vhdl-kill-entire-line)
|
|
)
|
|
|
|
(defun vhdl-character-to-event-hack (char)
|
|
(if (memq 'XEmacs vhdl-emacs-features)
|
|
(character-to-event char)
|
|
char))
|
|
|
|
;; ############################################################################
|
|
;; Abbrev hooks
|
|
|
|
(defun vhdl-electric-mode ()
|
|
"Toggle VHDL Electric mode."
|
|
(interactive)
|
|
(setq vhdl-electric-mode (not vhdl-electric-mode))
|
|
(setq mode-name (if vhdl-electric-mode "Electric VHDL" "VHDL"))
|
|
(force-mode-line-update)
|
|
)
|
|
|
|
(defun vhdl-stutter-mode ()
|
|
"Toggle VHDL Stuttering mode."
|
|
(interactive)
|
|
(setq vhdl-stutter-mode (not vhdl-stutter-mode))
|
|
)
|
|
|
|
(defun vhdl-hooked-abbrev (fun)
|
|
"Do function, if syntax says abbrev is a keyword, invoked by hooked abbrev,
|
|
but not if inside a comment or quote)"
|
|
(if (or (vhdl-in-comment-p)
|
|
(vhdl-in-string-p)
|
|
(save-excursion (forward-word -1) (looking-at "end")))
|
|
(progn
|
|
(insert " ")
|
|
(unexpand-abbrev)
|
|
(delete-char -1))
|
|
(if (not vhdl-electric-mode)
|
|
(progn
|
|
(insert " ")
|
|
(unexpand-abbrev)
|
|
(backward-word 1)
|
|
(vhdl-case-word 1)
|
|
(delete-char 1)
|
|
)
|
|
(let ((invoke-char last-command-char) (abbrev-mode -1))
|
|
(funcall fun)
|
|
(if (= invoke-char ?-) (setq abbrev-start-location (point)))
|
|
;; delete CR which is still in event queue
|
|
(if (memq 'XEmacs vhdl-emacs-features)
|
|
(enqueue-eval-event 'delete-char -1)
|
|
(setq unread-command-events ; push back a delete char
|
|
(list (vhdl-character-to-event-hack ?\177))))
|
|
))))
|
|
|
|
(defun vhdl-alias-hook () "hooked version of vhdl-alias."
|
|
(vhdl-hooked-abbrev 'vhdl-alias))
|
|
(defun vhdl-architecture-hook () "hooked version of vhdl-architecture."
|
|
(vhdl-hooked-abbrev 'vhdl-architecture))
|
|
(defun vhdl-array-hook () "hooked version of vhdl-array."
|
|
(vhdl-hooked-abbrev 'vhdl-array))
|
|
(defun vhdl-assert-hook () "hooked version of vhdl-assert."
|
|
(vhdl-hooked-abbrev 'vhdl-assert))
|
|
(defun vhdl-attribute-hook () "hooked version of vhdl-attribute."
|
|
(vhdl-hooked-abbrev 'vhdl-attribute))
|
|
(defun vhdl-block-hook () "hooked version of vhdl-block."
|
|
(vhdl-hooked-abbrev 'vhdl-block))
|
|
(defun vhdl-case-hook () "hooked version of vhdl-case."
|
|
(vhdl-hooked-abbrev 'vhdl-case))
|
|
(defun vhdl-component-hook () "hooked version of vhdl-component."
|
|
(vhdl-hooked-abbrev 'vhdl-component))
|
|
(defun vhdl-component-instance-hook ()
|
|
"hooked version of vhdl-component-instance."
|
|
(vhdl-hooked-abbrev 'vhdl-component-instance))
|
|
(defun vhdl-concurrent-signal-assignment-hook ()
|
|
"hooked version of vhdl-concurrent-signal-assignment."
|
|
(vhdl-hooked-abbrev 'vhdl-concurrent-signal-assignment))
|
|
(defun vhdl-configuration-hook ()
|
|
"hooked version of vhdl-configuration."
|
|
(vhdl-hooked-abbrev 'vhdl-configuration))
|
|
(defun vhdl-constant-hook () "hooked version of vhdl-constant."
|
|
(vhdl-hooked-abbrev 'vhdl-constant))
|
|
(defun vhdl-disconnect-hook () "hooked version of vhdl-disconnect."
|
|
(vhdl-hooked-abbrev 'vhdl-disconnect))
|
|
(defun vhdl-display-comment-hook () "hooked version of vhdl-display-comment."
|
|
(vhdl-hooked-abbrev 'vhdl-display-comment))
|
|
(defun vhdl-else-hook () "hooked version of vhdl-else."
|
|
(vhdl-hooked-abbrev 'vhdl-else))
|
|
(defun vhdl-elsif-hook () "hooked version of vhdl-elsif."
|
|
(vhdl-hooked-abbrev 'vhdl-elsif))
|
|
(defun vhdl-entity-hook () "hooked version of vhdl-entity."
|
|
(vhdl-hooked-abbrev 'vhdl-entity))
|
|
(defun vhdl-exit-hook () "hooked version of vhdl-exit."
|
|
(vhdl-hooked-abbrev 'vhdl-exit))
|
|
(defun vhdl-for-hook () "hooked version of vhdl-for."
|
|
(vhdl-hooked-abbrev 'vhdl-for))
|
|
(defun vhdl-function-hook () "hooked version of vhdl-function."
|
|
(vhdl-hooked-abbrev 'vhdl-function))
|
|
(defun vhdl-generate-hook () "hooked version of vhdl-generate."
|
|
(vhdl-hooked-abbrev 'vhdl-generate))
|
|
(defun vhdl-generic-hook () "hooked version of vhdl-generic."
|
|
(vhdl-hooked-abbrev 'vhdl-generic))
|
|
(defun vhdl-library-hook () "hooked version of vhdl-library."
|
|
(vhdl-hooked-abbrev 'vhdl-library))
|
|
(defun vhdl-header-hook () "hooked version of vhdl-header."
|
|
(vhdl-hooked-abbrev 'vhdl-header))
|
|
(defun vhdl-if-hook () "hooked version of vhdl-if."
|
|
(vhdl-hooked-abbrev 'vhdl-if))
|
|
(defun vhdl-loop-hook () "hooked version of vhdl-loop."
|
|
(vhdl-hooked-abbrev 'vhdl-loop))
|
|
(defun vhdl-map-hook () "hooked version of vhdl-map."
|
|
(vhdl-hooked-abbrev 'vhdl-map))
|
|
(defun vhdl-modify-hook () "hooked version of vhdl-modify."
|
|
(vhdl-hooked-abbrev 'vhdl-modify))
|
|
(defun vhdl-next-hook () "hooked version of vhdl-next."
|
|
(vhdl-hooked-abbrev 'vhdl-next))
|
|
(defun vhdl-package-hook () "hooked version of vhdl-package."
|
|
(vhdl-hooked-abbrev 'vhdl-package))
|
|
(defun vhdl-port-hook () "hooked version of vhdl-port."
|
|
(vhdl-hooked-abbrev 'vhdl-port))
|
|
(defun vhdl-procedure-hook () "hooked version of vhdl-procedure."
|
|
(vhdl-hooked-abbrev 'vhdl-procedure))
|
|
(defun vhdl-process-hook () "hooked version of vhdl-process."
|
|
(vhdl-hooked-abbrev 'vhdl-process))
|
|
(defun vhdl-record-hook () "hooked version of vhdl-record."
|
|
(vhdl-hooked-abbrev 'vhdl-record))
|
|
(defun vhdl-return-hook () "hooked version of vhdl-return-value."
|
|
(vhdl-hooked-abbrev 'vhdl-return-value))
|
|
(defun vhdl-selected-signal-assignment-hook ()
|
|
"hooked version of vhdl-selected-signal-assignment."
|
|
(vhdl-hooked-abbrev 'vhdl-selected-signal-assignment))
|
|
(defun vhdl-signal-hook () "hooked version of vhdl-signal."
|
|
(vhdl-hooked-abbrev 'vhdl-signal))
|
|
(defun vhdl-subtype-hook () "hooked version of vhdl-subtype."
|
|
(vhdl-hooked-abbrev 'vhdl-subtype))
|
|
(defun vhdl-type-hook () "hooked version of vhdl-type."
|
|
(vhdl-hooked-abbrev 'vhdl-type))
|
|
(defun vhdl-use-hook () "hooked version of vhdl-use."
|
|
(vhdl-hooked-abbrev 'vhdl-use))
|
|
(defun vhdl-variable-hook () "hooked version of vhdl-variable."
|
|
(vhdl-hooked-abbrev 'vhdl-variable))
|
|
(defun vhdl-wait-hook () "hooked version of vhdl-wait."
|
|
(vhdl-hooked-abbrev 'vhdl-wait))
|
|
(defun vhdl-when-hook () "hooked version of vhdl-when."
|
|
(vhdl-hooked-abbrev 'vhdl-when))
|
|
(defun vhdl-while-loop-hook () "hooked version of vhdl-while-loop."
|
|
(vhdl-hooked-abbrev 'vhdl-while-loop))
|
|
(defun vhdl-and-hook () "hooked version of vhdl-and."
|
|
(vhdl-hooked-abbrev 'vhdl-and))
|
|
(defun vhdl-or-hook () "hooked version of vhdl-or."
|
|
(vhdl-hooked-abbrev 'vhdl-or))
|
|
(defun vhdl-nand-hook () "hooked version of vhdl-nand."
|
|
(vhdl-hooked-abbrev 'vhdl-nand))
|
|
(defun vhdl-nor-hook () "hooked version of vhdl-nor."
|
|
(vhdl-hooked-abbrev 'vhdl-nor))
|
|
(defun vhdl-xor-hook () "hooked version of vhdl-xor."
|
|
(vhdl-hooked-abbrev 'vhdl-xor))
|
|
(defun vhdl-xnor-hook () "hooked version of vhdl-xnor."
|
|
(vhdl-hooked-abbrev 'vhdl-xnor))
|
|
(defun vhdl-not-hook () "hooked version of vhdl-not."
|
|
(vhdl-hooked-abbrev 'vhdl-not))
|
|
|
|
(defun vhdl-default-hook () "hooked version of vhdl-default."
|
|
(vhdl-hooked-abbrev 'vhdl-default))
|
|
(defun vhdl-default-indent-hook () "hooked version of vhdl-default-indent."
|
|
(vhdl-hooked-abbrev 'vhdl-default-indent))
|
|
|
|
|
|
;; ############################################################################
|
|
;; Font locking
|
|
;; ############################################################################
|
|
;; (using `font-lock.el')
|
|
|
|
;; ############################################################################
|
|
;; Syntax definitions
|
|
|
|
(defvar vhdl-font-lock-keywords nil
|
|
"Regular expressions to highlight in VHDL Mode.")
|
|
|
|
(defconst vhdl-font-lock-keywords-0
|
|
(list
|
|
;; highlight template prompts
|
|
'("\\(^\\|[ (.\t]\\)\\(<[^ =].*[^ =]>\\)\\([ .]\\|$\\)"
|
|
2 vhdl-font-lock-prompt-face)
|
|
|
|
;; highlight character literals
|
|
'("'\\(.\\)'" 1 'font-lock-string-face)
|
|
)
|
|
"For consideration as a value of `vhdl-font-lock-keywords'.
|
|
This does highlighting of template prompts and character literals.")
|
|
|
|
(defconst vhdl-font-lock-keywords-1
|
|
(list
|
|
;; highlight names of units, subprograms, and components when declared
|
|
(list
|
|
(concat
|
|
"^\\s-*\\("
|
|
"architecture\\|configuration\\|entity\\|package\\(\\s-+body\\|\\)\\|"
|
|
"function\\|procedure\\|component"
|
|
"\\)\\s-+\\(\\w+\\)")
|
|
3 'font-lock-function-name-face)
|
|
|
|
;; highlight labels of common constructs
|
|
(list
|
|
(concat
|
|
"^\\s-*\\(\\w+\\)\\s-*:\\(\\s-\\|\n\\)*\\("
|
|
"assert\\|block\\|case\\|exit\\|for\\|if\\|loop\\|"
|
|
"next\\|null\\|process\\| with\\|while\\|"
|
|
"\\w+\\(\\s-\\|\n\\)+\\(generic\\|port\\)\\s-+map"
|
|
"\\)\\>")
|
|
1 'font-lock-function-name-face)
|
|
|
|
;; highlight entity names of architectures and configurations
|
|
(list
|
|
"^\\s-*\\(architecture\\|configuration\\)\\s-+\\w+\\s-+of\\s-+\\(\\w+\\)"
|
|
2 'font-lock-function-name-face)
|
|
|
|
;; highlight names and labels at end of constructs
|
|
(list
|
|
(concat
|
|
"^\\s-*end\\s-+\\("
|
|
"\\(block\\|case\\|component\\|for\\|generate\\|if\\|loop\\|"
|
|
"process\\|record\\|units\\)\\>\\|"
|
|
"\\)\\s-*\\(\\w*\\)")
|
|
3 'font-lock-function-name-face)
|
|
)
|
|
"For consideration as a value of `vhdl-font-lock-keywords'.
|
|
This does highlighting of names and labels.")
|
|
|
|
(defconst vhdl-font-lock-keywords-2
|
|
(list
|
|
;; highlight keywords, and types, standardized attributes, enumeration values
|
|
(list (concat "'" vhdl-93-attributes-regexp)
|
|
1 'vhdl-font-lock-attribute-face)
|
|
(list vhdl-93-types-regexp 1 'font-lock-type-face)
|
|
(list vhdl-93-enum-values-regexp 1 'vhdl-font-lock-value-face)
|
|
(list vhdl-93-keywords-regexp 1 'font-lock-keyword-face)
|
|
)
|
|
"For consideration as a value of `vhdl-font-lock-keywords'.
|
|
This does highlighting of comments, keywords, and standard types.")
|
|
|
|
(defconst vhdl-font-lock-keywords-3
|
|
(list
|
|
;; highlight clock signals.
|
|
(cons vhdl-clock-signal-syntax 'vhdl-font-lock-clock-signal-face)
|
|
(cons vhdl-reset-signal-syntax 'vhdl-font-lock-reset-signal-face)
|
|
(cons vhdl-control-signal-syntax 'vhdl-font-lock-control-signal-face)
|
|
(cons vhdl-data-signal-syntax 'vhdl-font-lock-data-signal-face)
|
|
(cons vhdl-test-signal-syntax 'vhdl-font-lock-test-signal-face)
|
|
)
|
|
"For consideration as a value of `vhdl-font-lock-keywords'.
|
|
This does highlighting of signal names with specific syntax.")
|
|
|
|
;; ############################################################################
|
|
;; Font and color definitions
|
|
|
|
(defvar vhdl-font-lock-prompt-face 'vhdl-font-lock-prompt-face
|
|
"Face name to use for prompts.")
|
|
|
|
(defvar vhdl-font-lock-attribute-face 'vhdl-font-lock-attribute-face
|
|
"Face name to use for attributes.")
|
|
|
|
(defvar vhdl-font-lock-value-face 'vhdl-font-lock-value-face
|
|
"Face name to use for enumeration values.")
|
|
|
|
(defvar vhdl-font-lock-clock-signal-face 'vhdl-font-lock-clock-signal-face
|
|
"Face name to use for clock signals.")
|
|
|
|
(defvar vhdl-font-lock-reset-signal-face 'vhdl-font-lock-reset-signal-face
|
|
"Face name to use for reset signals.")
|
|
|
|
(defvar vhdl-font-lock-control-signal-face 'vhdl-font-lock-control-signal-face
|
|
"Face name to use for control signals.")
|
|
|
|
(defvar vhdl-font-lock-data-signal-face 'vhdl-font-lock-data-signal-face
|
|
"Face name to use for data signals.")
|
|
|
|
(defvar vhdl-font-lock-test-signal-face 'vhdl-font-lock-test-signal-face
|
|
"Face name to use for test signals.")
|
|
|
|
(defface vhdl-font-lock-prompt-face
|
|
'((((class color) (background light)) (:foreground "Red"))
|
|
(((class color) (background dark)) (:foreground "Red"))
|
|
(t (:inverse-video t)))
|
|
"Font Lock mode face used to highlight prompts."
|
|
:group 'font-lock-highlighting-faces)
|
|
|
|
(defface vhdl-font-lock-attribute-face
|
|
'((((class color) (background light)) (:foreground "CadetBlue"))
|
|
(((class color) (background dark)) (:foreground "CadetBlue"))
|
|
(t (:italic t :bold t)))
|
|
"Font Lock mode face used to highlight attributes."
|
|
:group 'font-lock-highlighting-faces)
|
|
|
|
(defface vhdl-font-lock-value-face
|
|
'((((class color) (background light)) (:foreground "DarkGoldenrod"))
|
|
(((class color) (background dark)) (:foreground "DarkGoldenrod"))
|
|
(t (:italic t :bold t)))
|
|
"Font Lock mode face used to highlight enumeration values."
|
|
:group 'font-lock-highlighting-faces)
|
|
|
|
(defface vhdl-font-lock-clock-signal-face
|
|
'((((class color) (background light)) (:foreground "LimeGreen"))
|
|
(((class color) (background dark)) (:foreground "LimeGreen"))
|
|
(t ()))
|
|
"Font Lock mode face used to highlight clock signals."
|
|
:group 'font-lock-highlighting-faces)
|
|
|
|
(defface vhdl-font-lock-reset-signal-face
|
|
'((((class color) (background light)) (:foreground "Red"))
|
|
(((class color) (background dark)) (:foreground "Red"))
|
|
(t ()))
|
|
"Font Lock mode face used to highlight reset signals."
|
|
:group 'font-lock-highlighting-faces)
|
|
|
|
(defface vhdl-font-lock-control-signal-face
|
|
'((((class color) (background light)) (:foreground "Blue"))
|
|
(((class color) (background dark)) (:foreground "Blue"))
|
|
(t ()))
|
|
"Font Lock mode face used to highlight control signals."
|
|
:group 'font-lock-highlighting-faces)
|
|
|
|
(defface vhdl-font-lock-data-signal-face
|
|
'((((class color) (background light)) (:foreground "Black"))
|
|
(((class color) (background dark)) (:foreground "Black"))
|
|
(t ()))
|
|
"Font Lock mode face used to highlight data signals."
|
|
:group 'font-lock-highlighting-faces)
|
|
|
|
(defface vhdl-font-lock-test-signal-face
|
|
'((((class color) (background light)) (:foreground "Gold"))
|
|
(((class color) (background dark)) (:foreground "Gold"))
|
|
(t ()))
|
|
"Font Lock mode face used to highlight test signals."
|
|
:group 'font-lock-highlighting-faces)
|
|
|
|
;; Custom color definitions for existing faces
|
|
(defun vhdl-set-face-foreground ()
|
|
(set-face-foreground 'font-lock-comment-face "IndianRed")
|
|
(set-face-foreground 'font-lock-function-name-face "MediumOrchid")
|
|
(set-face-foreground 'font-lock-keyword-face "SlateBlue")
|
|
(set-face-foreground 'font-lock-string-face "RosyBrown")
|
|
(set-face-foreground 'font-lock-type-face "ForestGreen")
|
|
)
|
|
|
|
(defun vhdl-set-face-grayscale ()
|
|
(interactive)
|
|
(set-face-bold-p 'font-lock-comment-face nil)
|
|
(set-face-inverse-video-p 'font-lock-comment-face nil)
|
|
(set-face-italic-p 'font-lock-comment-face t)
|
|
(set-face-underline-p 'font-lock-comment-face nil)
|
|
|
|
(set-face-bold-p 'font-lock-function-name-face nil)
|
|
(set-face-inverse-video-p 'font-lock-function-name-face nil)
|
|
(set-face-italic-p 'font-lock-function-name-face t)
|
|
(set-face-underline-p 'font-lock-function-name-face nil)
|
|
|
|
(set-face-bold-p 'font-lock-keyword-face t)
|
|
(set-face-inverse-video-p 'font-lock-keyword-face nil)
|
|
(set-face-italic-p 'font-lock-keyword-face nil)
|
|
(set-face-underline-p 'font-lock-keyword-face nil)
|
|
|
|
(set-face-bold-p 'font-lock-string-face nil)
|
|
(set-face-inverse-video-p 'font-lock-string-face nil)
|
|
(set-face-italic-p 'font-lock-string-face nil)
|
|
(set-face-underline-p 'font-lock-string-face t)
|
|
|
|
(set-face-bold-p 'font-lock-type-face t)
|
|
(set-face-inverse-video-p 'font-lock-type-face nil)
|
|
(set-face-italic-p 'font-lock-type-face t)
|
|
(set-face-underline-p 'font-lock-type-face nil)
|
|
)
|
|
|
|
;; ############################################################################
|
|
;; Font lock initialization
|
|
|
|
(defun vhdl-font-lock-init ()
|
|
"Initializes fontification."
|
|
(setq vhdl-font-lock-keywords
|
|
(append vhdl-font-lock-keywords-0
|
|
(if vhdl-highlight-names vhdl-font-lock-keywords-1)
|
|
(if vhdl-highlight-keywords vhdl-font-lock-keywords-2)
|
|
(if (and vhdl-highlight-signals (x-display-color-p))
|
|
vhdl-font-lock-keywords-3)))
|
|
(if (x-display-color-p)
|
|
(if (not vhdl-use-default-colors) (vhdl-set-face-foreground))
|
|
(if (not vhdl-use-default-faces) (vhdl-set-face-grayscale))
|
|
))
|
|
|
|
;; ############################################################################
|
|
;; Fontification for postscript printing
|
|
|
|
(defun vhdl-ps-init ()
|
|
"Initializes face and page settings for postscript printing."
|
|
(require 'ps-print)
|
|
(unless (or vhdl-use-default-faces
|
|
ps-print-color-p)
|
|
(set (make-local-variable 'ps-bold-faces)
|
|
'(font-lock-keyword-face
|
|
font-lock-type-face
|
|
vhdl-font-lock-attribute-face
|
|
vhdl-font-lock-value-face))
|
|
(set (make-local-variable 'ps-italic-faces)
|
|
'(font-lock-comment-face
|
|
font-lock-function-name-face
|
|
font-lock-type-face
|
|
vhdl-font-lock-prompt-face
|
|
vhdl-font-lock-attribute-face
|
|
vhdl-font-lock-value-face))
|
|
(set (make-local-variable 'ps-underlined-faces)
|
|
'(font-lock-string-face))
|
|
)
|
|
;; define page settings, so that a line containing 79 characters (default)
|
|
;; fits into one column
|
|
(if vhdl-print-two-column
|
|
(progn
|
|
(set (make-local-variable 'ps-landscape-mode) t)
|
|
(set (make-local-variable 'ps-number-of-columns) 2)
|
|
(set (make-local-variable 'ps-font-size) 7.0)
|
|
(set (make-local-variable 'ps-header-title-font-size) 10.0)
|
|
(set (make-local-variable 'ps-header-font-size) 9.0)
|
|
(set (make-local-variable 'ps-header-offset) 12.0)
|
|
(if (eq ps-paper-type 'letter)
|
|
(progn
|
|
(set (make-local-variable 'ps-inter-column) 40.0)
|
|
(set (make-local-variable 'ps-left-margin) 40.0)
|
|
(set (make-local-variable 'ps-right-margin) 40.0)
|
|
)))))
|
|
|
|
|
|
;; ############################################################################
|
|
;; Hideshow
|
|
;; ############################################################################
|
|
;; (using `hideshow.el')
|
|
|
|
(defun vhdl-forward-sexp-function (&optional count)
|
|
"Find begin and end of VHDL process or block (for hideshow)."
|
|
(interactive "p")
|
|
(let (name
|
|
(case-fold-search t))
|
|
(end-of-line)
|
|
(if (< count 0)
|
|
(re-search-backward "\\s-*\\(\\w\\|\\s_\\)+\\s-*:\\s-*\\(process\\|block\\)\\>" nil t)
|
|
(re-search-forward "\\s-*\\<end\\s-+\\(process\\|block\\)\\>" nil t)
|
|
)))
|
|
|
|
(require 'hideshow)
|
|
|
|
(unless (assq 'vhdl-mode hs-special-modes-alist)
|
|
(setq hs-special-modes-alist
|
|
(cons
|
|
'(vhdl-mode
|
|
"\\s-*\\(\\w\\|\\s_\\)+\\s-*:\\s-*\\(process\\|PROCESS\\|block\\|BLOCK\\)\\>"
|
|
"\\s-*\\<\\(end\\|END\\)\\s-+\\(process\\|PROCESS\\|block\\|BLOCK\\)\\>"
|
|
"-- "
|
|
vhdl-forward-sexp-function)
|
|
hs-special-modes-alist)))
|
|
|
|
|
|
;; ############################################################################
|
|
;; Compilation
|
|
;; ############################################################################
|
|
;; (using `compile.el')
|
|
|
|
(defvar vhdl-compile-commands
|
|
'(
|
|
(cadence "cv -file" nil)
|
|
(ikos "analyze" nil)
|
|
(quickhdl "qvhcom" nil)
|
|
(synopsys "vhdlan" nil)
|
|
(vantage "analyze -libfile vsslib.ini -src" nil)
|
|
(viewlogic "analyze -libfile vsslib.ini -src" nil)
|
|
(v-system "vcom" "vmake > Makefile")
|
|
)
|
|
"Commands to be called in the shell for compilation (syntax analysis) of a
|
|
single buffer and `Makefile' generation for different tools. First item is tool
|
|
identifier, second item is shell command for compilation, and third item is
|
|
shell command for `Makefile' generation. A tool is specified by assigning a
|
|
tool identifier to variable `vhdl-compiler'.")
|
|
|
|
(defvar vhdl-compilation-error-regexp-alist
|
|
(list
|
|
;; Cadence Design Systems: cv -file test.vhd
|
|
;; duluth: *E,430 (test.vhd,13): identifier (POSITIV) is not declared
|
|
'("duluth: \\*E,[0-9]+ (\\(.+\\),\\([0-9]+\\)):" 1 2)
|
|
|
|
;; Ikos Voyager: analyze test.vhd
|
|
;; E L4/C5: this library unit is inaccessible
|
|
; Xemacs does not support error messages without included file name
|
|
(if (not (memq 'XEmacs vhdl-emacs-features))
|
|
'("E L\\([0-9]+\\)/C[0-9]+:" nil 1)
|
|
'("E L\\([0-9]+\\)/C[0-9]+:" 2 1)
|
|
)
|
|
|
|
;; QuickHDL, Mentor Graphics: qvhcom test.vhd
|
|
;; ERROR: test.vhd(24): near "dnd": expecting: END
|
|
'("ERROR: \\(.+\\)(\\([0-9]+\\)):" 1 2)
|
|
|
|
;; Synopsys, VHDL Analyzer: vhdlan test.vhd
|
|
;; **Error: vhdlan,703 test.vhd(22): OTHERS is not legal in this context.
|
|
'("\\*\\*Error: vhdlan,[0-9]+ \\(.+\\)(\\([0-9]+\\)):" 1 2)
|
|
|
|
;; Vantage Analysis Systems: analyze -libfile vsslib.ini -src test.vhd
|
|
;; **Error: LINE 499 *** No aggregate value is valid in this context.
|
|
; Xemacs does not support error messages without included file name
|
|
(if (not (memq 'XEmacs vhdl-emacs-features))
|
|
'("\\*\\*Error: LINE \\([0-9]+\\) \\*\\*\\*" nil 1)
|
|
'("\\*\\*Error: LINE \\([0-9]+\\) \\*\\*\\*" 2 1)
|
|
)
|
|
|
|
;; Viewlogic: analyze -libfile vsslib.ini -src test.vhd
|
|
;; **Error: LINE 499 *** No aggregate value is valid in this context.
|
|
;; same regexp as for Vantage
|
|
|
|
;; V-System, Model Technology: vcom test.vhd
|
|
;; ERROR: test.vhd(14): Unknown identifier: positiv
|
|
;; same regexp as for QuickHDL
|
|
|
|
) "Alist that specifies how to match errors in VHDL compiler output.")
|
|
|
|
(defvar compilation-file-regexp-alist
|
|
'(
|
|
;; Ikos Voyager: analyze -libfile vsslib.ini -src test.vhd
|
|
;; analyze sdrctl.vhd
|
|
("^analyze +\\(.+ +\\)*\\(.+\\)$" 2)
|
|
|
|
;; Vantage Analysis Systems: analyze -libfile vsslib.ini -src test.vhd
|
|
;; Compiling "pcu.vhd" line 1...
|
|
(" *Compiling \"\\(.+\\)\" " 1)
|
|
|
|
;; Viewlogic: analyze -libfile vsslib.ini -src test.vhd
|
|
;; Compiling "pcu.vhd" line 1...
|
|
;; same regexp as for Vantage
|
|
|
|
) "Alist specifying how to match lines that indicate a new current file.
|
|
Used for compilers with no file name in the error messages.")
|
|
|
|
(defun vhdl-compile ()
|
|
"Compile current buffer using the VHDL compiler specified in
|
|
`vhdl-compiler'."
|
|
(interactive)
|
|
(let ((command-list vhdl-compile-commands)
|
|
command)
|
|
(while command-list
|
|
(if (eq vhdl-compiler (car (car command-list)))
|
|
(setq command (car (cdr (car command-list)))))
|
|
(setq command-list (cdr command-list)))
|
|
(if command
|
|
(compile (concat command " " vhdl-compiler-options
|
|
(if (not (string-equal vhdl-compiler-options "")) " ")
|
|
(file-name-nondirectory (buffer-file-name)))))))
|
|
|
|
(defun vhdl-make ()
|
|
"Call make command for compilation of all updated source files
|
|
(requires `Makefile')."
|
|
(interactive)
|
|
(compile "make"))
|
|
|
|
(defun vhdl-generate-makefile ()
|
|
"Generate new `Makefile'."
|
|
(interactive)
|
|
(let ((command-list vhdl-compile-commands)
|
|
command)
|
|
(while command-list
|
|
(if (eq vhdl-compiler (car (car command-list)))
|
|
(setq command (car (cdr (cdr (car command-list))))))
|
|
(setq command-list (cdr command-list)))
|
|
(if command
|
|
(compile command )
|
|
(message (format "Not implemented for `%s'!" vhdl-compiler))
|
|
(beep))))
|
|
|
|
|
|
;; ############################################################################
|
|
;; Bug reports
|
|
;; ############################################################################
|
|
;; (using `reporter.el')
|
|
|
|
(defconst vhdl-version "3.19"
|
|
"VHDL Mode version number.")
|
|
|
|
(defconst vhdl-mode-help-address "vhdl-mode@geocities.com"
|
|
"Address for VHDL Mode bug reports.")
|
|
|
|
(defun vhdl-version ()
|
|
"Echo the current version of VHDL Mode in the minibuffer."
|
|
(interactive)
|
|
(message "Using VHDL Mode version %s" vhdl-version)
|
|
(vhdl-keep-region-active))
|
|
|
|
;; get reporter-submit-bug-report when byte-compiling
|
|
(and (fboundp 'eval-when-compile)
|
|
(eval-when-compile
|
|
(require 'reporter)))
|
|
|
|
(defun vhdl-submit-bug-report ()
|
|
"Submit via mail a bug report on VHDL Mode."
|
|
(interactive)
|
|
;; load in reporter
|
|
(and
|
|
(y-or-n-p "Do you want to submit a report on VHDL Mode? ")
|
|
(require 'reporter)
|
|
(reporter-submit-bug-report
|
|
vhdl-mode-help-address
|
|
(concat "VHDL Mode " vhdl-version)
|
|
(list
|
|
;; report all important variables
|
|
'vhdl-basic-offset
|
|
'vhdl-offsets-alist
|
|
'vhdl-comment-only-line-offset
|
|
'tab-width
|
|
'vhdl-electric-mode
|
|
'vhdl-stutter-mode
|
|
'vhdl-indent-tabs-mode
|
|
'vhdl-compiler
|
|
'vhdl-compiler-options
|
|
'vhdl-upper-case-keywords
|
|
'vhdl-upper-case-types
|
|
'vhdl-upper-case-attributes
|
|
'vhdl-upper-case-enum-values
|
|
'vhdl-auto-align
|
|
'vhdl-additional-empty-lines
|
|
'vhdl-argument-list-indent
|
|
'vhdl-conditions-in-parenthesis
|
|
'vhdl-date-format
|
|
'vhdl-header-file
|
|
'vhdl-modify-date-prefix-string
|
|
'vhdl-zero-string
|
|
'vhdl-one-string
|
|
'vhdl-self-insert-comments
|
|
'vhdl-prompt-for-comments
|
|
'vhdl-comment-column
|
|
'vhdl-end-comment-column
|
|
'vhdl-highlight-names
|
|
'vhdl-highlight-keywords
|
|
'vhdl-highlight-signals
|
|
'vhdl-highlight-case-sensitive
|
|
'vhdl-use-default-colors
|
|
'vhdl-use-default-faces
|
|
'vhdl-clock-signal-syntax
|
|
'vhdl-reset-signal-syntax
|
|
'vhdl-control-signal-syntax
|
|
'vhdl-data-signal-syntax
|
|
'vhdl-test-signal-syntax
|
|
'vhdl-source-file-menu
|
|
'vhdl-index-menu
|
|
'vhdl-hideshow-menu
|
|
'vhdl-print-two-column
|
|
'vhdl-intelligent-tab
|
|
'vhdl-template-key-binding-prefix
|
|
'vhdl-word-completion-in-minibuffer
|
|
'vhdl-underscore-is-part-of-word
|
|
'vhdl-mode-hook
|
|
)
|
|
(function
|
|
(lambda ()
|
|
(insert
|
|
(if vhdl-special-indent-hook
|
|
(concat "\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"
|
|
"vhdl-special-indent-hook is set to '"
|
|
(format "%s" vhdl-special-indent-hook)
|
|
".\nPerhaps this is your problem?\n"
|
|
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n\n")
|
|
"\n")
|
|
(format "vhdl-emacs-features: %s\n" vhdl-emacs-features)
|
|
)))
|
|
nil
|
|
"Dear VHDL Mode maintainers,"
|
|
)))
|
|
|
|
|
|
;; ############################################################################
|
|
|
|
(provide 'vhdl-mode)
|
|
|
|
;;; vhdl-mode.el ends here
|