Tcl — небольшой встраиваемый язык, а Tk — библиотека для построения графических интерфейсов. Вместе они дают сочетание: скрипт на несколько десятков строк превращается в окно с полями, списками и кнопками, при этом тот же код можно запустить в консоли. Tcl используют в системной автоматизации, тестовых стендах, САПР и сетевом оборудовании, где важны компактность и стабильность. Ниже — маршрут от установки до приложения с файлами и обработкой ошибок.
Как устроен язык
В Tcl почти всё является командой. Строка состоит из слов, разделённых пробелами: первое слово — имя команды, остальные — аргументы. Фигурные скобки запрещают подстановку, квадратные выполняют вложенную команду, а знак доллара подставляет переменную. Списки и словари — обычные значения, поэтому не нужны отдельные типы для конфигурации.
set name "мир"
puts "Привет, $name"
set items [list alpha beta gamma]
puts [lindex $items 1]
foreach x $items { puts "элемент: $x" }
Процедуры объявляются командой proc. Область видимости локальная; чтобы изменить внешнюю переменную, используют global или upvar. Ошибки перехватывают через catch, а подробности остаются в errorInfo.
Сильная сторона Tcl — trace: он вызывает процедуру при чтении или записи переменной, что удобно для черновиков и автосохранения. В Tk переменная, связанная с полем через -textvariable, обновляется, а trace помогает реагировать на изменение.
trace add variable task write {apply {{args} {puts "поле изменено"}}}
set task "новая задача"
Установка и проверка
В Debian и Ubuntu пакеты называются tcl и tk, полезные библиотеки — tcllib и tklib. В Fedora используется dnf, в Arch — pacman.
sudo apt install tcl tk tcllib tklib
echo 'puts $tcl_patchLevel' | tclsh
echo 'package require Tk; puts $tk_version' | wish
apt-cache policy tcl tk
Команда tclsh запускает консоль без графики, wish — интерпретатор с уже загруженным Tk. Если wish не стартует в удалённой сессии, проверьте переменную DISPLAY: для X11 нужен доступ к серверу, а в Wayland Tk обычно работает через XWayland.
Первое окно
Ниже — минимальное приложение со списком задач. Поля и кнопка взяты из ttk, а список — классический listbox: отдельного темизированного списка в Tk нет. Геометрией управляет grid, а вес строк и столбцов заставляет список растягиваться вместе с окном.
#!/usr/bin/env wish
package require Tk
wm title . "Список задач"
ttk::frame .top -padding 8
ttk::entry .top.entry -textvariable task
ttk::button .top.add -text "Добавить" -command addTask
listbox .list -height 12
grid .top -row 0 -column 0 -sticky ew
grid .top.entry -in .top -row 0 -column 0 -sticky ew
grid .top.add -in .top -row 0 -column 1
grid columnconfigure .top 0 -weight 1
grid .list -row 1 -column 0 -sticky nsew
grid rowconfigure . 1 -weight 1
grid columnconfigure . 0 -weight 1
proc addTask {} {
global task
set value [string trim $task]
if {$value eq ""} { return }
.list insert end $value
set task ""
}
bind .top.entry <Return> addTask
Сохраните файл, выдайте права на выполнение и запустите. Обратите внимание: global task нужен потому, что переменная создана на верхнем уровне, а процедура работает в своей области видимости.
chmod +x tasks.tcl
./tasks.tcl
События и данные
Привязки bind связывают виджет, событие и скрипт. Событие <<ListboxSelect>> возникает при выборе строки, а after позволяет отложить действие без блокировки интерфейса. Словари удобны для настроек: dict set добавляет ключ, dict get читает значение.
bind .list <<ListboxSelect>> {
set i [.list curselection]
if {$i ne ""} {
.top.entry delete 0 end
.top.entry insert 0 [.list get $i]
}
}
after 1000 { puts "прошла секунда" }
set cfg [dict create host localhost port 5432]
dict set cfg user admin
puts [dict get $cfg port]
Для длительных операций не блокируйте цикл: разбейте работу на шаги через after или запустите процесс и читайте его вывод через канал.
Файлы и внешние команды
Файл открывается командой open, а кодировку лучше задать явно. Способ выполнить внешнюю программу — exec; он возвращает стандартный вывод и выбрасывает ошибку при ненулевом коде возврата.
set path [file join $env(HOME) tasks.txt]
set f [open $path w]
chan configure $f -encoding utf-8
puts $f [join [.list get 0 end] "\n"]
close $f
set out [exec uname -s]
puts "система: $out"
Чтение делается аналогично: open $path r, затем read $f и close $f. Не забывайте закрывать каналы в обработчике ошибок, иначе файл останется заблокированным.
Рисование на Canvas
Canvas подходит для схем, графиков и простых игр. Координаты задаются в пикселях, элементы можно двигать и удалять по идентификатору. Ниже — ломаная линия и подпись.
canvas .c -width 400 -height 200 -background white
pack .c -fill both -expand 1
.c create line 20 180 120 80 220 140 320 40 -fill "#2b6cb0" -width 3
.c create text 200 20 -text "Нагрузка" -font {Sans 12 bold}
Для интерактивности привяжите <Button-1> к Canvas и преобразуйте координаты события через canvasx и canvasy.
Запуск и диагностика
На Linux достаточно shebang и права на выполнение. На Windows файл запускают через wish.exe или по ассоциации с интерпретатором. Проверьте, что на целевой машине есть Tcl/Tk нужной ветки: код для Tcl 9 не заработает на старой 8.6. В Tcl 9 UTF-8 стала кодировкой по умолчанию, но явное указание кодировки в файловых операциях всё равно избавляет от сюрпризов при обмене со старыми системами.
tclsh check.tcl
wish app.tcl
if {[catch {open /root/secret r} err]} { puts "ошибка: $err" }
puts $errorInfo
- Окно не появляется — проверьте
DISPLAYи наличие XWayland. - Кириллица превращается в мусор — задайте
-encoding utf-8при открытии файла. - Процедура не видит переменную — используйте
globalилиupvar. - Интерфейс завис — ищите синхронный
execили долгий цикл.
Итог
Tcl/Tk остаётся практичным инструментом для небольших утилит и быстрых прототипов: язык компактный, Tk не требует тяжёлого окружения, а готовый скрипт легко переносится между Linux, macOS и Windows. Начните с tclsh для логики, добавьте wish для окна и не забывайте про области видимости и кодировки — это две самые частые причины ошибок.