cmd-modeはMS-DOSのバッチファイル(拡張子が.bat)や、Windows NT コマンドスクリプトファイル(拡張子が.cmd)等を編集する為の、Emacsのメジャーモードです。
Revision | 1e3810ca8a0a7246a8bce574ad53167764c4b561 (tree) |
---|---|
Time | 2001-08-28 22:14:43 |
Author | tfuruka1 <tfuruka1> |
Commiter | tfuruka1 |
Initial revision
@@ -0,0 +1,418 @@ | ||
1 | +;; -*- Mode: Emacs-Lisp ; coding: sjis-dos -*- | |
2 | +;; | |
3 | +;; Copyright 2001 by Tadamegu Furukawa.[tfuruka1@nifty.com] | |
4 | +;; | |
5 | +;; MS-DOSのバッチファイル及びWindows NTのコマンドスクリプトを編集する | |
6 | +;; 為のへなちょこモードです。%が沢山あって、何がなんだかわからないバッ | |
7 | +;; チファイルを読み易くする目的で作成したので、基本的にfont-lock以外の | |
8 | +;; 機能は殆どありません。しかもemacs 20.7 "Meadow-1.14 (AWSAKA:62)" で | |
9 | +;; しか試していません(これ以外で使用される事を想定していません)。 | |
10 | +;; | |
11 | +;; .emacsの何処かに以下を追加してください。拡張子がcmd又はbatのファイ | |
12 | +;; ルを開くと自動でcmd-modeになります。 | |
13 | +;; | |
14 | +;; (autoload 'cmd-mode "cmd-mode" "CMD mode." t) | |
15 | +;; (setq auto-mode-alist (append '(("\\.\\(cmd\\|bat\\)$" . cmd-mode)) | |
16 | +;; auto-mode-alist)) | |
17 | +;; | |
18 | +;; | |
19 | +;; $Id: cmd-mode.el,v 1.1 2001/08/28 13:14:43 tfuruka1 Exp $ | |
20 | +;; $Log: cmd-mode.el,v $ | |
21 | +;; Revision 1.1 2001/08/28 13:14:43 tfuruka1 | |
22 | +;; Initial revision | |
23 | +;; | |
24 | + | |
25 | +;; (replace-regexp "[\t ]+$" "") | |
26 | + | |
27 | +(defconst cmd-mode-revision-number "$Revision: 1.1 $" "cmd-modeのRevision") | |
28 | + | |
29 | +;;; *** hook | |
30 | +(defvar cmd-mode-hook nil | |
31 | + "cmd-modeを作成するタイミングで呼ばれる hook です。") | |
32 | +(defvar cmd-help-mode-hook nil | |
33 | + "cmd-help-modeを作成するタイミングで呼ばれる hook です。") | |
34 | + | |
35 | +;;; *** 外部コマンド | |
36 | +(defvar cmd-help-command "help" | |
37 | + "helpコマンドのコマンド名。Windows NT系以外には存在しません。") | |
38 | + | |
39 | +;;; *** buffer関係 | |
40 | +(defvar cmd-temp-buf " *cmd-temp-buf*" "作業用の隠しバッファ") | |
41 | +(defvar cmd-help-buf-base-name "*cmd-help " "ヘルプバッファのベース名") | |
42 | + | |
43 | +;;; *** regexp | |
44 | +(defvar cmd-full-size-space-etc-pattern "\\( +\\)" | |
45 | + "所謂「全角の空白」の正規表現") | |
46 | +(defvar cmd-tab-pattern "\\(\t+\\)" "TAB文字の正規表現") | |
47 | +(defvar cmd-comment-pattern "^[ \t]*\\(@*\\)\\(rem\\)\\([\t ].*$\\|$\\)" | |
48 | + "コメント行の正規表現") | |
49 | +(defvar cmd-variable-pattern | |
50 | + (concat "\\(%\\(" ;最初の文字が% | |
51 | + "\\*\\|" ;%* の場合 | |
52 | + "~[^0-9 \n]+[0-9a-z]\\|" ;~f1 等 | |
53 | + "[^%\n -龠]+%\\|" ;通常の環境変数 | |
54 | + "[0-9a-z]\\b\\|" ;%1 等 | |
55 | + "%[0-9a-z]?" ;%% 等 | |
56 | + "\\)\\)") | |
57 | + "環境変数の展開の正規表現 | |
58 | + | |
59 | +想定しているパターンは以下の通りです。 | |
60 | + | |
61 | +例 意味 | |
62 | +----------- ----------------------- | |
63 | +%* すべての引数を参照する | |
64 | +%~fi, %~dp1 バッチパラメータ(%n)及びFOR変数参照の置換 | |
65 | +%文字列% 通常の環境変数の参照 | |
66 | +%1, %i バッチパラメータ(%n)及びFOR変数参照 | |
67 | +%%, %%1, %%i %そのもの、バッチパラメータ(%n)及びFOR変数参照(バッチ | |
68 | + ファイル内で使用した場合)") | |
69 | +(defvar cmd-const-pattern | |
70 | + "\\(^[ \t]*@\\|nul\\|:eof\\|&&\\||\\|\\^\\|&[12]?\\|[,;]\\)" | |
71 | + "条件付き処理記号等の正規表現") | |
72 | +(defvar cmd-set-pattern | |
73 | + (concat "\\b" | |
74 | + "\\(set\\b\\)\\([ \t]+/a\\)*" | |
75 | + "\\(\\([ \t]+[_A-Za-z-][_A-Za-z0-9-]*\\)*\\)" | |
76 | + "\\(-\\|\\W\\)*") | |
77 | + "SETコマンドの正規表現") | |
78 | +(defvar cmd-label-pattern "^[ \t]*\\(:[:A-Za-z0-9_-]+\\)" | |
79 | + "ラベルの正規表現") | |
80 | +(defvar cmd-redirect-pattern | |
81 | + (concat "\\(" | |
82 | + "[12]?>>?\\|" ;1> 2> 1>> 2>> > >> | |
83 | + "<[12]?" ;<1 <2 < | |
84 | + "\\)") | |
85 | + "リダイレクトの正規表現") | |
86 | +(defvar cmd-option-pattern | |
87 | + (concat "\\b" | |
88 | + (regexp-opt | |
89 | + '( | |
90 | + ;; if | |
91 | + "not" "exist" "defined" "errorlevel" "cmdextversion" | |
92 | + "equ" "neq" "lss" "leq" "gtr" "geq" | |
93 | + ;; for | |
94 | + "eol" "skip" "delims" "tokens" "in" "do") t) "\\b") | |
95 | + "IF文等のオプションの正規表現") | |
96 | +(defvar cmd-command-pattern | |
97 | + (concat "\\b" | |
98 | + (regexp-opt '("assoc" "break" "call" "cd" "chdir" "cls" | |
99 | + "color" "copy" "date" "del" "dir" "echo" | |
100 | + "echo." "endlocal" "erase" "exit" "for" | |
101 | + "ftype" "goto" "if" "md" "mkdir" "move" "path" | |
102 | + "pause" "popd" "prompt" "pushd" "rd" "ren" | |
103 | + "rename" "rmdir" "setlocal" "shift" "start" | |
104 | + "time" "title" "type" "ver" "verify" "vol" ) | |
105 | + t) "\\b") | |
106 | + "コマンドの正規表現 | |
107 | + | |
108 | +コマンドは内部コマンドのみです。Windows NTのHELPコマンドで一覧表示され | |
109 | +るコマンドから、外部コマンド(*.exe, *.com)を除いたものです。但し、SET | |
110 | +と REM は他で定義していますので、ここでは除いています。また、ECHO は | |
111 | +ECHO. も含めています") | |
112 | + | |
113 | +;; font-lockの設定 | |
114 | +(defvar cmd-font-lock-keywords | |
115 | + (list | |
116 | + ;; コメント | |
117 | + (list cmd-comment-pattern | |
118 | + '(1 font-lock-constant-face) ;行頭の@ | |
119 | + '(2 font-lock-keyword-face) ;rem | |
120 | + '(3 font-lock-comment-face) ;コメント文字 | |
121 | + ) | |
122 | + ;; ラベル | |
123 | + (list cmd-label-pattern | |
124 | + '(1 (cons font-lock-function-name-face '(underline)))) | |
125 | + ;; リダイレクト記号 | |
126 | + (list cmd-redirect-pattern 1 font-lock-warning-face) | |
127 | + ;; 環境変数の参照 | |
128 | + (list cmd-variable-pattern 1 font-lock-variable-name-face) | |
129 | + ;; 内部コマンド | |
130 | + (list cmd-command-pattern 1 font-lock-keyword-face) | |
131 | + ;; SET | |
132 | + (list cmd-set-pattern | |
133 | + '(1 font-lock-keyword-face) ;SET | |
134 | + '(3 font-lock-type-face) ;環境変数名 | |
135 | + ) | |
136 | + ;;条件付き処理記号等 | |
137 | + (list cmd-const-pattern 1 font-lock-constant-face) | |
138 | + ;; IF文とFOR文のオプション等 | |
139 | + (list cmd-option-pattern 1 font-lock-builtin-face) | |
140 | + ;; 全角スペース | |
141 | + (list cmd-full-size-space-etc-pattern '(1 '(underline))) | |
142 | + ;; TAB文字 | |
143 | + (list cmd-tab-pattern '(1 '(highlight))) | |
144 | + ) | |
145 | + "cmd-mode, cmd-help-modeで使用するfont-lockの設定です。 | |
146 | +詳細はfont-lock-defaultsを参照してください。") | |
147 | + | |
148 | +(defun cmd-mode-version () | |
149 | + "cmd-modeのVersion表示" | |
150 | + (interactive) | |
151 | + (message | |
152 | + (concat "cmd-mode " cmd-mode-revision-number))) | |
153 | + | |
154 | +(defun cmd-help (arg) | |
155 | + "helpコマンドを実行して、結果を表示します。 | |
156 | +この関数は、Windows NT系以外では、動作しません。 | |
157 | + | |
158 | +※Windows \\(9[58]\\|Me\\)でも動作するように作ったつもりだったんですが、 | |
159 | +見事に動作しません。 | |
160 | +" | |
161 | + (interactive | |
162 | + (list (let* ((command (current-word)) | |
163 | + (input (read-string | |
164 | + (format "コマンド%s: " | |
165 | + (if (string-equal command "") | |
166 | + "" | |
167 | + (format "(%s)" command)))))) | |
168 | + (if (string-equal input "") | |
169 | + (if (string-equal command "") | |
170 | + "help" | |
171 | + command) | |
172 | + input)))) | |
173 | + | |
174 | + (let* ((case-fold-search t) | |
175 | + (cmd-help-buffer (format "%s%s*" | |
176 | + cmd-help-buf-base-name (downcase arg))) | |
177 | + (comspec (getenv "ComSpec")) | |
178 | + (cmd-help-arg | |
179 | + (cond | |
180 | + ((string-match "cmd\\.exe$" comspec) | |
181 | + (list "\\/c" cmd-help-command | |
182 | + (if (string-equal arg "help") "" arg))) | |
183 | + ((string-match "command\\.com$" comspec) | |
184 | + (if (string-equal arg "help") | |
185 | + (error "コマンドを入力してください") | |
186 | + (list "\\/c" arg "\\/?"))) | |
187 | + (t | |
188 | + (error (concat "WindowsXX以外では動作しません ComSpec=" comspec))))) | |
189 | + ) | |
190 | + (set-buffer (get-buffer-create cmd-help-buffer)) | |
191 | + (setq buffer-read-only nil) | |
192 | + (erase-buffer) | |
193 | + (apply (function call-process) comspec nil t nil cmd-help-arg) | |
194 | + (goto-char (point-min)) | |
195 | + (display-buffer cmd-help-buffer) | |
196 | + (cmd-help-mode) | |
197 | + ) | |
198 | + ) | |
199 | +(defun cmd-help-mode-exit () | |
200 | + "cmd-help-modeを終了します。" | |
201 | + (interactive) | |
202 | + (if (eq major-mode 'cmd-help-mode) | |
203 | + (kill-buffer (current-buffer))) | |
204 | + ) | |
205 | + | |
206 | +(defun cmd-help-mode () | |
207 | + "cmd-helpから呼び出されます。 | |
208 | + | |
209 | +●ヘルプコマンドを実行し、結果を表示します。 | |
210 | + \\[cmd-help] | |
211 | + | |
212 | +●cmd-help-modeを終了します。 | |
213 | + \\[cmd-help-mode-exit] | |
214 | +" | |
215 | + (interactive) | |
216 | + (kill-all-local-variables) | |
217 | + ;;モード名の設定と、モードラインのモード名フィールドの設定 | |
218 | + (setq major-mode 'cmd-help-mode | |
219 | + mode-name "cmd-help" | |
220 | + buffer-auto-save-file-name nil ;自動保存しない | |
221 | + buffer-read-only t ;読み込み専用 | |
222 | + ) | |
223 | + ;; キーマップの設定 | |
224 | + (setq cmd-help-local-map (make-keymap)) | |
225 | + ;; キーの割り当て | |
226 | + (define-key cmd-help-local-map "\C-ch" 'cmd-help) | |
227 | + (define-key cmd-help-local-map "\C-m" 'cmd-help) | |
228 | + (define-key cmd-help-local-map " " 'cmd-help) | |
229 | + (define-key cmd-help-local-map "q" 'cmd-help-mode-exit) | |
230 | + (define-key cmd-help-local-map "Q" 'cmd-help-mode-exit) | |
231 | + (define-key cmd-help-local-map "n" 'next-line) | |
232 | + (define-key cmd-help-local-map "p" 'previous-line) | |
233 | + | |
234 | + (use-local-map cmd-help-local-map) ; ローカルマップの使用宣言 | |
235 | + | |
236 | + ;; お化粧の設定 | |
237 | + (make-local-variable 'font-lock-defaults) | |
238 | + (setq font-lock-defaults | |
239 | + '((cmd-font-lock-keywords) t t)) | |
240 | + (font-lock-mode t) | |
241 | + | |
242 | + (run-hooks 'cmd-help-mode-hook) | |
243 | + ) | |
244 | + | |
245 | +(defun cmd-right-trim-region (start end) | |
246 | + "リージョンで指定された範囲の行末の空白文字を削除します。" | |
247 | + (interactive "r") | |
248 | + (save-excursion | |
249 | + (goto-char start) | |
250 | + (while (re-search-forward "[\t ]+$" end t) | |
251 | + (replace-match "")))) | |
252 | + | |
253 | +(defun cmd-exec () | |
254 | + "バッファの内容を(必要であれば)ファイルに保存し、保存したファイル | |
255 | +を実行する。かなり手抜きをしています。" | |
256 | + (interactive) | |
257 | + (save-buffer) | |
258 | + (shell-command (buffer-file-name)) | |
259 | + ) | |
260 | + | |
261 | +(defun cmd-recenter () | |
262 | + "カレント位置を中央に配置した後、余分な行末のスペースを削除する" | |
263 | + (interactive) | |
264 | + (recenter) | |
265 | + (cmd-right-trim-region (point-min) (point-max))) | |
266 | + | |
267 | +(defun cmd-next-label () | |
268 | + "次のラベルへ跳ぶ" | |
269 | + (interactive) | |
270 | + (if (re-search-forward cmd-label-pattern nil t) | |
271 | + (goto-char (match-end 0)))) | |
272 | +(defun cmd-prev-label () | |
273 | + "前のラベルへ跳ぶ" | |
274 | + (interactive) | |
275 | + (if (re-search-backward cmd-label-pattern nil t) | |
276 | + (goto-char (match-beginning 0)))) | |
277 | + | |
278 | +(defun cmd-fill-paragraph () | |
279 | + "コメント行等の行詰めを行います。かなり手抜きをしています(こんな事を | |
280 | +して良いのだろうか)。" | |
281 | + (interactive) | |
282 | + (save-excursion | |
283 | + (let ((case-fold-search t) ;大文字・小文字を区別しない | |
284 | + (cmd-rem-regexp | |
285 | + "\\([\t ]*@?\\(rem\\|echo\\)\\)\\([ \t].*$\\|$\\)") | |
286 | + rem-begin | |
287 | + rem-end | |
288 | + rem-paragraph | |
289 | + match-str | |
290 | + (cmd-fill-column fill-column) | |
291 | + (current-buffer (buffer-name)) | |
292 | + ) | |
293 | + (beginning-of-line) | |
294 | + (if (looking-at cmd-rem-regexp) | |
295 | + (progn | |
296 | + (setq match-str (buffer-substring | |
297 | + (match-beginning 1) (match-end 1)) | |
298 | + rem-begin (point)) | |
299 | + (message "cmd-fill-paragraph【%s】" match-str) | |
300 | + (while (not (bobp)) | |
301 | + (forward-line -1) | |
302 | + (if (looking-at (concat match-str "\\([\t ]\\|$\\)")) | |
303 | + (setq rem-begin (point)) | |
304 | + (goto-char (point-min)))) | |
305 | + | |
306 | + (goto-char rem-begin) | |
307 | + (setq cmd-rem-regexp | |
308 | + (concat "\\(" | |
309 | + "\\(^" match-str "[^\n]*\n\\)+" | |
310 | + "\\(^" match-str "[^\n]*\\)?\\|" | |
311 | + "^" match-str ".*$\\)")) | |
312 | + (if (looking-at cmd-rem-regexp) | |
313 | + (progn | |
314 | + (setq rem-end (match-end 0) | |
315 | + rem-paragraph (buffer-substring rem-begin rem-end)) | |
316 | + (set-buffer (get-buffer-create cmd-temp-buf)) | |
317 | + (erase-buffer) | |
318 | + (insert rem-paragraph) | |
319 | + (indented-text-mode) | |
320 | + | |
321 | + (goto-char (point-min)) | |
322 | + (while (re-search-forward | |
323 | + (concat "^" match-str " ?") nil t) | |
324 | + (replace-match "")) | |
325 | + | |
326 | + (setq fill-column (- cmd-fill-column (length match-str))) | |
327 | + (goto-char (point-min)) | |
328 | + (while (not (eobp)) | |
329 | + (fill-paragraph nil) | |
330 | + (forward-paragraph)) | |
331 | + | |
332 | + (goto-char (point-min)) | |
333 | + (while (not (eobp)) | |
334 | + (beginning-of-line) | |
335 | + (insert (concat match-str | |
336 | + (if (looking-at "$") "" " "))) | |
337 | + (beginning-of-line) | |
338 | + (if (looking-at "[ \t]*@?echo$") | |
339 | + (progn | |
340 | + (end-of-line); | |
341 | + (insert "."))) | |
342 | + (forward-line 1)) | |
343 | + | |
344 | + (goto-char (point-max)) | |
345 | + (beginning-of-line) | |
346 | + (if (looking-at (concat match-str "$")) | |
347 | + (replace-match "")) | |
348 | + | |
349 | + (cmd-right-trim-region (point-min) (point-max)) | |
350 | + | |
351 | + (setq rem-paragraph | |
352 | + (buffer-substring (point-min) (point-max))) | |
353 | + (kill-buffer cmd-temp-buf) | |
354 | + (set-buffer current-buffer) | |
355 | + (delete-region rem-begin rem-end) | |
356 | + (insert rem-paragraph) | |
357 | + (message "done.") | |
358 | + ) | |
359 | + (progn | |
360 | + (ding) | |
361 | + (error "cmd-fill-paragraph【バグでしょう】"))) | |
362 | + ) | |
363 | + (message "cmd-fill-paragraph: 行頭が REM 又は ECHO ではありません") | |
364 | + ) | |
365 | + ) | |
366 | + ) | |
367 | + ) | |
368 | + | |
369 | +(defun cmd-mode () | |
370 | + "MS-DOSのバッチファイルやWindows NT のコマンドスクリプトファイルを編 | |
371 | +集する為のへなちゃこもーどです。 | |
372 | + | |
373 | +●バッファを保存後、保存したファイルを実行する | |
374 | + \\[cmd-exec] | |
375 | + | |
376 | +●コマンドのヘルプを表示する。 | |
377 | + \\[cmd-help] | |
378 | + | |
379 | +●現在のカーソル位置を画面の中央に配置し、行末の余分な空白文字を削除 | |
380 | + する。 | |
381 | + \\[cmd-recenter] | |
382 | + | |
383 | +●コメント行等(REM or ECHO)の行詰めを行なう。 | |
384 | + \\[cmd-fill-paragraph] | |
385 | + | |
386 | +●前のラベルへ | |
387 | + \\[cmd-prev-label] | |
388 | + | |
389 | +●次のラベルへ | |
390 | + \\[cmd-next-label] | |
391 | +" | |
392 | + (interactive) | |
393 | + (kill-all-local-variables) | |
394 | + ;;モード名の設定と、モードラインのモード名フィールドの設定 | |
395 | + (setq major-mode 'cmd-mode | |
396 | + mode-name "CMDとBAT") | |
397 | + ;; キーマップの設定 | |
398 | + (setq cmd-local-map (make-keymap)) | |
399 | + ;; キーの割り当て | |
400 | + (define-key cmd-local-map "\C-c\C-c" 'cmd-exec) | |
401 | + (define-key cmd-local-map "\C-ch" 'cmd-help) | |
402 | + (define-key cmd-local-map "\C-l" 'cmd-recenter) | |
403 | + (define-key cmd-local-map "\eq" 'cmd-fill-paragraph) | |
404 | + (define-key cmd-local-map "\e\C-a" 'cmd-prev-label) | |
405 | + (define-key cmd-local-map "\e\C-e" 'cmd-next-label) | |
406 | + | |
407 | + (use-local-map cmd-local-map) ; ローカルマップの使用宣言 | |
408 | + | |
409 | + ;; font-lockの設定 | |
410 | + (make-local-variable 'font-lock-defaults) | |
411 | + (setq font-lock-defaults | |
412 | + '((cmd-font-lock-keywords) t t)) | |
413 | + (font-lock-mode t) | |
414 | + | |
415 | + (run-hooks 'cmd-mode-hook) | |
416 | +) | |
417 | + | |
418 | +;; end here. |