Welcome to Vifm Q&A, where you can ask questions about using Vifm. Registration is optional, anonymous posts are moderated. E-mail and GitHub logins are enabled.
0 votes
in vifm by

Hello there!

I have a question about customizing filetype associations.
I want to have different filetype associations for non-tar *.gz and *.tar.gz

If I define it directly, like:

filetype {*.tar.gz} command-1
filetype {*.gz}     command-2

then command-2 obviously will be linked to tar files too.

I have tried this way:

filetype {*.gz},!{*.tar.gz} command-2

or

filetype !{*.tar.gz},{*.gz} command-2

But it not worked at all, it adds command-2 both to tar files and to all non-tar.gz (any other, like txt,zip,avi, .etc).

The best way I have found is to use regex with negative look behind pattern, like:

(?<!\.tar)\.gz

But as I understand, POSIX regex does not support this, so is there simple way to do that?
I want to avoid complex regex-es like in this SO question.

P.S.: Many thanks for VIFM, it is amazing software!

1 Answer

0 votes
by
selected by
 
Best answer

Hello,

Yes, POSIX regexps (man 7 regex) don't have positive/negative look behind/ahead, but you can still achieve the desired effect in Vifm. You even almost got it, just drop the comma:

filetype {*.tar.gz} command-1
filetype {*.gz}!{*.tar.gz} command-2

filetype {a},{b} command is just a shorthand for

filetype {a} command
filetype {b} command

That's basically a disjunction (logical OR). filetype {a}{b} command, on the other hand, is a conjunction (logical AND) of 2 patterns each of which can be negated individually.

by

Thank you very much, you are awesome!

After your pointing on OR and AND rules I have found it in the documentation (:help vifm-patterns):

To combine several patterns (AND them), make sure you're using one of the
first five forms and write patterns one after another, like this:
  <text/plain>{*.vifm}
Mind that if you make a mistake the whole string will be treated as the sixth
form.

|vifm-:filetype|, |vifm-:filextype| and |vifm-:fileviewer| commands accept
comma-separated list of patterns instead of a single pattern, thus effectively
handling OR operation on them: >
  <text/plain>{*.vifm},<application/pdf>{*.pdf}
Forms that accept comma-separated lists of patterns also process them as
lists of alternatives.

Now I have two forms of desired configuration:

{*.gz}!{*.tar.gz},
\{*.bz2}!{*.tar.bz2},
\{*.xz}!{*.tar.xz}

" or

/\.(gz|bz2|xz)$/!/\.tar\.(gz|bz2|xz)$/

Both are work well. First one is more readable imho.

To those who still need look behind in POSIX there is verbose workaround, which was worked well until xaizek have answered this question:

/([^r]|[^a]r|[^t]ar|[^\.]tar)\.(gz|bz2|xz)$/

It is convenient to check it with select (select all .gz,.bz2,.xz without .tar before it):

:select /([^r]|[^a]r|[^t]ar|[^\.]tar)\.(gz|bz2|xz)$/
...