summaryrefslogtreecommitdiffstats
path: root/.emacs.d/batch-mode.el
blob: dcc156ae94be19bec7d6bea62d06f761d5c75e97 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
;;; batch-mode.el --- major mode for editing ESRI batch scrips
;;; Copyright (C) 2002, Agnar Renolen <agnar.renolen@emap.no>
;;; Modified (c) 2009, Matthew Fidler <matthew.fidler at gmail.com>
;;; Fixed indents (and labels)

;; batch-mode.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
;; 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 this program; if not, write to the Free Software
;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

;; This is version 1.0 of 21 August 2002.

;;; Comentary:

;; The batch-mode provides syntax hilighting and auto-indentation for
;; DOS batch files (.bat).  and auto-idendation.  

;; Agnar Renolen, <agnar.renolen@emap.no>

;;; Code:

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

; (defvar batch-mode-hook nil
;   "Hooks called when batch mode fires up."
;   :type 'hook
;   :group 'batch)

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

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

(defvar batch-font-lock-keywords
  (eval-when-compile
    (list
     ; since we can't specify batch comments through the syntax table,
     ; we have to specify it here, and override whatever is highlighted
     '( "^[ \t]*rem\\>.*" (0 font-lock-comment-face t))

     ; since the argument to the echo command is a string, we format it
     ; as a string
     '( "\\<echo\\>[ \t]*\\(.*\\)" (1 font-lock-string-face t))

     ; the argument of the goto statement is a label
     '( "\\<goto\\>[ \t]*\\([a-zA-Z0-9_]+\\)" (1
					      font-lock-constant-face))
     
     ; the keywords of batch (which are not built-in commands)
     (concat "\\<\\(cmdextversion\\|"
	     "d\\(efined\\|isableextensions\\|o\\)\\|"
	     "e\\(lse\\|n\\(ableextensions\\|dlocal\\)"
	     "\\|qu\\|rrorlevel\\|xist\\)\\|for\\|"
	     "goto\\|i[fn]\\|n\\(eq\\|ot\\)\\|setlocal\\)\\>")

     ; built-in DOS commands
     (cons (concat "\\<\\(a\\(ssoc\\|t\\(\\|trib\\)\\)\\|break\\|"
		   "c\\(a\\(cls\\|ll\\)\\|d\\|h\\(cp\\|dir\\|k\\("
		   "dsk\\|ntfs\\)\\)\\|ls\\|md\\|o\\(lor\\|mp\\(\\|act\\)"
		   "\\|nvert\\|py\\)\\)\\|d\\(ate\\|el\\|i\\("
		   "r\\|skco\\(mp\\|py\\)\\)\\|oskey\\)\\|"
		   "e\\(cho\\|rase\\|xit\\)\\|"
		   "f\\(c\\|ind\\(\\|str\\)\\|for\\(\\|mot\\)\\|type\\)\\|"
		   "graftabl\\|help\\|label\\|"
		   "m\\(d\\|mkdir\\|o[dvr]e\\)\\|p\\(a\\(th\\|use\\)"
		   "\\|opd\\|r\\(int\\|opmt\\)\\|ushd\\)\\|"
		   "r\\(d\\|e\\(cover\\|n\\(\\|ame\\)\\|place\\)\\|mdir\\)\\|"
		   "s\\(et\\|hift\\|ort\\|tart\\|ubst\\)\\|"
		   "t\\(i\\(me\\|tle\\)\\|ree\\|ype\\)\\|"
		   "v\\(er\\(\\|ify\\)\\|ol\\)\\|xcopy\\)\\>")
	   'font-lock-builtin-face)
     
     ; variables are embeded in percent chars
     '( "%[a-zA-Z0-9_]+%?" . font-lock-variable-name-face)
     ; labels are formatted as constants
     '( ":[a-zA-Z0-9_]+" . font-lock-constant-face)

     ; command line switches are hilighted as type-face
     '( "[-/][a-zA-Z0-9_]+" . font-lock-type-face)

     ; variables set should also be hilighted with variable-name-face
     '( "\\<set\\>[ \t]*\\([a-zA-Z0-9_]+\\)" (1 font-lock-variable-name-face))
    )))
     

;;;###autoload
(defun batch-mode ()
  "Major mode for editing batch scripts."
  (interactive)
  (kill-all-local-variables)
  (setq major-mode 'batch-mode)
  (setq mode-name "Avenue")
  (set (make-local-variable 'indent-line-function) 'batch-indent-line)
  (set (make-local-variable 'comment-start) "rem")
  (set (make-local-variable 'comment-start-skip) "rem[ \t]*")
  (set (make-local-variable 'font-lock-defaults)
       '(batch-font-lock-keywords nil t nil))
  (run-hooks 'batch-mode-hook))
  
(defun batch-indent-line ()
  "Indent current line as batch script"
  (let ((indent (batch-calculate-indent))
	beg shift-amt 
	(old-pos (- (point-max) (point))))
    (beginning-of-line)
    (setq beg (point))
    (skip-chars-forward " \t")
    (if (looking-at ")")
	(setq indent (max (- indent batch-indent-level))))
    (message "prev indent: %d" indent)
    (setq shift-amt (- indent (current-column)))
    (if (not (zerop shift-amt))
	(progn
	  (delete-region beg (point))
	  ; ArcView replaces tabs with single spaces, so we only insert
	  ; spaces to make indentation correct in ArcView.
	  (insert-char ?  indent)
	  (if (> (- (point-max) old-pos) (point))
	      (goto-char (- (point-max) old-pos)))))
    shift-amt))
    
(defun batch-calculate-indent ()
  "Return appropriate indentation for the current line as batch code."
  (save-excursion
    (beginning-of-line)
    (current-indentation)
    (if (bobp)
	0
      (if (re-search-backward "^[ \t]*[^ \t\n\r]" nil t)
	  (if (looking-at "[ \t]*\\()[ \t]*else\\|for\\|if\\)\\>[^(\n]*([^)\n]*")
	      (+ (current-indentation) batch-indent-level)
	    (if (looking-at "[ \t]*[^(]*)[ \t]*")
		(- (current-indentation) batch-indent-level)
	      (current-indentation)))
	0))))

(add-to-list 'auto-mode-alist '("\\.bat\\'" . batch-mode))
  
(provide 'batch-mode)

;;; batch-mode.el ends here