Refill some copyright headers.
[bpt/emacs.git] / lisp / eshell / esh-var.el
CommitLineData
60370d40 1;;; esh-var.el --- handling of variables
affbf647 2
e9bffc61
GM
3;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
4;; 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
affbf647 5
7de5b421
GM
6;; Author: John Wiegley <johnw@gnu.org>
7
affbf647
GM
8;; This file is part of GNU Emacs.
9
4ee57b2a 10;; GNU Emacs is free software: you can redistribute it and/or modify
affbf647 11;; it under the terms of the GNU General Public License as published by
4ee57b2a
GM
12;; the Free Software Foundation, either version 3 of the License, or
13;; (at your option) any later version.
affbf647
GM
14
15;; GNU Emacs is distributed in the hope that it will be useful,
16;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18;; GNU General Public License for more details.
19
20;; You should have received a copy of the GNU General Public License
4ee57b2a 21;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
affbf647 22
affbf647
GM
23;;; Commentary:
24
25;; These are the possible variable interpolation syntaxes. Also keep
26;; in mind that if an argument looks like a number, it will be
27;; converted to a number. This is not significant when invoking
28;; external commands, but it's important when calling Lisp functions.
29;;
30;; $VARIABLE
31;;
32;; Interval the value of an environment variable, or a Lisp variable
33;;
34;; $ALSO-VAR
35;;
0138efd4 36;; "-" is a valid part of a variable name.
affbf647
GM
37;;
38;; $<MYVAR>-TOO
39;;
40;; Only "MYVAR" is part of the variable name in this case.
41;;
42;; $#VARIABLE
43;;
44;; Returns the length of the value of VARIABLE. This could also be
45;; done using the `length' Lisp function.
46;;
47;; $(lisp)
48;;
49;; Returns result of lisp evaluation. Note: Used alone like this, it
50;; is identical to just saying (lisp); but with the variable expansion
51;; form, the result may be interpolated a larger string, such as
52;; '$(lisp)/other'.
53;;
54;; ${command}
55;;
56;; Returns the value of an eshell subcommand. See the note above
57;; regarding Lisp evaluations.
58;;
59;; $ANYVAR[10]
60;;
61;; Return the 10th element of ANYVAR. If ANYVAR's value is a string,
62;; it will be split in order to make it a list. The splitting will
63;; occur at whitespace.
64;;
65;; $ANYVAR[: 10]
66;;
67;; As above, except that splitting occurs at the colon now.
68;;
69;; $ANYVAR[: 10 20]
70;;
71;; As above, but instead of returning just a string, it now returns a
72;; list of two strings. If the result is being interpolated into a
73;; larger string, this list will be flattened into one big string,
74;; with each element separated by a space.
75;;
76;; $ANYVAR["\\\\" 10]
77;;
78;; Separate on backslash characters. Actually, the first argument --
79;; if it doesn't have the form of a number, or a plain variable name
80;; -- can be any regular expression. So to split on numbers, use
81;; '$ANYVAR["[0-9]+" 10 20]'.
82;;
83;; $ANYVAR[hello]
84;;
85;; Calls `assoc' on ANYVAR with 'hello', expecting it to be an alist.
86;;
87;; $#ANYVAR[hello]
88;;
89;; Returns the length of the cdr of the element of ANYVAR who car is
90;; equal to "hello".
91;;
92;; There are also a few special variables defined by Eshell. '$$' is
93;; the value of the last command (t or nil, in the case of an external
94;; command). This makes it possible to chain results:
95;;
96;; /tmp $ echo /var/spool/mail/johnw
97;; /var/spool/mail/johnw
98;; /tmp $ dirname $$
99;; /var/spool/mail/
100;; /tmp $ cd $$
101;; /var/spool/mail $
102;;
103;; '$_' refers to the last argument of the last command. And $?
104;; contains the exit code of the last command (0 or 1 for Lisp
105;; functions, based on successful completion).
106
8c7309fe
GM
107;;; Code:
108
11740ce5
GM
109(provide 'esh-var)
110
111(eval-when-compile
112 (require 'pcomplete)
113 (require 'esh-test)
114 (require 'esh-util)
115 (require 'esh-opt)
116 (require 'esh-mode))
affbf647
GM
117(require 'env)
118(require 'ring)
119
11740ce5
GM
120(defgroup eshell-var nil
121 "Variable interpolation is introduced whenever the '$' character
122appears unquoted in any argument (except when that argument is
123surrounded by single quotes). It may be used to interpolate a
124variable value, a subcommand, or even the result of a Lisp form."
125 :tag "Variable handling"
126 :group 'eshell)
127
affbf647
GM
128;;; User Variables:
129
130(defcustom eshell-var-load-hook '(eshell-var-initialize)
ec60da52 131 "A list of functions to call when loading `eshell-var'."
affbf647
GM
132 :type 'hook
133 :group 'eshell-var)
134
135(defcustom eshell-prefer-lisp-variables nil
ec60da52 136 "If non-nil, prefer Lisp variables to environment variables."
affbf647
GM
137 :type 'boolean
138 :group 'eshell-var)
139
140(defcustom eshell-complete-export-definition t
ec60da52 141 "If non-nil, completing names for `export' shows current definition."
affbf647
GM
142 :type 'boolean
143 :group 'eshell-var)
144
6995786d 145(defcustom eshell-modify-global-environment nil
ec60da52 146 "If non-nil, using `export' changes Emacs's global environment."
6995786d
JW
147 :type 'boolean
148 :group 'eshell-var)
149
affbf647 150(defcustom eshell-variable-name-regexp "[A-Za-z0-9_-]+"
ec60da52 151 "A regexp identifying what constitutes a variable name reference.
affbf647
GM
152Note that this only applies for '$NAME'. If the syntax '$<NAME>' is
153used, then NAME can contain any character, including angle brackets,
154if they are quoted with a backslash."
155 :type 'regexp
156 :group 'eshell-var)
157
158(defcustom eshell-variable-aliases-list
159 '(;; for eshell.el
160 ("COLUMNS" (lambda (indices) (window-width)) t)
161 ("LINES" (lambda (indices) (window-height)) t)
162
163 ;; for eshell-cmd.el
164 ("_" (lambda (indices)
165 (if (not indices)
166 (car (last eshell-last-arguments))
167 (eshell-apply-indices eshell-last-arguments
168 indices))))
169 ("?" eshell-last-command-status)
170 ("$" eshell-last-command-result)
171 ("0" eshell-command-name)
172 ("1" (lambda (indices) (nth 0 eshell-command-arguments)))
173 ("2" (lambda (indices) (nth 1 eshell-command-arguments)))
174 ("3" (lambda (indices) (nth 2 eshell-command-arguments)))
175 ("4" (lambda (indices) (nth 3 eshell-command-arguments)))
176 ("5" (lambda (indices) (nth 4 eshell-command-arguments)))
177 ("6" (lambda (indices) (nth 5 eshell-command-arguments)))
178 ("7" (lambda (indices) (nth 6 eshell-command-arguments)))
179 ("8" (lambda (indices) (nth 7 eshell-command-arguments)))
180 ("9" (lambda (indices) (nth 8 eshell-command-arguments)))
181 ("*" (lambda (indices)
182 (if (not indices)
183 eshell-command-arguments
184 (eshell-apply-indices eshell-command-arguments
185 indices)))))
ec60da52 186 "This list provides aliasing for variable references.
affbf647
GM
187It is very similar in concept to what `eshell-user-aliases-list' does
188for commands. Each member of this defines defines the name of a
189command, and the Lisp value to return for that variable if it is
190accessed via the syntax '$NAME'.
191
192If the value is a function, that function will be called with two
193arguments: the list of the indices that was used in the reference, and
194whether the user is requesting the length of the ultimate element.
195For example, a reference of '$NAME[10][20]' would result in the
196function for alias `NAME' being called (assuming it were aliased to a
197function), and the arguments passed to this function would be the list
198'(10 20)', and nil."
199 :type '(repeat (list string sexp
200 (choice (const :tag "Copy to environment" t)
201 (const :tag "Use only in Eshell" nil))))
202 :group 'eshell-var)
203
204(put 'eshell-variable-aliases-list 'risky-local-variable t)
205
206;;; Functions:
207
208(defun eshell-var-initialize ()
209 "Initialize the variable handle code."
210 ;; Break the association with our parent's environment. Otherwise,
211 ;; changing a variable will affect all of Emacs.
6995786d
JW
212 (unless eshell-modify-global-environment
213 (set (make-local-variable 'process-environment)
214 (eshell-copy-environment)))
affbf647
GM
215
216 (define-key eshell-command-map [(meta ?v)] 'eshell-insert-envvar)
217
218 (set (make-local-variable 'eshell-special-chars-inside-quoting)
219 (append eshell-special-chars-inside-quoting '(?$)))
220 (set (make-local-variable 'eshell-special-chars-outside-quoting)
221 (append eshell-special-chars-outside-quoting '(?$)))
222
affbf647
GM
223 (add-hook 'eshell-parse-argument-hook 'eshell-interpolate-variable t t)
224
affbf647
GM
225 (add-hook 'eshell-prepare-command-hook
226 'eshell-handle-local-variables nil t)
227
228 (when (eshell-using-module 'eshell-cmpl)
affbf647
GM
229 (add-hook 'pcomplete-try-first-hook
230 'eshell-complete-variable-reference nil t)
231 (add-hook 'pcomplete-try-first-hook
232 'eshell-complete-variable-assignment nil t)))
233
234(defun eshell-handle-local-variables ()
235 "Allow for the syntax 'VAR=val <command> <args>'."
236 ;; strip off any null commands, which can only happen if a variable
237 ;; evaluates to nil, such as "$var x", where `var' is nil. The
238 ;; command name in that case becomes `x', for compatibility with
239 ;; most regular shells (the difference is that they do an
240 ;; interpolation pass before the argument parsing pass, but Eshell
241 ;; does both at the same time).
242 (while (and (not eshell-last-command-name)
243 eshell-last-arguments)
244 (setq eshell-last-command-name (car eshell-last-arguments)
245 eshell-last-arguments (cdr eshell-last-arguments)))
246 (let ((setvar "\\`\\([A-Za-z_][A-Za-z0-9_]*\\)=\\(.*\\)\\'")
247 (command (eshell-stringify eshell-last-command-name))
248 (args eshell-last-arguments))
249 ;; local variable settings (such as 'CFLAGS=-O2 make') are handled
250 ;; by making the whole command into a subcommand, and calling
251 ;; setenv immediately before the command is invoked. This means
252 ;; that 'BLAH=x cd blah' won't work exactly as expected, but that
253 ;; is by no means a typical use of local environment variables.
254 (if (and command (string-match setvar command))
255 (throw
256 'eshell-replace-command
257 (list
258 'eshell-as-subcommand
259 (append
260 (list 'progn)
261 (let ((l (list t)))
262 (while (string-match setvar command)
263 (nconc
264 l (list
265 (list 'setenv (match-string 1 command)
266 (match-string 2 command)
267 (= (length (match-string 2 command)) 0))))
268 (setq command (eshell-stringify (car args))
269 args (cdr args)))
270 (cdr l))
271 (list (list 'eshell-named-command
272 command (list 'quote args)))))))))
273
274(defun eshell-interpolate-variable ()
275 "Parse a variable interpolation.
276This function is explicit for adding to `eshell-parse-argument-hook'."
277 (when (and (eq (char-after) ?$)
ca7aae91 278 (/= (1+ (point)) (point-max)))
affbf647
GM
279 (forward-char)
280 (list 'eshell-escape-arg
281 (eshell-parse-variable))))
282
283(defun eshell/define (var-alias definition)
012d3cb5 284 "Define a VAR-ALIAS using DEFINITION."
affbf647
GM
285 (if (not definition)
286 (setq eshell-variable-aliases-list
287 (delq (assoc var-alias eshell-variable-aliases-list)
288 eshell-variable-aliases-list))
289 (let ((def (assoc var-alias eshell-variable-aliases-list))
290 (alias-def
291 (list var-alias
292 (list 'quote (if (= (length definition) 1)
293 (car definition)
294 definition)))))
295 (if def
296 (setq eshell-variable-aliases-list
297 (delq (assoc var-alias eshell-variable-aliases-list)
298 eshell-variable-aliases-list)))
299 (setq eshell-variable-aliases-list
300 (cons alias-def
301 eshell-variable-aliases-list))))
302 nil)
303
304(defun eshell/export (&rest sets)
a4fd4556 305 "This alias allows the `export' command to act as bash users expect."
affbf647 306 (while sets
ca7aae91
JW
307 (if (and (stringp (car sets))
308 (string-match "^\\([^=]+\\)=\\(.*\\)" (car sets)))
affbf647
GM
309 (setenv (match-string 1 (car sets))
310 (match-string 2 (car sets))))
311 (setq sets (cdr sets))))
312
79cf8e80
JW
313(defun pcomplete/eshell-mode/export ()
314 "Completion function for Eshell's `export'."
315 (while (pcomplete-here
316 (if eshell-complete-export-definition
317 process-environment
318 (eshell-envvar-names)))))
319
ca7aae91
JW
320(defun eshell/unset (&rest args)
321 "Unset an environment variable."
322 (while args
323 (if (stringp (car args))
324 (setenv (car args) nil t))
325 (setq args (cdr args))))
326
79cf8e80
JW
327(defun pcomplete/eshell-mode/unset ()
328 "Completion function for Eshell's `unset'."
329 (while (pcomplete-here (eshell-envvar-names))))
affbf647
GM
330
331(defun eshell/setq (&rest args)
332 "Allow command-ish use of `setq'."
333 (let (last-value)
334 (while args
335 (let ((sym (intern (car args)))
336 (val (cadr args)))
337 (setq last-value (set sym val)
338 args (cddr args))))
339 last-value))
340
341(defun pcomplete/eshell-mode/setq ()
342 "Completion function for Eshell's `setq'."
343 (while (and (pcomplete-here (all-completions pcomplete-stub
344 obarray 'boundp))
345 (pcomplete-here))))
346
347(defun eshell/env (&rest args)
348 "Implemention of `env' in Lisp."
349 (eshell-init-print-buffer)
350 (eshell-eval-using-options
351 "env" args
352 '((?h "help" nil nil "show this usage screen")
353 :external "env"
354 :usage "<no arguments>")
355 (eshell-for setting (sort (eshell-environment-variables)
356 'string-lessp)
357 (eshell-buffered-print setting "\n"))
358 (eshell-flush)))
359
360(defun eshell-insert-envvar (envvar-name)
361 "Insert ENVVAR-NAME into the current buffer at point."
362 (interactive
363 (list (read-envvar-name "Name of environment variable: " t)))
364 (insert-and-inherit "$" envvar-name))
365
366(defun eshell-envvar-names (&optional environment)
367 "Return a list of currently visible environment variable names."
368 (mapcar (function
369 (lambda (x)
370 (substring x 0 (string-match "=" x))))
371 (or environment process-environment)))
372
373(defun eshell-environment-variables ()
374 "Return a `process-environment', fully updated.
375This involves setting any variable aliases which affect the
376environment, as specified in `eshell-variable-aliases-list'."
377 (let ((process-environment (eshell-copy-environment)))
378 (eshell-for var-alias eshell-variable-aliases-list
379 (if (nth 2 var-alias)
380 (setenv (car var-alias)
381 (eshell-stringify
382 (or (eshell-get-variable (car var-alias)) "")))))
383 process-environment))
384
385(defun eshell-parse-variable ()
386 "Parse the next variable reference at point.
387The variable name could refer to either an environment variable, or a
388Lisp variable. The priority order depends on the setting of
389`eshell-prefer-lisp-variables'.
390
391Its purpose is to call `eshell-parse-variable-ref', and then to
392process any indices that come after the variable reference."
393 (let* ((get-len (when (eq (char-after) ?#)
394 (forward-char) t))
395 value indices)
396 (setq value (eshell-parse-variable-ref)
397 indices (and (not (eobp))
398 (eq (char-after) ?\[)
399 (eshell-parse-indices))
400 value (list 'let
401 (list (list 'indices
402 (list 'quote indices)))
403 value))
404 (if get-len
405 (list 'length value)
406 value)))
407
408(defun eshell-parse-variable-ref ()
409 "Eval a variable reference.
410Returns a Lisp form which, if evaluated, will return the value of the
411variable.
412
413Possible options are:
414
415 NAME an environment or Lisp variable value
416 <LONG-NAME> disambiguates the length of the name
417 {COMMAND} result of command is variable's value
418 (LISP-FORM) result of Lisp form is variable's value"
419 (let (end)
420 (cond
421 ((eq (char-after) ?{)
422 (let ((end (eshell-find-delimiter ?\{ ?\})))
423 (if (not end)
424 (throw 'eshell-incomplete ?\{)
425 (prog1
426 (list 'eshell-convert
427 (list 'eshell-command-to-value
428 (list 'eshell-as-subcommand
429 (eshell-parse-command
430 (cons (1+ (point)) end)))))
431 (goto-char (1+ end))))))
432 ((memq (char-after) '(?\' ?\"))
433 (let ((name (if (eq (char-after) ?\')
434 (eshell-parse-literal-quote)
435 (eshell-parse-double-quote))))
436 (if name
437 (list 'eshell-get-variable (eval name) 'indices))))
f1572159 438 ((eq (char-after) ?\<)
affbf647
GM
439 (let ((end (eshell-find-delimiter ?\< ?\>)))
440 (if (not end)
441 (throw 'eshell-incomplete ?\<)
1ae720ac 442 (let* ((temp (make-temp-file temporary-file-directory))
affbf647
GM
443 (cmd (concat (buffer-substring (1+ (point)) end)
444 " > " temp)))
445 (prog1
446 (list
447 'let (list (list 'eshell-current-handles
448 (list 'eshell-create-handles temp
449 (list 'quote 'overwrite))))
450 (list
451 'progn
452 (list 'eshell-as-subcommand
453 (eshell-parse-command cmd))
454 (list 'ignore
455 (list 'nconc 'eshell-this-command-hook
456 (list 'list
457 (list 'function
458 (list 'lambda nil
459 (list 'delete-file temp))))))
460 (list 'quote temp)))
461 (goto-char (1+ end)))))))
462 ((eq (char-after) ?\()
463 (condition-case err
464 (list 'eshell-command-to-value
465 (list 'eshell-lisp-command
466 (list 'quote (read (current-buffer)))))
467 (end-of-file
468 (throw 'eshell-incomplete ?\())))
469 ((assoc (char-to-string (char-after))
470 eshell-variable-aliases-list)
471 (forward-char)
472 (list 'eshell-get-variable
473 (char-to-string (char-before)) 'indices))
474 ((looking-at eshell-variable-name-regexp)
475 (prog1
476 (list 'eshell-get-variable (match-string 0) 'indices)
477 (goto-char (match-end 0))))
478 (t
479 (error "Invalid variable reference")))))
480
481(eshell-deftest var interp-cmd
482 "Interpolate command result"
483 (eshell-command-result-p "+ ${+ 1 2} 3" "6\n"))
484
485(eshell-deftest var interp-lisp
486 "Interpolate Lisp form evalution"
487 (eshell-command-result-p "+ $(+ 1 2) 3" "6\n"))
488
489(eshell-deftest var interp-concat
490 "Interpolate and concat command"
491 (eshell-command-result-p "+ ${+ 1 2}3 3" "36\n"))
492
493(eshell-deftest var interp-concat-lisp
494 "Interpolate and concat Lisp form"
495 (eshell-command-result-p "+ $(+ 1 2)3 3" "36\n"))
496
497(eshell-deftest var interp-concat2
498 "Interpolate and concat two commands"
499 (eshell-command-result-p "+ ${+ 1 2}${+ 1 2} 3" "36\n"))
500
501(eshell-deftest var interp-concat-lisp2
502 "Interpolate and concat two Lisp forms"
503 (eshell-command-result-p "+ $(+ 1 2)$(+ 1 2) 3" "36\n"))
504
505(defun eshell-parse-indices ()
506 "Parse and return a list of list of indices."
507 (let (indices)
508 (while (eq (char-after) ?\[)
509 (let ((end (eshell-find-delimiter ?\[ ?\])))
510 (if (not end)
511 (throw 'eshell-incomplete ?\[)
512 (forward-char)
513 (let (eshell-glob-function)
514 (setq indices (cons (eshell-parse-arguments (point) end)
515 indices)))
516 (goto-char (1+ end)))))
517 (nreverse indices)))
518
519(defun eshell-get-variable (name &optional indices)
520 "Get the value for the variable NAME."
521 (let* ((alias (assoc name eshell-variable-aliases-list))
522 (var (if alias
523 (cadr alias)
524 name)))
525 (if (and alias (functionp var))
526 (funcall var indices)
527 (eshell-apply-indices
528 (cond
529 ((stringp var)
530 (let ((sym (intern-soft var)))
531 (if (and sym (boundp sym)
532 (or eshell-prefer-lisp-variables
533 (not (getenv var))))
534 (symbol-value sym)
535 (getenv var))))
536 ((symbolp var)
537 (symbol-value var))
538 (t
539 (error "Unknown variable `%s'" (eshell-stringify var))))
540 indices))))
541
542(defun eshell-apply-indices (value indices)
543 "Apply to VALUE all of the given INDICES, returning the sub-result.
544The format of INDICES is:
545
546 ((INT-OR-NAME-OR-OTHER INT-OR-NAME INT-OR-NAME ...)
547 ...)
548
549Each member of INDICES represents a level of nesting. If the first
550member of a sublist is not an integer or name, and the value it's
551reference is a string, that will be used as the regexp with which is
552to divide the string into sub-parts. The default is whitespace.
553Otherwise, each INT-OR-NAME refers to an element of the list value.
554Integers imply a direct index, and names, an associate lookup using
555`assoc'.
556
557For example, to retrieve the second element of a user's record in
558'/etc/passwd', the variable reference would look like:
559
560 ${egrep johnw /etc/passwd}[: 2]"
561 (while indices
562 (let ((refs (car indices)))
563 (when (stringp value)
564 (let (separator)
565 (if (not (or (not (stringp (caar indices)))
566 (string-match
567 (concat "^" eshell-variable-name-regexp "$")
568 (caar indices))))
569 (setq separator (caar indices)
570 refs (cdr refs)))
571 (setq value
572 (mapcar 'eshell-convert
573 (split-string value separator)))))
574 (cond
575 ((< (length refs) 0)
5b423d48 576 (error "Invalid array variable index: %s"
affbf647
GM
577 (eshell-stringify refs)))
578 ((= (length refs) 1)
579 (setq value (eshell-index-value value (car refs))))
580 (t
581 (let ((new-value (list t)))
582 (while refs
583 (nconc new-value
584 (list (eshell-index-value value
585 (car refs))))
586 (setq refs (cdr refs)))
587 (setq value (cdr new-value))))))
588 (setq indices (cdr indices)))
589 value)
590
591(defun eshell-index-value (value index)
592 "Reference VALUE using the given INDEX."
593 (if (stringp index)
594 (cdr (assoc index value))
595 (cond
596 ((ring-p value)
597 (if (> index (ring-length value))
598 (error "Index exceeds length of ring")
599 (ring-ref value index)))
600 ((listp value)
601 (if (> index (length value))
602 (error "Index exceeds length of list")
603 (nth index value)))
604 ((vectorp value)
605 (if (> index (length value))
606 (error "Index exceeds length of vector")
607 (aref value index)))
608 (t
609 (error "Invalid data type for indexing")))))
610
611;;;_* Variable name completion
612
613(defun eshell-complete-variable-reference ()
614 "If there is a variable reference, complete it."
615 (let ((arg (pcomplete-actual-arg)) index)
616 (when (setq index
617 (string-match
618 (concat "\\$\\(" eshell-variable-name-regexp
619 "\\)?\\'") arg))
620 (setq pcomplete-stub (substring arg (1+ index)))
621 (throw 'pcomplete-completions (eshell-variables-list)))))
622
623(defun eshell-variables-list ()
624 "Generate list of applicable variables."
625 (let ((argname pcomplete-stub)
626 completions)
627 (eshell-for alias eshell-variable-aliases-list
628 (if (string-match (concat "^" argname) (car alias))
629 (setq completions (cons (car alias) completions))))
630 (sort
631 (append
632 (mapcar
633 (function
634 (lambda (varname)
635 (let ((value (eshell-get-variable varname)))
636 (if (and value
637 (stringp value)
638 (file-directory-p value))
6b0e3e4d 639 (concat varname "/")
affbf647
GM
640 varname))))
641 (eshell-envvar-names (eshell-environment-variables)))
642 (all-completions argname obarray 'boundp)
643 completions)
644 'string-lessp)))
645
646(defun eshell-complete-variable-assignment ()
647 "If there is a variable assignment, allow completion of entries."
648 (let ((arg (pcomplete-actual-arg)) pos)
649 (when (string-match (concat "\\`" eshell-variable-name-regexp "=") arg)
650 (setq pos (match-end 0))
651 (if (string-match "\\(:\\)[^:]*\\'" arg)
652 (setq pos (match-end 1)))
653 (setq pcomplete-stub (substring arg pos))
654 (throw 'pcomplete-completions (pcomplete-entries)))))
655
affbf647 656;;; esh-var.el ends here