Proposed tip Please edit this page to improve it, or add your comments below (do not use the discussion page).
It bothered me a bit that Ctrl-D in insert mode would just hop on multiples of shiftwidth when editing files with complex (and creative) indentation such as Haskell source files. I replaced <Ctrl-D> with the following Python function that scans the lines above the current one, finds the closest line that has strictly smaller indent and dedents the current one to that level.
" Handy function to search previous lines for indent levels and " use those instead of multiples of shiftwidth. function! DedentToPrevious() python << EOF import vim tabsize = int(vim.eval("&ts")) l = vim.current.line rest = l.lstrip() indent = l[:len(l)-len(rest)] if indent != "": cur_size = len(indent.replace("\t", " "*tabsize)) idx = vim.current.window.cursor[0]-2 while idx >= 0: ll = vim.current.buffer[idx] indent = ll[:len(ll)-len(ll.lstrip())] if len(indent.replace("\t", " "*tabsize)) < cur_size: vim.current.line = indent+rest break idx -= 1 EOF endfunction " replace the <C-D> in insert mode with the above function imap <C-d> <C-o>:call DedentToPrevious()<cr>
Tips for improvement
If you are feeling adventurous, you could make a modified version that takes over the backspace key. I'd recommend using
vim.current.window.cursor
to detect if the cursor is right between the indent whitespace and line contents (if any) and only use the above behavior in that case. All other cursor positions would need to have the normal backspace behavior.
Comments
TO DO
When Vim auto-indents a new line after pressing return, the line and cursor position exposed to scripts is actually emtpy and zero, respectively. Does anyone know how to get the perceived cursor position (i.e. as the user sees it)?