Как динамически переключать цвета терминала для всех открытых терминалов?

Вопрос или проблема

Я использую gnome-terminal на Ubuntu / Fedora. Для цветовых схем я использую base16-shell, а также соответствующие настройки для моего редактора vi.

Я настроил свой .bashrc для установки темы base16 при запуске. Иногда я переключаюсь между темами, изменяя этот файл bashrc. Это работает для периодических изменений моей цветовой схемы, так как я могу просто изменить .bashrc время от времени, и все будущие окна откроются с правильной цветовой схемой.

Чего я хочу?

Я хочу иметь возможность менять цветовую схему во всех открытых окнах gnome-terminal одним кликом или командой. Есть ли способ сделать это?

О моем рабочем процессе

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

Я не хочу вводить команду для переключения цветовых схем в каждом открытом окне терминала. Кроме того, в некоторых окнах может быть запущена программа, выводящая данные на экран, которую я не хочу прерывать. Можно ли “сигнализировать” терминалу о переключении на пользовательскую цветовую схему?

Я понимаю, что это может быть сложно сделать в терминалах, где активно работает программа на переднем плане. Но, по крайней мере, могу ли я сделать это для всех других терминалов, где программы находятся в фоновом режиме или команды не выполняются?

Я готов рассмотреть другие терминалы, если это поможет. Я думал о использовании профилей gnome-terminal, но не могу понять, как именно достичь того, что я хочу.

Заранее спасибо!

Настройки GNOME Terminal, как и большинства приложений GNOME, хранятся в базе данных dconf. Вы можете использовать команды dconf или более высокоуровневую альтернативу gsettings, чтобы запрашивать или изменять настройки.

GNOME Terminal поддерживает несколько профилей. Вы не можете переключить профиль во всех существующих окнах, однако, вы можете в любое время переопределять свойства профиля.

Терминал автоматически отслеживает изменения в подлежащей базе данных незамедлительно.

Дамп базы данных, например, с помощью dconf dump / > outputfile, измените некоторые значения в диалоге “Предпочтения” GNOME Terminal, затем повторите предыдущую команду и сравните два вывода, чтобы определить различия.

Вы можете программно изменять значения с помощью таких команд, как:

dconf write /org/gnome/terminal/legacy/profiles:/:b1dcc9dd-5262-4d8d-a863-c897e6d979b9/background-color "'rgb(200,210,220)'"

и аналогично для полей foreground-color, palette.

Более стандартное обозначение #rrggbb также работает.

Обратите внимание на вложенные кавычки, оболочка удаляет внешние, тогда как фактическое значение, которое вы устанавливаете, также должно содержать кавычки.

Если вы используете непрофиль по умолчанию, то идентификатор профиля будет у вас другим.


Другой возможный подход:

Последовательности экранирования OSC 4, 10, 11 позволяют переопределять цвета во время выполнения. Они имеют преимущество перед настройками терминала, по крайней мере, в случае GNOME Terminal.

Пройдитесь через все записи в /dev/pts, и отправьте эти последовательности экранирования на все из них. Например:

printf '\e]11;#abcdef\e\\' > /dev/pts/17

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

Обратите внимание, что существует вероятность, что текущая активность в терминале находится в середине многобайтовой последовательности UTF-8 или последовательности экранирования, и вы вставите что-то между ними. В этом случае вы увидите испорченный вывод из программы, работающей внутри.

Я рекомендую этот метод для тех, чьи терминалы поддерживают эти последовательности OSC, но не позволяют изменить настройки во время выполнения другими, более безопасными способами.

В итоге я использовал следующий обходной путь.

  1. Обновите PROMPT_COMMAND в моем ~/.bashrc.

     # каждый раз, когда отображается новая командная строка, обновлять тему терминала на основе последней выбранной темы
     PROMPT_COMMAND="$HOME/bin/reset_term_background.sh"
    
  2. Это содержимое reset_term_background.sh.

#!/bin/bash

set -e

TERM_BACKGROUND="$HOME/.term_background"

if [ -f $TERM_BACKGROUND ]; then
    BACKGROUND_CONTENTS=$(cat $TERM_BACKGROUND)
    COMMAND="$HOME/.config/base16-shell/scripts/$BACKGROUND_CONTENTS.sh"
    source $COMMAND

cat << EOF > "$HOME/.vimrc_background"
if !exists('g:colors_name') || g:colors_name != '$BACKGROUND_CONTENTS'
  colorscheme $BACKGROUND_CONTENTS
endif
EOF

fi

В кратце, я использую base16-shell для управления цветовыми схемами на моем терминале. Затем я храню текущую цветовую схему в специальном файле ~/.term_background. В каждом открытом терминале, в следующий раз, когда я запускаю любую команду (или просто нажимаю Enter), PROMPT_COMMAND будет выполнена. Это запускает мой кастомный сценарий bash, который читает содержимое ~/.term_background и использует соответствующий сценарий base16-shell.

Я думаю, что мог бы оптимизировать это немного больше, сохраняя текущий TERM_BACKGROUND в какой-то общей переменной окружения, чтобы мне не приходилось повторно запускать команду source каждый раз. Но на данный момент это было достаточно.

Один недостаток заключается в том, что если у меня есть какие-то открытые процессы vim, это не обновит цветовые схемы на них. Я думаю, что это можно исправить. Но для меня этого было достаточно.

Ответ или решение

Для решения задачи по динамическому переключению цветовых схем во всех открытых терминалах GNOME Terminal на системах Ubuntu или Fedora, вы можете воспользоваться различными методами, учитывая использование base16-shell и особенности вашей рабочей среды. Рассмотрим теоретические аспекты, примеры и практическое применение возможных решений.

Теория

GNOME Terminal хранит настройки в базе данных dconf, что позволяет программно изменять их с помощью команд dconf или gsettings. Это дает возможность изменить свойства профиля терминала в режиме реального времени.

В GNOME Terminal поддерживаются несколько профилей, и вы можете переопределять свойства этих профилей в любой момент. Управление цветами в терминале также возможно с помощью управляющих последовательностей OSC (Operating System Command), таких как OSC 4, 10, 11.

Пример

  1. Изменение настроек через dconf или gsettings:

    • Вы можете использовать команду dconf или gsettings для изменения настроек цветовой схемы, которые терминал подхватит автоматически.
      dconf write /org/gnome/terminal/legacy/profiles:/:<profile-uuid>/background-color "'#rrggbb'"

      Здесь необходимо подставить корректный UUID профиля терминала.

  2. Управляющие последовательности OSC:

    • Они позволяют изменить цвета в терминале на лету, отправляя escape-последовательности непосредственно в терминал.
      printf '\e]11;#ffffff\e\\' > /dev/pts/<n>

      Команда изменит цвет фона указанного терминала.

Применение

Теперь давайте рассмотрим практические шаги для реализации переключения цветовых схем для всех открытых терминалов:

  1. Автоматизация через PROMPT_COMMAND:

    • Включите вызов скрипта, обновляющего цветовую схему, в PROMPT_COMMAND, что обеспечит выполнение при каждом вызове командной строки.
      PROMPT_COMMAND="$HOME/bin/reset_term_background.sh"

      Этот подход позволяет обновлять терминал при каждом возврате к командной строке.

  2. Содержание скрипта reset_term_background.sh:

    • Скрипт считывает файл с текущей цветовой схемой и применяет соответствующую настройку из base16-shell.
      
      #!/bin/bash
      set -e
      TERM_BACKGROUND="$HOME/.term_background"

    if [ -f $TERM_BACKGROUND ]; then
    BACKGROUND_CONTENTS=$(cat $TERM_BACKGROUND)
    COMMAND="$HOME/.config/base16-shell/scripts/$BACKGROUND_CONTENTS.sh"
    source $COMMAND

    cat << EOF > "$HOME/.vimrc_background"
    if !exists(‘g:colors_name’) || g:colors_name != ‘$BACKGROUND_CONTENTS’
    colorscheme $BACKGROUND_CONTENTS
    endif
    EOF

    fi

    
    Скрипт обновляет конфигурацию как терминала, так и редактора Vim, что упрощает управление цветовой темой.
  3. Замечания по использованию:

    • Данный метод не обновляет цветовую схему в интерфейсах, где активно работают программы в переднем плане, например, в случаях с открытым Vim. Это ограничение можно обойти добавлением функционала, который отправляет управляющие сигналы на обновление цвета, если это критично для вашего рабочего процесса.
  4. Настройка и улучшение:

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

Таким образом, данное решение обеспечивает гибкость и автоматизацию при переключении цветовых схем, используя возможности GNOME Terminal и base16-shell. Настройка PROMPT_COMMAND позволяет минимизировать необходимость ручного вмешательства при работе с терминалом, что особенно полезно в динамичных рабочих условиях.

Оцените материал
Добавить комментарий

Капча загружается...