* lisp/progmodes/dos.el: New file.
[bpt/emacs.git] / lisp / progmodes / dos.el
CommitLineData
400a3178
AM
1;;; dos.el --- Major mode for editing Dos scripts
2
3;; Copyright (C) 2003, 2008-2013 Free Software Foundation, Inc.
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;;
25;; Major mode for editing Dos scripts (batch files). Provides syntax
26;; highlighting, a basic template, access to Dos help pages, imenu/outline
27;; navigation, and the ability to run scripts from within Emacs. The syntax
28;; groups for highlighting are:
29;;
30;; Face Example
31;; dos-label-face :LABEL
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;;
42;; See documentation of function `dos-mode'.
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
55(defgroup dos nil
56 "Major mode for editing Dos scripts."
57 :link '(custom-group-link :tag "Font Lock Faces group" font-lock-faces)
58 :group 'languages)
59
60;; 2 User variables
61
62(defface dos-label-face '((t :weight bold))
63 "Font Lock mode face used to highlight Dos labels."
64 :group 'dos)
65
66;; 3 Internal variables
67
68(defvar dos-font-lock-keywords
69 (eval-when-compile
70 (let ((COMMANDS
71 '("assoc" "at" "attrib" "cd" "cls" "color" "copy" "date" "del" "dir"
72 "doskey" "echo" "endlocal" "erase" "fc" "find" "findstr" "format"
73 "ftype" "label" "md" "mkdir" "more" "move" "net" "path" "pause"
74 "popd" "prompt" "pushd" "rd" "ren" "rename" "replace" "rmdir" "set"
75 "setlocal" "shift" "sort" "subst" "time" "title" "tree" "type"
76 "ver" "vol" "xcopy"))
77 (CONTROLFLOW
78 '("call" "cmd" "defined" "do" "else" "equ" "exist" "exit" "for" "geq"
79 "goto" "gtr" "if" "in" "leq" "lss" "neq" "not" "start"))
80 (LINUX
81 '("cat" "cp" "ls" "mv" "rm")))
82 (list
83 '("\\<\\(call\\|goto\\)\\>[ \t]+%?\\([A-Za-z0-9-_\\:.]+\\)%?"
84 (2 font-lock-constant-face t))
85 '("^[ \t]*\\(@?rem\\>\\|::\\).*"
86 (0 font-lock-comment-face t))
87 '("^:[^:].*"
88 . 'dos-label-face)
89 '("\\<\\(defined\\|set\\)\\>[ \t]*\\(\\w+\\)"
90 (2 font-lock-variable-name-face))
91 '("%\\(\\w+\\)%?"
92 (1 font-lock-variable-name-face))
93 '("!\\(\\w+\\)!?" ; delayed-expansion !variable!
94 (1 font-lock-variable-name-face))
95 '("[ =][-/]+\\(\\w+\\)"
96 (1 font-lock-type-face append))
97 (cons (regexp-opt COMMANDS 'words) font-lock-builtin-face)
98 (cons (regexp-opt CONTROLFLOW 'words) font-lock-keyword-face)
99 (cons (regexp-opt LINUX 'words) font-lock-warning-face)))))
100
101(defvar dos-menu
102 '("Dos"
103 ["Run" dos-run :help "Run script"]
104 ["Run with Args" dos-run-args :help "Run script with args"]
105 "--"
106 ["Imenu" imenu :help "Navigate with imenu"]
107 "--"
108 ["Template" dos-template :help "Insert template"]
109 "--"
110 ["Help (Command)" dos-cmd-help :help "Show help page for Dos command"]
111 ["Help (Mode)" dos-mode-help :help "Show help page for Emacs Dos Mode"]))
112
113(defvar dos-mode-map
114 (let ((map (make-sparse-keymap)))
115 (easy-menu-define nil map nil dos-menu)
116 (define-key map [?\C-c ?\C-.] 'dos-mode-help)
117 (define-key map [?\C-c ?\C-/] 'dos-cmd-help)
118 (define-key map [?\C-c ?\C-a] 'dos-run-args)
119 (define-key map [?\C-c ?\C-c] 'dos-run)
120 (define-key map [?\C-c ?\C-t] 'dos-template)
121 (define-key map [?\C-c ?\C-v] 'dos-run)
122 map))
123
124(defvar dos-mode-syntax-table
125 (let ((table (make-syntax-table)))
126 (modify-syntax-entry ?~ "w" table)
127 (modify-syntax-entry ?% "." table)
128 (modify-syntax-entry ?- "w" table)
129 (modify-syntax-entry ?_ "w" table)
130 (modify-syntax-entry ?{ "w" table)
131 (modify-syntax-entry ?} "w" table)
132 (modify-syntax-entry ?\\ "." table)
133 table))
134
135;; 4 User functions
136
137(defun dos-cmd-help (cmd)
138 "Show help for Dos command."
139 (interactive "sHelp: ")
140 (if (string-equal cmd "net")
141 (shell-command "net /?") (shell-command (concat "help " cmd))))
142
143(defun dos-mode-help ()
144 "Show help page for `dos-mode'."
145 (interactive)
146 (describe-function 'dos-mode)
147 (switch-to-buffer "*Help*") (delete-other-windows) (message nil))
148
149(defun dos-run ()
150 "Run Dos script."
151 (interactive)
152 (save-buffer) (shell-command buffer-file-name))
153
154(defun dos-run-args (args)
155 "Run Dos script with ARGS."
156 (interactive "sArgs: ")
157 (shell-command (concat buffer-file-name " " args)))
158
159(defun dos-template ()
160 "Insert minimal Dos template."
161 (interactive)
162 (goto-char (point-min)) (insert "@echo off\nsetlocal\n\n"))
163
164;; 5 Main function
165
166;;;###autoload
167(define-derived-mode dos-mode prog-mode "Dos"
168 "Major mode for editing Dos scripts.\n
169The `dos-mode-help' command shows this page.\n
170Start a new script from `dos-template'. Read help pages for Dos commands with
171`dos-cmd-help'. Navigate between sections using `imenu'. Run script using
172`dos-run' and `dos-run-args'.\n
173\\{dos-mode-map}"
174 (set (make-local-variable 'comment-start) "rem")
175 (set (make-local-variable 'font-lock-defaults)
176 '(dos-font-lock-keywords nil t)) ; case-insensitive keywords
177 (set (make-local-variable 'imenu-generic-expression) '((nil "^:[^:].*" 0)))
178 (set (make-local-variable 'outline-regexp) ":[^:]")
179 (set-syntax-table dos-mode-syntax-table))
180
181(provide 'dos)
182
183;;; dos.el ends here