Search code examples
emacsoverlayelisphighlighting

Highlight which of the file names in emacs buffer are missing


In GNU Emacs, I could use something like a hypothetical "flyexist.el" - I have a buffer with absolute (Unix) file names in it (plus some additional text around them). Most of those files exist, but some are missing. I would like to run a function that highlights me the missing files (maybe with a red overlay). This function would need to figure out which of the text in the buffer looks like a file name (some false positives are okay) and then work on it with file-exists-p.

For example, assume that my buffer contains

Some random text mentioning /file/that/does/exist.txt, 
some more random text, and a /file/that/does/not-exist.txt

I want to have the second file highlighted.

Does something like this exist already?


Solution

  • I am new to emacs hacking... Here is my "minor-mode" version.

    (defvar filehi-path-re "\\([/$][[:alnum:]$-_.]+\\)+"
      "Regexp used for path matching.")
    
    
    (defface filehi-file-existing
      '((t (:foreground "White" :background "Green")))
      "Face for existing files.")
    
    (defface filehi-file-missing
      '((t (:foreground "Yellow" :background "Red")))
      "Face for missing files.")
    
    (defun filehi-check-and-highlight (start end)
      "Check if substring is existing file path and highlight it."
        (remove-overlays start end 'name 'filehi-highlight)
        (let ((overlay (make-overlay start end)))
          (overlay-put overlay 'name 'filehi-highlight)
          (overlay-put overlay 'face (if (file-exists-p (substitute-in-file-name
                                                         (buffer-substring start end)))
                                         'filehi-file-existing
                                       'filehi-file-missing))))
    
    
    (defun filehi-highlight-file-paths (&optional start end _ignore)
       "Run through the buffer and highliht file paths."
        (save-excursion
          (save-match-data ; fixes problem with dabbrev (and may be more...)
            (remove-overlays (point-min) end 'name 'filehi-highlight)
            (let ((prev-end (point-min)))
              (goto-char (point-min)) ; FIXME use something like greedy
                                            ; search-backward
              (while (and (<= (point) end)
                          (re-search-forward filehi-path-re nil t))
                (filehi-check-and-highlight (match-beginning 0) (match-end 0)))))))
    
    
    (define-minor-mode filehi-mode
      "Minor mode for highlighting existing file paths.
    May conflict with other modes..."
      nil " Filehi" nil
      (if filehi-mode
          (progn ; enable mode
            (make-local-hook 'after-change-functions)
            (filehi-highlight-file-paths (point-min) (point-max))
            (add-hook 'after-change-functions 'filehi-highlight-file-paths nil t))
        ; disable mode
        (remove-hook 'after-change-functions 'filehi-highlight-file-paths t)
        (remove-overlays (point-min) (point-max) 'name 'filehi-highlight)))