I am trying to implement "trimming trailing whitespace in changed lines only". For this purpose, I intercept
TextChangedI autocmd events and record the current line (
line(.)) in the handler. The changed lines are then trimmed in a
BufWritePre autocmd event handler.
It works OK, except for the case when a line is inserted/removed. In this case, I need to shift existing records.
Initially I assumed that the cursor always gets placed on last inserted/first removed line (with this knowledge, it is possible to calculate the range, if you remember the previous line count), but with undo and paste this is not true.
How to determine the exact line range which has been inserted/removed with current TextChanged event?
The current (broken) python handler code is here (I use amoffat/snake to script in python):
@on_autocmd("TextChanged,TextChangedI", "*") def trim_whitespace_remember_line(context): line_count_old = int(my_get("line_count")) line_count = int(vim.eval("line(\"$\")")) line = int(vim.eval("line(\".\")")) if line_count_old != line_count: log("trim_whitespace_remember_line: line_count %d -> %d" % (line_count_old, line_count)) if line_count > line_count_old: # FIXME: we assume that the cursor is placed on the last inserted line diff = line_count - line_count_old log("trim_whitespace_remember_line: %d lines inserted, current line %d" % (diff, line)) trim_whitespace_lines_inserted(context, line - diff + 1, line) else: # FIXME: we assume that the cursor is placed on the first line after removed block, # i. e. on the first removed line (before reaccounting) diff = line_count_old - line_count log("trim_whitespace_remember_line: %d lines removed, current line %d" % (diff, line)) trim_whitespace_lines_removed(context, line, line + diff - 1) else: log("trim_whitespace_remember_line: line changed, current line %d" % line) lines = my_get("modified_lines") line = str(line) + " " if lines.rfind(" " + line) == -1: lines = lines + line my_let(context, "modified_lines", lines) my_let(context, "line_count", line_count) log("trim_whitespace_remember_line: new lines = '%s'" % my_get("modified_lines"))
This all is needed because I often work on projects with a legacy codebase where no one paid attention to trailing whitespace and/or sanity of code formatting altogether.
Trimming all trailing whitespace produces a diff polluted with unrelated changes all over the file, which makes troubles at code review. Hence, I want to avoid trimming whitespace on unchanged lines, but at the same time ensure that there is no trailing whitespace introduced by me.