4

I use ido for switching buffers, and it is awesome. I also have (flx-ido mode t) in my init file.

I have run into a problem that causes me to switch to a buffer different from what I was expecting. I will explain with an example:

Say I have two buffers, EmacsBuffer, and EightyMegabytesAndConstantlySwapping. I switch to a different buffer, e.g. *scratch*, and now I want to get back to EmacsBuffer, so I do C-x b and start typing: e m a c... This is what I see:

Buffer: emac[sBuffer]{EightyMegabytesAndConstantlySwapping}
EmacsBuffer

As you can see, the candidate for tab-completion is EmacsBuffer, as I would expect. However, because I have flex enabled, the other buffer is fuzzy-matched, and so it is the candidate to immediately switch to. Since I usually am looking only at what I am typing, I see that EmacsBuffer is the candidate for tab-completion, so I immediately hit RET, and am surprised when it switches to EightyMegabytesAndConstantlySwapping. How do I change this so that the immediate-switch buffer is the same as the tab-completion buffer?

I could just disable flex, but I do find it useful, because e.g. if I don't have a buffer named EmacsBuffer, I like that e m a c s matches EightyMegabytesAndConstantlySwapping.

  • 2
    Looks like the behavior of flx-ido-mode is to favor the longest match. I don't see a straightforward way to tweak this behavior. – glucas Dec 4 '14 at 19:42
  • Not a real answer, but might solve your problem: Is it viable to give one of these files different names? – Malabarba Dec 4 '14 at 21:16
  • @Malabarba Not really. I gave a simplified example, but in practice it happens even for things that may not be acronyms. Also, with the amount of files I have open on a regular basis, it will be pretty hard to guarantee that there isn't a conflict somewhere. – Scott Weldon Dec 4 '14 at 23:36
  • 1
    Maybe you can bind RET to send TAB and RET in the ido completion map. Not sure what that might break, though. – glucas Dec 5 '14 at 17:18
  • @glucas That could work. I think the combination of your two comments are worthy of an answer. :) – Scott Weldon Dec 5 '14 at 17:59
2

From looking at the source, flx-ido-mode favors the longest potential match. There aren't any options to tune this behavior.

You might be able to get what you want by tweaking the ido key bindings. Ido has a few different key maps, so depending on exactly what you want you could modify ido-common-completion-map, ido-file-completion-map, or ido-buffer-completion-map.

A couple thoughts:

  • You could add an ido binding to toggle flx-ido-mode on and off. Perhaps leave it off by default and toggle it on when you need it. This seems to work:

    ;; always start ido with flx matching off
    (add-hook 'ido-setup-hook (lambda () (flx-ido-mode -1)))
    
    ;; toggle flx matching without writing to the minibuffer
    (defun quietly-toggle-flx-ido-mode ()
      (interactive)
      (let ((minibuffer-message-timeout 0))
        (flx-ido-mode 'toggle)))
    
    ;; define a key to toggle flx matching while in ido
    (define-key ido-common-completion-map (kbd "<f8>") #'quietly-toggle-flx-ido-mode)
    
  • You could rebind RET to first trigger tab completion. I haven't played with this, but something like:

    (defun ido-complete-and-exit ()
      (interactive)
      (ido-complete)
      (ido-exit-minibuffer))
    
    (define-key ido-common-completion-map (kbd "RET") #'ido-complete-and-exit)
    

EDIT

As noted in the comments, the second example above does not work. Unfortunately I'm not familiar enough with ido internals to propose a solution along these lines that doesn't break other ido behavior.

The best solution would be to revise how flx sorts the candidates. I see some open issues along these lines, e.g. https://github.com/lewang/flx/issues/63.

  • Hmm.. the code you gave doesn't seem to work (no errors though). I'll hack at it for a while and report back if I get it working. – Scott Weldon Dec 5 '14 at 20:51
  • 1
    Yeah, I see that -- sorry! I tried using ido-select-text instead of ido-exit-minibuffer. That works for this one test case, but I think it'll break when tab-completion yields more than one candidate. – glucas Dec 5 '14 at 21:27
  • Yeah that did the same thing for me. It also didn't work when switching directly to the previous buffer (e.g. C-x b RET). – Scott Weldon Dec 5 '14 at 21:28
  • Accepted this answer, though I will keep hacking at it to see if I can get the second solution to work, because I think that would be ideal (after having the root cause fixed of course). – Scott Weldon Dec 5 '14 at 22:59

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.