TransWikia.com

Un-tab the cursor

Vi and Vim Asked on August 31, 2021

Is there a way in vim to move backwards a tab as it does move forward a tab? For example, if my line is:

 *   *   *   *   *   *
 hello     |      =      4
           ^ 
           ^
           cursor is here

If I pressed [tab] it would go to the next tabstop, so:

 *   *   *   *   *   *
 hello       |      =      4
             ^ 
             ^
             cursor is here

How would I do un-tab, so my cursor would go here:

 *   *   *   *   *   *
 hello   |      =      4
         ^ 
         ^
         cursor is here

Note: I’m not looking for a >>/<<, or ctrl-d/ctrl-t, which tabs or untabs the entire line. I only want from the cursor position forward.

Update: I added a bounty for this question. I’d like to see how to add a ‘forward-delete’ with ctrl-d and a backward-delete with delete. Here is an example from TextMate: https://gyazo.com/c16d903c1a28c307e3875d9fdf11fe60

The closest I could find is:

*i_CTRL-I* *i_<Tab>* *i_Tab*
<Tab> or CTRL-I Insert a tab.  If the 'expandtab' option is on, the
    equivalent number of spaces is inserted (use CTRL-V <Tab> to
    avoid the expansion; use CTRL-Q <Tab> if CTRL-V is map

One Answer

It is called softtabstop and smarttab, you can read it in help :h 'softtabstop':

Number of spaces that a <Tab> counts for while performing editing
operations, like inserting a <Tab> or using <BS>.  It "feels" like
<Tab>s are being inserted, while in fact a mix of spaces and <Tab>s is
used.  This is useful to keep the 'ts' setting at its standard value
of 8, while being able to edit like it is set to 'sts'.  However,
commands like "x" still work on the actual characters.
When 'sts' is zero, this feature is off.
When 'sts' is negative, the value of 'shiftwidth' is used.

:h smarttab

When on, a <Tab> in front of a line inserts blanks according to
'shiftwidth'.  'tabstop' or 'softtabstop' is used in other places.  A
<BS> will delete a 'shiftwidth' worth of space at the start of the
line.

Usually, one can set it to -1 to be equal to shiftwidth which is used to insert number of spaces instead of tab.

set softtabstop=-1 shiftwidth=4 expandtab smarttab

expandtab is needed to insert spaces instead of tabs, but I guess you have it somewhere in your settings (otherwise you would have used tabs and they behave the way you showed us).

PS, it doesn't work with <Delete>, backspace only (as far as I know). I guess it is possible to come up with insert mode remapping of <Delete> key to delete forward shiftwidth number of spaces.

enter image description here

PPS, proof of concept to forward delete:

func! DumbForwardDelete() abort
    let line = strcharpart(getline('.'), col('.'), shiftwidth())
    if line =~ '^s*$' && strchars(line) == shiftwidth()
        return repeat("<Del>", shiftwidth())
    else
        return "<Del>"
    endif
endfunc

inoremap <expr> <Del> DumbForwardDelete()

Not very robust but might guide you to further improvements.

Correct answer by Maxim Kim on August 31, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP