comparison lisp/termdev.el @ 83416:4513d8dcdfd5

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
author Karoly Lorentey <lorentey@elte.hu>
date Thu, 22 Dec 2005 21:02:45 +0000
parents
children 521d3f18b3d1
comparison
equal deleted inserted replaced
83415:d2c799f58129 83416:4513d8dcdfd5
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