TIP 449: [text] undo/redo to Return Range of Characters

Login
Author:         François Vogel <[email protected]>
State:          Final
Type:           Project
Vote:           Done
Created:        07-Jun-2016
Post-History:   
Keywords:       Tk
Tcl-Version:    8.7
Tk-Branch:      tip-449

Abstract

Tk features an undo/redo mechanism for the text widget. This TIP proposes that the edit undo and edit redo commands of the text widget return the ranges of characters impacted by the undo or redo operation.

Rationale

In some applications using the text widget, say a text editor, modern practice is to show the text with highlighting, colorization, or any other ways of improving readablity for the human user. When undoing/redoing changes in the text, these applications need to know which characters were impacted by the undo or redo operation. This can be done by comparing the text widget contents before the change with its contents after the change, but this is very far from optimal especially with large texts.

Therefore a better way to get this information is proposed in the present TIP.

This feature was requested for the text widget in RFE 1217222 https://core.tcl-lang.org/tk/tktview/1217222

Proposed Change

Currently, edit undo and edit redo commands return the empty string.

It is proposed to change this return value and make these commands return the ranges of indices that were impacted by the undo or redo operation.

This return value is a list of indices, with an even number of elements. Indeed, there can be several edits (insertions and deletions) between two separators in the undo stack and all such edits have to report which range of text they changed.

The returned ranges are made of indices making sense at undo/redo return time, i.e. they refer to the text widget content at the time edit undo and edit redo return. Moreover, the returned list of indices is optimal, in the sense that the ranges contained in that list are all disjoint (overlapping ranges are merged, and ranges already contained in another range are not returned).

Backwards Compatibility

The proposed implementation makes use of temporary marks, that only exist during an undo or redo operation (and never before or after these operations). This could be seen as a concern regarding backwards compatibility, however it is believed that the names of these marks has been chosen such that this should not be an issue. The chosen name is tk::undoMark, where is either L or R, and is an integer identifier. The risk of name collision is therefore deemed very low due to prefixing by tk::. This naming convention follows what is already existing in the text widget (internal anchors).

Example

  package require Tk

  pack [text .t -undo true]
  .t insert end "Hello World.\n"
  .t edit separator
  .t insert end "Again hello.\n"

  .t edit undo  ; # will now return {2.0 3.0}
  .t edit redo  ; # will now return {2.0 3.0}

More examples can be found by studying the new tests in the feature branch tip-449 hosting the development.

Reference Implementation

A reference implementation is available in branch tip-449 of the Tk fossil repository.

This new capability is implemented entirely in the code of the text widget. The undo/redo generic code (in generic/tkUndo.c) is untouched.

Copyright

This document has been placed in the public domain.