Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
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) (<http://utopia.knoware.nl/~hlub/uck/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.

       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.

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	get called from	the 'run'
       method with a message  (i.e. the	un-filtered input, output, prompt) as
       their first argument. For convenience, $_ is set	to the same value.
       They should return the re-written message text. They get	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.

       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 the the entire input	line,
	   the prefix (partial word to complete), and rlwrap's own completion
	   list	as arguments. 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 ->	input_handler, $f -> input_handler(\&handler)
	   Every input line 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 ->	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 -> 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_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.

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 B<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 B<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 I<command>'s	pty.

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)	and it
       will respond in the same	way on its standard output

SEE ALSO
       rlwrap (1), readline (3)

perl v5.16.3			  2014-09-11		     RlwrapFilter(3pm)

NAME | SYNOPSIS | DESCRIPTION | PUBLIC METHODS | LOW LEVEL PROTOCOL | SIGNALS | FILTER LIFETIME | ENVIRONMENT | DEBUGGING FILTERS | SEE ALSO

Want to link to this manual page? Use this URL:
<https://www.freebsd.org/cgi/man.cgi?query=RlwrapFilter&sektion=3pm&manpath=FreeBSD+12.1-RELEASE+and+Ports>

home | help