1

I'm wondering how to:

  • Check the presence in the current buffer of words that are present in a given file and
  • Highlight them.
4
  • 1
    Plugin requests are off-topic; an answer might include "try this plugin [details]," but we prefer the question to be plugin agnostic to not exclude non-plugin answers.
    – D. Ben Knoble
    Commented Apr 26, 2023 at 12:44
  • Is one of the answers addressing your problem? How can we help you further? Commented Apr 27, 2023 at 17:33
  • 1
    @VivianDeSmedt I commented one answer to get further help. Thank you for asking. Commented Apr 28, 2023 at 6:27
  • If the solution fit your need maybe could you validate it using the v button next to the arrow voting buttons. It allow the question to rest :-) Commented Apr 28, 2023 at 6:48

2 Answers 2

3

Supposing you want to highlight the word list with the WarningMsg highlighting group (you can change that).

Here what I would do:

execute 'match' 'WarningMsg' '/\V' .. join(readfile(path_to_file), '\|') .. '/'

Explanation

The match command: match highlighting_group /pattern/ highlight the string that match the pattern with the highlighting_group

The code is building the command as a string and execute it with the execute command.

The readfile read the line of the file and return a list (e.g. ['foo', 'bar'])

The join function convert the list into a string using the \| separator (e.g. foo\|bar) searching for all the words (e.g. either foo or bar)

Because the words could contains special character that have pattern meaning (e.g. .) we prefix the pattern with \V to match as literally as possible with Vim.

More information in the doc with :help match, :help readfile(), :help join(), :help /\V.

Using a Command

You can also create a Highlight command for it:

command! -narg=1 -complete=file Highlight execute 'match' 'WarningMsg' '/\V' .. join(readfile(<f-args>), '\|') .. '/'

The command command introduce a new command:

  • -narg=1 set the number of argument to the command to 1
  • --complete=file tell Vim that the argument is a file and the file autocompletion could be used.
  • <f-args> is the list of argument quoted

More information with :help command,:help command-nargs, :help command-complete and :help <f-args>

Supporting words with Backslash

command! -narg=1 -complete=file Highlight execute 'match' 'WarningMsg' '/\V' .. join(mapnew(readfile(<f-args>), {_, v -> escape(v, '\')}), '\|') .. '/'

Remark: The mapnew code escape each word of the list it takes the list of the words and a lambda function that get the index of the element in the list (_) and the element itself (v) and return the replacement escape(v, '\')/

More information with: :help mapnew(), :help lambda

Thanks to @Ben for that.

Stop Higlighting

To stop highlighting you can do:

match none

Or if you prefer (as suggested by @romainl) to extend the highlighting with the command you could do:

command! -narg=1 -complete=file Highlight call matchadd('WarningMsg', '\V' .. join(readfile(<f-args>)))

But the code to reset the highlighting is slightly more complex to write

8
  • 1
    I was about to post a very similar answer, but using :help matchadd() instead of :help :match.
    – romainl
    Commented Apr 26, 2023 at 13:30
  • 1
    Wow, thanks. Since I'm new to this: please explain, where do I have to use your lines of code. I copied one line in the .vimrc (edited the path to the words.txt) but it didn't work. Seems I used your code not in the way I'd have to. Commented Apr 28, 2023 at 6:25
  • 1
    I have added some explanation. Don't hesitate to ask me for more. Commented Apr 28, 2023 at 6:40
  • 1
    @VivianDeSmedt Thanks for the explanation. I'm still wondering where to put your code. In the .vimrc? Or in a *.vim-file as a plugin? Sorry to ask again, but I'm still a novice. Commented Apr 28, 2023 at 7:00
  • 1
    @VivianDeSmedt Thank you, very much! Commented Apr 28, 2023 at 7:39
2

Let's use LogiPat to build a search pattern for all words in the file:

const words = readfile('words')
const patterns = mapnew(words, {_, v -> printf('"%s"', substitute(v, '"', '&&', 'g'))})
const logipat = join(patterns, '|')
execute 'LogiPat' logipat

or all together

execute 'LogiPat' readfile('words')->mapnew({_,v -> printf('"%s"', substitute(v, '"', '&&', 'g'))})->join('|')

With set hlsearch, this highlights everything. And n/N navigate matches.

Now, LogiPat highlights whole lines because it uses .* around each pattern. You could also try

const words = readfile('words')
const patterns = mapnew(words, {_, v -> printf('\(%s\)', escape(v, '\'))})
const pat = join(patterns, '\|')
execute 'normal! /`..pat.."\<Enter>"

where \V and escape(v, '\') help us build robust patterns for literal text.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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