From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Andy Stewart Newsgroups: gmane.emacs.devel Subject: Integrate term.el with multi-term.el Date: Sat, 20 Dec 2008 10:13:26 +0800 Message-ID: <87vdtf61bt.fsf@debian.domain> NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Trace: ger.gmane.org 1229739233 23513 80.91.229.12 (20 Dec 2008 02:13:53 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Sat, 20 Dec 2008 02:13:53 +0000 (UTC) To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Sat Dec 20 03:14:57 2008 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.50) id 1LDrMn-0002wj-60 for ged-emacs-devel@m.gmane.org; Sat, 20 Dec 2008 03:14:57 +0100 Original-Received: from localhost ([127.0.0.1]:47405 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1LDrLa-0000ep-Mi for ged-emacs-devel@m.gmane.org; Fri, 19 Dec 2008 21:13:42 -0500 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1LDrLV-0000cG-KG for emacs-devel@gnu.org; Fri, 19 Dec 2008 21:13:37 -0500 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1LDrLS-0000Yt-4S for emacs-devel@gnu.org; Fri, 19 Dec 2008 21:13:36 -0500 Original-Received: from [199.232.76.173] (port=52665 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1LDrLR-0000Yo-U8 for emacs-devel@gnu.org; Fri, 19 Dec 2008 21:13:33 -0500 Original-Received: from ti-out-0910.google.com ([209.85.142.186]:25353) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1LDrLR-0007Xs-0G for emacs-devel@gnu.org; Fri, 19 Dec 2008 21:13:33 -0500 Original-Received: by ti-out-0910.google.com with SMTP id u5so796328tia.10 for ; Fri, 19 Dec 2008 18:13:30 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:from:to:subject:date :message-id:user-agent:mime-version:content-type; bh=xw18vzo8YSWUOSAb194v9CUDj19200FHkxkyW61Ox7Q=; b=A74PBdwf4twULewF/9uzB+gjAwcW6/pR299LeNmedQNXH9Zwf/4otIx/F0657tqHAx IbQOITHWub4wlcmi2zSUrKtF1SqG7EvCeskby9krOtuz6VyHKtC+GBFQplT+rEVTm/NN gIF9C8qxvKBcF9wL2V7P4a0VWdW6ERL2CjLK8= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=from:to:subject:date:message-id:user-agent:mime-version :content-type; b=DSb2dUGd+EXHqxnzADNyFJfqMYTC9zypTEtt6NYpW0pxO7EtgD6vcwFz8YaS/KGzJo dZb3eCp7eNCjVTEwL/SYh8fyuHdeQ5H012YgkrduhZK1Ug1uPQo/ILuhxS+kl1chPp7X eKdSuDdpvc9MT7W/y72IlArERGsM6QjQaxk18= Original-Received: by 10.110.17.6 with SMTP id 6mr1117496tiq.21.1229739210633; Fri, 19 Dec 2008 18:13:30 -0800 (PST) Original-Received: from smtp.gmail.com ([222.212.143.192]) by mx.google.com with ESMTPS id 25sm6706873tif.6.2008.12.19.18.13.28 (version=TLSv1/SSLv3 cipher=RC4-MD5); Fri, 19 Dec 2008 18:13:29 -0800 (PST) User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.60 (gnu/linux) X-detected-operating-system: by monty-python.gnu.org: GNU/Linux 2.6 (newer, 2) X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:107087 Archived-At: --=-=-= Hi all, term.el is a great terminal in Emacs. But it have some point not very convenient: ,---- | 1-> Enter term, need use command "term", type everytime. | | 2-> Have not have good method to manage multiple term-buffer create and | switch. | | 3-> Don't handle close the buffer when type command "exit" in term. | | 4-> Don't handle interrupt sub-process when kill term-buffer forcible. | | 5-> Many keystroke binding is conflict with global keystroke binding | with user, so user can't use term.el with other modes convenient. `---- And multi-term.el is extension those features with term.el. I have attached newest version of multi-term.el I want integrate multi-term.el with term.el. I have sign the copyright of FSF. Any suggestions? Thanks -- Andy --=-=-= Content-Type: application/emacs-lisp Content-Disposition: attachment; filename=multi-term.el Content-Transfer-Encoding: quoted-printable Content-Description: multi-term.el ;;; multi-term.el --- Multi term buffer. ;; Author: Andy Stewart ;; Maintainer: Andy Stewart ;; Copyright (C) 2008, Andy Stewart, all rights reserved. ;; Created: 2008-09-19 23:02:42 ;; Version: 0.4 ;; Last-Updated: 2008-12-10 10:08:50 ;; URL: not distributed yet ;; Keywords: term, multiple buffer ;; Compatibility: GNU Emacs 23.0.60.1 ;; This program 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, 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; see the file COPYING. If not, write to ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth ;; Floor, Boston, MA 02110-1301, USA. ;; Features that might be requried by this library: ;; ;; `term' ;; ;;; Installation: ;; ;; Copy multi-term.el to your load-path and add to your ~/.emacs ;; ;; (require 'multi-term) ;; ;; And setup program that `multi-term' will need: ;; ;; (setq multi-term-program "/bin/bash") ;; ;; or setup like me "/bin/zsh" ;) ;; ;; Here, have below command you can use: ;; ;; `multi-term' create a new term buffer. ;; `multi-term-next' switch to next term buffer. ;; `multi-term-prev' switch to previous term buffer. ;; `multi-term-current-directory' create a new term with current-dire= ctory. ;; ;;; Customize ;; ;; `multi-term-program' default is nil, so when create new term buffer, ;; send environment variable of `SHELL' (`ESHELL', `/bin/sh') to `make-term= '. ;; ;; And you can set it to your like, like me: ;-) ;; ;; (setq multi-term-program "/bin/zsh") ;; ;; `multi-term-default-dir' default is `~/', only use when current buffer ;; is not in real directory. ;; ;; `multi-term-current-window-height' is window height when use function ;; ;; `multi-term-buffer-name' is a name of term buffer. ;; ;; `multi-term-scroll-show-maximum-output' is control how interpreter ;; output causes window to scorll. ;; ;; `multi-term-scroll-to-bottom-on-output' is control whether interpreter ;; output causes window to scroll. ;; ;; `term-unbind-key-list' is a key list control unbind some keystroke. ;; ;; `term-bind-key-alist' is a key alist that bind some keystroke. ;; If you don't like default, modified it. ;; ;; All above setup can customize by: ;; M-x customize-group RET multi-term RET ;; ;;; Commentary: ;; ;; This package is for create and manager multiple term buffer. ;; ;; Default, `term.el' can create a terminal buffer with `term-mode'. ;; But have some discommoded point: ;; ;; 1 -> ;; term-mode just create one terminal buffer with `term' command. ;; But not command for quick create and switch with terminal buffers. ;; ;; Now, use command `multi-term' can quick create new terminal buffer. ;; And use command `multi-term-next' or `multi-term-prev' can switch ;; next or previous terminal buffer quickly, whatever current buffer. ;; ;; 2 -> ;; Default, when use *NIX command `exit' from term-mode, will left ;; an unused buffer. ;; ;; Now `multi-term' can handled this, close buffer when use `exit'. ;; ;; 3 -> ;; If you use command `kill-this-buffer' to kill terminal buffer forci= ble. ;; term-mode can't interrupt sub-process before kill buffer. ;; ;; And `multi-term' do this now. ;; ;; 4 -> ;; And this is most import, `term-mode' is great for use shell in emac= s. ;; But it's default keystroke conflict with some global keystroke (exa= mple: C-x). ;; ;; Now `multi-term' unbind those conflict keystroke with `term-char-mo= de'. ;; ;;; Change log: ;; ;; 2008/12/10 ;; Improve customize interface. ;; ;; Setup customize automatically, don't need user setup it. ;; ;; Fix doc. ;; ;; Add option `multi-term-try-create'. ;; ;; Make function `multi-term-switch' accept offset argument. ;; ;; 2008/10/22 ;; Add variable `multi-term-current-window-height'. ;; Add variable `multi-term-buffer-name'. ;; ;; Add variable `term-unbind-key-list'. ;; Add variable `term-rebind-key-alist'. ;; Move key setup and some extension from `term-extension.el'. ;; Create new function `multi-term-keystroke-setup'. ;; ;; Fix doc. ;; ;; 2008/09/19 ;; First released. ;; ;;; Acknowledgments: ;; ;; Mark Triggs for multi-shell.el ;; ;;; TODO ;; ;; None ;; ;;; Require: (require 'term) ;;; Code: ;;; Customize (defgroup multi-term nil "Multi term manager." :group 'term) (defcustom multi-term-program nil "The program of term. If this is nil, setup it equal the environment variable of `SHELL'." :type 'string :group 'multi-term) (defcustom multi-term-try-create t "Try to create a new term buffer when switch. When use `multi-term-next' or `multi-term-prev' to switch term buffer, try to create a new term buffer if haven't any term buffers exist." :type 'boolean :group 'multi-shell) (defcustom multi-term-default-dir "~/" "The default directory that term create. If current local directory is in-existence." :type 'string :group 'multi-term) (defcustom multi-term-buffer-name "terminal" "The buffer name of term buffer." :type 'string :group 'multi-term) (defcustom multi-term-scroll-show-maximum-output nil "*Controls how interpreter output causes window to scroll. If non-nil, then show the maximum output when the window is scrolled. See variable `multi-term-scroll-to-bottom-on-output'." :type 'boolean :group 'multi-term) (defcustom multi-term-scroll-to-bottom-on-output nil "*Controls whether interpreter output causes window to scroll. If nil, then do not scroll. If t or `all', scroll all windows showing buff= er. If `this', scroll only the selected window. If `others', scroll only those that are not the selected window. The default is nil. See variable `multi-term-scroll-show-maximum-output'." :type 'boolean :group 'multi-term) (defcustom multi-term-current-window-height -13 "This value is window height when call `multi-term-switch-to-current-dire= ctory'." :type 'integer :group 'multi-term) (defcustom term-unbind-key-list '("C-z" "C-x" "C-c" "C-h" "C-y" "") "The key list that need to unbind." :type 'list :group 'multi-term) (defcustom term-bind-key-alist '( ("C-c C-c" . term-interrupt-subjob) ("M-f" . term-send-forward-word) ("M-b" . term-send-backward-word) ("M-o" . term-send-backspace) ("C-p" . previous-line) ("C-n" . next-line) ("M-p" . term-send-up) ("M-n" . term-send-down) ("C-s" . isearch-forward) ("C-r" . isearch-backward) ("M-M" . term-send-forward-kill-word) ("M-N" . term-send-backward-kill-word) ("M-." . comint-dynamic-complete) ("M-," . term-send-input)) "The key alist that need to bind. If you not like default setup, modified it, with (KEY . COMMAND) format." :type 'alist :group 'multi-term) ;;;###autoload (defun multi-term () "Create new term buffer." (interactive) (let* ((term-buffer (multi-term-get-buffer))) (set-buffer term-buffer) ;; Add customize keystroke with `term-mode-hook' (remove-hook 'term-mode-hook 'multi-term-keystroke-setup) (add-hook 'term-mode-hook 'multi-term-keystroke-setup) ;; Load term mode (term-mode) (term-char-mode) ;; Handle term buffer close (multi-term-handle-close) ;; Handle `output' varialble (setq term-scroll-show-maximum-output multi-term-scroll-show-maximum-ou= tput term-scroll-to-bottom-on-output multi-term-scroll-to-bottom-on-ou= tput) ;; Swtich buffer (switch-to-buffer term-buffer) ;; Add hook to be sure `term' interrupt subjob before buffer killed. (add-hook 'kill-buffer-hook 'multi-term-kill-buffer-hook))) (defun multi-term-get-buffer () "Get term buffer." (let* ((term-list-length (length (multi-term-list))) ;get length= of term list (index (if term-list-length (1+ term-list-length) 1))) ;setup new = term index (with-temp-buffer ;; switch to current local directory, ;; if in-existence, switch to `multi-term-default-dir'. (cd (or default-directory (expand-file-name multi-term-default-dir))) ;; adjust value N when max index of term buffer is less than length o= f term list (while (buffer-live-p (get-buffer (format "*%s<%s>*" multi-term-buffe= r-name index))) (setq index (1+ index))) ;; make term, details to see function `make-term' in `term.el'. (make-term (format "%s<%s>" multi-term-buffer-name index) (or multi-term-program (getenv "SHELL") (getenv "ESHELL") "/bin/sh"))))) (defun multi-term-handle-close () "This function for close current term buffer. When `exit' from term buffer." (when (ignore-errors (get-buffer-process (current-buffer))) (set-process-sentinel (get-buffer-process (current-buffer)) (lambda (proc change) (when (string-match "\\(finished\\|exited\\)" c= hange) (kill-buffer (process-buffer proc))))))) (defun multi-term-kill-buffer-hook () "Function that hook `kill-buffer-hook'." ;; Interrupt the current subjob ;; when have alive process with current term buffer (when (and (eq major-mode 'term-mode) (term-check-proc (current-buffer))) (term-interrupt-subjob))) (defun multi-term-list () "The term buffers presently active." ;; Autload command `remove-if-not'. (autoload 'remove-if-not "cl-seq") (sort (remove-if-not (lambda (b) (string-match (concat "^\*" multi-term-buffer-name) (buffer-name b))) (buffer-list)) (lambda (a b) (< (string-to-number (cadr (split-string (buffer-name a) "[<>]"))) (string-to-number (cadr (split-string (buffer-name b) "[<>]"))))))) (defun multi-term-next (&optional offset) "Go to the next term." (interactive "P") (multi-term-switch 'NEXT (or offset 1))) (defun multi-term-prev (&optional offset) "Go to the previous term." (interactive) (multi-term-switch 'PREVIOUS (or offset 1))) (defun multi-term-switch (direction offset) "If DIRECTION is `NEXT', switch to the next term. If `PREVIOUS', switch to the previous term." (let (terms this-buffer) (setq terms (multi-term-list)) (if (consp terms) (progn (setf (cdr (last terms)) terms) (setq this-buffer (position (current-buffer) (multi-term-list))) (if this-buffer (if (eql direction 'NEXT) (switch-to-buffer (nth (+ this-buffer offset) terms)) (switch-to-buffer (nth (+ (- (length (multi-term-list)) off= set) this-buffer) terms))) (switch-to-buffer (car terms)))) (if multi-term-try-create (progn (multi-term) (message "Create a new `multi-term' buffer.")) (message "Haven't any `multi-term' buffer exist."))))) (defun multi-term-current-directory () "Open term that start at current directory." (interactive) (split-window-vertically multi-term-current-window-height) (other-window 1) (multi-term)) (defun multi-term-keystroke-setup () "Keystroke setup of `term-char-mode'. Default, the key binds of `term-char-mode' conflict with user's keystroke. So this function unbind some keys with `term-raw-map'. And bind some keystroke with `term-raw-map'." (let (bind-key bind-command) ;; Unbind base key that conflict with user's keys-tokes. (dolist (unbind-key term-unbind-key-list) (cond ((stringp unbind-key) (setq unbind-key (read-kbd-macro unbind-key))) ((vectorp unbind-key) nil) (t (signal 'wrong-type-argument (list 'array unbind-key)))) (define-key term-raw-map unbind-key nil)) ;; Add some i use keys. ;; If you don't like my keystroke, ;; just modified `term-bind-key-alist' (dolist (element term-bind-key-alist) (setq bind-key (car element)) (setq bind-command (cdr element)) (cond ((stringp bind-key) (setq bind-key (read-kbd-macro bind-key))) ((vectorp bind-key) nil) (t (signal 'wrong-type-argument (list 'array bind-key)))) (define-key term-raw-map bind-key bind-command)))) (defun term-send-backward-kill-word () "Backward kill word in term mode." (interactive) (term-send-raw-string "\C-w")) (defun term-send-forward-kill-word () "Kill word in term mode." (interactive) (term-send-raw-string "\ed")) (defun term-send-backward-word () "Move backward word in term mode." (interactive) (term-send-raw-string "\eb")) (defun term-send-forward-word () "Move forward word in term mode." (interactive) (term-send-raw-string "\ef")) (provide 'multi-term) ;;; multi-term.el ends here --=-=-=--