Question

I am starting with emacs, and don't know much elisp. Nearly nothing, really.

I want to use ack as a replacement of grep.

These are the instructions I followed to use ack from within emacs: http://www.rooijan.za.net/?q=ack_el

Now I don't like the output format that is used in this el file, I would like the output to be that of ack --group.

So I changed:

(read-string "Ack arguments: " "-i" nil "-i" nil)

to:

(read-string "Ack arguments: " "-i --group" nil "-i --group" nil)

So far so good. But this made me lose the ability to click-press_enter on the rows of the output buffer. In the original behaviour, compile-mode was used to be able to jump to the selected line.

I figured I should add a regexp to the ack-mode. The ack-mode is defined like this:

(define-compilation-mode ack-mode "Ack"
  "Specialization of compilation-mode for use with ack."
   nil)

and I want to add the regexp [0-9]+: to be detected as an error too, since it is what every row of the output bugger includes (line number).

I've tried to modify the define-compilation-modeabove to add the regexp, but I failed miserably.

How can I make the output buffer of ack let me click on its rows?

--- EDIT, I tried also: ---

(defvar ack-regexp-alist 
    '(("[0-9]+:"
     2 3))
  "Alist that specifies how to match rows in ack output.")

(setq compilation-error-regexp-alist
      (append compilation-error-regexp-alist
          ack-regexp-alist))

I stole that somewhere and tried to adapt to my needs. No luck.

--- EDIT, result after Ivan's proposal ---

With ack.el updated to include:

(defvar ack-regexp-alist 
  '(("^[0-9]+:" ;; match the line number
     nil        ;; the file is not found on this line, so assume that it's the same as before
     0          ;; The line is the 0'th subexpression (the whole thing)
     )
    ("^[^: ]+$" ;; match a file -- this could be better
     0          ;; The file is the 0'th subexpression
     ))
  "Alist that specifies how to match rows in ack output.")

(setq compilation-error-regexp-alist
      (append compilation-error-regexp-alist
          ack-regexp-alist))


(define-compilation-mode ack-mode "Ack"
  "Specialization of compilation-mode for use with ack."
   nil) 

Then checking the compilation-error-regext-alist variable, I get the value:

(absoft ada aix ant bash borland caml comma edg-1 edg-2 epc ftnchek iar ibm irix java jikes-file jikes-line gnu gcc-include lcc makepp mips-1 mips-2 msft oracle perl rxp sparc-pascal-file sparc-pascal-line sparc-pascal-example sun sun-ada 4bsd gcov-file gcov-header gcov-nomark gcov-called-line gcov-never-called
        ("^[0-9]+:" nil 0)
        ("^[^: ]+$" 0))

I find the format of the variable very strange, isn't it? I don't know elisp (yet), so maybe it's correct that way.

Still no links or color in the *ack* buffer.

Was it helpful?

Solution

There is another full-ack package up on ELPA which I have used before and handles --group output.

That said, reading the documentation for compilation-error-regexp-alist you see that it has the form:

(REGEXP FILE [LINE COLUMN TYPE HYPERLINK HIGHLIGHT...])

In the case of --group output, you have to match file and line separately, so I think you want something like (untested)

(defvar ack-regexp-alist
  '(("^\\S +$" ;; match a file -- this could be better
     0          ;; The file is the 1st subexpression
     )
    ("^[0-9]+:" ;; match the line number
     nil        ;; the file is not found on this line, so assume that it's the same as before
     0          ;; The line is the 0'th subexpression (the whole thing)
     ))
  "Alist that specifies how to match rows in ack output.")

-- Updated --

The variable compilation-error-regext-alist is a list of symbols or elements like (REGEXP ...). Symbols are looked up in compilation-error-regexp-alist-alist to find the corresponding elements. So yes, it is a little weird, but it's easier to see what's turned on and off without having to look at ugly regexes and guess what they do. If you were going to distribute this I would suggest adding the regex to compilation-error-regexp-alist-alist and then turning it on in compilation-error-regext-alist, but that is somewhat moot until you get it to work correctly.

Looking more closely at ack.el, I notice that it uses

(let (compile-command
      (compilation-error-regexp-alist grep-regexp-alist)
      ...)
  ...
  )

In other words it locally overwrites compilation-error-regexp-alist with grep-regexp-alist, so you need to add the regexes there instead. Or even better might be to replace it with

(let (compile-command
      (compilation-error-regexp-alist ack-regexp-alist)
      ...)
  ...
  )

In the end I still recommend full-ack since the filename regex does not seem to be working correctly. It seems more complete (though more complicated), and I have been happy with it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top