Search code examples
regexstringcolorsbackground-colorls

Apply a Regex between string README_* and REAME_IMP_*


I use grc to colorify the results of ls command.

For the moment, I have the following rule to display the text in white foreground on blue background. I did for this :

#README
regexp=(README_[^.]*$)
colours=on_blue blink 

Now I would like for string beginning by README_IMP_* (star * represent any other string) to display in white foreground on red background.

I did in the same file :

#README_IMP
regexp=(README_IMP[^.]*$)
colours=on_red blink

But the issue is even I type $ touch README_IMP_any_string , the text will be displayed unfortunately in white foreground on blue background, that is to say, the first rule regexp=(README_[^.]*$) has the priority on regexp=(README_IMP[^.]*$).

How to distinguish, with an appropriate regexp (with grc), the string README_any_string from README_IMP_any_string ?

PS: you can take a look at examples of regexp grc engine on https://apple.stackexchange.com/questions/371668/grc-inside-terminal-with-different-colors-into-terminal-as-a-function-of-files

UPDATE 1: following the advice of @Ludovic Kuty, If I invert the order between the 2 rules like this :

#README_IMP
regexp=(README_IMP[^.]*$)
colours=on_red blink

# README
regexp=(README_[^.]*$)
colours=on_blue blink

The second rule seems to overwrite the first one and this is illustrated on this figure :

difference between README_* and READ_IMP_*

As you can see, the file READ_IMP_1 is in white on blue and not white on red as expected.

UPDATE 2: From what I have seen, the file conf.ls is readed from the top to the bottom and I can't explain why the negative regexp=(README_(?!IMP)[^.]*$) is not matched when I create a README_string where string is any string excepted IMP.

For example, in my conf.ls, I have set for the moment :

# README with no IMP after
regexp=(README_(?!IMP)[^.]*$)
colours=on_blue blink

# README_IMP
regexp=(README_IMP[^.]*$)
colours=on_red blink

If a create a file named README_for_example, then this latter will be in 'on_red blink' color whereas the other README_* with * not string containing IMP , will be in white :

Why regexp=(README_(?!IMP)[^.]*$) is not matched in this case ?

Maybe there is a conflict between dircolors and grc ?

Here the beginning of ~/.dircolors :

#NORMAL 01;37       # global default, although everything should be something.
FILE 01;37         # normal file
DIR 32       # directory
LINK 01;36      # symbolic link
FIFO 40;33      # pipe
SOCK 01;35      # socket
BLK 40;33;01    # block device driver
CHR 40;33;01    # character device driver

As you can see, I commented the NORMAL line, believing that it could make a change but actually, no consequences.

It looks like the lest regexp rule had the priority and is applied even the match is wrong ...

UPDATE 3:

Given the fact that no one is able to suggest a solution, I think that I am going to have to modif ls.c and recompile following previous post. I understand, it is like to use a nuclear bomb to kill a chicken but it seems that I have not other alternatives.

UPDATE 4: Here the last attempt suggested by @NechesStich :

# README_IMP
regexp=(README_IMP[^.]*$)
colours=on_red blink

# README with no IMP after
regexp=README_[^.I][^.]*$|README_[^.][^.M][^.]*$|README_[^.][^.][^.P][^.]*$|README_I$|README_IM$
colours=on_blue blink

Unfortunately, the distinction between README_* (where * doesn't start by IMP) and README_IMP_* (with * any string).

I get the following result :

No distinction between README_* and README_IMP_*

As you can see, README_* is well recognize wheread README_IMP_1 is colrized in white :

I think the conflict between the white color between for normal files and from grc come from ~/.dircolors :

#NORMAL 01;37       # global default, although everything should be something.
FILE 01;37         # normal file
DIR 32       # directory
LINK 01;36      # symbolic link
FIFO 40;33      # pipe
SOCK 01;35      # socket
BLK 40;33;01    # block device driver
CHR 40;33;01    # character device driver

I don't understand why dircolors has the priority before grc.

It deserves more investigations, I am going to do other tests.

UPDATE 5 Here an extract from documentation doc grc of grc about the policy of string colorified :

**count** is one of words: once, more, stop, previous, block or unblock

- **once** means that if the regexp is matched, its first occurrence is coloured and the program will continue with other regexp's.
- **more** means that if there are multiple matches of the regexp in one line, all of them will be coloured.
- **stop** means that the regexp will be coloured and program will move to the next line (i.e. ignoring other regexp's)
- **previous** means the count will be the same as for the previous line
- **block** marks a start of a multiline block of text, coloured with the same colour
- **unblock**, obviously, marks the end of such a block

example:

    # this is probably a pathname
    regexp=/[\w/\.]+
    colour=green
    count=more

this will match `/usr/bin`, `/usr/local/bin/`, `/etc/init.d/syslogd` and similar strings and paint it with green.

Another example:

    regexp=^-{1,2}\s{0,1}$
    colours=red
    count=block
    -
    regexp=^\s{0,5}$
    colours=default
    count=unblock

this will turn all correctly formatted mail signatures red.

Regular expressions are evaluated from top to bottom, this allows nested and overlapped expressions. (e.g. you colour everything inside parentheses with one colour, and if a following expression matches the text inside parentheses, it will be also coloured).

Can you see an application in my case ?


Solution

  • From reading the sourcecode on https://github.com/garabik/grc/blob/master/grcat (lines 157-165)

    You can see grc dosen't consider lines that start with # or \n to start new rules only lines with other non letter characters, and if you look at other examples they separate their rules with =======

    This is why only your last rule ever applied since they weren't separated properly they were overwriting each other

    It should work when separated like this

    # README with no IMP after
    regexp=README_(?!IMP)[^.]*$
    colours=on_blue blink
    =======
    # README_IMP
    regexp=README_IMP[^.]*$
    colours=on_red blink