56de8c005f2b969c20ad220f1d2269c23c0c870e
[packages/precise/mcollective.git] / lib / mcollective / vendor / i18n / lib / i18n / core_ext / string / interpolate.rb
1 # This backports the Ruby 1.9 String interpolation syntax to Ruby 1.8.
2 #
3 # This backport has been shipped with I18n for a number of versions. Meanwhile
4 # Rails has started to rely on it and we are going to move it to ActiveSupport.
5 # See https://rails.lighthouseapp.com/projects/8994/tickets/6013-move-19-string-interpolation-syntax-backport-from-i18n-to-activesupport
6 #
7 # Once the above patch has been applied to Rails the following code will be
8 # removed from I18n.
9
10 =begin
11   heavily based on Masao Mutoh's gettext String interpolation extension
12   http://github.com/mutoh/gettext/blob/f6566738b981fe0952548c421042ad1e0cdfb31e/lib/gettext/core_ext/string.rb
13   Copyright (C) 2005-2009 Masao Mutoh
14   You may redistribute it and/or modify it under the same license terms as Ruby.
15 =end
16
17 begin
18   raise ArgumentError if ("a %{x}" % {:x=>'b'}) != 'a b'
19 rescue ArgumentError
20   # KeyError is raised by String#% when the string contains a named placeholder
21   # that is not contained in the given arguments hash. Ruby 1.9 includes and
22   # raises this exception natively. We define it to mimic Ruby 1.9's behaviour
23   # in Ruby 1.8.x
24   class KeyError < IndexError
25     def initialize(message = nil)
26       super(message || "key not found")
27     end
28   end unless defined?(KeyError)
29
30   # Extension for String class. This feature is included in Ruby 1.9 or later but not occur TypeError.
31   #
32   # String#% method which accept "named argument". The translator can know
33   # the meaning of the msgids using "named argument" instead of %s/%d style.
34   class String
35     # For older ruby versions, such as ruby-1.8.5
36     alias :bytesize :size unless instance_methods.find {|m| m.to_s == 'bytesize'}
37     alias :interpolate_without_ruby_19_syntax :% # :nodoc:
38
39     INTERPOLATION_PATTERN = Regexp.union(
40       /%\{(\w+)\}/,                               # matches placeholders like "%{foo}"
41       /%<(\w+)>(.*?\d*\.?\d*[bBdiouxXeEfgGcps])/  # matches placeholders like "%<foo>.d"
42     )
43
44     INTERPOLATION_PATTERN_WITH_ESCAPE = Regexp.union(
45       /%%/,
46       INTERPOLATION_PATTERN
47     )
48
49     # % uses self (i.e. the String) as a format specification and returns the
50     # result of applying it to the given arguments. In other words it interpolates
51     # the given arguments to the string according to the formats the string
52     # defines.
53     #
54     # There are three ways to use it:
55     #
56     # * Using a single argument or Array of arguments.
57     #
58     #   This is the default behaviour of the String class. See Kernel#sprintf for
59     #   more details about the format string.
60     #
61     #   Example:
62     #
63     #     "%d %s" % [1, "message"]
64     #     # => "1 message"
65     #
66     # * Using a Hash as an argument and unformatted, named placeholders.
67     #
68     #   When you pass a Hash as an argument and specify placeholders with %{foo}
69     #   it will interpret the hash values as named arguments.
70     #
71     #   Example:
72     #
73     #     "%{firstname}, %{lastname}" % {:firstname => "Masao", :lastname => "Mutoh"}
74     #     # => "Masao Mutoh"
75     #
76     # * Using a Hash as an argument and formatted, named placeholders.
77     #
78     #   When you pass a Hash as an argument and specify placeholders with %<foo>d
79     #   it will interpret the hash values as named arguments and format the value
80     #   according to the formatting instruction appended to the closing >.
81     #
82     #   Example:
83     #
84     #     "%<integer>d, %<float>.1f" % { :integer => 10, :float => 43.4 }
85     #     # => "10, 43.3"
86     def %(args)
87       if args.kind_of?(Hash)
88         dup.gsub(INTERPOLATION_PATTERN_WITH_ESCAPE) do |match|
89           if match == '%%'
90             '%'
91           else
92             key = ($1 || $2).to_sym
93             raise KeyError unless args.has_key?(key)
94             $3 ? sprintf("%#{$3}", args[key]) : args[key]
95           end
96         end
97       elsif self =~ INTERPOLATION_PATTERN
98         raise ArgumentError.new('one hash required')
99       else
100         result = gsub(/%([{<])/, '%%\1')
101         result.send :'interpolate_without_ruby_19_syntax', args
102       end
103     end
104   end
105 end