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