Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

helm-do-grep-ag: ripgrep colours in search results #2313

Closed
manuel-uberti opened this issue May 30, 2020 · 30 comments
Closed

helm-do-grep-ag: ripgrep colours in search results #2313

manuel-uberti opened this issue May 30, 2020 · 30 comments

Comments

@manuel-uberti
Copy link
Contributor

manuel-uberti commented May 30, 2020

Expected behavior

For Helm to use the helm-grep-match face, the command-line call to grep or other backends has to specify --color=never (or equivalent). Otherwise Helm will use whatever the command-line output would use for the matching text: typically bold text in red (ANSI color 1).

Using this generally works as expected, by showing the theme's faces:

(setq helm-grep-ag-command
      "rg --color=never --smart-case --no-heading --line-number %s %s %s")

This is a screenshot showing the output of helm-do-grep-ag with dired as its input:

1

Actual behaviour

The same setup fails in two ways when the input is an incomplete/invalid regular expression, such as \(dired:

  • It matches dired as if it were a string.
  • It shows the matching lines, but not the contents.

This is a screenshot showing the output of helm-do-grep-ag with \(dired as its input:

2

Actual behavior (from emacs-helm.sh if possible, see note at the bottom)

3

Steps to reproduce (recipe)

  • run emacs-helm.sh
  • evaluate the following code:
(setq helm-grep-ag-command
      "rg --color=never --smart-case --no-heading --line-number %s %s %s")
  • M-x helm-do-grep-ag RET \(dired

Describe versions of Helm, Emacs, operating system, etc.

  • Helm: commit 9101738a4ff56f838641ea412dfc2c3d24f5be82
  • Emacs: GNU Emacs 28.0.50 (f42db4b6e1598c12924cce4bbe4d67e6d86b7963)
  • OS: Ubuntu 20.04 LTS

Are you using emacs-helm.sh to reproduce this bug? (yes/no):

Yes

Are you using Spacemacs? (yes/no):

No

Notes

The rg executable can parse an arbitrary colour value specified as an option for --colors (see the manpage). This uses #0030a6 as the match's background (expressed as 0x00,0x30,0xa6):

# command-line call
rg helm --color=always --colors 'match:bg:0x00,0x30,0xa6' --colors match:fg:white --colors match:style:bold --smart-case --no-heading

The interpretation of the blue #0030a6 works on the command-line, but not in the Helm buffer.

I originally reported this problem on the @protesilaos' modus-themes issue tracker, where you can find further discussion, if you want: https://gitlab.com/protesilaos/modus-themes/-/issues/49

@thierryvolpiatto
Copy link
Member

thierryvolpiatto commented May 30, 2020 via email

@manuel-uberti
Copy link
Contributor Author

Using --colors 'match:fg:yellow' works, but what I don't understand is how using something like --colors 'match:bg:0x00,0x30,0xa6' doesn't. (See my Notes above).

@thierryvolpiatto
Copy link
Member

Hmm, I don't know, I only know how to do basic settings, perhaps you can ask @BurntSushi the developer of ripgrep.

@thierryvolpiatto
Copy link
Member

Is it working on command line ?

@manuel-uberti
Copy link
Contributor Author

Yes, it is working from the command line.

@thierryvolpiatto
Copy link
Member

thierryvolpiatto commented May 30, 2020 via email

@manuel-uberti
Copy link
Contributor Author

Thanks Thierry, I think you may have found something here. With this:

(setq helm-grep-ag-command
        "rg --color=ansi --colors match:fg:32,31,32 --colors match:style:nobold --smart-case --no-heading --line-number %s %s %s")

I can see the foreground colour. @protesilaos what do you think?

@protesilaos
Copy link

Thank you both for looking into this!

@manuel-uberti Your last snippet works for the foreground. But I cannot get the expected result for the background with --colors match:fg:32,31,32. So maybe something can be done there.

That granted, I was about to comment that the values for the terminal colours is controlled by ansi-color-names-vector. Below is a proof-of-concept where I swap the original red with another colour.

Using this command:

(setq helm-grep-ag-command
      "rg helm --color=always --colors match:bg:red --colors match:fg:black --colors match:style:bold --smart-case --no-heading --line-number %s %s %s")

Original (no changes to the ansi vector)

Screenshot from 2020-05-30 22-12-57

With the demo change

Screenshot from 2020-05-30 22-12-29

Idea

So perhaps users could do something like (this does not work):

(let ((ansi-color-names-vector [black "#f8ddea" green yellow blue magenta cyan white]))
  (call-interactively 'helm-do-grep-ag))

@manuel-uberti
Copy link
Contributor Author

Interesting. So what is the next step here? I don't think this is Helm-related now, nor rg for that matter.

@protesilaos are you going to add the change to ansi-color-names-vector to the themes?

@protesilaos
Copy link

@manuel-uberti Changing that at the theme level would probably cause more problems, because other commands are likely expecting to read from it.

The cleaner solution for a theme would be to tweak the values of a face. Absent that, I would need to experiment more with the code I posted under the "Idea" heading. Though that is not an ideal solution either.

@protesilaos
Copy link

This is the way a user may update the ANSI colour values:

(ansi-color-map-update 'ansi-color-names-vector ["#000000" "#a60000" "#005e00" "#813e00" "#0030a6" "#721045" "#00538b" "#ffffff"]

The sequence is: black, red, green, yellow, blue, magenta, cyan, white.

Demo where I change the "red" value (preview colours with M-x rainbow-mode):

Screenshot from 2020-05-31 00-21-48

Screenshot from 2020-05-31 00-22-09

I am not sure what the best options is and would like to hear from you. What I now see are these main possibilities:

  1. Users could just change the ansi-color-names-vector at their config level (I can help you @manuel-uberti on the themes' issue tracker).
  2. The vector could be dynamically set and reset on a per-function basis. More difficult to maintain, but unlikely to cause unforeseen issues with other aspects of Emacs.
  3. A Helm face could be taking over the ANSI colour code.

Your thoughts?

@BurntSushi
Copy link

However the setting of colors have changed several time along ripgrep
versions

Could you elaborate? I don't think this has changed at all.

I'm happy to answer any ripgrep specific questions.

@thierryvolpiatto
Copy link
Member

thierryvolpiatto commented May 31, 2020 via email

@thierryvolpiatto
Copy link
Member

thierryvolpiatto commented May 31, 2020 via email

thierryvolpiatto pushed a commit that referenced this issue May 31, 2020
* helm-grep.el (helm-grep-ag-command): Do it.
* helm-help.el (helm-grep-help-message): Do it.
@manuel-uberti
Copy link
Contributor Author

manuel-uberti commented May 31, 2020

@protesilaos

I'd avoid option 2 because it'd mean more maintenance work for something that should not be this complicated.

Option 1 would need to be well documented, and would put the user in charge of the problem.

Option 3 seems the more reasonable: provided that everything is in place, the user would just have to install ripgrep, Helm, and a theme supporting this colour setup and nothing more would be required.

WRT a Helm face, helm-grep-match is already present. Couldn't this be re-used?

@protesilaos
Copy link

@manuel-uberti I agree that option 3 is the best. @thierryvolpiatto is welcome to a possible PR, but I do not yet know how to implement that, so as to help you in that regard.

@manuel-uberti
Copy link
Contributor Author

I am not sure either.

ansi-color-names-vector isn't strictly related to Helm, and it is a vector, not a single specific face. A defcustom could be used to apply the needed colours to ansi-color-names-vector, but then what would the use of helm-grep-match be?

@protesilaos
Copy link

Thinking about it, messing around with that vector would be fragile. Perhaps the answer is to tweak helm-grep-highlight-match?

@manuel-uberti
Copy link
Contributor Author

manuel-uberti commented May 31, 2020

That uses helm-add-face-text-properties to apply helm-grep-match, so I guess it still is a matter of having the correct face to highlight the matches.

But then again, the problem is mixing ansi-color-names-vector and a defface.

@thierryvolpiatto
Copy link
Member

thierryvolpiatto commented May 31, 2020 via email

thierryvolpiatto pushed a commit that referenced this issue May 31, 2020
We need to transform pcre regexp to elisp when needed.

* helm-grep.el (helm-grep-mode--use-pcre): New local flag.
(helm-grep-save-results-1): Use it.
(helm-grep-mode--sentinel): Maybe use pcre.
(helm-grep-class): Use now a FCT.
(helm-grep--filter-candidate-1): Take one more arg PCRE.
(helm-grep-filter-one-by-one): Same.
(helm-grep-fc-transformer): New use it now for grep and ag.
(helm-grep-highlight-match): Use pcre regexp when pcre arg is specified.
(helm-grep-ag-class): Use now a FCT.
* helm-occur.el (helm-occur-filter-one-by-one): Fix arg no more used.
@manuel-uberti
Copy link
Contributor Author

manuel-uberti commented May 31, 2020

Just tried latest commit (4071dca7f80b590a9d089ff790fb54224fad110d), and now I am getting the desired effect with:

(setq helm-grep-ag-command
        "rg --color=never --smart-case --no-heading --line-number %s %s %s")

@protesilaos could you give it a try? I am pretty sure we can close both this ticket and the one on your issue tracker now.

Thank you Thierry once again for the amazing support.

@thierryvolpiatto
Copy link
Member

thierryvolpiatto commented May 31, 2020 via email

@manuel-uberti
Copy link
Contributor Author

Oh I see, thanks for the clarification. :)

@BurntSushi
Copy link

However the setting of colors have changed several time along ripgrep versions Could you elaborate? I don't think this has changed at all.
IIRC At the first times there was no option at all, then it was --color-match, nowaday it is --colors, is this right?

Ah nope, it was originally introduced as --colors way back in ripgrep 0.3.0, which was released about 3.5 years ago. (It was only a few months after ripgrep's original release.) It has stayed the same since then, so there has been very little churn in this feature from my perspective.

I'm happy to answer any ripgrep specific questions.
Thanks (and thanks for ripgrep ;-)).

:-)

@thierryvolpiatto
Copy link
Member

thierryvolpiatto commented May 31, 2020 via email

@jagrg
Copy link
Contributor

jagrg commented Jun 15, 2020

A few things I noticed (using ./emacs-helm.sh) with:

(setq helm-grep-ag-command
      "rg --color=never --smart-case --no-heading --line-number %s %s %s")

If I type defun helm str, "defun" is not highlighted.

With --color=always, "defun" is red while "helm" and "str" are green.

Also, if I set nohighlight to nil in helm-grep-ag-class, the three words are red which is what I'd expect, and is what I see with C-x C-f C-s. Maybe the nohighlight slot should be set conditionally. Anyhow, if this is an issue with the ripgrep version I'm using (11.0.2), what is the correct way of changing the value of nohighlight? The code below does nothing AFAICT.

(defmethod helm-setup-user-source ((source helm-grep-ag-class))
  (setf (slot-value source 'nohighlight) nil))

Thank you all.

@thierryvolpiatto
Copy link
Member

thierryvolpiatto commented Jun 15, 2020 via email

@jagrg
Copy link
Contributor

jagrg commented Jun 16, 2020 via email

thierryvolpiatto pushed a commit that referenced this issue Jun 16, 2020
Without this, with multi matches, first pattern matched is not colorized
because ansi is used only on next matches.

Try to extract the info from helm-grep-ag-command --color= parameter.

With this patch both --color=always and --color=never should work properly.
@jagrg
Copy link
Contributor

jagrg commented Jun 16, 2020 via email

@thierryvolpiatto
Copy link
Member

thierryvolpiatto commented Jun 17, 2020 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants