Project

General

Profile

Actions

Feature #442

closed

name referencing in sprintf

Added by mame (Yusuke Endoh) about 13 years ago. Updated over 10 years ago.

Status:
Closed
Priority:
Normal
[ruby-dev:35851]

Description

=begin
遠藤です。

1.9 では正規表現で名前を使った参照ができるので、sprintf でも
名前を使った参照ができると便利じゃないでしょうか。

$ ./ruby -e 'puts "%d : %f" % { :foo => 1, :bar => 2 }'
1 : 2.000000

$ ./ruby -e 'printf("%d : %f\n", :foo => 1, :bar => 2)'
1 : 2.000000

あまりテストしていませんが、たたき台の実装です。

Index: sprintf.c
===================================================================
--- sprintf.c (revision 18638)
+++ sprintf.c (working copy)
@@ -103,18 +103,28 @@
} while (0)

#define GETARG() (nextvalue != Qundef ? nextvalue : \

  • posarg < 0 ? \
  • posarg == -1 ? \ (rb_raise(rb_eArgError, "unnumbered(%d) mixed with numbered", nextarg), 0) : \
  • posarg == -2 ? \
  • (rb_raise(rb_eArgError, "unnumbered(%d) mixed with named", nextarg), 0) : \ (posarg = nextarg++, GETNTHARG(posarg)))

#define GETPOSARG(n) (posarg > 0 ? \
(rb_raise(rb_eArgError, "numbered(%d) after unnumbered(%d)", n,
posarg), 0) : \

  • posarg == -2 ? \
  • (rb_raise(rb_eArgError, "numbered(%d) after named", n), 0) : \ ((n < 1) ? (rb_raise(rb_eArgError, "invalid index - %d$", n), 0) : \ (posarg = -1, GETNTHARG(n))))

#define GETNTHARG(nth) \
((nth >= argc) ? (rb_raise(rb_eArgError, "too few arguments"), 0)
: argv[nth])

+#define GETNAMEARG(id) (posarg > 0 ? \

  • (rb_raise(rb_eArgError, "named after unnumbered(%d)", posarg), 0) : \
  • posarg == -1 ? \
  • (rb_raise(rb_eArgError, "named after numbered"), 0) : \
  • rb_hash_aref(get_hash(&hash, argc, argv), id)) + #define GETNUM(n, val) \ for (; p < end && rb_enc_isdigit(*p, enc); p++) { \ int next_n = 10 * n + (*p - '0'); \ @@ -141,7 +151,22 @@ val = NUM2INT(tmp); \ } while (0)

+static VALUE
+get_hash(volatile VALUE *hash, int argc, const VALUE *argv)
+{

  • VALUE tmp;

  • if (*hash != Qundef) return *hash;

  • if (argc != 2) {

  • rb_raise(rb_eArgError, "one hash required");

  • }

  • tmp = rb_check_convert_type(argv[1], T_HASH, "Hash", "to_hash");

  • if (NIL_P(tmp)) {

  • rb_raise(rb_eArgError, "one hash required");

  • }

  • return (hash = tmp);
    +}
    +
    /

    • call-seq:
    • format(format_string [, arguments...] ) => string @@ -412,6 +437,7 @@ VALUE nextvalue; VALUE tmp; VALUE str;
  • volatile VALUE hash = Qundef;

#define CHECK_FOR_WIDTH(f) \
if ((f) & FWIDTH) { \
@@ -513,6 +539,22 @@
flags |= FWIDTH;
goto retry;

  • case '<':
  • {
  • const char *start = p;
  • ID id;
  • for (; p < end && *p != '>'; ) {
  • p += rb_enc_mbclen(p, end, enc);
  • }
  • if (p >= end) {
  • rb_raise(rb_eArgError, "malformed name - unmatched parenthesis");
  • }
  • id = rb_intern3(start + 1, p - start - 1, enc);
  • nextvalue = GETNAMEARG(ID2SYM(id));
  • p++;
  • goto retry;
  • } + case '*': CHECK_FOR_WIDTH(flags); flags |= FWIDTH;

--
Yusuke ENDOH mame@tsg.ne.jp
=end


Related issues

Related to Ruby master - Bug #3574: Missing documentation for sprintf named argument supportClosed07/15/2010Actions
Actions

Also available in: Atom PDF