.emacs.d / files / ido.el

;;; Interactive do, find-file and iswitchb replacement with fuzzy/flex matching.

(require 'ido)
(ido-mode t)
;; fuzzy matching is a must have
(setq ido-enable-flex-matching t)
;; forget latest selected directory names
(setq ido-enable-last-directory-history nil)
;; Allow the same buffer to be open in different frames
(setq ido-default-buffer-method 'selected-window)

;; Display ido results vertically, rather than horizontally
(setq ido-decorations (quote ("\n-> " "" "\n   " "\n   ..." "[" "]" " [No match]" " [Matched]" " [Not readable]" " [Too big]" " [Confirm]")))
(defun ido-disable-line-trucation () (set (make-local-variable 'truncate-lines) nil))
(add-hook 'ido-minibuffer-setup-hook 'ido-disable-line-trucation)

;; see:
(defun ido-smart-select-text ()
  "Select the current completed item.  Do NOT descend into directories."
  (when (and (or (not ido-require-match)
                 (if (memq ido-require-match
                           '(confirm confirm-after-completion))
                     (if (or (eq ido-cur-item 'dir)
                             (eq last-command this-command))
                       (setq ido-show-confirm-message t)
             (not ido-incomplete-regexp))
    (when ido-current-directory
      (setq ido-exit 'takeprompt)
      (unless (and ido-text (= 0 (length ido-text)))
        (let ((match (ido-name (car ido-matches))))
          (throw 'ido
                 (setq ido-selected
                       (if match
                           (replace-regexp-in-string "/\\'" "" match)
                       ido-text ido-selected
                       ido-final-text ido-text)))))

(defun my-ido-keys ()
  (bind-key "C-<tab>" 'ido-smart-select-text ido-file-dir-completion-map))

(add-hook 'ido-setup-hook 'my-ido-keys)

;; ido and imenu integration
(defun ido-goto-symbol (&optional symbol-list)
  "Refresh imenu and jump to a place in the buffer using Ido."
  (unless (featurep 'imenu)
    (require 'imenu nil t))
   ((not symbol-list)
    (let ((ido-mode ido-mode)
           (if (boundp 'ido-enable-flex-matching)
               ido-enable-flex-matching t))
          name-and-pos symbol-names position)
      (unless ido-mode
        (ido-mode 1)
        (setq ido-enable-flex-matching t))
      (while (progn
               (setq imenu--index-alist nil)
               (ido-goto-symbol (imenu--make-index-alist))
               (setq selected-symbol
                     (ido-completing-read "Symbol? " symbol-names))
               (string= (car imenu--rescan-item) selected-symbol)))
      (unless (and (boundp 'mark-active) mark-active)
        (push-mark nil t nil))
      (setq position (cdr (assoc selected-symbol name-and-pos)))
       ((overlayp position)
        (goto-char (overlay-start position)))
        (goto-char position)))))
   ((listp symbol-list)
    (dolist (symbol symbol-list)
      (let (name position)
         ((and (listp symbol) (imenu--subalist-p symbol))
          (ido-goto-symbol symbol))
         ((listp symbol)
          (setq name (car symbol))
          (setq position (cdr symbol)))
         ((stringp symbol)
          (setq name symbol)
          (setq position
                (get-text-property 1 'org-imenu-marker symbol))))
        (unless (or (null position) (null name)
                    (string= (car imenu--rescan-item) name))
          (setq word-under-cursor (thing-at-point 'symbol))
          (setq fix-the-order (not (null (member word-under-cursor symbol-names))))
          (add-to-list 'symbol-names name)
          (when fix-the-order
            (delete word-under-cursor symbol-names)
            (add-to-list 'symbol-names word-under-cursor))
          (add-to-list 'name-and-pos (cons name position))))))))

;; sort ido filelist by mtime instead of alphabetically
(add-hook 'ido-make-file-list-hook 'ido-sort-mtime)
(add-hook 'ido-make-dir-list-hook 'ido-sort-mtime)
(defun ido-sort-mtime ()
  (setq ido-temp-list
        (sort ido-temp-list
              (lambda (a b)
                 (sixth (file-attributes (concat ido-current-directory b)))
                 (sixth (file-attributes (concat ido-current-directory a)))))))
  (ido-to-end  ;; move . files to end (again)
   (--select (char-equal (string-to-char it) ?.) ido-temp-list))
  (when ido-show-dot-for-dired
    (setq ido-temp-list
          (cons "." (--remove (equal it ".") ido-temp-list)))))