frameset.el (frameset--jump-to-register): Check that buffer is live (bug#16749).
[bpt/emacs.git] / lisp / progmodes / bat-mode.el
CommitLineData
7679edb1 1;;; bat-mode.el --- Major mode for editing DOS/Windows scripts
400a3178 2
ba318903 3;; Copyright (C) 2003, 2008-2014 Free Software Foundation, Inc.
400a3178
AM
4
5;; Author: Arni Magnusson <arnima@hafro.is>
6;; Keywords: languages
7
8;; This file is part of GNU Emacs.
9
10;; GNU Emacs is free software: you can redistribute it and/or modify
11;; it under the terms of the GNU General Public License as published by
12;; the Free Software Foundation, either version 3 of the License, or
13;; (at your option) any later version.
14
15;; GNU Emacs is distributed in the hope that it will be useful,
16;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18;; GNU General Public License for more details.
19
20;; You should have received a copy of the GNU General Public License
21;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
22
23;;; Commentary:
24;;
7679edb1
SM
25;; Major mode for editing DOS/Windows scripts (batch files). Provides syntax
26;; highlighting, a basic template, access to DOS help pages, imenu/outline
312b1740 27;; navigation, and the ability to run scripts from within Emacs. The syntax
400a3178
AM
28;; groups for highlighting are:
29;;
30;; Face Example
7679edb1 31;; bat-label-face :LABEL
400a3178
AM
32;; font-lock-comment-face rem
33;; font-lock-builtin-face copy
34;; font-lock-keyword-face goto
35;; font-lock-warning-face cp
36;; font-lock-constant-face [call] prog
37;; font-lock-variable-name-face %var%
38;; font-lock-type-face -option
39;;
40;; Usage:
41;;
7679edb1 42;; See documentation of function `bat-mode'.
400a3178
AM
43;;
44;; Separate package `dos-indent' (Matthew Fidler) provides rudimentary
45;; indentation, see http://www.emacswiki.org/emacs/dos-indent.el.
46;;
47;; Acknowledgements:
48;;
49;; Inspired by `batch-mode' (Agnar Renolen) and `cmd-mode' (Tadamegu Furukawa).
50
51;;; Code:
52
53;; 1 Preamble
54
7679edb1 55(defgroup bat-mode nil
cdc1ebb9 56 "Major mode for editing DOS/Windows batch files."
400a3178
AM
57 :link '(custom-group-link :tag "Font Lock Faces group" font-lock-faces)
58 :group 'languages)
59
60;; 2 User variables
61
7679edb1
SM
62(defface bat-label-face '((t :weight bold))
63 "Font Lock mode face used to highlight labels in batch files.")
400a3178
AM
64
65;; 3 Internal variables
66
7679edb1 67(defvar bat-font-lock-keywords
400a3178
AM
68 (eval-when-compile
69 (let ((COMMANDS
70 '("assoc" "at" "attrib" "cd" "cls" "color" "copy" "date" "del" "dir"
71 "doskey" "echo" "endlocal" "erase" "fc" "find" "findstr" "format"
72 "ftype" "label" "md" "mkdir" "more" "move" "net" "path" "pause"
73 "popd" "prompt" "pushd" "rd" "ren" "rename" "replace" "rmdir" "set"
74 "setlocal" "shift" "sort" "subst" "time" "title" "tree" "type"
75 "ver" "vol" "xcopy"))
76 (CONTROLFLOW
77 '("call" "cmd" "defined" "do" "else" "equ" "exist" "exit" "for" "geq"
78 "goto" "gtr" "if" "in" "leq" "lss" "neq" "not" "start"))
cdc1ebb9
EZ
79 (UNIX
80 '("bash" "cat" "cp" "fgrep" "grep" "ls" "sed" "sh" "mv" "rm")))
312b1740 81 `(("\\<_\\(call\\|goto\\)\\_>[ \t]+%?\\([A-Za-z0-9-_\\:.]+\\)%?"
400a3178 82 (2 font-lock-constant-face t))
312b1740 83 ("^:[^:].*"
7679edb1 84 . 'bat-label-face)
312b1740 85 ("\\<_\\(defined\\|set\\)\\_>[ \t]*\\(\\w+\\)"
400a3178 86 (2 font-lock-variable-name-face))
312b1740 87 ("%\\(\\w+\\)%?"
400a3178 88 (1 font-lock-variable-name-face))
312b1740 89 ("!\\(\\w+\\)!?" ; delayed-expansion !variable!
400a3178 90 (1 font-lock-variable-name-face))
312b1740 91 ("[ =][-/]+\\(\\w+\\)"
400a3178 92 (1 font-lock-type-face append))
312b1740
SM
93 (,(concat "\\_<" (regexp-opt COMMANDS) "\\_>") . font-lock-builtin-face)
94 (,(concat "\\_<" (regexp-opt CONTROLFLOW) "\\_>")
95 . font-lock-keyword-face)
cdc1ebb9 96 (,(concat "\\_<" (regexp-opt UNIX) "\\_>")
312b1740 97 . font-lock-warning-face)))))
400a3178 98
7679edb1
SM
99(defvar bat-menu
100 '("Bat"
101 ["Run" bat-run :help "Run script"]
102 ["Run with Args" bat-run-args :help "Run script with args"]
400a3178
AM
103 "--"
104 ["Imenu" imenu :help "Navigate with imenu"]
105 "--"
7679edb1 106 ["Template" bat-template :help "Insert template"]
400a3178 107 "--"
7679edb1 108 ["Help (Command)" bat-cmd-help :help "Show help page for DOS command"]))
400a3178 109
7679edb1 110(defvar bat-mode-map
400a3178 111 (let ((map (make-sparse-keymap)))
7679edb1
SM
112 (easy-menu-define nil map nil bat-menu)
113 (define-key map [?\C-c ?\C-/] 'bat-cmd-help) ;FIXME: Why not C-c C-? ?
114 (define-key map [?\C-c ?\C-a] 'bat-run-args)
115 (define-key map [?\C-c ?\C-c] 'bat-run)
116 (define-key map [?\C-c ?\C-t] 'bat-template)
117 (define-key map [?\C-c ?\C-v] 'bat-run)
400a3178
AM
118 map))
119
7679edb1 120(defvar bat-mode-syntax-table
400a3178 121 (let ((table (make-syntax-table)))
f001e98e 122 (modify-syntax-entry ?\n ">" table)
40f7e0e8 123 (modify-syntax-entry ?\" "\"" table)
312b1740
SM
124 ;; Beware: `w' should not be used for non-alphabetic chars.
125 (modify-syntax-entry ?~ "_" table)
400a3178 126 (modify-syntax-entry ?% "." table)
312b1740
SM
127 (modify-syntax-entry ?- "_" table)
128 (modify-syntax-entry ?_ "_" table)
129 ;; FIXME: { and } can appear in identifiers? Really?
130 (modify-syntax-entry ?{ "_" table)
131 (modify-syntax-entry ?} "_" table)
400a3178
AM
132 (modify-syntax-entry ?\\ "." table)
133 table))
134
f001e98e
SM
135(defconst bat--syntax-propertize
136 (syntax-propertize-rules
137 ("^[ \t]*\\(?:\\(@?r\\)em\\_>\\|\\(?1::\\):\\).*" (1 "<"))))
138
400a3178
AM
139;; 4 User functions
140
7679edb1 141(defun bat-cmd-help (cmd)
cdc1ebb9 142 "Show help for batch file command CMD."
400a3178
AM
143 (interactive "sHelp: ")
144 (if (string-equal cmd "net")
312b1740 145 ;; FIXME: liable to quoting nightmare. Use call-process?
400a3178
AM
146 (shell-command "net /?") (shell-command (concat "help " cmd))))
147
7679edb1 148(defun bat-run ()
cdc1ebb9 149 "Run a batch file."
400a3178 150 (interactive)
312b1740 151 ;; FIXME: liable to quoting nightmare. Use call/start-process?
400a3178
AM
152 (save-buffer) (shell-command buffer-file-name))
153
7679edb1 154(defun bat-run-args (args)
cdc1ebb9 155 "Run a batch file with ARGS."
400a3178 156 (interactive "sArgs: ")
312b1740 157 ;; FIXME: Use `compile'?
400a3178
AM
158 (shell-command (concat buffer-file-name " " args)))
159
7679edb1 160(defun bat-template ()
cdc1ebb9 161 "Insert minimal batch file template."
400a3178
AM
162 (interactive)
163 (goto-char (point-min)) (insert "@echo off\nsetlocal\n\n"))
164
312b1740 165;;;###autoload
7679edb1 166(add-to-list 'auto-mode-alist '("\\.\\(bat\\|cmd\\)\\'" . bat-mode))
312b1740 167
400a3178
AM
168;; 5 Main function
169
170;;;###autoload
7679edb1 171(define-derived-mode bat-mode prog-mode "Bat"
cdc1ebb9 172 "Major mode for editing DOS/Windows batch files.\n
7679edb1
SM
173Start a new script from `bat-template'. Read help pages for DOS commands
174with `bat-cmd-help'. Navigate between sections using `imenu'.
175Run script using `bat-run' and `bat-run-args'.\n
176\\{bat-mode-map}"
312b1740 177 (setq-local comment-start "rem ")
f001e98e 178 (setq-local syntax-propertize-function bat--syntax-propertize)
312b1740 179 (setq-local font-lock-defaults
7679edb1 180 '(bat-font-lock-keywords nil t)) ; case-insensitive keywords
312b1740
SM
181 (setq-local imenu-generic-expression '((nil "^:[^:].*" 0)))
182 (setq-local outline-regexp ":[^:]"))
400a3178 183
7679edb1 184(provide 'bat-mode)
400a3178 185
7679edb1 186;;; bat-mode.el ends here