Loading ...
Sorry, an error occurred while loading the content.
 

Variable width tabstops

Expand Messages
  • Tony Veale
    Is it possible to have variable width tabs within a single line? I d like to replace a Tab marker in a line with a variable number of spaces depending on the
    Message 1 of 5 , Feb 28, 2001
      Is it possible to have variable width tabs within a single line?

      I'd like to replace a "Tab marker" in a line with a variable number of
      spaces depending on the column, specifically I want to have tabstops at
      the 28, 88, 105 and 115 columns.

      Effectively, it would be something like :

      if column < 28
      then insert spaces to column 28
      else
      if column < 88
      then insert spaces to column 88

      etc, etc, etc

      TIA

      --
      Tony Veale Transportation Systems Dept.
      veale@... Software Engineering Laboratory
      tel : (508)490-2072 Raytheon
      fax : (508)490-2007 Marlborough, MA 01752-3789
    • Benji Fisher
      ... I thought this was an interesting problem, so I wrote a map and a function: imap =VarTab(virtcol( . ), 28, 88, 105, 115) fun! VarTab(c, ...)
      Message 2 of 5 , Feb 28, 2001
        Tony Veale wrote:
        >
        > Is it possible to have variable width tabs within a single line?
        >
        > I'd like to replace a "Tab marker" in a line with a variable number of
        > spaces depending on the column, specifically I want to have tabstops at
        > the 28, 88, 105 and 115 columns.
        >
        > Effectively, it would be something like :
        >
        > if column < 28
        > then insert spaces to column 28
        > else
        > if column < 88
        > then insert spaces to column 88
        >
        > etc, etc, etc
        >
        > TIA

        I thought this was an interesting problem, so I wrote a map and a function:

        imap <Tab> <C-R>=VarTab(virtcol("."), 28, 88, 105, 115)<CR>

        fun! VarTab(c, ...)
        let i = 1
        while i <= a:0
        execute "let num_sp = -a:c + a:" . i
        if num_sp > 0
        break
        endif
        let i = i+1
        endwhile
        if i > a:0
        return ""
        endif
        let spaces = " "
        let len = 1
        while len < num_sp
        let spaces = spaces . spaces
        let len = len + len
        endwhile
        return strpart(spaces, 0, num_sp)
        endfun

        You did not say what should happen if the cursor is already at or beyond
        the last tabstop, so I decided to do nothing. To understand how the map
        calls the function, see

        :help i_ctrl-r
        :help virtcol()

        HTH --Benji Fisher
      • Tony Veale
        ... Thanks Benji - that was agreat help! Unfortunately, I have since discovered that the tabstop widths are not fixed, but need to be extracted from an
        Message 3 of 5 , Mar 1, 2001
          It appeared that Benji Fisher wrote:
          >
          > Tony Veale wrote:
          > >
          > > Is it possible to have variable width tabs within a single line?
          > >
          > > I'd like to replace a "Tab marker" in a line with a variable number of
          > > spaces depending on the column, specifically I want to have tabstops at
          > > the 28, 88, 105 and 115 columns.
          > >
          > > Effectively, it would be something like :
          > >
          > > if column < 28
          > > then insert spaces to column 28
          > > else
          > > if column < 88
          > > then insert spaces to column 88
          > >
          > > etc, etc, etc
          > >
          > > TIA
          >
          > I thought this was an interesting problem, so I wrote a map and a function:
          >
          > imap <Tab> <C-R>=VarTab(virtcol("."), 28, 88, 105, 115)<CR>
          >
          > fun! VarTab(c, ...)
          > let i = 1
          > while i <= a:0
          > execute "let num_sp = -a:c + a:" . i
          > if num_sp > 0
          > break
          > endif
          > let i = i+1
          > endwhile
          > if i > a:0
          > return ""
          > endif
          > let spaces = " "
          > let len = 1
          > while len < num_sp
          > let spaces = spaces . spaces
          > let len = len + len
          > endwhile
          > return strpart(spaces, 0, num_sp)
          > endfun
          >
          > You did not say what should happen if the cursor is already at or beyond
          > the last tabstop, so I decided to do nothing. To understand how the map
          > calls the function, see
          >
          > :help i_ctrl-r
          > :help virtcol()
          >
          > HTH --Benji Fisher

          Thanks Benji - that was agreat help!

          Unfortunately, I have since discovered that the tabstop widths are not
          fixed, but need to be extracted from an embedded code of the format:

          <ST.n.n.n.n.n.n>

          where n is each tabstop width and there may be between 1 and 9 of these
          "n"'s.

          So what I need is to extract the tabstop values and pass them by
          variable into the VarTab function, but I can't seem to be able to write
          a regexp to describe a variable length format and use the
          sub-expressions are arguments to VarTab.

          Any help as to how to do this would be appreciated!

          --
          Tony Veale Transportation Systems Dept.
          veale@... Software Engineering Laboratory
          tel : (508)490-2072 Raytheon
          fax : (508)490-2007 Marlborough, MA 01752-3789
        • 赵如飞
          Tony Veale£¬ÄúºÃ£¡ ÔÚ 2001-03-01 17:28:00 ÄúдµÀ£º ... So, if column==28? I think you d like let it go. Let s separate the task into more
          Message 4 of 5 , Mar 1, 2001
            Tony Veale,您好!



            在 2001-03-01 17:28:00 您写道:
            >It appeared that Benji Fisher wrote:
            >>
            >> Tony Veale wrote:
            >> >
            >> > Is it possible to have variable width tabs within a single line?
            >> >
            >> > I'd like to replace a "Tab marker" in a line with a variable number of
            >> > spaces depending on the column, specifically I want to have tabstops at
            >> > the 28, 88, 105 and 115 columns.
            >> >
            >> > Effectively, it would be something like :
            >> >
            >> > if column < 28
            >> > then insert spaces to column 28
            >> > else
            >> > if column < 88
            >> > then insert spaces to column 88
            So, if column==28? I think you'd like let it go.
            Let's separate the task into more simples:
            expand line which length less than 28 up to 28 with spaces;
            fu! ExpSpace1(lineLimit)
            if strlen(getline("."))<a:lineLimit
            exe "normal ".(a:lineLimit-strlen(getline(".")))."A ^C"
            endif
            endf
            Usage:
            :1,$call ExpSpace1(28)
            replace 28 with your favorite number.
            Now it's time to deal with serval column vaulues:
            fun! ExpSpace(...)
            if a:0<1
            return
            endif
            let i=1
            while i<a:0
            exe "let lineLimit=a:".i
            if strlen(getline("."))<lineLimit
            return ExpSpace1(lineLimit)
            elseif strlen(getline("."))==lineLimit
            break | "do nothing
            else
            let i=i+1 | "use larger lineLimit
            endif
            endwhile
            endf

            usage:
            :1,$call ExpSpace(28,88,105,115)
            One thing you must follow is the arg num must be increment sequence, which depend upon the function ExpSpace, because make ExpSpace(88,28,115,105) work as you expected will make the function more complex.
            The basic logic is:
            if(column<28)
            expand to 28 with spaces
            else if(column==28)
            let it go.
            else if(column<88)
            expand to 88 with spaces
            else if(column==88)
            let it go.
            else if(column<105)
            expand to 105 with spaces
            else if(column==105)
            let it go.
            else if(column<115)
            expand to 115 with spaces
            else
            let it go.

            Is it what you expected.

            BTW, I think you can't use different tabstop value in one sigle line, in fact, you can't use varies ts value in one file(buffer), :set ts=N, N is global to the current buffer.


            >> >
            >> > etc, etc, etc
            >> >
            >> > TIA
            >>
            >> I thought this was an interesting problem, so I wrote a map and a function:
            >>
            >> imap <Tab> <C-R>=VarTab(virtcol("."), 28, 88, 105, 115)<CR>
            >>
            >> fun! VarTab(c, ...)
            >> let i = 1
            >> while i <= a:0
            >> execute "let num_sp = -a:c + a:" . i
            >> if num_sp > 0
            >> break
            >> endif
            >> let i = i+1
            >> endwhile
            >> if i > a:0
            >> return ""
            >> endif
            >> let spaces = " "
            >> let len = 1
            >> while len < num_sp
            >> let spaces = spaces . spaces
            >> let len = len + len
            >> endwhile
            >> return strpart(spaces, 0, num_sp)
            >> endfun
            >>
            >> You did not say what should happen if the cursor is already at or beyond
            >> the last tabstop, so I decided to do nothing. To understand how the map
            >> calls the function, see
            >>
            >> :help i_ctrl-r
            >> :help virtcol()
            >>
            >> HTH --Benji Fisher
            >
            >Thanks Benji - that was agreat help!
            >
            >Tony Veale Transportation Systems Dept.
            >veale@... Software Engineering Laboratory
            >tel : (508)490-2072 Raytheon
            >fax : (508)490-2007 Marlborough, MA 01752-3789


            礼!

            赵如飞
            vimer@...
          • Benji Fisher
            ... [snip] ... Well, if you want to convert to ,28,105,115 then you would do ... ) ... or, if that regexp makes you go cross-eyed,
            Message 5 of 5 , Mar 1, 2001
              Tony Veale wrote:
              >
              > It appeared that Benji Fisher wrote:
              > >
              > > Tony Veale wrote:
              > > >
              > > > Is it possible to have variable width tabs within a single line?
              > > >
              > > > I'd like to replace a "Tab marker" in a line with a variable number of
              > > > spaces depending on the column, specifically I want to have tabstops at
              > > > the 28, 88, 105 and 115 columns.
              [snip]
              > >
              > > I thought this was an interesting problem, so I wrote a map and a function:
              > >
              > > imap <Tab> <C-R>=VarTab(virtcol("."), 28, 88, 105, 115)<CR>
              > >
              > > fun! VarTab(c, ...)
              > > let i = 1
              > > while i <= a:0
              > > execute "let num_sp = -a:c + a:" . i
              > > if num_sp > 0
              > > break
              > > endif
              > > let i = i+1
              > > endwhile
              > > if i > a:0
              > > return ""
              > > endif
              > > let spaces = " "
              > > let len = 1
              > > while len < num_sp
              > > let spaces = spaces . spaces
              > > let len = len + len
              > > endwhile
              > > return strpart(spaces, 0, num_sp)
              > > endfun
              > >
              > > You did not say what should happen if the cursor is already at or beyond
              > > the last tabstop, so I decided to do nothing. To understand how the map
              > > calls the function, see
              > >
              > > :help i_ctrl-r
              > > :help virtcol()
              > >
              > > HTH --Benji Fisher
              >
              > Thanks Benji - that was agreat help!
              >
              > Unfortunately, I have since discovered that the tabstop widths are not
              > fixed, but need to be extracted from an embedded code of the format:
              >
              > <ST.n.n.n.n.n.n>
              >
              > where n is each tabstop width and there may be between 1 and 9 of these
              > "n"'s.
              >
              > So what I need is to extract the tabstop values and pass them by
              > variable into the VarTab function, but I can't seem to be able to write
              > a regexp to describe a variable length format and use the
              > sub-expressions are arguments to VarTab.
              >
              > Any help as to how to do this would be appreciated!

              Well, if you want to convert "<ST.28.88.105.115>" to
              ",28,105,115" then you would do

              :s/<ST//
              :s/>//
              :s/\./,/g

              In a script, it is easier to use the substitute() function:

              :let params = substitute(getline("."), '.*<ST\([.[:digit:]]*\)>.*', '\1',
              '')
              :let params = substitute(params, '\.', ',', 'g')

              or, if that regexp makes you go cross-eyed, perhaps

              :let params = matchstr(getline("."), '<ST.*>')
              :let params = substitute(params, '<ST', '', '')
              :let params = substitute(params, '>', '', '')
              :let params = substitute(params, '\.', ',', 'g')

              Then, build a string that defines the :map command and :execute it.

              :execute ':map <Tab> <C-R>=VarTab(virtcol(".")' . params . ')'

              Now, wrap these commands in a function, and decide whether you want to
              invoke it manually (maybe with a command or menu item) or automatically,
              with an autocommand. If you want to search for the embedded code, use the
              regexp in the first substitute() line (without the .* at the beginning and
              end).

              HTH --Benji Fisher
            Your message has been successfully submitted and would be delivered to recipients shortly.