{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "383195d7",
   "metadata": {},
   "source": [
    "# 18-25 · Повтор действий (Redo)\n",
    "\n",
    "Практика к разделу [«Повтор действий (Redo)»](../../site/chapters/glava-18/18-25-povtor-deystviy.html)."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ff4fe33d",
   "metadata": {},
   "source": [
    "## Цель\n",
    "\n",
    "Redo восстанавливает отменённое действие; новое действие обязано очистить redo_stack."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "247d9e29",
   "metadata": {},
   "source": [
    "## Рабочий пример"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "adcaca9a",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-03T00:52:12.417855Z",
     "iopub.status.busy": "2026-09-03T00:52:12.417532Z",
     "iopub.status.idle": "2026-09-03T00:52:12.440190Z",
     "shell.execute_reply": "2026-09-03T00:52:12.439046Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['A'] [['B']]\n"
     ]
    }
   ],
   "source": [
    "document, undo_stack, redo_stack = [], [], []\n",
    "\n",
    "\n",
    "def commit_action(shapes):\n",
    "    document.extend(shapes)\n",
    "    undo_stack.append(shapes)\n",
    "    redo_stack.clear()  # новое действие делает старую ветку redo недействительной\n",
    "\n",
    "\n",
    "def undo():\n",
    "    if not undo_stack:\n",
    "        return\n",
    "    shapes = undo_stack.pop()\n",
    "    del document[len(document) - len(shapes):]\n",
    "    redo_stack.append(shapes)\n",
    "\n",
    "\n",
    "def redo():\n",
    "    if not redo_stack:\n",
    "        return\n",
    "    shapes = redo_stack.pop()\n",
    "    document.extend(shapes)\n",
    "    undo_stack.append(shapes)\n",
    "\n",
    "\n",
    "commit_action([\"A\"])\n",
    "commit_action([\"B\"])\n",
    "undo()\n",
    "print(document, redo_stack)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "af72151c",
   "metadata": {},
   "source": [
    "## Задание ★ Базовая практика"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "5de03bce",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-03T00:52:12.441825Z",
     "iopub.status.busy": "2026-09-03T00:52:12.441620Z",
     "iopub.status.idle": "2026-09-03T00:52:12.447907Z",
     "shell.execute_reply": "2026-09-03T00:52:12.446852Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Redo работает, а новое действие очищает устаревшую историю redo.\n"
     ]
    }
   ],
   "source": [
    "assert document == [\"A\"]\n",
    "assert redo_stack == [[\"B\"]]\n",
    "redo()\n",
    "assert document == [\"A\", \"B\"]\n",
    "undo()\n",
    "commit_action([\"C\"])  # новое действие ПОСЛЕ undo — должно очистить redo_stack\n",
    "assert document == [\"A\", \"C\"]\n",
    "assert redo_stack == [], \"новое действие обязано очистить старую ветку redo\"\n",
    "print(\"Redo работает, а новое действие очищает устаревшую историю redo.\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Cartesian Python 3.14",
   "language": "python",
   "name": "cartesian-python314"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.14.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
