I need to confirm I have not created duplicate variables in a c file, while converting code from another language which is case insensitive.

For example, a file's content (below 2 lines) is:

  x = data1;
  data2 = Data1+ X;

Above text has x and X, data1 and Data1 and I want to know all such variables in the file.

  • I have got this from search as a solution but this again required me to manually go through sorted words and that too it is not effective in splitting words. cat <filename> | xargs -n1 | sed 's/[/ /g' | xargs -n1 | sort – DevBee Feb 7 '17 at 16:01
  • Sorry, I'm a bit unclear on what you're looking for. You want to find all instances of data1 or Data1, but you don't want it in a search pattern? What do you want it in then? – Tumbler41 Feb 7 '17 at 16:03
  • 1
    @Tmbler41 I want to know such repeated words with case differing, and if case doesn't differ, I dont need them. – DevBee Feb 7 '17 at 16:08
  • How would you differentiate between code and variables? – user41805 Feb 7 '17 at 16:09
  • There wont be such words in code, only variables might be created so, by mistake (or some other reasons). My language in context is C. – DevBee Feb 7 '17 at 16:10

The following script provides the :Ambiguous command. It displays keywords (read :h 'iskeyword') that are the same but have different letter case in the location-list window.

The script is explained through its comments:

function! s:display_ambiguous() abort
  let buckets = {}

  " Split all text in the buffer by non-keywords.
  for word in split(join(getline(1, '$')), '\%(\k\@!.\)\+')
    " Words are collected into a bucket, keyed by the lowercased word.
    let key = tolower(word)
    if !has_key(buckets, key)
      let buckets[key] = []

    " Only add words that haven't been seen before.
    if index(buckets[key], word) == -1
      call add(buckets[key], word)

  let ambiguous = []
  for [key, items] in items(buckets)
    " If a bucket has more than one item, add it to the results.
    if len(items) > 1
      call add(ambiguous, {
            \ 'text': join(items, ', '),
            \ 'bufnr': bufnr('%'),
            \ })

  if !empty(ambiguous)
    " Set the contents of the location-list window.
    call setloclist(0, ambiguous, 'r')
    " Display the location-list window.

command! Ambiguous call s:display_ambiguous()
| improve this answer | |
  • FWIW I agree with your last edit, but just to be clear, I make a lot of mistakes, and I also see other people doing a lot. Usually I don't try to fix them because they're not important / relevant to the question. But here, when I tried the code it didn't work at all because in Vim (could be wrong) it seems the list is ignored if you give a fourth argument. So I tried to fix the code so that it works as intended both in Vim and Neovim. – user9433424 Feb 8 '17 at 18:22
  • By the way, I like your answers in general, they frequently make me learn something. Here for example, it made me learn how to simulate the pseudo-class \K inside the pattern \K\+ (sequence of non keyword characters). So far, I tried to do it like this: [^a-zA-Z_0-9\d192-\d255]\+. But your version is more readable, and takes into account the current value of 'isk': \%(\k\@!.\)\+ – user9433424 Feb 8 '17 at 18:22
  • 1
    @user9433424 No sweat! It was actually my bad since I use Neovim and didn't realize the fourth argument was different from Vim's. Setting the quickfix title wasn't relevant to the question, so I thought it'd be better to just remove it and avoid confusion. Sorry if it seemed like a silent, passive-aggressive edit. SE doesn't make it easy to discuss revisions. I'm glad you get useful information out of my long-winded posts :-) – Tommy A Feb 8 '17 at 20:18

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.