0

In image-dired I use M-x image-dired-mark-tagged-files to mark files containing a tag e.g. bar (one word tag). The problem is that foo bar (multiple word tag) is marked as well.

What regex do I need to mark the tag bar but not the other tag foo bar?

Input (how image-dired stores files):

/foo/IMG_2022.JPG;foo bar
/foo/IMG_2023.JPG;bar

Expected match

/foo/IMG_2023.JPG;bar

4 Answers 4

1

Please M-x report-emacs-bug

The current implementation (as of 28.1) of image-dired-mark-tagged-files doesn't make it possible to reliably isolate a tag:

(image-dired--with-db-file
 ;; Collect matches
 (while (search-forward-regexp
         (concat "\\(^[^;\n]+\\);.*" tag ".*$") nil t)
   (push (match-string 1) files)))

You can isolate the end of a tag using bar\(;\|$\) and if there's a preceding tag you can then use ;bar\(;\|$\) -- but if there's no preceding tag then you can't do anything about that .* before the tag resulting in a match for foobar, so I'd treat this as a bug.

1
0

How about this?

M-x re-builder with C-c TAB rx RET

Buffer with *RE-Builder*

rx-form of the regexp

 '(and ";"
       ;; Match the tags that precede "bar"
       (group                ; This only to give it some color
    (optional
     (one-or-more (not (or ";" "\n"))) ; one or more tags, together with it's separator
     (one-or-more " ")         ; separator
     ))
       ;; Match the tag itself
       (group                ; This only to give it some color
    "bar")
       ;; Match the tags that follows "bar"
       (group                ; This only to give it some color
    (optional
     (and
      (one-or-more " ")     ; separator
      (zero-or-more (not (or ";" "\n"))) ; one or more tags, together with it's separator
      )))
       line-end)

Convert rx-form to string and read-formats

*** Welcome to IELM ***  Type (describe-mode) or press C-h m for help.
ELISP> (rx-to-string 
 '(and ";"
       ;; Match the tags that precede "bar"
       (group                ; This only to give it some color
    (optional
     (one-or-more (not (or ";" "\n"))) ; one or more tags, together with it's separator
     (one-or-more " ")         ; separator
     ))
       ;; Match the tag itself
       (group                ; This only to give it some color
    "bar")
       ;; Match the tags that follows "bar"
       (group                ; This only to give it some color
    (optional
     (and
      (one-or-more " ")     ; separator
      (zero-or-more (not (or ";" "\n"))) ; one or more tags, together with it's separator
      )))
       line-end)
)
"\\(?:;\\(\\(?:[^
;]+ +\\)?\\)\\(bar\\)\\(\\(?: +[^
;]*\\)?\\)$\\)"
ELISP> (message "%s" *)
"\\(?:;\\(\\(?:[^
;]+ +\\)?\\)\\(bar\\)\\(\\(?: +[^
;]*\\)?\\)$\\)"
ELISP> 

Regex for use with minibuffer format

If you are C-u C-s-ing then you can use type the following---which is what you would see in *Messages* buffer---at minibuffer prompt

\(?:;\(\(?:[^
;]+ +\)?\)\(bar\)\(\(?: +[^
;]*\)?\)$\)

C-u C-sin action

Input forC-u C-s

(Of course, I could have used C-c TAB in in the "*RE-Builder*" buffer to effect the conversion from rx->read->string formats.)

0

If you use Bookmark+ then you can tag files with arbitrary strings, including strings containing whitespace.

There are commands for accessing files with tags all of which, or some of which, match a given regexp. The matching is against each tag separately, so there's no problem such as you report for image-dired tags.

For example, command bmkp-autofile-all-tags-regexp-jump, bound by default to C-x j t a % *:

bmkp-autofile-all-tags-regexp-jump is an interactive compiled Lisp function in bookmark+-1.el.

(bmkp-autofile-all-tags-regexp-jump REGEXP BOOKMARK)

Jump to an autofile BOOKMARK in this dir that has each tag matching REGEXP.

You are prompted for the REGEXP.

Then you are prompted for the BOOKMARK (with completion).

Bookmark+ commands pertaining to tags are by default on prefix key C-x x t — use C-x x t C-h to see them.

And the keys on that prefix by default follow a mnemonic pattern. For example the key sequence C-x j t a % * uses these mnemonics:

  • j means it's a bookmark jump command (visit the bookmarked file)
  • t means it's a tags command
  • a means it's an autofile command, that is, the bookmark is an autofile: a file wrapper, and its name is the file name
  • % means that the command prompts for a regexp (to match tags)

In the bookmark list (buffer *Bookmark List*), commands pertaining to tags are on prefix key T — use T C-h to see them. For example, you can mark and unmark the bookmarks that have tags matching various patterns.

0

Using rx-let to build a regular expression brick-by-brick

See Defining new rx forms

(info "(elisp) Extending Rx")

This ...

(require 'rx)
(rx-let (
     (tags-start (seq ";" (zero-or-more " ")))
     (tags-end (seq (zero-or-more " ") line-end))
     (tag-separators (one-or-more " "))
     (tag (one-or-more (not (or " " ";" "\n" "\r"))))
     (leading-tags (zero-or-more (seq tag tag-separators)))
     (lagging-tags (zero-or-more (seq tag-separators tag)))
     (match-this-tag (tag)
             (seq tags-start leading-tags tag lagging-tags tags-end)))
  (rx (match-this-tag "bar")))

on evaluation gives

"; *\\(?:[^

 ;]+ +\\)*bar\\(?: +[^

 ;]+\\)* *$"

The above value can then be plugged in to a *RE-Builder* that uses string format

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.