The following code defines the command :UniqueWords
which tries to do what you want:
command! UniqueWords call UniqueWords()
function! UniqueWords() abort
let words = []
silent! %s/"\zs\w\{-}\ze"/\=add(words, submatch(0))/gn
let dic = {}
let uniq_words = uniq(sort(copy(words)))
for i in range(len(uniq_words))
if uniq_words[i] != ''
call extend(dic, {uniq_words[i]: count(words, uniq_words[i])})
endif
endfor
call filter(dic, 'v:val == 1')
let pattern = join(keys(dic), '\|')
silent! execute 'match SpellBad /' . pattern . '/'
return [keys(dic), pattern]
endfunction
The command calls the UniqueWords()
function which does the following:
let words = []
Define the empty list words
whose purpose will be to contain all the words surrounded by double quotes in your current buffer.
silent! %s/"\zs\w\{-}\ze"/\=add(words, submatch(0))/gn
Call the substitute command :s
to look for the pattern "\zs\w\{-}\ze"
(word characters between 2 consecutive double quotes). Whenever such a text is found it's added to the words
list, but without actually performing any substitution thanks to the n
flag.
let dic = {}
Define an empty dictionary, whose purpose will be to contain all your quoted words as well as the number of times they appear.
let uniq_words = uniq(sort(copy(words)))
Define the list uniq_words
which again contains all the words, but this time the list is sorted with the sort()
function, and the duplicates are removed with the uniq()
function. A copy of words
is also made, so that the latter is not altered in the process.
for i in range(len(uniq_words))
Begin a loop which iterates over the words in uniq_words
.
call extend(dic, {uniq_words[i]: count(words, uniq_words[i])})
Add a new item to the dictionary dic
, whose key is a word from uniq_words
(uniq_words[i]
) and whose value is the number of times it appears (count(words, uniq_words[i])
).
call filter(dic, 'v:val == 1')
Remove all the items from dic
whose values are different than one, because you're only interested in words which appear once.
let pattern = join(keys(dic), '\|')
Build a pattern by joining all the keys from dic
and separating them with \|
(that's how you separate two branches, see :h /bar
).
silent! execute 'match SpellBad /' . pattern . '/'
Highlight the words which appear inside pattern
with the highlighting group SpellBad
.
return [keys(dic), pattern]
Return the keys from dic
, so that you can access them through a list, as well as the pattern so that you can use it later in a substitute command.
For example, to see the list, you could type: :echo UniqueWords()[0]
And to remove the words which appear only once, you could type:
:exe '%s/' . UniqueWords()[1] . '//g'
For more information, see:
:help :command
:help add()
:help copy()
:help sort()
:help uniq()
:help len()
:help range()
:help count()
:help extend()
:help filter()
:help keys()
:help join()
:help :match