任意のコマンドをreadline化するRubyスクリプト
telnetなどのreadlineが組み込まれていない環境で入力を間違えた場合、ctrl+BSで文字を削除する(bash環境)。これでも十分ではあるが、慣れ親しんだemacsキーバインドが使えた方が便利だと思った。
そこで、任意のコマンドをreadline環境下で実行するスクリプトrl.rbを作ってみた。使い方は下記のようになる。
rl.rb telnet d.hatena.ne.jp 80
対話環境でctrl+h(1文字削除), ctrl+a(行の先頭へ移動)などが使えるようになる。また、ヒストリも有効にしてある。ただし、^]などのエスケープ・シークエンスが送れなくなるので注意すること。
コードは下記。ライセンスはrubyと同一とする。
#! /usr/bin/env ruby # rl.rb - readline wrapper # by llamerada (http://d.hatena.ne.jp/llamerada) # # You may redistribute it and/or modify it under the same license # terms as Ruby. # require "readline" require "optparse" def parse_opt parser = OptionParser.new parser.banner = "Usage: #{$0} [OPTION] command" parser.on('-v', '--vi', 'vi editing mode.') { Readline.vi_editing_mode } parser.on('-e', '--emacs', 'emacs editing mode.') { Readline.emacs_editing_mode } parser.on('--help', 'Prints this message and quit.') { puts parser.help exit 0 } def parser.error(msg = nil) $stderr.puts msg if msg $stderr.puts help() exit 1 end begin parser.parse! rescue OptionParser::ParseError => err parser.error err.message end parser.error 'no input command' if ARGV.empty? end def setup_int_signal # for ctrc-c stty_save = `stty -g`.chomp trap("INT") { system "stty", stty_save; exit 0 } end parse_opt setup_int_signal io = IO.popen(ARGV.join(" "), "r+") at_exit do io.close end # writing thread Thread.new do while line = io.gets puts line end exit 0 end # reading thread while buf = Readline.readline("", true) Readline::HISTORY.pop if /^\s*$/ =~ buf begin Readline::HISTORY.pop if Readline::HISTORY[-2] == buf rescue IndexError end io.puts buf end