* Problems with catch and throw
@ 2007-10-04 16:16 Tassilo Horn
2007-10-05 6:59 ` Barry Margolin
0 siblings, 1 reply; 4+ messages in thread
From: Tassilo Horn @ 2007-10-04 16:16 UTC (permalink / raw)
To: help-gnu-emacs
Hi,
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 ()
(interactive)
(throw 'foo (minibuffer-contents))))
map)))
--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: "
nil
(let ((map (copy-keymap minibuffer-local-map)))
(define-key map "\C-i"
(lambda ()
(interactive)
;; WHY RETURN MINIBUFFER-CONTENTS ""
;; HERE, ALTHOUGH I TYPED FOOBAR AT THE
;; PROMPT???
(message "cont = " (minibuffer-contents))
(throw 'escape-from-exec-abbrev-cmd
(minibuffer-contents))))
map)))
(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)
(mapatoms
(lambda (a)
(if (commandp a)
(push (symbol-name a) c))))
c)))))
(if (not commands)
(message "No such command.")
(let ((c (cond ((> (length commands) 1)
(intern
(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) "'): ")
commands
nil t nil nil (car commands)))))
(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.
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
function.
Any pointers are highly welcome!
Bye,
Tassilo
__________
[1] http://www.tsdh.de/cgi-bin/wiki.pl/exec-abbrev-cmd.el
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: Problems with catch and throw
2007-10-04 16:16 Problems with catch and throw Tassilo Horn
@ 2007-10-05 6:59 ` Barry Margolin
2007-10-05 7:14 ` Tassilo Horn
0 siblings, 1 reply; 4+ messages in thread
From: Barry Margolin @ 2007-10-05 6:59 UTC (permalink / raw)
To: help-gnu-emacs
In article <87myuy26tn.fsf@baldur.tsdh.de>,
Tassilo Horn <tassilo@member.fsf.org> wrote:
> Hi,
>
> 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 ()
> (interactive)
> (throw 'foo
> (minibuffer-contents))))
> map)))
> --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?
The problem isn't with minibuffer-contents, it's with
(message "cont = " (minibuffer-contents))
The first argument to message is a format string, and the remaining
arguments will be substituted for the % codes in the string. Since you
don't have any % codes, it never displays the minibuffer contents. So
that should be:
(message "cont = %s" (minibuffer-contents))
>
> --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: "
> nil
> (let ((map (copy-keymap minibuffer-local-map)))
> (define-key map "\C-i"
> (lambda ()
> (interactive)
> ;; WHY RETURN MINIBUFFER-CONTENTS ""
> ;; HERE, ALTHOUGH I TYPED FOOBAR AT THE
> ;; PROMPT???
> (message "cont = " (minibuffer-contents))
> (throw 'escape-from-exec-abbrev-cmd
> (minibuffer-contents))))
> map)))
> (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)
> (mapatoms
> (lambda (a)
> (if (commandp a)
> (push (symbol-name a)
> c))))
> c)))))
> (if (not commands)
> (message "No such command.")
> (let ((c (cond ((> (length commands) 1)
> (intern
> (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)
> "'): ")
> commands
> nil t nil nil (car
> commands)))))
> (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.
> 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
> function.
>
> Any pointers are highly welcome!
>
> Bye,
> Tassilo
> __________
> [1] http://www.tsdh.de/cgi-bin/wiki.pl/exec-abbrev-cmd.el
--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: Problems with catch and throw
2007-10-05 6:59 ` Barry Margolin
@ 2007-10-05 7:14 ` Tassilo Horn
2007-10-05 8:11 ` Tassilo Horn
0 siblings, 1 reply; 4+ messages in thread
From: Tassilo Horn @ 2007-10-05 7:14 UTC (permalink / raw)
To: help-gnu-emacs
Barry Margolin <barmar@alum.mit.edu> writes:
Hi Barry,
> The problem isn't with minibuffer-contents, it's with
>
> (message "cont = " (minibuffer-contents))
>
> The first argument to message is a format string, and the remaining
> arguments will be substituted for the % codes in the string. Since
> you don't have any % codes, it never displays the minibuffer contents.
> So that should be:
>
> (message "cont = %s" (minibuffer-contents))
Oh my god, that's more than awkward. That happens when you use `insert'
and `message' in parallel. :-P
Ok, then the real question is: How can I invoke
`execute-extended-command' with an initial input string?
Bye,
Tassilo
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: Problems with catch and throw
2007-10-05 7:14 ` Tassilo Horn
@ 2007-10-05 8:11 ` Tassilo Horn
0 siblings, 0 replies; 4+ messages in thread
From: Tassilo Horn @ 2007-10-05 8:11 UTC (permalink / raw)
To: help-gnu-emacs
Tassilo Horn <tassilo@member.fsf.org> writes:
Hi,
> Ok, then the real question is: How can I invoke
> `execute-extended-command' with an initial input string?
For the record: That seems to be not possible, but you can mimic its
behavior like this:
--8<---------------cut here---------------start------------->8---
(let ((command (completing-read "M-x "
(let (commands)
(mapatoms (lambda (a)
(when (commandp a)
(push (symbol-name a)
commands))))
commands)
nil t catch-val)))
(command-execute (intern command) t nil t))
--8<---------------cut here---------------end--------------->8---
Bye,
Tassilo
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2007-10-05 8:11 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-10-04 16:16 Problems with catch and throw Tassilo Horn
2007-10-05 6:59 ` Barry Margolin
2007-10-05 7:14 ` Tassilo Horn
2007-10-05 8:11 ` Tassilo Horn
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).