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