lib/binman.rb in binman-4.0.0 vs lib/binman.rb in binman-4.1.0

- old
+ new

@@ -1,5 +1,6 @@ +require 'fileutils' require 'shellwords' require 'binman/version' module BinMan extend self @@ -43,42 +44,17 @@ def show source=nil, query=nil # try showing existing man page files for given source if file = find(source) and File.exist? file man_page = File.basename(file) man_path = File.expand_path('../../man', file) - - # try showing HTML manual page in a web browser in background - require 'opener' - Dir["#{man_path}/**/#{man_page}.*.html"].each do |man_html| - # close streams to avoid interference with man(1) reader below - begin - Opener.spawn man_html, 0 => :close, 1 => :close, 2 => :close - rescue Errno::ENOENT - # designated opener program could not be found on this system - end - end - - # try showing roff manual page in man(1) reader in foreground; - # close STDERR to avoid interference with the fall back below - return if view query, '-M', man_path, '-a', man_page, 2 => :close + return if show_man(man_path, man_page, query) end - # fall back to showing leading comment header as-is + # fall back to rendering leading comment header or showing it as-is header = snip(source) - - begin - roff = conv(header) - require 'tempfile' - Tempfile.open 'binman' do |temp| - temp.write roff - temp.close - view query, temp.path, 2 => :close - end - rescue => error - warn "binman: #{error}" - puts header - end + return if show_str(header, query) + puts header end # Shows leading comment header from given source as UNIX man page and exits # if the given argument vector contains '-h' or '--help', except after '--', # optionally followed by a regular expression argument that specifies text @@ -93,20 +69,16 @@ end private # Launches man(1) with the given arguments and then tries to search for the - # query (if given) within. If man(1) is not able to launch with the search - # capability, then it tries launching man(1) without the search capability. + # query (if given) within. This is achieved by specifying the LESS and MORE + # environment variables used by the less(1) and more(1) pagers respectively. def view query, *argv - # man(1) defaults to `pager -s` under Debian but `less -is` under CentOS - # so try different pagers, but always fall back to using no pager at all. - # See https://www.debian-administration.org/article/246/ for pager list. - query and %w[ pager less most more ].any? do |pager| - # the `-s` and `+/pattern` options are universally supported by pagers - system 'man', '-P', "#{pager} -s +/#{query.shellescape}", *argv - end or system 'man', *argv + env = query ? {'LESS' => [ENV['LESS'], "+/#{query}"].compact.join(' '), + 'MORE' => [ENV['MORE'], "+/#{query}"].compact.join(' ')} : {} + system env, 'man', *argv end # Converts given markdown(7) source into roff(7). def conv source=nil require 'md2man/roff/engine' @@ -129,7 +101,58 @@ # Resolves given source into first caller's file name if nil. def find source=nil source || if first_caller = caller.find {|f| not f.start_with? __FILE__ } first_caller.sub(/:\d+.*$/, '') end + end + + # Tries to show the given manual page file in man(1) reader + # and returns true if successful; else you need a fallback. + # If HTML manual page shown, its path is printed to stdout. + def show_man path, page, query=nil + # try showing roff manual page in man(1) reader in foreground + Dir["#{path}/man?/#{page}.?"].any? and + view query, '-M', path, '-a', page, 2 => :close or + begin + # try showing HTML manual page in a web browser in background + require 'opener' + Dir["#{path}/**/#{page}.*.html"].map do |html| + begin + # close streams to avoid interference with man(1) reader + Opener.spawn html, 0 => :close, 1 => :close, 2 => :close + puts html + true + rescue Errno::ENOENT + # designated opener program was not found on this system + end + end.compact.any? + end + end + + # Tries to display the given header string in man(1) reader + # and returns true if successful; else you need a fallback. + def show_str header, query=nil + roff = conv(header) + + require 'tempfile' + Tempfile.open 'binman' do |temp| + temp_man_root = temp.path + '_man' + begin + # create a temporary man/ directory structure for `man -M ...` + temp_man_page = 'temporary_manual_page' + temp_man_path = "#{temp_man_root}/man" + temp_man_file = "#{temp_man_path}/man1/#{temp_man_page}.1" + FileUtils.mkdir_p File.dirname(temp_man_file) + + # write the given header string to temporary file and show it + File.open(temp_man_file, 'w') {|file| file << roff } + return true if show_man(temp_man_path, temp_man_page, query) + ensure + FileUtils.rm_rf temp_man_root + end + end + + false + rescue => error + warn "binman: #{error}" end end