diff options
| author | Karoly Lorentey | 2005-12-22 21:02:45 +0000 |
|---|---|---|
| committer | Karoly Lorentey | 2005-12-22 21:02:45 +0000 |
| commit | f35ca2fe35859b40b1b0ff15a1751aab4805d392 (patch) | |
| tree | cd20a5dee4af655f0a1cb31175fee4c28aff7b3f /lisp/termdev.el | |
| parent | a18b8cb5070a81da0659275bef52f77f925644c8 (diff) | |
| download | emacs-f35ca2fe35859b40b1b0ff15a1751aab4805d392.tar.gz emacs-f35ca2fe35859b40b1b0ff15a1751aab4805d392.zip | |
Reimplement and extend support for terminal-local environment variables.
* lisp/termdev.el: New file. Move terminal parameter-related functions
here from frame.el.
(terminal-getenv, with-terminal-environment): Reimplement and extend.
(terminal-setenv, terminal-setenv-internal): New functions.
* lisp/frame.el (make-frame-on-tty, framep-on-display, suspend-frame):
Extend doc string, update parameter names.
(terminal-id, terminal-parameter-alist, terminal-parameters)
(terminal-parameter-p, terminal-parameter, set-terminal-parameter)
(terminal-handle-delete-frame, terminal-getenv, terminal-getenv)
(with-terminal-environment): Move to termdev.el.
* lisp/loadup.el: Load termdev as well.
* lisp/Makefile.in (lisp, shortlisp): Add termdev.elc.
* lisp/makefile.MPW (shortlisp): Ditto.
* lisp/ebuff-menu.el (electric-buffer-menu-mode-map): Bind C-z to
`suspend-frame', not `suspend-emacs'.
* lisp/echistory.el (electric-history-map): Ditto.
* lisp/ebrowse.el (ebrowse-electric-list-mode-map): Ditto.
* lisp/ebrowse.el (ebrowse-electric-position-mode-map): Ditto.
* lisp/startup.el (normal-splash-screen): Use `save-buffers-kill-display'
instead of `save-buffers-kill-emacs'.
* lisp/x-win.el (x-initialize-window-system): Add 'global-ok option to
`terminal-getenv'.
* src/term.c (suspend-tty): Update doc string.
git-archimport-id: lorentey@elte.hu--2004/emacs--multi-tty--0--patch-456
Diffstat (limited to 'lisp/termdev.el')
| -rw-r--r-- | lisp/termdev.el | 255 |
1 files changed, 255 insertions, 0 deletions
diff --git a/lisp/termdev.el b/lisp/termdev.el new file mode 100644 index 00000000000..667975b9b8b --- /dev/null +++ b/lisp/termdev.el | |||
| @@ -0,0 +1,255 @@ | |||
| 1 | ;;; termdev.el --- functions for dealing with terminals | ||
| 2 | |||
| 3 | ;; Copyright (C) 2005 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | ;; Author: Karoly Lorentey <karoly@lorentey.hu> | ||
| 6 | ;; Created: 2005-12-22 | ||
| 7 | ;; Keywords: internal | ||
| 8 | |||
| 9 | ;; This file is part of GNU Emacs. | ||
| 10 | |||
| 11 | ;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 12 | ;; it under the terms of the GNU General Public License as published by | ||
| 13 | ;; the Free Software Foundation; either version 2, or (at your option) | ||
| 14 | ;; any later version. | ||
| 15 | |||
| 16 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 17 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 18 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 19 | ;; GNU General Public License for more details. | ||
| 20 | |||
| 21 | ;; You should have received a copy of the GNU General Public License | ||
| 22 | ;; along with GNU Emacs; see the file COPYING. If not, write to the | ||
| 23 | ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
| 24 | ;; Boston, MA 02110-1301, USA. | ||
| 25 | |||
| 26 | (substitute-key-definition 'suspend-emacs 'suspend-frame global-map) | ||
| 27 | |||
| 28 | (defun terminal-id (terminal) | ||
| 29 | "Return the numerical id of terminal TERMINAL. | ||
| 30 | |||
| 31 | TERMINAL can be a terminal id (an integer), a frame, or | ||
| 32 | nil (meaning the selected frame's terminal). Alternatively, | ||
| 33 | TERMINAL may be the name of an X display | ||
| 34 | device (HOST.SERVER.SCREEN) or a tty device file." | ||
| 35 | (cond | ||
| 36 | ((integerp terminal) | ||
| 37 | (if (display-live-p terminal) | ||
| 38 | terminal | ||
| 39 | (signal 'wrong-type-argument (list 'display-live-p terminal)))) | ||
| 40 | ((or (null terminal) (framep terminal)) | ||
| 41 | (frame-display terminal)) | ||
| 42 | ((stringp terminal) | ||
| 43 | (let ((f (car (filtered-frame-list (lambda (frame) | ||
| 44 | (or (equal (frame-parameter frame 'display) terminal) | ||
| 45 | (equal (frame-parameter frame 'tty) terminal))))))) | ||
| 46 | (or f (error "Display %s does not exist" terminal)) | ||
| 47 | (frame-display f))) | ||
| 48 | (t | ||
| 49 | (error "Invalid argument %s in `terminal-id'" terminal)))) | ||
| 50 | |||
| 51 | (defvar terminal-parameter-alist nil | ||
| 52 | "An alist of terminal parameter alists.") | ||
| 53 | |||
| 54 | (defun terminal-parameters (&optional terminal) | ||
| 55 | "Return the paramater-alist of terminal TERMINAL. | ||
| 56 | It is a list of elements of the form (PARM . VALUE), where PARM is a symbol. | ||
| 57 | |||
| 58 | TERMINAL can be a terminal id, a frame, or nil (meaning the | ||
| 59 | selected frame's terminal)." | ||
| 60 | (cdr (assq (terminal-id terminal) terminal-parameter-alist))) | ||
| 61 | |||
| 62 | (defun terminal-parameter-p (terminal parameter) | ||
| 63 | "Return non-nil if PARAMETER is a terminal parameter on TERMINAL. | ||
| 64 | |||
| 65 | The actual value returned in that case is a cell (PARAMETER . VALUE), | ||
| 66 | where VALUE is the current value of PARAMETER. | ||
| 67 | |||
| 68 | TERMINAL can be a terminal id, a frame, or nil (meaning the | ||
| 69 | selected frame's terminal)." | ||
| 70 | (assq parameter (cdr (assq (terminal-id terminal) terminal-parameter-alist)))) | ||
| 71 | |||
| 72 | (defun terminal-parameter (terminal parameter) | ||
| 73 | "Return TERMINAL's value for parameter PARAMETER. | ||
| 74 | |||
| 75 | TERMINAL can be a terminal id, a frame, or nil (meaning the | ||
| 76 | selected frame's terminal)." | ||
| 77 | (cdr (terminal-parameter-p terminal parameter))) | ||
| 78 | |||
| 79 | (defun set-terminal-parameter (terminal parameter value) | ||
| 80 | "Set TERMINAL's value for parameter PARAMETER to VALUE. | ||
| 81 | Returns the previous value of PARAMETER. | ||
| 82 | |||
| 83 | TERMINAL can be a terminal id, a frame, or nil (meaning the | ||
| 84 | selected frame's terminal)." | ||
| 85 | (setq terminal (terminal-id terminal)) | ||
| 86 | (let* ((alist (assq terminal terminal-parameter-alist)) | ||
| 87 | (pair (assq parameter (cdr alist))) | ||
| 88 | (result (cdr pair))) | ||
| 89 | (cond | ||
| 90 | (pair (setcdr pair value)) | ||
| 91 | (alist (setcdr alist (cons (cons parameter value) (cdr alist)))) | ||
| 92 | (t (setq terminal-parameter-alist | ||
| 93 | (cons (cons terminal | ||
| 94 | (cons (cons parameter value) | ||
| 95 | nil)) | ||
| 96 | terminal-parameter-alist)))) | ||
| 97 | result)) | ||
| 98 | |||
| 99 | (defun terminal-handle-delete-frame (frame) | ||
| 100 | "Clean up terminal parameters of FRAME, if it's the last frame on its terminal." | ||
| 101 | ;; XXX We assume that the display is closed immediately after the | ||
| 102 | ;; last frame is deleted on it. It would be better to create a hook | ||
| 103 | ;; called `delete-display-functions', and use it instead. | ||
| 104 | (when (and (frame-live-p frame) | ||
| 105 | (= 1 (length (frames-on-display-list (frame-display frame))))) | ||
| 106 | (setq terminal-parameter-alist | ||
| 107 | (assq-delete-all (frame-display frame) terminal-parameter-alist)))) | ||
| 108 | |||
| 109 | (add-hook 'delete-frame-functions 'terminal-handle-delete-frame) | ||
| 110 | |||
| 111 | (defun terminal-getenv (variable &optional terminal global-ok) | ||
| 112 | "Get the value of VARIABLE in the client environment of TERMINAL. | ||
| 113 | VARIABLE should be a string. Value is nil if VARIABLE is undefined in | ||
| 114 | the environment. Otherwise, value is a string. | ||
| 115 | |||
| 116 | If TERMINAL has an associated emacsclient process, then | ||
| 117 | `terminal-getenv' looks up VARIABLE in the environment of that | ||
| 118 | process; otherwise the function consults the global environment, | ||
| 119 | i.e., the environment of the Emacs process itself. | ||
| 120 | |||
| 121 | If GLOBAL-OK is non-nil, and VARIABLE is not defined in the | ||
| 122 | terminal-local environment, then `terminal-getenv' will return | ||
| 123 | its value in the global environment instead. | ||
| 124 | |||
| 125 | TERMINAL can be a terminal id, a frame, or nil (meaning the | ||
| 126 | selected frame's terminal)." | ||
| 127 | (setq terminal (terminal-id terminal)) | ||
| 128 | (if (not (terminal-parameter-p terminal 'environment)) | ||
| 129 | (getenv variable) | ||
| 130 | (if (multibyte-string-p variable) | ||
| 131 | (setq variable (encode-coding-string variable locale-coding-system))) | ||
| 132 | (let ((env (terminal-parameter terminal 'environment)) | ||
| 133 | result entry) | ||
| 134 | (while (and env (null result)) | ||
| 135 | (setq entry (car env) | ||
| 136 | env (cdr env)) | ||
| 137 | (if (and (> (length entry) (length variable)) | ||
| 138 | (eq ?= (aref entry (length variable))) | ||
| 139 | (equal variable (substring entry 0 (length variable)))) | ||
| 140 | (setq result (substring entry (+ (length variable) 1))))) | ||
| 141 | (if (and global-ok (null result)) | ||
| 142 | (getenv variable) | ||
| 143 | (and result (decode-coding-string result locale-coding-system)))))) | ||
| 144 | |||
| 145 | (defun terminal-setenv (variable &optional value terminal) | ||
| 146 | "Set the value of VARIABLE in the environment of TERMINAL. | ||
| 147 | VARIABLE should be string. VALUE is optional; if not provided or | ||
| 148 | nil, the environment variable VARIABLE is removed. Returned | ||
| 149 | value is the new value of VARIABLE, or nil if it was removed from | ||
| 150 | the environment. | ||
| 151 | |||
| 152 | If TERMINAL was created by an emacsclient invocation, then the | ||
| 153 | variable is set in the environment of the emacsclient process; | ||
| 154 | otherwise the function changes the environment of the Emacs | ||
| 155 | process itself. | ||
| 156 | |||
| 157 | TERMINAL can be a terminal id, a frame, or nil (meaning the | ||
| 158 | selected frame's terminal)." | ||
| 159 | (if (not (terminal-parameter-p terminal 'environment)) | ||
| 160 | (setenv variable value) | ||
| 161 | (with-terminal-environment terminal variable | ||
| 162 | (setenv variable value)))) | ||
| 163 | |||
| 164 | (defun terminal-setenv-internal (variable value terminal) | ||
| 165 | "Set the value of VARIABLE in the environment of TERMINAL. | ||
| 166 | The caller is responsible to ensure that both VARIABLE and VALUE | ||
| 167 | are usable in environment variables and that TERMINAL is a | ||
| 168 | remote terminal." | ||
| 169 | (if (multibyte-string-p variable) | ||
| 170 | (setq variable (encode-coding-string variable locale-coding-system))) | ||
| 171 | (if (and value (multibyte-string-p value)) | ||
| 172 | (setq value (encode-coding-string value locale-coding-system))) | ||
| 173 | (let ((env (terminal-parameter terminal 'environment)) | ||
| 174 | found) | ||
| 175 | (while (and env (not found)) | ||
| 176 | (if (and (> (length (car env)) (length variable)) | ||
| 177 | (eq ?= (aref (car env) (length variable))) | ||
| 178 | (equal variable (substring (car env) 0 (length variable)))) | ||
| 179 | (progn | ||
| 180 | (if value | ||
| 181 | (setcar env (concat variable "=" value)) | ||
| 182 | (set-terminal-parameter terminal 'environment | ||
| 183 | (delq (car env) | ||
| 184 | (terminal-parameter terminal | ||
| 185 | 'environment)))) | ||
| 186 | (setq found t)) | ||
| 187 | (setq env (cdr env)))) | ||
| 188 | (cond | ||
| 189 | ((and value found) | ||
| 190 | (setcar env (concat variable "=" value))) | ||
| 191 | ((and value (not found)) | ||
| 192 | (set-terminal-parameter terminal 'environment | ||
| 193 | (cons (concat variable "=" value) | ||
| 194 | (terminal-parameter terminal | ||
| 195 | 'environment)))) | ||
| 196 | ((and (not value) found) | ||
| 197 | (set-terminal-parameter terminal 'environment | ||
| 198 | (delq (car env) | ||
| 199 | (terminal-parameter terminal | ||
| 200 | 'environment))))))) | ||
| 201 | |||
| 202 | (defmacro with-terminal-environment (terminal vars &rest body) | ||
| 203 | "Evaluate BODY with environment variables VARS set to those of TERMINAL. | ||
| 204 | The environment variables are then restored to their previous values. | ||
| 205 | |||
| 206 | VARS should be a single string, a list of strings, or t for all | ||
| 207 | environment variables. | ||
| 208 | |||
| 209 | TERMINAL can be a terminal id, a frame, or nil (meaning the | ||
| 210 | selected frame's terminal). | ||
| 211 | |||
| 212 | If BODY uses `setenv' to change environment variables in VARS, | ||
| 213 | then the new variable values will be remembered for TERMINAL, and | ||
| 214 | `terminal-getenv' will return them even outside BODY." | ||
| 215 | (declare (indent 2)) | ||
| 216 | (let ((var (make-symbol "var")) | ||
| 217 | (term (make-symbol "term")) | ||
| 218 | (v (make-symbol "v")) | ||
| 219 | (old-env (make-symbol "old-env"))) | ||
| 220 | `(let ((,term ,terminal) ; Evaluate arguments only once. | ||
| 221 | (,v ,vars)) | ||
| 222 | (if (stringp ,v) | ||
| 223 | (setq ,v (list ,v))) | ||
| 224 | (cond | ||
| 225 | ((not (terminal-parameter-p ,term 'environment)) | ||
| 226 | ;; Not a remote terminal; nothing to do. | ||
| 227 | (progn ,@body)) | ||
| 228 | ((eq ,v t) | ||
| 229 | ;; Switch the entire process-environment. | ||
| 230 | (let (,old-env process-environment) | ||
| 231 | (setq process-environment (terminal-parameter ,term 'environment)) | ||
| 232 | (unwind-protect | ||
| 233 | (progn ,@body) | ||
| 234 | (set-terminal-parameter ,term 'environment process-environment) | ||
| 235 | (setq process-environment ,old-env)))) | ||
| 236 | (t | ||
| 237 | ;; Do only a set of variables. | ||
| 238 | (let (,old-env) | ||
| 239 | (dolist (,var ,v) | ||
| 240 | (setq ,old-env (cons (cons ,var (getenv ,var)) ,old-env)) | ||
| 241 | (setenv ,var (terminal-getenv ,var ,term))) | ||
| 242 | (unwind-protect | ||
| 243 | (progn ,@body) | ||
| 244 | ;; Split storing new values and restoring old ones so | ||
| 245 | ;; that we DTRT even if a variable is specified twice in | ||
| 246 | ;; VARS. | ||
| 247 | (dolist (,var ,v) | ||
| 248 | (terminal-setenv-internal ,var (getenv ,var) ,term)) | ||
| 249 | (dolist (,var ,old-env) | ||
| 250 | (setenv (car ,var) (cdr ,var)))))))))) | ||
| 251 | |||
| 252 | (provide 'termdev) | ||
| 253 | |||
| 254 | ;;; arch-tag: 4c4df277-1ec1-4f56-bfde-7f156fe62fb2 | ||
| 255 | ;;; termdev.el ends here | ||