Problem
I am trying to implement "trimming trailing whitespace in changed lines only". For this purpose, I intercept TextChanged
and 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.
Question
How to determine the exact line range which has been inserted/removed with current TextChanged event?
Code
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"))
Clarification
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.