unofficial mirror of help-gnu-emacs@gnu.org
 help / color / mirror / Atom feed
* Re: completion-ui.el question: my vimpulse-show-completion-menu function always gives me an empty menu
@ 2007-04-12 23:16 Jason Spiro
       [not found] ` <c241693f0704121619i14d16188j2cdb3e5c6baf6860@mail.gmail.com>
  0 siblings, 1 reply; 4+ messages in thread
From: Jason Spiro @ 2007-04-12 23:16 UTC (permalink / raw)
  To: Toby Cubitt, help-gnu-emacs; +Cc: Alessandro Piras, Brad Beveridge

Hi list, hello Toby,

As you may know, I am working on vimpulse[1] which extends viper-mode
to emulate the most useful Vim keys in Emacs.  I am hoping to add C-n
and C-p completion to vimpulse, and I am wondering how to do so.

I am hoping to use hippie-expand because it can complete:

- words,
- filenames, and
- entire buffer lines

among other things.[2]  Dabbrev seems to basically only complete
words.  I am trying to emulate Vim's completion behavior, and Vim can
complete all those things and more.[3]

> As an Elisp coder, you're not supposed to invoke *any* completion
> interface explicitly, as you've tried to do. Deciding which combination
> of user-interfaces to use is the user's business, not the package
> writer's. Maybe some users want to use menu completion, but others
> prefer to see a list in the echo area, whilst still others just want a
> tooltip to popup after a delay, etc. etc. Completion-UI offloads those
> choices onto the user, which is where they should be.

OK.  I will tell vimpulse users they should set certain Completion-UI
settings themselves to get something closer to Vim completion.  But
meanwhile, I still have a question about the code I am writing myself
for testing purposes.

;; Begin code {{{

(require 'completion-ui)

;; Note: This code has an additional bug in addition to the problem I
;; am asking about in this mailing list message:
;; When called with a MAXNUM of nil, this func sometimes fails.  (Seems
;; to work the first time, then fail all times after, in such cases.
;; To fix, call with a normal MAXNUM.)
(defun vimpulse-try-hippie-expand-listed-functions (prefix &optional maxnum)
;  (interactive "*MString to expand:
;nMaximum number of expansions, or nil for unlimited: ")
 (setq expansions nil)
 (with-temp-buffer
   (insert-string prefix)
   (hippie-expand nil)
   (unless (string-equal (current-message) "No expansion found")
     (while (and
             (not (string-equal
                   (current-message)
                   "No further expansions found"))
             (if maxnum (not (= (length expansions) maxnum))))
       ;; Hippie-expand was designed to be run interactively.  If
       ;; this-command and last-command are equal, it assumes it's
       ;; being called as a "repeated use" (additional call without
       ;; moving the point) and searches for additional expansions
       ;; with the same prefix.  So, make this-command and
       ;; last-command equal.
       (setq this-command last-command)
       (hippie-expand nil)
       (add-to-list 'expansions (buffer-string))
       (buffer-string)
     ))
   expansions))

(defun jason-problem-demo ()
 (interactive)
 (setq-default completion-function
'vimpulse-try-hippie-expand-listed-functions)
 (setq completion-function 'vimpulse-try-hippie-expand-listed-functions)
 ;; is this always necessary?  Am I even ever supposed to call it?
 (completion-setup-overlay 'prefix)
 (completion-show-menu))

;; }}} End code

Whenever I start typing a word then run
M-x jason-problem-demo I get an empty menu.  Why?

Am I using
completion-show-menu wrong?  It errors on me if I don't call
completion-setup-overlay first, so I call it first.  Should I?

Cheers,
Jason[5]

[1] http://www.emacswiki.org/cgi-bin/wiki/vimpulse.el

[2] Unfortunately hippie-expand can't complete multiple-word sequences
like dabbrev can when you press M-/ SPC M-/ SPC M-/.  Vim can do it:
just press CTRL-X CTRL-P repeatedly.  But I hope I'll eventually fix
that.

Then again, maybe I'll never have time to make that change to
hippie-expand.  So maybe I should have Completion-UI call
dabbrev-expand instead.

[3] e.g. CTRL-X CTRL-T for thesaurus completion, or many other[4] things.

[4] http://ianua.initd.org/vimit/vim63/html/insert.html#ins-completion

[5] P.S. You may want to mention in the completion-ui documentation at
the top of the file that
http://www.emacswiki.org/cgi-bin/wiki/CompletionUI#toc2 has examples
of how to use completion-ui with dabbrev and etags.  If I knew that
info, it would have saved me time. :-)

-- 
Jason Spiro: computer consulting with a smile.
I provide software development and training services to clients worldwide.
Contact me for a FREE consultation. Satisfaction guaranteed.
+1 (416) 781-5938 / Email: info@jspiro.com / MSN: jasonspiro@hotmail.com

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Fwd: completion-ui.el question: my vimpulse-show-completion-menu function always gives me an empty menu
       [not found] ` <c241693f0704121619i14d16188j2cdb3e5c6baf6860@mail.gmail.com>
@ 2007-04-13  8:00   ` Toby Cubitt
  2007-04-13  8:31     ` Jason Spiro
  0 siblings, 1 reply; 4+ messages in thread
From: Toby Cubitt @ 2007-04-13  8:00 UTC (permalink / raw)
  To: Jason A. Spiro; +Cc: help-gnu-emacs

Jason A. Spiro wrote:
>> As an Elisp coder, you're not supposed to invoke *any* completion
>> interface explicitly, as you've tried to do. Deciding which combination
>> of user-interfaces to use is the user's business, not the package
>> writer's. Maybe some users want to use menu completion, but others
>> prefer to see a list in the echo area, whilst still others just want a
>> tooltip to popup after a delay, etc. etc. Completion-UI offloads those
>> choices onto the user, which is where they should be.
> 
> OK.  I will tell vimpulse users they should set certain Completion-UI
> settings themselves to get something closer to Vim completion.  But
> meanwhile, I still have a question about the code I am writing myself
> for testing purposes.

I now understand a bit better what you're trying to do. I guess in the 
special case of trying to emulate vim, my arguments are specious, since 
you *want* to make user-interface choices for the user. So I guess 
vimpulse-mode could set the completion-ui customization variables 
appropriately. However, the main point still stands: you shouldn't be 
calling any internal completion-ui functions (such as completion-menu) 
from your own code.


> ;; Begin code {{{
> 
> (require 'completion-ui)
> 
> ;; Note: This code has an additional bug in addition to the problem I
> ;; am asking about in this mailing list message:
> ;; When called with a MAXNUM of nil, this func sometimes fails.  (Seems
> ;; to work the first time, then fail all times after, in such cases.
> ;; To fix, call with a normal MAXNUM.)

This might cause problems later, since completion-UI occasionally needs 
to call it with a nil MAXNUM. The function is then supposed to return a 
list of all possible completions.

BTW, I realise that setting up a temporary buffer and simulating an 
interactive call to hippie-expand is a simple way to get what you want, 
but it also seems a bit ugly to me. Hippie-expand contains a lot of code 
that deals with user-interface issues, and you're using completion-UI 
for that. Wouldn't it be better to read through the hippie-expand code, 
work out which internal function returns the list of completions as its 
return value, and call that instead? It's more work, but also less ugly, 
more efficient, and I suspect more robust.


> (defun vimpulse-try-hippie-expand-listed-functions (prefix &optional 
> maxnum)
> ;  (interactive "*MString to expand:
> ;nMaximum number of expansions, or nil for unlimited: ")
> (setq expansions nil)
> (with-temp-buffer
>   (insert-string prefix)
>   (hippie-expand nil)
>   (unless (string-equal (current-message) "No expansion found")
>     (while (and
>             (not (string-equal
>                   (current-message)
>                   "No further expansions found"))
>             (if maxnum (not (= (length expansions) maxnum))))
>       ;; Hippie-expand was designed to be run interactively.  If
>       ;; this-command and last-command are equal, it assumes it's
>       ;; being called as a "repeated use" (additional call without
>       ;; moving the point) and searches for additional expansions
>       ;; with the same prefix.  So, make this-command and
>       ;; last-command equal.
>       (setq this-command last-command)
>       (hippie-expand nil)
>       (add-to-list 'expansions (buffer-string))
>       (buffer-string)
>     ))
>   expansions))

This is almost OK. Completion-UI expects the completion-function to 
return a list of completion strings *without* the prefix. So you need to 
change "expansions" in the last line to:

   (mapcar (lambda (str) (substring str 1)) expansions)


> (defun jason-problem-demo ()
> (interactive)
> (setq-default completion-function
> 'vimpulse-try-hippie-expand-listed-functions)
> (setq completion-function 'vimpulse-try-hippie-expand-listed-functions)
> ;; is this always necessary?  Am I even ever supposed to call it?
> (completion-setup-overlay 'prefix)
> (completion-show-menu))
 > ;; }}} End code
 >
 > Whenever I start typing a word then run
 > M-x jason-problem-demo I get an empty menu.  Why?
 >
 > Am I using
 > completion-show-menu wrong?  It errors on me if I don't call
 > completion-setup-overlay first, so I call it first.  Should I?

This won't work, because you're *still* fighting completion-UI rather 
than working harmoniously with it :) What you should be doing is setting 
'completion-function' to 'vimpulse-try-hippie-expand-listed-functions, 
and then going off to make a cup of tea, have a bite to eat, watch a 
movie, and then spend the weekend fishing and contemplating whether you 
really want to spend so much of your life at a desk hacking Emacs :) 
Because setting 'completion-function' is *all* you have to do!

Once 'completion-function' is set, when you type some characters and 
then call 'complete-word-at-point' (bound to M-TAB by default), 
everything should work. (At least, it did when I just tested it!) By 
default, you can bring up the menu using 'completion-show-menu' (bound 
to M-down by default). Given that you seem to want to show the menu 
immediately, in your case you might want to set 
'completion-auto-show-menu' to non-nil, so that the menu is displayed 
immediately after calling 'complete-word-at-point'. (Again, setting the 
'completion-auto-show-menu' customization option should normally be left 
to the user to customize, but in your case I can see why you might want 
vimpulse-mode to do the customization itself.)


> Cheers,
> Jason[5]
> 
> [1] http://www.emacswiki.org/cgi-bin/wiki/vimpulse.el
> 
> [2] Unfortunately hippie-expand can't complete multiple-word sequences
> like dabbrev can when you press M-/ SPC M-/ SPC M-/.  Vim can do it:
> just press CTRL-X CTRL-P repeatedly.  But I hope I'll eventually fix
> that.
> 
> Then again, maybe I'll never have time to make that change to
> hippie-expand.  So maybe I should have Completion-UI call
> dabbrev-expand instead.

How exactly does this multiple-word completion work? I don't follow.


> [3] e.g. CTRL-X CTRL-T for thesaurus completion, or many other[4] things.
> 
> [4] http://ianua.initd.org/vimit/vim63/html/insert.html#ins-completion
> 
> [5] P.S. You may want to mention in the completion-ui documentation at
> the top of the file that
> http://www.emacswiki.org/cgi-bin/wiki/CompletionUI#toc2 has examples
> of how to use completion-ui with dabbrev and etags.  If I knew that
> info, it would have saved me time. :-)

Ah, I kind of assumed you'd already seen them. I should probably include 
the examples in the documentation at the top of the file. Or better 
still, get round to writing some texinfo documentation for 
completion-UI. There are a lot of features I suspect only I know about 
at the moment :)


Toby

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Fwd: completion-ui.el question: my vimpulse-show-completion-menu function always gives me an empty menu
  2007-04-13  8:00   ` Fwd: " Toby Cubitt
@ 2007-04-13  8:31     ` Jason Spiro
  2007-04-13  8:50       ` Toby Cubitt
  0 siblings, 1 reply; 4+ messages in thread
From: Jason Spiro @ 2007-04-13  8:31 UTC (permalink / raw)
  To: Toby Cubitt; +Cc: help-gnu-emacs

2007/4/13, Toby Cubitt <tsc25@cantab.net> wrote:
[snip]
Thank you kindly for your detailed reply.  I will print it out and
read through it carefully.

> How exactly does this multiple-word completion work? I don't follow.

For example, type:  The quick brown fox jumped over the lazy dog. My
favorite foM-/ SPC M-/ SPC M-/ SPC M-/ SPC M-/ SPC M-/

It should write: The quick brown fox jumped over the lazy dog. My
favorite fox jumped over the lazy dog"

-- 
Jason Spiro: computer consulting with a smile.
I provide software development and training services to clients worldwide.
Contact me for a FREE consultation. Satisfaction guaranteed.
+1 (416) 781-5938 / Email: info@jspiro.com / MSN: jasonspiro@hotmail.com

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Fwd: completion-ui.el question: my vimpulse-show-completion-menu function always gives me an empty menu
  2007-04-13  8:31     ` Jason Spiro
@ 2007-04-13  8:50       ` Toby Cubitt
  0 siblings, 0 replies; 4+ messages in thread
From: Toby Cubitt @ 2007-04-13  8:50 UTC (permalink / raw)
  To: Jason Spiro; +Cc: help-gnu-emacs

Jason Spiro wrote:
> 2007/4/13, Toby Cubitt <tsc25@cantab.net> wrote:
 >> (defun vimpulse-try-hippie-expand-listed-functions
 >>        (prefix &optional maxnum)
 >> ;  (interactive "*MString to expand:
 >> ;nMaximum number of expansions, or nil for unlimited: ")
 >> (setq expansions nil)
 >> (with-temp-buffer
 >>   (insert-string prefix)
 >>   (hippie-expand nil)
 >>   (unless (string-equal (current-message) "No expansion found")
 >>     (while (and
 >>             (not (string-equal
 >>                   (current-message)
 >>                   "No further expansions found"))
 >>             (if maxnum (not (= (length expansions) maxnum))))
 >>       ;; Hippie-expand was designed to be run interactively.  If
 >>       ;; this-command and last-command are equal, it assumes it's
 >>       ;; being called as a "repeated use" (additional call without
 >>       ;; moving the point) and searches for additional expansions
 >>       ;; with the same prefix.  So, make this-command and
 >>       ;; last-command equal.
 >>       (setq this-command last-command)
 >>       (hippie-expand nil)
 >>       (add-to-list 'expansions (buffer-string))
 >>       (buffer-string)
 >>     ))
 >>   expansions))

 > This is almost OK. Completion-UI expects the completion-function to
 > return a list of completion strings *without* the prefix. So you need
 > to change "expansions" in the last line to:
 >   (mapcar (lambda (str) (substring str 1)) expansions)

Sorry, this isn't quite correct. It should of course be:

   (mapcar (lambda (str) (substring str (length prefix))) expansions)


>> How exactly does this multiple-word completion work? I don't follow.
> 
> For example, type:  The quick brown fox jumped over the lazy dog. My
> favorite foM-/ SPC M-/ SPC M-/ SPC M-/ SPC M-/ SPC M-/
> 
> It should write: The quick brown fox jumped over the lazy dog. My
> favorite fox jumped over the lazy dog"

I see. This relies on the fact that the first dabbrev expansion is the 
one that is closest in the buffer. If you're completion function (or 
rather, hippie-expand's) returned the completions in this order, you 
could get the same behaviour using completion-UI. My personal favourite 
is to enable 'completion-use-dynamic', so that you don't even need to 
type the M-/ equivalent (M-TAB).

Toby

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2007-04-13  8:50 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-04-12 23:16 completion-ui.el question: my vimpulse-show-completion-menu function always gives me an empty menu Jason Spiro
     [not found] ` <c241693f0704121619i14d16188j2cdb3e5c6baf6860@mail.gmail.com>
2007-04-13  8:00   ` Fwd: " Toby Cubitt
2007-04-13  8:31     ` Jason Spiro
2007-04-13  8:50       ` Toby Cubitt

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).