📜 ⬆️ ⬇️

Using ncurses in PHP

As a programmer and web developer, you probably from time to time write programs in php to administer the site from the console. The language can only make a program outputting / reading from the console, but using the ncurses library you can create a console utility with a rather complex appearance that will look the same in different types of terminals.

PHP is very flexible and extensible, with it you can create scripts that can be replaced with similar ones in other languages ​​(Perl / bash scripts, etc.). The ncurses functionality is amazing and really takes the ability to work with a terminal php application to a new level.

The purpose of the article is to give you a "push" in the field of writing console tools for php, which will use the opportunity of this library. I’m going to show only the most important thing related to the library itself, and I hope to give you a base for using ncurses in your application.
')
Who is the article for?

The material is intended for experienced php-programmers interested in creating console php-applications with a user interface. (comment of the translator: material is useful to the developer of any level, here there is nothing difficult).

Topics studied


From this article you will learn:

Definitions



From the author


The documentation for ncurses functions in php is very limited. Some features used in this article are not available on the official website. Applications with ncurses follow C programming style as if they were real programs, not scripts.

If you have programming experience in C or C ++, you may already be familiar with ncurses and can imagine what a useful tool ncurses can be when used with an interpreted language such as PHP.

What you need to know


You need PHP compiled with the -with-ncurses option on a unix-like system. Not all terminals support color output, so I did not include the use of colors in the article.

Know that you may need to “reset” your terminal command reset . If any error occurs and ncurses_end() not called, your terminal will not work properly.

The order of the following functions is also important. PHP may show an error if you try to update a window that does not have a corresponding handler.

Let's start with a simple application before moving on to a complex one.

Simple example with windows


First, create a main window that will use all the available space. Then add a smaller window in the middle of the screen and place a line of text there. To make it like this:
image

You need to start by calling ncurses_init(); to switch to ncurses mode. Without this, when calling the functions of the PHP library will fall with an error.

Script to display two windows and lines
 <?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,   


Try resizing the window and run the script again. The main window will again occupy exactly the entire space.

Now you may want to see some action when pressing the key, or you want to make it possible to exit the application by pressing any button. I prefer to use for this esc (27 ascii-code).
To add the ability to exit by pressing ESC , add this code instead of $pressed = ncurses_getch();
 while (true) { $pressed = ncurses_getch(); //    if ($pressed == 27) { break; } else { ncurses_mvwaddstr($small, 5, 5, $pressed); ncurses_wrefresh($small); } } 

Now if you press esc, the program will end, otherwise the ascii-code of the pressed key will be displayed in a small window.

You can add a header by placing the code before calling ncurses_refresh(); :
 ncurses_attron(NCURSES_A_REVERSE); ncurses_mvaddstr(0,1,"My first ncurses application"); ncurses_attroff(NCURSES_A_REVERSE); 

You are not limited to REVERSE mode (color and background are interchanged), there is also DIM, UNDERLINE and others.

You can increase comfort by adding an interactive menu selection.

Create a menu


Many programs have menus and the ability to choose from it. In the past, on pure PHP we could only display a list of options, and give the opportunity to enter the number of the desired one. Such an awkward choice of one option can be replaced by a more intuitive one.
image

Menu output script with a choice
 <?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(); 

On the resulting menu, you can navigate with the arrow keys and exit with esc.

Now you are probably thinking of console applications that you can create, knowing only a few of the functions used above. Further on, we will create a useful application that will be the starting point for further development.

Together


The php.net website lists 119 functions of the ncurses library. The table below contains a list of the functions used and links to the documentation. I note that four of these functions are missing in the official documentation. (comment of the translator: at the moment all functions are contained in the documentation on php.net, but without a detailed description).
FunctionDescriptionDocumentation
ncurses_initInitializes ncurseswww.php.net/manual/en/function.ncurses-init.php
ncurses_newwinCreates a new windowwww.php.net/manual/en/function.ncurses-newwin.php
ncurses_getmaxyx (resource window, int
return Y, int return X);
Writes to variables X and Y the maximum size of the terminal-
ncurses_borderDraws a frame around the main windowwww.php.net/manual/en/function.ncurses-border.php
ncurses_refreshUpdates the main window. To redraw secondary windows use ncurses_wrefreshwww.php.net/manual/en/function.ncurses-refresh.php
ncurses_attronApplies an attribute to the displayed text.www.php.net/manual/en/function.ncurses-attron.php
ncurses_attroffDisable attribute usewww.php.net/manual/en/function.ncurses-attroff.php
ncurses_mvaddstrDisplays the stringwww.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);
Draws a frame for the background window.-
ncurses_wattron (resource window, int
attribute)
Same as ncurses_attron , only applies to window-
ncurses_mvwaddstrPlaces the string in the secondary windowwww.php.net/manual/en/function.ncurses-mvwaddstr.php
ncurses_wattroff (resource window, int
attribute)
Identical to ncurses_wattroff , only used for window-
ncurses_wrefreshRedraws the background window.www.php.net/manual/en/function.ncurses-wrefresh.php
ncurses_getchWaiting for input from the keyboard or mouse.www.php.net/manual/en/function.ncurses-getch.php


Improved traceroute


Now we will create a really useful program: traceroute with the output of whois information about each jump.
image

This script runs traceroute to zend.com (max 10 hops) and shows the results in a single window. You can navigate through the elements using the arrows. When you click on enter, information about this ip will be shown in the bottom window. By pressing esc, the program will end.

Script content
 <?php //    define("ESCAPE_KEY", 27); define("ENTER_KEY", 13); //   $tr_return = traceroute("www.zend.com"); array_shift($tr_return); $ncurses_session = ncurses_init(); $main = ncurses_newwin(0, 0, 0, 0); //   ncurses_getmaxyx($main, $lines, $columns); ncurses_border(0, 0, 0, 0, 0, 0, 0, 0); //    ncurses_attron(NCURSES_A_REVERSE); ncurses_mvaddstr(0,1, "Traceroute example"); ncurses_attroff(NCURSES_A_REVERSE); //  ,      ... $lower_frame_window = ncurses_newwin ($lines-14, $columns-3, 13, 1); ncurses_wborder($lower_frame_window, 0,0, 0,0, 0,0, 0,0); //  $lower_main_window = ncurses_newwin ($lines - 16, $columns-5, 15, 2); $main_list_window = ncurses_newwin (12, $columns-3, 1, 1); ncurses_wborder($main_list_window, 0,0, 0,0, 0,0, 0,0); //  ncurses_refresh(); $currently_selected = 0; while(true) { for($a=0; $a < count($tr_return); $a++){ $out = $tr_return[$a]; if($currently_selected == intval($a)) { ncurses_wattron($main_list_window,NCURSES_A_REVERSE); ncurses_mvwaddstr ($main_list_window, 1+$a, 1, $out); ncurses_wattroff($main_list_window,NCURSES_A_REVERSE); } else { ncurses_mvwaddstr ($main_list_window, 1+$a, 1, $out); } } ncurses_move(-1,1); //      ncurses_wrefresh($lower_frame_window); ncurses_wrefresh($lower_main_window); //   ncurses_wrefresh($main_list_window); //    $y = ncurses_getch($lower_main_window); if ($y == ENTER_KEY) { $newout = explode(" ", trim($tr_return[$currently_selected])); $rwhois_return = rwhois($newout[2]); foreach ($rwhois_return as $n => $l) { ncurses_mvwaddstr($lower_main_window, $n - 1, 1, $l); } } elseif($y == ESCAPE_KEY) { ncurses_end(); exit; } elseif ($y == NCURSES_KEY_UP) { $currently_selected--; if ($currently_selected < 0) $currently_selected = 0; } elseif($y == NCURSES_KEY_DOWN) { $currently_selected++; if ($currently_selected >= count($tr_return)) $currently_selected = count($tr_return)-1; } } //       function traceroute($address) { exec("traceroute -n -m 10 $address", $trreturn); return $trreturn; } // reverse whois function rwhois($query) { $fp = fsockopen ("rwhois.arin.net", 4321, $errno, $errstr, 30); if (!$fp) { $ret[] = "$errstr ($errno)\n"; } else { fputs($fp, "$query\r\n"); while (!feof($fp)) { $back = trim(fgets ($fp, 256)); if (empty($back) || stripos($back, ':') === false || substr($back, 0, 1) == '#') continue; $ret[] = $back; }//wend fclose ($fp); } return $ret; } 


Finally


The above code is quite simple and can serve as a basis for your application using ncurses .

We did not consider using the mouse, colors and many other output functions.

Perhaps you will create a set of functions to use this output library. As a start, I suggest you two functions that will simplify the creation of windows. You can add panels to them, draw headlines or something else.

 /** 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; } 


Happy programming!

useful links



From translator

Installing the ncurses extension
  1. Install pecl. Package php5-dev in ubuntu, php-pear in arch
  2. Install the extension itself: pecl install ncurses ( pecl install ncurses rights, therefore with sudo)
  3. Connect extension. Add the line "extension = ncurses.so" to your php.ini

Original article: devzone.zend.com/173/using-ncurses-in-php
Please report typos in HP

Source: https://habr.com/ru/post/186570/


All Articles