Skip to content

Fix selection shrink when indenting

BUG: 329247

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 :

Screenshot_2023-10-27_20-20-13.png

After one indent :

Screenshot_2023-10-27_20-20-38.png

After two indents :

Screenshot_2023-10-27_20-30-03.png

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() :

  1. computes the current indentation (current leading spaces)
  2. computes the required indentation to add to obtain the given offset
  3. removes the current leading spaces
  4. 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

These manual tests have been done on a version based on Kt5/Qt5, I've rebased on master and I'm currently installing and building for Qt6 for testing again.

@teams/qa @teams/vdg

Merge request reports