[xyzzy:04132] shell-mode
- Subject: [xyzzy:04132] shell-mode
- From: Yutaka OIWA <yutaka@xxxxxxxxxxxxxxxxxxxxx>
おおいわです。
xyzzy の shell-mode は、素の DOS よりは遥かに使い勝手いいですが、
例えば pause<RET> と打ってしまうと C-c C-c 以外どうにもならなく
なってしまう (^^; など、emacs と比較するとまだ改良の余地がある
気がします。
# TeX に至っては特定の問い合わせで SIGINT がトラップされているので
# どうにもならなくなってしまいます (^^;
## ESC ESC (process-send-string (buffer-process (selected-buffer)) "x\n") RET
## とか手で入れてその場はしのいだ (^^;;;;;;
というわけで、とりあえず入力判定部分を改善した shell2.l を
作ってみました。
メカニズムとしては、xyzzy に process-mark が存在しない (なぜ?)
ので、process-filter を使って emacsen の process-mark の動作を
エミュレーションします。その上で、process-mark 以降で RET が
押された際には、process-mark と point-max の間の全ての文字列を
送信します。この際には prompt-regexp を使わないのでどんな状況でも
それなりに文字列が送信できます。
TODO: (やるきは未定)
・複数行ある時はどうする??
・M-p/M-n によるヒストリー検索。
既存のこの辺りの関数の動作を理解していない (^^;
・ファイル名の補完。
すごくめんどくさそう (^^;
やるなら cd コマンドを監視してディレクトリを移動することに。
・単独のコマンド実行の際もこの動作になって欲しい。
shell-mode から emacs でいう comint 部分の機能を独立させる?
あと、minibuffer でファイル名や関数名の補完を TAB で行なった際、
2回以上連続で TAB が押された際には *Completion* を1画面スクロール
して欲しいです。面倒でしょうか。>亀井様
;;; -*- Mode: Lisp; Package: LISP -*-
;;;
;;; Original version is part of xyzzy.
;;; modified by Yutaka Oiwa <oiwa@xxxxxxxxxxxxxxxxxx>.
;;; version 0.1.
(provide "shell")
(in-package "editor")
(export '(*shell-mode-hook* *shell-prompt-regexp* *shell-mode-map*
*shell-ret* *shell-echo* shell shell-send-input shell-send-interrupt))
(defvar *shell-mode-hook* nil)
(defvar *shell-prompt-regexp* "^[^#$%>?\n]*[#$%>?] *")
(defvar-local *shell-ret* "\n")
(defvar-local *shell-echo* nil)
(defvar *process-marker* nil)
(make-variable-buffer-local '*process-marker*)
(defvar *shell-mode-map* nil)
(unless *shell-mode-map*
(setq *shell-mode-map* (make-sparse-keymap))
(define-key *shell-mode-map* #\RET 'shell-send-input)
(define-key *shell-mode-map* '(#\C-c #\C-c) 'shell-send-interrupt))
(defun shell-mode ()
(setq mode-name "Shell")
(setq buffer-mode 'shell-mode)
(use-keymap *shell-mode-map*)
(setq need-not-save t)
(setq auto-save nil)
(setq kept-undo-information nil)
(set-buffer-fold-width 80)
(cond ((string-matchp *eshell* "command.com$")
(setq *shell-ret* "\r" *shell-echo* t))
((string-matchp *eshell* "cmd.exe$")
(setq *shell-ret* "\n" *shell-echo* t))
(t
(setq *shell-ret* "\n" *shell-echo* nil)))
(run-hooks '*shell-mode-hook*))
(defun shell ()
(interactive)
(set-buffer (get-buffer-create "*Shell*"))
(let ((proc (buffer-process (selected-buffer))))
(and proc (eq (process-status proc) ':run)
(return-from shell t)))
(goto-char (point-max))
(shell-mode)
(let ((proc (make-process *eshell* :output (selected-buffer))))
(set-process-filter proc #'shell-process-filter)
)
(setq *process-marker* (make-marker))
(set-marker *process-marker* (point-max))
)
(defun shell-process-filter (proc str)
(let ((*inhibit-quit* t) ;; for xyzzy prior to 0.2.0.124.
(old-buffer (selected-buffer))
(old-window (selected-window))
(win-config (current-window-configuration))
(buf (process-buffer proc))
pt
)
(unwind-protect
(progn
(set-buffer buf)
(let ((e (and (markerp *process-marker*) (= (marker-point *process-marker*) (point-max)))))
(save-excursion
(if (markerp *process-marker*)
(goto-marker *process-marker*)
(goto-char (point-max)))
(insert str)
(setq pt (point))
)
(set-marker *process-marker* pt)
(when e
(set-window (get-buffer-window buf))
; (message (format nil "~A ~A ~A" (marker-point *process-marker*) (point) (point-max)))
(goto-char (point-max))
)
))
(set-window old-window)
(set-buffer old-buffer)
(refresh-screen)))
; (message str)
)
(defun shell-send-input ()
(interactive)
(if (markerp *process-marker*)
(let ((start (marker-point *process-marker*))
(end (point-max)))
(if (<= start (point))
(let ((str (buffer-substring start end)))
(setq str (string-right-trim '(#\LFD #\RET) str))
(delete-region start end)
(unless *shell-echo*
(insert str "\n"))
(process-send-string (buffer-process (selected-buffer))
(concat str *shell-ret*))
(return-from shell-send-input t)))))
; original shell-send-input starts
(when (save-excursion
(goto-bol)
(looking-at *shell-prompt-regexp*))
(let* ((tail (progn (goto-eol) (point)))
(cmd (buffer-substring (match-end 0) tail)))
(cond ((eobp)
(if *shell-echo*
(delete-region (match-end 0) tail)
(insert "\n")))
(t
(goto-char (point-max))
; (or (bolp)
; (insert "\n"))
; (insert (match-string 0))
(unless *shell-echo*
(insert cmd "\n"))))
(process-send-string (buffer-process (selected-buffer))
(concatenate 'string cmd *shell-ret*)))))
(setf (symbol-function 'shell-send-interrupt) #'kill-subprocess)
--
大岩 寛 Yutaka Oiwa
東京大学大学院 理学系研究科情報科学専攻 修士課程 米澤研究室
<oiwa@xxxxxxxxxxxxxxxxxxxxx>, <yutaka@xxxxxxxxxxxxxxxxxxxxx>
PGP fingerprint = C9 8D 5C B8 86 ED D8 07 EA 59 34 D8 F4 65 53 61