Skip to content

Commit

Permalink
Invoke pager for --help
Browse files Browse the repository at this point in the history
  • Loading branch information
nobu committed Feb 29, 2024
1 parent 59b9fd7 commit 77dccce
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 2 deletions.
23 changes: 21 additions & 2 deletions lib/optparse.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1050,6 +1050,26 @@ def compsys(to, name = File.basename($0)) # :nodoc:
to << " '*:file:_files' && return 0\n"
end

def help_exit
if STDOUT.tty? && (pager = ENV.values_at(*%w[RUBY_PAGER PAGER]).find {|e| e && !e.empty?})
less = ENV["LESS"]
args = [{"LESS" => "#{!less || less.empty? ? '-' : less}Fe"}, pager, "w"]
print = proc do |f|
f.puts help
rescue Errno::EPIPE
# pager terminated
end
if Process.respond_to?(:fork) and false
IO.popen("-") {|f| f ? Process.exec(*args, in: f) : print.call(STDOUT)}
# unreachable
end
IO.popen(*args, &print)
else
puts help
end
exit
end

#
# Default options for ARGV, which never appear in option summary.
#
Expand All @@ -1061,8 +1081,7 @@ def compsys(to, name = File.basename($0)) # :nodoc:
#
Officious['help'] = proc do |parser|
Switch::NoArgument.new do |arg|
puts parser.help
exit
parser.help_exit
end
end

Expand Down
40 changes: 40 additions & 0 deletions test/optparse/test_optparse.rb
Original file line number Diff line number Diff line change
Expand Up @@ -164,4 +164,44 @@ def test_nonopt_pattern
e = assert_raise(OptionParser::InvalidOption) {@opt.parse(%w(-t))}
assert_equal(["-t"], e.args)
end

def test_help_pager
require 'tmpdir'
Dir.mktmpdir do |dir|
File.open(File.join(dir, "options.rb"), "w") do |f|
f.puts "#{<<~"begin;"}\n#{<<~'end;'}"
begin;
stdout = STDOUT.dup
def stdout.tty?; true; end
Object.__send__(:remove_const, :STDOUT)
STDOUT = stdout
ARGV.options do |opt|
end;
100.times {|i| f.puts " opt.on('--opt-#{i}') {}"}
f.puts "#{<<~"begin;"}\n#{<<~'end;'}"
begin;
opt.parse!
end
end;
end

optparse = $".find {|path| path.end_with?("/optparse.rb")}
args = ["-r#{optparse}", "options.rb", "--help"]
cmd = File.join(dir, "pager.cmd")
if RbConfig::CONFIG["EXECUTABLE_EXTS"]&.include?(".cmd")
command = "@echo off"
else # if File.executable?("/bin/sh")
# TruffleRuby just calls `posix_spawnp` and no fallback to `/bin/sh`.
command = "#!/bin/sh\n"
end

[
[{"RUBY_PAGER"=>cmd, "PAGER"=>"echo ng"}, "Executing RUBY_PAGER"],
[{"RUBY_PAGER"=>nil, "PAGER"=>cmd}, "Executing PAGER"],
].each do |env, expected|
File.write(cmd, "#{command}\n" "echo #{expected}\n", perm: 0o700)
assert_in_out_err([env, *args], "", [expected], chdir: dir)
end
end
end
end

0 comments on commit 77dccce

Please sign in to comment.