diff --git a/ChangeLog b/ChangeLog index a6c5b8deb8..bac6618840 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,43 @@ +Thu Dec 18 19:31:54 2008 Yuki Sonoda (Yugui) + + * lib/irb/init.rb (IRB.opt_parse): (M17N) adds -U and -E as command + line options. [ruby-dev:37161]. Fixes #711. + improved long optinos. + + * lib/irb/init.rb (IRB.set_encoding): new subroutine for IRB.opt_parse + + * lib/irb/input-method.rb (IRB::StdioInputMethod): (M17N) regards + scripts that user types as encoded in the external_encoding. + + * lib/irb/input-method.rb (IRB::ReadlineInputMethod): ditto. + + * lib/irb/input-method.rb (IRB::FileInputMethod): (M17N) respects + magic comment. + + * lib/irb/help.rb (IRB.print_usage): (M17N) respects magic comment + in the resource file. + + * lib/irb/lc/help-message: adds -U and -E. + + * lib/irb/lc/ja/help-message: ditto. re-encoded from ISO-2022-JP into UTF-8. + + * lib/irb/lc/ja/encoding_aliases.rb: new file. provides Japanese specific + character encoding name table for backward compatibility. + + * lib/irb/lc/ja/error.rb: re-eoncoded from ISO-2022-JP into UTF-8. + magic comment. + + * lib/irb/locale.rb: integrated with Ruby 1.9's M17N support. + + * lib/irb/magic-file.rb: new file. utility to handle files with magic + comment and opens in the correct encoding. + + * lib/irb/ruby-lex.rb (RubyLex#each_top_level_statement): recovers + character encoding for a statement after it lexed so that irb can + eval the statement in correct encoding. + + * lib/irb/src_encoding.rb: new file. utility. + Thu Dec 18 21:12:28 2008 Takeyuki FUJIOKA * lib/cgi/session.rb: fix bug for ignore session_id option. diff --git a/lib/irb/help.rb b/lib/irb/help.rb index 01e5878d18..2b064d5d6d 100644 --- a/lib/irb/help.rb +++ b/lib/irb/help.rb @@ -9,24 +9,27 @@ # # +require 'irb/magic-file' + module IRB def IRB.print_usage lc = IRB.conf[:LC_MESSAGES] path = lc.find("irb/help-message") space_line = false - File.foreach(path) do - |l| - if /^\s*$/ =~ l - lc.puts l unless space_line - space_line = true - next + IRB::MagicFile.open(path){|f| + f.each_line do |l| + if /^\s*$/ =~ l + lc.puts l unless space_line + space_line = true + next + end + space_line = false + + l.sub!(/#.*$/, "") + next if /^\s*$/ =~ l + lc.puts l end - space_line = false - - l.sub!(/#.*$/, "") - next if /^\s*$/ =~ l - lc.puts l - end + } end end diff --git a/lib/irb/init.rb b/lib/irb/init.rb index 576b99d1c8..62c862a1c3 100644 --- a/lib/irb/init.rb +++ b/lib/irb/init.rb @@ -139,6 +139,11 @@ module IRB when /^-I(.+)?/ opt = $1 || ARGV.shift load_path.concat(opt.split(File::PATH_SEPARATOR)) if opt + when '-U' + set_encoding("UTF-8", "UTF-8") + when /^-E(.+)?/, /^--encoding(?:=(.+))?/ + opt = $1 || ARGV.shift + set_encoding(*opt.split(':', 2)) when "--inspect" @CONF[:INSPECT_MODE] = true when "--noinspect" @@ -155,8 +160,9 @@ module IRB @CONF[:VERBOSE] = true when "--noverbose" @CONF[:VERBOSE] = false - when "--prompt-mode", "--prompt" - prompt_mode = ARGV.shift.upcase.tr("-", "_").intern + when /^--prompt-mode(?:=(.+))?/, /^--prompt(?:=(.+))?/ + opt = $1 || ARGV.shift + prompt_mode = opt.upcase.tr("-", "_").intern @CONF[:PROMPT_MODE] = prompt_mode when "--noprompt" @CONF[:PROMPT_MODE] = :NULL @@ -166,14 +172,14 @@ module IRB @CONF[:PROMPT_MODE] = :SIMPLE when "--tracer" @CONF[:USE_TRACER] = true - when "--back-trace-limit" - @CONF[:BACK_TRACE_LIMIT] = ARGV.shift.to_i - when "--context-mode" - @CONF[:CONTEXT_MODE] = ARGV.shift.to_i + when /^--back-trace-limit(?:=(.+))?/ + @CONF[:BACK_TRACE_LIMIT] = ($1 || ARGV.shift).to_i + when /^--context-mode(?:=(.+))?/ + @CONF[:CONTEXT_MODE] = ($1 || ARGV.shift).to_i when "--single-irb" @CONF[:SINGLE_IRB] = true - when "--irb_debug" - @CONF[:DEBUG_LEVEL] = ARGV.shift.to_i + when /^--irb_debug=(?:=(.+))?/ + @CONF[:DEBUG_LEVEL] = ($1 || ARGV.shift).to_i when "-v", "--version" print IRB.version, "\n" exit 0 @@ -181,6 +187,12 @@ module IRB require "irb/help" IRB.print_usage exit 0 + when "--" + if opt = ARGV.shfit + @CONF[:SCRIPT] = opt + $0 = opt + end + break when /^-/ IRB.fail UnrecognizedSwitch, opt else @@ -195,6 +207,7 @@ module IRB end end $LOAD_PATH.unshift(*load_path) + end # running config @@ -253,4 +266,21 @@ module IRB end end + + DefaultEncodings = Struct.new(:external, :internal) + class << IRB + private + def set_encoding(extern, intern = nil) + verbose, $VERBOSE = $VERBOSE, nil + Encoding.default_external = extern unless extern.nil? || extern.empty? + Encoding.default_internal = intern unless intern.nil? || intern.empty? + @CONF[:ENCODINGS] = IRB::DefaultEncodings.new(extern, intern) + [$stdin, $stdout, $stderr].each do |io| + io.set_encoding(extern, intern) + end + @CONF[:LC_MESSAGES].instance_variable_set(:@encoding, extern) + ensure + $VERBOSE = verbose + end + end end diff --git a/lib/irb/input-method.rb b/lib/irb/input-method.rb index fc8d476eae..c4142a924e 100644 --- a/lib/irb/input-method.rb +++ b/lib/irb/input-method.rb @@ -8,6 +8,9 @@ # # # +require 'irb/src_encoding' +require 'irb/magic-file' + module IRB # # InputMethod @@ -41,15 +44,19 @@ module IRB super @line_no = 0 @line = [] + @stdin = IO.open(STDIN.to_i, :external_encoding => IRB.conf[:LC_MESSAGES].encoding, :internal_encoding => "-") + @stdout = IO.open(STDOUT.to_i, :external_encoding => IRB.conf[:LC_MESSAGES].encoding, :internal_encoding => "-") end def gets print @prompt - @line[@line_no += 1] = $stdin.gets + line = @stdin.gets + p line.encoding + @line[@line_no += 1] = line end def eof? - $stdin.eof? + @stdin.eof? end def readable_atfer_eof? @@ -59,12 +66,16 @@ module IRB def line(line_no) @line[line_no] end + + def encoding + @stdin.external_encoding + end end class FileInputMethod < InputMethod def initialize(file) super - @io = open(file) + @io = IRB::MagicFile.open(file) end attr_reader :file_name @@ -78,6 +89,10 @@ module IRB # print @prompt, l l end + + def encoding + @io.external_encoding + end end begin @@ -90,11 +105,14 @@ module IRB @line_no = 0 @line = [] @eof = false + + @stdin = IO.open(STDIN.to_i, :external_encoding => IRB.conf[:LC_MESSAGES].encoding, :internal_encoding => "-") + @stdout = IO.open(STDOUT.to_i, :external_encoding => IRB.conf[:LC_MESSAGES].encoding, :internal_encoding => "-") end def gets - Readline.input = STDIN - Readline.output = STDOUT + Readline.input = @stdin + Readline.output = @stdout if l = readline(@prompt, false) HISTORY.push(l) if !l.empty? @line[@line_no += 1] = l + "\n" @@ -115,6 +133,10 @@ module IRB def line(line_no) @line[line_no] end + + def encoding + @stdin.external_encoding + end end rescue LoadError end diff --git a/lib/irb/lc/help-message b/lib/irb/lc/help-message index d93951b33d..9c08a5c29d 100644 --- a/lib/irb/lc/help-message +++ b/lib/irb/lc/help-message @@ -1,3 +1,4 @@ +# -*- coding: US-ASCII -*- # # irb/lc/help-message.rb - # $Release Version: 0.9.5$ @@ -14,6 +15,8 @@ Usage: irb.rb [options] [programfile] [arguments] -d Set $DEBUG to true (same as `ruby -d') -r load-module Same as `ruby -r' -I path Specify $LOAD_PATH directory + -U Same as `ruby -U` + -E enc Same as `ruby -E` --inspect Use `inspect' for output (default except for bc mode) --noinspect Don't use inspect for output --readline Use Readline extension module @@ -32,3 +35,4 @@ Usage: irb.rb [options] [programfile] [arguments] value is 16. --irb_debug n Set internal debug level to n (not for popular use) -v, --version Print the version of irb +# vim:fileencoding=us-ascii diff --git a/lib/irb/lc/ja/encoding_aliases.rb b/lib/irb/lc/ja/encoding_aliases.rb new file mode 100644 index 0000000000..a713dff4be --- /dev/null +++ b/lib/irb/lc/ja/encoding_aliases.rb @@ -0,0 +1,8 @@ +module IRB + class Locale + @@legacy_encoding_alias_map = { + 'ujis' => Encoding::EUC_JP, + 'euc' => Encoding::EUC_JP + }.freeze + end +end diff --git a/lib/irb/lc/ja/error.rb b/lib/irb/lc/ja/error.rb index 13cf180142..dc0345e6df 100644 --- a/lib/irb/lc/ja/error.rb +++ b/lib/irb/lc/ja/error.rb @@ -1,4 +1,4 @@ -# +# -*- coding: utf-8 -*- # irb/lc/ja/error.rb - # $Release Version: 0.9.5$ # $Revision$ @@ -13,14 +13,15 @@ require "e2mmap" module IRB # exceptions extend Exception2MessageMapper - def_exception :UnrecognizedSwitch, '$B%9%$%C%A(B(%s)$B$,J,$j$^$;$s(B' - def_exception :NotImplementedError, '`%s\'$B$NDj5A$,I,MW$G$9(B' - def_exception :CantReturnToNormalMode, 'Normal$B%b!<%I$KLa$l$^$;$s(B.' - def_exception :IllegalParameter, '$B%Q%i%a!<%?(B(%s)$B$,4V0c$C$F$$$^$9(B.' - def_exception :IrbAlreadyDead, 'Irb$B$O4{$K;`$s$G$$$^$9(B.' - def_exception :IrbSwitchedToCurrentThread, '$B%+%l%s%H%9%l%C%I$K@Z$jBX$o$j$^$7$?(B.' - def_exception :NoSuchJob, '$B$=$N$h$&$J%8%g%V(B(%s)$B$O$"$j$^$;$s(B.' - def_exception :CantShiftToMultiIrbMode, 'multi-irb mode$B$K0\$l$^$;$s(B.' - def_exception :CantChangeBinding, '$B%P%$%s%G%#%s%0(B(%s)$B$KJQ99$G$-$^$;$s(B.' - def_exception :UndefinedPromptMode, '$B%W%m%s%W%H%b!<%I(B(%s)$B$ODj5A$5$l$F$$$^$;$s(B.' + def_exception :UnrecognizedSwitch, 'スイッチ(%s)が分りません' + def_exception :NotImplementedError, '`%s\'の定義が必要です' + def_exception :CantReturnToNormalMode, 'Normalモードに戻れません.' + def_exception :IllegalParameter, 'パラメータ(%s)が間違っています.' + def_exception :IrbAlreadyDead, 'Irbは既に死んでいます.' + def_exception :IrbSwitchedToCurrentThread, 'カレントスレッドに切り替わりました.' + def_exception :NoSuchJob, 'そのようなジョブ(%s)はありません.' + def_exception :CantShiftToMultiIrbMode, 'multi-irb modeに移れません.' + def_exception :CantChangeBinding, 'バインディング(%s)に変更できません.' + def_exception :UndefinedPromptMode, 'プロンプトモード(%s)は定義されていません.' end +# vim:fileencoding=utf-8 diff --git a/lib/irb/lc/ja/help-message b/lib/irb/lc/ja/help-message index ff09b073da..d156039c9b 100644 --- a/lib/irb/lc/ja/help-message +++ b/lib/irb/lc/ja/help-message @@ -1,4 +1,4 @@ -# +# -*- coding: utf-8 -*- # irb/lc/ja/help-message.rb - # $Release Version: 0.9.5$ # $Revision$ @@ -9,27 +9,31 @@ # # Usage: irb.rb [options] [programfile] [arguments] - -f ~/.irbrc $B$rFI$_9~$^$J$$(B. - -m bc$B%b!<%I(B($BJ,?t(B, $B9TNs$N7W;;$,$G$-$k(B) - -d $DEBUG $B$r(Btrue$B$K$9$k(B(ruby -d $B$HF1$8(B) - -r load-module ruby -r $B$HF1$8(B. - -I path $LOAD_PATH $B$K(B path $B$rDI2C$9$k(B. - --inspect $B7k2L=PNO$K(Binspect$B$rMQ$$$k(B(bc$B%b!<%I0J30$O%G%U%)%k%H(B). - --noinspect $B7k2L=PNO$K(Binspect$B$rMQ$$$J$$(B. - --readline readline$B%i%$%V%i%j$rMxMQ$9$k(B. - --noreadline readline$B%i%$%V%i%j$rMxMQ$7$J$$(B. + -f ~/.irbrc を読み込まない. + -m bcモード(分数, 行列の計算ができる) + -d $DEBUG をtrueにする(ruby -d と同じ) + -r load-module ruby -r と同じ. + -I path $LOAD_PATH に path を追加する. + -U ruby -U と同じ. + -E enc ruby -E と同じ. + --inspect 結果出力にinspectを用いる(bcモード以外はデフォルト). + --noinspect 結果出力にinspectを用いない. + --readline readlineライブラリを利用する. + --noreadline readlineライブラリを利用しない. --prompt prompt-mode/--prompt-mode prompt-mode - $B%W%m%s%W%H%b!<%I$r@ZBX$($^$9(B. $B8=:_Dj5A$5$l$F$$$k%W(B - $B%m%s%W%H%b!<%I$O(B, default, simple, xmp, inf-ruby$B$,(B - $BMQ0U$5$l$F$$$^$9(B. - --inf-ruby-mode emacs$B$N(Binf-ruby-mode$BMQ$N%W%m%s%W%HI=<($r9T$J$&(B. $BFC(B - $B$K;XDj$,$J$$8B$j(B, readline$B%i%$%V%i%j$O;H$o$J$/$J$k(B. - --simple-prompt $BHs>o$K%7%s%W%k$J%W%m%s%W%H$rMQ$$$k%b!<%I$G$9(B. - --noprompt $B%W%m%s%W%HI=<($r9T$J$o$J$$(B. - --tracer $B%3%^%s%I[[:alpha:]]{2}) + (?:_ + (?[[:alpha:]]{2,3}) + (?:\. + (?[^@]+) + )? + )? + (?:@ + (?.*) + )? + ]x LOCALE_DIR = "/lc/" + @@legacy_encoding_alias_map = {}.freeze + def initialize(locale = nil) - @lang = locale || ENV["IRB_LANG"] || ENV["LC_MESSAGES"] || ENV["LC_ALL"] || ENV["LANG"] || "C" - end + @locale = locale || ENV["IRB_LANG"] || ENV["LC_MESSAGES"] || ENV["LC_ALL"] || ENV["LANG"] || "C" + if m = LOCALE_NAME_RE.match(@locale) + @lang, @territory, @encoding_name, @modifier = m[:language], m[:territory], m[:codeset], m[:modifier] - attr_reader :lang - - def lc2kconv(lang) - case lang - when "ja_JP.ujis", "ja_JP.euc", "ja_JP.eucJP", "ja_JP.EUC-JP" - Kconv::EUC - when "ja_JP.sjis", "ja_JP.SJIS" - Kconv::SJIS - when /ja_JP.utf-?8/i - Kconv::UTF8 + if @encoding_name + begin; load 'irb/encoding_aliases.rb' rescue LoadError; end + if @encoding = @@legacy_encoding_alias_map[@encoding_name] + warn "%s is obsolete. use %s" % ["#{@lang}_#{@territory}.#{@encoding_name}", "#{@lang}_#{@territory}.#{@encoding.name}"] + end + @encoding = Encoding.find(@encoding_name) rescue nil + end end + @encoding ||= (Encoding.find('locale') rescue Encoding::ASCII_8BIT) end - private :lc2kconv + + attr_reader :lang, :territory, :encoding, :modifieer def String(mes) mes = super(mes) - case @lang - when /^ja/ - mes = Kconv::kconv(mes, lc2kconv(@lang)) + if @encoding + mes.encode(@encoding) else mes end - mes end def format(*opts) @@ -106,27 +114,20 @@ module IRB dir = "" if dir == "." base = File.basename(file) - if /^ja(_JP)?$/ =~ @lang - back, @lang = @lang, "C" + if dir[0] == ?/ #/ + lc_path = search_file(dir, base) + return real_load(lc_path, priv) if lc_path end - begin - if dir[0] == ?/ #/ - lc_path = search_file(dir, base) - return real_load(lc_path, priv) if lc_path - end - - for path in $: - lc_path = search_file(path + "/" + dir, base) - return real_load(lc_path, priv) if lc_path - end - ensure - @lang = back if back + + for path in $: + lc_path = search_file(path + "/" + dir, base) + return real_load(lc_path, priv) if lc_path end raise LoadError, "No such file to load -- #{file}" end def real_load(path, priv) - src = self.String(File.read(path)) + src = MagicFile.open(path){|f| f.read} if priv eval("self", TOPLEVEL_BINDING).extend(Module.new {eval(src, nil, path)}) else @@ -152,29 +153,39 @@ module IRB end def search_file(path, file) - if File.exist?(p1 = path + lc_path(file, "C")) - if File.exist?(p2 = path + lc_path(file)) - return p2 - else - end - return p1 - else + each_sublocale do |lc| + full_path = path + lc_path(file, lc) + return full_path if File.exist?(full_path) end nil end private :search_file - def lc_path(file = "", lc = @lang) - case lc - when "C" + def lc_path(file = "", lc = @locale) + if lc.nil? LOCALE_DIR + file - when /^ja/ - LOCALE_DIR + "ja/" + file else LOCALE_DIR + @lang + "/" + file end end private :lc_path + + def each_sublocale + if @lang + if @territory + if @encoding_name + yield "#{@lang}_#{@territory}.#{@encoding_name}@#{@modifier}" if @modifier + yield "#{@lang}_#{@territory}.#{@encoding_name}" + end + yield "#{@lang}_#{@territory}@#{@modifier}" if @modifier + yield "#{@lang}_#{@territory}" + end + yield "#{@lang}@#{@modifier}" if @modifier + yield "#{@lang}" + end + yield nil + end + private :each_sublocale end end diff --git a/lib/irb/magic-file.rb b/lib/irb/magic-file.rb new file mode 100644 index 0000000000..861262050e --- /dev/null +++ b/lib/irb/magic-file.rb @@ -0,0 +1,36 @@ +module IRB + class << (MagicFile = Object.new) + # see parser_magic_comment in parse.y + ENCODING_SPEC_RE = %r"coding\s*[=:]\s*([[:alnum:]\-_]+)" + + def open(path) + io = File.open(path, 'rb') + line = io.gets + line = io.gets if line[0,2] == "#!" + encoding = detect_encoding(line) + encoding ||= default_src_encoding + io.rewind + io.set_encoding(encoding, nil) + + if block_given? + begin + return (yield io) + ensure + io.close + end + else + return io + end + end + + private + def detect_encoding(line) + return unless line[0] == ?# + line = line[1..-1] + line = $1 if line[/-\*-\s*(.*?)\s*-*-$/] + return nil unless ENCODING_SPEC_RE =~ line + encoding = $1 + return encoding.sub(/-(?:mac|dos|unix)/i, '') + end + end +end diff --git a/lib/irb/ruby-lex.rb b/lib/irb/ruby-lex.rb index 2569fd93d5..b21f0d34f8 100644 --- a/lib/irb/ruby-lex.rb +++ b/lib/irb/ruby-lex.rb @@ -240,6 +240,7 @@ class RubyLex end end if @line != "\n" + @line.force_encoding(@io.encoding) yield @line, @exp_line_no end break unless l diff --git a/lib/irb/src_encoding.rb b/lib/irb/src_encoding.rb new file mode 100644 index 0000000000..958cef104c --- /dev/null +++ b/lib/irb/src_encoding.rb @@ -0,0 +1,4 @@ +# DO NOT WRITE ANY MAGIC COMMENT HERE. +def default_src_encoding + return __ENCODING__ +end