[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

name-capture problem in completing-read

From: Drew Adams
Subject: name-capture problem in completing-read
Date: Fri, 1 Jun 2007 11:00:57 -0700

I wonder if someone could help with this name-capture problem.

I have a function that calls `completing-read', passing the same arguments.
Some other code, invoked from the minibuffer during completion, uses the
value of `minibuffer-history-variable', which is taken from the HIST
parameter to `completing-read'. Whatever I name the history parameter in my
function, there is a possible name clash if the value of the parameter
refers to the same parameter name.

For example, if the parameter is called `hist' and its value happens to be
(hist . 1), then `minibuffer-history-variable' is `hist', and the value of
that is (hist . 1), not whatever the value of `hist' is outside the
function. Because (hist . 1) is the current value of `hist' within my
function, when `minibuffer-history-variable' is `hist' that same value is
picked up.

I could use a macro with an uninterned symbol, but I really want to use a
function. The reason is beside the point here, but this is it, FYI: In fact,
I defalias `completing-read' to my function (calling the original
`completing-read' definition in the function body). I need a function
because I'm replacing `completing-read': other code that calls
`completing-read' should pick up my redefinition instead (while in a
particular minor mode; I restore the original definition of
`completing-read' on mode exit).

To see the problem:

emacs -Q

(defun my-completing-read  ;; Just call original.
  (prompt table &optional predicate require-match
   initial-input hist def inherit-input-method) ""
   prompt table predicate require-match
   initial-input hist def inherit-input-method))

(defun test () "" (interactive)
  (message "hist-var: `%S', val: %S"
             (symbol-value minibuffer-history-variable))
  (sit-for 3))

(define-key minibuffer-local-completion-map "\C-s" 'test)
(setq hist `("c" "d")) ; Or leave it unbound - makes no difference.

Eval this, then, at the minibuffer prompt, hit C-s:

(my-completing-read "fff: " '(("a")("b")) nil t nil (cons 'hist 1))

You'll see this: "hist-var: `hist', val: (hist . 1)"

The desired behavior would have been this:
"hist-var: `hist', val: ("c" "d")"

`hist' is bound as a parameter to `my-completing-read', and `hist' is
(correctly) the value of `minibuffer-history-variable'. However, the user
didn't intend that the `hist' that is the value of
`minibuffer-history-variable' be the `hist' that is passed as the parameter.

Users of `my-completing-read', like users of `completing-read', expect to be
able to pass any variable as the history variable. With `completing-read',
they can, but not with `my-completing-read'.

What is a clean way to work around the problem, to get the desired behavior?

Simply changing the `hist' parameter name in `my-complete-read' is no help
of course; then the problem just arises for the new name. Likewise, passing
(set (make-symbol "foo") hist) as the HIST arg to `completing-read' is no

A solution is to use a macro with an uninterned symbol:

(defmacro my-completing-read
  (prompt table &optional predicate require-match
          initial-input hist def inherit-input-method)
    ,prompt ,table ,predicate ,require-match
    ,initial-input ,(set (make-symbol "foo") hist)
    ,def ,inherit-input-method))

That works, but I really need a function. Does anyone have a suggestion? Any
help is appreciated, even an explanation that "you can't get there from
here". If the latter is indeed the case, a second-best workaround would also
be appreciated. All I can think of for that is to use an unlikely-to-capture
name. Thx.

reply via email to

[Prev in Thread] Current Thread [Next in Thread]