Subject: bug#895: slow processing of process output

From: "Drew Adams" <[email-masked]>
Date: Wed, 6 Jul 2011 10:58:35 -0700

> That is, if we instead prompted for the regexp we wanted to match
> explicitly, then we could highlight it ourselves instead of relying on
> grep to do it.

I did that (without prompting), for Emacs 20 & 21.  See:
http://www.emacswiki.org/emacs/download/compile%2b20.el

It was I who proposed that vanilla Emacs itself highlight the matches.  That
idea was adopted, but Emacs Dev decided to do the highlighting using escape
chars provided by (some) external `grep' commands.

(So I adjusted my code too to use that approach:
http://www.emacswiki.org/emacs/download/grep%2b.el)

> However, `M-x grep' as it is is pretty neat, because you can 
> fiddle with all the options and do
> grep ... | grep -v | etc

Absolutely.  But there is no reason to conflate "[having] the `M-x grep' command
be less...shell-script-ey" with doing the highlighting in Lisp.  Why do you want
less shell-script-ey?

My code did the highlighting in Lisp, but it should not in any way interfere
with piping etc.  (However, for unrelated reasons piping with Emacs `grep' is
not available until Emacs 22, and it was Emacs 22 that introduced
external-`grep' highlighting.)

> So providing something that is as flexible as `M-x grep' is today, but
> allow Emacs greater control of the output sounds difficult.

Not at all (IIUYC).

> Ok, here's one other possibility off the top of my head: What about if
> Emacs parsed the command line?  :-) That is, if you're typing
> grep -nH -e foo.*bar *.el
> then the grep syntax isn't that impossible to parse.  I mean, finding
> the regexp, and highlighting the matching bits.

That is what I did, IIUYC.  The relevant bit of the compile+20.el code:

;; Remember `grep-pattern' for highlighting, if highlighting is possible.
(cond (;; Quoted pattern (either "..." or '...')
       (string-match
        (concat
         grep-program
         "[ \t]*\\(-[a-zA-Z]+\\s-+\\)*[ \t]*\\('[^']+'\\|\"[^\"]+\"\\)") ;"
        command-args)
       (setq grep-pattern
             (substring command-args
                        (1+ (match-beginning 2)) (1- (match-end 2)))))
      (;; Unquoted pattern.
       (string-match
        (concat grep-program
                "[ \t]*\\(-[a-zA-Z]+\\s-+\\)*[ \t]*\\([^ \n\t'\"]+\\)") ; "
        command-args)
       (setq grep-pattern
             (substring command-args (match-beginning 2) (match-end 2))))
      (t;; Bad pattern.
       (setq grep-pattern nil)))

;; Account for a case-insensitivity option.
(when (and (not (string= "" grep-case-insensitive-option))
           (string-match grep-case-insensitive-option command-args))
  (setq grep-pattern (mapconcat
                      (lambda (char)
                        (if (or (and (>= char ?a) (<= char ?z))
                                (and (>= char ?A) (<= char ?Z)))
                            (concat "["  (char-to-string (downcase char))
                                    (char-to-string (upcase char)) "]")
                          (char-to-string char)))
                      grep-pattern "")))

This is a quick hack that works well in general (for Emacs 20/21).  But note
that the `grep-pattern' highlighting is not anchored after the file name and
line number, so if the file name itself matches the `grep-pattern' then it
doesn't highlight the latter.

Someone could work out the code to anchor the pattern match properly.  I didn't
bother to try, since it is good enough as is, for my use.

> It isn't difficult to imagine more complex command lines that Emacs
> wouldn't be able to parse, though.  And you'd lose highlighting of the
> matches there...

Yes.

FWIW, I think the Emacs Dev approach of using external `grep' highlighting is
generally not bad (but there have been a few bugs that needed to be fixed along
the way).