patch 8.1.0105: all tab stops are the same

Problem:    All tab stops are the same.
Solution:   Add the variable tabstop feature. (Christian Brabandt,
            closes #2711)
diff --git a/runtime/doc/change.txt b/runtime/doc/change.txt
index 05c18e6..b59f28f 100644
--- a/runtime/doc/change.txt
+++ b/runtime/doc/change.txt
@@ -987,6 +987,11 @@
 			this (that's a good habit anyway).
 			`:retab!` may also change a sequence of spaces by
 			<Tab> characters, which can mess up a printf().
+			If the |+vartabs| feature is enabled then a list of
+			tab widths separated by commas may be used in place of
+			a single tabstop.  Each value in the list represents
+			the width of one tabstop, except the final value which
+			applies to all following tabstops.
 			{not in Vi}
 
 							*retab-example*
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index d37fa64..65a9d17 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -7172,6 +7172,10 @@
 	set.
 	NOTE: This option is set to 0 when 'compatible' is set.
 
+	If Vim is compiled with the |+vartabs| feature then the value of
+	'softtabstop' will be ignored if |'varsofttabstop'| is set to
+	anything other than an empty string.
+
 						*'spell'* *'nospell'*
 'spell'			boolean	(default off)
 			local to window
@@ -7723,6 +7727,10 @@
 	   though.  Otherwise aligned comments will be wrong when 'tabstop' is
 	   changed.
 
+	If Vim is compiled with the |+vartabs| feature then the value of
+	'tabstop' will be ignored if |'vartabstop'| is set to anything other
+	than an empty string.
+
 			*'tagbsearch'* *'tbs'* *'notagbsearch'* *'notbs'*
 'tagbsearch' 'tbs'	boolean	(default on)
 			global
@@ -8468,6 +8476,44 @@
 	written to disk (see |crash-recovery|).  Also used for the
 	|CursorHold| autocommand event.
 
+					*'varsofttabstop'* *'vsts'*
+'varsofttabstop' 'vsts'	string	(default "")
+			local to buffer
+			{only available when compiled with the |+vartabs|
+			feature}
+			{not in Vi}
+	A list of the number of spaces that a <Tab> counts for while editing,
+	such as inserting a <Tab> or using <BS>.  It "feels" like variable-
+	width <Tab>s are being inserted, while in fact a mixture of spaces
+	and <Tab>s is used.  Tab widths are separated with commas, with the
+	final value applying to all subsequent tabs.
+
+	For example, when editing assembly language files where statements
+	start in the 8th column and comments in the 40th, it may be useful
+	to use the following: >
+		:set varsofttabstop=8,32,8
+<	This will set soft tabstops at the 8th and 40th columns, and at every
+	8th column thereafter.
+
+	Note that the value of |'softtabstop'| will be ignored while
+	'varsofttabstop' is set.
+
+						*'vartabstop'* *'vts'*
+'vartabstop' 'vts'	string	(default "")
+			local to buffer
+			{only available when compiled with the |+vartabs|
+			feature}
+			{not in Vi}
+	A list of the number of spaces that a <Tab> in the file counts for,
+	separated by commas.  Each value corresponds to one tab, with the
+	final value applying to all subsequent tabs. For example: >
+		:set vartabstop=4,20,10,8
+<	This will make the first tab 4 spaces wide, the second 20 spaces,
+	the third 10 spaces, and all following tabs 8 spaces.
+
+	Note that the value of |'tabstop'| will be ignored while 'vartabstop'
+	is set.
+
 						*'verbose'* *'vbs'*
 'verbose' 'vbs'		number	(default 0)
 			global
diff --git a/runtime/doc/various.txt b/runtime/doc/various.txt
index 7c8f311..bd2b35e 100644
--- a/runtime/doc/various.txt
+++ b/runtime/doc/various.txt
@@ -453,6 +453,7 @@
 N  *+title*		Setting the window 'title' and 'icon'
 N  *+toolbar*		|gui-toolbar|
 N  *+user_commands*	User-defined commands. |user-commands|
+B  *+vartabs*		Variable-width tabstops. |'vartabstop'|
 N  *+viminfo*		|'viminfo'|
    *+vertsplit*		Vertically split windows |:vsplit|; Always enabled
 			since 8.0.1118.
diff --git a/runtime/optwin.vim b/runtime/optwin.vim
index cd1bea0..5ab5792 100644
--- a/runtime/optwin.vim
+++ b/runtime/optwin.vim
@@ -856,6 +856,14 @@
 call append("$", "shiftwidth\tnumber of spaces used for each step of (auto)indent")
 call append("$", "\t(local to buffer)")
 call <SID>OptionL("sw")
+if has("vartabs")
+  call append("$", "vartabstop\tlist of number of spaces a tab counts for")
+  call append("$", "\t(local to buffer)")
+  call <SID>OptionL("vts")
+  call append("$", "varsofttabstop\tlist of number of spaces a soft tabsstop counts for")
+  call append("$", "\t(local to buffer)")
+  call <SID>OptionL("vsts")
+endif
 call append("$", "smarttab\ta <Tab> in an indent inserts 'shiftwidth' spaces")
 call <SID>BinOptionG("sta", &sta)
 call append("$", "softtabstop\tif non-zero, number of spaces to insert for a <Tab>")