Fix selection shrink when indenting
Bug
This bug appears when the following conditions are met :
- the text selection ends in the leading white-spaces of the last line
- several indent actions are triggered (with Tab key or Ctrl+I shortcut)
It can be observed that :
- the first indent works correctly but modifies the selection
- the following indents work incorrectly because the selection has been modified
Original document :
After one indent :
After two indents :
Internal root cause
Text bloc indentation is managed by KTextEditor::DocumentPrivate::indent()
method
... which calls KateAutoIndent::changeIndent()
... which splits the given range into lines
... and calls KateAutoIndent::doIndent()
for each line of the given range
Depending on the given asked offset, KateAutoIndent::doIndent()
:
- computes the current indentation (current leading spaces)
- computes the required indentation to add to obtain the given offset
- removes the current leading spaces
- adds the required leading spaces to obtain the given offset
The problem is that text removal in step 3 indirectly triggers TextRange::checkValidity()
method which can silently shrink the text selection if the removed text is at the beginning or at the end of the range.
Fix
The fix consists of switching step 3 and step 4 so that the selection is never shrink.
A (failing) autotest has been added to reproduce the bug, which passes after the bug fix.
This fix solves any type of indentation (space, tab).
This fix seems harmless but I hope there isn't indirect magic somewhere in the codebase relying on the selection shrink.
In addition to the autotest, I have manually tested several cases in kate :
- different indentation modes : "Normal", "C++"
- different indentation config : Tab, Space
- different text bloc size (1 to several lines)
- different start and end selection
- indent and unindent