Графические демо сценарии на языке shell
Широкое распространение в Inferno получила концепция динамически загружаемых модулей. Одним из примеров ее применения является оболочка sh, которую та действительно гальванизировала, предоставив std (эквивалент "стандартной библиотеки" для командной строки), regex (распознавание регулярных выражений), expr (простая целочисленная арифметика), file2chan (создание файла в пространстве имен с детерминированными свойствами), tk (доступ к графической подсистеме Inferno Tk, а также взаимодействие каналов, на котором собственно основан механизм событий Tk в ОС) и прочие модули. Поскольку основные навыки работы с командной строкой и, скажем, тем же Tk получить не составляет больших усилий, мы попробуем разобраться более или менее детально с конкретной работой этого… существа.
#!/dis/sh load tk wid:= ${tk window 'Тест окно'}
Что мы видим: стандартный заголовок для сценария sh, загрузку модуля tk, и создание нового Tk-окна с заголовком "Тест окно". Последняя операция возвращает идентификатор на окно (переменная $wid), который также является каналом (через него можно получать сообщения от окна). Определив элементарную функцию-исполнитель:
fn x { tk $wid $* }
можно приступать к выполнению команд Tk. Например, создать кнопку в новом окне можно следующим образом:
x button.b -text {Надпись на кнопке} x pack.b x update
Поскольку Inferno Tk отправляет события через каналы Limbo, модуль Tk обеспечивает доступ к простым строковым каналам. Канал создается с помощью команды chan:
chan cmd
Команда tk namechan предназначена для создания канала, известного Tk:
tk namechan $wid cmd
send отправляет строку в канал; принятое значение присваивается встроенной переменной ${recv}. Теперь можно получать события от Tk:
x.b configure -command {send cmd Текст в консоли} while {} { echo ${recv cmd} }
В результате создается фоновый процесс, выводящий в консоли сообщение "Текст в консоли" каждый раз, когда нажимается кнопка с надписью "Надпись на кнопке". Взаимодействие с оконным менеджером осуществляется на схожий манер. Когда инициализируется окно, то оно автоматически ассоциируется с каналом под номером равным значению идентификатора окна. Поступающие при этом строки являются событиями оконного менеджера, наподобие изменения размеров (resize) и перемещения (move). При желании она могут интерпретироваться "по иному", или же отправляться назад оконному менеджеру для обработки по умолчанию посредством tk winctl. Полезной идиомой является ниже указанная конструкция, которая выполняет всю обычную обработку событий окна:
while {} { tk winctl $wid ${recv $wid} } &
И последнее замечание, операция закрытия окна вызывает останов всех процессов текущей группы, поэтому чтобы не закрывалось окно оболочки, из которой был запущен графический сценарий, следует разветвлять (fork) группу процессов с помощью раннего выполнения команды pctl newpgrp.