24

Apologize for the newbie question, but I have read the manual, this question, and tried several times without results I expected.

So I was using vim to edit a file (attached). But when running, I got the TabError: inconsistent use of tabs and spaces in indentation error.

Here is what I have tried:

  • Open the file with Vim. type :retab, and :x. Run the file again. Still got the TabError message.
  • Open the file again and type :retab! and :x. Run the file again. Still got the TabError message.
  • Open the file again and type :retab! 4 and :x. Run the file again. This time it works but I have no idea why? Plus, in the files indentation seems excessively long. (I read here that the editor might display 8 spaces for a tab)

My questions are:

  • What does :retab, :retab!, and :retab! 4 mean?

  • Why doesn't :retab work on my file?

    #!/usr/bin/env python
    #Reduce function for computing matrix multiply A*B    
    #Input arguments:
    #variable n should be set to the inner dimension of the matrix product (i.e., the number of columns of A/rows of B) 
    import sys
    import string
    import numpy
    
    #number of columns of A/rows of B
    n = int(sys.argv[1]) 
    
    #Create data structures to hold the current row/column values (if needed; your code goes here)
    
    currentkey = None
    alist = [] # list for elelents in  A
    blist = [] # list for elements in B
    # input comes from STDIN (stream data that goes to the program)
    for line in sys.stdin:
        #Remove leading and trailing whitespace
        line = line.strip()
        #Get key/value 
        key, value = line.split('\t',1)
        print(key, value)
        #Parse key/value input (your code goes here)
        key = (key.split(',', 1)[0], key.split(',',1)[1])   
        value = (value.split(',', 1)[0], value.split(',',1)[1], value.split(',',1)[2])  
        #If we are still on the same key...
        if key==currentkey:
            #Process key/value pair (your code goes here)
            # store all values in a lisl
            if value[0]=='A':
            alist.append([value[1], value[2]])
            else:
            blist.append([value[1], value[2]])
            #Otherwise, if this is a new key...
        else:
        #If this is a new key and not the first key we've seen, i.e. currentkey!=None
            if currentkey:
        #compute/output result to STDOUT (your code goes here)
            alist = sorted(alist)
            blist = sorted(blist)
            newlist = [a[1]*b[1] for a,b in zip(alist, blist)]
            res = newlist.sum() 
            print(currentkey, res)
            currentkey = key
            #Process input for new key (your code goes here)
    
yuqli
  • 4,461
  • 8
  • 26
  • 46
  • You say you have read the manual, did you type `:help retab` in Vim? – progmatico Feb 11 '18 at 19:55
  • 1
    @promatico Thanks for the reply! The manual is a bit technical and I'm not sure I understand it correctly. I guess `:retab! 4` means a tab is changed to 4 spaces? If this is the case, why doesn't `:retab` or `:retab!`work? – yuqli Feb 11 '18 at 20:14
  • They do work. try `%:retab! 4` or `%:retab 4`, but after `:set list` to see the tabs as tabs. Sometimes they do nothing because there is nothing to be done. – progmatico Feb 11 '18 at 21:46

3 Answers3

20

Just type :help retab in Vim and read. I think I can't explain it better than the help. Maybe you are missing the optional range part; use % prefix to apply to the whole file. Also useful is :set list to show you every chars; this will show you the tabs and line ends (disable with :set nolist) and :set <name> with no value to see the current value, ex : set tabstop or followed by some value to set.

By showing all chars, enabling and disabling expansion of tabs into spaces with :set expandtab and :set noexpandtab, setting tabstop and by using for ex. :retab! 4 you can play your way around and switch from tabs only and spaces only, and change the tab column width.

This link, vim settings for python might be useful also

progmatico
  • 4,714
  • 1
  • 16
  • 27
  • 4
    Just some tangential vim advice: Whenever I'm manually toggling an option with exactly two states, on or off, rather than using the explicit `:set – Edward Feb 11 '18 at 22:43
  • Thanks for the pointer! With :set list I was able to see exactly how many tabs in my scripts and undersood why the script looked ugly. It's also good to know the use of %. @Edward I unfortunately don't exactly understand your advice at the moment, but I'm sure they might be useful sometime in the future! – yuqli Feb 12 '18 at 02:53
  • 2
    @yuqli, to clarify: If `list`, for example, is turned off and you want to turn it on, you have two choices - `:set list` OR `:set list!`. Then to turn `list` off again later, you can use `:set nolist`, OR you can use `:set list!` again. The "!" here means "whatever the current state of the option", flip it to the opposite. Now the business with the up arrow: If you have typed a command with ":" lately, that you want to use again, you can save retyping it by hitting ":" and then the up arrow (repeatedly), to scroll through your past commands in reverse-chronological order. Then Enter to select – Edward Feb 12 '18 at 17:05
  • @Edward I understand it now. Thanks! – yuqli Mar 04 '18 at 00:17
17

Esc

:%s/\t/    /g

It means to replace the tab with 4 spaces. Hit Enter Esc

:wq
DARK_C0D3R
  • 2,075
  • 16
  • 21
2

While just trying to run :retab might not work if you have copy pasted code and started to edit it.

You can try setting the vim/vi settings first:

  1. Check if you have ~/.vim/vimrc file else run sudo mkdir ~/.vim && sudo touch ~/.vim/vimrc to create settings file
  2. once created edit vimrc to add below snippet
    set softtabstop=4
    set tabstop=4
    set shiftwidth=4
    set expandtab
  1. open your file using vim/vi and run :retab
Aklesh Sakunia
  • 321
  • 2
  • 6