Материал из Tkabber Wiki
Содержание
- 1 Общие сведения
- 2 Немного о синтаксисе тикля
- 3 Временное исключение кусков кода конфигурации
- 4 Хуки
- 5 Тестирование конфигурации
Общие сведения
Прежде чем читать эту статью, подумайте, достаточно ли вы хорошо представляете себе, что такое файл config.tcl (в частности, где Ткаббер ищет его при старте); если нет, начните с чтения этой статьи.
Чтобы понять место и роль файла config.tcl в процедуре загрузки Ткаббера, прочитайте ещё одну статью.
А после прочтения данного опуса можно со знанием дела переходить к "книге рецептов".
Файл конфигурации — config.tcl — читается на ранней стадии запуска Ткаббера и поэтому позволяет влиять на большинство аспектов работы этой программы.
Файл конфигурации выполняется интерпретатором тикля, который исполняет код Ткаббера. То есть этот файл является полноценной программой на тикле. Этот аспект следует хорошо прочувствовать, имея в виду беспрецедентный динамизм языка Tcl, позволяющий, среди прочего, переопределять процедуры Ткаббера и "перепаковывать" его окна.
Наиболее важные способы влияния на Ткаббер из его конфига можно условно разделить на три группы:
- Установка предопределённых (документированных) переменных Ткаббера. Например, переменная
debug_lvls
управляет "темами" отладочных сообщений Ткаббера, аifacetk::options(use_tabbar)
— стилем интерфейса (0 — многооконный, 1 — "с табами"). Эти переменные описаны в официальной документации к Ткабберу. - Переопределение процедур Ткаббера. Например, таким образом
можно "деактивировать" IRC-команду чата
/exec
, которую некоторые считают опасной, или переделать реакцию Ткаббера на запросjabber:iq:last
(см. код плагина "Last Activity"). - Изменение привязок событий Tk (нажатий комбинаций клавиш, к примеру) к определённым действиям.
- Просто выполнение некоторого кода, который может, к примеру, менять изначальный "лук и фил" Ткаббера.
- Установка обработчиков определённых хуков (см. ниже). Внутри этих обработчиков можно делать интересные вещи, описанные в предыдущих пунктах.
Вообще же, вещи, которые можно сделать с Ткаббером при помощи файла его конфигурации, ограничены, в основном, лишь фантазией и знаниями ковыряющегося.
Важно осмыслить и запомнить следующее правило:
Ткаббер читает свой файл конфигурации ровно один раз за сеанс своей работы. Механизма "перечитывания" файла конфигурации нет (и не будет). Это означает, что после внесения изменений в файл конфигурации Ткаббер нужно перезапустить (а лучше для начала запустить его вторую копию "рядом" — см. ниже обсуждение тестирования конфигурации).
Ткаббер прекрасно обходится без config.tcl — как он, так и "парный" файл custom.tcl не нужны Ткабберу для запуска и работы. Поэтому, если у Вас нет файла config.tcl в условленном месте, просто создайте его сами.
Немного о синтаксисе тикля
Вообще, если вы собираетесь заняться "продвинутым" конфигурированием Ткаббера всерьёз (а не просто применять готовые рецепты не задумываясь), подумайте о самообразовании. Для начала можно порекомендовать такую последовательность действий:
- Изучить туториал;
- Изучить "додекалогию";
- Почитать классику (переведённую и на язык родных осин).
В качестве "быстрого погружения" для нетерпеливых предложим самые главные правила, про которые нужно помнить, занимаясь правкой конфига на тикле:
Любые пробельные символы являются разделителем слов
Это означает, что символы логически цельных строк (они именуются в тикле "словами"), содержащих пробелы, нужно группировать.
Для группировки используются ограничители {} и ""
Внутри {} не выполняется никакая интерпретация содержимого, внутри "" тикль выполняет подстановку переменных (нотация $имя_переменной
), выполняет команды (нотация [команда аргументы...]
) и раскрывает "escape-последовательности" (нотация \X
, где "X" — спецсимвол).
Путевые имена файлов в Windows могут содержать прямые слэши
То есть имя "C:/Program files/FrobozzMagic 2000" является вполне допустимым.
Строка без пробелов и группирующих символов также интерполируется
То есть используйте прямые слэши под Windows, если данная строка — путевое имя файла.
Следствия этих правил:
- Всегда заключайте имена файлов в "" или {}, если эти имена содержат пробелы.
- Предпочтительно заключайте такие имена в {} чтобы подавить интерпретацию содержимого строки.
- Если вы всё-таки хотите использовать "", указывайте прямые слэши в путевых именах файлов Windows — это убережёт имена от раскрытия "escape-последовательностей", вводимых обратными слэшами.
- Также можно обойтись вообще без группирующих символов, но тогда нужно удваивать все обратные слэши и "искейпить" пробелы обратными слэшами.
Примеры:
# Путь в {} — подавляется любая интерпретация содержимого:
set somepath {C:\Documents and Settings\Vassily Petrovich}
# Путь в "" + прямые слэши = тот же эффект:
set someotherpath "C:/Program files/Новая папка"
# Группирующие символы не нужны — имя не содержит пробелов;
# Однако слэши — прямые, ибо такие строки интерполируются:
set thethirdpath C:/TMP
# Нет группирующих символов ⇒ танцы с "искейпингом":
set falsepath C:\\Program\ Files\\Common\ Files\\Woohoo
Обратный слэш, за которым сразу следует перевод строки, обозначает "продлённую" строку
То есть запись
command arg1 \
arg2 arg3
полностью эквивалентна записи
command arg1 arg2 arg3
Продление строк используется для улучшения читабельности.
Ссылки на элементы массивов не должны содержать пробелов
Имя переменной в такой, к примеру, команде присваивания
set ifacetk::options(use_tabbar) false
# ifacetk::options(use_tabbar) — имя переменной
вовсе не означает, что скобки являются какой-то операцией, как могли бы предположить программисты на ALGOL-подобных языках. Скобки являются частью имени переменной, хоть и обрабатываются особым образом (запись foo(bar)
означает переменную с именем "bar" в массиве с именем "foo"), поэтому нельзя писать так:
set ifacetk::options (use_tabbar) false
или так:
ifacetk::options( use_tabbar ) false
Временное исключение кусков кода конфигурации
Для временного исключения некоторого куска кода длиннее одной строчки удобно использовать стандартную идиому Tcl — условный оператор if с ложным условием, который компенсирует отсутствие в тикле "блочных" комментариев (в стиле "сишного" /* ... */), например:
Нужно отключить некую настройку, которая введена примерно так:
hook::add postload_hook {
do this
now do that
}
Запрещаем выполнение этого кода так:
if 0 {
hook::add postload_hook {
do this
now do that
}
}
При следующем старте Ткаббера всё, что находится внутри блоков if 0 { ... }
, выполнено не будет.
Отдельные строчки удобнее комментировать символом "#", который вводит однострочный комментарий (который, впрочем, может быть продлён на следующую строку при помощи "\", за которым сразу же следует перевод строки).
Имейте в виду весьма необычное поведение комментариев в тикле: в отличие от "классических" языков, в тикле комментарии обрабатываются во время выполнения программы, а не являются чем-то вроде директив препроцессора. Невнимание к этому факту может привести как к ошибкам на стадии чтения конфига, например:
missing close-brace: possible unbalanced brace in comment
так и к ошибкам во время выполнения, например:
invalid command name "}"
Объясним "на пальцах": есть такой код:
proc foo {a b} {
if {some conditional expr} {
...
}
}
и вы хотите изменить условное выражение, закомментировав старое.
Разумный на первый взгляд способ
proc foo {a b} {
# if {some conditional expr} {
if {some other cond expr} {
...
}
}
вызовет ошибку интерпретатора на этапе формирования аргументов для команды proc, так как в комментарии есть несбалансированный символ "{", но этот комментарий игнорируется до фактического выполнения точки кода, в которой он находится, и символ "{" в комментарии "уравновешивается" символом "}", закрывающем тело процедуры, а скобка, открывающая тело процедуры, оказывается без пары.
Правильным решением будет, к примеру, такое решение:
# if {some conditional expr} { } <-- балансирующая скобка
if {some other cond expr} {
...
}
или такое:.
# if {some conditional expr} {
if {some other cond expr} {
...
}
# } <-- балансирующая скобка
или такое:
if {some other cond expr} { # {some conditional expr}
...
}
Хардкорные подробности этих "странностей" описаны тут.
Хуки
Большинство полезных настроек использует механизм "хуков" — обработчиков различных событий Ткаббера; подробнее о них можно прочитать тут. Здесь приведены некоторые неочевидные особенности работы с ними.
На каждый хук можно "навесить" произвольное количество обработчиков.
С другой стороны, код для одних и тех же хуков можно объединять. К примеру, вы хотите использовать два рецепта, которые вешают свой код на один и тот же хук:
hook::add finload_hook {
do_this
do_that
}
...
hook:add finload_hook {
foo -config bar
}
ничего не мешает вам написать в конфиг:
hook::add finload_hook {
do_this
do_that
foo -config bar
}
То есть по сути это вопрос стиля.
Имейте, однако, в виду, что обработчики хуков могут иметь приоритет, и объединять код обработчиков, имеющих разный приоритет, естественно, нельзя.
Код обработчиков хуков выполняется интерпретатором тикля при помощи команды eval. То есть, если мы имеем, к примеру,
hook::add finload_hook {
frobnicate foo
}
то этот код в соответствующий момент будет выполнен примерно так:
eval {
frobnicate foo
}
что в данном случае приведёт к выполнению команды
fronbnicate foo
Ситуация усложняется в том случае, когда коду хука передаются некоторые параметры (аргументы).
Пример такого хука — open_chat_post_hook
: он принимает параметры chatid и type (описание
хука см. в официальной документации). Текущие значения параметров хука "присоединяются" (или
"дописываются через пробел", если так мыслить удобнее) к коду хука, после чего полученная
конструкция вычисляется с помощью eval. В этом случае выполнение, скажем, такой
реализации обработчика данного хука:
hook::add open_chat_post_hook {
frobnicate foo
}
будет произведено так:
eval {
frobnicate foo
} some_chatid some_type
что "развернётся" командой eval в следующий код:
frobnicate foo some_chatid some_type
В подавляющем случае это не то, чего хотел достичь автор хука.
Решение проблемы обработчиков "параметризованных хуков" — реализация их в виде процедуры тикля. Пример:
proc tweak_something {chatid type} {
frobnicate foo
}
hook::add open_chat_post_hook tweak_something
будет выполнено как
eval tweak_something some_chatid some_type
то есть, в результате, как простой вызов процедуры с двумя параметрами. Что и требовалось получить.
Тестирование конфигурации
Несмотря на то, что подавляющее большинство настроек Ткаббера "применяются" сразу, без перезагрузок, некоторые настройки требуют перезапуска Ткаббера. К ним относятся, к примеру, настройки шрифтов (в версиях Ткаббера ниже 0.11.0 либо у приверженцев Tk 8.4), подключение "цветовых схем", изменение стиля интерфейса (многооконный/с табами) и другие. Также перезапуска Ткаббера требует установка/обновление некоторого пакета Tcl, который может использоваться Ткаббером.
Удобнее (и правильнее) всего не перезапускать Ткаббер, а запускать "рядом" его вторую копию.
Достоинства этого способа:
- Не мешает оставаться на связи, так как основной Ткаббер продолжает работать;
- Может потребоваться несколько раундов редактирования и перезапуска Ткаббера чтобы "допилить" настройку, которую вы делаете, до нужной вам кондиции.
Недостатки:
- Ткаббер прожорлив и медленно стартует, поэтому на некоторых очень старых машинах запуск второй копии Ткаббера нежелателен;
- При запуске второй копии Ткаббера, если вы собираетесь соединяться из неё с сервером, требуется соблюдать некоторые меры предосторожности, о которых рассказано ниже.
Как запустить второй Ткаббер, не помешав первому
Большинство требуемых мер предосторожности требуется только если вы собираетесь подключаться к серверу из второй копии Ткаббера.
"Общая" проблема — одна: соревнование при записи настроек. Суть её в том, что все N запущенных "рядом" Ткабберов будут сохранять настройки в один и тот же файл custom.tcl (и некоторые другие). Ткаббер использует весьма прямолинейный, но разумный метод сохранения настроек: при изменении некоторой настройки файл custom.tcl тут же перезаписывается, отражая новое состояние конфигурации. Понятно, что после редактировании настроек параллельно в нескольких копиях Ткаббера, сохранённым останется набор настроек того Ткаббера, в котором он менялся последним по времени.
Имейте в виду, что это относится только к сохранению настроек "для текущей и следующих сессий"; установка настройки "только для текущей сессии" не вызывает перезапись custom.tcl.
Теперь перейдём к мерам предосторожности, которые нужно соблюдать при одновременном соединении с сервером из нескольких копий Ткаббера.
Они чуть отличаются для случев:
- Подключение к тому же серверу с тем же логином;
- Подключение к другому серверу, или к тому же, но с другим логином.
Подключение с тем же логином
- Обязательно в окне логина поставьте ресурс отличный от ресурса основного Ткаббера — это позволит Вам создать разные сессии (сеансы работы) с сервером;
- Там же можете выбрать приоритет, меньший, чем у основной копии. Для чего это может пригодиться, читайте в указанной заметке про приоритеты.
Теперь можете подключиться — будет создано второе подключение с тем же логином (к тому же аккаунту), но одно будет являться другой сессией и не будет "пересекаться" с первой.
Прежде чем продолжить тестирование, усвойте ещё несколько вещей:
- Подключаясь к тем же конференциям, в которых вы сидите из основной копии Ткаббера, выбирайте другой ник — ваш уже занят (вами);
- При таком подключении поведение сообщений, приходящих от гейтов, зависит от приоритетов запущенных копий Ткаббера.
Подключение с другим логином (или к другому серверу)
В этом случае единственное, о чём нужно думать, это регистрация на гейтах в другие системы быстрого обмена сообщениями: к примеру, если как на первом, так и на втором аккаунте вы зарегистрированы на гейте в ICQ, логин на второй аккаунт также подключит вас к гейту, что вызовет отключение от гейта первого аккаунта. Причина этого не в гейте, а в самой "вражеской" системе быстрого обмена сообщениями, которая не позволяет делать одновременные подключения к одному своему аккаунту с разных IP-адресов (которыми будут выступать IP-адреса гейтов).
Если вы столкнулись с этой проблемой, временно отключитесь ("отлогиньтесь") от гейтов в основном Ткаббере.
Тестирование конфигурации "вживую"
Сделать: написать раздел
Пока в качестве примера можно изучить это.