[前][次][番号順一覧][スレッド一覧]

ruby-changes:40823

From: nobu <ko1@a...>
Date: Sun, 6 Dec 2015 15:25:30 +0900 (JST)
Subject: [ruby-changes:40823] nobu:r52902 (trunk): console.c: console_getpass

nobu	2015-12-06 15:25:10 +0900 (Sun, 06 Dec 2015)

  New Revision: 52902

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=52902

  Log:
    console.c: console_getpass
    
    * ext/io/console/console.c (console_getpass): add IO#getpass
      method.

  Modified files:
    trunk/ChangeLog
    trunk/ext/io/console/console.c
    trunk/test/io/console/test_io_console.rb
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 52901)
+++ ChangeLog	(revision 52902)
@@ -1,3 +1,8 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Sun Dec  6 15:25:06 2015  Nobuyoshi Nakada  <nobu@r...>
+
+	* ext/io/console/console.c (console_getpass): add IO#getpass
+	  method.
+
 Sun Dec  6 08:39:05 2015  SHIBATA Hiroshi  <hsbt@r...>
 
 	* ext/json/json.gemspec: bump version to json 1.8.3. CRuby already contained
Index: ext/io/console/console.c
===================================================================
--- ext/io/console/console.c	(revision 52901)
+++ ext/io/console/console.c	(revision 52902)
@@ -73,7 +73,7 @@ getattr(int fd, conmode *t) https://github.com/ruby/ruby/blob/trunk/ext/io/console/console.c#L73
 #define SET_LAST_ERROR (0)
 #endif
 
-static ID id_getc, id_console, id_close, id_min, id_time;
+static ID id_getc, id_gets, id_console, id_close, id_min, id_time;
 
 #ifndef HAVE_RB_F_SEND
 static ID id___send__;
@@ -845,6 +845,85 @@ io_getch(int argc, VALUE *argv, VALUE io https://github.com/ruby/ruby/blob/trunk/ext/io/console/console.c#L845
     return rb_funcall2(io, id_getc, argc, argv);
 }
 
+static VALUE
+puts_call(VALUE io)
+{
+    return rb_io_write(io, rb_default_rs);
+}
+
+static VALUE
+getpass_call(VALUE io)
+{
+    return ttymode(io, rb_io_gets, set_noecho, NULL);
+}
+
+static VALUE
+write_io(VALUE io)
+{
+    VALUE wio = rb_io_get_write_io(io);
+    if (wio == io && io == rb_stdin) wio = rb_stdout;
+    return wio;
+}
+
+static void
+prompt(int argc, VALUE *argv, VALUE io)
+{
+    if (argc > 0 && !NIL_P(argv[0])) {
+	VALUE str = argv[0];
+	StringValueCStr(str);
+	rb_check_safe_obj(str);
+	rb_io_write(io, str);
+    }
+}
+
+static VALUE
+str_chomp(VALUE str)
+{
+    if (!NIL_P(str)) {
+	str = rb_funcallv(str, rb_intern("chomp!"), 0, 0);
+    }
+    return str;
+}
+
+/*
+ * call-seq:
+ *   io.getpass(prompt=nil)       -> string
+ *
+ * Reads and returns a line without echo back.
+ * Prints +prompt+ unless it is +nil+.
+ *
+ * You must require 'io/console' to use this method.
+ */
+static VALUE
+console_getpass(int argc, VALUE *argv, VALUE io)
+{
+    VALUE str, wio;
+
+    rb_check_arity(argc, 0, 1);
+    wio = write_io(io);
+    prompt(argc, argv, wio);
+    str = rb_ensure(getpass_call, io, puts_call, wio);
+    return str_chomp(str);
+}
+
+/*
+ * call-seq:
+ *   io.getpass(prompt=nil)       -> string
+ *
+ * See IO#getpass.
+ */
+static VALUE
+io_getpass(int argc, VALUE *argv, VALUE io)
+{
+    VALUE str;
+
+    rb_check_arity(argc, 0, 1);
+    prompt(argc, argv, io);
+    str = str_chomp(rb_funcallv(io, id_gets, 0, 0));
+    puts_call(io);
+    return str;
+}
+
 /*
  * IO console methods
  */
@@ -853,6 +932,7 @@ Init_console(void) https://github.com/ruby/ruby/blob/trunk/ext/io/console/console.c#L932
 {
 #undef rb_intern
     id_getc = rb_intern("getc");
+    id_gets = rb_intern("gets");
     id_console = rb_intern("console");
     id_close = rb_intern("close");
     id_min = rb_intern("min");
@@ -884,9 +964,11 @@ InitVM_console(void) https://github.com/ruby/ruby/blob/trunk/ext/io/console/console.c#L964
     rb_define_method(rb_cIO, "cursor", console_cursor_pos, 0);
     rb_define_method(rb_cIO, "cursor=", console_cursor_set, 1);
     rb_define_method(rb_cIO, "pressed?", console_key_pressed_p, 1);
+    rb_define_method(rb_cIO, "getpass", console_getpass, -1);
     rb_define_singleton_method(rb_cIO, "console", console_dev, -1);
     {
 	VALUE mReadable = rb_define_module_under(rb_cIO, "generic_readable");
 	rb_define_method(mReadable, "getch", io_getch, -1);
+	rb_define_method(mReadable, "getpass", io_getpass, -1);
     }
 }
Index: test/io/console/test_io_console.rb
===================================================================
--- test/io/console/test_io_console.rb	(revision 52901)
+++ test/io/console/test_io_console.rb	(revision 52902)
@@ -180,6 +180,20 @@ class TestIO_Console < Test::Unit::TestC https://github.com/ruby/ruby/blob/trunk/test/io/console/test_io_console.rb#L180
     }
   end
 
+  def test_getpass
+    th = nil
+    helper {|m, s|
+      th = Thread.start {
+        sleep 0.1
+        s.print "asdf\n"
+      }
+      assert_equal("asdf", m.getpass("> "))
+      assert_equal("\n", s.readpartial(2))
+    }
+  ensure
+    th.join
+  end
+
   def test_iflush
     helper {|m, s|
       m.print "a"

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]