Search code examples
vimvim-plugin

Delete backwards contiguous whitespace or contiguous non-whitespace upto beginning of line


Vim often creates lines with lots of contiguous whitespace, so I'm surprised there isn't an easy way to backwards delete until the end of the previous word. Am I missing something obvious?

hello this is a line       |

deletes back to here:

hello this is a line|

or non-whitespace is before the cursor:

hello this is a line|

deletes back to here:

hello this is a |

That way I could map a key in insert mode and just back delete words or not-words.


Solution

  • Okay, this function does what I need:

    function! BackspaceContiguousInsertMode()
    python << EOF
    import vim  
    try:
        line = vim.current.line
        row, deleteto = vim.current.window.cursor
        if deleteto==0:
            vim.current.line = ""
            vim.command("startinsert")
        elif line[deleteto] == " ":
            deletefrom=deleteto
            while deletefrom-1>0 and vim.current.line[deletefrom-1] == " ":
                deletefrom=deletefrom-1
            vim.current.line=line[:deletefrom] + line[deleteto+1:]
            if len(line)-1 == deleteto:
                vim.current.window.cursor = (row,deletefrom+1)
                vim.command("startinsert!")
            else:
                vim.current.window.cursor = (row,deletefrom)
                vim.command("startinsert")
        else:
            eol=deleteto+1 >= len(line)
            if not eol and line[deleteto+1] != " ":
                trailingline = line[deleteto+1:]
                vim.current.line=line[:deleteto+1] + " " + trailingline
                vim.command("normal diw")
                leadingto=len(vim.current.line)-len(trailingline)-1
                vim.current.line=vim.current.line[:leadingto] + trailingline
                vim.command("startinsert")
            elif eol:    
                vim.command("normal diw")
                vim.command("startinsert!")
            else: 
                vim.command("normal diw")
                vim.command("startinsert")
    
    except Exception as e:
        print("Error: {}".format(e))
    EOF
    endfunction
    inoremap <C-b> <Esc>:call BackspaceContiguousInsertMode()<CR>
    

    From insert mode (which is where I wanted to invoke it from) I can press <C-b> to back delete each word block or whitespace block to the beginning of the line. Given the following line, each time I press <C-b> this is what happens:

    alskdjf       a;sjdf a kjkdjd        |kja sdf
    alskdjf       a;sjdf a kjkdjd|kja sdf
    alskdjf       a;sjdf a |kja sdf
    alskdjf       a;sjdf a|kja sdf
    alskdjf       a;sjdf |kja sdf
    alskdjf       a;sjdf|kja sdf
    alskdjf       a;|kja sdf
    alskdjf       a|kja sdf
    alskdjf       |kja sdf
    alskdjf|kja sdf
    |kja sdf
    |... (stays on the same line)