]> git.eshelyaron.com Git - emacs.git/commitdiff
* lisp/eshell/esh-opt.el: Fix last change to set lexical-vars properly.
authorStefan Monnier <monnier@iro.umontreal.ca>
Mon, 16 Sep 2013 18:23:30 +0000 (14:23 -0400)
committerStefan Monnier <monnier@iro.umontreal.ca>
Mon, 16 Sep 2013 18:23:30 +0000 (14:23 -0400)
(eshell--do-opts): Rename from eshell-do-opt, remove arg `body-fun',
return args and options.
(eshell-eval-using-options): Use the new return value of
eshell--do-opts to set the options's vars in their scope.
(eshell--set-option): Rename from eshell-set-option.
Add arg `opt-vals'.
(eshell--process-option): Rename from eshell-process-option.
Add arg `opt-vals'.
(eshell--process-args): Use an `opt-vals' alist to store the options's
values during their processing and return them additionally to the
remaining args.

Fixes: debbugs:15379
lisp/ChangeLog
lisp/eshell/esh-opt.el
lisp/eshell/esh-util.el

index 44a81ee32fc5e9bc9df5a563d4822a34a6df0c05..f5710d85e16135e70023622805b0095cc804754c 100644 (file)
@@ -1,3 +1,19 @@
+2013-09-16  Stefan Monnier  <monnier@iro.umontreal.ca>
+
+       * eshell/esh-opt.el: Fix last change to set lexical-vars properly
+       (bug#15379).
+       (eshell--do-opts): Rename from eshell-do-opt, remove arg `body-fun',
+       return args and options.
+       (eshell-eval-using-options): Use the new return value of
+       eshell--do-opts to set the options's vars in their scope.
+       (eshell--set-option): Rename from eshell-set-option.
+       Add arg `opt-vals'.
+       (eshell--process-option): Rename from eshell-process-option.
+       Add arg `opt-vals'.
+       (eshell--process-args): Use an `opt-vals' alist to store the options's
+       values during their processing and return them additionally to the
+       remaining args.
+
 2013-09-15  Dmitry Gutov  <dgutov@yandex.ru>
 
        * progmodes/ruby-mode.el (ruby-operator-re): Consider line
index e9252cb540ecff629314b3901aea959fb65df455..3f5bcb641ac78ada99ead32d10a458f93381b301 100644 (file)
@@ -98,45 +98,44 @@ the new process for its value.
 Lastly, any remaining arguments will be available in a locally
 interned variable `args' (created using a `let' form)."
   (declare (debug (form form sexp body)))
-  `(let ((temp-args
-         ,(if (memq ':preserve-args (cadr options))
-              macro-args
-            (list 'eshell-stringify-list
-                  (list 'eshell-flatten-list macro-args)))))
-     (let ,(delq nil (mapcar (lambda (opt)
-                                      (and (listp opt) (nth 3 opt)))
-                                    (cadr options)))
-       ;; FIXME: `options' ends up hiding some variable names under `quote',
-       ;; which is incompatible with lexical scoping!!
-       (eshell-do-opt ,name ,options (lambda (args) ,@body-forms) temp-args))))
+  `(let* ((temp-args
+           ,(if (memq ':preserve-args (cadr options))
+                macro-args
+              (list 'eshell-stringify-list
+                    (list 'eshell-flatten-list macro-args))))
+          (processed-args (eshell--do-opts ,name ,options temp-args))
+          ,@(delete-dups
+             (delq nil (mapcar (lambda (opt)
+                                 (and (listp opt) (nth 3 opt)
+                                      `(,(nth 3 opt) (pop processed-args))))
+                               ;; `options' is of the form (quote OPTS).
+                               (cadr options))))
+          (args processed-args))
+     ,@body-forms))
 
 ;;; Internal Functions:
 
 ;; Documented part of the interface; see eshell-eval-using-options.
 (defvar eshell--args)
 
-(defun eshell-do-opt (name options body-fun args)
+(defun eshell--do-opts (name options args)
   "Helper function for `eshell-eval-using-options'.
 This code doesn't really need to be macro expanded everywhere."
-  (let* (last-value
-         (ext-command
-       (catch 'eshell-ext-command
-            (let ((usage-msg
-               (catch 'eshell-usage
-                 (setq last-value nil)
-                 (if (and (= (length args) 0)
-                          (memq ':show-usage options))
-                     (throw 'eshell-usage
-                            (eshell-show-usage name options)))
-                 (setq args (eshell-process-args name args options)
-                       last-value (funcall body-fun args))
-                     nil)))
-              (when usage-msg
-                (error "%s" usage-msg))))))
+  (let ((ext-command
+         (catch 'eshell-ext-command
+           (let ((usage-msg
+                  (catch 'eshell-usage
+                    (if (and (= (length args) 0)
+                             (memq ':show-usage options))
+                        (eshell-show-usage name options)
+                      (setq args (eshell--process-args name args options))
+                      nil))))
+             (when usage-msg
+               (error "%s" usage-msg))))))
     (if ext-command
-      (throw 'eshell-external
-             (eshell-external-command ext-command args))
-      last-value)))
+        (throw 'eshell-external
+               (eshell-external-command ext-command args))
+      args)))
 
 (defun eshell-show-usage (name options)
   "Display the usage message for NAME, using OPTIONS."
@@ -185,23 +184,24 @@ passed to this command, the external version '%s'
 will be called instead." extcmd)))))
     (throw 'eshell-usage usage)))
 
-(defun eshell-set-option (name ai opt options)
+(defun eshell--set-option (name ai opt options opt-vals)
   "Using NAME's remaining args (index AI), set the OPT within OPTIONS.
 If the option consumes an argument for its value, the argument list
 will be modified."
   (if (not (nth 3 opt))
       (eshell-show-usage name options)
-    (if (eq (nth 2 opt) t)
-       (if (> ai (length eshell--args))
-           (error "%s: missing option argument" name)
-         (set (nth 3 opt) (nth ai eshell--args))
-         (if (> ai 0)
-             (setcdr (nthcdr (1- ai) eshell--args)
-                      (nthcdr (1+ ai) eshell--args))
-           (setq eshell--args (cdr eshell--args))))
-      (set (nth 3 opt) (or (nth 2 opt) t)))))
-
-(defun eshell-process-option (name switch kind ai options)
+    (setcdr (assq (nth 3 opt) opt-vals)
+            (if (eq (nth 2 opt) t)
+                (if (> ai (length eshell--args))
+                    (error "%s: missing option argument" name)
+                  (prog1 (nth ai eshell--args)
+                    (if (> ai 0)
+                        (setcdr (nthcdr (1- ai) eshell--args)
+                                (nthcdr (1+ ai) eshell--args))
+                      (setq eshell--args (cdr eshell--args)))))
+              (or (nth 2 opt) t)))))
+
+(defun eshell--process-option (name switch kind ai options opt-vals)
   "For NAME, process SWITCH (of type KIND), from args at index AI.
 The SWITCH will be looked up in the set of OPTIONS.
 
@@ -219,7 +219,7 @@ switch is unrecognized."
                (nth kind (car opts))
                (equal switch (nth kind (car opts))))
          (progn
-           (eshell-set-option name ai (car opts) options)
+           (eshell--set-option name ai (car opts) options opt-vals)
            (setq found t opts nil))
        (setq opts (cdr opts))))
     (unless found
@@ -232,11 +232,18 @@ switch is unrecognized."
                      "%s: unrecognized option --%s")
                    name switch)))))))
 
-(defun eshell-process-args (name args options)
-  "Process the given ARGS using OPTIONS.
-This assumes that symbols have been intern'd by `eshell-eval-using-options'."
-  (let ((ai 0) arg
-        (eshell--args args))
+(defun eshell--process-args (name args options)
+  "Process the given ARGS using OPTIONS."
+  (let* ((seen ())
+         (opt-vals (delq nil (mapcar (lambda (opt)
+                                       (when (listp opt)
+                                         (let ((sym (nth 3 opt)))
+                                           (when (and sym (not (memq sym seen)))
+                                            (push sym seen)
+                                             (list sym)))))
+                                    options)))
+         (ai 0) arg
+         (eshell--args args))
     (while (< ai (length args))
       (setq arg (nth ai args))
       (if (not (and (stringp arg)
@@ -249,13 +256,14 @@ This assumes that symbols have been intern'd by `eshell-eval-using-options'."
            (setcdr (nthcdr (1- ai) args) (nthcdr (1+ ai) args)))
          (if dash
              (if (> (length switch) 0)
-                 (eshell-process-option name switch 1 ai options)
+                 (eshell--process-option name switch 1 ai options opt-vals)
                (setq ai (length args)))
            (let ((len (length switch))
                  (index 0))
              (while (< index len)
-               (eshell-process-option name (aref switch index) 0 ai options)
-               (setq index (1+ index)))))))))
-  args)
+               (eshell--process-option name (aref switch index)
+                                        0 ai options opt-vals)
+               (setq index (1+ index))))))))
+    (nconc (mapcar #'cdr opt-vals) args)))
 
 ;;; esh-opt.el ends here
index 5fa591a30823db21462240dc2fc585162fb19613..5e0aad8345f2435480e3d799dbd108718317eae7 100644 (file)
@@ -144,7 +144,7 @@ function `string-to-number'."
 Otherwise, evaluates FORM with no error handling."
   (declare (indent 2))
   (if eshell-handle-errors
-      `(condition-case ,tag
+      `(condition-case-unless-debug ,tag
           ,form
         ,@handlers)
     form))