@@ -150,6 +150,131 @@ func (a String) M__ge__(other Object) (Object, error) {
150150
151151// % operator
152152
153+ /*
154+
155+ 4.7.2. printf-style String Formatting
156+
157+ Note The formatting operations described here exhibit a variety of
158+ quirks that lead to a number of common errors (such as failing to
159+ display tuples and dictionaries correctly). Using the newer
160+ str.format() interface helps avoid these errors, and also provides a
161+ generally more powerful, flexible and extensible approach to
162+ formatting text.
163+
164+ String objects have one unique built-in operation: the % operator
165+ (modulo). This is also known as the string formatting or interpolation
166+ operator. Given format % values (where format is a string), %
167+ conversion specifications in format are replaced with zero or more
168+ elements of values. The effect is similar to using the sprintf() in
169+ the C language.
170+
171+ If format requires a single argument, values may be a single non-tuple
172+ object. [5] Otherwise, values must be a tuple with exactly the number
173+ of items specified by the format string, or a single mapping object
174+ (for example, a dictionary).
175+
176+ A conversion specifier contains two or more characters and has the
177+ following components, which must occur in this order:
178+
179+ The '%' character, which marks the start of the specifier.
180+
181+ Mapping key (optional), consisting of a parenthesised sequence of
182+ characters (for example, (somename)).
183+
184+ Conversion flags (optional), which affect the result of some
185+ conversion types.
186+
187+ Minimum field width (optional). If specified as an '*' (asterisk), the
188+ actual width is read from the next element of the tuple in values, and
189+ the object to convert comes after the minimum field width and optional
190+ precision.
191+
192+ Precision (optional), given as a '.' (dot) followed by the
193+ precision. If specified as '*' (an asterisk), the actual precision is
194+ read from the next element of the tuple in values, and the value to
195+ convert comes after the precision.
196+
197+ Length modifier (optional).
198+
199+ Conversion type.
200+
201+ When the right argument is a dictionary (or other mapping type), then
202+ the formats in the string must include a parenthesised mapping key
203+ into that dictionary inserted immediately after the '%' character. The
204+ mapping key selects the value to be formatted from the mapping. For
205+ example:
206+
207+ >>>
208+ >>> print('%(language)s has %(number)03d quote types.' %
209+ ... {'language': "Python", "number": 2})
210+ Python has 002 quote types.
211+
212+ In this case no * specifiers may occur in a format (since they require
213+ a sequential parameter list).
214+
215+ The conversion flag characters are:
216+
217+ Flag Meaning
218+ '#' The value conversion will use the “alternate form” (where defined below).
219+ '0' The conversion will be zero padded for numeric values.
220+ '-' The converted value is left adjusted (overrides the '0' conversion if both are given).
221+ ' ' (a space) A blank should be left before a positive number (or empty string) produced by a signed conversion.
222+ '+' A sign character ('+' or '-') will precede the conversion (overrides a “space” flag).
223+
224+ A length modifier (h, l, or L) may be present, but is ignored as it is
225+ not necessary for Python – so e.g. %ld is identical to %d.
226+
227+ The conversion types are:
228+
229+ Conversion Meaning Notes
230+ 'd' Signed integer decimal.
231+ 'i' Signed integer decimal.
232+ 'o' Signed octal value. (1)
233+ 'u' Obsolete type – it is identical to 'd'. (7)
234+ 'x' Signed hexadecimal (lowercase). (2)
235+ 'X' Signed hexadecimal (uppercase). (2)
236+ 'e' Floating point exponential format (lowercase). (3)
237+ 'E' Floating point exponential format (uppercase). (3)
238+ 'f' Floating point decimal format. (3)
239+ 'F' Floating point decimal format. (3)
240+ 'g' Floating point format. Uses lowercase exponential format if exponent is less than -4 or not less than precision, decimal format otherwise. (4)
241+ 'G' Floating point format. Uses uppercase exponential format if exponent is less than -4 or not less than precision, decimal format otherwise. (4)
242+ 'c' Single character (accepts integer or single character string).
243+ 'r' String (converts any Python object using repr()). (5)
244+ 's' String (converts any Python object using str()). (5)
245+ 'a' String (converts any Python object using ascii()). (5)
246+ '%' No argument is converted, results in a '%' character in the result.
247+ Notes:
248+
249+ The alternate form causes a leading zero ('0') to be inserted between
250+ left-hand padding and the formatting of the number if the leading
251+ character of the result is not already a zero.
252+
253+ The alternate form causes a leading '0x' or '0X' (depending on whether
254+ the 'x' or 'X' format was used) to be inserted between left-hand
255+ padding and the formatting of the number if the leading character of
256+ the result is not already a zero.
257+
258+ The alternate form causes the result to always contain a decimal
259+ point, even if no digits follow it.
260+
261+ The precision determines the number of digits after the decimal point
262+ and defaults to 6.
263+
264+ The alternate form causes the result to always contain a decimal
265+ point, and trailing zeroes are not removed as they would otherwise be.
266+
267+ The precision determines the number of significant digits before and
268+ after the decimal point and defaults to 6.
269+
270+ If precision is N, the output is truncated to N characters.
271+
272+ See PEP 237. Since Python strings have an explicit length, %s
273+ conversions do not assume that '\0' is the end of the string.
274+
275+ Changed in version 3.1: %f conversions for numbers whose absolute
276+ value is over 1e50 are no longer replaced by %g conversions.
277+ */
153278func (a String ) M__mod__ (other Object ) (Object , error ) {
154279 var values Tuple
155280 switch b := other .(type ) {
@@ -159,7 +284,14 @@ func (a String) M__mod__(other Object) (Object, error) {
159284 values = Tuple {other }
160285 }
161286 // FIXME not a full implementation ;-)
162- return String (fmt .Sprintf ("%s %#v" , a , values )), nil
287+ params := make ([]interface {}, len (values ))
288+ for i := range values {
289+ params [i ] = values [i ]
290+ }
291+ s := string (a )
292+ s = strings .Replace (s , "%s" , "%v" , - 1 )
293+ s = strings .Replace (s , "%r" , "%#v" , - 1 )
294+ return String (fmt .Sprintf (s , params ... )), nil
163295}
164296
165297func (a String ) M__rmod__ (other Object ) (Object , error ) {
0 commit comments