expandtab after non-blanks only

18 views
Skip to first unread message

Andreas Müller

unread,
Oct 11, 2007, 4:17:17 PM10/11/07
to vim...@googlegroups.com
Hello ..

Among suggested uses for tabs, :help tabstop lists

--
4. Always set 'tabstop' and 'shiftwidth' to the same value, and
'noexpandtab'. This should then work (for initial indents only)
for any tabstop setting that people use. It might be nice to have
tabs after the first non-blank inserted as spaces if you do this
though. Otherwise aligned comments will be wrong when 'tabstop' is
changed.
--

I like to format code like this, but I haven't found a setting to avoid
having to enter spaces manually. Is there an easy way to expand tabs
automatically after non-blanks?

Regards, Andreas

signature.asc

Andy Wokula

unread,
Oct 12, 2007, 8:34:30 AM10/12/07
to vim...@googlegroups.com
Andreas Müller schrieb:

> Hello ..
>
> Among suggested uses for tabs, :help tabstop lists
>
> --
> 4. Always set 'tabstop' and 'shiftwidth' to the same value, and
> 'noexpandtab'. This should then work (for initial indents only)
> for any tabstop setting that people use. It might be nice to have
> tabs after the first non-blank inserted as spaces if you do this
> though. Otherwise aligned comments will be wrong when 'tabstop' is
> changed.
> --

The "nice to have"-part is not supported by an option yet. There isn't
even an entry in the todo list - at least I haven't found one. The help
for :retab is satisfied with a warning

| Careful: This command modifies any <Tab> characters inside of strings
| in a C program. Use "\t" to avoid this (that's a good habit anyway).
| ":retab!" may also change a sequence of spaces by <Tab> characters,
| which can mess up a printf().

As a workaround, you could remove hard tabs within lines with
:set et| retab| set noet| %>| %<

before finally saving a file.

It would be nice to have an option 'indenttab': If on, hard tabs are
only inserted for the indent (default off). But currently, there is no
such option.

> I like to format code like this, but I haven't found a setting to avoid
> having to enter spaces manually. Is there an easy way to expand tabs
> automatically after non-blanks?
>
> Regards, Andreas

You have to go along with a script, like this one:

""""""""""""""""""""""""""""""""""""""""""""""""""
ino <silent><tab> <c-r>=<sid>tabet()<cr><c-o>:call<sid>restoret()<cr>

" set 'expandtab' when needed and return <Tab>
func! <sid>tabet()
if !&expandtab && virtcol(".")-1 > indent(".")
let s:restoret = 1
set expandtab
else
let s:restoret = 0
endif
return "\<tab>"
endfunc

" restore 'expandtab'
func! <sid>restoret()
if s:restoret
set noexpandtab
endif
endfunc
""""""""""""""""""""""""""""""""""""""""""""""""""

It looks ugly, but an easier variant fails:

""""""""""""""""""""""""""""""""""""""""""""""""""
" Script2:
if &ts != &sw || !&et
echo "Script2 requires tabstop==shiftwidth and expandtab on"
finish
endif

ino <silent><tab> <c-r>=<sid>mytab()<cr>

func! <sid>mytab()
if virtcol(".")-1 > indent(".")
return "\<tab>"
else
return "\<c-v>\<tab>"
endif
endfunc
""""""""""""""""""""""""""""""""""""""""""""""""""

... because with 'expandtab' on, spaces are inserted for the
auto-indent.

Remaining problem: Won't probably work together with scripts like
supertab.

See also: Converting tabs to spaces
http://vim.wikia.com/wiki/VimTip12

I'd also like to hear about an easy solution for the issue.

--
Andy

Tim Chase

unread,
Oct 12, 2007, 8:45:07 AM10/12/07
to vim...@googlegroups.com
>> for any tabstop setting that people use. It might be nice to have
>> tabs after the first non-blank inserted as spaces if you do this
>> though. Otherwise aligned comments will be wrong when 'tabstop' is
>> changed.

I've done something like this with a substitute command:

:%s/\S.*/\=substitute(submatch(0), '\t', ' ', 'g')

where the number of spaces in the 3rd parameter is the number.
In Vim7+, you can make that

:%s/\S.*/\=substitute(submatch(0), '\t', repeat(' ', &ts), 'g')

to deal with whatever your 'tabstop' setting happens to be.

Granted, it's not dynamic, but it can be mapped to retab things
at a keypress.

-tim

Andy Wokula

unread,
Oct 12, 2007, 9:56:33 AM10/12/07
to vim...@googlegroups.com
Andy Wokula schrieb:
> Andreas Müller schrieb:

>> 4. Always set 'tabstop' and 'shiftwidth' to the same value, and
>> 'noexpandtab'. This should then work (for initial indents only)
>> for any tabstop setting that people use. It might be nice to have
>> tabs after the first non-blank inserted as spaces if you do this
>> though. Otherwise aligned comments will be wrong when 'tabstop' is
>> changed.
>> --
> The "nice to have"-part is not supported by an option yet.

Hmm: The assumption is wrong. Spaces within the line don't help keeping
comments aligned when 'tabstop' changes, example (here ":---" means a
hardtab with ts=4):

:---:---Code // comment
:---Code // comment

Now :set ts=3 . Either the help is wrong or I misunderstood sth here.

--
Andy

Andreas Müller

unread,
Oct 12, 2007, 3:58:59 PM10/12/07
to vim...@googlegroups.com
Andy Wokula schrieb:

> It would be nice to have an option 'indenttab': If on, hard tabs are
> only inserted for the indent (default off). But currently, there is no
> such option.

I would have been quite surprised if there was such an option - I've
been looking for exactly that everywhere ...

> You have to go along with a script, like this one:
>
> """"""""""""""""""""""""""""""""""""""""""""""""""
> ino <silent><tab> <c-r>=<sid>tabet()<cr><c-o>:call<sid>restoret()<cr>
>
> " set 'expandtab' when needed and return <Tab>
> func! <sid>tabet()
> if !&expandtab && virtcol(".")-1 > indent(".")
> let s:restoret = 1
> set expandtab
> else
> let s:restoret = 0
> endif
> return "\<tab>"
> endfunc
>
> " restore 'expandtab'
> func! <sid>restoret()
> if s:restoret
> set noexpandtab
> endif
> endfunc
> """"""""""""""""""""""""""""""""""""""""""""""""""

This works very nicely, thanks!

Regards, Andreas

signature.asc

Andreas Müller

unread,
Oct 12, 2007, 4:02:16 PM10/12/07
to vim...@googlegroups.com
Tim Chase schrieb:

I tried this in a similar way, but the problem with this is that it will
expand any tab to the maximum amount of spaces, no matter how many
spaces the tab actually occupied.

Regards, Andreas

signature.asc

Andreas Müller

unread,
Oct 12, 2007, 4:13:18 PM10/12/07
to vim...@googlegroups.com
Andy Wokula schrieb:

I know that it wont work for different indents, but without expanding
tabs, even comments aligned behind code of the same indent may get
broken. e.g.:

<tab>Code<tab>// comment
<tab>XYZ<tab><tab>// comment

is aligned with sw=4 and ts=4, but changing to ts=5 or ts=3 will break
it. For this, expanding the tabs is already quite an improvement.

Regards, Andreas

signature.asc
Reply all
Reply to author
Forward
0 new messages