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

"hungry" delete in vim?

Expand Messages
  • Peter Wright
    Hi all, I ve been trying to work out how to implement a hungry whitespace delete mapping in Vim 6.1. By this I mean: in insert mode, if you hit the backspace
    Message 1 of 5 , Sep 1, 2002
    • 0 Attachment
      Hi all,

      I've been trying to work out how to implement a "hungry" whitespace
      delete mapping in Vim 6.1. By this I mean: in insert mode, if you hit
      the backspace key (though I've used control-backspace in my attempts
      below, so I don't inadvertantly stuff up my "normal" backspace), it
      will delete backwards over consecutive whitespace characters until
      reaching a non-whitespace character (including blank lines).

      For those who know Emacs, yes, much like the hungry-delete feature in
      Emacs' C-mode.

      I played around with this for a bit, trying to work out some way to
      implement it, but have not completely succeeded, and I was hoping
      someone could either (a) tell me a way to get my attempt (shown below)
      working properly, or (b) could suggest a completely different way of
      solving the problem.


      I tried a mapping like so:

      " Attempt at hungry-delete...
      " NB. using control-backspace for now.
      set virtualedit=block
      imap <C-BS> <Esc>vgE<Space>xi


      Unfortunately, this (a) doesn't handle the case of multiple blank
      lines between starting point and "corrent" end point as empty lines
      are considered "words" (see :help gE):

      > A WORD consists of a sequence of non-blank characters, separated
      > with white space. An empty line is also considered to be a word and
      > a WORD.

      ...and (b) doesn't handle the case where the starting cursor point is
      at the _beginning_ of a line.

      Also, I really don't like the idea of 'x'-ing stuff into a register,
      when the user normally wouldn't expect backspacing to "copy" the
      deleted text.

      I'd prefer some way to map <C-BS> to some kind of function that will
      keep backspacing while (character-immediately-before-cursor is
      whitespace or end-of-line). But I'm not actually sure if that's
      possible *wry grin*... my Vim scripting experience is fairly minimal.

      I'd appreciate any suggestions on implementing this... a complete
      solution would be fantastic, but even a hint on implementing just the
      "while" condition described in the previous paragraph would be nice.
      Hell, I'd like to know how to do that even if someone can offer a
      completely different way to handle the mapping... ;-)


      Thanks,

      Pete.
      --
      http://akira.apana.org.au/~pete/
      "Beware of bugs in the above code; I have only proved
      it correct, not tried it." -- Donald Knuth
    • Mark Khemma
      Try this out: imap bi :s/ +// i basically what it does is go into normal mode, then move back to the beginning of
      Message 2 of 5 , Sep 2, 2002
      • 0 Attachment
        Try this out:
        imap <your mapkey of choice> <ESC>bi<CR><ESC>:s/ \+//<CR>i<BS>

        basically what it does is go into normal mode,
        then move back to the beginning of the previous word
        go into insert mode
        carriage return to move it to next line
        the regex continuous whitespace (one instance)
        back into insert mode
        the move the word back.

        you have to move that last word to the next line because if you do the
        regex without it, it would remove the first instance of continuous
        whitespaces at the beginning of that line, if that makes any sense.

        I dont' know if this is exactly what you want but, it was a
        fun puzzle for me to try :)

        -mark.k

        On Mon, 2 Sep 2002, Peter Wright wrote:

        >
        > Hi all,
        >
        > I've been trying to work out how to implement a "hungry" whitespace
        > delete mapping in Vim 6.1. By this I mean: in insert mode, if you hit
        > the backspace key (though I've used control-backspace in my attempts
        > below, so I don't inadvertantly stuff up my "normal" backspace), it
        > will delete backwards over consecutive whitespace characters until
        > reaching a non-whitespace character (including blank lines).
        >
        > For those who know Emacs, yes, much like the hungry-delete feature in
        > Emacs' C-mode.
        >
        > I played around with this for a bit, trying to work out some way to
        > implement it, but have not completely succeeded, and I was hoping
        > someone could either (a) tell me a way to get my attempt (shown below)
        > working properly, or (b) could suggest a completely different way of
        > solving the problem.
        >
        >
        > I tried a mapping like so:
        >
        > " Attempt at hungry-delete...
        > " NB. using control-backspace for now.
        > set virtualedit=block
        > imap <C-BS> <Esc>vgE<Space>xi
        >
        >
        > Unfortunately, this (a) doesn't handle the case of multiple blank
        > lines between starting point and "corrent" end point as empty lines
        > are considered "words" (see :help gE):
        >
        > > A WORD consists of a sequence of non-blank characters, separated
        > > with white space. An empty line is also considered to be a word and
        > > a WORD.
        >
        > ...and (b) doesn't handle the case where the starting cursor point is
        > at the _beginning_ of a line.
        >
        > Also, I really don't like the idea of 'x'-ing stuff into a register,
        > when the user normally wouldn't expect backspacing to "copy" the
        > deleted text.
        >
        > I'd prefer some way to map <C-BS> to some kind of function that will
        > keep backspacing while (character-immediately-before-cursor is
        > whitespace or end-of-line). But I'm not actually sure if that's
        > possible *wry grin*... my Vim scripting experience is fairly minimal.
        >
        > I'd appreciate any suggestions on implementing this... a complete
        > solution would be fantastic, but even a hint on implementing just the
        > "while" condition described in the previous paragraph would be nice.
        > Hell, I'd like to know how to do that even if someone can offer a
        > completely different way to handle the mapping... ;-)
        >
        >
        > Thanks,
        >
        > Pete.
        > --
        > http://akira.apana.org.au/~pete/
        > "Beware of bugs in the above code; I have only proved
        > it correct, not tried it." -- Donald Knuth
        >
      • Preben 'Peppe' Guldberg
        ... While not excactly what you describe, I quite like setting softtabstop equal to shiftwidth when I set expandtab . Doing so, a backspace in insert mode
        Message 3 of 5 , Sep 2, 2002
        • 0 Attachment
          Thus wrote Peter Wright (pete@...) on [020902]:

          > I've been trying to work out how to implement a "hungry" whitespace
          > delete mapping in Vim 6.1. By this I mean: in insert mode, if you hit
          > the backspace key (though I've used control-backspace in my attempts
          > below, so I don't inadvertantly stuff up my "normal" backspace), it
          > will delete backwards over consecutive whitespace characters until
          > reaching a non-whitespace character (including blank lines).

          While not excactly what you describe, I quite like setting 'softtabstop'
          equal to 'shiftwidth' when I set 'expandtab'. Doing so, a backspace in
          insert mode will delete a soft tabstops worth of spaces.

          For an initial test, try

          $ vim -u NONE -N -c 'se et sts=8'

          Also see ":help 'softtabstop'".

          Peppe
          --
          Preben 'Peppe' Guldberg __/-\__ "Before you criticize someone, walk
          peppe@... (o o) a mile in his shoes. That way, if
          -----------------------oOOo (_) oOOo-- he gets angry, he'll be a mile away
          http://www.xs4all.nl/~peppe/ - and barefoot." --Sarah Jackson
        • David Brown
          Try this out: imap v? S?e+1 di This mapping does not work if only white space exists to the beginning of the file. If you have wrapscan turned
          Message 4 of 5 , Sep 5, 2002
          • 0 Attachment
            Try this out:

            imap <C-BS> <ESC>v?\\S?e+1<CR>di

            This mapping does not work if only white space exists to the beginning of
            the file. If you have wrapscan turned on it will delete everything from the
            cursor to the last nonwhite stuff in the file. If you have wrapscan turned
            off it gives an error message (no nonwhite space to find) and deletes
            nothing. Other then that, it seemed to work very well.

            -----Original Message-----
            From: Peter Wright [mailto:pete@...]On Behalf Of Peter
            Wright
            Sent: Monday, September 02, 2002 1:37 AM
            To: vim@...
            Subject: "hungry" delete in vim?



            Hi all,

            I've been trying to work out how to implement a "hungry" whitespace
            delete mapping in Vim 6.1. By this I mean: in insert mode, if you hit
            the backspace key (though I've used control-backspace in my attempts
            below, so I don't inadvertantly stuff up my "normal" backspace), it
            will delete backwards over consecutive whitespace characters until
            reaching a non-whitespace character (including blank lines).

            For those who know Emacs, yes, much like the hungry-delete feature in
            Emacs' C-mode.

            I played around with this for a bit, trying to work out some way to
            implement it, but have not completely succeeded, and I was hoping
            someone could either (a) tell me a way to get my attempt (shown below)
            working properly, or (b) could suggest a completely different way of
            solving the problem.


            I tried a mapping like so:

            " Attempt at hungry-delete...
            " NB. using control-backspace for now.
            set virtualedit=block
            imap <C-BS> <Esc>vgE<Space>xi


            Unfortunately, this (a) doesn't handle the case of multiple blank
            lines between starting point and "corrent" end point as empty lines
            are considered "words" (see :help gE):

            > A WORD consists of a sequence of non-blank characters, separated
            > with white space. An empty line is also considered to be a word and
            > a WORD.

            ...and (b) doesn't handle the case where the starting cursor point is
            at the _beginning_ of a line.

            Also, I really don't like the idea of 'x'-ing stuff into a register,
            when the user normally wouldn't expect backspacing to "copy" the
            deleted text.

            I'd prefer some way to map <C-BS> to some kind of function that will
            keep backspacing while (character-immediately-before-cursor is
            whitespace or end-of-line). But I'm not actually sure if that's
            possible *wry grin*... my Vim scripting experience is fairly minimal.

            I'd appreciate any suggestions on implementing this... a complete
            solution would be fantastic, but even a hint on implementing just the
            "while" condition described in the previous paragraph would be nice.
            Hell, I'd like to know how to do that even if someone can offer a
            completely different way to handle the mapping... ;-)


            Thanks,

            Pete.
            --
            http://akira.apana.org.au/~pete/
            "Beware of bugs in the above code; I have only proved
            it correct, not tried it." -- Donald Knuth
          • Thomas S. Urban
            ... This behaves strangely for me, leaving the cursor at the wrong place and deleting multiple characters when used on non-whitespace. I think your best bet
            Message 5 of 5 , Sep 6, 2002
            • 0 Attachment
              On Fri, Sep 06, 2002 at 00:42:12 -0400, David Brown sent 2.8K bytes:
              > From: Peter Wright [mailto:pete@...]On Behalf Of Peter
              > > I've been trying to work out how to implement a "hungry" whitespace
              > > delete mapping in Vim 6.1. By this I mean: in insert mode, if you hit
              > > the backspace key (though I've used control-backspace in my attempts
              > > below, so I don't inadvertantly stuff up my "normal" backspace), it
              > > will delete backwards over consecutive whitespace characters until
              > > reaching a non-whitespace character (including blank lines).
              >
              > Try this out:
              >
              > imap <C-BS> <ESC>v?\\S?e+1<CR>di

              This behaves strangely for me, leaving the cursor at the wrong place and
              deleting multiple characters when used on non-whitespace. I think your
              best bet is to write a function and call it from your mapping, the below
              is a quick trial that seems to handle beginning of file, newline, and
              normal characters. The logic could probably use some clean up:

              function! GreedyBackspace()
              let c = getline(line("."))[col(".") - 1]
              if c == ' ' || c == "\t" || col("$") == 1
              while c == ' ' || c == "\t" || col("$") == 1
              if col("$") == 1
              if line (".") == 1
              break
              endif
              normal k$gJ
              else
              normal x
              endif
              let c = getline(line("."))[col(".") - 1]
              endwhile
              else
              normal x
              endif
              endfunction
              imap <C-BS> <Esc>:call GreedyBackspace()<CR>a

              <snip>

              Scott

              --
              ... The prejudices people feel about each other disappear when then get
              to know each other.
              -- Kirk, "Elaan of Troyius", stardate 4372.5
            Your message has been successfully submitted and would be delivered to recipients shortly.