3

When I run the find-file command and hit the tab key twice without giving anything, I get the Completion List of my, for instance, home directory. By default it lists everything inside, including the hidden files and directories ("dot-files").

Is it possible to exclude the dot-files in this case? But additionally, when I start typing . and then hit the tab twice, I would like to see the all or matched dot-files.

1
  • This isn't really helpful, because I don't know why does it work like that, but I know that Emacs doesn't autocmplete .git directory for me. (I'm not sure if that's due to IDO or Magit, but that would be a direction I'd look in first.)
    – wvxvw
    Mar 16, 2015 at 15:40

2 Answers 2

3

I solved this by modifying the answer here. This works for emacs 24.3.1, at least.

I put the following in my .emacs file:

; Don't show dot files in the completion...                               
(require 'cl-lib) ; Needed for cl-remove-if-not                                        

; Define string-suffix-p.                                                       
(defun string-suffix-p (str1 str2 &optional ignore-case)
  (let ((begin2 (- (length str2) (length str1))) (end2 (length str2)))
    (when (< begin2 0) (setq begin2 0))
    (eq t (compare-strings str1 nil nil str2 begin2 end2 ignore-case))))

; Modify to return true for files you're interested in.                         
(defun my-file-match (str)
  (and (not (cl-remove-if-not (lambda (x) (string-suffix-p x str))
                               completion-ignored-extensions))
       (not (string-prefix-p "." str))))

; Add the advice after completion.                                              
(defadvice completion-file-name-table (after ignoring-backups-f-n-completion
                                             activate)
  (if (and (listp ad-return-value) (stringp (car ad-return-value))
           (cdr ad-return-value))
      (let ((newlis (cl-remove-if-not 'my-file-match ad-return-value)))
        ; If there are no qualifiers, list everything.                          
        (if (and (listp newlis) (cdr newlis))
            (setq ad-return-value newlis)))))
1
  • You might consider switching to cl-lib, the successor to cl, and using cl-remove-if-not.
    – Dan
    Dec 19, 2015 at 11:14
0

The function completion-file-name-table is called with three arguments. The first one is the string to be completed, and the second one is a predicate with which it is expected to filter possible matches.

We can put an advice around completion-file-name-table that calls the function with the original arguments unchanged when the first argument starts with a dot (so we have auto-completion when we actually want to open a dot-file), but that calls completion-file-name-table with a dot-file-excluding predicate when the first argument does not start with a dot.

(defun completion-f-n-table-ignoring-dot-prefix (fun str pred flag)
  "Call `completion-file-name-table' with a predicate that
ignores matches starting with a dot, unless STR starts with a
dot."
  (funcall fun str
           (cond ((string-prefix-p "." (file-name-nondirectory str))
                  pred)
                 ((not pred)
                  (lambda (str)
                    (not (string-prefix-p "." str))))
                 (t
                  (lambda (str)
                    (and (not (string-prefix-p "." str))
                         (funcall pred str)))))
           flag))

(advice-add 'completion-file-name-table :around
            'completion-f-n-table-ignoring-dot-prefix)

To restore the standard behaviour, remove the advice

(advice-remove 'completion-file-name-table
               'completion-f-n-table-ignoring-dot-prefix)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.