Giter Site home page Giter Site logo

Get file basename? about orderless HOT 19 CLOSED

rickalex21 avatar rickalex21 commented on August 20, 2024
Get file basename?

from orderless.

Comments (19)

oantolin avatar oantolin commented on August 20, 2024

It sounds like you want a matching style that appends [^/]+$ to a component and then matches it as a regexp. Let me know if that is enough of a hint or if you need help implementing it.

from orderless.

rickalex21 avatar rickalex21 commented on August 20, 2024

Thanks @oantolin , I am aware that I can do regex in the minibuffer. I'm not sure how to do this
automatically. I was under the impression that completion-category-overrides file styles would
help me with this? Sorry, I still consider myself a newbie. I find embark easier to understand.

from orderless.

oantolin avatar oantolin commented on August 20, 2024

Well, you have to decide exactly what kind of matching you want to support, but for example say you only want to match text literally and only against basenames. Then given a string like a.b what regexp do you actually want to match against the filepath? That would be a\.b[^/]*$ (the dot is escaped to make the dot match literally). A function that converts an input string into the regexp you actually want to match against is called a "matching style" in orderless, and this particular matching style would be defined as the function +match-basename below:

(defun +match-basename-literally (string)
  (format "\\(%s\\)[^/]*\\'" (regexp-quote string)))

(orderless-define-completion-style +orderless-basename-only
  "Completion style for matching against base file names only."
  (orderless-matching-styles '(+match-basename-literally)))

(setq completion-category-overrides
      '((project-file (styles +orderless-basename-only))
        (file (styles +orderless-basename-only))))

The rest of that code block defines a new completion style, +orderless-basename-only that exclusively uses this style of matching text literally and then the completion-category-overrides variable is set so that that completion style is tried first when completing either files or project-files (which also tend to have long paths).

You could add support for other styles of matching against basenames, like, maybe you want to match regexps against basenames, or maybe shell-style file globs (which is easy to implement thanks to the dired-glob-regexp function which turns a file glob into an equivalent regexp! —Emacs Lisp has one of the most ridiculously complete "standard libraries" of any language I've used).

from orderless.

rickalex21 avatar rickalex21 commented on August 20, 2024

@oantolin This makes more sense, however I'm not getting the expected results. Is there something
wrong with my config here? I updated it. I also comment out orderless-style-dispatchers just to
be on the safe side.

As far as I'm aware all of these steps are done.

  1. Define function : +match-basename-literally converts input to a regex.
  2. Define style + Add func : +orderless-basename-only with +match-basename-literally
  3. Override Categories : Add cons (file (styles +orderless-basename-only)) to completion-category-overrides
(orderless-define-completion-style +orderless-with-initialism
  (orderless-matching-styles '(orderless-initialism
                              orderless-literal
                              orderless-regexp)))

(defun +match-basename-literally (string)
    (format "\\$%s\$[^/]\*\\\\'" (regexp-quote string)))

(orderless-define-completion-style +orderless-basename-only
  "Completion style for matching against base file names only."
  (orderless-matching-styles '(+match-basename-literally)))

(setq completion-styles '(orderless basic)
      completion-category-defaults nil
      completion-category-overrides '((file         (styles +orderless-basename-only))
                                      (project-file (styles +orderless-basename-only))
                                      ;;(file (styles partial-completion)) ;; partial-completion is tried first
                                      (command      (styles +orderless-with-initialism))
                                      (variable     (styles +orderless-with-initialism))
                                      (symbol       (styles +orderless-with-initialism)))
      orderless-component-separator #'orderless-escapable-split-on-space ;; allow escaping space with backslash!
      ;; Comment out for now till I get +orderless-basename-only working
      ;;orderless-style-dispatchers '(+orderless-dispatch)
      )

I'm not matching agenda-org.el, I'm matching emacs.org and others. Your regex works, I
tested it in the picture. I imagine the single quote at the end of the regex is a suffix
to match literately?

How do I know if something is explicitly file,command, variable, X, Y, Z etc..? I need to know this info for
completion-category-overrides. I've seen other configs that have consult-something in there. I did read the part in the docs that talk about Marginalia which I have installed but I'm not so sure. Obviously this picture is file because I can see the file permissions. Obviously if I do Describe variable I know it's a variable. command I presume is M-x.

Thanks

from orderless.

oantolin avatar oantolin commented on August 20, 2024

You changed the regexp! In my function I used "\\(%s\\)[^/]*\\'" and you used instead the very different "\\$%s\$[^/]\*\\\\'"! You were getting the correct results for the (weird) regexp you chose.

from orderless.

oantolin avatar oantolin commented on August 20, 2024

I imagine the single quote at the end of the regex is a suffix to match literately?

No, \' matches the end of the string, just like $ matches the end of a line.

from orderless.

rickalex21 avatar rickalex21 commented on August 20, 2024

@oantolin Sorry about that, it's the markdown exporter that I'm using, it's not my code. It needs
to be fixed. Here is my code again without using the markdown exporter. As shown in the
picture above I'm not matching agenda-org.el.

;; FIXME: Markdown exporter adding backslashes
(orderless-define-completion-style +orderless-with-initialism
  (orderless-matching-styles '(orderless-initialism
                              orderless-literal
                              orderless-regexp)))

(defun +match-basename-literally (string)
    (format "\\(%s\\)[^/]*\\'" (regexp-quote string)))

(orderless-define-completion-style +orderless-basename-only
  "Completion style for matching against base file names only."
  (orderless-matching-styles '(+match-basename-literally)))

(setq completion-styles '(orderless basic)
      completion-category-defaults nil
      completion-category-overrides '((file         (styles +orderless-basename-only))
                                      (project-file (styles +orderless-basename-only))
                                      ;;(file (styles partial-completion)) ;; partial-completion is tried first
                                      (command      (styles +orderless-with-initialism))
                                      (variable     (styles +orderless-with-initialism))
                                      (symbol       (styles +orderless-with-initialism)))
      orderless-component-separator #'orderless-escapable-split-on-space ;; allow escaping space with backslash!
      ;; Comment out for now till I get +orderless-basename-only working
      ;;orderless-style-dispatchers '(+orderless-dispatch)
      )

from orderless.

oantolin avatar oantolin commented on August 20, 2024

As shown in the picture above I'm not matching agenda-org.el.

I'm confused: the picture clearly shows that agenda-org.el does match. Maybe instead of saying that agenda-org.el doesn't match you meant to say that you want the other files shown to not match?

If that is what you meant, one way to achieve that would be to anchor the regexps to the beginning of the basename. You could do that by changing the regexp from "\\(%s\\)[^/]*\\'" to "\\(?:^\\|/\\)\\(%s\\)[^/]*\\'".

Is that what you wanted?

from orderless.

rickalex21 avatar rickalex21 commented on August 20, 2024

Yes ! Thanks alot Omar, that's what I needed. Hopefully this post will help someone else along
the way. I understand Orderless a bit better now.

BTW

How do I know what category something is in: file,command, variable, X, Y, Z etc..? I need to know this info for
completion-category-overrides. I've seen other configs that have consult-something in there. I did read the part in the docs that talk about Marginalia which I have installed but I'm not so sure. Obviously the picture above is file because I can see the file permissions. Obviously if I do Describe variable I know it's a variable and command I presume is M-x.

from orderless.

oantolin avatar oantolin commented on August 20, 2024

How do I know what category something is in?

I wish Emacs made that a little easier than it is. I'd suggest you bind the following command to some key in minibuffer-local-map, then when you are in the minibuffer you can use the command to find out the category.

(defun show-completion-category ()
  (interactive)
  (message "Category: %s"
           (alist-get 'category
                      (cdr
                       (completion-metadata
                        (buffer-substring-no-properties
                         (minibuffer-prompt-end)
                         (max (minibuffer-prompt-end) (point)))
                        minibuffer-completion-table
                        minibuffer-completion-predicate)))))

(keymap-set minibuffer-local-map "M-?" #'show-completion-category)

from orderless.

rickalex21 avatar rickalex21 commented on August 20, 2024

I see, thanks for the function. Is there something I need to autoload or do to use keymap-set ?
I understand that define-key is legacy now. It's really weird cause I get void function keymap-set
before doom-mode-line but after it it works fine. There's something in doom-modeline that enables
keymap-set or emacs loads it at that time.

I even tried (autoload 'keymap-set "compat-29"), don't work. I get:

Symbol's function definition is void: keymap-set

BTW I'm using: GNU Emacs 28.2 (build 2, x86_64-unknown-linux-gnu, GTK+ Version 3.24.34, cairo version 1.16.0) of 2022-09-13

I don't have anything weird in my doom-modeline config:

;; Don't work before
;; (keymap-set minibuffer-local-map "C-c o s" #'oantolin/show-completion-category)

(use-package doom-modeline
  :straight t
  :demand t
  :custom-face
  (doom-modeline-bar-inactive ((t (:background "dim gray"))))
  (doom-modeline-buffer-modified ((t (:inherit (error bold) ))))
  (doom-modeline-lsp-error ((t (:inherit error :foreground "dark red" :weight normal))))
  (doom-modeline-urgent ((t (:inherit (error bold) :foreground "orange red"))))
  (doom-modeline-notification ((t (:foreground "dark orange" :background "black"))))
  (mode-line ((t (:family "Noto Sans" :height 140 ))))
  (mode-line-active ((t (:inherit (doom-modeline-project-parent-dir) ))))
  (mode-line-inactive ((t (:inherit (doom-modeline-project-parent-dir)))))
  :config
  (setq doom-modeline-project-detection 'auto)
  (setq doom-modeline-minor-modes t)
  (setq doom-modeline-lsp t)
  ;; (setq doom-modeline-buffer-file-name-style 'truncate-upto-root)
  (setq doom-modeline-buffer-file-name-style 'truncate-upto-project)
  :init (doom-modeline-mode 1))

;; Works after
(keymap-set minibuffer-local-map "C-c o s" #'oantolin/show-completion-category)

from orderless.

oantolin avatar oantolin commented on August 20, 2024

You can easily rewrite that line to use define-key or general or whatever Doom uses to define key bindings instead of keymap-set, if you want.

Alternatively load compat which has a definition of keymap-set. Consult, for example, depends o compat.

from orderless.

rickalex21 avatar rickalex21 commented on August 20, 2024

I use vanilla emacs, I had to install compat, that fixed it. Turns out it's required by doom-modeline.

UPDATE: I noticed the aqua color is the second match after space. Perhaps I misunderstood the way
that the faces work but what I describe below would be a nice feature if it does not already exist.

I created a test function to use with your function. Are the matches suppose to be colored
differently based on the style? They look the same color. ode matches my/orderless-test and
org.org is matched by +match-basename-literally.

If this is the case then the first match ode should be color mangeta orderless-match-face-0
and the second match org.org should be aqua color orderless-match-face-1 ? However,
everything looks the same color.

Not sure I understood this part of the readme.

You will only see these particular faces when the orderless completion is the one that ends up being used, of course.

These are the faces:

 (orderless-match-face-0 ((t (:foreground "#d33682" :background "#073642"))))
 (orderless-match-face-1 ((t (:foreground "#2aa198" :background "#073642"))))
 (orderless-match-face-2 ((t (:foreground "#b58900" :background "#073642"))))
 (orderless-match-face-3 ((t (:foreground "#859900" :background "#073642"))))

The code of interest:

(defun my/orderless-test (string)
(format "\\(%sd\\)\\([a-z]+\\)" (regexp-quote string)))

(orderless-define-completion-style my/path-with-basename
  (orderless-matching-styles '( +match-basename-literally my/orderless-test)))

from orderless.

oantolin avatar oantolin commented on August 20, 2024

Are the matches suppose to be colored differently based on the style?

No, they are colored by component. So if your minibuffer input is ab cd then the matches of ab get one color and the matches of cd get a different color. For each component, each matching style is tried in order and the first matching style that makes that component match is used; but the color is the one that correspond to that number of component, not depending on the style that matched.

from orderless.

rickalex21 avatar rickalex21 commented on August 20, 2024

Would it be difficult to implement something like that? If I'm matching +orderless-with-initialism color
it yellow, if I'm matching +orderless-other-style color it green? Not sure what use cases but
interesting for sure.

from orderless.

oantolin avatar oantolin commented on August 20, 2024

It would not be too difficult, but I don't think it would be useful. Nor has anyone ever suggested it before. The point of highlighting the matches of different components of the input string in different colors is that they can match out of order (this is orderless after all), so the color helps you see were each component matched.

from orderless.

oantolin avatar oantolin commented on August 20, 2024

I also think coloring based on matching style would be a little confusing with style dispatchers in the mix: people use style dispatchers to invent "query syntax" by translating input to appropriate string & matching-style pairs. The matching style used is really an implementation detail, and very often is just orderless-regexp. Is it helpful to highlight all matches that are implement via orderless-regexp in the color assigned to orderless-regexp? Probably not. The current system, where the color indicates the component number (mod 4) seems more informative to me.

from orderless.

minad avatar minad commented on August 20, 2024

In order to get the completion category one can also use marginalia-cycle which prints a message.

from orderless.

rickalex21 avatar rickalex21 commented on August 20, 2024

@oantolin That makes sense, thanks for all your help. Thanks for the tip @minad.

from orderless.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.