[Top][All Lists]

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

Problems with catch and throw

From: Tassilo Horn
Subject: Problems with catch and throw
Date: Thu, 04 Oct 2007 18:16:52 +0200
User-agent: Gnus/5.110007 (No Gnus v0.7) Emacs/23.0.50 (gnu/linux)


I use a home-brewn function [1] instead of `execute-extended-command'
most of the time.  It uses `read-from-minibuffer' to get a command
abbrev from the user and then executes the command whose abbreviation
was given.

Now I'd like to bind TAB in my function so that it aborts
`read-from-minibuffer' and my function and falls back to
`execute-extended-command' where the current minibuffer contents are
inserted as initial input.

That sounds like a good candidate for catch/throw to me.  A minimal
working example is:

--8<---------------cut here---------------start------------->8---
(catch 'foo
  (read-from-minibuffer "test: " nil
                        (let ((map (copy-keymap minibuffer-local-map)))
                          (define-key map "\C-i" (lambda ()
                                                   (throw 'foo 
--8<---------------cut here---------------end--------------->8---

Hit `C-j' after the last closing paren and type "foobar" at the "test: "
prompt.  The form's result is "foobar" then.

So now here's my function with this mechanism applied.  But it doesn't
work like the minimal example.  (minibuffer-contents) always returns the
empty string "".  Why is that?

--8<---------------cut here---------------start------------->8---
(defun exec-abbrev-cmd (prefixarg)
  "Query for a command abbreviation like \"mbm\" and calculate a
list of all commands of the form \"m[^-]*-b[^-]*-m[^-]*$\".

If this list has only one item, this command will be executed
directly. If there a more choices, the user will be queried which
one to call.

The PREFIXARG is passed on to the invoked command.

With TAB fall back to `execute-extended-command'."
  (interactive "P")
  (let ((catch-val
         (catch 'escape-from-exec-abbrev-cmd
           (let* ((abbrev (read-from-minibuffer
                           "Command Abbrev: "
                           (let ((map (copy-keymap minibuffer-local-map)))
                             (define-key map "\C-i"
                               (lambda ()
                                 ;; WHY RETURN MINIBUFFER-CONTENTS ""
                                 ;; HERE, ALTHOUGH I TYPED FOOBAR AT THE
                                 ;; PROMPT???
                                 (message "cont = " (minibuffer-contents))
                                 (throw 'escape-from-exec-abbrev-cmd
                  (regexp (concat "^"
                                  (let ((part-list (split-string abbrev "-")))
                                    (if (= 1 (length part-list))
                                        ;; abc => a*-b*-c*
                                        (mapconcat #'list abbrev "[^-]*-")
                                      ;; ahead-b-c => ahead*-b*-c*
                                      (mapconcat #'identity part-list 
                  (commands (exec-abbrev-cmd-sort
                             (remove-if-not (lambda (string)
                                              (string-match regexp string))
                                            (let (c)
                                               (lambda (a)
                                                 (if (commandp a)
                                                     (push (symbol-name a) c))))
             (if (not commands)
                 (message "No such command.")
               (let ((c (cond ((> (length commands) 1)
                                (if (and (featurep 'ido) ido-mode)
                                    ;; ido is available and enabled, so use it.
                                    (ido-completing-read "Command: " commands)
                                  ;; fallback to normal completion with the
                                  ;; most frequently used command as default.
                                  (completing-read (concat "Command (defaults 
to `"
                                                           (car commands) "'): 
                                                   nil t nil nil (car 
                              (t (intern (car commands))))))
                 (call-interactively c t)
                 (when exec-abbrev-cmd-mode
                   (exec-abbrev-cmd-record c)))))
           ;; Always return nil so that an escape with TAB is the only thing
           ;; that makes `catch-val' non-nil.
    (when catch-val
      (message "catch-val = " catch-val)
      (execute-extended-command prefixarg)
      (insert catch-val))))
--8<---------------cut here---------------end--------------->8---

I guess it's something obvious, but I cannot see any principal
difference between the simple working example and the code of my

Any pointers are highly welcome!


reply via email to

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