-module(etui@undo). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/etui/undo.gleam"). -export([undo_new/2, current/1, can_undo/1, can_redo/1, undo_depth/1, push/2, undo/1, redo/1, reset/2]). -export_type([undo_stack/1]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. -type undo_stack(FCD) :: {undo_stack, list(FCD), FCD, list(FCD), integer()}. -file("src/etui/undo.gleam", 42). ?DOC( " Create a new stack with an initial `present` value.\n" " `max_size` limits how many past entries are retained (0 = unlimited).\n" ). -spec undo_new(FCE, integer()) -> undo_stack(FCE). undo_new(Initial, Max_size) -> {undo_stack, [], Initial, [], Max_size}. -file("src/etui/undo.gleam", 50). ?DOC(" The current value.\n"). -spec current(undo_stack(FCG)) -> FCG. current(Stack) -> erlang:element(3, Stack). -file("src/etui/undo.gleam", 55). ?DOC(" `True` if there is at least one past state to undo to.\n"). -spec can_undo(undo_stack(any())) -> boolean(). can_undo(Stack) -> not gleam@list:is_empty(erlang:element(2, Stack)). -file("src/etui/undo.gleam", 60). ?DOC(" `True` if there is at least one future state to redo to.\n"). -spec can_redo(undo_stack(any())) -> boolean(). can_redo(Stack) -> not gleam@list:is_empty(erlang:element(4, Stack)). -file("src/etui/undo.gleam", 65). ?DOC(" Number of past entries available to undo.\n"). -spec undo_depth(undo_stack(any())) -> integer(). undo_depth(Stack) -> erlang:length(erlang:element(2, Stack)). -file("src/etui/undo.gleam", 74). ?DOC( " Record `new_value` as the new present, moving the old present into past.\n" " Clears the future (redo history) since the branch diverged.\n" ). -spec push(undo_stack(FCO), FCO) -> undo_stack(FCO). push(Stack, New_value) -> Past = [erlang:element(3, Stack) | erlang:element(2, Stack)], Trimmed = case (erlang:element(5, Stack) > 0) andalso (erlang:length(Past) > erlang:element( 5, Stack )) of true -> gleam@list:take(Past, erlang:element(5, Stack)); false -> Past end, {undo_stack, Trimmed, New_value, [], erlang:element(5, Stack)}. -file("src/etui/undo.gleam", 90). ?DOC( " Undo: move present to future, restore the most-recent past as present.\n" " No-op if there is nothing to undo.\n" ). -spec undo(undo_stack(FCR)) -> undo_stack(FCR). undo(Stack) -> case erlang:element(2, Stack) of [] -> Stack; [Prev | Rest] -> {undo_stack, Rest, Prev, [erlang:element(3, Stack) | erlang:element(4, Stack)], erlang:element(5, Stack)} end. -file("src/etui/undo.gleam", 105). ?DOC( " Redo: move present to past, restore the most-recent future as present.\n" " No-op if there is nothing to redo.\n" ). -spec redo(undo_stack(FCU)) -> undo_stack(FCU). redo(Stack) -> case erlang:element(4, Stack) of [] -> Stack; [Next | Rest] -> {undo_stack, [erlang:element(3, Stack) | erlang:element(2, Stack)], Next, Rest, erlang:element(5, Stack)} end. -file("src/etui/undo.gleam", 119). ?DOC(" Reset to initial state, clearing all history.\n"). -spec reset(undo_stack(FCX), FCX) -> undo_stack(FCX). reset(Stack, Initial) -> {undo_stack, [], Initial, [], erlang:element(5, Stack)}.