[#37248] [Feature:1.9] Enumerator#inspect — "Yusuke ENDOH" <mame@...>

遠藤です。

12 messages 2008/12/02

[#37337] [Feature #841] Object#self — "rubikitch ." <redmine@...>

Feature #841: Object#self

13 messages 2008/12/09

[#37513] Current status of 1.9.1 RC1's issues — "Yugui (Yuki Sonoda)" <yugui@...>

Hi, folks

14 messages 2008/12/20
[#37516] Re: Current status of 1.9.1 RC1's issues — Masatoshi SEKI <m_seki@...> 2008/12/20

咳といいます。

[#37576] [BUG:trunk] encoding for stdio's — "Yugui (Yuki Sonoda)" <yugui@...>

Yuguiです。

11 messages 2008/12/24

[ruby-dev:37610] Re: M17N of erb(1) Was: Re: Current status of 1.9.1 RC1's issues

From: "Yugui (Yuki Sonoda)" <yugui@...>
Date: 2008-12-26 10:06:06 UTC
List: ruby-dev #37610
Yuguiです。

頂いた判断をもとにざっと実装してみました。

On 12/25/08 2:23 AM, Masatoshi SEKI wrote:
> znzさんの日記 (http://znz.s1.xrea.com/t/?date=20080108) で知ったのですが、
> evalもmagic commentを解釈するのですね。

すっかり忘れてましたが、そうですね。そして、evalは渡された文字列のエン
コーディングよりmagic commentを優先するので、適当にmagic commentが付いた
文字列を生成できればeval結果はmagic commentで解釈されるわけです。

で、
> うーむ。ERB.resultはどうしたものか。ERBもerbもmagic commentを同様に処理する
> べきならERBに渡されたスクリプトの最初のコメントをevalするRubyスクリプトに
> 残してあげれば動きそうな気がする。

magic commentを付加するコードは実は既に成瀬さんが追加してくださっていた
のでした。

で、全部合わせて添付のパッチのようになりました。どうでしょうか。
<%# -*- coding: ENCODING-NAME -*-%>

冒頭のを解釈します。

-- 
Yugui <yugui@yugui.jp>
http://yugui.jp
私は私をDumpする

Attachments (1)

erb-m17n.diff (3.49 KB, text/x-diff)
diff --git a/bin/erb b/bin/erb
index 8541437..8525749 100755
--- a/bin/erb
+++ b/bin/erb
@@ -72,6 +72,11 @@ class ERB
             end
             raise "invalid trim mode #{arg.dump}" unless arg =~ /^[0-2]$/
             trim_mode = arg.to_i
+          when '-E'
+            arg = ARGV.req_arg
+            set_encoding(*arg.split(/:/, 2))
+          when '-U'
+            set_encoding(Encoding::UTF_8, Encoding::UTF_8)
           when '-P'
             disable_percent = true
           when '--help'
@@ -91,12 +96,15 @@ class ERB
   -d               set $DEBUG to true
   -r [library]     load a library
   -S [safe_level]  set $SAFE (0..4)
+  -E ex[:in]       set default external/internal encodings
+  -U               set default encoding to UTF-8.
   -T [trim_mode]   specify trim_mode (0..2, -)
   -P               ignore lines which start with "%"
 EOU
         exit 1
       end
 
+      $<.set_encoding(Encoding::ASCII_8BIT, nil)
       src = $<.read
       filename = $FILENAME
       exit 2 unless src
@@ -105,10 +113,8 @@ EOU
       erb.filename = filename
       if output
         if number
-          l = 1
-          for line in erb.src
-            puts "%3d %s"%[l, line]
-            l += 1
+          erb.src.each_line.with_index do |line, l|
+            puts "%3d %s"%[l+1, line]
           end
         else
           puts erb.src
@@ -118,6 +124,19 @@ EOU
       end
     end
     module_function :run
+
+    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?
+      [$stdin, $stdout, $stderr].each do |io|
+        io.set_encoding(extern, intern)
+      end
+    ensure
+      $VERBOSE = verbose
+    end
+    module_function :set_encoding
+    class << self; private :set_encoding; end
   end
 end
 
diff --git a/lib/erb.rb b/lib/erb.rb
index c879941..006de63 100644
--- a/lib/erb.rb
+++ b/lib/erb.rb
@@ -58,6 +58,24 @@
 #
 # See the ERB.new and ERB#result methods for more detail.
 #
+# == Character encodings
+#
+# ERB (or ruby code generated by ERB) returns a string in the same
+# character encoding as the input string.  When the input string has
+# a magic comment, however, it returns a string in the encoding specified
+# by the magic comment.
+#
+#   # -*- coding: UTF-8 -*-
+#   require 'erb'
+#
+#   template = ERB.new <<EOF
+#   <%#-*- coding: Big5 -*-%>
+#     \_\_ENCODING\_\_ is <%= \_\_ENCODING\_\_ %>.
+#   EOF
+#   puts template.result
+#
+# <em>Prints:</em> \_\_ENCODING\_\_ is Big5.
+#
 #
 # == Examples
 #
@@ -517,10 +535,13 @@ class ERB
     end
 
     def compile(s)
-      out = Buffer.new(self, s.encoding)
+      enc = s.encoding
+      s = s.dup.force_encoding(Encoding::ASCII_8BIT)
+      enc = detect_magic_comment(s) || enc
+      out = Buffer.new(self, enc)
 
       content = ''
-      scanner = make_scanner(s.dup.force_encoding("ASCII-8BIT"))
+      scanner = make_scanner(s) 
       scanner.scan do |token|
 	if scanner.stag.nil?
 	  case token
@@ -613,6 +634,18 @@ class ERB
     end
     attr_reader :percent, :trim_mode
     attr_accessor :put_cmd, :insert_cmd, :pre_cmd, :post_cmd
+
+    private
+    def detect_magic_comment(s)
+      if /\A<%#(.*)%>/ =~ s or (@percent and /\A%#(.*)/ =~ s)
+	comment = $1
+	comment = $1 if comment[/-\*-\s*(.*?)\s*-*-$/]
+	if %r"coding\s*[=:]\s*([[:alnum:]\-_]+)" =~ comment
+	  enc = $1.sub(/-(?:mac|dos|unix)/i, '')
+	  enc = Encoding.find(enc)
+	end
+      end
+    end
   end
 end
 

In This Thread