Xterm.js: Поддержка сохранения и восстановления состояния терминала

Созданный на 14 мар. 2017  ·  15Комментарии  ·  Источник: xtermjs/xterm.js

Всем привет,

С созреванием xterm.js я думаю, что отличной функцией для расширения диапазона приложений xterm.js может быть формализация режима без головы. Что я имею в виду? Ну в основном за способность:

  1. Запустите клиент без средства визуализации.
  2. Сообщите клиенту с помощью средства визуализации состояние безголового клиента и наоборот.

Прямо сейчас единственный способ надежно «установить» состояние клиента - это воспроизвести набор всех команд, которые привели к состоянию этого редактора (по крайней мере, через общедоступный API). Однако вы легко можете себе представить, что хотите делать такие вещи, как:

  • листать историю терминала взад и вперед
  • запуск терминала в облаке, к которому вы периодически подключаетесь через клиента
  • (мой вариант использования) наличие у нескольких пользователей буквально одного и того же терминала с возможностью приходить и уходить

Многое из этого в основном уже возможно, если вы просто сериализуете term.rows и различные флаги состояния, но принятие формального API очень поможет. Это также может помочь улучшить тестируемость и надежность основной библиотеки!

Мысли?
Винсент

help wanted typenhancement

Самый полезный комментарий

Есть какие-нибудь обновления по этому поводу? У меня также есть аналогичный вариант использования.

Все 15 Комментарий

@vincentwoo Я вижу, что это очень полезно, вы представляете, как будет выглядеть такой API?

Я думаю, вы, вероятно, захотите другой конструктор, например term.Headless , и новый метод как для безголовых, так и для обычных терминалов, например getState() который затем можно будет передать в reset .

@vincentwoo будет ли

Да, сериализация - это в основном то, что я подразумеваю под "getState", если то, что произведено, может быть использовано клиентом.

Что касается использования обычного xterm без элемента, это может сработать. Я могу попробовать его на узле позже.

Я думаю, что https://github.com/sourcelair/xterm.js/issues/266 означает, что он, по сути, работает без головы до вызова Terminal.open .

Здорово. Есть мысли о том, как может работать состояние экспорта?

Зависит от того, что нужно сохранить, только буфер и курсор?

Я сам не уверен, поэтому это была просьба. Я не знаю, как машина состояний xterm выглядит внутри, и не знаю, что именно вы подразумеваете под «буфером» и «курсором».

Это отличное предложение @vincentwoo , спасибо! Я думаю, что лучшая часть этого - сериализация состояния (которая также является основной частью этого обсуждения).

ИМО, хорошее начало в этом направлении - введение частной собственности (например, с именем state ), где мы будем хранить «данные» терминала, например:

  • геометрия терминала
  • терминальный режим
  • буфер (это текст, выводимый на терминал)
  • позиция курсора
  • стиль курсора

Это свойство должно использоваться внутренне для "установки" состояния терминала каждый раз (и к нему должны обращаться внутренние компоненты терминала, чтобы увидеть, что происходит, когда это необходимо), но оно должно быть доступно только для чтения для внешнего мира (например, term.getState() ).

Как это звучит?

Звучит неплохо! Я не специалист в том, чтобы точно знать каждую переменную состояния, которая однозначно идентифицирует состояние xterm.js , но я счастлив надрать утомление. Я думаю, что попытка составить список и его тестирование - это также отличный способ найти странное поведение в библиотеке.

Еще несколько вещей, которые мы, вероятно, хотим сериализовать:

  • Все варианты
  • Альтернативный буфер

@parisk Я думал, что getState или serialize выполнит сериализацию в этот момент, мы могли бы поместить все в какой-нибудь объект json и довольно легко вернуть json. Все упомянутые вами состояния могут не принадлежать объекту Terminal, например, буфер находится в CircularList . Было бы разумнее указать CircularList сериализовать себя при вызове функции. Что-то вроде этого:

Terminal.prototype.getState() {
  const state = {};
  // this.serializableComponents is an ISerializable[] which ensures they
  // have componentKey/getState()
  this.serializableComponents.forEach(c => {
    state[c.componentKey] = c.getState();
  });
  // TODO: Add anything owned by Terminal to state
  // ...
  return state;
}

// Restore using something like this which would do the reverse
Terminal.prototype.restoreState(state: Object): void;

// A static method that returns a Terminal might be better:
Terminal.restoreTerminal(state: Object): Terminal;

Это интересный подход 👍. Я открываю ветку, чтобы попробовать.

Есть какие-нибудь обновления по этому поводу? У меня также есть аналогичный вариант использования.

Копирование и вставка предложения по устранению этой проблемы из https://github.com/xtermjs/xterm.js/pull/2213#issuecomment -500233758 ниже


Я поговорил об этом с

  • Нам нужно будет предоставить API для сохранения / восстановления состояния, но мы определенно не хотим фиксировать конкретный формат, поэтому это, вероятно, сломает каждые несколько версий.
  • Это добавляет кучу раздувания в ядро, когда так мало пользователей фактически будут его использовать.

Учитывая это, мы считаем, что лучший способ приблизиться к этой функции - использовать надстройку (пример xterm-addon-serialize ), которая сериализует состояние с помощью нового API буфера ( Terminal.buffer.* ). Метод сериализации может выглядеть так:

/**
 * Serializes terminal rows into a string that can be written back to the terminal
 * to restore the state. The cursor will also be positioned to the correct cell.
 * When restoring a terminal it is best to do before `Terminal.open` is called
 * to avoid wasting CPU cycles rendering incomplete frames.
 * <strong i="16">@param</strong> rows The number of rows to serialize, starting from the bottom of the
 * terminal. This defaults to the number of rows in the viewport.
 */
serialize(rows?: number): string;

Если вы не знакомы с терминалами, результирующая строка будет выглядеть примерно так: "\x1b[Hfoo\n\rbar\x1b[2;4H" для простой строки (переместите курсор в строку 1, столбец 1, выведите "foo" , перейдите к следующей строке и выведите "bar" затем поместите курсор в строку 2 и столбец 4).

У этого есть ряд преимуществ:

  • Потребителям, которые его не используют, не нужно загружать код
  • Пользователи, которые его используют, могут динамически загружать код.
  • Он использует общедоступный API, который объявлен как стабильный и сериализуется в стандартный формат, который можно использовать на любом терминале.
  • Он использует всю потрясающую работу @jerch, ускоряя парсер
  • По умолчанию используется только область просмотра, которая будет молниеносно сериализована и восстановлена.
  • Это не усложняет / не раздувает основную архитектуру

Обратите внимание, что он не сможет поддерживать цвет или другие стили, пока мы не предоставим атрибуты в API, но это то, что мы хотим сделать и можем улучшить его позже.

Удален безголовый режим из заголовка, поскольку xterm.js уже поддерживает его, отлично работая без вызова open .

Была ли эта страница полезной?
0 / 5 - 0 рейтинги