Subject: bug#5952: 23.1.95; Some new ido features on top of virtual buffers

From: Leo <[email-masked]>
Date: Thu, 15 Apr 2010 11:54:37 +0100

Hello John,

Thank you for the new feature 'virtual buffers' to ido.el in the devel
repo. I have been using a similar feature locally but since discovered
your patch, I switched to it.

Here are three patches that add three features:

1. make it possible to toggle the use of virtual buffers. Bind the
   command to C-o when switching buffer (o for 'old' buffers).

2. handle files with same base names by appending one level of parent
   directory. Some files may still be ignored but the chance is much
   slimmer.

3. automatically bring in virtual buffers when user input doesn't match
   existing ones.

>From 9577b975915066f95ea744b54d25f594d7ceeeac Mon Sep 17 00:00:00 2001
From: Leo <[email-masked]>
Date: Thu, 15 Apr 2010 08:39:13 +0100
Subject: [PATCH 1/3] New function ido-toggle-virtual-buffers and bind to C-o

---
 lisp/ido.el |   12 ++++++++++++
 1 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/lisp/ido.el b/lisp/ido.el
index ac97aed..704bf22 100644
--- a/lisp/ido.el
+++ b/lisp/ido.el
@@ -1633,6 +1633,7 @@ This function also adds a hook to the minibuffer."
     (define-key map "\C-x\C-f" 'ido-enter-find-file)
     (define-key map "\C-x\C-b" 'ido-fallback-command)
     (define-key map "\C-k" 'ido-kill-buffer-at-head)
+    (define-key map "\C-o" 'ido-toggle-virtual-buffers)
     (set-keymap-parent map ido-common-completion-map)
     (setq ido-buffer-completion-map map)))
 
@@ -2182,6 +2183,7 @@ If cursor is not at the end of the user input, move to end of input."
 	   (ido-current-directory nil)
 	   (ido-directory-nonreadable nil)
 	   (ido-directory-too-big nil)
+           (ido-use-virtual-buffers ido-use-virtual-buffers)
 	   (require-match (confirm-nonexistent-file-or-buffer))
 	   (buf (ido-read-internal 'buffer (or prompt "Buffer: ") 'ido-buffer-history default
 				   require-match initial))
@@ -2707,6 +2709,16 @@ C-x C-f ... C-d  enter `dired' on current directory."
 	(setq ido-exit 'keep)
 	(exit-minibuffer))))
 
+(defun ido-toggle-virtual-buffers ()
+  "Toggle the use of virtual buffers.
+See `ido-use-virtual-buffers' for explanation of virtual buffer."
+  (interactive)
+  (when (and ido-mode (eq ido-cur-item 'buffer))
+    (setq ido-use-virtual-buffers (not ido-use-virtual-buffers))
+    (setq ido-text-init ido-text)
+    (setq ido-exit 'refresh)
+    (exit-minibuffer)))
+
 (defun ido-reread-directory ()
   "Read current directory again.
 May be useful if cached version is no longer valid, but directory
-- 
1.7.0.4

>From 8ed6d4f903efcab1d915ec67bb907bd9bb4f2c09 Mon Sep 17 00:00:00 2001
From: Leo <[email-masked]>
Date: Wed, 14 Apr 2010 18:58:18 +0100
Subject: [PATCH 2/3] Use parent directory for files with same base name

---
 lisp/ido.el |   24 +++++++++++++++++++++++-
 1 files changed, 23 insertions(+), 1 deletions(-)

diff --git a/lisp/ido.el b/lisp/ido.el
index 704bf22..92d2a09 100644
--- a/lisp/ido.el
+++ b/lisp/ido.el
@@ -3410,6 +3410,21 @@ for first matching file."
     (run-hooks 'ido-make-buffer-list-hook)
     ido-temp-list))
 
+(defun ido-find-duplicate-basenames (files)
+  "Find all the duplicate base names in FILES."
+  (let ((names (mapcar 'file-name-nondirectory files))
+        dups head dup-p)
+    (setq names (sort names 'string<))
+    (while names
+      (setq head (pop names))
+      (while (string= head (car names))
+        (pop names)
+        (setq dup-p t))
+      (when dup-p
+        (push head dups)
+        (setq dup-p nil)))
+    dups))
+
 (defun ido-add-virtual-buffers-to-list ()
   "Add recently visited files, and bookmark files, to the buffer list.
 This is to make them appear as if they were \"virtual buffers\"."
@@ -3418,10 +3433,17 @@ This is to make them appear as if they were \"virtual buffers\"."
   ;; the file which the user might thought was still open.
   (unless recentf-mode (recentf-mode 1))
   (setq ido-virtual-buffers nil)
-  (let (name)
+  (let ((dups (ido-find-duplicate-basenames recentf-list))
+        name dir)
     (dolist (head recentf-list)
       (and (setq name (file-name-nondirectory head))
            (null (get-file-buffer head))
+           (if (not (member name dups))
+               t
+             (setq dir head)
+             (dotimes (__ 2)
+               (setq dir (directory-file-name (file-name-directory dir))))
+             (setq name (file-relative-name head dir)))
            (not (assoc name ido-virtual-buffers))
            (not (member name ido-temp-list))
            (not (ido-ignore-item-p name ido-ignore-buffers))
-- 
1.7.0.4

>From ed1321a6ea51ece2a90bb63842081a5ccee495a9 Mon Sep 17 00:00:00 2001
From: Leo <[email-masked]>
Date: Thu, 15 Apr 2010 08:27:59 +0100
Subject: [PATCH 3/3] Turn on virtual buffers automatically when no matches

---
 lisp/ido.el |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/lisp/ido.el b/lisp/ido.el
index 92d2a09..671e8a8 100644
--- a/lisp/ido.el
+++ b/lisp/ido.el
@@ -4491,7 +4491,14 @@ For details of keybindings, see `ido-find-file'."
 	    (setq ido-exit 'refresh)
 	    (exit-minibuffer)))
 
+        (when (and (eq ido-cur-item 'buffer)
+                   (not ido-matches)
+                   (not ido-use-virtual-buffers))
+          (setq ido-text-init ido-text)
+          (setq ido-use-virtual-buffers t)
+          (setq ido-exit 'refresh)
+          (exit-minibuffer))
+
 	(when (and
 	       ido-rescan
 	       (not ido-matches)
-- 
1.7.0.4

Leo