Skip to content

Conversation

@minad
Copy link
Owner

@minad minad commented Aug 4, 2021

The input string is transformed before passing it to the backend. Spaces are
replaced by .*. Furthermore the input is interpreted as Emacs regular
expression and transformed to a Perl-compatible regular expression (PCRE), by a
handful of basic substitutions. The matching substrings are not obtained anymore
from the backend by looking for ANSI escape sequences. Instead the input regular
expression is used to heuristically apply highlighting.

Advantages:

  • No parsing of ANSI escape sequences, which is fragile and inefficient.
  • More flexibility, input string can be transformed, e.g., "def consult" -> "def.*consult".
  • Highlighting becomes possible for backends which don't return highlights, e.g., find.

Disadvantages:

  • Highlighting may be incorrect. In practice this is rare, since most search inputs
    are simple regular expressions.

@minad minad changed the title Transform input of consult-*grep* and consult-*find* commands Transform input of consult-grep and consult-find commands Aug 4, 2021
@minad minad force-pushed the transform-grep branch 13 times, most recently from 3c80fef to ebcfff1 Compare August 4, 2021 22:34
@oantolin
Copy link
Contributor

oantolin commented Aug 4, 2021

It's tempting to reuse orderless-pattern-compiler, translate each regexp to PCRE, and join with " -and " or .* as the case may be.

@minad
Copy link
Owner Author

minad commented Aug 4, 2021

Yes, it is! I also had that planned originally but then somehow moved away from it because of the more complicated translations. If you look into the code I have some basic infrastructure there (very basic!). Maybe I should cut this down even more and focus on the Orderless integration. Probably one needs pcre2el to make this robust.

@oantolin
Copy link
Contributor

oantolin commented Aug 4, 2021

Does pcre2el also have el2pcre functions?

@minad
Copy link
Owner Author

minad commented Aug 4, 2021

Yes, both directions. This is quite nice since then the users can configure the style as they like :)

@minad
Copy link
Owner Author

minad commented Aug 4, 2021

Maybe a simpler converter would suffice for Orderless as long as you don't write complicated custom regexps yourself?

@oantolin
Copy link
Contributor

oantolin commented Aug 4, 2021

Maybe a simpler converter would suffice for Orderless as long as you don't write complicated custom regexps yourself?

I think that's right. The regexp features used by the matching styles that come with orderless are not that fancy. Grouping without capturing, word boundaries, maybe a little more.

@minad minad force-pushed the transform-grep branch 3 times, most recently from 21fdeb1 to 2539fd7 Compare August 5, 2021 12:21
@minad
Copy link
Owner Author

minad commented Aug 5, 2021

I refactored everything a bit, which should allow us to integrate orderless. Now we have these regexp functions:

  • consult--emacs-to-extended-regexp: Very basic converter
  • consult--compile-regexp: Compile string to list of regexps of type basic, extended, emacs or lookahead
  • consult--join-regexp: Compile string to a single joined regexp of type basic, extended, emacs or lookahead

consult/consult.el

Lines 582 to 609 in 2539fd7

(defun consult--emacs-to-extended-regexp (regexp)
"Convert Emacs REGEXP to extended regexp syntax (ERE).
This function only changes the escaping of parentheses, braces and pipes."
(replace-regexp-in-string
"\\\\\\\\\\|\\\\?[(){}|]"
(lambda (x)
(cond
((equal x "\\\\") x)
((= 1 (length x)) (concat "\\\\" x))
(t (substring x 1))))
regexp))
(defun consult--compile-regexp (str type)
"Compile STR to a list of regexps of TYPE."
(setq str (split-string str nil 'omit-nulls))
(pcase-exhaustive type
((or 'basic 'emacs) str)
((or 'lookahead 'extended)
(mapcar #'consult--emacs-to-extended-regexp str))))
(defun consult--join-regexp (str type)
"Compile STR to a regexp joined from multiple regexps of TYPE."
(setq str (consult--compile-regexp str type))
(pcase-exhaustive type
((or 'basic 'emacs 'extended) (string-join str ".*"))
('lookahead (concat "^" (mapconcat
(lambda (x) (format "(?=.*%s)" x))
str "")))))

In order to support Orderless it is only necessary to replace consult--compile-regexp. If a basic regexp is requested, Orderless should bail out, but for the other types Orderless can be used. Furthermore consult--emacs-to-extended-regexp must be extended such that it translates the regexp features used by Orderless.

@minad minad force-pushed the transform-grep branch 3 times, most recently from 9f1d297 to 00e3742 Compare August 5, 2021 12:56
The input string is transformed before passing it to the backend. Spaces are
replaced by `.*`. Furthermore the input is interpreted as Emacs regular
expression and transformed to a Perl-compatible regular expression (PCRE), by a
handful of basic substitutions. The matching substrings are not obtained anymore
from the backend by looking for ANSI escape sequences. Instead the input regular
expression is used to heuristically apply highlighting.

Advantages:

- No parsing of ANSI escape sequences, which is fragile and inefficient.
- More flexibility, input string can be transformed, e.g., "def consult" -> "def.*consult".
- Highlighting becomes possible for backends which don't return highlights, e.g., find.

Disadvantages:

- Highlighting may be incorrect. In practice this is rare, since most search inputs
  are simple regular expressions.
@grolongo
Copy link

grolongo commented Aug 6, 2021

Just to make sure I understand this, is the intended way to configure consult-grep/ripgrep/find through consult-customize as we already do for consult-buffer completions?

Example:

(consult-customize
 consult-ripgrep-config
 :args "rg --line-buffered --color=never --max-columns=1000 --no-heading\
 --line-number --follow --hidden --search-zip --smart-case .")

consult-find doesn't work out of the box on windows-nt.
:args "find . -not ( -wholename \\*/.\\* -prune )" fixes it, though as an UX suggestion I think it would be better for windows-nt users to not have to look for a solution and make it just work for them too. Maybe add an os detection to tweak the command or just don't include to ignore dotfiles by default?

Last question, would you think it would be a good idea to make consult-grep to also rely on grep-find-ignored-files and grep-find-ignored-directories?

@minad
Copy link
Owner Author

minad commented Aug 6, 2021

Just to make sure I understand this, is the intended way to configure consult-grep/ripgrep/find through consult-customize as we already do for consult-buffer completions?

No you configure the commands by modifying the consult-ripgrep-config variable directly. consult-customize is only for command and buffer configurations, it is a feature of the underlying consult--read API. This is unfortunately a bit misleading, but consult-customize is a special case.

consult-find doesn't work out of the box on windows-nt.

Yes, this is a known issue, see #317. Unfortunately I don't have the possibility to test or fix this. But if someone implements a proper fix I would appreciate it. Furthermore I suggest to report this as an upstream bug to emacs-devel. This is a bug in the process API, the API abstraction is broken.

Last question, would you think it would be a good idea to make consult-grep to also rely on grep-find-ignored-files and grep-find-ignored-directories?

It doesn't sound like a bad idea at first. I also considered this. Downside is that we have to require the grep library then, which is not good for lazy loading. The consult-grep etc commands are completely decoupled from the Emacs grep library, it does not make use of any of its infrastructure. embark-export is the glue which allows to transfer from consult-grep to a grep-mode buffer.

@oantolin
Copy link
Contributor

oantolin commented Aug 6, 2021

While consult-find doesn't work out of the box on Windows, I had found a workaround that's documented in that issue that @minad linked, #317. I guess that workaround might need updating for the recent changed in consult.

@minad
Copy link
Owner Author

minad commented Aug 6, 2021

@oantolin Do you have an idea how the issue could be fixed properly at the core? It doesn't make sense to me why this problem exists at all.

@grolongo
Copy link

grolongo commented Aug 7, 2021

No you configure the commands by modifying the consult-ripgrep-config variable directly. consult-customize is only for command and buffer configurations, it is a feature of the underlying consult--read API. This is unfortunately a bit misleading, but consult-customize is a special case.

Understood, therefore plist-put is the way to go unless you use the customize interface.

Downside is that we have to require the grep library then, which is not good for lazy loading. The consult-grep etc commands are completely decoupled from the Emacs grep library, it does not make use of any of its infrastructure.

After thinking about it I agree with you it's better to keep it separated. Also those options are made to be used with find coupled with grep after all, not just grep alone.

@minad
Copy link
Owner Author

minad commented Aug 7, 2021

Understood, therefore plist-put is the way to go unless you use the customize interface.

Yes, but I am currently overhauling this again. I am not yet satisfied with the current design and it is still lacking flexibility. The goal is to have the ability to plug in orderless as a pattern transformer, such that you can search via ripgrep with the usual orderless patterns.

@rswgnu
Copy link
Contributor

rswgnu commented Feb 20, 2023

Could you add a comment here on whether/how you have added orderless support for grep/ripgrep commands. Please give a complete example as I find the documentation on how to send arguments to the grep commands very hard to follow. For example, give an example where a multi-word pattern is searched regardless of order but only within a single, specific file. Thanks. (Just starting with consult and the grep functionality is really great. Would like to be able to search over either multiple directories or within a specific list of files too).

@minad
Copy link
Owner Author

minad commented Feb 20, 2023

@rswgnu
Copy link
Contributor

rswgnu commented Feb 20, 2023

This still does not supply a precise example of the syntax to specify for the initial input args. Is that fully documented anywhere with specific examples? It would really help if you just gave one detailed example wherever you mention complex syntax and then explain that example rather than just listing it. For example, if I say use this: "#expr -- -g *.c#filter", no one will no what that means. But if you break it down and explain each part, then it will be clear. Thanks.

@rswgnu
Copy link
Contributor

rswgnu commented Feb 20, 2023

To make it even simpler, I know how to write a grep command like: grep -n my-expr file1 file2. What is the exact expression to send those args to consult-grep and consult-ripgrep (or their associated commands)?

@rswgnu
Copy link
Contributor

rswgnu commented Feb 20, 2023

@rswgnu It is in the wiki: https://github.com/minad/consult/wiki#use-orderless-as-pattern-compiler-for-consult-grepripgrepfind

I tried that and it errored out since 'input' is not known within the lambda expression (using latest consult and orderless packages). This sort of runs but only matches to the first character typed and only after removing the leading # async symbol:

(defun consult--orderless-regexp-compiler (input type &rest _config)
  (setq input (orderless-pattern-compiler input))
  (cons
   (mapcar (lambda (r) (consult--convert-regexp r type)) input)
   `(lambda (str) (orderless--highlight ',input str))))

;; OPTION 1: Activate globally for all consult-grep/ripgrep/find/...
(setq consult--regexp-compiler #'consult--orderless-regexp-compiler)

@minad
Copy link
Owner Author

minad commented Feb 20, 2023

@rswgnu I think you want to do something which is not directly supported by consult-grep (but you can of course configure and adjust it). You probably want to adjust everything to your Hyperbole ways but that's not what most users necessarily want. ;)

I suggest you try Consult as is for a while. Then you will see how everything fits together. Also you should read the docs completely. Most of the information you asked for should be there. Since you are an expert you could also skim the wiki and the source for additional tweaks.

@rswgnu
Copy link
Contributor

rswgnu commented Feb 20, 2023 via email

@minad
Copy link
Owner Author

minad commented Feb 20, 2023 via email

@rswgnu
Copy link
Contributor

rswgnu commented Feb 20, 2023 via email

@minad
Copy link
Owner Author

minad commented Feb 20, 2023 via email

@rswgnu
Copy link
Contributor

rswgnu commented Feb 20, 2023 via email

@minad minad deleted the transform-grep branch January 31, 2024 14:55
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

Successfully merging this pull request may close these issues.

5 participants