3
(defun tmp:interactive (&optional scope pos-style)
  "POS-STYLE has no effect when SCOPE is `directory'."
  (interactive
   (list
    (cdr (assoc (read-char-choice
                 "Copy (f)ull name, (d)irectory, or just the (b)asename? "
                 '(?f ?d ?b))
                '((?f . full)
                  (?d . directory)
                  (?b . basename))))
    (when (and (not (equal scope 'directory)) current-prefix-arg)
      (cdr (assoc (read-char-choice
                   "Style: (n)one, (l)ine, (c)olumn, or (p)oint? "
                   '(?n ?l ?c ?p))
                  '((?n . nil)
                    (?l . line)
                    (?c . line-column)
                    (?p . point)))))))
  (message "%S %S" scope pos-style))

Above is a skeleton of a function that copies the appropriate file name for the current buffer. However, it doesn't really make sense to include position information when the user is copying the directory name.

Is there a way to ignore a prefix argument within the (interactive ...) form based on previous input?

(An alternative solution to this end would be to test called-interactively-p and leave the optional argument as nil to test in the body of the defun, but that's very fragmented.

3

You cannot refer to SCOPE within the interactive form, because it is that form that defines SCOPE.

What you can do is use let to save the result of read-char-choice and then test that in the rest of the interactive spec.

(defun tmp:interactive (&optional scope pos-style)
  "POS-STYLE has no effect when SCOPE is `directory'."
  (interactive
   (let ((scop  (cdr (assoc (read-char-choice
                             "Copy (f)ull name, (d)irectory, or just the (b)asename? "
                             '(?f ?d ?b))
                            '((?f . full)
                              (?d . directory)
                              (?b . basename))))))

     (list scop (and (not (equal scop 'directory))
                     current-prefix-arg
                     (cdr (assoc (read-char-choice
                                  "Style: (n)one, (l)ine, (c)olumn, or (p)oint? "
                                  '(?n ?l ?c ?p))
                                 '((?n . nil)
                                   (?l . line)
                                   (?c . line-column)
                                   (?p . point))))))))
  (message "%S %S" scope pos-style))
  • That's why I figured it didn't work. I did think of doing something like that (naïvely using setq, though), but I couldn't figure a way to get around the scoping issue. Can you provide an example using a let-binding? – Sean Allred Dec 7 '14 at 19:18
  • 1
    See above. Also, you don't need when here; it is extra. What's more, many people (me too) prefer to not use when when the return value is important. We use when and until only for side effects. This makes it easier for humans to understand the code (the intent). – Drew Dec 7 '14 at 19:22
  • Good points about side-effects; I'll keep that in mind for future development. And ah!! It seems so simple now that you laid it out! Thanks :) – Sean Allred Dec 7 '14 at 19:24
  • By the way, you don't need to use scop rather than scope here – is that another style choice? – Sean Allred Dec 7 '14 at 19:27
  • Yes, it just makes it easier to read (IMO). You saw how easy it was to confuse the input parameter with using it inside `interactive'. This helps human readers realize that this local variable is not the same thing. It is true that a function parameter cannot be a dynamic variable in Emacs Lisp, but it's best to help readers avoid any confusion here (IMO). – Drew Dec 7 '14 at 21:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.