term.el 179 KB
Newer Older
1
;;; term.el --- general command interpreter in a window stuff -*- lexical-binding: t -*-
Richard M. Stallman's avatar
Richard M. Stallman committed
2

Paul Eggert's avatar
Paul Eggert committed
3
;; Copyright (C) 1988, 1990, 1992, 1994-1995, 2001-2019 Free Software
4
;; Foundation, Inc.
Richard M. Stallman's avatar
Richard M. Stallman committed
5

Richard M. Stallman's avatar
Richard M. Stallman committed
6 7
;; Author: Per Bothner <per@bothner.com>
;; Maintainer: Dan Nicolaescu <dann@ics.uci.edu>, Per Bothner <per@bothner.com>
8 9
;; Based on comint mode written by: Olin Shivers <shivers@cs.cmu.edu>
;; Keywords: processes
Richard M. Stallman's avatar
Richard M. Stallman committed
10

11 12
;; This file is part of GNU Emacs.

13
;; GNU Emacs is free software: you can redistribute it and/or modify
14
;; it under the terms of the GNU General Public License as published by
15 16
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
17 18 19 20 21 22 23

;; GNU Emacs 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
24
;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
25

26 27
;; Marck 13 2001
;; Fixes for CJK support by Yong Lu <lyongu@yahoo.com>.
28

29 30
;; Dir/Hostname tracking and ANSI colorization by
;; Marco Melgazzi <marco@techie.com>.
Richard M. Stallman's avatar
Richard M. Stallman committed
31

32
;; To see what I've modified and where it came from search for '-mm'
Richard M. Stallman's avatar
Richard M. Stallman committed
33

34 35
;;; Commentary:

36 37 38 39
;; Speed considerations and a few caveats
;; --------------------------------------
;;
;; While the message passing and the colorization surely introduce some
Paul Eggert's avatar
Paul Eggert committed
40 41
;; overhead this has became so small that IMHO it is surely outweighed by
;; the benefits you get but, as usual, YMMV.
42
;;
Paul Eggert's avatar
Paul Eggert committed
43
;; Important caveat, when deciding the cursor/'gray keys' keycodes I had to
44 45
;; make a choice: on my Linux box this choice allows me to run all the
;; ncurses applications without problems but make these keys
Paul Eggert's avatar
Paul Eggert committed
46
;; incomprehensible to all the cursesX programs.  Your mileage may vary so
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
;; you may consider changing the default 'emulation'.  Just search for this
;; piece of code and modify it as you like:
;;
;; ;; Which would be better:  "\e[A" or "\eOA"? readline accepts either.
;; ;; For my configuration it's definitely better \eOA but YMMV.  -mm
;; ;; For example: vi works with \eOA while elm wants \e[A ...
;; (defun term-send-up    () (interactive) (term-send-raw-string "\eOA"))
;; (defun term-send-down  () (interactive) (term-send-raw-string "\eOB"))
;; (defun term-send-right () (interactive) (term-send-raw-string "\eOC"))
;; (defun term-send-left  () (interactive) (term-send-raw-string "\eOD"))
;;
;;
;; IMPORTANT: additions & changes
;; ------------------------------
;;
;;  With this enhanced ansi-term.el you will get a reliable mechanism of
;; directory/username/host tracking: the only drawback is that you will
;; have to modify your shell start-up script.  It's worth it, believe me :).
;;
;; When you rlogin/su/telnet and the account you access has a modified
;; startup script, you will be able to access the remote files as usual
;; with C-x C-f, if it's needed you will have to enter a password,
;; otherwise the file should get loaded straight away.
;;
;; This is useful even if you work only on one host: it often happens that,
;; for maintenance reasons, you have to edit files 'as root': before
;; patching term.el, I su-ed in a term.el buffer and used vi :), now I
;; simply do a C-x C-f and, via ange-ftp, the file is automatically loaded
;; 'as-root'.  ( If you don't want to enter the root password every time you
;; can put it in your .netrc: note that this is -not- advisable if you're
;; connected to the internet or if somebody else works on your workstation!)
;;
;; If you use wu-ftpd you can use some of its features to avoid root ftp
;; access to the rest of the world: just put in /etc/ftphosts something like
;;
;; # Local access
;; allow	root		127.0.0.1
;;
;; # By default nobody can't do anything
;; deny	root		*
;;
;;
;;             ----------------------------------------
;;
;;  If, instead of 'term', you call 'ansi-term', you get multiple term
;; buffers, after every new call ansi-term opens a new *ansi-term*<xx> window,
;; where <xx> is, as usual, a number...
;;
;;             ----------------------------------------
;;
;;  With the term-buffer-maximum-size you can finally decide how many
;; scrollback lines to keep: its default is 2048 but you can change it as
;; usual.
;;
;;             ----------------------------------------
;;
;;
104 105
;;  ANSI colorization should work well.  Blink, is not supported.
;;  Currently it's mapped as bold.
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
;;
;;             ----------------------------------------
;;
;;  TODO:
;;
;;  - Add hooks to allow raw-mode keys to be configurable
;;  - Which keys are better ? \eOA or \e[A ?
;;
;;
;;  Changes:
;;
;; V4.0 January 1997
;;
;;   - Huge reworking of the faces code: now we only have roughly 20-30
;;     faces for everything so we're even faster than the old md-term.el !
;;   - Finished removing all the J-Shell code.
;;
;;  V3.0 January 1997
;;
;;  - Now all the supportable ANSI commands work well.
;;  - Reworked a little the code: much less jsh-inspired stuff
;;
;;  V2.3 November
;;
;;  - Now all the faces are accessed through an array: much cleaner code.
;;
;;  V2.2 November 4 1996
;;
;;  - Implemented ANSI output colorization ( a bit rough but enough for
;;    color_ls )
;;
;;  - Implemented a maximum limit for the scroll buffer (stolen from
;;    comint.el)
;;
;;  v2.1 October 28 1996, first public release
;;
;;  - Some new keybindings for term-char mode ( notably home/end/...)
;;  - Directory, hostname and username tracking via ange-ftp
;;  - Multi-term capability via the ansi-term call
;;
;;  ----------------------------------------------------------------
;;  You should/could have something like this in your .emacs to take
;;  full advantage of this package
;;
;;  (add-hook 'term-mode-hook
151 152 153 154 155 156 157
;;  	      (function
;;  	       (lambda ()
;;  	             (setq term-prompt-regexp "^[^#$%>\n]*[#$%>] *")
;;  	             (setq-local mouse-yank-at-point t)
;;  	             (setq-local transient-mark-mode nil)
;;  	             (auto-fill-mode -1)
;;  	             (setq tab-width 8 ))))
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
;;
;;
;;             ----------------------------------------
;;
;;  If you want to use color ls the best setup is to have a different file
;; when you use eterm ( see above, mine is named .emacs_dircolors ).  This
;; is necessary because some terminals, rxvt for example, need non-ansi
;; hacks to work ( for example on my rxvt white is wired to fg, and to
;; obtain normal white I have to do bold-white :)
;;
;;             ----------------------------------------
;;
;;
;;  # Configuration file for the color ls utility
;;  # This file goes in the /etc directory, and must be world readable.
;;  # You can copy this file to .dir_colors in your $HOME directory to
;;  # override the system defaults.
;;
;;  # COLOR needs one of these arguments: 'tty' colorizes output to ttys, but
;;  # not pipes.  'all' adds color characters to all output.  'none' shuts
;;  # colorization off.
;;  COLOR tty
;;  OPTIONS -F
;;
;;  # Below, there should be one TERM entry for each termtype that is
;;  # colorizable
;;  TERM eterm
;;
;;  # EIGHTBIT, followed by '1' for on, '0' for off.  (8-bit output)
;;  EIGHTBIT 1
;;
;;  # Below are the color init strings for the basic file types.  A color init
;;  # string consists of one or more of the following numeric codes:
;;  # Attribute codes:
;;  # 00=none 01=bold 04=underscore 05=blink 07=reverse 08=concealed
;;  # Text color codes:
;;  # 30=black 31=red 32=green 33=yellow 34=blue 35=magenta 36=cyan 37=white
;;  # Background color codes:
;;  # 40=black 41=red 42=green 43=yellow 44=blue 45=magenta 46=cyan 47=white
;;  NORMAL 00	# global default, although everything should be something.
;;  FILE 00 		# normal file
;;  DIR 00;37 	# directory
;;  LINK 00;36 	# symbolic link
;;  FIFO 00;37	# pipe
;;  SOCK 40;35	# socket
;;  BLK 33;01	# block device driver
;;  CHR 33;01 	# character device driver
;;
;;  # This is for files with execute permission:
;;  EXEC 00;32
;;
;;  # List any file extensions like '.gz' or '.tar' that you would like ls
;;  # to colorize below.  Put the extension, a space, and the color init
;;  # string.  (and any comments you want to add after a '#')
;;  .tar 01;33 # archives or compressed
;;  .tgz 01;33
;;  .arj 01;33
;;  .taz 01;33
;;  .lzh 01;33
;;  .zip 01;33
;;  .z   01;33
;;  .Z   01;33
;;  .gz  01;33
;;  .jpg 01;35 # image formats
;;  .gif 01;35
;;  .bmp 01;35
;;  .xbm 01;35
;;  .xpm 01;35
;;
;;
;;             ----------------------------------------
;;
;;  Notice: for directory/host/user tracking you need to have something
231
;; like this in your shell startup script (this is for a POSIXish shell
232 233 234 235 236 237
;; like Bash but should be quite easy to port to other shells).
;;
;; For troubleshooting in Bash, you can check the definition of the
;; custom functions with the "type" command.  e.g. "type cd".  If you
;; do not see the expected definition from the config below, then the
;; directory tracking will not work.
238 239 240
;;
;;             ----------------------------------------
;;
241
;;	# Set HOSTNAME if not already set.
242
;;	: ${HOSTNAME=$(uname -n)}
243
;;
244
;;	# su does not change this but I'd like it to
245
;;	USER=$(whoami)
246
;;
247
;;	# ...
248
;;
249 250
;;	case $TERM in
;;	    eterm*)
251
;;
252 253
;;		printf '%s\n' \
;;		 -------------------------------------------------------------- \
254
;;		 "Hello $USER" \
255 256 257
;;		 "Today is $(date)" \
;;		 "We are on $HOSTNAME running $(uname) under Emacs term mode" \
;;		 --------------------------------------------------------------
258
;;
259 260
;;		# The \033 stands for ESC.
;;		# There is a space between "AnSiT?" and $whatever.
261
;;
262 263 264
;;		cd()    { command cd    "$@"; printf '\033AnSiTc %s\n' "$PWD"; }
;;		pushd() { command pushd "$@"; printf '\033AnSiTc %s\n' "$PWD"; }
;;		popd()  { command popd  "$@"; printf '\033AnSiTc %s\n' "$PWD"; }
265
;;
266 267 268
;;		printf '\033AnSiTc %s\n' "$PWD"
;;		printf '\033AnSiTh %s\n' "$HOSTNAME"
;;		printf '\033AnSiTu %s\n' "$USER"
269
;;
270 271
;;		# Use custom dircolors in term buffers.
;;		# eval $(dircolors $HOME/.emacs_dircolors)
272
;;	esac
273
;;
274
;;	# ...
275 276
;;
;;
Richard M. Stallman's avatar
Richard M. Stallman committed
277

278
;;; Original Commentary:
279
;; ---------------------
Richard M. Stallman's avatar
Richard M. Stallman committed
280

Erik Naggum's avatar
Erik Naggum committed
281
;; The changelog is at the end of this file.
Richard M. Stallman's avatar
Richard M. Stallman committed
282

Erik Naggum's avatar
Erik Naggum committed
283 284 285
;; Please send me bug reports, bug fixes, and extensions, so that I can
;; merge them into the master source.
;;     - Per Bothner (bothner@cygnus.com)
Richard M. Stallman's avatar
Richard M. Stallman committed
286 287


Erik Naggum's avatar
Erik Naggum committed
288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318
;; Brief Command Documentation:
;;============================================================================
;; Term Mode Commands: (common to all derived modes, like cmushell & cmulisp
;; mode)
;;
;; m-p	    term-previous-input    	  Cycle backwards in input history
;; m-n	    term-next-input  	    	  Cycle forwards
;; m-r     term-previous-matching-input  Previous input matching a regexp
;; m-s     comint-next-matching-input      Next input that matches
;; return  term-send-input
;; c-c c-a term-bol                      Beginning of line; skip prompt.
;; c-d	    term-delchar-or-maybe-eof     Delete char unless at end of buff.
;; c-c c-u term-kill-input	    	    ^u
;; c-c c-w backward-kill-word    	    ^w
;; c-c c-c term-interrupt-subjob 	    ^c
;; c-c c-z term-stop-subjob	    	    ^z
;; c-c c-\ term-quit-subjob	    	    ^\
;; c-c c-o term-kill-output		    Delete last batch of process output
;; c-c c-r term-show-output		    Show last batch of process output
;; c-c c-h term-dynamic-list-input-ring  List input history
;;
;; Not bound by default in term-mode
;; term-send-invisible			Read a line w/o echo, and send to proc
;; (These are bound in shell-mode)
;; term-dynamic-complete		Complete filename at point.
;; term-dynamic-list-completions	List completions in help buffer.
;; term-replace-by-expanded-filename	Expand and complete filename at point;
;;					replace with expanded/completed name.
;; term-kill-subjob			No mercy.
;; term-show-maximum-output            Show as much output as possible.
;; term-continue-subjob		Send CONT signal to buffer's process
319
;;					group.  Useful if you accidentally
Erik Naggum's avatar
Erik Naggum committed
320 321
;;					suspend your process (with C-c C-z).

322
;; term-mode-hook is the term mode hook.  Basically for your keybindings.
Erik Naggum's avatar
Erik Naggum committed
323 324
;; term-load-hook is run after loading in this package.

325
;;; Code:
Erik Naggum's avatar
Erik Naggum committed
326 327 328

;; This is passed to the inferior in the EMACS environment variable,
;; so it is important to increase it if there are protocol-relevant changes.
329
(defconst term-protocol-version "0.96")
Richard M. Stallman's avatar
Richard M. Stallman committed
330

331
(eval-when-compile (require 'ange-ftp))
332
(eval-when-compile (require 'cl-lib))
Richard M. Stallman's avatar
Richard M. Stallman committed
333 334
(require 'ring)
(require 'ehelp)
335
(require 'comint) ; Password regexp.
336

337 338 339 340 341 342
(declare-function ring-empty-p "ring" (ring))
(declare-function ring-ref "ring" (ring index))
(declare-function ring-insert-at-beginning "ring" (ring item))
(declare-function ring-length "ring" (ring))
(declare-function ring-insert "ring" (ring item))

343
(defgroup term nil
344
  "General command interpreter in a window."
345
  :group 'processes)
346

Richard M. Stallman's avatar
Richard M. Stallman committed
347 348

;;; Buffer Local Variables:
349 350 351 352 353 354
;;============================================================================
;; Term mode buffer local variables:
;;     term-prompt-regexp    - string       term-bol uses to match prompt.
;;     term-delimiter-argument-list - list  For delimiters and arguments
;;     term-last-input-start - marker       Handy if inferior always echoes
;;     term-last-input-end   - marker       For term-kill-output command
355 356
;; For the input history mechanism:
(defvar term-input-ring-size 32 "Size of input history ring.")
357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381
;;     term-input-ring-size  - integer
;;     term-input-ring       - ring
;;     term-input-ring-index - number           ...
;;     term-input-autoexpand - symbol           ...
;;     term-input-ignoredups - boolean          ...
;;     term-last-input-match - string           ...
;;     term-dynamic-complete-functions - hook   For the completion mechanism
;;     term-completion-fignore - list           ...
;;     term-get-old-input    - function     Hooks for specific
;;     term-input-filter-functions - hook     process-in-a-buffer
;;     term-input-filter     - function         modes.
;;     term-input-send	- function
;;     term-scroll-to-bottom-on-output - symbol ...
;;     term-scroll-show-maximum-output - boolean...
(defvar term-height)                    ; Number of lines in window.
(defvar term-width)                     ; Number of columns in window.
(defvar term-home-marker) ; Marks the "home" position for cursor addressing.
(defvar term-saved-home-marker nil
  "When using alternate sub-buffer,
contains saved term-home-marker from original sub-buffer.")
(defvar term-start-line-column 0
  "(current-column) at start of screen line, or nil if unknown.")
(defvar term-current-column 0 "If non-nil, is cache for (current-column).")
(defvar term-current-row 0
  "Current vertical row (relative to home-marker) or nil if unknown.")
382 383
(defvar term-insert-mode nil)
(defvar term-vertical-motion)
384 385
(defvar term-do-line-wrapping nil
  "Last character was a graphic in the last column.
386 387
If next char is graphic, first move one column right
\(and line warp) before displaying it.
388
This emulates (more or less) the behavior of xterm.")
389 390
(defvar term-kill-echo-list nil
  "A queue of strings whose echo we want suppressed.")
391
(defvar term-terminal-undecoded-bytes nil)
392
(defvar term-current-face 'term)
393 394 395 396 397 398 399 400 401 402
(defvar-local term-scroll-start 0
  "Top-most line (inclusive) of the scrolling region.
`term-scroll-start' must be in the range [0,term-height).  In addition, its
value has to be smaller than `term-scroll-end', i.e. one line scroll regions are
not allowed.")
(defvar-local term-scroll-end nil
  "Bottom-most line (inclusive) of the scrolling region.
`term-scroll-end' must be in the range [0,term-height).  In addition, its
value has to be greater than `term-scroll-start', i.e. one line scroll regions are
not allowed.")
403 404
(defvar term-pager-count nil
  "Number of lines before we need to page; if nil, paging is disabled.")
405
(defvar term-saved-cursor nil)
406 407 408
(define-obsolete-variable-alias 'term-command-hook
  'term-command-function "27.1")
(defvar term-command-function #'term-command-hook)
409
(defvar term-log-buffer nil)
410 411 412 413 414 415 416 417 418 419 420 421
(defvar term-scroll-with-delete nil
  "If t, forward scrolling should be implemented by delete to
top-most line(s); and if nil, scrolling should be implemented
by moving term-home-marker.  It is set to t if there is a
\(non-default) scroll-region OR the alternate buffer is used.")
(defvar term-pending-delete-marker) ; New user input in line mode
       ; needs to be deleted, because it gets echoed by the inferior.
       ; To reduce flicker, we defer the delete until the next output.
(defvar term-old-mode-map nil "Saves the old keymap when in char mode.")
(defvar term-old-mode-line-format) ; Saves old mode-line-format while paging.
(defvar term-pager-old-local-map nil "Saves old keymap while paging.")
(defvar term-pager-old-filter) ; Saved process-filter while paging.
422 423
(defvar-local term-line-mode-buffer-read-only nil
  "The `buffer-read-only' state to set in `term-line-mode'.")
Richard M. Stallman's avatar
Richard M. Stallman committed
424

425
(defcustom explicit-shell-file-name nil
Lute Kamstra's avatar
Lute Kamstra committed
426
  "If non-nil, is file name to use for explicitly requested inferior shell."
427 428
  :type '(choice (const nil) file)
  :group 'term)
Richard M. Stallman's avatar
Richard M. Stallman committed
429 430

(defvar term-prompt-regexp "^"
431
  "Regexp to recognize prompts in the inferior process.
Richard M. Stallman's avatar
Richard M. Stallman committed
432 433 434 435 436 437 438 439 440 441 442 443 444
Defaults to \"^\", the null string at BOL.

Good choices:
  Canonical Lisp: \"^[^> \\n]*>+:? *\" (Lucid, franz, kcl, T, cscheme, oaklisp)
  Lucid Common Lisp: \"^\\\\(>\\\\|\\\\(->\\\\)+\\\\) *\"
  franz: \"^\\\\(->\\\\|<[0-9]*>:\\\\) *\"
  kcl: \"^>+ *\"
  shell: \"^[^#$%>\\n]*[#$%>] *\"
  T: \"^>+ *\"

This is a good thing to set in mode hooks.")

(defvar term-delimiter-argument-list ()
445
  "List of characters to recognize as separate arguments in input.
Richard M. Stallman's avatar
Richard M. Stallman committed
446
Strings comprising a character in this list will separate the arguments
447 448
surrounding them, and also be regarded as arguments in their own right
\(unlike whitespace).  See `term-arguments'.
Richard M. Stallman's avatar
Richard M. Stallman committed
449 450
Defaults to the empty list.

451
For shells, a good value is (?\\| ?& ?< ?> ?\\( ?\\) ?\\;).
Richard M. Stallman's avatar
Richard M. Stallman committed
452 453 454

This is a good thing to set in mode hooks.")

455
(defcustom term-input-autoexpand nil
Lute Kamstra's avatar
Lute Kamstra committed
456
  "If non-nil, expand input command history references on completion.
Richard M. Stallman's avatar
Richard M. Stallman committed
457 458 459 460 461 462 463
This mirrors the optional behavior of tcsh (its autoexpand and histlit).

If the value is `input', then the expansion is seen on input.
If the value is `history', then the expansion is only when inserting
into the buffer's input ring.  See also `term-magic-space' and
`term-dynamic-complete'.

464 465 466
This variable is buffer-local."
  :type '(choice (const nil) (const t) (const input) (const history))
  :group 'term)
Richard M. Stallman's avatar
Richard M. Stallman committed
467

468
(defcustom term-input-ignoredups nil
Lute Kamstra's avatar
Lute Kamstra committed
469
  "If non-nil, don't add input matching the last on the input ring.
Richard M. Stallman's avatar
Richard M. Stallman committed
470 471
This mirrors the optional behavior of bash.

472 473 474
This variable is buffer-local."
  :type 'boolean
  :group 'term)
Richard M. Stallman's avatar
Richard M. Stallman committed
475

476
(defcustom term-input-ring-file-name nil
Lute Kamstra's avatar
Lute Kamstra committed
477
  "If non-nil, name of the file to read/write input history.
Richard M. Stallman's avatar
Richard M. Stallman committed
478 479
See also `term-read-input-ring' and `term-write-input-ring'.

480 481 482
This variable is buffer-local, and is a good thing to set in mode hooks."
  :type 'boolean
  :group 'term)
Richard M. Stallman's avatar
Richard M. Stallman committed
483

484 485 486 487 488 489 490 491 492
(defcustom term-char-mode-buffer-read-only t
  "If non-nil, only the process filter may modify the buffer in char mode.

A non-nil value makes the buffer read-only in `term-char-mode',
which prevents editing commands from making the buffer state
inconsistent with the state of the terminal understood by the
inferior process.  Only the process filter is allowed to make
changes to the buffer.

Paul Eggert's avatar
Paul Eggert committed
493
Customize this option to nil if you want the previous behavior."
494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513
  :version "26.1"
  :type 'boolean
  :group 'term)

(defcustom term-char-mode-point-at-process-mark t
  "If non-nil, keep point at the process mark in char mode.

A non-nil value causes point to be moved to the current process
mark after each command in `term-char-mode' (provided that the
pre-command point position was also at the process mark).  This
prevents commands that move point from making the buffer state
inconsistent with the state of the terminal understood by the
inferior process.

Mouse events are not affected, so moving point and selecting text
is still possible in char mode via the mouse, after which other
commands can be invoked on the mouse-selected point or region,
until the process filter (or user) moves point to the process
mark once again.

Paul Eggert's avatar
Paul Eggert committed
514
Customize this option to nil if you want the previous behavior."
515 516 517 518
  :version "26.1"
  :type 'boolean
  :group 'term)

519
(defcustom term-scroll-to-bottom-on-output nil
Lute Kamstra's avatar
Lute Kamstra committed
520
  "Controls whether interpreter output causes window to scroll.
Richard M. Stallman's avatar
Richard M. Stallman committed
521 522 523 524 525 526 527
If nil, then do not scroll.  If t or `all', scroll all windows showing buffer.
If `this', scroll only the selected window.
If `others', scroll only those that are not the selected window.

The default is nil.

See variable `term-scroll-show-maximum-output'.
528 529 530
This variable is buffer-local."
  :type 'boolean
  :group 'term)
Richard M. Stallman's avatar
Richard M. Stallman committed
531

532
(defcustom term-scroll-show-maximum-output nil
Lute Kamstra's avatar
Lute Kamstra committed
533
  "Controls how interpreter output causes window to scroll.
Richard M. Stallman's avatar
Richard M. Stallman committed
534 535 536
If non-nil, then show the maximum output when the window is scrolled.

See variable `term-scroll-to-bottom-on-output'.
537 538 539
This variable is buffer-local."
  :type 'boolean
  :group 'term)
Richard M. Stallman's avatar
Richard M. Stallman committed
540

541 542 543 544 545 546
(defcustom term-suppress-hard-newline nil
  "Non-nil means interpreter should not break long lines with newlines.
This means text can automatically reflow if the window is resized."
  :version "24.4"
  :type 'boolean
  :group 'term)
547
(make-obsolete-variable 'term-suppress-hard-newline nil
548
                        "27.1")
549

Richard M. Stallman's avatar
Richard M. Stallman committed
550 551 552 553 554 555 556 557 558 559
;; Where gud-display-frame should put the debugging arrow.  This is
;; set by the marker-filter, which scans the debugger's output for
;; indications of the current pc.
(defvar term-pending-frame nil)

;;; Here are the per-interpreter hooks.
(defvar term-get-old-input (function term-get-old-input-default)
  "Function that submits old text in term mode.
This function is called when return is typed while the point is in old text.
It returns the text to be submitted as process input.  The default is
560 561
`term-get-old-input-default', which grabs the current line, and strips off
leading text matching `term-prompt-regexp'.")
Richard M. Stallman's avatar
Richard M. Stallman committed
562 563 564 565 566 567 568 569 570 571 572 573 574

(defvar term-dynamic-complete-functions
  '(term-replace-by-expanded-history term-dynamic-complete-filename)
  "List of functions called to perform completion.
Functions should return non-nil if completion was performed.
See also `term-dynamic-complete'.

This is a good thing to set in mode hooks.")

(defvar term-input-filter
  (function (lambda (str) (not (string-match "\\`\\s *\\'" str))))
  "Predicate for filtering additions to input history.
Only inputs answering true to this function are saved on the input
575
history list.  Default is to save anything that isn't all whitespace.")
Richard M. Stallman's avatar
Richard M. Stallman committed
576 577 578 579 580 581 582

(defvar term-input-filter-functions '()
  "Functions to call before input is sent to the process.
These functions get one argument, a string containing the text to send.

This variable is buffer-local.")

583
(defvar term-input-sender #'term-simple-send
Richard M. Stallman's avatar
Richard M. Stallman committed
584
  "Function to actually send to PROCESS the STRING submitted by user.
585
Usually this is just `term-simple-send', but if your mode needs to
586
massage the input string, this is your hook.  This is called from
587
the user command `term-send-input'.  `term-simple-send' just sends
Richard M. Stallman's avatar
Richard M. Stallman committed
588 589
the string plus a newline.")

590
(defcustom term-eol-on-send t
Lute Kamstra's avatar
Lute Kamstra committed
591
  "Non-nil means go to the end of the line before sending input.
592 593 594
See `term-send-input'."
  :type 'boolean
  :group 'term)
595

596
(defcustom term-mode-hook '()
597
  "Called upon entry into term mode.
598 599 600
This is run before the process is cranked up."
  :type 'hook
  :group 'term)
Richard M. Stallman's avatar
Richard M. Stallman committed
601

602
(defcustom term-exec-hook '()
603
  "Called each time a process is exec'd by `term-exec'.
Richard M. Stallman's avatar
Richard M. Stallman committed
604
This is called after the process is cranked up.  It is useful for things that
605
must be done each time a process is executed in a term mode buffer (e.g.,
606 607
`set-process-query-on-exit-flag').  In contrast, `term-mode-hook' is only
executed once, when the buffer is created."
608 609
  :type 'hook
  :group 'term)
Richard M. Stallman's avatar
Richard M. Stallman committed
610

Lute Kamstra's avatar
Lute Kamstra committed
611
(defvar term-mode-map
612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640
  (let ((map (make-sparse-keymap)))
    (define-key map "\ep" 'term-previous-input)
    (define-key map "\en" 'term-next-input)
    (define-key map "\er" 'term-previous-matching-input)
    (define-key map "\es" 'term-next-matching-input)
    (unless (featurep 'xemacs)
      (define-key map [?\A-\M-r]
	'term-previous-matching-input-from-input)
      (define-key map [?\A-\M-s] 'term-next-matching-input-from-input))
    (define-key map "\e\C-l" 'term-show-output)
    (define-key map "\C-m" 'term-send-input)
    (define-key map "\C-d" 'term-delchar-or-maybe-eof)
    (define-key map "\C-c\C-a" 'term-bol)
    (define-key map "\C-c\C-u" 'term-kill-input)
    (define-key map "\C-c\C-w" 'backward-kill-word)
    (define-key map "\C-c\C-c" 'term-interrupt-subjob)
    (define-key map "\C-c\C-z" 'term-stop-subjob)
    (define-key map "\C-c\C-\\" 'term-quit-subjob)
    (define-key map "\C-c\C-m" 'term-copy-old-input)
    (define-key map "\C-c\C-o" 'term-kill-output)
    (define-key map "\C-c\C-r" 'term-show-output)
    (define-key map "\C-c\C-e" 'term-show-maximum-output)
    (define-key map "\C-c\C-l" 'term-dynamic-list-input-ring)
    (define-key map "\C-c\C-n" 'term-next-prompt)
    (define-key map "\C-c\C-p" 'term-previous-prompt)
    (define-key map "\C-c\C-d" 'term-send-eof)
    (define-key map "\C-c\C-k" 'term-char-mode)
    (define-key map "\C-c\C-j" 'term-line-mode)
    (define-key map "\C-c\C-q" 'term-pager-toggle)
Glenn Morris's avatar
Glenn Morris committed
641 642 643 644 645 646 647
    ;; completion: (line mode only)
    (easy-menu-define nil map "Complete menu for Term mode."
      '("Complete"
        ["Complete Before Point" term-dynamic-complete t]
        ["Complete File Name" term-dynamic-complete-filename t]
        ["File Completion Listing" term-dynamic-list-filename-completions t]
        ["Expand File Name" term-replace-by-expanded-filename t]))
648
    ;; Input history: (line mode only)
Glenn Morris's avatar
Glenn Morris committed
649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671
    (easy-menu-define nil map "In/Out menu for Term mode."
      '("In/Out"
        ["Expand History Before Point" term-replace-by-expanded-history
         term-input-autoexpand]
        ["List Input History" term-dynamic-list-input-ring t]
        ["Previous Input" term-previous-input t]
        ["Next Input" term-next-input t]
        ["Previous Matching Current Input"
          term-previous-matching-input-from-input t]
        ["Next Matching Current Input" term-next-matching-input-from-input t]
        ["Previous Matching Input..." term-previous-matching-input t]
        ["Next Matching Input..." term-next-matching-input t]
        ["Backward Matching Input..." term-backward-matching-input t]
        ["Forward Matching Input..." term-forward-matching-input t]
        ["Copy Old Input" term-copy-old-input t]
        ["Kill Current Input" term-kill-input t]
        ["Show Current Output Group" term-show-output t]
        ["Show Maximum Output" term-show-maximum-output t]
        ["Backward Output Group" term-previous-prompt t]
        ["Forward Output Group" term-next-prompt t]
        ["Kill Current Output Group" term-kill-output t]))
    map)
  "Keymap for Term mode.")
672

673
(defvar term-escape-char nil
674
  "Escape character for char sub-mode of term mode.
675
Do not change it directly; use `term-set-escape-char' instead.")
Richard M. Stallman's avatar
Richard M. Stallman committed
676

Glenn Morris's avatar
Glenn Morris committed
677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695
(defvar term-pager-break-map
  (let ((map (make-keymap)))
    ;; (dotimes (i 128)
    ;;   (define-key map (make-string 1 i) 'term-send-raw))
    (define-key map "\e" (lookup-key (current-global-map) "\e"))
    (define-key map "\C-x" (lookup-key (current-global-map) "\C-x"))
    (define-key map "\C-u" (lookup-key (current-global-map) "\C-u"))
    (define-key map " " 'term-pager-page)
    (define-key map "\r" 'term-pager-line)
    (define-key map "?" 'term-pager-help)
    (define-key map "h" 'term-pager-help)
    (define-key map "b" 'term-pager-back-page)
    (define-key map "\177" 'term-pager-back-line)
    (define-key map "q" 'term-pager-discard)
    (define-key map "D" 'term-pager-disable)
    (define-key map "<" 'term-pager-bob)
    (define-key map ">" 'term-pager-eob)
    map)
  "Keymap used in Term pager mode.")
Richard M. Stallman's avatar
Richard M. Stallman committed
696 697 698

(defvar term-ptyp t
  "True if communications via pty; false if by pipe.  Buffer local.
699
This is to work around a bug in Emacs process signaling.")
Richard M. Stallman's avatar
Richard M. Stallman committed
700 701 702

(defvar term-last-input-match ""
  "Last string searched for by term input history search, for defaulting.
703
Buffer local variable.")
Richard M. Stallman's avatar
Richard M. Stallman committed
704 705 706 707 708 709 710 711 712

(defvar term-input-ring nil)
(defvar term-last-input-start)
(defvar term-last-input-end)
(defvar term-input-ring-index nil
  "Index of last matched history element.")
(defvar term-matching-input-from-input-string ""
  "Input previously used to match input history.")
; This argument to set-process-filter disables reading from the process,
713
; assuming this is Emacs 19.20 or newer.
Richard M. Stallman's avatar
Richard M. Stallman committed
714 715 716 717 718 719 720 721 722 723 724 725
(defvar term-pager-filter t)

(put 'term-input-ring 'permanent-local t)
(put 'term-input-ring-index 'permanent-local t)
(put 'term-input-autoexpand 'permanent-local t)
(put 'term-input-filter-functions 'permanent-local t)
(put 'term-scroll-to-bottom-on-output 'permanent-local t)
(put 'term-scroll-show-maximum-output 'permanent-local t)
(put 'term-ptyp 'permanent-local t)

(defmacro term-in-char-mode () '(eq (current-local-map) term-raw-map))
(defmacro term-in-line-mode () '(not (term-in-char-mode)))
726 727 728 729 730
;; True if currently doing PAGER handling.
(defmacro term-pager-enabled () 'term-pager-count)
(defmacro term-handling-pager () 'term-pager-old-local-map)
(defmacro term-using-alternate-sub-buffer () 'term-saved-home-marker)

731
;; Let's silence the byte-compiler -mm
732 733 734 735 736 737 738
(defvar term-ansi-at-host nil)
(defvar term-ansi-at-dir nil)
(defvar term-ansi-at-user nil)
(defvar term-ansi-at-message nil)
(defvar term-ansi-at-save-user nil)
(defvar term-ansi-at-save-pwd nil)
(defvar term-ansi-at-save-anon nil)
739
(defvar term-ansi-current-bold nil)
740
(defvar term-ansi-current-color 0)
741
(defvar term-ansi-face-already-done nil)
742
(defvar term-ansi-current-bg-color 0)
743 744 745
(defvar term-ansi-current-underline nil)
(defvar term-ansi-current-reverse nil)
(defvar term-ansi-current-invisible nil)
746

747 748
;;; Faces
(defvar ansi-term-color-vector
749
  [term
750 751 752 753 754 755 756 757 758 759
   term-color-black
   term-color-red
   term-color-green
   term-color-yellow
   term-color-blue
   term-color-magenta
   term-color-cyan
   term-color-white])

(defcustom term-default-fg-color nil
760
  "If non-nil, default color for foreground in Term mode."
761
  :group 'term
762
  :type '(choice (const nil) (string :tag "color")))
763 764
(make-obsolete-variable 'term-default-fg-color "use the face `term' instead."
                        "24.3")
765

766
(defcustom term-default-bg-color nil
767
  "If non-nil, default color for foreground in Term mode."
768
  :group 'term
769
  :type '(choice (const nil) (string :tag "color")))
770 771
(make-obsolete-variable 'term-default-bg-color "use the face `term' instead."
                        "24.3")
772

773
(defface term
774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829
  `((t
     :foreground ,term-default-fg-color
     :background ,term-default-bg-color
     :inherit default))
  "Default face to use in Term mode."
  :group 'term)

(defface term-bold
  '((t :bold t))
  "Default face to use for bold text."
  :group 'term)

(defface term-underline
  '((t :underline t))
  "Default face to use for underlined text."
  :group 'term)

(defface term-color-black
  '((t :foreground "black" :background "black"))
  "Face used to render black color code."
  :group 'term)

(defface term-color-red
  '((t :foreground "red3" :background "red3"))
  "Face used to render red color code."
  :group 'term)

(defface term-color-green
  '((t :foreground "green3" :background "green3"))
  "Face used to render green color code."
  :group 'term)

(defface term-color-yellow
  '((t :foreground "yellow3" :background "yellow3"))
  "Face used to render yellow color code."
  :group 'term)

(defface term-color-blue
  '((t :foreground "blue2" :background "blue2"))
  "Face used to render blue color code."
  :group 'term)

(defface term-color-magenta
  '((t :foreground "magenta3" :background "magenta3"))
  "Face used to render magenta color code."
  :group 'term)

(defface term-color-cyan
  '((t :foreground "cyan3" :background "cyan3"))
  "Face used to render cyan color code."
  :group 'term)

(defface term-color-white
  '((t :foreground "white" :background "white"))
  "Face used to render white color code."
  :group 'term)
830

831
;; Inspiration came from comint.el -mm
832 833
(defcustom term-buffer-maximum-size 2048
  "The maximum size in lines for term buffers.
834
Term buffers are truncated from the top to be no greater than this number.
835
Notice that a setting of 0 means \"don't truncate anything\".  This variable
836 837 838
is buffer-local."
  :group 'term
  :type 'integer)
839 840 841

;; Set up term-raw-map, etc.

842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858
(defvar term-raw-map
  (let* ((map (make-keymap))
         (esc-map (make-keymap))
         (i 0))
    (while (< i 128)
      (define-key map (make-string 1 i) 'term-send-raw)
      ;; Avoid O and [. They are used in escape sequences for various keys.
      (unless (or (eq i ?O) (eq i 91))
        (define-key esc-map (make-string 1 i) 'term-send-raw-meta))
      (setq i (1+ i)))
    (define-key map [remap self-insert-command] 'term-send-raw)
    (define-key map "\e" esc-map)

    ;; Added nearly all the 'gray keys' -mm

    (if (featurep 'xemacs)
        (define-key map [button2] 'term-mouse-paste)
Glenn Morris's avatar
Glenn Morris committed
859
      (define-key map [mouse-2] 'term-mouse-paste))
860 861 862 863
    (define-key map [up] 'term-send-up)
    (define-key map [down] 'term-send-down)
    (define-key map [right] 'term-send-right)
    (define-key map [left] 'term-send-left)
864 865 866 867
    (define-key map [C-up] 'term-send-ctrl-up)
    (define-key map [C-down] 'term-send-ctrl-down)
    (define-key map [C-right] 'term-send-ctrl-right)
    (define-key map [C-left] 'term-send-ctrl-left)
868 869 870 871 872 873 874 875 876 877 878
    (define-key map [delete] 'term-send-del)
    (define-key map [deletechar] 'term-send-del)
    (define-key map [backspace] 'term-send-backspace)
    (define-key map [home] 'term-send-home)
    (define-key map [end] 'term-send-end)
    (define-key map [insert] 'term-send-insert)
    (define-key map [S-prior] 'scroll-down)
    (define-key map [S-next] 'scroll-up)
    (define-key map [S-insert] 'term-paste)
    (define-key map [prior] 'term-send-prior)
    (define-key map [next] 'term-send-next)
879
    (define-key map [xterm-paste] #'term--xterm-paste)
880 881 882
    map)
  "Keyboard map for sending characters directly to the inferior process.")

Glenn Morris's avatar
Glenn Morris committed
883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922
(easy-menu-define term-terminal-menu
  (list term-mode-map term-raw-map term-pager-break-map)
  "Terminal menu for Term mode."
  '("Terminal"
    ["Line mode" term-line-mode :active (term-in-char-mode)
     :help "Switch to line (cooked) sub-mode of term mode"]
    ["Character mode" term-char-mode :active (term-in-line-mode)
     :help "Switch to char (raw) sub-mode of term mode"]
    ["Paging" term-pager-toggle :style toggle :selected term-pager-count
     :help "Toggle paging feature"]))

(easy-menu-define term-signals-menu
  (list term-mode-map term-raw-map term-pager-break-map)
  "Signals menu for Term mode."
  '("Signals"
    ["BREAK" term-interrupt-subjob :active t
     :help "Interrupt the current subjob"]
    ["STOP" term-stop-subjob :active t :help "Stop the current subjob"]
    ["CONT" term-continue-subjob :active t
     :help "Send CONT signal to process buffer's process group"]
    ["QUIT" term-quit-subjob :active t
     :help "Send quit signal to the current subjob"]
    ["KILL" term-kill-subjob :active t
     :help "Send kill signal to the current subjob"]
    ["EOF" term-send-eof :active t
     :help "Send an EOF to the current buffer's process"]))

(easy-menu-define term-pager-menu term-pager-break-map
  "Menu for Term pager mode."
  '("More pages?"
    ["1 page forwards" term-pager-page t]
    ["1 page backwards" term-pager-back-page t]
    ["1 line backwards" term-pager-back-line t]
    ["1 line forwards" term-pager-line t]
    ["Goto to beginning" term-pager-bob t]
    ["Goto to end" term-pager-eob t]
    ["Discard remaining output" term-pager-discard t]
    ["Disable paging" term-pager-toggle t]
    ["Help" term-pager-help t]))

923 924 925 926 927 928 929 930 931 932 933 934 935 936
(defvar term-raw-escape-map
  (let ((map (make-sparse-keymap)))
    (set-keymap-parent map 'Control-X-prefix)
    ;; Define standard bindings in term-raw-escape-map.
    (define-key map "\C-v" (lookup-key (current-global-map) "\C-v"))
    (define-key map "\C-u" (lookup-key (current-global-map) "\C-u"))
    (define-key map "\C-q" 'term-pager-toggle)
    ;; The keybinding for term-char-mode is needed by the menubar code.
    (define-key map "\C-k" 'term-char-mode)
    (define-key map "\C-j" 'term-line-mode)
    ;; It's convenient to have execute-extended-command here.
    (define-key map [?\M-x] 'execute-extended-command)
    map))

937
(defun term-set-escape-char (key)
938
  "Change `term-escape-char' and keymaps that depend on it."
939
  (when term-escape-char
940
    ;; Undo previous term-set-escape-char.
941
    (define-key term-raw-map term-escape-char 'term-send-raw))
942
  (setq term-escape-char (if (vectorp key) key (vector key)))
943 944 945
  (define-key term-raw-map term-escape-char term-raw-escape-map)
  ;; FIXME: If we later call term-set-escape-char again with another key,
  ;; we should undo this binding.
946
  (define-key term-raw-escape-map term-escape-char 'term-send-raw))
947

948
(term-set-escape-char (or term-escape-char ?\C-c))
Kenichi Handa's avatar
Kenichi Handa committed
949

950 951 952

(put 'term-mode 'mode-class 'special)

953

954
;; Use this variable as a display table for `term-mode'.
955 956 957 958 959
(defvar term-display-table
  (let ((dt (or (copy-sequence standard-display-table)
		(make-display-table)))
        i)
    ;; avoid changing the display table for ^J
960
    (setq i 0)
961 962 963
    (while (< i 10)
      (aset dt i (vector i))
      (setq i (1+ i)))
964
    (setq i 11)
965 966 967 968 969 970 971 972 973
    (while (< i 32)
      (aset dt i (vector i))
      (setq i (1+ i)))
    (setq i 128)
    (while (< i 256)
      (aset dt i (vector i))
      (setq i (1+ i)))
    dt))

Stefan Monnier's avatar
Stefan Monnier committed
974
(defun term-ansi-reset ()
975
  (setq term-current-face 'term)
Stefan Monnier's avatar
Stefan Monnier committed
976 977 978 979 980
  (setq term-ansi-current-underline nil)
  (setq term-ansi-current-bold nil)
  (setq term-ansi-current-reverse nil)
  (setq term-ansi-current-color 0)
  (setq term-ansi-current-invisible nil)
981 982 983 984
  ;; Stefan thought this should be t, but could not remember why.
  ;; Setting it to t seems to cause bug#11785.  Setting it to nil
  ;; again to see if there are other consequences...
  (setq term-ansi-face-already-done nil)
Stefan Monnier's avatar
Stefan Monnier committed
985 986
  (setq term-ansi-current-bg-color 0))

987
(define-derived-mode term-mode fundamental-mode "Term"
988 989 990 991 992
  "Major mode for interacting with an inferior interpreter.
The interpreter name is same as buffer name, sans the asterisks.

There are two submodes: line mode and char mode.  By default, you are
in char mode.  In char sub-mode, each character (except
993 994
`term-escape-char') is sent immediately to the subprocess.
The escape character is equivalent to the usual meaning of C-x.
995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014

In line mode, you send a line of input at a time; use
\\[term-send-input] to send.

In line mode, this maintains an input history of size
`term-input-ring-size', and you can access it with the commands
\\[term-next-input], \\[term-previous-input], and
\\[term-dynamic-list-input-ring].  Input ring history expansion can be
achieved with the commands \\[term-replace-by-expanded-history] or
\\[term-magic-space].  Input ring expansion is controlled by the
variable `term-input-autoexpand', and addition is controlled by the
variable `term-input-ignoredups'.

Input to, and output from, the subprocess can cause the window to scroll to
the end of the buffer.  See variables `term-scroll-to-bottom-on-input',
and `term-scroll-to-bottom-on-output'.

If you accidentally suspend your process, use \\[term-continue-subjob]
to continue it.

1015
This mode can be customized to create specific modes for running
1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028
particular subprocesses.  This can be done by setting the hooks
`term-input-filter-functions', `term-input-filter',
`term-input-sender' and `term-get-old-input' to appropriate functions,
and the variable `term-prompt-regexp' to the appropriate regular
expression.

Commands in raw mode:

\\{term-raw-map}

Commands in line mode:

\\{term-mode-map}
Richard M. Stallman's avatar
Richard M. Stallman committed
1029

1030
Entry to this mode runs the hooks on `term-mode-hook'."
1031 1032 1033
  ;; we do not want indent to sneak in any tabs
  (setq indent-tabs-mode nil)
  (setq buffer-display-table term-display-table)
1034
  (set (make-local-variable 'term-home-marker) (copy-marker 0))
1035
  (set (make-local-variable 'term-height) (floor (window-screen-lines)))
1036
  (set (make-local-variable 'term-width) (window-max-chars-per-line))
1037 1038 1039 1040 1041
  (set (make-local-variable 'term-last-input-start) (make-marker))
  (set (make-local-variable 'term-last-input-end) (make-marker))
  (set (make-local-variable 'term-last-input-match) "")

  ;; These local variables are set to their local values:
1042 1043
  (make-local-variable 'term-saved-home-marker)
  (make-local-variable 'term-saved-cursor)
1044 1045
  (make-local-variable 'term-prompt-regexp)
  (make-local-variable 'term-input-ring-size)
1046 1047 1048
  (make-local-variable 'term-input-ring)
  (make-local-variable 'term-input-ring-file-name)
  (make-local-variable 'term-input-ring-index)
1049 1050
  (unless term-input-ring
    (setq term-input-ring (make-ring term-input-ring-size)))
1051

1052 1053 1054 1055
  ;; I'm not sure these saves are necessary but, since I
  ;; haven't tested the whole thing on a net connected machine with
  ;; a properly configured ange-ftp, I've decided to be conservative
  ;; and put them in. -mm
1056

1057 1058 1059
  (set (make-local-variable 'term-ansi-at-host) (system-name))
  (set (make-local-variable 'term-ansi-at-dir) default-directory)
  (set (make-local-variable 'term-ansi-at-message) nil)
1060

1061
  ;; For user tracking purposes -mm
1062 1063 1064 1065
  (make-local-variable 'ange-ftp-default-user)
  (make-local-variable 'ange-ftp-default-password)
  (make-local-variable 'ange-ftp-generate-anonymous-password)

1066
  ;; You may want to have different scroll-back sizes -mm
1067 1068
  (make-local-variable 'term-buffer-maximum-size)

1069
  ;; Of course these have to be buffer-local -mm
1070 1071 1072 1073 1074 1075 1076 1077
  (make-local-variable 'term-ansi-current-bold)
  (make-local-variable 'term-ansi-current-color)
  (make-local-variable 'term-ansi-face-already-done)
  (make-local-variable 'term-ansi-current-bg-color)
  (make-local-variable 'term-ansi-current-underline)
  (make-local-variable 'term-ansi-current-reverse)
  (make-local-variable 'term-ansi-current-invisible)

1078
  (make-local-variable 'term-terminal-undecoded-bytes)
1079

1080
  (make-local-variable 'term-do-line-wrapping)
1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101
  (make-local-variable 'term-kill-echo-list)
  (make-local-variable 'term-start-line-column)
  (make-local-variable 'term-current-column)
  (make-local-variable 'term-current-row)
  (make-local-variable 'term-log-buffer)
  (make-local-variable 'term-pager-count)
  (make-local-variable 'term-pager-old-local-map)
  (make-local-variable 'term-old-mode-map)
  (make-local-variable 'term-insert-mode)
  (make-local-variable 'term-completion-fignore)
  (make-local-variable 'term-get-old-input)
  (make-local-variable 'term-matching-input-from-input-string)
  (make-local-variable 'term-input-autoexpand)
  (make-local-variable 'term-input-ignoredups)
  (make-local-variable 'term-delimiter-argument-list)
  (make-local-variable 'term-input-filter)
  (make-local-variable 'term-input-sender)
  (make-local-variable 'term-eol-on-send)
  (make-local-variable 'term-scroll-to-bottom-on-output)
  (make-local-variable 'term-scroll-show-maximum-output)
  (make-local-variable 'term-ptyp)
1102
  (set (make-local-variable 'term-vertical-motion) 'vertical-motion)
1103
  (set (make-local-variable 'term-pending-delete-marker) (make-marker))
1104
  (make-local-variable 'term-current-face)
Stefan Monnier's avatar
Stefan Monnier committed
1105
  (term-ansi-reset)
1106
  (set (make-local-variable 'term-pending-frame) nil)
1107
  ;; Cua-mode's keybindings interfere with the term keybindings, disable it.
1108
  (set (make-local-variable 'cua-mode) nil)
1109 1110 1111

  (set (make-local-variable 'font-lock-defaults) '(nil t))

1112 1113 1114
  (add-function :filter-return
                (local 'filter-buffer-substring-function)
                #'term--filter-buffer-substring)
1115 1116 1117 1118 1119
  (add-function :filter-return
                (local 'window-adjust-process-window-size-function)
                (lambda (size)
                  (when size
                    (term-reset-size (cdr size) (car size)))
Noam Postavsky's avatar
Noam Postavsky committed
1120 1121
                  size)
                '((name . term-maybe-reset-size)))
1122

1123 1124
  (add-hook 'read-only-mode-hook #'term-line-mode-buffer-read-only-update nil t)

1125 1126
  (term--reset-scroll-region)

Glenn Morris's avatar
Glenn Morris committed
1127 1128
  (easy-menu-add term-terminal-menu)
  (easy-menu-add term-signals-menu)
1129 1130 1131 1132
  (or term-input-ring
      (setq term-input-ring (make-ring term-input-ring-size)))
  (term-update-mode-line))

1133 1134 1135 1136 1137 1138
(defun term--remove-fake-newlines ()
  (goto-char (point-min))
  (let (fake-newline)
    (while (setq fake-newline (next-single-property-change (point)
                                                           'term-line-wrap))
      (goto-char fake-newline)
1139
      (cl-assert (eq ?\n (char-after)))
1140 1141 1142
      (let ((inhibit-read-only t))
        (delete-char 1)))))

1143 1144 1145
(defun term--last-line ()
  (1- term-height))

1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173
(defun term--filter-buffer-substring (content)
  (with-temp-buffer
    (insert content)
    (term--remove-fake-newlines)
    (buffer-string)))

(defun term--unwrap-visible-long-lines (width)
  ;; Unwrap lines longer than width using fake newlines.  Only do it
  ;; for lines that are currently visible (i.e. following the home
  ;; marker).  Invisible lines don't have to be unwrapped since they
  ;; are unreachable using the cursor movement anyway.  Not having to
  ;; unwrap the entire buffer means the runtime of this function is
  ;; bounded by the size of the screen instead of the buffer size.

  (save-excursion
    ;; We will just assume that our accounting for the home marker is
    ;; correct, i.e. programs will not try to reach any position
    ;; earlier than this marker.
    (goto-char term-home-marker)

    (move-to-column width)
    (while (not (eobp))
      (if (eolp)
          (forward-char)
        (let ((inhibit-read-only t))
          (term-unwrap-line)))
      (move-to-column width))))

Richard M. Stallman's avatar
Richard M. Stallman committed
1174
(defun term-reset-size (height width)
1175 1176
  (when (or (/= height term-height)
            (/= width term-width))
1177 1178 1179 1180
    ;; Delete all newlines used for wrapping
    (when (/= width term-width)
      (save-excursion
        (term--remove-fake-newlines)))
1181 1182 1183 1184 1185 1186
    (let ((point (point)))
      (setq term-height height)
      (setq term-width width)
      (setq term-start-line-column nil)
      (setq term-current-row nil)
      (setq term-current-column nil)
1187
      (term--reset-scroll-region)
1188 1189 1190 1191 1192
      ;; `term-set-scroll-region' causes these to be set, we have to
      ;; clear them again since we're changing point (Bug#30544).
      (setq term-start-line-column nil)
      (setq term-current-row nil)
      (setq term-current-column nil)
1193 1194
      (goto-char point))
    (term--unwrap-visible-long-lines width)))
Richard M. Stallman's avatar
Richard M. Stallman committed
1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212

;; Recursive routine used to check if any string in term-kill-echo-list
;; matches part of the buffer before point.
;; If so, delete that matched part of the buffer - this suppresses echo.
;; Also, remove that string from the term-kill-echo-list.
;; We *also* remove any older string on the list, as a sanity measure,
;; in case something gets out of sync.  (Except for type-ahead, there
;; should only be one element in the list.)

(defun term-check-kill-echo-list ()
  (let ((cur term-kill-echo-list) (found nil) (save-point (point)))
    (unwind-protect
	(progn
	  (end-of-line)
	  (while cur
	    (let* ((str (car cur)) (len (length str)) (start (- (point) len)))
	      (if (and (>= start (point-min))
		       (string= str (buffer-substring start (point))))
1213
		  (progn (delete-char (- len))
Richard M. Stallman's avatar
Richard M. Stallman committed
1214 1215 1216 1217 1218 1219
			 (setq term-kill-echo-list (cdr cur))
			 (setq term-current-column nil)
			 (setq term-current-row nil)
			 (setq term-start-line-column nil)
			 (setq cur nil found t))
		(setq cur (cdr cur))))))
1220 1221
      (when (not found)
	(goto-char save-point)))
Richard M. Stallman's avatar
Richard M. Stallman committed
1222 1223 1224
    found))

(defun term-send-raw-string (chars)
1225
  (deactivate-mark)
Richard M. Stallman's avatar
Richard M. Stallman committed
1226 1227 1228 1229 1230 1231
  (let ((proc (get-buffer-process (current-buffer))))
    (if (not proc)
	(error "Current buffer has no process")
      ;; Note that (term-current-row) must be called *after*
      ;; (point) has been updated to (process-mark proc).
      (goto-char (process-mark proc))
1232 1233
      (when (term-pager-enabled)
	(setq term-pager-count (term-current-row)))
1234
      (process-send-string proc chars))))
Richard M. Stallman's avatar
Richard M. Stallman committed
1235 1236 1237

(defun term-send-raw ()
  "Send the last character typed through the terminal-emulator
1238
without any interpretation."
Richard M. Stallman's avatar
Richard M. Stallman committed
1239
  (interactive)
Stefan Monnier's avatar
Stefan Monnier committed
1240 1241
  (let ((keys (this-command-keys)))
    (term-send-raw-string (string (aref keys (1- (length keys)))))))
Richard M. Stallman's avatar
Richard M. Stallman committed
1242 1243 1244

(defun term-send-raw-meta ()
  (interactive)
1245
  (let ((char last-input-event))
1246
    (when (symbolp char)
1247 1248
      ;; Convert `return' to C-m, etc.
      (let ((tmp (get char 'event-symbol-elements)))
1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260
	(if tmp (setq char (car tmp)))
	(and (symbolp char)
	     (setq tmp (get char 'ascii-character))
	     (setq char tmp))))
    (when (numberp char)
      (let ((base (event-basic-type char))
	    (mods (delq 'meta (event-modifiers char))))
	(if (memq 'control mods)
	    (setq mods (delq 'shift mods)))
	(term-send-raw-string
	 (format "\e%c"
		 (event-convert-list (append mods (list base)))))))))
Richard M. Stallman's avatar
Richard M. Stallman committed
1261

1262 1263 1264
(defun term-mouse-paste (click)
  "Insert the primary selection at the position clicked on."
  (interactive "e")
1265
  (if (featurep 'xemacs)
1266
      (term-send-raw-string
1267
       (or (condition-case () (x-get-selection) (error ()))
1268
	   (error "No selection available")))
1269 1270 1271 1272
    ;; Give temporary modes such as isearch a chance to turn off.
    (run-hooks 'mouse-leave-buffer-hook)
    (setq this-command 'yank)
    (mouse-set-point click)
1273
    (term-send-raw-string (gui-get-primary-selection))))
Richard M. Stallman's avatar
Richard M. Stallman committed
1274

1275 1276 1277 1278 1279
(defun term-paste ()
  "Insert the last stretch of killed text at point."
  (interactive)
   (term-send-raw-string (current-kill 0)))

1280 1281 1282 1283 1284 1285 1286
(defun term--xterm-paste ()
  "Insert the text pasted in an XTerm bracketed paste operation."
  (interactive)
  (term-send-raw-string (xterm--pasted-text)))

(declare-function xterm--pasted-text "term/xterm" ())

Richard M. Stallman's avatar
Richard M. Stallman committed
1287
;; Which would be better:  "\e[A" or "\eOA"? readline accepts either.
1288 1289
;; For my configuration it's definitely better \eOA but YMMV. -mm
;; For example: vi works with \eOA while elm wants \e[A ...
1290
;; (terminfo: kcuu1, kcud1, kcuf1, kcub1, khome, kend, kpp, knp, kdch1, kbs)
1291 1292 1293 1294
(defun term-send-up    () (interactive) (term-send-raw-string "\eOA"))
(defun term-send-down  () (interactive) (term-send-raw-string "\eOB"))
(defun term-send-right () (interactive) (term-send-raw-string "\eOC"))
(defun term-send-left  () (interactive) (term-send-raw-string "\eOD"))
1295 1296 1297 1298
(defun term-send-ctrl-up    () (interactive) (term-send-raw-string "\e[1;5A"))
(defun term-send-ctrl-down  () (interactive) (term-send-raw-string "\e[1;5B"))
(defun term-send-ctrl-right () (interactive) (term-send-raw-string "\e[1;5C"))
(defun term-send-ctrl-left  () (interactive) (term-send-raw-string "\e[1;5D"))
1299
(defun term-send-home  () (interactive) (term-send-raw-string "\e[1~"))
1300
(defun term-send-insert() (interactive) (term-send-raw-string "\e[2~"))
1301
(defun term-send-end   () (interactive) (term-send-raw-string "\e[4~"))
1302 1303
(defun term-send-prior () (interactive) (term-send-raw-string "\e[5~"))
(defun term-send-next  () (interactive) (term-send-raw-string "\e[6~"))
1304 1305
(defun term-send-del   () (interactive) (term-send-raw-string "\e[3~"))
(defun term-send-backspace  () (interactive) (term-send-raw-string "\C-?"))
1306

Richard M. Stallman's avatar
Richard M. Stallman committed
1307
(defun term-char-mode ()
1308 1309
  "Switch to char (\"raw\") sub-mode of term mode.
Each character you type is sent directly to the inferior without
1310
intervention from Emacs, except for the escape character (usually C-c)."
Richard M. Stallman's avatar
Richard M. Stallman committed
1311 1312
  (interactive)
  ;; FIXME: Emit message? Cfr ilisp-raw-message
1313 1314 1315
  (when (term-in-line-mode)
    (setq term-old-mode-map (current-local-map))
    (use-local-map term-raw-map)
Glenn Morris's avatar
Glenn Morris committed
1316 1317
    (easy-menu-add term-terminal-menu)
    (easy-menu-add term-signals-menu)
1318

1319 1320 1321 1322 1323 1324 1325
    ;; Don't allow changes to the buffer or to point which are not
    ;; caused by the process filter.
    (when term-char-mode-buffer-read-only
      (setq buffer-read-only t))
    (add-hook 'pre-command-hook #'term-set-goto-process-mark nil t)
    (add-hook 'post-command-hook #'term-goto-process-mark-maybe nil t)

1326
    ;; Send existing partial line to inferior (without newline).
1327
    (let ((pmark (process-mark (get-buffer-process (current-buffer)))))
1328 1329 1330
      (when (> (point) pmark)
	(unwind-protect
	    (progn
1331
	      (add-function :override term-input-sender #'term-send-string)
1332 1333
	      (end-of-line)
	      (term-send-input))
1334
	  (remove-function term-input-sender #'term-send-string))))
1335
    (term-update-mode-line)))
Richard M. Stallman's avatar
Richard M. Stallman committed
1336 1337

(defun term-line-mode  ()
1338
  "Switch to line (\"cooked\") sub-mode of term mode.
1339
This means that Emacs editing commands work as normally, until
1340
you type \\[term-send-input] which sends the current line to the inferior."
Richard M. Stallman's avatar
Richard M. Stallman committed
1341
  (interactive)
1342
  (when (term-in-char-mode)
1343 1344 1345 1346
    (when term-char-mode-buffer-read-only
      (setq buffer-read-only term-line-mode-buffer-read-only))
    (remove-hook 'pre-command-hook #'term-set-goto-process-mark t)
    (remove-hook 'post-command-hook #'term-goto-process-mark-maybe t)
1347 1348
    (use-local-map term-old-mode-map)
    (term-update-mode-line)))
1349

1350 1351 1352 1353 1354 1355 1356
(defun term-line-mode-buffer-read-only-update ()
  "Update the user-set state of `buffer-read-only' in `term-line-mode'.

Called as a buffer-local `read-only-mode-hook' function."
  (when (term-in-line-mode)
    (setq term-line-mode-buffer-read-only buffer-read-only)))

1357
(defun term-update-mode-line ()
Glenn Morris's avatar
Glenn Morris committed
1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382
  (let ((term-mode
         (if (term-in-char-mode)
             (propertize "char"
                         'help-echo "mouse-1: Switch to line mode"
                         'mouse-face 'mode-line-highlight
                         'local-map
                         '(keymap
                           (mode-line keymap (down-mouse-1 . term-line-mode))))
           (propertize "line"
                       'help-echo "mouse-1: Switch to char mode"
                       'mouse-face 'mode-line-highlight
                       'local-map
                       '(keymap
                         (mode-line keymap (down-mouse-1 . term-char-mode))))))
        (term-page
         (when (term-pager-enabled)
           (concat " "
                   (propertize
                    "page"
                    'help-echo "mouse-1: Disable paging"
                    'mouse-face 'mode-line-highlight
                    'local-map
                    '(keymap
                      (mode-line keymap (down-mouse-1 .
                                                      term-pager-toggle)))))))
1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408
        (serial-item-speed)
        (serial-item-config)
        (proc (get-buffer-process (current-buffer))))
    (when (and (term-check-proc (current-buffer))
               (equal (process-type nil) 'serial))
      (let ((temp (serial-speed)))
        (setq serial-item-speed
            `(:propertize
              ,(or (and temp (format " %d" temp)) "")
              help-echo "mouse-1: Change the speed of the serial port"
              mouse-face mode-line-highlight
              local-map (keymap (mode-line keymap
                                (down-mouse-1 . serial-mode-line-speed-menu-1))))))
      (let ((temp (process-contact proc :summary)))
        (setq serial-item-config
              `(:propertize
                ,(or (and temp (format " %s" temp)) "")
                help-echo "mouse-1: Change the configuration of the serial port"
                mouse-face mode-line-highlight
                local-map (keymap (mode-line keymap
                           (down-mouse-1 . serial-mode-line-config-menu-1)))))))
    (setq mode-line-process
          (list ": " term-mode term-page
                serial-item-speed
                serial-item-config
                " %s")))
1409
  (force-mode-line-update))
Richard M. Stallman's avatar
Richard M. Stallman committed
1410 1411

(defun term-check-proc (buffer)
1412 1413
  "True if there is a process associated w/buffer BUFFER, and it
is alive.  BUFFER can be either a buffer or the name of one."
Richard M. Stallman's avatar
Richard M. Stallman committed
1414
  (let ((proc (get-buffer-process buffer)))
1415
    (and proc (memq (process-status proc) '(run stop open listen connect)))))
Richard M. Stallman's avatar
Richard M. Stallman committed
1416 1417 1418 1419 1420 1421

;;;###autoload
(defun make-term (name program &optional startfile &rest switches)
"Make a term process NAME in a buffer, running PROGRAM.
The name of the buffer is made by surrounding NAME with `*'s.
If there is already a running process in that buffer, it is not restarted.
1422
Optional third arg STARTFILE is the name of a file to send the contents of to
Richard M. Stallman's avatar
Richard M. Stallman committed
1423 1424 1425
the process.  Any more args are arguments to PROGRAM."
  (let ((buffer (get-buffer-create (concat "*" name "*"))))
    ;; If no process, or nuked process, crank up a new one and put buffer in
1426
    ;; term mode.  Otherwise, leave buffer and existing process alone.
Richard M. Stallman's avatar
Richard M. Stallman committed
1427
    (cond ((not (term-check-proc buffer))