-
-
Save pvdb/da0d384cbf98907f507e019844de8e2d to your computer and use it in GitHub Desktop.
wrap a non-interactive command in an interactive REPL _(read-eval-print loop)_
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
# frozen_string_literal: true | |
REPL_NAME = 'repl' | |
REPL_VERSION = '1.0.0' | |
# | |
# INSTALLATION | |
# | |
# ln -s ${PWD}/repl $(brew --prefix)/bin/ | |
# sudo ln -s ${PWD}/repl /usr/local/bin/ | |
# | |
# DEPENDENCIES | |
# | |
# brew install rlwrap # optional, but recommended | |
# | |
## | |
# run `repl` as a subcommand of `git`, `brew`, `rbenv`, etc. | |
name = File.basename($PROGRAM_NAME) # `git-repl`, `brew-repl`, etc. | |
match = name.match(/\A(?<cmd>.+)-repl\z/) # <cmd> === `git`, `brew`, etc. | |
exec('repl', match[:cmd], *ARGV) if match # 'git repl *' --> 'repl git *' | |
require 'mkmf' | |
require 'English' | |
require 'benchmark' | |
require 'fileutils' | |
require 'shellwords' | |
require 'io/console' | |
## | |
# script-specific IO::console extension | |
class IO | |
def console.log(message, color, width: 78, debug: false, quiet: false) | |
# suppress output when in quiet mode | |
return if quiet | |
# deduct length of '===[]==' (7 characters) | |
max_msg_length = width < 78 ? 71 : (width - 7) | |
# truncate message if too long | |
log_msg = if message.length > max_msg_length | |
"#{message[0, (max_msg_length - 3)]}..." | |
else | |
message | |
end | |
# add padding to message to fill overall width | |
padding = '=' * (max_msg_length - log_msg.length) | |
puts debug ? "===[#{log_msg.send(color)}]==#{padding}" : message | |
end | |
end | |
## | |
# script-specific Kernel extension | |
module Kernel | |
def which(executable) | |
MakeMakefile.find_executable0(executable) | |
end | |
end | |
## | |
# script-specific String extensions | |
class String | |
def colorize(color_code) | |
"\e[#{color_code}m#{self}\e[0m" | |
end | |
def strip_ansi | |
gsub(/\e\[(\d+)(;\d+)*m/, '') | |
end | |
# rubocop:disable Style/SingleLineMethods | |
def bold() colorize('1'); end | |
def invert() colorize('7'); end | |
def red() colorize('31'); end | |
def green() colorize('32'); end | |
def yellow() colorize('33'); end | |
def blue() colorize('34'); end | |
# rubocop:enable Style/SingleLineMethods | |
def true? | |
strip == 'true' | |
end | |
def comment? | |
strip.start_with? '#' | |
end | |
end | |
## | |
# version of rlwrap utility | |
def rlwrap_version | |
`rlwrap --version`.chomp | |
rescue Errno::ENOENT | |
'rlwrap not found' | |
end | |
## | |
# version of Ruby runtime | |
def runtime_version | |
"#{RUBY_ENGINE} #{RUBY_VERSION}" | |
end | |
## | |
# version of repl script | |
def repl_version | |
"#{REPL_NAME} #{REPL_VERSION} (#{rlwrap_version}, #{runtime_version})" | |
end | |
if ARGV.delete('--version') | |
IO.console.puts(repl_version) | |
exit(0) | |
end | |
if ARGV.delete('--help') | |
IO.console.puts(DATA.read) | |
exit(0) | |
end | |
if ARGV.delete('--man') | |
exec('man', File.join(__dir__, 'repl.1')) | |
exit(0) # superfluous, really... | |
end | |
if ARGV.delete('--html') | |
exec('open', File.join(__dir__, 'repl.1.html')) | |
exit(0) # superfluous, really... | |
end | |
# list of remaining options (pipeline and logging) | |
OPTIONS = %w[--stdin --printf --escape --debug --quiet].freeze | |
## | |
# is repl running "inside" rlwrap? | |
def repl_wrapped? | |
!ENV['__RLWRAP_REPL__'].nil? | |
end | |
## | |
# is repl interactive (not piped)? | |
def interactive? | |
$stdin.tty? | |
end | |
## | |
# location of the REPL configuration file | |
def repl_conf | |
ENV.fetch('REPL_CONF', File.join(Dir.home, '.repl.conf')) | |
end | |
unless repl_wrapped? | |
# merge additional REPL config into ENV | |
if File.file?(repl_conf) | |
File.readlines(repl_conf, chomp: true).each do |line| | |
next if line.empty? | |
next if line.comment? | |
key, value = line.split(/\s*=\s*/, 2).map(&:strip) | |
# strip surrounding quotes | |
value.delete_prefix!('"') | |
value.delete_suffix!('"') | |
ENV[key] ||= value # ENV takes precedence | |
end | |
end | |
# replace process with `rlwrap`-ed version | |
# if `rlwrap` is installed and also `repl` | |
# is running interactively (and not piped) | |
if interactive? && (rlwrap_exec = which('rlwrap')) | |
rlwrap_args = [] | |
# suppress all default rlwrap break characters | |
# specifically the '-' (hyphen/dash) character | |
# note that whitespace is always word-breaking | |
rlwrap_args += ['-b', "''"] | |
# rubocop:disable Metrics/BlockNesting | |
# rubocop:disable Style/SoleNestedConditional | |
unless (base_cmd = (ARGV - OPTIONS).map(&:strip).first).nil? | |
if File.executable?(base_cmd) || !which(base_cmd).nil? | |
base_cmd = File.basename(base_cmd) | |
default_history_dir = Dir.home | |
history_dir = ENV['REPL_HISTORY_DIR'] || default_history_dir | |
if File.directory? history_dir = File.expand_path(history_dir) | |
history_file = File.join(history_dir, ".#{base_cmd}_history") | |
rlwrap_args += ['-H', history_file] | |
end | |
default_completion_dir = File.join(Dir.home, '.repl') | |
completion_dir = ENV['REPL_COMPLETION_DIR'] || default_completion_dir | |
if File.directory? completion_dir = File.expand_path(completion_dir) | |
if File.exist? completion_file = File.join(completion_dir, base_cmd) | |
rlwrap_args += ['-f', completion_file] | |
end | |
end | |
end | |
end | |
# rubocop:enable Style/SoleNestedConditional | |
# rubocop:enable Metrics/BlockNesting | |
ENV['__RLWRAP_REPL__'] = Process.pid.to_s | |
exec(rlwrap_exec, *rlwrap_args, $PROGRAM_NAME, *ARGV) | |
end | |
end | |
# process the pipeline options | |
stdin = ARGV.delete('--stdin') | |
printf = ARGV.delete('--printf') | |
escape = ARGV.delete('--escape') | |
# process the logging options (can be set in ~/.repl.conf or ENV) | |
debug = ARGV.delete('--debug') || ENV['REPL_DEBUG']&.true? | |
quiet = ARGV.delete('--quiet') || ENV['REPL_QUIET']&.true? | |
# command is whatever's left | |
if (cmd_string = ARGV.join(' ').strip).empty? | |
IO.console.puts('No command specified... use `--help`') | |
exit(0) | |
end | |
cmd_template = if stdin | |
pipe_cmd = which(printf ? 'printf' : 'echo') | |
"#{pipe_cmd} \"%s\" | #{cmd_string}" | |
elsif ARGV.grep(/%s/).any? | |
cmd_string # the '%s' is embedded | |
else | |
"#{cmd_string} %s" | |
end | |
cmd_prompt = if debug | |
if repl_wrapped? | |
"rlwrap(repl(\"#{cmd_template.blue}\"))" | |
else | |
"repl(\"#{cmd_template.blue}\")" | |
end | |
else | |
"\"#{cmd_template.blue}\"" | |
end | |
log_options = { | |
debug: debug, quiet: quiet, | |
width: cmd_prompt.strip_ansi.length | |
}.freeze | |
repl_prompt = ENV.fetch('REPL_PROMPT', '>>') | |
full_prompt = "#{cmd_prompt} #{repl_prompt}" | |
# rubocop:disable Metrics/BlockLength | |
loop do | |
# prompt user for cmd arguments | |
IO.console.print(full_prompt, ' ') if interactive? || !quiet | |
line = begin | |
$stdin.gets&.strip # nil when ^D | |
rescue Interrupt | |
nil # Interrupt is raised for ^C | |
end | |
# echo input if read from piped stdin | |
IO.console.puts(line) unless interactive? || quiet | |
# terminate `repl` loop on (^C|^D|EOF) | |
break unless line | |
unless line.empty? || line.comment? | |
line = Shellwords.escape(line) if escape | |
# command = format(cmd_template, line) # expand single '%s' placeholder | |
command = cmd_template.gsub('%s', line) # expand _all_ '%s' placeholders | |
begin | |
# print "expanded" command to be executed | |
message = "Executing: '#{command}'" | |
IO.console.log(message, :blue, **log_options) | |
tms = Benchmark.measure do | |
system(command, exception: true) | |
rescue Interrupt | |
# print message when command is interrupted | |
message = 'Command was interrupted' | |
IO.console.log(message, :red, **log_options) | |
end | |
# print elapsed real time to execute command | |
message = format('Command took %.2fs to execute', tms.real) | |
IO.console.log(message, :green, **log_options) | |
rescue RuntimeError, Errno::ENOENT | |
# print exception message when command fails | |
message = $ERROR_INFO.message | |
IO.console.log(message, :red, **log_options) | |
next unless line =~ /(quit|exit)/i | |
# print message when command fails due to 'quit'/'exit' | |
message = 'Use ^C or ^D to exit repl' | |
IO.console.log(message, :yellow, **log_options) | |
end | |
end | |
# empty separator line | |
IO.console.puts if interactive? || !quiet | |
end | |
# rubocop:enable Metrics/BlockLength | |
exit(0) # cleanly exit repl | |
__END__ | |
Usage: repl [options] command ... | |
Options: | |
--version Display repl version information | |
--help Display repl usage information | |
--man Display the repl man page | |
--html Open HTML version of man page | |
--stdin Pipe input to command's STDIN | |
--printf Avoid newline chars in STDIN | |
--escape Shell escape user's input | |
--debug Display each command being executed | |
--quiet Don't echo the prompt in pipelines | |
Homepage: | |
http://github.com/pvdb/repl | |
Bug reports, suggestions, updates: | |
http://github.com/pvdb/repl/issues | |
That's all Folks! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.\" generated with Ronn-NG/v0.10.1 | |
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1 | |
.TH "REPL" "1" "January 2025" "PVDB" "Awesome Utilities" | |
.SH "NAME" | |
\fBrepl\fR \- sometimes you \fIreally\fR need a repl | |
.SH "SYNOPSIS" | |
\fBrepl\fR \fI[options]\fR \fIcommand\fR <\|\.\|\.\|\.> | |
.SH "DESCRIPTION" | |
\fBrepl\fR wraps a non\-interactive \fBcommand\fR in an interactive read\-eval\-print\-loop prompt\. Each line you type into the prompt is executed as arguments to \fBcommand\fR\. Anything written to standard output or standard error by the \fBcommand\fR is displayed\. | |
.P | |
If you have \fBrlwrap(1)\fR installed you'll automatically get the full benefits of readline: history, reverse searches, etc\. | |
.P | |
\fBrepl\fR is meant to wrap programs which accept command line arguments and print to the standard output\. It keeps no state between executed lines and, as such, cannot be used to replace \fBirb\fR or the Python REPL (for example)\. | |
.SH "EXAMPLES" | |
Using \fBrepl\fR with \fBredis\-cli\fR: | |
.IP "" 4 | |
.nf | |
$ repl redis\-cli | |
>> set name chris | |
OK | |
>> get name | |
chris | |
>> info | |
redis_version:1\.000 | |
uptime_in_seconds:182991 | |
uptime_in_days:2 | |
\&\.\. etc \.\. | |
.fi | |
.IP "" 0 | |
.P | |
Using \fBrepl\fR with Ruby's \fBgem\fR: | |
.IP "" 4 | |
.nf | |
$ repl gem | |
>> \-\-version | |
1\.3\.5 | |
>> search yajl | |
*** LOCAL GEMS *** | |
yajl\-ruby (0\.6\.7) | |
>> search yajl \-r | |
*** REMOTE GEMS *** | |
brianmario\-yajl\-ruby (0\.6\.3) | |
filipegiusti\-yajl\-ruby (0\.6\.4) | |
jdg\-yajl\-ruby (0\.5\.12) | |
oortle\-yajl\-ruby (0\.5\.8) | |
yajl\-ruby (0\.6\.7) | |
.fi | |
.IP "" 0 | |
.P | |
Using \fBrepl\fR with \fBgit\fR: | |
.IP "" 4 | |
.nf | |
$ repl git | |
>> branch | |
gh\-pages | |
* master | |
>> tag | |
rm | |
v0\.1\.0 | |
v0\.1\.1 | |
v0\.1\.2 | |
v0\.1\.3 | |
>> tag \-d rm | |
Deleted tag 'rm' | |
>> pwd | |
git: 'pwd' is not a git\-command\. See 'git \-\-help'\. | |
Did you mean this? | |
add | |
.fi | |
.IP "" 0 | |
.SH "OPTIONS" | |
.TP | |
\fB\-\-version\fR | |
Display \fBrepl\fR version information\. | |
.TP | |
\fB\-\-help\fR | |
Display \fBrepl\fR usage information\. | |
.TP | |
\fB\-\-man\fR | |
Display the \fBrepl\fR man page | |
.TP | |
\fB\-\-html\fR | |
Open HTML version of man page | |
.TP | |
\fB\-\-debug\fR | |
Display each command being executed | |
.TP | |
\fB\-\-quiet\fR | |
Don't echo the prompt in pipelines | |
.SH "COMPLETION" | |
Because \fBrlwrap\fR supports completion, \fBrepl\fR does too\. Any file in \fB~/\.repl\fR matching the name of the command you start \fBrepl\fR with will be used for completion\. | |
.P | |
For instance, a file named \fB~/\.repl/redis\-cli\fR containing "get set info" will cause "get", "set", and "info" to be tab completeable at the \fBrepl redis\-cli\fR prompt\. | |
.P | |
The directory searched for completion files can be configured using the \fBREPL_COMPLETION_DIR\fR environment variable\. | |
.SH "COMMAND HISTORY" | |
Because \fBrlwrap\fR supports command history, \fBrepl\fR does too\. Any file in \fB~/\fR matching the name of the command you start \fBrepl\fR with prefix with a dot and suffixed with "_history" will be used for completion\. | |
.P | |
For instance, a file named \fB~/\.redis\-cli_history\fR containing a newline separated list of "get set info" will cause "get", "set", and "info" to be reachable using the up arrow as command history at the \fBrepl redis\-cli\fR prompt\. | |
.P | |
The directory searched for history files can be configured using the \fBREPL_HISTORY_DIR\fR environment variable\. | |
.SH "ENVIRONMENT" | |
The following environment variables can be used to configure \fBrepl\fR's behaviour, and can be set permanently in the \fB~/\.repl\.conf\fR configuration file: | |
.SS "REPL_PROMPT" | |
the prompt to display before each line of input (defaults to \fB>>\fR) | |
.SS "REPL_DEBUG" | |
print out the expanded command before executing it | |
.SS "REPL_QUIET" | |
suppress superfluous output when inside a pipeline | |
.SS "REPL_HISTORY_DIR" | |
directory in which command history files are kept | |
.SS "REPL_COMPLETION_DIR" | |
directory in which command completion files are kept | |
.SH "HOMEPAGE" | |
\fIhttp://github\.com/pvdb/repl\fR | |
.P | |
You will find many more practical examples there! | |
.SH "BUGS" | |
\fIhttp://github\.com/pvdb/repl/issues\fR | |
.SH "AUTHOR" | |
Peter Vandenberk :: @pvdb \fIhttps://github\.com/pvdb\fR | |
.SH "CREDITS" | |
Chris Wanstrath :: @defunkt \fIhttps://github\.com/defunkt\fR | |
.P | |
Check out his (awesome, but unmaintained) original version \fIhttps://github\.com/defunkt/repl\fR on which this one is based! | |
.SH "SEE ALSO" | |
rlwrap(1), readline(3) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta http-equiv='content-type' content='text/html;charset=utf-8'> | |
<meta name='generator' content='Ronn-NG/v0.10.1 (http://github.com/apjanke/ronn-ng/tree/0.10.1)'> | |
<title>repl(1) - sometimes you <em>really</em> need a repl</title> | |
<style type='text/css' media='all'> | |
/* style: man */ | |
body#manpage {margin:0} | |
.mp {max-width:100ex;padding:0 9ex 1ex 4ex} | |
.mp p,.mp pre,.mp ul,.mp ol,.mp dl {margin:0 0 20px 0} | |
.mp h2 {margin:10px 0 0 0} | |
.mp > p,.mp > pre,.mp > ul,.mp > ol,.mp > dl {margin-left:8ex} | |
.mp h3 {margin:0 0 0 4ex} | |
.mp dt {margin:0;clear:left} | |
.mp dt.flush {float:left;width:8ex} | |
.mp dd {margin:0 0 0 9ex} | |
.mp h1,.mp h2,.mp h3,.mp h4 {clear:left} | |
.mp pre {margin-bottom:20px} | |
.mp pre+h2,.mp pre+h3 {margin-top:22px} | |
.mp h2+pre,.mp h3+pre {margin-top:5px} | |
.mp img {display:block;margin:auto} | |
.mp h1.man-title {display:none} | |
.mp,.mp code,.mp pre,.mp tt,.mp kbd,.mp samp,.mp h3,.mp h4 {font-family:monospace;font-size:14px;line-height:1.42857142857143} | |
.mp h2 {font-size:16px;line-height:1.25} | |
.mp h1 {font-size:20px;line-height:2} | |
.mp {text-align:justify;background:#fff} | |
.mp,.mp code,.mp pre,.mp pre code,.mp tt,.mp kbd,.mp samp {color:#131211} | |
.mp h1,.mp h2,.mp h3,.mp h4 {color:#030201} | |
.mp u {text-decoration:underline} | |
.mp code,.mp strong,.mp b {font-weight:bold;color:#131211} | |
.mp em,.mp var {font-style:italic;color:#232221;text-decoration:none} | |
.mp a,.mp a:link,.mp a:hover,.mp a code,.mp a pre,.mp a tt,.mp a kbd,.mp a samp {color:#0000ff} | |
.mp b.man-ref {font-weight:normal;color:#434241} | |
.mp pre {padding:0 4ex} | |
.mp pre code {font-weight:normal;color:#434241} | |
.mp h2+pre,h3+pre {padding-left:0} | |
ol.man-decor,ol.man-decor li {margin:3px 0 10px 0;padding:0;float:left;width:33%;list-style-type:none;text-transform:uppercase;color:#999;letter-spacing:1px} | |
ol.man-decor {width:100%} | |
ol.man-decor li.tl {text-align:left} | |
ol.man-decor li.tc {text-align:center;letter-spacing:4px} | |
ol.man-decor li.tr {text-align:right;float:right} | |
</style> | |
</head> | |
<!-- | |
The following styles are deprecated and will be removed at some point: | |
div#man, div#man ol.man, div#man ol.head, div#man ol.man. | |
The .man-page, .man-decor, .man-head, .man-foot, .man-title, and | |
.man-navigation should be used instead. | |
--> | |
<body id='manpage'> | |
<div class='mp' id='man'> | |
<div class='man-navigation' style='display:none'> | |
<a href="#NAME">NAME</a> | |
<a href="#SYNOPSIS">SYNOPSIS</a> | |
<a href="#DESCRIPTION">DESCRIPTION</a> | |
<a href="#EXAMPLES">EXAMPLES</a> | |
<a href="#OPTIONS">OPTIONS</a> | |
<a href="#COMPLETION">COMPLETION</a> | |
<a href="#COMMAND-HISTORY">COMMAND HISTORY</a> | |
<a href="#ENVIRONMENT">ENVIRONMENT</a> | |
<a href="#HOMEPAGE">HOMEPAGE</a> | |
<a href="#BUGS">BUGS</a> | |
<a href="#AUTHOR">AUTHOR</a> | |
<a href="#CREDITS">CREDITS</a> | |
<a href="#SEE-ALSO">SEE ALSO</a> | |
</div> | |
<ol class='man-decor man-head man head'> | |
<li class='tl'>repl(1)</li> | |
<li class='tc'>Awesome Utilities</li> | |
<li class='tr'>repl(1)</li> | |
</ol> | |
<h2 id="NAME">NAME</h2> | |
<p class="man-name"> | |
<code>repl</code> - <span class="man-whatis">sometimes you <em>really</em> need a repl</span> | |
</p> | |
<h2 id="SYNOPSIS">SYNOPSIS</h2> | |
<p><code>repl</code> <var>[options]</var> <var>command</var> <...></p> | |
<h2 id="DESCRIPTION">DESCRIPTION</h2> | |
<p><code>repl</code> wraps a non-interactive <code>command</code> in an interactive | |
read-eval-print-loop prompt. Each line you type into the prompt is | |
executed as arguments to <code>command</code>. Anything written to standard | |
output or standard error by the <code>command</code> is displayed.</p> | |
<p>If you have <code>rlwrap(1)</code> installed you'll automatically get the full | |
benefits of readline: history, reverse searches, etc.</p> | |
<p><code>repl</code> is meant to wrap programs which accept command line arguments | |
and print to the standard output. It keeps no state between executed | |
lines and, as such, cannot be used to replace <code>irb</code> or the Python | |
REPL (for example).</p> | |
<h2 id="EXAMPLES">EXAMPLES</h2> | |
<p>Using <code>repl</code> with <code>redis-cli</code>:</p> | |
<pre><code>$ repl redis-cli | |
>> set name chris | |
OK | |
>> get name | |
chris | |
>> info | |
redis_version:1.000 | |
uptime_in_seconds:182991 | |
uptime_in_days:2 | |
.. etc .. | |
</code></pre> | |
<p>Using <code>repl</code> with Ruby's <code>gem</code>:</p> | |
<pre><code>$ repl gem | |
>> --version | |
1.3.5 | |
>> search yajl | |
*** LOCAL GEMS *** | |
yajl-ruby (0.6.7) | |
>> search yajl -r | |
*** REMOTE GEMS *** | |
brianmario-yajl-ruby (0.6.3) | |
filipegiusti-yajl-ruby (0.6.4) | |
jdg-yajl-ruby (0.5.12) | |
oortle-yajl-ruby (0.5.8) | |
yajl-ruby (0.6.7) | |
</code></pre> | |
<p>Using <code>repl</code> with <code>git</code>:</p> | |
<pre><code>$ repl git | |
>> branch | |
gh-pages | |
* master | |
>> tag | |
rm | |
v0.1.0 | |
v0.1.1 | |
v0.1.2 | |
v0.1.3 | |
>> tag -d rm | |
Deleted tag 'rm' | |
>> pwd | |
git: 'pwd' is not a git-command. See 'git --help'. | |
Did you mean this? | |
add | |
</code></pre> | |
<h2 id="OPTIONS">OPTIONS</h2> | |
<dl> | |
<dt><code>--version</code></dt> | |
<dd>Display <code>repl</code> version information.</dd> | |
<dt><code>--help</code></dt> | |
<dd>Display <code>repl</code> usage information.</dd> | |
<dt><code>--man</code></dt> | |
<dd>Display the <code>repl</code> man page</dd> | |
<dt><code>--html</code></dt> | |
<dd>Open HTML version of man page</dd> | |
<dt><code>--debug</code></dt> | |
<dd>Display each command being executed</dd> | |
<dt><code>--quiet</code></dt> | |
<dd>Don't echo the prompt in pipelines</dd> | |
</dl> | |
<h2 id="COMPLETION">COMPLETION</h2> | |
<p>Because <code>rlwrap</code> supports completion, <code>repl</code> does too. Any file in | |
<code>~/.repl</code> matching the name of the command you start <code>repl</code> with will | |
be used for completion.</p> | |
<p>For instance, a file named <code>~/.repl/redis-cli</code> containing "get set | |
info" will cause "get", "set", and "info" to be tab completeable at | |
the <code>repl redis-cli</code> prompt.</p> | |
<p>The directory searched for completion files can be configured using | |
the <code>REPL_COMPLETION_DIR</code> environment variable.</p> | |
<h2 id="COMMAND-HISTORY">COMMAND HISTORY</h2> | |
<p>Because <code>rlwrap</code> supports command history, <code>repl</code> does too. Any file in | |
<code>~/</code> matching the name of the command you start <code>repl</code> with prefix | |
with a dot and suffixed with "_history" will be used for completion.</p> | |
<p>For instance, a file named <code>~/.redis-cli_history</code> containing a newline | |
separated list of "get set info" will cause "get", "set", and "info" | |
to be reachable using the up arrow as command history at the <code>repl | |
redis-cli</code> prompt.</p> | |
<p>The directory searched for history files can be configured using the | |
<code>REPL_HISTORY_DIR</code> environment variable.</p> | |
<h2 id="ENVIRONMENT">ENVIRONMENT</h2> | |
<p>The following environment variables can be used to configure <code>repl</code>'s behaviour, and can be set permanently in the <code>~/.repl.conf</code> configuration file:</p> | |
<h3 id="REPL_PROMPT">REPL_PROMPT</h3> | |
<p>the prompt to display before each line of input (defaults to <code>>></code>)</p> | |
<h3 id="REPL_DEBUG">REPL_DEBUG</h3> | |
<p>print out the expanded command before executing it</p> | |
<h3 id="REPL_QUIET">REPL_QUIET</h3> | |
<p>suppress superfluous output when inside a pipeline</p> | |
<h3 id="REPL_HISTORY_DIR">REPL_HISTORY_DIR</h3> | |
<p>directory in which command history files are kept</p> | |
<h3 id="REPL_COMPLETION_DIR">REPL_COMPLETION_DIR</h3> | |
<p>directory in which command completion files are kept</p> | |
<h2 id="HOMEPAGE">HOMEPAGE</h2> | |
<p><a href="http://github.com/pvdb/repl" data-bare-link="true">http://github.com/pvdb/repl</a></p> | |
<p>You will find many more practical examples there!</p> | |
<h2 id="BUGS">BUGS</h2> | |
<p><a href="http://github.com/pvdb/repl/issues" data-bare-link="true">http://github.com/pvdb/repl/issues</a></p> | |
<h2 id="AUTHOR">AUTHOR</h2> | |
<p>Peter Vandenberk :: <a href="https://github.com/pvdb">@pvdb</a></p> | |
<h2 id="CREDITS">CREDITS</h2> | |
<p>Chris Wanstrath :: <a href="https://github.com/defunkt">@defunkt</a></p> | |
<p>Check out his (awesome, but unmaintained) <a href="https://github.com/defunkt/repl">original version</a> on which this one is based!</p> | |
<h2 id="SEE-ALSO">SEE ALSO</h2> | |
<p><span class="man-ref">rlwrap<span class="s">(1)</span></span>, <span class="man-ref">readline<span class="s">(3)</span></span></p> | |
<ol class='man-decor man-foot man foot'> | |
<li class='tl'>PVDB</li> | |
<li class='tc'>January 2025</li> | |
<li class='tr'>repl(1)</li> | |
</ol> | |
</div> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment