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

Re: Variable width tabstops

Expand Messages
  • 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 1 of 5 , Mar 1, 2001
    • 0 Attachment
      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 2 of 5 , Mar 1, 2001
      • 0 Attachment
        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 3 of 5 , Mar 1, 2001
        • 0 Attachment
          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.