summaryrefslogtreecommitdiffstats
path: root/emacs.d/nxhtml/related/visual-basic-mode.el
diff options
context:
space:
mode:
Diffstat (limited to 'emacs.d/nxhtml/related/visual-basic-mode.el')
-rw-r--r--emacs.d/nxhtml/related/visual-basic-mode.el1263
1 files changed, 1263 insertions, 0 deletions
diff --git a/emacs.d/nxhtml/related/visual-basic-mode.el b/emacs.d/nxhtml/related/visual-basic-mode.el
new file mode 100644
index 0000000..ca448a6
--- /dev/null
+++ b/emacs.d/nxhtml/related/visual-basic-mode.el
@@ -0,0 +1,1263 @@
+;;; visual-basic-mode.el
+;; This is free software.
+
+;; A mode for editing Visual Basic programs.
+;; Modified version of Fred White's visual-basic-mode.el
+
+;; Copyright (C) 1996 Fred White <fwhite@alum.mit.edu>
+;; Copyright (C) 1998 Free Software Foundation, Inc.
+;; (additions by Dave Love)
+;; Copyright (C) 2008-2009 Free Software Foundation, Inc.
+;; (additions by Randolph Fritz and Vincent Belaiche (VB1) )
+
+;; Author: Fred White <fwhite@alum.mit.edu>
+;; Adapted-by: Dave Love <d.love@dl.ac.uk>
+;; : Kevin Whitefoot <kevin.whitefoot@nopow.abb.no>
+;; : Randolph Fritz <rfritz@u.washington.edu>
+;; : Vincent Belaiche (VB1) <vincentb1@users.sourceforge.net>
+;; Version: 1.4.8 (2009-09-29)
+;; Serial Version: %Id: 17%
+;; Keywords: languages, basic, Evil
+
+
+;; (Old) LCD Archive Entry:
+;; basic-mode|Fred White|fwhite@alum.mit.edu|
+;; A mode for editing Visual Basic programs.|
+;; 18-Apr-96|1.0|~/modes/basic-mode.el.Z|
+
+;; This file is NOT part of GNU Emacs but the same permissions apply.
+;;
+;; 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, 675 Mass Ave, Cambridge, MA 02139, USA.
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2 of the
+;; License, or (at your option) any later version.
+
+;;; Commentary:
+
+;; Purpose of this package:
+;; This is a mode for editing programs written in The World's Most
+;; Successful Programming Language. It features automatic
+;; indentation, font locking, keyword capitalization, and some minor
+;; convenience functions.
+
+;; Installation instructions
+;; Put visual-basic-mode.el somewhere in your path, compile it, and add
+;; the following to your init file:
+
+;; (autoload 'visual-basic-mode "visual-basic-mode" "Visual Basic mode." t)
+;; (setq auto-mode-alist (append '(("\\.\\(frm\\|bas\\|cls\\)$" .
+;; visual-basic-mode)) auto-mode-alist))
+;;
+;; If you are doing Rhino scripts, add:
+;; (setq auto-mode-alist (append '(("\\.\\(frm\\|bas\\|cls\\|rvb\\)$" .
+;; visual-basic-mode)) auto-mode-alist))
+
+;; If you had visual-basic-mode already installed, you may need to call
+;; visual-basic-upgrade-keyword-abbrev-table the first time that
+;; visual-basic-mode is loaded.
+
+;; Of course, under Windows 3.1, you'll have to name this file
+;; something shorter than visual-basic-mode.el
+
+;; Revisions:
+;; 1.0 18-Apr-96 Initial version
+;; 1.1 Accomodate emacs 19.29+ font-lock-defaults
+;; Simon Marshall <Simon.Marshall@esrin.esa.it>
+; 1.2 Rename to visual-basic-mode
+;; 1.3 Fix some indentation bugs.
+;; 1.3+ Changes by Dave Love: [No attempt at compatibility with
+;; anything other than Emacs 20, sorry, but little attempt to
+;; sanitize for Emacs 20 specifically.]
+;; Change `_' syntax only for font-lock and imenu, not generally;
+;; provide levels of font-locking in the current fashion;
+;; font-lock case-insensitively; use regexp-opt with the font-lok
+;; keywords; imenu support; `visual-basic-split-line', bound to
+;; C-M-j; account for single-statement `if' in indentation; add
+;; keyword "Global"; use local-write-file-hooks, not
+;; write-file-hooks.
+;; 1.4 September 1998
+;; 1.4 KJW Add begin..end, add extra keywords
+;; Add customisation for single line if. Disallow by default.
+;; Fix if regexp to require whitespace after if and require then.
+;; Add more VB keywords. Make begin..end work as if..endif so
+;; that forms are formatted correctly.
+;; 1.4.1 KJW Merged Dave Love and KJW versions.
+;; Added keywords suggested by Mickey Ferguson
+;; <MFerguson@peinc.com>
+;; Fixed imenu variable to find private variables and enums
+
+;; Changed syntax class of =, <, > to punctuation to allow dynamic
+;; abbreviations to pick up only the word at point rather than the
+;; whole expression.
+
+;; Fixed bug introduced by KJW adding suport for begin...end in
+;; forms whereby a single end outdented.
+
+;; Partially fixed failure to recognise if statements with
+;; continuations (still fails on 'single line' if with
+;; continuation, ugh).
+;; 1.4.2 RF added "class" and "null" keywords, "Rhino" script note.
+;; 1.4.3 VB1 added
+;; 1) function visual-basic-if-not-on-single-line to recognize single line
+;; if statements, even when line is broken. variable
+;; visual-basic-allow-single-line-if default set to t again.
+;; 2) use of 'words in calling regexp-opt rather than concat \\< ...\\>
+;; 3) new keywords Preserve and Explicit
+;; 1.4.4 VB1 added function visual-basic-close-block
+;; 1.4.5 VB1, (expand-abbrev) within (save-excusion...)
+;; 1.4.6 VB1 correct visual-basic-close-block (single line If case)
+;; 1.4.7 VB1 correct visual-basic-close-block (For/Next)
+;; 1.4.8 VB1 correct visual-basic-close-block (Property, + add With /End With)
+;; add command visual-basic-insert-item
+
+;; Lennart Borgman:
+;; 2009-11-20
+;; - Added eval-and-compile to visual-basic-label-regexp.
+;;
+;; Notes:
+;; Dave Love
+;; BTW, here's a script for making tags tables that I (Dave Love) have
+;; used with reasonable success. It assumes a hacked version of etags
+;; with support for case-folded regexps. I think this is now in the
+;; development version at <URL:ftp://fly.cnuce.cnr.it/pub/> and should
+;; make it into Emacs after 20.4.
+
+;; #! /bin/sh
+
+;; # etags-vb: (so-called) Visual (so-called) Basic TAGS generation.
+;; # Dave Love <d.love@dl.ac.uk>. Public domain.
+;; # 1997-11-21
+
+;; if [ $# -lt 1 ]; then
+;; echo "Usage: `basename $0` [etags options] VBfile ... [etags options] " 1>&2
+;; exit 1
+;; fi
+
+;; if [ $1 = "--help" ] || [ $1 = "-h" ]; then
+;; echo "Usage: `basename $0` [etags options] VBfile ... [etags options]
+
+;; "
+;; etags --help
+;; fi
+
+;; exec etags --lang=none -c '/\(global\|public\)[ \t]+\(\(const\|type\)[ \t]+\)*\([a-z_0-9]+\)/\4/' \
+;; -c '/public[ \t]+\(sub\|function\|class\)[ \t]+\([a-z_0-9]+\)/\2/' \
+;; "$@"
+
+;; End Notes Dave Love
+
+
+;; Known bugs:
+;; Doesn't know about ":" separated stmts
+
+
+
+;; todo:
+;; fwd/back-compound-statement
+;; completion over OCX methods and properties.
+;; IDE integration
+;; Change behaviour of ESC-q to recognise words used as paragraph
+;; titles and prevent them being dragged into the previous
+;; paragraph.
+;; etc.
+
+
+;;; Code:
+
+(provide 'visual-basic-mode)
+
+(defvar visual-basic-xemacs-p (string-match "XEmacs\\|Lucid" (emacs-version)))
+(defvar visual-basic-winemacs-p (string-match "Win-Emacs" (emacs-version)))
+(defvar visual-basic-win32-p (eq window-system 'w32))
+
+;; Variables you may want to customize.
+(defvar visual-basic-mode-indent 8 "*Default indentation per nesting level.")
+(defvar visual-basic-fontify-p t "*Whether to fontify Basic buffers.")
+(defvar visual-basic-capitalize-keywords-p t
+ "*Whether to capitalize BASIC keywords.")
+(defvar visual-basic-wild-files "*.frm *.bas *.cls"
+ "*Wildcard pattern for BASIC source files.")
+(defvar visual-basic-ide-pathname nil
+ "*The full pathname of your Visual Basic exe file, if any.")
+;; VB
+(defvar visual-basic-allow-single-line-if t
+ "*Whether to allow single line if")
+
+
+(defvar visual-basic-defn-templates
+ (list "Public Sub ()\nEnd Sub\n\n"
+ "Public Function () As Variant\nEnd Function\n\n"
+ "Public Property Get ()\nEnd Property\n\n")
+ "*List of function templates though which visual-basic-new-sub cycles.")
+
+(defvar visual-basic-imenu-generic-expression
+ '((nil "^\\s-*\\(public\\|private\\)*\\s-+\\(declare\\s-+\\)*\\(sub\\|function\\)\\s-+\\(\\sw+\\>\\)"
+ 4)
+ ("Constants"
+ "^\\s-*\\(private\\|public\\|global\\)*\\s-*\\(const\\s-+\\)\\(\\sw+\\>\\s-*=\\s-*.+\\)$\\|'"
+ 3)
+ ("Variables"
+ "^\\(private\\|public\\|global\\|dim\\)+\\s-+\\(\\sw+\\>\\s-+as\\s-+\\sw+\\>\\)"
+ 2)
+ ("Types" "^\\(public\\s-+\\)*type\\s-+\\(\\sw+\\)" 2)))
+
+
+
+(defvar visual-basic-mode-syntax-table nil)
+(if visual-basic-mode-syntax-table
+ ()
+ (setq visual-basic-mode-syntax-table (make-syntax-table))
+ (modify-syntax-entry ?\' "\<" visual-basic-mode-syntax-table) ; Comment starter
+ (modify-syntax-entry ?\n ">" visual-basic-mode-syntax-table)
+ (modify-syntax-entry ?\\ "w" visual-basic-mode-syntax-table)
+ (modify-syntax-entry ?\= "." visual-basic-mode-syntax-table)
+ (modify-syntax-entry ?\< "." visual-basic-mode-syntax-table)
+ (modify-syntax-entry ?\> "." visual-basic-mode-syntax-table)) ; Make =, etc., punctuation so that dynamic abbreviations work properly
+
+
+(defvar visual-basic-mode-map nil)
+(if visual-basic-mode-map
+ ()
+ (setq visual-basic-mode-map (make-sparse-keymap))
+ (define-key visual-basic-mode-map "\t" 'visual-basic-indent-line)
+ (define-key visual-basic-mode-map "\r" 'visual-basic-newline-and-indent)
+ (define-key visual-basic-mode-map "\M-\r" 'visual-basic-insert-item)
+ (define-key visual-basic-mode-map "\C-c\C-j" 'visual-basic-insert-item)
+ (define-key visual-basic-mode-map "\M-\C-a" 'visual-basic-beginning-of-defun)
+ (define-key visual-basic-mode-map "\M-\C-e" 'visual-basic-end-of-defun)
+ (define-key visual-basic-mode-map "\M-\C-h" 'visual-basic-mark-defun)
+ (define-key visual-basic-mode-map "\M-\C-\\" 'visual-basic-indent-region)
+ (define-key visual-basic-mode-map "\M-q" 'visual-basic-fill-or-indent)
+ (define-key visual-basic-mode-map "\M-\C-j" 'visual-basic-split-line)
+ (define-key visual-basic-mode-map "\C-c]" 'visual-basic-close-block)
+ (cond (visual-basic-winemacs-p
+ (define-key visual-basic-mode-map '(control C) 'visual-basic-start-ide))
+ (visual-basic-win32-p
+ (define-key visual-basic-mode-map (read "[?\\S-\\C-c]") 'visual-basic-start-ide)))
+ (if visual-basic-xemacs-p
+ (progn
+ (define-key visual-basic-mode-map "\M-G" 'visual-basic-grep)
+ (define-key visual-basic-mode-map '(meta backspace) 'backward-kill-word)
+ (define-key visual-basic-mode-map '(control meta /) 'visual-basic-new-sub))))
+
+
+;; These abbrevs are valid only in a code context.
+(defvar visual-basic-mode-abbrev-table nil)
+
+(defvar visual-basic-mode-hook ())
+
+
+;; Is there a way to case-fold all regexp matches?
+;; Change KJW Add enum, , change matching from 0 or more to zero or one for public etc.
+(eval-and-compile
+ (defconst visual-basic-defun-start-regexp
+ (concat
+ "^[ \t]*\\([Pp]ublic \\|[Pp]rivate \\|[Ss]tatic\\|[Ff]riend \\)?"
+ "\\([Ss]ub\\|[Ff]unction\\|[Pp]roperty +[GgSsLl]et\\|[Tt]ype\\|[Ee]num\\|[Cc]lass\\)"
+ "[ \t]+\\(\\w+\\)[ \t]*(?")))
+
+
+(defconst visual-basic-defun-end-regexp
+ "^[ \t]*[Ee]nd \\([Ss]ub\\|[Ff]unction\\|[Pp]roperty\\|[Tt]ype\\|[Ee]num\\|[Cc]lass\\)")
+
+(defconst visual-basic-dim-regexp
+ "^[ \t]*\\([Cc]onst\\|[Dd]im\\|[Pp]rivate\\|[Pp]ublic\\)\\_>" )
+
+
+;; Includes the compile-time #if variation.
+;; KJW fixed if to require a whitespace so as to avoid matching, for
+;; instance, iFileName and to require then.
+
+;; Two versions; one recognizes single line if just as though it were
+;; a multi-line and the other does not. Modified again to remove the
+;; requirement for then so as to allow it to match if statements that
+;; have continuations -- VB1 further elaborated on this for single line
+;; if statement to be recognized on broken lines.
+;;(defconst visual-basic-if-regexp
+;; "^[ \t]*#?[Ii]f[ \t]+.*[ \t]+[Tt]hen[ \t]*.*\\('\\|$\\)")
+(defconst visual-basic-if-regexp
+ "^[ \t]*#?[Ii]f[ \t]+.*[ \t_]+")
+
+(defconst visual-basic-ifthen-regexp "^[ \t]*#?[Ii]f.+\\<[Tt]hen\\>\\s-\\S-+")
+
+(defconst visual-basic-else-regexp "^[ \t]*#?[Ee]lse\\([Ii]f\\)?")
+(defconst visual-basic-endif-regexp "[ \t]*#?[Ee]nd[ \t]*[Ii]f")
+
+(defconst visual-basic-looked-at-continuation-regexp "_[ \t]*$")
+
+(defconst visual-basic-continuation-regexp
+ (concat "^.*" visual-basic-looked-at-continuation-regexp))
+
+(eval-and-compile
+ (defconst visual-basic-label-regexp "^[ \t]*[a-zA-Z0-9_]+:$"))
+
+(defconst visual-basic-select-regexp "^[ \t]*[Ss]elect[ \t]+[Cc]ase")
+(defconst visual-basic-case-regexp "^[ \t]*[Cc]ase")
+(defconst visual-basic-select-end-regexp "^[ \t]*[Ee]nd[ \t]+[Ss]elect")
+
+
+(defconst visual-basic-for-regexp "^[ \t]*[Ff]or\\b")
+(defconst visual-basic-next-regexp "^[ \t]*[Nn]ext\\b")
+
+(defconst visual-basic-do-regexp "^[ \t]*[Dd]o\\b")
+(defconst visual-basic-loop-regexp "^[ \t]*[Ll]oop\\b")
+
+(defconst visual-basic-while-regexp "^[ \t]*[Ww]hile\\b")
+(defconst visual-basic-wend-regexp "^[ \t]*[Ww]end\\b")
+
+;; Added KJW Begin..end for forms
+(defconst visual-basic-begin-regexp "^[ \t]*[Bb]egin)?")
+;; This has created a bug. End on its own in code should not outdent.
+;; How can we fix this? They are used in separate Lisp expressions so
+;; add another one.
+(defconst visual-basic-end-begin-regexp "^[ \t]*[Ee]nd")
+
+(defconst visual-basic-with-regexp "^[ \t]*[Ww]ith\\b")
+(defconst visual-basic-end-with-regexp "^[ \t]*[Ee]nd[ \t]+[Ww]ith\\b")
+
+(defconst visual-basic-blank-regexp "^[ \t]*$")
+(defconst visual-basic-comment-regexp "^[ \t]*\\s<.*$")
+
+
+;; This is some approximation of the set of reserved words in Visual Basic.
+(eval-and-compile
+ (defvar visual-basic-all-keywords
+ '("Add" "Aggregate" "And" "App" "AppActivate" "Application" "Array" "As"
+ "Asc" "AscB" "Atn" "Attribute"
+ "Beep" "Begin" "BeginTrans" "Boolean" "ByVal" "ByRef"
+ "CBool" "CByte" "CCur"
+ "CDate" "CDbl" "CInt" "CLng" "CSng" "CStr" "CVErr" "CVar" "Call"
+ "Case" "ChDir" "ChDrive" "Character" "Choose" "Chr" "ChrB" "Class"
+ "ClassModule" "Clipboard" "Close" "Collection" "Column" "Columns"
+ "Command" "CommitTrans" "CompactDatabase" "Component" "Components"
+ "Const" "Container" "Containers" "Cos" "CreateDatabase" "CreateObject"
+ "CurDir" "Currency"
+ "DBEngine" "DDB" "Data" "Database" "Databases"
+ "Date" "DateAdd" "DateDiff" "DatePart" "DateSerial" "DateValue" "Day"
+ "Debug" "Declare" "Deftype" "DeleteSetting" "Dim" "Dir" "Do"
+ "DoEvents" "Domain"
+ "Double" "Dynaset" "EOF" "Each" "Else" "Empty" "End" "EndProperty"
+ "Enum" "Environ" "Erase" "Err" "Error" "Exit" "Exp" "Explicit" "FV" "False" "Field"
+ "Fields" "FileAttr" "FileCopy" "FileDateTime" "FileLen" "Fix" "Font" "For"
+ "Form" "FormTemplate" "Format" "Forms" "FreeFile" "FreeLocks" "Friend"
+ "Function"
+ "Get" "GetAllSettings" "GetAttr" "GetObject" "GetSetting" "Global" "GoSub"
+ "GoTo" "Group" "Groups" "Hex" "Hour" "IIf" "IMEStatus" "IPmt" "IRR"
+ "If" "Implements" "InStr" "Input" "Int" "Integer" "Is" "IsArray" "IsDate"
+ "IsEmpty" "IsError" "IsMissing" "IsNull" "IsNumeric" "IsObject" "Kill"
+ "LBound" "LCase" "LOF" "LSet" "LTrim" "Left" "Len" "Let" "Like" "Line"
+ "Load" "LoadPicture" "LoadResData" "LoadResPicture" "LoadResString" "Loc"
+ "Lock" "Log" "Long" "Loop" "MDIForm" "MIRR" "Me" "MenuItems"
+ "MenuLine" "Mid" "Minute" "MkDir" "Month" "MsgBox" "NPV" "NPer" "Name"
+ "New" "Next" "Not" "Now" "Nothing" "Null" "Object" "Oct" "On" "Open"
+ "OpenDatabase"
+ "Operator" "Option" "Optional"
+ "Or" "PPmt" "PV" "Parameter" "Parameters" "Partition"
+ "Picture" "Pmt" "Preserve" "Print" "Printer" "Printers" "Private"
+ "ProjectTemplate" "Property"
+ "Properties" "Public" "Put" "QBColor" "QueryDef" "QueryDefs"
+ "RSet" "RTrim" "Randomize" "Rate" "ReDim" "Recordset" "Recordsets"
+ "RegisterDatabase" "Relation" "Relations" "Rem" "RepairDatabase"
+ "Reset" "Resume" "Return" "Right" "RmDir" "Rnd" "Rollback" "RowBuffer"
+ "SLN" "SYD" "SavePicture" "SaveSetting" "Screen" "Second" "Seek"
+ "SelBookmarks" "Select" "SelectedComponents" "SendKeys" "Set"
+ "SetAttr" "SetDataAccessOption" "SetDefaultWorkspace" "Sgn" "Shell"
+ "Sin" "Single" "Snapshot" "Space" "Spc" "Sqr" "Static" "Step" "Stop" "Str"
+ "StrComp" "StrConv" "String" "Sub" "SubMenu" "Switch" "Tab" "Table"
+ "TableDef" "TableDefs" "Tan" "Then" "Time" "TimeSerial" "TimeValue"
+ "Timer" "To" "Trim" "True" "Type" "TypeName" "UBound" "UCase" "Unload"
+ "Unlock" "Val" "Variant" "VarType" "Verb" "Weekday" "Wend"
+ "While" "Width" "With" "Workspace" "Workspaces" "Write" "Year")))
+
+(defvar visual-basic-font-lock-keywords-1
+ (eval-when-compile
+ (list
+ ;; Names of functions.
+ (list visual-basic-defun-start-regexp
+ '(1 font-lock-keyword-face nil t)
+ '(2 font-lock-keyword-face nil t)
+ '(3 font-lock-function-name-face))
+
+ ;; Statement labels
+ (cons visual-basic-label-regexp 'font-lock-keyword-face)
+
+ ;; Case values
+ ;; String-valued cases get font-lock-string-face regardless.
+ (list "^[ \t]*case[ \t]+\\([^'\n]+\\)" 1 'font-lock-keyword-face t)
+
+ ;; Any keywords you like.
+ (list (regexp-opt
+ '("Dim" "If" "Then" "Else" "ElseIf" "End If") 'words)
+ 1 'font-lock-keyword-face))))
+
+(defvar visual-basic-font-lock-keywords-2
+ (append visual-basic-font-lock-keywords-1
+ (eval-when-compile
+ `((, (regexp-opt visual-basic-all-keywords 'words)
+ 1 font-lock-keyword-face)))))
+
+(defvar visual-basic-font-lock-keywords visual-basic-font-lock-keywords-1)
+
+
+(put 'visual-basic-mode 'font-lock-keywords 'visual-basic-font-lock-keywords)
+
+;;;###autoload
+(defun visual-basic-mode ()
+ "A mode for editing Microsoft Visual Basic programs.
+Features automatic indentation, font locking, keyword capitalization,
+and some minor convenience functions.
+Commands:
+\\{visual-basic-mode-map}"
+ (interactive)
+ (kill-all-local-variables)
+ (use-local-map visual-basic-mode-map)
+ (setq major-mode 'visual-basic-mode)
+ (setq mode-name "Visual Basic")
+ (set-syntax-table visual-basic-mode-syntax-table)
+
+ ;;; This does not work in multi major modes.
+ ;;(add-hook 'local-write-file-hooks 'visual-basic-untabify)
+
+ (setq local-abbrev-table visual-basic-mode-abbrev-table)
+ (if visual-basic-capitalize-keywords-p
+ (progn
+ (make-local-variable 'pre-abbrev-expand-hook)
+ (add-hook 'pre-abbrev-expand-hook 'visual-basic-pre-abbrev-expand-hook)
+ (abbrev-mode 1)))
+
+ (make-local-variable 'comment-start)
+ (setq comment-start "' ")
+ (make-local-variable 'comment-start-skip)
+ (setq comment-start-skip "'+ *")
+ (make-local-variable 'comment-column)
+ (setq comment-column 40)
+ (make-local-variable 'comment-end)
+ (setq comment-end "")
+
+ (make-local-variable 'indent-line-function)
+ (setq indent-line-function 'visual-basic-indent-line)
+
+ (if visual-basic-fontify-p
+ (visual-basic-enable-font-lock))
+
+ (make-local-variable 'imenu-generic-expression)
+ (setq imenu-generic-expression visual-basic-imenu-generic-expression)
+
+ (set (make-local-variable 'imenu-syntax-alist) `((,(string-to-char "_") . "w")))
+ (set (make-local-variable 'imenu-case-fold-search) t)
+
+ ;;(make-local-variable 'visual-basic-associated-files)
+ ;; doing this here means we need not check to see if it is bound later.
+ (add-hook 'find-file-hooks 'visual-basic-load-associated-files)
+
+ (run-hooks 'visual-basic-mode-hook))
+
+
+(defun visual-basic-enable-font-lock ()
+ ;; Emacs 19.29 requires a window-system else font-lock-mode errs out.
+ (cond ((or visual-basic-xemacs-p window-system)
+
+ ;; In win-emacs this sets font-lock-keywords back to nil!
+ (if visual-basic-winemacs-p
+ (font-lock-mode 1))
+
+ ;; Accomodate emacs 19.29+
+ ;; From: Simon Marshall <Simon.Marshall@esrin.esa.it>
+ (cond ((boundp 'font-lock-defaults)
+ (make-local-variable 'font-lock-defaults)
+ (setq font-lock-defaults
+ `((visual-basic-font-lock-keywords
+ visual-basic-font-lock-keywords-1
+ visual-basic-font-lock-keywords-2)
+ nil t ((,(string-to-char "_") . "w")))))
+ (t
+ (make-local-variable 'font-lock-keywords)
+ (setq font-lock-keywords visual-basic-font-lock-keywords)))
+
+ (if visual-basic-winemacs-p
+ (font-lock-fontify-buffer)
+ (font-lock-mode 1)))))
+
+;; KJW should add some odds and bobs here to cover "end if" one way
+;; could be to create the abbreviations by removing whitespace then we
+;; could put "end if", "end with" and so on in the keyword table
+;; Another idea would be to make it intelligent enough to substitute
+;; the correct end for the construct (with, select, if)
+;; Is this what the abbrev table hook entry is for?
+(defun visual-basic-construct-keyword-abbrev-table ()
+ (if visual-basic-mode-abbrev-table
+ nil
+ (let ((words visual-basic-all-keywords)
+ (word nil)
+ (list nil))
+ (while words
+ (setq word (car words)
+ words (cdr words))
+ (setq list (cons (list (downcase word) word) list)))
+
+ (define-abbrev-table 'visual-basic-mode-abbrev-table list))))
+
+;; Would like to do this at compile-time.
+(visual-basic-construct-keyword-abbrev-table)
+
+
+(defun visual-basic-upgrade-keyword-abbrev-table ()
+ "Use this in case of upgrading visual-basic-mode.el"
+ (interactive)
+
+ (let ((words visual-basic-all-keywords)
+ (word nil)
+ (list nil))
+ (while words
+ (setq word (car words)
+ words (cdr words))
+ (setq list (cons (list (downcase word) word) list)))
+ (define-abbrev-table 'visual-basic-mode-abbrev-table list)))
+
+
+(defun visual-basic-in-code-context-p ()
+ (if (fboundp 'buffer-syntactic-context) ; XEmacs function.
+ (null (buffer-syntactic-context))
+ ;; Attempt to simulate buffer-syntactic-context
+ ;; I don't know how reliable this is.
+ (let* ((beg (save-excursion
+ (beginning-of-line)
+ (point)))
+ (list
+ (parse-partial-sexp beg (point))))
+ (and (null (nth 3 list)) ; inside string.
+ (null (nth 4 list)))))) ; inside comment
+
+
+(defun visual-basic-pre-abbrev-expand-hook ()
+ ;; Allow our abbrevs only in a code context.
+ (setq local-abbrev-table
+ (if (visual-basic-in-code-context-p)
+ visual-basic-mode-abbrev-table)))
+
+
+(defun visual-basic-newline-and-indent (&optional count)
+ "Insert a newline, updating indentation."
+ (interactive)
+ (save-excursion
+ (expand-abbrev)
+ (visual-basic-indent-line))
+ (call-interactively 'newline-and-indent))
+
+(defun visual-basic-beginning-of-defun ()
+ (interactive)
+ (re-search-backward visual-basic-defun-start-regexp))
+
+(defun visual-basic-end-of-defun ()
+ (interactive)
+ (re-search-forward visual-basic-defun-end-regexp))
+
+(defun visual-basic-mark-defun ()
+ (interactive)
+ (beginning-of-line)
+ (visual-basic-end-of-defun)
+ (set-mark (point))
+ (visual-basic-beginning-of-defun)
+ (if visual-basic-xemacs-p
+ (zmacs-activate-region)))
+
+(defun visual-basic-indent-defun ()
+ (interactive)
+ (save-excursion
+ (visual-basic-mark-defun)
+ (call-interactively 'visual-basic-indent-region)))
+
+
+(defun visual-basic-fill-long-comment ()
+ "Fills block of comment lines around point."
+ ;; Derived from code in ilisp-ext.el.
+ (interactive)
+ (save-excursion
+ (beginning-of-line)
+ (let ((comment-re "^[ \t]*\\s<+[ \t]*"))
+ (if (looking-at comment-re)
+ (let ((fill-prefix
+ (buffer-substring
+ (progn (beginning-of-line) (point))
+ (match-end 0))))
+
+ (while (and (not (bobp))
+ (looking-at visual-basic-comment-regexp))
+ (forward-line -1))
+ (if (not (bobp)) (forward-line 1))
+
+ (let ((start (point)))
+
+ ;; Make all the line prefixes the same.
+ (while (and (not (eobp))
+ (looking-at comment-re))
+ (replace-match fill-prefix)
+ (forward-line 1))
+
+ (if (not (eobp))
+ (beginning-of-line))
+
+ ;; Fill using fill-prefix
+ (fill-region-as-paragraph start (point))))))))
+
+
+(defun visual-basic-fill-or-indent ()
+ "Fill long comment around point, if any, else indent current definition."
+ (interactive)
+ (cond ((save-excursion
+ (beginning-of-line)
+ (looking-at visual-basic-comment-regexp))
+ (visual-basic-fill-long-comment))
+ (t
+ (visual-basic-indent-defun))))
+
+
+(defun visual-basic-new-sub ()
+ "Insert template for a new subroutine. Repeat to cycle through alternatives."
+ (interactive)
+ (beginning-of-line)
+ (let ((templates (cons visual-basic-blank-regexp
+ visual-basic-defn-templates))
+ (tem nil)
+ (bound (point)))
+ (while templates
+ (setq tem (car templates)
+ templates (cdr templates))
+ (cond ((looking-at tem)
+ (replace-match (or (car templates)
+ ""))
+ (setq templates nil))))
+
+ (search-backward "()" bound t)))
+
+
+;; (defun visual-basic-untabify ()
+;; "Do not allow any tabs into the file."
+;; (if (eq major-mode 'visual-basic-mode)
+;; (untabify (point-min) (point-max)))
+;; nil)
+
+(defun visual-basic-default-tag ()
+ (if (and (not (bobp))
+ (save-excursion
+ (backward-sexp)
+ (looking-at "\\w")))
+ (backward-word 1))
+ (let ((s (point))
+ (e (save-excursion
+ (forward-sexp)
+ (point))))
+ (buffer-substring s e)))
+
+(defun visual-basic-grep (tag)
+ "Search BASIC source files in current directory for TAG."
+ (interactive
+ (list (let* ((def (visual-basic-default-tag))
+ (tag (read-string
+ (format "Grep for [%s]: " def))))
+ (if (string= tag "") def tag))))
+ (grep (format "grep -n %s %s" tag visual-basic-wild-files)))
+
+
+;;; IDE Connection.
+
+(defun visual-basic-buffer-project-file ()
+ "Return a guess as to the project file associated with the current buffer."
+ (car (directory-files (file-name-directory (buffer-file-name)) t "\\.vbp")))
+
+(defun visual-basic-start-ide ()
+ "Start Visual Basic (or your favorite IDE, (after Emacs, of course))
+on the first project file in the current directory.
+Note: it's not a good idea to leave Visual Basic running while you
+are editing in Emacs, since Visual Basic has no provision for reloading
+changed files."
+ (interactive)
+ (let (file)
+ (cond ((null visual-basic-ide-pathname)
+ (error "No pathname set for Visual Basic. See visual-basic-ide-pathname"))
+ ((null (setq file (visual-basic-buffer-project-file)))
+ (error "No project file found"))
+ ((fboundp 'win-exec)
+ (iconify-emacs)
+ (win-exec visual-basic-ide-pathname 'win-show-normal file))
+ ((fboundp 'start-process)
+ (iconify-frame (selected-frame))
+ (start-process "*VisualBasic*" nil visual-basic-ide-pathname file))
+ (t
+ (error "No way to spawn process!")))))
+
+
+
+;;; Indentation-related stuff.
+
+(defun visual-basic-indent-region (start end)
+ "Perform visual-basic-indent-line on each line in region."
+ (interactive "r")
+ (save-excursion
+ (goto-char start)
+ (beginning-of-line)
+ (while (and (not (eobp))
+ (< (point) end))
+ (if (not (looking-at visual-basic-blank-regexp))
+ (visual-basic-indent-line))
+ (forward-line 1)))
+
+ (cond ((fboundp 'zmacs-deactivate-region)
+ (zmacs-deactivate-region))
+ ((fboundp 'deactivate-mark)
+ (deactivate-mark))))
+
+
+
+(defun visual-basic-previous-line-of-code ()
+ (if (not (bobp))
+ (forward-line -1)) ; previous-line depends on goal column
+ (while (and (not (bobp))
+ (or (looking-at visual-basic-blank-regexp)
+ (looking-at visual-basic-comment-regexp)))
+ (forward-line -1)))
+
+
+(defun visual-basic-find-original-statement ()
+ "If the current line is a continuation, move back to the original stmt."
+ (let ((here (point)))
+ (visual-basic-previous-line-of-code)
+ (while (and (not (bobp))
+ (looking-at visual-basic-continuation-regexp))
+ (setq here (point))
+ (visual-basic-previous-line-of-code))
+ (goto-char here)))
+
+(defun visual-find-matching-stmt (open-p close-p)
+ ;; Searching backwards
+ (let ((level 0))
+ (while (and (>= level 0) (not (bobp)))
+ (visual-basic-previous-line-of-code)
+ (visual-basic-find-original-statement)
+ (cond ((funcall close-p)
+ (setq level (+ level 1)))
+ ((funcall open-p)
+ (setq level (- level 1)))))))
+
+(defun visual-basic-find-matching-stmt (open-regexp close-regexp)
+ (visual-find-matching-stmt
+ (lambda () (looking-at open-regexp))
+ (lambda () (looking-at close-regexp))))
+
+(defun visual-basic-get-complete-tail-of-line ()
+ "Return the tail of the current statement line, starting at
+ point and going up to end of statement line. If you want the
+ complete statement line, you have to call functions
+ `visual-basic-find-original-statement' and then
+ `beginning-of-line' before"
+ (let* ((start-point (point))
+ complete-line
+ (line-beg start-point)
+ line-end)
+ (while (null line-end)
+ (end-of-line)
+ (setq line-end (point))
+ (if (search-backward "_" line-beg t)
+ (if (looking-at visual-basic-looked-at-continuation-regexp)
+ ;; folded line
+ (progn
+ (setq line-end (1- (point))
+ complete-line (cons
+ (buffer-substring-no-properties
+ line-beg line-end)
+ complete-line)
+ line-end nil)
+ (beginning-of-line 2)
+ (setq line-beg (point)))
+ ;; _ found, but not a folded line (this is a syntax error)
+ (setq complete-line
+ (cons (buffer-substring-no-properties line-beg line-end) complete-line)))
+ ;; not a folded line
+ (setq complete-line
+ (cons (buffer-substring-no-properties line-beg line-end)
+ complete-line))))
+ (mapconcat 'identity (nreverse complete-line) " ")))
+
+(defun visual-basic-if-not-on-single-line ()
+ "Return non-`nil' when the If statement is not on a single statement
+line, i.e. requires a matching End if. Note that a statement line may
+be folded over several code lines."
+ (if (looking-at visual-basic-if-regexp)
+ (save-excursion
+ (beginning-of-line)
+ (let (p1
+ p2
+ ;; 1st reconstruct complete line
+ (complete-line (visual-basic-get-complete-tail-of-line)) )
+
+ ;; now complete line has been reconstructed, drop confusing elements
+
+ ;; remove any VB string from complete line, as strings may disrupt : and ' detection
+ (while (and (setq p1 (string-match "\"" complete-line))
+ (setq p2 (string-match "\"" complete-line (1+ p1))))
+ (setq complete-line (concat (substring complete-line 0 p1)
+ (substring complete-line (1+ p2)))))
+ ;; now drop tailing comment if any
+ (when (setq p1 (string-match "'" complete-line))
+ (setq complete-line (substring complete-line p1)))
+ ;; now drop 1st concatenated instruction is any
+ (when (setq p1 (string-match ":" complete-line))
+ (setq complete-line (substring complete-line p1)))
+ ;;
+ (string-match "Then\\s-*$" complete-line))); end (save-excursion ...)
+ ;; else, not a basic if
+ nil))
+
+(defun visual-basic-find-matching-if ()
+ (visual-find-matching-stmt 'visual-basic-if-not-on-single-line
+ (lambda () (looking-at visual-basic-endif-regexp))))
+
+(defun visual-basic-find-matching-select ()
+ (visual-basic-find-matching-stmt visual-basic-select-regexp
+ visual-basic-select-end-regexp))
+
+(defun visual-basic-find-matching-for ()
+ (visual-basic-find-matching-stmt visual-basic-for-regexp
+ visual-basic-next-regexp))
+
+(defun visual-basic-find-matching-do ()
+ (visual-basic-find-matching-stmt visual-basic-do-regexp
+ visual-basic-loop-regexp))
+
+(defun visual-basic-find-matching-while ()
+ (visual-basic-find-matching-stmt visual-basic-while-regexp
+ visual-basic-wend-regexp))
+
+(defun visual-basic-find-matching-with ()
+ (visual-basic-find-matching-stmt visual-basic-with-regexp
+ visual-basic-end-with-regexp))
+
+;;; If this fails it must return the indent of the line preceding the
+;;; end not the first line because end without matching begin is a
+;;; normal simple statement
+(defun visual-basic-find-matching-begin ()
+ (let ((original-point (point)))
+ (visual-basic-find-matching-stmt visual-basic-begin-regexp
+ visual-basic-end-begin-regexp)
+ (if (bobp) ;failed to find a matching begin so assume that it is
+ ;an end statement instead and use the indent of the
+ ;preceding line.
+ (progn (goto-char original-point)
+ (visual-basic-previous-line-of-code)))))
+
+
+(defun visual-basic-calculate-indent ()
+ (let ((original-point (point)))
+ (save-excursion
+ (beginning-of-line)
+ ;; Some cases depend only on where we are now.
+ (cond ((or (looking-at visual-basic-defun-start-regexp)
+ (looking-at visual-basic-label-regexp)
+ (looking-at visual-basic-defun-end-regexp))
+ 0)
+
+ ;; The outdenting stmts, which simply match their original.
+ ((or (looking-at visual-basic-else-regexp)
+ (looking-at visual-basic-endif-regexp))
+ (visual-basic-find-matching-if)
+ (current-indentation))
+
+ ;; All the other matching pairs act alike.
+ ((looking-at visual-basic-next-regexp) ; for/next
+ (visual-basic-find-matching-for)
+ (current-indentation))
+
+ ((looking-at visual-basic-loop-regexp) ; do/loop
+ (visual-basic-find-matching-do)
+ (current-indentation))
+
+ ((looking-at visual-basic-wend-regexp) ; while/wend
+ (visual-basic-find-matching-while)
+ (current-indentation))
+
+ ((looking-at visual-basic-end-with-regexp) ; with/end with
+ (visual-basic-find-matching-with)
+ (current-indentation))
+
+ ((looking-at visual-basic-select-end-regexp) ; select case/end select
+ (visual-basic-find-matching-select)
+ (current-indentation))
+
+ ;; A case of a select is somewhat special.
+ ((looking-at visual-basic-case-regexp)
+ (visual-basic-find-matching-select)
+ (+ (current-indentation) visual-basic-mode-indent))
+
+ ;; Added KJW: Make sure that this comes after the cases
+ ;; for if..endif, end select because end-regexp will also
+ ;; match "end select" etc.
+ ((looking-at visual-basic-end-begin-regexp) ; begin/end
+ (visual-basic-find-matching-begin)
+ (current-indentation))
+
+ (t
+ ;; Other cases which depend on the previous line.
+ (visual-basic-previous-line-of-code)
+
+ ;; Skip over label lines, which always have 0 indent.
+ (while (looking-at visual-basic-label-regexp)
+ (visual-basic-previous-line-of-code))
+
+ (cond
+ ((looking-at visual-basic-continuation-regexp)
+ (visual-basic-find-original-statement)
+ ;; Indent continuation line under matching open paren,
+ ;; or else one word in.
+ (let* ((orig-stmt (point))
+ (matching-open-paren
+ (condition-case ()
+ (save-excursion
+ (goto-char original-point)
+ (beginning-of-line)
+ (backward-up-list 1)
+ ;; Only if point is now w/in cont. block.
+ (if (<= orig-stmt (point))
+ (current-column)))
+ (error nil))))
+ (cond (matching-open-paren
+ (1+ matching-open-paren))
+ (t
+ ;; Else, after first word on original line.
+ (back-to-indentation)
+ (forward-word 1)
+ (while (looking-at "[ \t]")
+ (forward-char 1))
+ (current-column)))))
+ (t
+ (visual-basic-find-original-statement)
+
+ (let ((indent (current-indentation)))
+ ;; All the various +indent regexps.
+ (cond ((looking-at visual-basic-defun-start-regexp)
+ (+ indent visual-basic-mode-indent))
+
+ ((or (visual-basic-if-not-on-single-line)
+ (and (looking-at visual-basic-else-regexp)
+ (not (and visual-basic-allow-single-line-if
+ (looking-at visual-basic-ifthen-regexp)))))
+ (+ indent visual-basic-mode-indent))
+
+ ((or (looking-at visual-basic-select-regexp)
+ (looking-at visual-basic-case-regexp))
+ (+ indent visual-basic-mode-indent))
+
+ ((or (looking-at visual-basic-do-regexp)
+ (looking-at visual-basic-for-regexp)
+ (looking-at visual-basic-while-regexp)
+ (looking-at visual-basic-with-regexp)
+ (looking-at visual-basic-begin-regexp))
+ (+ indent visual-basic-mode-indent))
+
+ (t
+ ;; By default, just copy indent from prev line.
+ indent))))))))))
+
+(defun visual-basic-indent-to-column (col)
+ (let* ((bol (save-excursion
+ (beginning-of-line)
+ (point)))
+ (point-in-whitespace
+ (<= (point) (+ bol (current-indentation))))
+ (blank-line-p
+ (save-excursion
+ (beginning-of-line)
+ (looking-at visual-basic-blank-regexp))))
+
+ (cond ((/= col (current-indentation))
+ (save-excursion
+ (beginning-of-line)
+ (back-to-indentation)
+ (delete-region bol (point))
+ (indent-to col))))
+
+ ;; If point was in the whitespace, move back-to-indentation.
+ (cond (blank-line-p
+ (end-of-line))
+ (point-in-whitespace
+ (back-to-indentation)))))
+
+
+(defun visual-basic-indent-line ()
+ "Indent current line for BASIC."
+ (interactive)
+ (visual-basic-indent-to-column (visual-basic-calculate-indent)))
+
+
+(defun visual-basic-split-line ()
+ "Split line at point, adding continuation character or continuing a comment.
+In Abbrev mode, any abbrev before point will be expanded."
+ (interactive)
+ (let ((pps-list (parse-partial-sexp (save-excursion
+ (beginning-of-line)
+ (point))
+ (point))))
+ ;; Dispatch on syntax at this position.
+ (cond ((equal t (nth 4 pps-list)) ; in comment
+ (indent-new-comment-line))
+ ((equal t (nth 4 pps-list)) ; in string
+ (error "Can't break line inside a string"))
+ (t (just-one-space) ; leading space on next line
+ ; doesn't count, sigh
+ (insert "_")
+ (visual-basic-newline-and-indent)))))
+
+(defun visual-basic-detect-idom ()
+ "Detects whether this is a VBA or VBS script. Returns symbol
+ `vba' if it is VBA, `nil' otherwise"
+ (let (ret)
+ (save-excursion
+ (save-restriction
+ (widen)
+ (goto-char (point-min))
+ (cond
+ ((looking-at "^[ \t]*Attribute\\s-+VB_Name\\s-+= ") (setq ret 'vba)))
+ ))
+ ret))
+
+(defun visual-basic-close-block ()
+ "Insert `End If' is current block is a `If Then ...', `End
+With' if the block is a `With ...', etc..."
+ (interactive)
+ (let (end-statement end-indent)
+ (save-excursion
+ (save-match-data
+ (while
+ (unless (bobp)
+ (visual-basic-previous-line-of-code)
+ (visual-basic-find-original-statement)
+ (cond
+ ;; Cases where the current statement is a start-of-smthing statement
+ ((looking-at visual-basic-defun-start-regexp)
+ (let ((smt (match-string 2)))
+ (when (string-match "\\`Prop" smt)
+ (setq smt "Property"))
+ (setq end-statement (concat "End " smt)
+ end-indent 0))
+ nil)
+ ((looking-at visual-basic-select-regexp)
+ (setq end-statement "End Select"
+ end-indent (current-indentation))
+ nil)
+ ((looking-at visual-basic-with-regexp)
+ (setq end-statement "End With"
+ end-indent (current-indentation))
+ nil)
+ ((looking-at visual-basic-case-regexp)
+ (setq end-statement "End Select"
+ end-indent (max 0 (- (current-indentation) visual-basic-mode-indent)))
+ nil)
+ ((looking-at visual-basic-begin-regexp)
+ (setq end-statement "End"
+ end-indent (current-indentation))
+ nil)
+ ((or (visual-basic-if-not-on-single-line)
+ (looking-at visual-basic-else-regexp))
+ (setq end-statement "End If"
+ end-indent (current-indentation))
+ nil)
+
+ ((looking-at visual-basic-do-regexp)
+ (setq end-statement "Loop"
+ end-indent (current-indentation))
+ nil)
+
+ ((looking-at visual-basic-for-regexp)
+ (goto-char (match-end 0))
+ (setq end-statement "Next"
+ end-indent (current-indentation))
+ (let ((vb-idom (visual-basic-detect-idom)))
+ (cond
+ ;; for VBA add the variable name after Next.
+ ((eq vb-idom 'vba)
+ (when (looking-at "\\s-+\\(Each\\s-+\\|\\)\\([^ \t\n\r]+\\)")
+ (setq end-statement (concat end-statement " " (match-string 2)))))))
+ nil)
+ ;; Cases where the current statement is an end-of-smthing statement
+ ((or (looking-at visual-basic-else-regexp)
+ (looking-at visual-basic-endif-regexp))
+ (visual-basic-find-matching-if)
+ t)
+ ((looking-at visual-basic-next-regexp) ; for/next
+ (visual-basic-find-matching-for)
+ t)
+ ((looking-at visual-basic-loop-regexp) ; do/loop
+ (visual-basic-find-matching-do)
+ t)
+ ((looking-at visual-basic-wend-regexp) ; while/wend
+ (visual-basic-find-matching-while)
+ t)
+ ((looking-at visual-basic-end-with-regexp) ; with/end with
+ (visual-basic-find-matching-with)
+ t)
+ ((looking-at visual-basic-select-end-regexp) ; select case/end select
+ (visual-basic-find-matching-select)
+ t)
+
+
+ ;; default is to loop again back to previous line of code.
+ (t t))))))
+ (when end-statement
+ (insert end-statement)
+ (visual-basic-indent-to-column end-indent))))
+
+(defvar delta-split-to-cur-point) ;; Don't know what it is, just silence compiler
+
+(defun visual-basic-insert-item ()
+ "Insert a new item in a block.
+
+This function is under developement, and for the time being only Dim items are handled.
+
+Interting an item means:
+
+* Add a `Case' or `Case Else' into a `Select ... End Select'
+ block. Pressing again toggles between `Case' and `Case
+ Else'. `Case Else' is possible only if there is not already a `Case Else'.
+
+* split a Dim declaration over several lines.
+
+* Add an `Else' or `ElseIf ... Then' into an `If ... Then ... End
+ If' block. Pressing again toggles between `Else' and `ElseIf
+ ... Then'. `Else' is possible only if therei s not already an
+ `Else'.
+"
+ (interactive)
+ ;; possible cases are
+ ;; dim-split-before => split before variable name
+ ;; dim-split-after => split after type name if any
+ ;; if-with-else
+ ;; if-without-else
+ ;; select-with-else
+ ;; select-without-else
+ ;; not-itemizable
+ (let (item-case
+ item-ident
+ split-point
+ cur-point-mark
+ prefix
+ tentative-split-point
+ block-stack (cur-point (point)) previous-line-of-code)
+ (save-excursion
+ (save-match-data
+ (beginning-of-line)
+ (while
+ (progn
+ (visual-basic-find-original-statement)
+ (cond
+ ;; dim case
+ ;;--------------------------------------------------------------
+ ((and (null previous-line-of-code)
+ (looking-at visual-basic-dim-regexp)
+ (null (save-match-data (looking-at visual-basic-defun-start-regexp))))
+ (setq prefix (buffer-substring-no-properties
+ (point)
+ (goto-char (setq split-point (match-end 0)))))
+ (while
+ (progn
+ (if
+ (looking-at "\\s-*\\sw+\\s-*")
+ (progn
+ (goto-char (setq tentative-split-point (match-end 0)))
+ (if (>= tentative-split-point cur-point)
+ nil
+ (while (or
+ (looking-at "([^)\n]+)\\s-*")
+ (looking-at visual-basic-looked-at-continuation-regexp))
+ (goto-char (setq tentative-split-point (match-end 0))))
+ (when (looking-at "As\\s-+\\sw+\\s-*")
+ (goto-char (setq tentative-split-point (match-end 0))))
+ (when (looking-at visual-basic-looked-at-continuation-regexp)
+ (beginning-of-line 2))
+ (if (looking-at ",")
+ (goto-char (setq split-point (match-end 0)))
+ (setq split-point (point))
+ nil)))
+ nil)))
+ (goto-char split-point)
+ (setq item-case (if (<= split-point cur-point) 'dim-split-before 'dim-split-after))
+ (setq delta-split-to-cur-point (- split-point cur-point))
+ (setq cur-point-mark (make-marker))
+ (set-marker cur-point-mark cur-point)
+ (looking-at "\\s-*")
+ (setq delta-split-to-cur-point (- delta-split-to-cur-point
+ (- (match-end 0) (match-beginning 0))))
+ (delete-region (point) (match-end 0))
+ (when (looking-back ",")
+ (delete-region split-point (1- split-point)))
+ (insert "\n" prefix " ")
+ (setq cur-point (marker-position cur-point-mark))
+ (set-marker cur-point-mark nil)
+ nil)
+ ;; next
+ ((looking-at visual-basic-next-regexp)
+ (push (list 'next) block-stack))
+ ;; default
+ ;;--------------------------------------------------------------
+ (t (if (bobp)
+ (setq item-case 'not-itemizable)))
+ )
+ (when (null item-case)
+ (visual-basic-previous-line-of-code)
+ (setq previous-line-of-code t))
+ (null item-case)))))
+ (cond
+ ((eq item-case 'dim-split-after)
+ (goto-char cur-point))
+ )
+ ))
+
+;;; Some experimental functions
+
+;;; Load associated files listed in the file local variables block
+(defun visual-basic-load-associated-files ()
+ "Load files that are useful to have around when editing the source of the file that has just been loaded.
+The file must have a local variable that lists the files to be loaded.
+If the file name is relative it is relative to the directory
+containing the current buffer. If the file is already loaded nothing
+happens, this prevents circular references causing trouble. After an
+associated file is loaded its associated files list will be
+processed."
+ (if (boundp 'visual-basic-associated-files)
+ (let ((files visual-basic-associated-files)
+ (file nil))
+ (while files
+ (setq file (car files)
+ files (cdr files))
+ (message "Load associated file: %s" file)
+ (visual-basic-load-file-ifnotloaded file default-directory)))))
+
+
+
+(defun visual-basic-load-file-ifnotloaded (file default-directory)
+ "Load file if not already loaded.
+If file is relative then default-directory provides the path"
+ (let((file-absolute (expand-file-name file default-directory)))
+ (if (get-file-buffer file-absolute); don't do anything if the buffer is already loaded
+ ()
+ (find-file-noselect file-absolute ))))
+
+
+
+;;; visual-basic-mode.el ends here
+
+
+;External Links
+;* [http://visualbasic.freetutes.com/ Visual Basic tutorials]
+