ГоловнаСтаттіТаблиця шматків: Секретний буфер редагування тексту

Таблиця шматків: Секретний буфер редагування тексту

Кожне натискання клавіші, яке ви вводите у текстовий редактор, має якось оновлювати документ, і наївний підхід до зберігання всього документа як одного великого змінних рядка швидко стає непридатним: вставка одного символу посередині файлу з мільйонними символами означатиме зміщення всього після нього, операція O(n) при кожному натисканні клавіші, що робить великі документи повільними. Таблиця шматків є елегантним рішенням цієї проблеми, яка використовується у виробничих редакторах, включаючи ранні версії Microsoft Word та нещодавно як основну структуру даних для буфера тексту VS Code. Замість зберігання документа як одного змінного блоку, таблиця шматків підтримує два лише додавання буфери – початковий буфер, який містить вміст файлу точно таким, яким він був завантажений, і доданий буфер, який збільшується шляхом додавання кожного нового символа, введеного користувачем, і ніколи не змінює жоден з цих буферів на місці. Фактичний документ представляється опосередковано як відсортована послідовність невеликих описників шматків, кожен з яких просто вказує на один із двох буферів разом із початковим зміщенням і довжиною, що описує безперервний фрагмент тексту. Редагування документа стає операцією над цією легкою послідовністю описників, а не над самим текстом: вставка тексту розділяє існуючий шматок на два та вставляє новий шматок, який вказує на свіжододаний вміст доданого буфера, а видалення тексту аналогічно розділяє та обрізає шматки без жодного впливу на підлеглі буфери. Це моделювання дозволяє вам вводити та видаляти текст всередині живої таблиці шматків, спостерігаючи за оновленням початкового буфера, доданого буфера та зв’язаного списку описників шматків у реальному часі.

mysimulator teamОновлено — червень 2026≈ 8 хв читання▶ Відкрити симуляцію

Два буфера, ніколи не змінювані в місці

Оригінальний буфер завантажується один раз під час відкриття файлу та вважається строго лише для читання протягом усього сеансу редагування; ніщо не вставляється в нього або не видаляється з нього. Буфер додавання починається порожнім і росте виключно шляхом додавання, кожен символ, який користувач пише в документі, прикріплюється до кінця цього буфера, незалежно від того, де в логічному документі він має бути. Ця дисципліна лише додавання робить таблицю «пісень» ефективною: оскільки ні один з буферів не змінюється посереднім, немає потреби у дорогому переміщенні пам’яті при обробці редагування, і обидва буфери можуть бути реалізовані як прості, безперервні, зростаючі масиви, які дуже добре підходять для кешу та швидкі для додавання. Фактична візуальна позиція символу в документі повністю визначається тим, де його описовий елемент сидить у послідовності елементів, а не його фізичним зсувом в будь-якому з буферів, що є концептуальним стрибком, який відділяє логічний порядок документа від порядку зберігання фізичного середовища.

Послідовність шма́тків: впорядкований список невеликих описів

Документ представляється як впорядкована послідовність описів шма́тків, зазвичай реалізована як подвоєно зв’язаний список або іноді більш просунута структура, така як збалансоване дерево для дуже великих документів, де кожен шматок є невеликим кортежем, що записує, в який буфер він вказує, початковий з offset у цьому буфері та довжину рядка тексту, який він покриває. Читання всього документа послідовно означає перебіг цієї послідовності від початку до кінця та конкатенацію тексту кожного шматка, на який вона вказує; недавньо відкритий, незаредагований файл починається як один шматок, що охоплює весь оригінальний буфер. Оскільки шматки є невеликими фіксованими розмірами записуватими, а не копіями фактичного тексту, послідовність шма́тків залишається компактною навіть для сильно відредагованого документа, збільшуючись лише пропорційно кількості операцій редагування, виконаних, а не розміру документа або обсягу вставленого тексту, що є важливим розрізненням від підходів, які б потребували дублювати спасинки тексту при кожному зміні.

Вставлення тексту: розділ та з’єднання

Щоб вставити новий текст на певне місце у документі, редактор спочатку додає новонаписані символи на кінець буфера додавання, потім знаходить, який існуючий елемент у послідовності зараз покриває цю точку вставлення. Якщо точка вставлення падає точно на межу елемента, новий елемент, що описує текст, доданий з буфера додавання, може бути просто вставлений у список посилань без додаткової роботи. Якщо точка вставлення падає посередині існуючого елемента, цей елемент має бути розділений на два елементи, один покриває текст до точки вставки та інший – текст після неї, обидва все ще вказуючи на будь-який оригінальний буфер, який посилається на розірваний елемент, і новий елемент для введеного тексту вставляється між ними. У будь-якому випадку ця операція торкається лише невеликої постійної кількості описів елементів: розділення максимум одного існуючого елемента та введення одного нового елемента, незалежно від того, наскільки великий документ.

Якщо точка вставки падає точно на межу елемента, новий елемент, що описує текст, доданий з буфера додавання, може бути просто вставлений у список посилань без додаткової роботи. Якщо точка вставки падає посередині існуючого елемента, цей елемент має бути розділений на два елементи, один покриває текст до точки вставки та інший – текст після неї, обидва все ще вказуючи на будь-який оригінальний буфер, який посилається на розірваний елемент, і новий елемент для введеного тексту вставляється між ними. У будь-якому випадку ця операція торкається лише невеликої постійної кількості описів елементів: розділення максимум одного існуючого елемента та введення одного нового елемента, незалежно від того, наскільки великий документ.

Видалення тексту: розділ та обрізка, жодна інформація не втрачена

Видалення працює за тією ж логікою розділу та з’єднання у зворотньому напрямку. Якщо діапазон видалених елементів охоплює точно один або декілька цілих елементів, то ці елементи просто видаляються з послідовності. Якщо діапазон видалення починається або закінчується посередині елемента, то цей елемент ділиться на межі видалення, і лише частина за межами видаленого діапазону зберігається в послідовності; частина всередині діапазону видалення просто виключається з списку елементів, хоча її основні біти все ще фізично не змінюються в оригінальному або буфері додавання. Це одна з найбільш елегантних властивостей таблиці елементів: оскільки базові буфери ніколи не змінюються і не зменшуються, видалений текст ніколи справді не знищується, він просто більше не посилається на будь-який елемент у поточному списку, що означає, що структура даних природним чином терпимо до дизайну, який хоче тримати старий текст для інших цілей.

Быстрое, дешевое отмену и повтор бесплатно

Поскольку каждое действие редактирования выражается как небольшое локальное изменение в последовательности фрагментов, редактор может реализовать полную отмену и повтор просто путем записи для каждого изменения, какие фрагменты были удалены и какие добавлены, по сути, небольшой дифференциал связанного списка вместо дифференциала или снимка всего текста документа. Отмена вставки означает удаление одного или нескольких фрагментов, которые были добавлены, и восстановление любого из фрагментов или нескольких фрагментов, которые были разделены, все без касания ни одной из буферов, а повтор просто воспроизводит то же небольшое изменение снова. Это значительно дешевле, чем наивные реализации отмены, которые делают снимок всей строки документа при каждом нажатии клавиши, и это основная причина, по которой таблицы фрагментов остаются популярными в современных реализациях редакторов: они дают вам не только быстрое наведение курсора, но и фактически бесплатную историю отмены с эффективным использованием памяти как естественный побочный эффект того, как уже внутренне представлены изменения данных, что является именно тем типом дизайна, где правильное представление основного структурного элемента окупается во всей системе.

Frequently asked questions

Чому не використовувати просто змінний рядок або масив для всього документа?

Вставлення або видалення посередині великого змінного масиву вимагає зміщення кожного символу після точки редагування, що коштує O(n) операцій на кожне натискання клавіші та стає помітно повільним для великих файлів. Таблиці шматків уникають цього, ніколи не переміщуючи існуючий текст, лише коригуючи невеликі описові дані.

Що саме зберігається в описі шматка?

Опис шматка записує, у якому буфері (оригінальному або буфері додавання), від якого стартового зсуву всередині цього буфера та довжину текстового інтервалу, який він охоплює. Він не містить жодного фактичного тексту, лише метадані, що описують діапазон.

Чи видаляє текст насправді байти з пам'яті?

Ні. Видалення лише видаляє або обрізає описи шматків із послідовності, щоб видалений текст більше не був частиною видимого документа; базові байти все ще фізично присутні в буфері оригінального або буфера додавання, просто не посилаються на них.

Як таблиця шматків забезпечує ефективність відмінення та відновлення?

Оскільки кожне редагування є лише невеликою, локалізованою зміною послідовності шматків, наприклад, розділення одного шматка на два або вставлення нового, відміна лише потребує запису та скасування цієї невеликої зміни, а не створення знімка всього документа, що робить історію відмінення надзвичайно дешевою для підтримки.

Які реальні редактори використовують таблиці шматків?

Ранні версії Microsoft Word використовували підхід на основі стилю таблиці шматків, а внутрішня реалізація буфера тексту VS Code, описана в її блозі інженерів, використовує варіант таблиці шматків, побудований на збалансованому дереві для ефективного редагування великих файлів.

Спробуйте наживо

Усе, що вище, працює прямо у вашому браузері — відкрийте Piece Table: The Text Editor's Secret Edit Buffer і змінюйте параметри під час роботи. Нічого не встановлюється, нічого не завантажується на сервер, уся модель живе в одній вкладці.

▶ Відкрити симуляцію Piece Table: The Text Editor's Secret Edit Buffer

Що ви знайшли?

Додати кроки відтворення (опційно)