dwww Home | Manual pages | Find package

RlwrapFilter(3pm)     User Contributed Perl Documentation    RlwrapFilter(3pm)

NAME
       RlwrapFilter - Perl class for rlwrap filters

SYNOPSIS
         use lib $ENV{RLWRAP_FILTERDIR};
         use RlwrapFilter;

         $filter = new RlwrapFilter;

         $filter -> output_handler(sub {s/apple/orange/; $_}); # re-write output
         $filter -> prompt_handler(\&pimp_the_prompt); # change prompt
         $filter -> history_handler(sub {s/with password \w+/with password ****/; $_}); # keep passwords out of history

         $filter -> run;

DESCRIPTION
       rlwrap (1) (<https://github.com/hanslub42/rlwrap>) is a tiny utility
       that sits between the user and any console command, in order to bestow
       readline capabilities (line editing, history recall) to commands that
       don't have them.

       Since version 0.32, rlwrap can use filters to script almost every
       aspect of rlwrap's interaction with the user: changing the history, re-
       writing output and input, calling a pager or computing completion word
       lists from the current input.

       Filters can be combined in a pipeline using the special pipeline
       filter.

       RlwrapFilter makes it very simple to write rlwrap filters in perl. A
       filter only needs to instantiate a RlwrapFilter object, change a few of
       its default handlers and then call its 'run' method.

       There is also a Python 3 module rlwrapfilter.py, distributed together
       with rlwrap, that provides  more or less the same API as its perl
       counterpart.

PUBLIC METHODS
   CONSTRUCTOR
       $f = new RlwrapFilter
       $f = RlwrapFilter -> new(prompt_handler => sub {"Hi! > "},
       minimal_rlwrap_version => "0.35", ...)
           Return a new RlwrapFilter object.

   SETTING/GETTING HANDLERS
       Handlers are user-defined callbacks that specify one or more of an
       RlwrapFilter object's handler methods (handle_input, handle_prompt)
       They get called from the 'run' method in response to a message sent
       from rlwrap.  Messages consist of a tag indicating which handler should
       be called (e.g. TAG_INPUT, TAG_HISTORY) and the message text. Usually,
       a filter overrides only one or at most two methods.

   CALLING CONVENTIONS
       In many cases (e.g. TAG_INPUT, TAG_OUTPUT, TAG_PROMPT) the message text
       is a simple string. Their handlers are called with the message text
       (i.e. the un-filtered input, output, prompt) as their only argument.
       For convenience, $_ is set to the same value. They should return the
       re-written message text.

       Some handlers (those for TAG_COMPLETION and TAG_HOTKEY) are a little
       more complex: their message text (accessible via $_) is a tab-separated
       list of fields; they get called with multiple arguments and are
       evaluated in list context.

       The message handlers are called in a fixed cyclic order: prompt,
       completion, history, input, echo, output, prompt, ... etc ad infinitum.
       Rlwrap may always skip a handler when in direct mode; on the other
       hand, completion and output handlers may get called more than once in
       succession. If a handler is left undefined, the result is as if the
       message text were returned unaltered (in fact, rlwrap knows when this
       is the case and won't even bother to send the message)

       It is important to note that the filter, and hence all its handlers,
       are bypassed when command is in direct mode, i.e. when it asks for
       single keystrokes (and also, for security reasons, when it doesn't
       echo, e.g. when asking for a password). If you don't want this to
       happen, use rlwrap -a to force rlwrap to remain in readline mode and to
       apply the filter to all of command's in- and output. This will make
       editors and pagers (which respond to single keystrokes) unusable,
       unless you use rlwrap's -N option (linux only)

       The getters/setters for the respective handlers are listed below:

       $handler = $f -> prompt_handler, $f -> prompt_handler(\&handler)
           The prompt handler re-writes prompts and gets called when rlwrap
           decides it is time to "cook" the prompt, by default some 40 ms
           after the last output has arrived. Of course, rlwrap cannot read
           the mind of command, so what looks like a prompt to rlwrap may
           actually be the beginning of an output line that took command a
           little longer to formulate. If this is a problem, specify a longer
           "cooking" time with rlwrap's -w option, use the
           prompts_are_never_empty method or "reject" the prompt (cf. the
           prompt_rejected method)

       $handler = $f -> completion_handler, $f ->
       completion_handler(\&handler)
           The completion handler gets called with three arguments: the entire
           input line, the prefix (partial word to complete), and rlwrap's own
           completion list.  It should return a (possibly revised) list of
           completions.  As an example, suppose the user has typed "She played
           for A<TAB>". The handler will be called like this:

                myhandler("She played for A", "A", "Arsenal", "Arendal", "Anderlecht")

           it could then return a list of stronger clubs: ("Ajax", "AZ67",
           "Arnhem")

       $handler = $f -> history_handler, $f -> history_handler(\&handler)
           Every input line is submitted to this handler, the return value is
           put in rlwrap's history. Returning an empty or undefined value will
           keep the input line out of the history.

       $handler = $f -> hotkey_handler, $f -> hotkey_handler(\&handler)
           If, while editing an input line, the user presses a key that is
           bound to "rlwrap_hotkey" in .inputrc, the handler is called with
           five arguments: the hotkey, the prefix (i.e.  the part of the
           current input line before the cursor), the remaining part of the
           input line (postfix), the history as one string ("line 1\nline
           2\n...line N", and the history position. It has to return a similar
           list, except that the first element will be printed in the "echo
           area" if it is changed from its original value.

           Example: if the current input line is  "pea soup" (with the cursor
           on the space), and the user presses CTRL+P, which happens to be
           bound to "rlwrap-hotkey" in .inputrc, the handler is called like
           this:

               my_handler("\0x10", "pea", " soup", "tomato soup\nasparagus..", 12) # 16 = CTRL-P

           If you prefer peanut soup, the handler should return

               ("Mmmm!", "peanut", " soup", "asparagus..", 11)

           after which the input line will be "peanut soup" (with the cursor
           again on the space), the echo area will display "Mmmm!", and any
           reference to inferior soups will have been purged from the history.

           If the returned input line ends with a newline rlwrap will
           immediately accept the result.

       $handler = $f -> input_handler, $f -> input_handler(\&handler)
           Every input line (which may consist of multiple \n-separated lines,
           when using bracketed paste) is submitted to this handler, The
           handler's return value is written to command's pty (pseudo-
           terminal).

       $handler = $f -> echo_handler, $f -> echo_handler(\&handler)
           The first line of output that is read back from command's pty is
           the echo'ed input line. If your input handler alters the input
           line, it is the altered input that will be echo'ed back. If you
           don't want to confuse the user, use an echo handler that returns
           your original input.

           If you use rlwrap in --multi-line mode, additional echo lines will
           have to be handled by the output handler

       $handler = $f -> output_handler, $f -> output_handler(\&handler)
           All command output after the echo line is submitted to the output
           handler (including newlines). This handler may get called many
           times in succession, dependent on the size of command's write()
           calls, and the whims of your system's scheduler. Therefore your
           handler should be prepared to rewrite your output in "chunks",
           where you even don't have the guarantee that the chunks contain
           entire unbroken lines.

           If you want to handle command's entire output in one go, you can
           specify an output handler that returns an empty string, and then
           use $filter -> cumulative_output in your prompt handler to send the
           re-written output "out-of-band" just before the prompt:

               $filter -> output_handler(sub {""});

               $filter -> prompt_handler(
                             sub{ $filter -> send_output_oob(mysub($filter -> cumulative_output));
                                  "Hi there > "
                                });

           Note that when rlwrap is run in --multi-line mode the echo handler
           will still only handle the first echo line.  The remainder will
           generally be echoed back preceded by a continuation prompt; it is
           up to the output handler what to do with it.

       $handler = $f -> signal_handler, $f -> signal_handler(\&handler)
           As rlwrap is transparent to signals, signals get passed on to
           command.  This handler gets called (as handler($signo)) for signals
           SIGHUP, SIGINT, SIGQUIT, SIGTERM, SIGCONT, SIGUSR1, SIGUSR2, and
           SIGWINCH, before the signal is delivered.  It receives (and should
           return) $signo as a string. The returned signal is delivered to
           command; return "0" to ignore the signal altogether. Output can be
           written out-of-band (to rlwrap) or cloak_and_dagger (to command,
           see below)

       $handler = $f -> message_handler, $f -> message_handler(\&handler)
           This handler gets called (as handler($message, $tag)) for every
           incoming message, and every tag (including out-of-band tags),
           before all other handlers. Its return value is ignored, but it may
           be useful for logging and debugging purposes. The $tag is an
           integer that can be converted to a tag name by the 'tag2name'
           method

   OTHER METHODS
       $f -> help_text("Usage...")
           Set the help text for this filter. It will be displayed by rlwrap
           -z <filter>. The second line of the help text is used by "rlwrap -z
           listing"; it should be a short description of what the filter does.

       $f -> minimal_rlwrap_version("x.yy")
           Die unless rlwrap is version x.yy or newer

       $dir = $f -> cwd
           return the name of command's current working directory. This uses
           the /proc filesystem, and may only work on newer linux systems (on
           older linux and on Solaris, it will return something like
           "/proc/12345/cwd", useful to find the contents of command's working
           directory, but not its name)

       $text = $f -> cumulative_output
           return the current cumulative output. All (untreated) output gets
           appended to the cumulative output after the output_handler has been
           called. The cumulative output starts with a fresh slate with every
           OUTPUT message that directly follows an INPUT message (ignoring
           out-of-band messages and rejected prompts)

           When necessary (i.e. when rlwrap is in "impatient mode") the prompt
           is removed from $filter->cumulative_output by the time the prompt
           handler is called.

       $tag = $f -> previous_tag
           The tag of the last preceding in-band message. A tag is an integer
           between 0 and 255, its name can be found with the following method:

       $name = $f -> tag2name($tag)
           Convert the tag (an integer) to its name (e.g. "TAG_PROMPT")

       $name = $f -> name2tag($tag)
           Convert a valid tag name like "TAG_PROMPT" to a tag (an integer)

       $f -> send_output_oob($text)
           Make rlwrap display $text. $text is sent "out-of-band" : rlwrap
           will not see it until just  after it has sent the next message to
           the filter

       $f -> send_ignore_oob($text)
           Send an out-of-band TAG_IGNORE message to rlwrap. rlwrap will
           silently discard it, but it can be useful when debugging filters

       $f -> tweak_readline_oob($readline_function, @parameters)
           Send a specially formatted out-of-band message in order to tweak
           readline (i.e. to make rlwrap call a readline function or set a
           readline variable). See the GNU Readline documentation for details.

           At this moment, the following tweaks are recognised:

               $filter -> tweak_readline_oob("rl_variable_bind", $rl_variable_name, $value);
               # ... only for bindable readline variables like those in .inputrc
               $filter -> tweak_readline_oob("rl_completer_word_break_characters", $chars);
               $filter -> tweak_readline_oob("rl_completer_quote_characters", $chars);
               $filter -> tweak_readline_oob("rl_filename_completion_desired", "0" or "1");

           The parameters should not contain "::" (two consecutive colons).
           This method can be called at any moment, even before $filter -> run

       $f -> add_to_completion_list(@words)
       $f -> remove_from_completion_list(@words)
           Permanently add or remove the words in @words to/from rlwrap's
           completion list.

       $f -> cloak_and_dagger($question, $prompt, $timeout);
           Send $question to command's input and read back everything that
           comes back until $prompt is seen at "end-of-chunk", or no new
           chunks arrive for $timeout seconds, whichever comes first.  Return
           the response (without the final $prompt).  rlwrap remains
           completely unaware of this conversation.

       $f -> cloak_and_dagger_verbose($verbosity)
           If $verbosity evaluates to a true value, make rlwrap print all
           questions sent to command by the "cloak_and_dagger" method, and
           command's responses. By default, $verbosity = 0; setting it to 1
           will mess up the screen but greatly facilitate the (otherwise
           rather tricky) use of "cloak_and_dagger"

       $self -> prompt_rejected
           A special text ("_THIS_CANNOT_BE_A_PROMPT_") to be returned by a
           prompt handler to "reject" the prompt. This will make rlwrap skip
           cooking the prompt.  $self->previous_tag and
           $self->cumulative_output will not be touched.

       $text = $f -> prompts_are_never_empty($val)
           If $val evaluates to a true value, automatically reject empty
           prompts.

       $f -> command_line
           In scalar context: the rlwrapped command and its arguments as a
           string ("command -v blah") in list context: the same as a list
           ("command", "-v", "blah")

       $f -> running_under_rlwrap
           Whether the filter is run by rlwrap, or directly from the command
           line

       $f -> run
           Start an event loop that reads rlwrap's messages from the input
           pipe, calls the appropriate handlers and writes the result to the
           output pipe.  This method never returns.

LOW LEVEL PROTOCOL
       rlwrap communicates with a filter through messages consisting of a tag
       byte (TAG_OUTPUT, TAG_PROMPT etc. - to inform the filter of what is
       being sent), an unsigned 32-bit integer containing the length of the
       message, the message text and an extra newline. For every message sent,
       rlwrap expects, and waits for an answer message with the same tag.
       Sending back a different (in-band) tag is an error and instantly kills
       rlwrap, though filters may precede their answer message with "out-of-
       band" messages to output text (TAG_OUTPUT_OUT_OF_BAND), report errors
       (TAG_ERROR), and to manipulate the completion word list
       (TAG_ADD_TO_COMPLETION_LIST and TAG_REMOVE_FROM_COMPLETION_LIST) Out-
       of-band messages are not serviced by rlwrap until right after it has
       sent the next in-band message - the communication with the filter is
       synchronous and driven by rlwrap.

       Messages are received and sent via two pipes. STDIN, STDOUT and STDERR
       are still connected to the user's terminal, and you can read and write
       them directly, though this may mess up the screen and confuse the user
       unless you are careful. A filter can even communicate with the
       rlwrapped command behind rlwrap's back (cf the cloak_and_dagger()
       method)

       The protocol uses the following tags (tags > 128 are out-of-band)

        TAG_INPUT       0
        TAG_OUTPUT      1
        TAG_HISTORY     2
        TAG_COMPLETION  3
        TAG_PROMPT      4
        TAG_HOTKEY      5
        TAG_SIGNAL      6

        TAG_WHAT_ARE_YOUR_INTERESTS     127

        TAG_IGNORE                      251
        TAG_ADD_TO_COMPLETION_LIST      252
        TAG_REMOVE_FROM_COMPLETION_LIST 253
        TAG_OUTPUT_OUT_OF_BAND          254
        TAG_ERROR                       255

       To see how this works, you can eavesdrop on the protocol using the
       logger filter.

       The constants TAG_INPUT, ... are exported by the RlwrapFilter.pm
       module.

       TAG_WHAT_ARE_YOUR_INTERESTS is only ever used internally, to prevent
       the exchange of messages that won't be handled by the filter anyway. It
       will be seen by the general message handler, and therefore show up
       (exactly once, at program start) in the output of e.g. the logger
       filter.

SIGNALS
       As STDIN is still connected to the users teminal, one might expect the
       filter to receive SIGINT, SIGTERM, SIGTSTP directly from the terminal
       driver if the user presses CTRL-C, CTRL-Z etc Normally, we don't want
       this - it would confuse rlwrap, and the user (who thinks she is talking
       straight to the rlwapped command) probably meant those signals to be
       sent to the command itself. For this reason the filter starts with all
       signals blocked.

       Filters that interact with the users terminal (e.g. to run a pager)
       should unblock signals like SIGTERM, SIGWINCH.

FILTER LIFETIME
       The filter is started by rlwrap after command, and stays alive as long
       as rlwrap runs. Filter methods are immediately usable. When command
       exits, the filter stays around for a little longer in order to process
       command's last words. As calling the cwd and cloak_and_dagger methods
       at that time will make the filter die with an error, it may be
       advisable to wrap those calls in eval{}

       If a filter calls die() it will send an (out-of-band) TAG_ERROR message
       to rlwrap before exiting. rlwrap will then report the message and exit
       (just after its next in-band message - out-of-band messages are not
       always processed immediately)

       die() within an eval() sets $@ as usual.

ENVIRONMENT
       Before calling a filter, rlwrap sets the following environment
       variables:

           RLWRAP_FILTERDIR      directory where RlwrapFilter.pm and most filters live (set by rlwrap, can be
                                 overridden by the user before calling rlwrap)

           PATH                  rlwrap automatically adds $RLWRAP_FILTERDIR to the front of filter's PATH

           RLWRAP_VERSION        rlwrap version (e.g. "0.35")

           RLWRAP_COMMAND_PID    process ID of the rlwrapped command

           RLWRAP_COMMAND_LINE   command line of the rlwrapped command

           RLWRAP_IMPATIENT      whether rlwrap is in "impatient mode" (cf rlwrap (1)). In impatient mode,
                                 the candidate prompt is filtered through the output handler (and displayed before
                                 being overwritten by the cooked prompt).

           RLWRAP_INPUT_PIPE_FD  File descriptor of input pipe. For internal use only

           RLWRAP_OUTPUT_PIPE_FD File descriptor of output pipe. For internal use only

           RLWRAP_MASTER_PTY_FD  File descriptor of command's pty.

           RLWRAP_BREAK_CHARS    The characters rlwrap considers word-breaking (cf. the --break-chars option in rlwrap (1))

           RLWRAP_DEBUG          The value of the --debug (-d) option given to rlwrap

DEBUGGING FILTERS
       While RlwrapFilter.pm makes it easy to write simple filters, debugging
       them can be a problem. A couple of useful tricks:

   LOGGING
       When running a filter, the in- and outgoing messages can be logged by
       the logger filter, using a pipeline:

         rlwrap -z 'pipeline logger incoming : my_filter : logger outgoing' command

   RUNNING WITHOUT rlwrap
       When called by rlwrap, filters get their input from
       $RLWRAP_INPUT_PIPE_FD and write their output to $RLWRAP_OUTPUT_PIPE_FD,
       and expect and write messages consisting of a tag byte, a 32-bit length
       and the message proper. This is not terribly useful when running a
       filter directly from the command line (outside rlwrap), even if we set
       the RLWRAP_*_FD ourselves.

       Therefore, when run directly from the command line, a filter expects
       input messages on its standard input of the form

         TAG_PROMPT myprompt >

       (i.a. a tag name, one space and a message followed by a newline. The
       message will not contain the final newline) and it will respond in the
       same way on its standard output. Of course, rlwrap can help with the
       tedious typing of tag names:

         rlwrap -f tagnames filter_to_be_debugged

       Because rlwrap cannot put TABs and newlines in input lines, filters
       will convert '\t' and '\n' into TAB and newline when run directly from
       the command line.

SEE ALSO
       rlwrap (1), readline (3)

perl v5.36.0                      2022-11-08                 RlwrapFilter(3pm)

Generated by dwww version 1.15 on Mon Jul 1 04:27:15 CEST 2024.