0

I want to use filesystem path completion in programming modes and their derivatives. To do so, I attempted to add the following code to my init.el:

(add-hook 'prog-mode-hook
          (lambda ()
            (add-hook 'completion-at-point-functions
                      #'comint--complete-file-name-data
                      nil 'local)))

However, it seems that comint--complete-file-name-data always returns non-nil, and prevents other completion-at-point functions from running.

What is the most natural way to solve this issue, or is there a simpler method to achieve the desired result?

3
  • Maybe you can add the function at the end of the hook, so it will run last.
    – NickD
    Commented Dec 18, 2023 at 17:18
  • @Drew this isn't quite what I need. According to the documentation, each function in completion-at-point-functions should return nil when it is not applicable at a point. Perhaps it is possible to write a wrapper around comint--complete-file-name-data which checks whether it is applicable or not, but I anticipate that there might be a more natural solution.
    – Alex
    Commented Dec 18, 2023 at 17:18
  • @NickD This indeed solves the issue; however, when the text around a point looks like a path, I would like path completion to take precedence over others.
    – Alex
    Commented Dec 18, 2023 at 17:21

1 Answer 1

2

EDIT

I suddenly, realized that I did not inspect comint--complete-file-name-data, then while I was checking some things, I accidentally added comint-filename-completion to the global hook (i.e. as follows):

(add-hook 'completion-at-point-functions #'comint-filename-completion)

This seems to have the right effect also. It seems that now Emacs tries completion using the functions in the local completion-at-point-functions first and otherwise falls back to the global value (I guess this is general Emacs behavior, but I was not aware of it before). Anyway, I would recommend this solution if you don't mind having filename completion in every buffer (also, you would still have to load comint first).

If this solution does not work for other modes, then the original answer below is still relevant for describing how to approach another solution.

END EDIT

From ielm-complete-filename we find that a solution is to make sure that the thing you are trying to complete is a string. There are probably better ways to ensure it, but the following is an example of a simple solution (it might be good enough)

(defun my-filename-completion-function ()
  (when (save-excursion
      (search-backward " ")
      (forward-char)
      (looking-at "\""))
    (comint-filename-completion)))

So add this function to completion-at-point-functions instead. I hope this solution solves the issue 'sufficiently well' (only tested it very quickly).

(require 'comint)

(add-hook 'prog-mode-hook
          (lambda ()
            (add-hook 'completion-at-point-functions
                      #'my-filename-completion-function
                      nil 'local)))

Of course, an alternative solution would be to simply use one of the in buffer completion packages company-mode, corfu or auto-complete.

3
  • 1
    Thank you! It seems that the first part of your answer (between EDIT and END EDIT) works well, at least in emacs lisp mode.
    – Alex
    Commented Dec 19, 2023 at 12:53
  • Your welcome. Indeed I did not test the 'first part' of the answer outside emacs-lisp mode. However, if in other modes the 'first part solution' does not work well, then the second part describes a possible approach to a better solution. B.t.w, personally, I would recommend you to simply use 'company-mode'. Commented Dec 19, 2023 at 13:51
  • "I guess this is general Emacs behavior, but I was not aware of it before" - this is the standard behavior for a buffer-local variable vs its global value, right? The completion-at-point-functions case is not a special case. Or am I misunderstanding?
    – NickD
    Commented Dec 24, 2023 at 13:05

Your Answer

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

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