The use of PHP command line extension Readline related functions

Time:2022-8-5
Table of contents
  • Installation of the Readline extension
  • Basic function operation
    • read a line
    • Command History List Related Operations
    • Check Readline Status
    • command prompt effect
  • Examples of character callback operations
    • Summarize

      The readline extension function implements an interface to access the GNU Readline library. These functions provide editable command lines. An example is in Bash which allows you to use the arrow keys to insert characters or scroll through the command history. Because of the interactive nature of this library, this feature isn't very useful when you're writing Web programs, but it's very useful when you're writing scripts that are used on the command line.

      Installation of the Readline extension

      The Readline extension has been added to the official PHP installation package. If it is a new PHP environment, add –with-readline when compiling. In addition, we also need to install the Readline library for the operating system. Of course, if the PHP is already running normally, you can also recompile it.

      
      # yum install -y readline-devel
      # ./congiure xxxx --with-readline

      By default, if –whit-readline is not added at compile time, some functions of Readline can also be used, but they call the system libedit library. Some functions, such as readline_list_history(), cannot be used. In order to fully use the ability of Readline extension, you still need to install the libreadline library of the operating system (the readline-devel installed by yum above) and compile and install the corresponding parameters in PHP.

      Basic function operation

      The Readline extension provides few functions and is very easy to use.

      read a line

      $line = readline("Please enter the command: "); // Read command line interactive information
      echo $line, PHP_EOL; // aaa

      After running the PHP code, we enter the command prompt waiting state, and will prompt "Please enter the command:", when we enter aaa and press Enter, the entered content is saved to the $line variable.

      Command History List Related Operations

      One of the powerful features of Readline is that it comes with a set of command history functions. But this requires us to manually add the command to the command history.

      $line = readline("Please enter the command: "); // Read command line interactive information
      if (!empty($line)) {
          readline_add_history($line); // Need to manually add to the command history
      }
      echo $line, PHP_EOL; // aaa
      
      $line = readline("Please enter the command: ");
      if (!empty($line)) {
          readline_add_history($line);
      }
      
      // command history list
      print_r(readline_list_history());
      // Array
      // (
      //     [0] => aaa
      //     [1] => bbb
      // )

      Using the readline_add_history() function, you can add a command to the command history, and then use readline_list_history() to print out a record of the commands we sent in the interactive environment before. Of course, it would be boring if it was simply saved and then printed. It can also save these historical information to an external file for storage.

      // write command history to a file
      readline_write_history('./readline_history');
      // in ./readline_history
      // _HiStOrY_V2_
      // aaa
      // bbb
      
      // clean up command history
      readline_clear_history();
      print_r(readline_list_history());
      // Array
      // (
      // )
      
      // read command history from file
      readline_read_history('./readline_history');
      print_r(readline_list_history());
      // Array
      // (
      //     [0] => bbb
      //     [1] => bbb
      // )

      We use the readline_write_history() function to save the current command history to a file, and then use readline_clear_history() to clear the contents of the current command history list. At this time, if readline_list_history() is printed, there is nothing in it. Next, we use readline_read_history() to load the command history back from the file for restoration. Is this set of functions very interesting? We can record all the command operations of customers, whether it is security review or event playback, it is very useful.

      Check Readline Status

      // Variable information inside the current command line
      print_r(readline_info());
      // Array
      // (
      //     [line_buffer] => bbb
      //     [point] => 3
      //     [end] => 3
      //     [mark] => 0
      //     [done] => 1
      //     [pending_input] => 0
      // [prompt] => Please enter the command:
      //     [terminal_name] => xterm-256color
      //     [completion_append_character] =>
      //     [completion_suppress_append] =>
      //     [library_version] => 7.0
      //     [readline_name] => other
      //     [attempted_completion_over] => 0
      // )

      The readline_info() function is relatively simple. We can see the information of the last interactive command, which includes the command input content line_buffer, content length point, prompt information prompt and so on.

      command prompt effect

      On operating systems such as Linux, it doesn't matter if we can't remember the full spelling of a command, just remember the first few characters of it and press two Tab keys to get the relevant command prompt. Of course, the Readline extension library also prepares such functions for us.

      // Similar to the prompt effect of pressing the Tab key in the command line
      readline_completion_function(function ($input, $index) {
          $commands = ['next', 'exit', 'quit'];
          $matches = [];
          if ($input) {
              // If the keyword is included in the command, prompt for command information
              foreach ($commands as $c) {
                  if (strpos($c, $input) !== false) {
                      $matches[] = $c;
                  }
              }
          }else{
              $matches = $commands;
          }
          return $matches;
      });
      
      // Test it with the Tab key
      $line = trim(readline("Please enter the command: "));
      if (!empty($line)) {
          readline_add_history($line);
      }
      echo $line, PHP_EOL; // currently entered command information
      // If the command is exit or quit, exit the program execution
      if($line == 'exit' || $line == 'quit'){
          exit;
      }

      The readline_completion_function() function will receive a callback function. When in the interactive command line mode, that is, when the readline function is called, when the Tab key is pressed, it will enter the callback function of this function. \$input is the value of the currently entered content, and $index is the number of characters. We define several default commands in this callback function. When you type an n, press the Tab key directly, and the program will prompt the complete next command. Of course, multiple characters starting with the same letter can be returned and rendered through this $matches array.

      Also, in this code, if we typed exit or quit. The running of the program will be exited.

      Examples of character callback operations

      The last few functions we will learn through a complex quiz.

      // The output content goes into this callback function
      function rl_callback($ret)
      {
          global $c, $prompting;
      
          echo "Your input is: $ret\n";
          $c++;
      
          readline_add_history($ret);
      
          // If it is limited, call it 10 times, or it can be judged by the content of the command line input, such as the exit above.
          if ($c > 10) {
              $prompting = false;
              // remove the last installed callback function handle and restore terminal settings
              readline_callback_handler_remove();
          } else {
              // continue recursive callback
              readline_callback_handler_install("[$c] Enter something: ", 'rl_callback');
      
          }
      }
      
      $c = 1;
      $prompting = true;
      
      // Initialize a readline callback interface, and then the terminal outputs prompt information and returns immediately. It needs to wait for the readline_callback_read_char() function to be called before entering the callback function
      readline_callback_handler_install("[$c] Enter something: ", 'rl_callback');
      
      // When $prompting is true, wait for input information
      while ($prompting) {
          $w = null;
          $e = null;
          $r = array(STDIN);
          $n = stream_select($r, $w, $e, null);
          if ($n && in_array(STDIN, $r)) {
              // Read a character when a line is received and notify readline to call the callback function
              readline_callback_read_char();
          }
      }
      
      echo "End, complete all input!\n";
      // [1] Enter something: A
      // Your input is: A
      // [2] Enter something: B
      // Your input is: B
      // [3] Enter something: C
      // Your input is: C
      // [4] Enter something: D
      // Your input is: D
      // [5] Enter something: E
      // Your input is: E
      // [6] Enter something: F
      // Your input is: F
      // [7] Enter something: G
      // Your input is: G
      // [8] Enter something: H
      // Your input is: H
      // [9] Enter something: I
      // Your input is: I
      // [10] Enter something: J
      // Your input is: J
      // Done, all input is done!
      
      print_r(readline_list_history());
      // Array
      // (
      //     [0] => A
      //     [1] => B
      //     [2] => C
      //     [3] => D
      //     [4] => E
      //     [5] => F
      //     [6] => G
      //     [7] => H
      //     [8] => I
      //     [9] => J
      // )

      First of all, let's ignore the above custom function and see readline_callback_read_char() directly. Its role is to read a character when a line is received and notify readline to call the callback function. That is, when a line of input is completed and a carriage return is typed, this function will notify the Readline component to call the callback function registered by readline_callback_handler_install().

      The function of the readline_callback_handler_install() function is to initialize a readline callback interface, and then the terminal outputs prompt information and returns immediately. If no operation is performed in the callback function, this function just outputs a prompt and ends. In the callback function rl_callback() in our example, according to the current number of received commands, we judge that if the received command is within ten times, we will continue to receive commands until ten commands and call readline_callback_handler_remove() to remove the previous readline_callback_handler_install () installs the callback and restores the terminal's default settings.

      The result of the final execution is the content in the comments. You can also copy the code and run the debugging. Only the debugging you have done can you understand it more deeply.

      Summarize

      Readline is very powerful, and it is also an extension that comes with PHP's default installation package. The extensions that are generally added to the default are time-tested and very useful extensions. You can learn more and apply them in actual combat based on these contents.

      Test code:

      https://github.com/zhangyue0503/dev-blog/

      The above is the detailed content of the use of PHP command line extension Readline related functions. For more information on the use of PHP command line extension Readline, please pay attention to other related articles on developpaer!