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