Difference between revision 9 and revision 10

Summary: Upload a new version of the mode -- this time, without doing that wierd "file" thing to the page.

No diff available.


;;; basic.el --- major mode for editing basic and visual basic code
;;; Copyright (C) 2002 Agnar Renolen <>
;;; Copyright (C) 2009 Samuel Bronson <>

;; basic.el is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2 of the License, or
;; (at your option) any later version.

;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with this program; if not, write to the Free Software
;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

;; Version: 1.1
;; Last-Updated: Sat Apr 18 15:27:37 2009 (-0400)
;; By: Samuel Bronson

;;; Commentary:

;; An editing mode for basic code.  It knows a lot about visual basic and
;; tries to provide proper indentation and syntax highlighting.  This
;; version is fairly crude.  It provides syntax highlighting and
;; indentation.
;;  I would very much like to automatically append a "_" at the end of a
;;  line that gets overflown in auto-fill-mode.  I'll leave that to a
;;  later version.
;;  I would also like to append the proper block end when the user
;;  presses enter at a block beginning.  For example, if the
;;  user typed a "for" statement, the ending "next" statement would be
;;  automatically added when the user pressed enter.

;;; Change Log:
;; 2009-04-18:  Samuel Bronson (1.0)
;;      * Switch to `font-lock-syntactic-keywords' for handling of REM
;;        comments, so that other keywords on a comment line won't
;;        prevent the comment from being recognized
;;      * Explicitly create the syntax table for `basic-mode'
;;      * Use `define-derived-mode' to define the `basic-mode'
;;        command, shortening it considerably
;;      * Fix `checkdoc' warnings
;;      * Other small changes
;; 2002-08-20:  Agnar Renolen (1.1)
;;      * Wrote `basic-mode'

;;; Code:

(defgroup basic nil
  "Major mode for editing basic code"
  :prefix "basic-"
  :group 'languages)

(defcustom basic-mode-hook nil
  "Hook called when `basic-mode' fires up."
  :type 'hook
  :group 'basic)

(defvar basic-mode-map nil
  "Keymap used with basic code.")

(defcustom basic-indent-level 4
  "Amount by which basic subexpressions are indented."
  :type 'integer
  :group 'basic)

(defvar basic-font-lock-keywords
     ;; function name declarations.
     '("\\<\\(sub\\|function\\)\\>[ \t]*\\(\\sw+\\)?"
       (1 font-lock-keyword-face) (2 font-lock-function-name-face nil t))
     ;; variable name declaration.
     '("\\<\\(dim\\|byref\\|byval\\)\\>[ \t]*\\(\\sw+\\)?"
       (1 font-lock-keyword-face) (2 font-lock-variable-name-face nil t))
     ;; keywords.
     (concat "\\<\\(a\\(ddressof\\|nd\\|s\\|ttribute\\)\\|"
     ;; storage specifiers
       . font-lock-keyword-face)
     ;; constants
       . font-lock-constant-face)
     ;; standard types
       . font-lock-type-face)

(defvar basic-mode-syntax-table
  (let ((st (make-syntax-table)))
    (modify-syntax-entry ?\' "<" st)
    (modify-syntax-entry ?\n ">" st)
    (modify-syntax-entry ?\_ "w" st)

(defvar basic-font-lock-syntactic-keywords
  '(("^[ \t]*\\<rem\\>" . (0 "<"))))

(define-derived-mode basic-mode nil "Basic"
  "Major mode for editing basic code."

  (set (make-local-variable 'indent-line-function) 'basic-indent-line)
  (set (make-local-variable 'comment-start) "'")
  (set (make-local-variable 'comment-start-skip) "'[ \t]*")
  (set (make-local-variable 'font-lock-defaults)
         ;; keywords-only: OFF
         ;; case-fold:     ON
         ;; syntax-alist
         ;; syntax-begin - func. move outside syntactic block?
         ;; buffer-local font-lock vars
         (font-lock-syntactic-keywords . basic-font-lock-syntactic-keywords)))
(defun basic-indent-line ()
  "Indent current line as basic script."
  (let ((indent (basic-calculate-indent))
	beg shift-amt
	(old-pos (- (point-max) (point))))
    (setq beg (point))
    (skip-chars-forward " \t")
    (if (looking-at "case\\|e\\(lse\\(\\|if\\)\\|nd\\)\\|loop\\|next\\|wend\\>")
	(setq indent (max (- indent basic-indent-level))))
    (message "prev indent: %d" indent)
    (setq shift-amt (- indent (current-column)))
    (if (not (zerop shift-amt))
	  (delete-region beg (point))
	  (indent-to indent)
	  (if (> (- (point-max) old-pos) (point))
	      (goto-char (- (point-max) old-pos)))))
(defun basic-calculate-indent ()
  "Return appropriate indentation for the current line as basic code."
    (if (bobp)
      (if (re-search-backward "^[ \t]*[^ \t\n\r]" nil t)
	  (if (looking-at (concat "[ \t]*\\(case\\|do\\|for\\|if\\|select"
				  "\\|static\\|declare\\|friend\\)[ \t]+\\)*"
	      (+ (current-indentation) basic-indent-level)
(provide 'basic-mode)
(provide 'basic)
;;; basic.el ends here