LXF87-88:Мастер на все руки

Материал из Linuxformat.

Перейти к: навигация, поиск
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.

Рис. 1

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 и посмотрите, что получится. Наконец, мы «упаковываем» все виджеты, соответствующие кнопкам, в одну рамку. Готово! Теперь можете добавить другие кнопки и назначить им определенные действия по своему усмотрению.

Изображение:LXF88 tcl2.pnf

Результат нашей работы: красочное меню запуска программ!

Заключение

Итак, создание небольших графических приложений в 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.

Ссылки

Личные инструменты
  • Купить электронную версию
  • Подписаться на бумажную версию