• Главная
  • О нас
  • Статьи
  • Вакансии
  • Контакты

Использование ncurses в PHP

24 Июль 2013 by Juds in PHP tags: cli, ncurses, PHP, консольные скрипты

Как программист и веб-разработчик, вы наверное время от времени пишете программы на php для администрирования сайта из консоли. Средствами языка можно сделать только выводящую/читающую из консоли программу, но с помощью библиотеки ncurses можно создать консольную утилиту с довольно сложным внешним видом, которая будет одинаково выглядеть в разных видах терминалов.

PHP очень гибок и расширяем, с его помощью можно создавать скрипты, которыми можно заменить аналогичные на других языках (Perl/bash-скрипты и прочее). Функциональность ncurses поразительна и действительно выводит возможности работы с терминальным php-приложением на новый уровень.

Предназначение статьи — дать вам «толчок» в сфере написания консольных утилит на php, которые будут использовать возможность этой библиотеки. Я собираюсь показать только самое важное, относящееся к самой библиотеке, и надеюсь дать вам базу для использования ncurses в вашем приложении.

Для кого предназначена статья

Материал предназначен для опытных php-программистов, заинтересованных в создании консольных php-приложений с пользовательским интерфейсом. (прим. переводчика: материал пригодится разработчику любого уровня, здесь нет ничего сложного).

Изучаемые темы

Из данной статьи вы узнаете:

  • Как создавать окна, используя ncurses, и заполнять их данными
  • Как создавать несколько окон и динамически изменять их размеры до размеров терминала
  • Как «ловить» нажатия клавиш
  • Как написать небольшую программу, расширяющую функциональность traceroute, используя все изученные возможности библиотеки ncurses

Определения

  • Ncurses (new curses) — библиотека, свободное ПО, имитирующая curses (System V Release 4.0), и даже больше. Она использует формат Terminfo, поддерживает знакоместа, цвета, множественную подсветку, использование функциональных клавиш и все другие возможности SYSV curses. Если вы использовали linux, то вы скорее всего видели его в действии: midnight commander,
    ncftp, Iptraf, trafshow и многие другие используют ncurser для создания интерфейса.
  • Окно означает лишь секцию терминала, созданную с помощью ncurses.

От автора

Документация по функциями ncurses в php сильно ограничена. Некоторые функции использованные в данной статье отсутствуют на официальном сайте. Приложения с ncurses следуют стилю программирования на C, как если бы они были настоящими программами, а не скриптами.

Если у вас есть опыт программирования в C или C++, возможно вы уже знакомы с ncurses и можете представить, каким полезным инструментом может быть ncurses при использовании с интерпретируемым языком, таким как PHP.

Что нужно знать

Вам нужен PHP, скомпилированный с опцией -with-ncurses на unix-подобной системе. Не все терминалы поддерживают цветной вывод, поэтому я не стал включать использование цветов в статью.

Знайте, что вам может понадобиться «сбрасывать» ваш терминал командной reset. Если возникнет какая-либо ошибка иncurses_end() не будет вызван, то ваш терминал будет работать неправильно.

Порядок выполнения нижеприведённых функций тоже важен. PHP может показать ошибку, если вы попытаетесь обновить окно, которое не имеет соответствующего обработчика.

Начнём с простого приложения прежде чем переходить к сложному.

Простой пример с окнами

Сначала создадим основное окно, которое будет использовать всё доступное пространство. Потом добавим меньшее окно посередине экрана и поместим туда строчку текста. Чтобы получилось вот так:
c5ab4d0ea15c81965f7961f7968c84f1

Начать нужно с вызова ncurses_init();, чтобы перейти в режим ncurses. Без этого при вызове функций библиотеки PHP будет падать с ошибкой.

Сценарий для вывода двух окон и строки

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
// начинаем с инициализации библиотеки
$ncurse = ncurses_init();
// используем весь экран
$fullscreen = ncurses_newwin ( 0, 0, 0, 0);
// рисуем рамку вокруг окна
ncurses_border(0,0, 0,0, 0,0, 0,0);
// создаём второе окно
$small = ncurses_newwin(10, 30, 7, 25);
// рамка для него
ncurses_wborder($small,0,0, 0,0, 0,0, 0,0);
 
ncurses_refresh(); // рисуем окна
 
// пишем в маленьком окне
ncurses_mvwaddstr($small, 5, 5, "   Test  String   ");
 
// обновляем маленькое окно для вывода строки
ncurses_wrefresh($small);
 
$pressed = ncurses_getch(); // ждём нажатия клавиши
 
ncurses_end(); // выходим из режима ncurses, чистим экран
 

Попробуйте изменить размеры окна и запустить скрипт ещё раз. Основное окно опять будет занимать ровно всё пространство.

Теперь вы может захотите увидеть какое-нибудь действо при нажатий на клавишу, или вы хотите сделать возможность выхода из приложения при нажатии на какую-либо кнопку. Я предпочитаю использовать для этого esc (27 ascii-код).
Чтобы добавить возможность выхода по нажатию на ESC, добавьте данный код вместо $pressed = ncurses_getch();

1
2
3
4
5
6
7
8
9
while (true) {
    $pressed = ncurses_getch(); // ждём нажатия клавиши
    if ($pressed == 27) {
        break;
    } else {
    ncurses_mvwaddstr($small, 5, 5, $pressed);
    ncurses_wrefresh($small);
    }
}

Теперь если вы нажмёте esc, программа завершится, в ином случае ascii-код нажатой клавиши будет отображён в маленьком окне.

Можно добавить заголовок, поместив код перед вызовом ncurses_refresh();:

1
2
3
ncurses_attron(NCURSES_A_REVERSE);
ncurses_mvaddstr(0,1,"My first ncurses application");
ncurses_attroff(NCURSES_A_REVERSE);

Вы не ограничены режимом REVERSE (цвет и фон меняются местами), также есть DIM, UNDERLINE и другие.

Можно повысить комфорт, добавив интерактивный выбор из меню.

Создаём меню

Многие программы имеют меню и возможность выбора из него. В прошлом на «чистом» PHP мы могли лишь выводить список вариантов, и давать возможность ввести номер нужного. Такой неудобный выбор одного варианта можно заменить более интуитивно понятным.
fe8c36eb647c7a6bafe2120f6e8fcfb7

Сценарий вывода меню с возможностью выбора

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<?php
define('ESCAPE_KEY', 27);
$ncurse = ncurses_init();
$fullscreen = ncurses_newwin ( 0, 0, 0, 0);
ncurses_border(0,0, 0,0, 0,0, 0,0);
$small = ncurses_newwin(10, 30, 7, 25);
ncurses_wborder($small,0,0, 0,0, 0,0, 0,0);
ncurses_attron(NCURSES_A_REVERSE);
ncurses_mvaddstr(0,1,"My first ncurses application");
ncurses_attroff(NCURSES_A_REVERSE);
ncurses_refresh();
 
$currently_selected = 0;
$menu = array('one', 'two', 'three', 'four');
 
while (true) {
    for($i=0; $i<count($menu); $i++){
        $out = $menu[$i];
        if($currently_selected == intval($i)){
            ncurses_wattron($small,NCURSES_A_REVERSE);
            ncurses_mvwaddstr($small, 1+$i, 1, $out);
            ncurses_wattroff($small,NCURSES_A_REVERSE);
        } else {
            ncurses_mvwaddstr($small, 1+$i, 1, $out);
        }
    }
 
    ncurses_wrefresh($small);
 
    $pressed = ncurses_getch();
 
    if ($pressed == NCURSES_KEY_UP) {
        $currently_selected--;
        if ($currently_selected < 0)
            $currently_selected = 0;
    } elseif ($pressed == NCURSES_KEY_DOWN) {
        $currently_selected++;
        if ($currently_selected >= count($menu))
            $currently_selected = count($menu)-1;
    } elseif($pressed == ESCAPE_KEY) {
        break;
    } else {
    ncurses_mvwaddstr($small, 5, 5, $pressed);
    }
}
 
ncurses_end();
 

По получившемуся меню можно перемещаться кнопками со стрелками и выходить с помощью esc.

Сейчас вы возможно думаете о консольных приложениях, которые вы можете создать, зная только несколько выше использованных функций. Далее по тексту мы создадим полезное приложение, которое будет стартовой точкой дальнейшей разработки.

Всё вместе

На сайте php.net перечислены 119 функций библиотеки ncurses. В нижеприведённой таблице есть список использованных функций и ссылки на документацию. Замечу, что четыре из перечисленных функций отсутствуют в официальной документации. (прим. переводчика: в настоящий момент все функции содержаться в документации на php.net, правда без подробного описания).

Функция Описание Документация
ncurses_init Инициализирует ncurses www.php.net/manual/en/function.ncurses-init.php
ncurses_newwin Создаёт новое окно www.php.net/manual/en/function.ncurses-newwin.php
ncurses_getmaxyx(resource window, int
return Y, int return X);
Записывает в переменные X и Y максимальных размеров терминала –
ncurses_border Рисует рамку вокруг основного окна www.php.net/manual/en/function.ncurses-border.php
ncurses_refresh Обновляет основное окно. Для перерисовки второстепенных окон используйте ncurses_wrefresh www.php.net/manual/en/function.ncurses-refresh.php
ncurses_attron Применяет атрибут к выводимому тексту www.php.net/manual/en/function.ncurses-attron.php
ncurses_attroff Отключает применение атрибута www.php.net/manual/en/function.ncurses-attroff.php
ncurses_mvaddstr Выводит строку www.php.net/manual/en/function.ncurses-mvaddstr.php
ncurses_wborder (resource window, int
left, int right, int top, int bottom, int tl_corner, int tr_corner, int
bl_corner, int br_corner);
Рисует рамку для второстепенного окна. –
ncurses_wattron(resource window, int
attribute)
Идентично ncurses_attron, только применяется для окна window –
ncurses_mvwaddstr Помещает строку во второстепенное окно www.php.net/manual/en/function.ncurses-mvwaddstr.php
ncurses_wattroff (resource window, int
attribute)
Идентично ncurses_wattroff, только применяется для окна window –
ncurses_wrefresh Перерисовывает второстепенное окно. www.php.net/manual/en/function.ncurses-wrefresh.php
ncurses_getch Ждёт ввода с клавиатуры или мыши. www.php.net/manual/en/function.ncurses-getch.php

Улучшенный traceroute

Сейчас создадим действительно полезную программу: traceroute с выводом whois-информации о каждом прыжке.

c1ba3a4a25d6c5049c1f6179ac0658be

Этот скрипт запускает traceroute до zend.com (макс 10 прыжков) и показывает результаты в одном окне. По элементам можно переходить с помощью стрелок. При нажатии на enter информация о данном ip будет показана в нижнем окне. По нажатию на esc произойдёт завершение работы программы.

Содержимое скрипта

В заключение

Выше изложенный код довольно прост и может послужить базой для вашего приложения с использованием ncurses.

Мы не рассматривали использование мыши, цветов и многих других функций вывода.

Возможно вы создадите набор функций для использования этой библиотеки вывода. В качестве старта предлагаю вам две функции, которые упростят создание окон. Вы можете добавить в них создание панелей, рисование заголовков или что-нибудь ещё.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/** Creates an ncurses window that is write-safe on the left-hand side of the screen
    * @param integer $size is how wide it will be
    * @return window handle of inner window.
    */
function left_window($size=15){
    global $fullscreen;
    ncurses_getmaxyx($fullscreen, $MAX_Y, $MAX_X);
    $c = ncurses_newwin ($MAX_Y-2 ,$size, 1, 1);
    ncurses_wborder($c,0,0, 0,0, 0,0, 0,0); // border it
    // now create window overtop the other just
    // slightly smaller so that we won't write over
    // the border.
    $d = ncurses_newwin ($MAX_Y-4 ,$size-2, 1+1, 2);
    ncurses_wrefresh($c); // show it
    ncurses_wrefresh($d);
    return $d;
}
 
#
# creates an upper-right window
#
function upperr_window($size=15){
    global $fullscreen;
    ncurses_getmaxyx($fullscreen, $MAX_Y, $MAX_X);
    $c = ncurses_newwin ($size ,$size, 1, $MAX_X-($size+1));
    ncurses_wborder($c,0,0, 0,0, 0,0, 0,0); // border it
    ncurses_wrefresh($c); // show it
    return $c;
}

Удачного программирования!

Полезные ссылки

  • www.opengroup.org/onlinepubs/007908799/xcurses/curses.h.html — это документация по заголовочному файлу ncurses, которая будет отличным справочником по функциям библиотеки.
  • dickey.his.com/ncurses/ncurses-intro.html — полезный материал по использованию ncurses в языке C. Много чего из него можно использовать с PHP.
  • И всегда используйте man ncurses. К тому же каждая функция имеет свою страницу справки (напр. man wborder
От переводчика

Установка расширения ncurses

  1. Установить pecl. Пакет php5-dev в ubuntu, php-pear в arch
  2. Установить само расширение: pecl install ncurses (права рут, поэтому с sudo)
  3. Подключить расширение. Добавить строчку «extension=ncurses.so» в свой php.ini

Источник: habrahabr.ru

Unity теперь работает с Windows Phone 8, Windows 8 и Blackberry 10
Google представляет Android 4.3

Leave a Comment! Отменить ответ

You must be logged in to post a comment.
Уроки
  • Cinema 4D
  • Unity3D
  • PHP
  • Delphi
  • JavaScript
  • Python
  • HTML5
  • Go
Статьи
  • Новости
  • Game Development
  • PHP
  • QA
  • IT Юмор
  • Разное
Теги
Android Composer Delphi excerption experience Game Design game development gameplay Git Go! AOP google Google Analytics HHVM it experience it юмор Laravel Linux manager Phalcon PHP Python QA RFC Selenium Silex Slim Symfony 2 unity3d warcraft Yii Yii 2 Zend Framework 2 Zephir Биографии Новости Обучение веб-разработка высоконагруженные проекты дайджест дизайн исследование подборка ссылки стартап тенденции
О Нас

Juds–компания по разработке программного обеспечения, разработке веб-проектов и мобильных приложений. Все предлагаемые нами решения индивидуальны и направлены на максимально точное удовлетворение потребностей наших партнеров. Мы находимся в постоянном поиске новых ярких решений. Главные критерии – актуальность применения и инновационность.

Статьи
  • Лучшее из мира PHP за 2013
  • Полезные функции Google Analytics
  • Что в SEO можно считать нормальным и работающим, а что – отжившим
  • 30 полезных для себя вещей
  • Дайджест интересных новостей и материалов из мира PHP (20 октября — 10 ноября 2013)
  • Cinema 4D: создаем плагин – объект
IT Юмор
Метки
Android Composer experience Game Design game development google HHVM it experience it юмор Laravel manager PHP unity3d Yii Zend Framework 2 Zephir Новости Обучение веб-разработка дайджест исследование подборка ссылки стартап тенденции
© 2014 Juds. Все права защищены.