1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556(* Claude Code
*
* Copyright (C) 2026 Yoann Padioleau
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public License
* (LGPL) as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*)(* See Undo.mli *)(* a version, and the name of the edit that made it *)(*****************************************************************************)(* Types *)(*****************************************************************************)type'astep={value:'a;name:stringoption}type'at={now:'astep;past:'asteplist;future:'asteplist;limit:int}(*****************************************************************************)(* Functions *)(*****************************************************************************)letstart?(limit=100)value={now={value;name=None};past=[];future=[];limit}letnowt=t.now.value(* the oldest versions are forgotten: an editor's memory has to stop
* somewhere, and it stops at the end furthest from the person *)letreckeepn=function[]->[]|x::rest->ifn<=0then[]elsex::keep(n-1)restletrecord?namevaluet={twithnow={value;name};past=keept.limit(t.now::t.past);future=[]}letamendvaluet={twithnow={t.nowwithvalue}}letundot=matcht.pastwith|[]->t|step::past->{twithnow=step;past;future=t.now::t.future}letredot=matcht.futurewith|[]->t|step::future->{twithnow=step;future;past=t.now::t.past}letcan_undot=t.past<>[]letcan_redot=t.future<>[](* undo takes back the edit that made the state we are in, so its name
* is the one to show *)letundo_namet=ifcan_undotthent.now.nameelseNoneletredo_namet=matcht.futurewith[]->None|step::_->step.nameletundost=List.lengtht.pastletredost=List.lengtht.future