Undo in D

Basile B. b2.temp at gmx.com
Sat Jun 23 16:44:56 UTC 2018


On Saturday, 23 June 2018 at 14:06:08 UTC, Basile B. wrote:
> On Saturday, 23 June 2018 at 01:58:31 UTC, DigitalDesigns wrote:
>> Is there any idiomatic undo designs in D that give a more 
>> natural implementation than the standard techniques?
>
> - The "stuff to undo" can be a forward range ("save" primitive, 
> + assignable from a stored state)
> - The manager can be an output range of the "stuff to undo"
>
>
> ```
> struct UndoManager(Undoable, Storage)
> if (isForwardRange!Undoable && isOutputRange!(Storage, 
> Undoable))
> {
>     Storage storage;
>     Undoable undoable;
>     size_t position;
>
>     this(Storage storage, Undoable undoable)
>     {}
>
>     void push(){ storage.put(undoable.save()); length++;}
>
>     /* etc */
> }
> ```
>
> So that the UndoMgr is reusable with any Undoable and Storage 
> that implement the right primitives.
>
> But well, you can do that with any PL that have basic generics, 
> e.g C# or FreePascal. The key is to have a nice generic 
> interface. IRL it's probably more complicated than my example. 
> Storage must probably be a RandomAccessRange or have more 
> specific primitives.
>
> Now, **and this is D specific / D idiomatic**, to this can be 
> applied the "design by introspection". UndoManager can allow 
> more or less advanced features, depending on the primitives 
> implemented by Storage and Undoable. Technically this is done 
> at compile-time using __traits(hasMember), typically.

Actually i did one once for an hex editor and i think this 
couldn't be applied. Typically a position, a command and a data 
are the member of a change, not the whole stuff. The generic 
abstraction should be changed to handle such a thing:


struct UndoItem(Position, Command)
{
     Position position; // e.g offset in doc or coordinate, etc
     Command command; // e.g an enum
     ubyte[] data;
}


About the Storage, i think that a linked list is better. No need 
to templatize it then. From this there's no thing possible that's 
very idiomatic in the design.
Somrething like this old shitty stuff : 
https://github.com/BBasile/LLClasses/blob/master/LLClasses.d#L5701 but with a better absssstraction (linked code is more or less the translation of what i did in Delphi years before).

So finally we come back to a simple generic stuff:

struct UndoMgr(Position, Command)
{
     List!(UndoItem!(Position, Command)) items;

     /*
         stupid method there
         - insert
         - undo
         - redo
         - compact
         - clear
     */
}

nothing D specific, you can do that in C# or in FreePascal. 
UndoRedo is a simple thing, too much abstraction could make the 
thing abstruse. But maybe this is what you look for, something 
utterly complex to fill your emptiness.


More information about the Digitalmars-d-learn mailing list