views:

144

answers:

1

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.

+2  A: 

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.

Ivan Andrus
Thanks for the help in defining the alist. However, I am still not sure how to pass it to the compile-command.The output does currently seem to care about the `ack-regexp-alist`, although I do `(setq compilation-error-regexp-alist (append compilation-error-regexp-alist ack-regexp-alist))`
Gauthier
That works for me when I run ack manually with `M-x compile` (though the file regexp doesn't work quite right). One thing you have to do is make sure that ack-regexp-alist is getting updated. Evaluating `defvar` many times won't change the value once it has been set. `C-h v ack-regexp-alist RET` will show you what the current value of `ack-regexp-alist` is. Likewise for `compilation-error-regexp-alist`.
Ivan Andrus
Thanks again. I am still confused, I edited my question to show where I am stuck after your proposal.
Gauthier
Thanks again. I am trying full-ack. The output looks very nice.Two annoying drawbacks though: 1. In the output buffer you must press enter on the searched term itself to jump to the code. Pressing Enter while anywhere else on the row does not work. 2. The searched term is not automatically filled in with the word under cursor. This makes me want to stick to ack.el so far. I'll try your solution and let you know.
Gauthier
And another major drawback with full-ack: doing a new search kills your old result buffer!
Gauthier
Fair enough. I'm not sure how to solve the first one. I found (after much frustration) that changing the order of the regexes seems to work. I have updated my solution.
Ivan Andrus
Hi, thanks for the update. It is indeed working better! The error lines are now links. But still I cannot jump to the file. I get prompted for the name of the file to open, while I expect this to happen automatically. `Find this error in (default):` is what I get. Maybe the file name regexp does not work on windows? I'm no king of regexps, I'll go see if I can understand what you wrote better.
Gauthier
I replaced your `"^\\S +$"` with `"[a-zA-Z]:/.+$"`, and got it working! Thanks a lot for your help!
Gauthier