LXF87-88:Мастер на все руки
|
|
|
- Tcl Нестандартное программирование
Содержание |
Tcl Нестандартное программирование
- Хотите взлететь повыше, чем C и Perl? Майк Сондерс открывает новую серию публикаций о менее известных, но не менее интересных языках программирования...
Вы строчили на C, баловались с Basic и программировали на Perl. А может, формулировали задачи на Фортране, применяли Python и даже атаковали Ada. Но ваш аппетит к кодированию не утолен… К счастью, в мире программирования всегда есть пища для пытливого ума. Изучение новых языков – прекрасный способ расширить профессиональные знания. Да и резюме, включающее не только приевшийся С, произведет большее впечатление на работодателя.
Мы начинаем серию статей, посвященных не совсем обычным языкам программирования. Они далеки от основного русла [mainstream], но тоже служат важным целям, а изучать их – одно удовольствие. Мы предполагаем, что вы уже владеете базовыми понятиями, поэтому не будем тратить время, объясняя, что такое переменная или цикл. Опустим также некоторые чисто технические подробности: их можно найти в документации.
В данной серии мы выясним, откуда взялись эти языки и что делает их интересными сегодня, и рассмотрим ряд практических примеров, которые позволят вам продолжить освоение языка самостоятельно. Правда, на четырех страницах особо развесистое приложение не проанализируешь, но трамплин для прыжка к написанию собственных программ мы вам подставим. И если у вас получится что-то действительно стоящее, мы сможем опубликовать это на нашем DVD!
Тиклни меня
Наша серия начнется с рассказа о Tcl (часто произносится как английский глагол tickle – «щекотать»). Этот интерпретируемый язык придуман в 1988 г. на родине BSD Unix и других пионерских разработок в компьютерных технологиях – в Калифорнийском университете Беркли. Его основоположник, Джон Остерхаут [John Ousterhout], создал собственный «командный язык инструментов» – Tool Control Language, насмотревшись на недопеченные встраиваемые языки от других разработчиков. Его основными целями были возможность простого и эффективного встраивания в более крупные приложения и ускорение процесса прототипирования – создания тестовых приложений, служащих для оценки какой-либо идеи.
Сейчас эти задачи успешно решаются и другими языками (например, Python), и невольно возникает вопрос: а зачем изучать Tcl – что в нем особенного? Во-первых, он облегчает разработку программ с графическим интерфейсом. Для работы с PyGtk (реализация Python на GTK) необходимо изучить структуру и особенности C-ориентированного инструментария, а Tcl использует Tk, несложный, но гибкий набор элементов GUI, существенно упрощающий организацию пользовательского интерфейса. Мы рассмотрим Tk более подробно чуть ниже.
Многие козыри языка Tcl уже стянули Perl, Python и PHP, но Tcl по-прежнему используется широко: именно его применяли при разработке программного обеспечения модуля оператора буровой вышки компании Shell и космического телескопа Хаббла. Это очень серьезная работа, так что в зрелости и стабильности Tcl сомневаться не приходится. Благодаря простоте освоения и интеграции в другие приложения язык принят на вооружение фирмами Oracle и IBM. В списке приложений с открытым исходным кодом, приведенном на сайте http://freshmeat.net/, более 300 Tcl-проектов; среди них программа для мониторинга серверных процессов Moodss, программа для записи дисков TkDVD и помощник кодировщика TkDiff.
Tcl/Tk в действии: Moodss анализирует Apache.
Интерпретатор языка Tcl входит в состав большинства дистрибутивов и обычно устанавливается по умолчанию. Если вашем дистрибутиве его почему-либо нет, возьмите Tcl на нашем DVD в разделе
Разработка. Tcl – интерпретируемый язык, и вы обойдетесь без текстового редактора и командной строки, обвешанной ключами-флагами: все будет ясно с первого взгляда. Для запуска интерпретатора
Tcl введите tclsh в командной строке. В строке приглашения появится
подсказка Tcl – лаконичное %; основы языка можно исследовать прямо с ходу. С чего начать? Конечно, с программы, выводящей на экранn строку «Hello, World!»
puts “Hello, world!”;
Здесь puts – команда put string, которая выводит заданную строку в стандартный поток вывода stdout. Можно записывать несколько операторов в одной строке, разделяя их точкой с запятой, или размещать каждый оператор на новой строке – это дело вкуса.
После вывода попробуем ввод:
gets stdin foostring;
Это запрос на ввод строки; результат сохраняется в переменной foostring. Обратите внимание на важную особенность языка: переменные не нужно объявлять до их использования. Чтобы вывести результат, воспользуемся уже известной нам командой puts:
puts stdout $foostring;
Ввод значений числовых величин также не представляет особых сложностей. Рассмотрим пример:
gets stdin x; gets stdin y; expr $x*$y;
Первые две строки попросят вас ввести числа; так и сделайте. Введенные числа сохранятся в виде строк в переменных x и y, затем команда expr вычислит заданное ей выражение произведения x*y и отобразит результат. Просто и мило! Переменные Tcl – не статически типизированные, и их можно определить в любое время. Значения присваиваются переменным командой set:
set x 7; echo $x; gets stdin y; set x $y; echo $x;
Переменной x присваивается значение 7, x выводится на экран, затем вводится значение y, копируется в x', и x выводится снова.
Перейдем к операторам условия. Наберите коды следующих примеров в текстовом редакторе, сохраните в файлах, а затем запускайте интерпретатор командой tclsh <имя_файла>'. Рассмотрим оператор условия if/else:
gets stdin x; if {$x>10} { puts “Bigger than ten”; } else { puts “Less than ten”; }
Правда, похоже на С? Оператор цикла while работает в той же манере:
gets stdin x; while {$x<=10} { puts “Enter a number bigger than 10”; gets stdin x; # User inputs number }
Пока вы не введете число, большее 10, оператор будет требовать ввода снова и снова. В строке с gets символ # означает начало комментария, а строка перед ним в Tcl должна заканчиваться точкой с запятой. В коде на Tcl вы нередко встретите «вложенные команды» (‘nested commands’), заключенные в квадратные скобки. Их результат может присваиваться другим переменным, например:
set mystring “Hello, world!”; set x [string length $mystring]; puts $x;
С помощью вложенной команды string length в переменную x записывается длина строки mystring.
Процедуры
Итак, мы освоили ввод/вывод, переменные, операторы условия, цикла и комментарии. Теперь поговорим о процедурах. Для объявления процедуры используется команда proc, после чего процедура становится просто командой Tcl. Процедура должна быть объявлена до ее использования – иначе ждите сообщения об ошибке. Пример простой процедуры, перемножающей два числа, приведен ниже:
proc multiply {x y} { set z [expr $x*$y]; return $z; } puts [multiply 3 4];
В первой строке скрипта объявляется процедура multiply и приводится список ее аргументов (x и y), заключенный в фигурные скобки.
Ниже в фигурных скобках определяется тело процедуры, а ее результат передается в основную программу оператором return. Tclsh первым делом выполнит последнюю строку скрипта (она находится вне процедуры), а вложенная команда вызывает процедуру, с тем, чтобы возвращаемое ею значение вывелось на экран командой puts. Запустив код, вы увидите 12.
В данном примере оператор return $z; можно опустить: Tcl возвращает значение последнего оператора процедуры как результат. Но лучше указывать оператор return явно: читать ваш код будет значительно легче, особенно тем, кто привык программировать на C.
Приведенный пример также демонстрирует область действия переменной. Аргументы и переменные, определенные в теле процедуры, являются локальными, и их нельзя использовать за пределами процедуры. Например, если вы попробуете вывести значение переменной z в основной программе (puts $z;), то получите сообщение об ошибке «переменная не определена» (‘no such variable’). Чтобы переменная была доступна в любом месте программы, ее необходимо объявить глобальной с помощью команды global:
global z;
Et voila! Теперь к переменной z можно обращаться и вне процедуры.
Разработка программ с GUI
Итак, основы Tcl изучены, и теперь вы сами можете попробовать что-нибудь написать. Список полезных сайтов, где можно найти дополнительные материалы, приведен далее.
А сейчас мы займемся понастоящему увлекательным делом – разработкой программ с графическим интерфейсом. Как упоминалось выше, к Tcl подвязан Tk – готовый набор виджетов (так называют элементы пользовательского интерфейса: кнопки, переключатели и т.д.), поэтому подобные программы занимают всего несколько строк кода. Если вы уже писали программы с использованием Qt или GTK, то оцените невероятную скорость разработки в Tcl/Tk: больше не нужно трудиться над кодом инициализации и долгими часами старательно изучать API.
Если консольные программы на языке Tcl используют интерпретатор tclsh, то приложения с графическим интерфейсом Tcl/Tk используют wish (‘windowing shell’). Этот интерпретатор выдает простейшую форму, на которой можно размещать виджеты вашего будущего приложения. Сейчас вы увидите, как все просто! Запустив wish, введите следующие команды:
button .mywidget -text “Clicktastic!”; pack .mywidget;
Готово! На форме появилась кнопка с надписью Clicktastic!. Ее даже можно нажать, но ничего не произойдет, потому что действие кнопки мы еще не определили. Команда button в первой строке создает кнопку с именем .mywidget (имена виджетов должны начинаться с точки). Используя это имя, мы сможем ссылаться на данный объект в дальнейшем. Опция -text задает надпись на кнопке.
Итак, создан объект .mywidget. Для отображения виджета в окне wish мы должны «упаковать» его в это окно (командой pack). «Упаковка» (packing) – это система размещения и упорядочивания виджетов в окне программы или родительском виджете (сейчас у нас только одна кнопка, и окно пристроилось под нее автоматически). Виджеты можно изменять «на лету» – введите в окне терминала такой код, в добавление к предыдущим двум строкам:
.mywidget configure -foreground green;
Текст Clicktastic! позеленел!
Небольшое отступление: по сравнению c GTK или Qt внешний вид виджетов Tk может показаться не совсем привычным. Дело в том, что Tk использует только базовые библиотеки X, а значит, не обеспечивает особых эффектов прорисовки (в частности, сглаживания); зато он быстр и нетребователен к памяти.
Пора заставить нашу кнопку что-то делать при нажатии. Снова запустите wish и введите в окне терминала следующие команды:
button .mywidget -text “Don’t click me” -command { puts “I said no!” }; pack .mywidget
Опция -command команды button описывает действия, выполняемые при нажатии кнопки, в фигурных скобках: в данном случае это оператор puts, и он выводит указанную строку в стандартный поток вывода. Теперь, как только мы нажмем на кнопку, этот текст появится в окне терминала!
Диспетчер запуска приложений
Вы уже неплохо вооружены средствами для разработки графического интерфейса. В завершение темы, создадим небольшую, но полезную программу – диспетчер запуска приложений. На сайтах Freshmeat и SourceForge пасутся табуны проектов этого рода. Они особенно популярны для оконных менеджеров типа FluxBox, не имеющих своих кнопок быстрого запуска.
Применим полученные знания и напишем простенькое приложение для запуска ваших любимых программ (например, Firefox или Thunderbird) и управления системными сервисами (например, SSHD или Apache). Вот как будет выглядеть наш код:
#!/usr/bin/env wish set sshcommand “/etc/init.d/ssh”; global sshcommand; proc sshstart {} { global sshcommand; exec $sshcommand start &; } proc sshstop {} { global sshcommand; exec $sshcommand stop &; } proc launchbrowser {} { exec firefox &; } proc launcheditor {} { exec emacs &; } frame .app -borderwidth 10; .app configure -background lightblue; pack .app; button .app.ssh-go -text “Start SSHD” -command sshstart; button .app.ssh-end -text “Stop SSHD” -command sshstop; button .app.browser -text “Web browser” -command launchbrowser; button .app.launcheditor -text “Text editor” -command launcheditor; .app.ssh-go configure -foreground green; .app.ssh-end configure -foreground red; pack .app.ssh-go .app.ssh-end .app.browser .app.launcheditor;
Наш менеджер предусматривает четыре кнопки: две для запуска и останова сервера SSH и еще две – для запуска Firefox и Emacs. Первая строка (вы могли встречать такую в скриптах Bash) указывает интерпретатор для обработки скрипта – wish, и благодаря ей уже не нужно набирать wish имя_файла, чтобы скрипт заработал. Сохраним скрипт в файл, например, /usr/bin/megatest и сделаем файл исполняемым (chmod +x /usr/bin/megatest). Теперь мы можем запускать его командной строкой (megatest) или создать соответствующий ярлык на рабочем столе.
Следующие две строки определяют глобальную переменную sshcommand: это строка, содержащая команду запуска сервера SSH, она сэкономит вам набор команды. Кроме того, если SSH в вашей системе расположен в другом каталоге, достаточно будет отредактировать это определение, и не выискивать обращения к SSH по всей программе – совсем как с #define в С.
Далее идут четыре процедуры. Две последние уместились в одну строчку; тем больше места останется для статьи, а кстати и код становится компактнее. Процедуры sshstart и sshstop предназначены для запуска и останова сервера SSH и используют нашу глобальную переменную sshcommand: она служит параметром команде exec, которая, таким образом, обращается к серверу SSH, прибавив вторым параметром start либо stop. Учтите, что ваша программа потребует привилегий суперпользователя (root): только ему дозволено распоряжаться SSH!
Процедуры launchbrowser и launcheditor запускают соответственно Firefox и Emacs; они запустят все что угодно в пределах вашего $PATH, так что можете заменить и браузер, и редактор на свои любимые. Первый оператор головной программы создает виджет-рамку по имени .app, он будет служить контейнером для остальных виджетов. Рамки, как и кнопки, можно располагать в окне wish; .app позволит нам задать контур вдоль границы окна. Ширина контура назначается с помощью опции -borderwidth (здесь – 10 пикселей). Затем мы «упаковываем» созданную рамку в главное окно программы.
Далее с помощью знакомой команды button мы создаем объекты, соответствующие кнопкам быстрого запуска. Что интересно, для размещения кнопок внутри рамки мы должны использовать префикс .app в именах кнопок – тогда каждая из них будет «упакована» в родительский виджет (рамку). Очень мощный аппарат для создания сложных GUI!
Попробуйте изменить имя объекта .app.launcheditor на .launcheditor (не забудьте также изменить последнюю команду pack!). Запустите скрипт, и увидите, что кнопка запуска редактора Emacs оказалась вне рамки. Таким образом, составные имена объектов определяют их взаимосвязь.
С помощью команд configure задается цвет надписи на кнопках управления сервисом SSH – попробуйте изменить foreground на background и посмотрите, что получится. Наконец, мы «упаковываем» все виджеты, соответствующие кнопкам, в одну рамку. Готово! Теперь можете добавить другие кнопки и назначить им определенные действия по своему усмотрению.
Результат нашей работы: красочное меню запуска программ!
Заключение
Итак, создание небольших графических приложений в Tcl/Tk – до изумления простая задача. Вот почему этот язык и его инструменты используются при создании ПО для объектов и систем, требующих надежной и безотказной работы и высокого быстродействия: ведь, к примеру, программе для управления телескопом нужен не элегантно сглаженный текст, а минимальный, четкий и легко модифицируемый код интерфейса. Добавьте к этому огромную библиотеку расширений, и получите язык без лишнего жира, зато с мускулами, способными справиться с решением множества задач.
Что дальше? Во врезке «Ссылки» приведены адреса сайтов с документацией и примерами скриптов – вы увидите, что можно приделать интерфейсы Tcl/Tk к инструментам командной строки. Кроме того, Tk поставляется с очень полезными примерами, обычно они находятся в каталоге /usr/share/doc/Tk8.4/examples/' (цифры означают номер версии; подставьте вместо них вашу). Исходный код программ Moodss, TkDVD и TkDiff имеется на нашем DVD, из него можно почерпнуть немало идей для ваших проектов. Удачи вам! LXF
Расширения
Хотя в языке Tcl хватает команд для решения большинства задач, можно обогатить его функции с помощью расширений. Расширения Tcl аналогичны библиотекам для языка C или дополнительным модулям для Python. Самое известное расширение – это, конечно, Tk, но доступны и многие другие, обеспечивающие доступ к базам данных, обработку изображений и т.д.
Расширения Tcl обычно пишутся на C или C++, и для владеющих этими языками особых затруднений тут не будет. Хорошее руководство по созданию расширений для Tcl есть на http://www.equi4.com/pub/etc/extuse.html.
Ссылки
- Официальный сайт: http://www.tcl.tk
- Документация: http://wiki.tcl.tk
- Проекты: http://www.tcllinks.org
- Модули расширений: http://www.flightlab.com/~joe/gutter