3

I'm using ag.el as a front-end for the ag search utility. The results are displayed in a compilation buffer in the form <file>:<line>:<column>:<matching-text>. The matching-text includes leading-whitespace, and this makes the results harder to scan visually, in my opinion.

I dug around in the bowels of compile.el and ag.el hoping to find a way to strip the leading whitespace, but came up empty. Is there a way to accomplish this?

An example of search results in Emacs: emacs-results

The same results in Vim (note the stripped whitespace): enter image description here

  • One simple way to do this, would be to pipe the results through, say, sed before displaying them, though maybe there's a better way. – wvxvw Jan 2 '17 at 5:27
  • Also, in theory, you could have advised compilation-filter to call some function on the text it is going to insert. – wvxvw Jan 2 '17 at 5:51
2

Kudos to @wvxvw for pointing me in the right direction. I was able to normalize the whitespace by advising ag-filter, which ag adds to compilation-filter-hook.

(defun ivan/filter-whitespace (prefix-pattern)
  (save-excursion
    (forward-line 0)
    (let ((end (point)) beg)
      (goto-char compilation-filter-start)
      (forward-line 0)
      (setq beg (point))
      (when (< (point) end)
        (setq end (copy-marker end))

        ;; normalize whitespace between prefix-pattern and rest of line
        (while (re-search-forward prefix-pattern end 1)
          (and (re-search-forward "[[:blank:]]*" end 1)
               (replace-match " " t t)))))))

(defun ivan/filter-ag-whitespace ()
  (ivan/filter-whitespace ag/file-column-pattern))

(advice-add 'ag-filter :after #'ivan/filter-ag-whitespace)

The structure of the filter is identical to ag-filter itself, just the while loop differs. I thought it might be nice to apply the same filter to the *Occur* buffer, but when all the results are from the same file I think the indentation lends worthwhile context.

The final result: normalized-whitespace

However, the downside is this breaks wgrep functionality, probably because wgrep is looking for an exact match. I had to rig up a workaround that recompiles the search results with whitespace intact when wgrep is engaged.

(define-key ag-mode-map
  [remap wgrep-change-to-wgrep-mode] #'ivan/init-wgrep-mode)

(defun ivan/init-wgrep-mode ()
  (interactive)
  (advice-remove 'ag-filter #'ivan/filter-ag-whitespace)
  (add-hook 'ag-search-finished-hook #'ivan/enable-wgrep-mode)
  (recompile))

(defun ivan/enable-wgrep-mode ()
  (remove-hook 'ag-search-finished-hook #'ivan/enable-wgrep-mode)
  (advice-add 'ag-filter :after #'ivan/filter-ag-whitespace)
  (wgrep-change-to-wgrep-mode))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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