1/************************************************ 2 3 readline.c - GNU Readline module 4 5 $Author: nagachika $ 6 created at: Wed Jan 20 13:59:32 JST 1999 7 8 Copyright (C) 1997-2008 Shugo Maeda 9 Copyright (C) 2008-2009 TAKAO Kouji 10 11 $Id: readline.c 45252 2014-03-02 16:33:36Z nagachika $ 12 13 Contact: 14 - TAKAO Kouji <kouji at takao7 dot net> (current maintainer) 15 16************************************************/ 17 18#ifdef RUBY_EXTCONF_H 19#include RUBY_EXTCONF_H 20#endif 21 22#include "ruby/config.h" 23#include <errno.h> 24#include <stdio.h> 25#include <string.h> 26#ifdef HAVE_READLINE_READLINE_H 27#include <readline/readline.h> 28#endif 29#ifdef HAVE_READLINE_HISTORY_H 30#include <readline/history.h> 31#endif 32#ifdef HAVE_EDITLINE_READLINE_H 33#include <editline/readline.h> 34#endif 35 36#include "ruby/ruby.h" 37#include "ruby/io.h" 38 39#ifdef HAVE_UNISTD_H 40#include <unistd.h> 41#endif 42 43#ifdef HAVE_SYS_STAT_H 44#include <sys/stat.h> 45#endif 46 47static VALUE mReadline; 48 49#define EDIT_LINE_LIBRARY_VERSION "EditLine wrapper" 50#ifndef USE_INSERT_IGNORE_ESCAPE 51# if !defined(HAVE_EDITLINE_READLINE_H) && defined(RL_PROMPT_START_IGNORE) && defined(RL_PROMPT_END_IGNORE) 52# define USE_INSERT_IGNORE_ESCAPE 1 53# else 54# define USE_INSERT_IGNORE_ESCAPE 0 55# endif 56#endif 57 58#define COMPLETION_PROC "completion_proc" 59#define COMPLETION_CASE_FOLD "completion_case_fold" 60static ID completion_proc, completion_case_fold; 61#if USE_INSERT_IGNORE_ESCAPE 62static ID id_orig_prompt, id_last_prompt; 63#endif 64#if defined(HAVE_RL_PRE_INPUT_HOOK) 65static ID id_pre_input_hook; 66#endif 67#if defined(HAVE_RL_SPECIAL_PREFIXES) 68static ID id_special_prefixes; 69#endif 70 71#ifndef HAVE_RL_FILENAME_COMPLETION_FUNCTION 72# define rl_filename_completion_function filename_completion_function 73#endif 74#ifndef HAVE_RL_USERNAME_COMPLETION_FUNCTION 75# define rl_username_completion_function username_completion_function 76#endif 77#ifndef HAVE_RL_COMPLETION_MATCHES 78# define rl_completion_matches completion_matches 79#endif 80 81static int (*history_get_offset_func)(int); 82static int (*history_replace_offset_func)(int); 83#ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER 84static int readline_completion_append_character; 85#endif 86 87static char **readline_attempted_completion_function(const char *text, 88 int start, int end); 89 90#define OutputStringValue(str) do {\ 91 SafeStringValue(str);\ 92 (str) = rb_str_conv_enc((str), rb_enc_get(str), rb_locale_encoding());\ 93} while (0)\ 94 95 96/* 97 * Document-class: Readline 98 * 99 * The Readline module provides interface for GNU Readline. 100 * This module defines a number of methods to facilitate completion 101 * and accesses input history from the Ruby interpreter. 102 * This module supported Edit Line(libedit) too. 103 * libedit is compatible with GNU Readline. 104 * 105 * GNU Readline:: http://www.gnu.org/directory/readline.html 106 * libedit:: http://www.thrysoee.dk/editline/ 107 * 108 * Reads one inputted line with line edit by Readline.readline method. 109 * At this time, the facilitatation completion and the key 110 * bind like Emacs can be operated like GNU Readline. 111 * 112 * require "readline" 113 * while buf = Readline.readline("> ", true) 114 * p buf 115 * end 116 * 117 * The content that the user input can be recorded to the history. 118 * The history can be accessed by Readline::HISTORY constant. 119 * 120 * require "readline" 121 * while buf = Readline.readline("> ", true) 122 * p Readline::HISTORY.to_a 123 * print("-> ", buf, "\n") 124 * end 125 * 126 * Most of methods raise SecurityError exception if $SAFE is 4. 127 * 128 * Documented by TAKAO Kouji <kouji at takao7 dot net>. 129 */ 130 131#if defined HAVE_RL_GETC_FUNCTION 132static VALUE readline_instream; 133 134#ifndef HAVE_RL_GETC 135#define rl_getc(f) EOF 136#endif 137 138static int readline_getc(FILE *); 139static int 140readline_getc(FILE *input) 141{ 142 rb_io_t *ifp = 0; 143 VALUE c; 144 if (!readline_instream) return rl_getc(input); 145 GetOpenFile(readline_instream, ifp); 146 if (rl_instream != ifp->stdio_file) return rl_getc(input); 147#if defined(_WIN32) 148 { 149 INPUT_RECORD ir; 150 int n; 151 static int prior_key = '0'; 152 for (;;) { 153 if (prior_key > 0xff) { 154 prior_key = rl_getc(ifp->stdio_file); 155 return prior_key; 156 } 157 if (PeekConsoleInput((HANDLE)_get_osfhandle(ifp->fd), &ir, 1, &n)) { 158 if (n == 1) { 159 if (ir.EventType == KEY_EVENT && ir.Event.KeyEvent.bKeyDown) { 160 prior_key = rl_getc(ifp->stdio_file); 161 return prior_key; 162 } else { 163 ReadConsoleInput((HANDLE)_get_osfhandle(ifp->fd), &ir, 1, &n); 164 } 165 } else { 166 HANDLE h = (HANDLE)_get_osfhandle(ifp->fd); 167 rb_w32_wait_events(&h, 1, INFINITE); 168 } 169 } else { 170 break; 171 } 172 } 173 } 174#endif 175 c = rb_io_getbyte(readline_instream); 176 if (NIL_P(c)) return EOF; 177#ifdef ESC 178 if (c == INT2FIX(ESC) && 179 RL_ISSTATE(RL_STATE_ISEARCH) && /* isn't needed in other states? */ 180 rb_io_read_pending(ifp)) { 181 int meta = 0; 182 c = rb_io_getbyte(readline_instream); 183 if (FIXNUM_P(c) && isascii(FIX2INT(c))) meta = 1; 184 rb_io_ungetbyte(readline_instream, c); 185 if (meta) rl_execute_next(ESC); 186 return ESC; 187 } 188#endif 189 return FIX2INT(c); 190} 191#elif defined HAVE_RL_EVENT_HOOK 192#define BUSY_WAIT 0 193 194static int readline_event(void); 195static int 196readline_event(void) 197{ 198#if BUSY_WAIT 199 rb_thread_schedule(); 200#else 201 rb_wait_for_single_fd(fileno(rl_instream), RB_WAITFD_IN, NULL); 202 return 0; 203#endif 204} 205#endif 206 207#if USE_INSERT_IGNORE_ESCAPE 208static VALUE 209insert_ignore_escape(VALUE self, VALUE prompt) 210{ 211 VALUE last_prompt, orig_prompt = rb_attr_get(self, id_orig_prompt); 212 int ignoring = 0; 213 const char *s0, *s, *e; 214 long len; 215 static const char ignore_code[2] = {RL_PROMPT_START_IGNORE, RL_PROMPT_END_IGNORE}; 216 217 prompt = rb_str_new_shared(prompt); 218 last_prompt = rb_attr_get(self, id_last_prompt); 219 if (orig_prompt == prompt) return last_prompt; 220 len = RSTRING_LEN(prompt); 221 if (NIL_P(last_prompt)) { 222 last_prompt = rb_str_tmp_new(len); 223 } 224 225 s = s0 = RSTRING_PTR(prompt); 226 e = s0 + len; 227 rb_str_set_len(last_prompt, 0); 228 while (s < e && *s) { 229 switch (*s) { 230 case RL_PROMPT_START_IGNORE: 231 ignoring = -1; 232 rb_str_cat(last_prompt, s0, ++s - s0); 233 s0 = s; 234 break; 235 case RL_PROMPT_END_IGNORE: 236 ignoring = 0; 237 rb_str_cat(last_prompt, s0, ++s - s0); 238 s0 = s; 239 break; 240 case '\033': 241 if (++s < e && *s == '[') { 242 rb_str_cat(last_prompt, s0, s - s0 - 1); 243 s0 = s - 1; 244 while (++s < e && *s) { 245 if (ISALPHA(*s)) { 246 if (!ignoring) { 247 ignoring = 1; 248 rb_str_cat(last_prompt, ignore_code+0, 1); 249 } 250 rb_str_cat(last_prompt, s0, ++s - s0); 251 s0 = s; 252 break; 253 } 254 else if (!('0' <= *s && *s <= '9' || *s == ';')) { 255 break; 256 } 257 } 258 } 259 break; 260 default: 261 if (ignoring > 0) { 262 ignoring = 0; 263 rb_str_cat(last_prompt, ignore_code+1, 1); 264 } 265 s++; 266 break; 267 } 268 } 269 if (ignoring > 0) { 270 ignoring = 0; 271 rb_str_cat(last_prompt, ignore_code+1, 1); 272 } 273 rb_str_cat(last_prompt, s0, s - s0); 274 275 rb_ivar_set(self, id_orig_prompt, prompt); 276 rb_ivar_set(self, id_last_prompt, last_prompt); 277 278 return last_prompt; 279} 280#endif 281 282static VALUE 283readline_get(VALUE prompt) 284{ 285#ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER 286 readline_completion_append_character = rl_completion_append_character; 287#endif 288 return (VALUE)readline((char *)prompt); 289} 290 291/* 292 * call-seq: 293 * Readline.readline(prompt = "", add_hist = false) -> string or nil 294 * 295 * Shows the +prompt+ and reads the inputted line with line editing. 296 * The inputted line is added to the history if +add_hist+ is true. 297 * 298 * Returns nil when the inputted line is empty and user inputs EOF 299 * (Presses ^D on UNIX). 300 * 301 * Raises IOError exception if below conditions are satisfied. 302 * 1. stdin is not tty. 303 * 2. stdin was closed. (errno is EBADF after called isatty(2).) 304 * 305 * This method supports thread. Switchs the thread context when waits 306 * inputting line. 307 * 308 * Supports line edit when inputs line. Provides VI and Emacs editing mode. 309 * Default is Emacs editing mode. 310 * 311 * NOTE: Terminates ruby interpreter and does not return the terminal 312 * status after user pressed '^C' when wait inputting line. 313 * Give 3 examples that avoid it. 314 * 315 * * Catches the Interrupt exception by pressed ^C after returns 316 * terminal status: 317 * 318 * require "readline" 319 * 320 * stty_save = `stty -g`.chomp 321 * begin 322 * while buf = Readline.readline 323 * p buf 324 * end 325 * rescue Interrupt 326 * system("stty", stty_save) 327 * exit 328 * end 329 * end 330 * end 331 * 332 * * Catches the INT signal by pressed ^C after returns terminal 333 * status: 334 * 335 * require "readline" 336 * 337 * stty_save = `stty -g`.chomp 338 * trap("INT") { system "stty", stty_save; exit } 339 * 340 * while buf = Readline.readline 341 * p buf 342 * end 343 * 344 * * Ignores pressing ^C: 345 * 346 * require "readline" 347 * 348 * trap("INT", "SIG_IGN") 349 * 350 * while buf = Readline.readline 351 * p buf 352 * end 353 * 354 * Can make as follows with Readline::HISTORY constant. 355 * It does not record to the history if the inputted line is empty or 356 * the same it as last one. 357 * 358 * require "readline" 359 * 360 * while buf = Readline.readline("> ", true) 361 * # p Readline::HISTORY.to_a 362 * Readline::HISTORY.pop if /^\s*$/ =~ buf 363 * 364 * begin 365 * if Readline::HISTORY[Readline::HISTORY.length-2] == buf 366 * Readline::HISTORY.pop 367 * end 368 * rescue IndexError 369 * end 370 * 371 * # p Readline::HISTORY.to_a 372 * print "-> ", buf, "\n" 373 * end 374 * 375 * Raises SecurityError exception if $SAFE is 4. 376 */ 377static VALUE 378readline_readline(int argc, VALUE *argv, VALUE self) 379{ 380 VALUE tmp, add_hist, result; 381 char *prompt = NULL; 382 char *buff; 383 int status; 384 385 rb_secure(4); 386 if (rb_scan_args(argc, argv, "02", &tmp, &add_hist) > 0) { 387 OutputStringValue(tmp); 388#if USE_INSERT_IGNORE_ESCAPE 389 tmp = insert_ignore_escape(self, tmp); 390 rb_str_locktmp(tmp); 391#endif 392 prompt = RSTRING_PTR(tmp); 393 } 394 395 if (!isatty(fileno(rl_instream)) && errno == EBADF) rb_raise(rb_eIOError, "closed stdin"); 396 if (rl_outstream) { 397 struct stat stbuf; 398 int fd = fileno(rl_outstream); 399 if (fd < 0 || fstat(fd, &stbuf) != 0) { 400 rb_raise(rb_eIOError, "closed stdout"); 401 } 402 } 403 404#ifdef _WIN32 405 rl_prep_terminal(1); 406#endif 407 buff = (char*)rb_protect(readline_get, (VALUE)prompt, &status); 408#if USE_INSERT_IGNORE_ESCAPE 409 if (prompt) { 410 rb_str_unlocktmp(tmp); 411 } 412#endif 413 if (status) { 414#if defined HAVE_RL_CLEANUP_AFTER_SIGNAL 415 /* restore terminal mode and signal handler*/ 416#if defined HAVE_RL_FREE_LINE_STATE 417 rl_free_line_state(); 418#endif 419 rl_cleanup_after_signal(); 420#elif defined HAVE_RL_DEPREP_TERM_FUNCTION 421 /* restore terminal mode */ 422 if (rl_deprep_term_function != NULL) /* NULL in libedit. [ruby-dev:29116] */ 423 (*rl_deprep_term_function)(); 424 else 425#else 426 rl_deprep_terminal(); 427#endif 428 rb_jump_tag(status); 429 } 430 431 if (RTEST(add_hist) && buff) { 432 add_history(buff); 433 } 434 if (buff) { 435 result = rb_locale_str_new_cstr(buff); 436 } 437 else 438 result = Qnil; 439 if (buff) free(buff); 440 return result; 441} 442 443/* 444 * call-seq: 445 * Readline.input = input 446 * 447 * Specifies a File object +input+ that is input stream for 448 * Readline.readline method. 449 * 450 * Raises SecurityError exception if $SAFE is 4. 451 */ 452static VALUE 453readline_s_set_input(VALUE self, VALUE input) 454{ 455 rb_io_t *ifp; 456 457 rb_secure(4); 458 Check_Type(input, T_FILE); 459 GetOpenFile(input, ifp); 460 rl_instream = rb_io_stdio_file(ifp); 461#ifdef HAVE_RL_GETC_FUNCTION 462 readline_instream = input; 463#endif 464 return input; 465} 466 467/* 468 * call-seq: 469 * Readline.output = output 470 * 471 * Specifies a File object +output+ that is output stream for 472 * Readline.readline method. 473 * 474 * Raises SecurityError exception if $SAFE is 4. 475 */ 476static VALUE 477readline_s_set_output(VALUE self, VALUE output) 478{ 479 rb_io_t *ofp; 480 481 rb_secure(4); 482 Check_Type(output, T_FILE); 483 GetOpenFile(output, ofp); 484 rl_outstream = rb_io_stdio_file(ofp); 485 return output; 486} 487 488#if defined(HAVE_RL_PRE_INPUT_HOOK) 489/* 490 * call-seq: 491 * Readline.pre_input_hook = proc 492 * 493 * Specifies a Proc object +proc+ to call after the first prompt has 494 * been printed and just before readline starts reading input 495 * characters. 496 * 497 * See GNU Readline's rl_pre_input_hook variable. 498 * 499 * Raises ArgumentError if +proc+ does not respond to the call method. 500 * 501 * Raises SecurityError if $SAFE is 4. 502 */ 503static VALUE 504readline_s_set_pre_input_hook(VALUE self, VALUE proc) 505{ 506 rb_secure(4); 507 if (!NIL_P(proc) && !rb_respond_to(proc, rb_intern("call"))) 508 rb_raise(rb_eArgError, "argument must respond to `call'"); 509 return rb_ivar_set(mReadline, id_pre_input_hook, proc); 510} 511 512/* 513 * call-seq: 514 * Readline.pre_input_hook -> proc 515 * 516 * Returns a Proc object +proc+ to call after the first prompt has 517 * been printed and just before readline starts reading input 518 * characters. The default is nil. 519 * 520 * Raises SecurityError if $SAFE is 4. 521 */ 522static VALUE 523readline_s_get_pre_input_hook(VALUE self) 524{ 525 rb_secure(4); 526 return rb_attr_get(mReadline, id_pre_input_hook); 527} 528 529static int 530readline_pre_input_hook(void) 531{ 532 VALUE proc; 533 534 proc = rb_attr_get(mReadline, id_pre_input_hook); 535 if (!NIL_P(proc)) 536 rb_funcall(proc, rb_intern("call"), 0); 537 return 0; 538} 539#else 540#define readline_s_set_pre_input_hook rb_f_notimplement 541#define readline_s_get_pre_input_hook rb_f_notimplement 542#endif 543 544#if defined(HAVE_RL_INSERT_TEXT) 545/* 546 * call-seq: 547 * Readline.insert_text(string) -> self 548 * 549 * Insert text into the line at the current cursor position. 550 * 551 * See GNU Readline's rl_insert_text function. 552 * 553 * Raises SecurityError if $SAFE is 4. 554 */ 555static VALUE 556readline_s_insert_text(VALUE self, VALUE str) 557{ 558 rb_secure(4); 559 OutputStringValue(str); 560 rl_insert_text(RSTRING_PTR(str)); 561 return self; 562} 563#else 564#define readline_s_insert_text rb_f_notimplement 565#endif 566 567#if defined(HAVE_RL_REDISPLAY) 568/* 569 * call-seq: 570 * Readline.redisplay -> self 571 * 572 * Change what's displayed on the screen to reflect the current 573 * contents. 574 * 575 * See GNU Readline's rl_redisplay function. 576 * 577 * Raises SecurityError if $SAFE is 4. 578 */ 579static VALUE 580readline_s_redisplay(VALUE self) 581{ 582 rb_secure(4); 583 rl_redisplay(); 584 return self; 585} 586#else 587#define readline_s_redisplay rb_f_notimplement 588#endif 589 590/* 591 * call-seq: 592 * Readline.completion_proc = proc 593 * 594 * Specifies a Proc object +proc+ to determine completion behavior. It 595 * should take input string and return an array of completion candidates. 596 * 597 * The default completion is used if +proc+ is nil. 598 * 599 * The String that is passed to the Proc depends on the 600 * Readline.completer_word_break_characters property. By default the word 601 * under the cursor is passed to the Proc. For example, if the input is "foo 602 * bar" then only "bar" would be passed to the completion Proc. 603 * 604 * Upon successful completion the Readline.completion_append_character will be 605 * appended to the input so the user can start working on their next argument. 606 * 607 * = Examples 608 * 609 * == Completion for a Static List 610 * 611 * require 'readline' 612 * 613 * LIST = [ 614 * 'search', 'download', 'open', 615 * 'help', 'history', 'quit', 616 * 'url', 'next', 'clear', 617 * 'prev', 'past' 618 * ].sort 619 * 620 * comp = proc { |s| LIST.grep(/^#{Regexp.escape(s)}/) } 621 * 622 * Readline.completion_append_character = " " 623 * Readline.completion_proc = comp 624 * 625 * while line = Readline.readline('> ', true) 626 * p line 627 * end 628 * 629 * == Completion For Directory Contents 630 * 631 * require 'readline' 632 * 633 * Readline.completion_append_character = " " 634 * Readline.completion_proc = Proc.new do |str| 635 * Dir[str+'*'].grep(/^#{Regexp.escape(str)}/) 636 * end 637 * 638 * while line = Readline.readline('> ', true) 639 * p line 640 * end 641 * 642 * = Autocomplete strategies 643 * 644 * When working with auto-complete there are some strategies that work well. 645 * To get some ideas you can take a look at the 646 * completion.rb[http://svn.ruby-lang.org/repos/ruby/trunk/lib/irb/completion.rb] 647 * file for irb. 648 * 649 * The common strategy is to take a list of possible completions and filter it 650 * down to those completions that start with the user input. In the above 651 * examples Enumerator.grep is used. The input is escaped to prevent Regexp 652 * special characters from interfering with the matching. 653 * 654 * It may also be helpful to use the Abbrev library to generate completions. 655 * 656 * Raises ArgumentError if +proc+ does not respond to the call method. 657 * 658 * Raises SecurityError if $SAFE is 4. 659 */ 660static VALUE 661readline_s_set_completion_proc(VALUE self, VALUE proc) 662{ 663 rb_secure(4); 664 if (!NIL_P(proc) && !rb_respond_to(proc, rb_intern("call"))) 665 rb_raise(rb_eArgError, "argument must respond to `call'"); 666 return rb_ivar_set(mReadline, completion_proc, proc); 667} 668 669/* 670 * call-seq: 671 * Readline.completion_proc -> proc 672 * 673 * Returns the completion Proc object. 674 * 675 * Raises SecurityError exception if $SAFE is 4. 676 */ 677static VALUE 678readline_s_get_completion_proc(VALUE self) 679{ 680 rb_secure(4); 681 return rb_attr_get(mReadline, completion_proc); 682} 683 684/* 685 * call-seq: 686 * Readline.completion_case_fold = bool 687 * 688 * Sets whether or not to ignore case on completion. 689 * 690 * Raises SecurityError exception if $SAFE is 4. 691 */ 692static VALUE 693readline_s_set_completion_case_fold(VALUE self, VALUE val) 694{ 695 rb_secure(4); 696 return rb_ivar_set(mReadline, completion_case_fold, val); 697} 698 699/* 700 * call-seq: 701 * Readline.completion_case_fold -> bool 702 * 703 * Returns true if completion ignores case. If no, returns false. 704 * 705 * NOTE: Returns the same object that is specified by 706 * Readline.completion_case_fold= method. 707 * 708 * require "readline" 709 * 710 * Readline.completion_case_fold = "This is a String." 711 * p Readline.completion_case_fold # => "This is a String." 712 * 713 * Raises SecurityError exception if $SAFE is 4. 714 */ 715static VALUE 716readline_s_get_completion_case_fold(VALUE self) 717{ 718 rb_secure(4); 719 return rb_attr_get(mReadline, completion_case_fold); 720} 721 722#ifdef HAVE_RL_LINE_BUFFER 723/* 724 * call-seq: 725 * Readline.line_buffer -> string 726 * 727 * Returns the full line that is being edited. This is useful from 728 * within the complete_proc for determining the context of the 729 * completion request. 730 * 731 * The length of +Readline.line_buffer+ and GNU Readline's rl_end are 732 * same. 733 */ 734static VALUE 735readline_s_get_line_buffer(VALUE self) 736{ 737 rb_secure(4); 738 if (rl_line_buffer == NULL) 739 return Qnil; 740 return rb_locale_str_new_cstr(rl_line_buffer); 741} 742#else 743#define readline_s_get_line_buffer rb_f_notimplement 744#endif 745 746#ifdef HAVE_RL_POINT 747/* 748 * call-seq: 749 * Readline.point -> int 750 * 751 * Returns the index of the current cursor position in 752 * +Readline.line_buffer+. 753 * 754 * The index in +Readline.line_buffer+ which matches the start of 755 * input-string passed to completion_proc is computed by subtracting 756 * the length of input-string from +Readline.point+. 757 * 758 * start = (the length of input-string) - Readline.point 759 */ 760static VALUE 761readline_s_get_point(VALUE self) 762{ 763 rb_secure(4); 764 return INT2NUM(rl_point); 765} 766#else 767#define readline_s_get_point rb_f_notimplement 768#endif 769 770static char ** 771readline_attempted_completion_function(const char *text, int start, int end) 772{ 773 VALUE proc, ary, temp; 774 char **result; 775 int case_fold; 776 long i, matches; 777 rb_encoding *enc; 778 VALUE encobj; 779 780 proc = rb_attr_get(mReadline, completion_proc); 781 if (NIL_P(proc)) 782 return NULL; 783#ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER 784 rl_completion_append_character = readline_completion_append_character; 785#endif 786#ifdef HAVE_RL_ATTEMPTED_COMPLETION_OVER 787 rl_attempted_completion_over = 1; 788#endif 789 case_fold = RTEST(rb_attr_get(mReadline, completion_case_fold)); 790 ary = rb_funcall(proc, rb_intern("call"), 1, rb_locale_str_new_cstr(text)); 791 if (!RB_TYPE_P(ary, T_ARRAY)) 792 ary = rb_Array(ary); 793 matches = RARRAY_LEN(ary); 794 if (matches == 0) return NULL; 795 result = (char**)malloc((matches + 2)*sizeof(char*)); 796 if (result == NULL) rb_memerror(); 797 enc = rb_locale_encoding(); 798 encobj = rb_enc_from_encoding(enc); 799 for (i = 0; i < matches; i++) { 800 temp = rb_obj_as_string(RARRAY_PTR(ary)[i]); 801 StringValueCStr(temp); /* must be NUL-terminated */ 802 rb_enc_check(encobj, temp); 803 result[i + 1] = (char*)malloc(RSTRING_LEN(temp) + 1); 804 if (result[i + 1] == NULL) rb_memerror(); 805 strcpy(result[i + 1], RSTRING_PTR(temp)); 806 } 807 result[matches + 1] = NULL; 808 809 if (matches == 1) { 810 result[0] = strdup(result[1]); 811 } 812 else { 813 const char *result1 = result[1]; 814 long low = strlen(result1); 815 816 for (i = 1; i < matches; ++i) { 817 register int c1, c2; 818 long i1, i2, l2; 819 int n1, n2; 820 const char *p2 = result[i + 1]; 821 822 l2 = strlen(p2); 823 for (i1 = i2 = 0; i1 < low && i2 < l2; i1 += n1, i2 += n2) { 824 c1 = rb_enc_codepoint_len(result1 + i1, result1 + low, &n1, enc); 825 c2 = rb_enc_codepoint_len(p2 + i2, p2 + l2, &n2, enc); 826 if (case_fold) { 827 c1 = rb_tolower(c1); 828 c2 = rb_tolower(c2); 829 } 830 if (c1 != c2) break; 831 } 832 833 low = i1; 834 } 835 result[0] = (char*)malloc(low + 1); 836 if (result[0] == NULL) rb_memerror(); 837 strncpy(result[0], result[1], low); 838 result[0][low] = '\0'; 839 } 840 841 return result; 842} 843 844#ifdef HAVE_RL_SET_SCREEN_SIZE 845/* 846 * call-seq: 847 * Readline.set_screen_size(rows, columns) -> self 848 * 849 * Set terminal size to +rows+ and +columns+. 850 * 851 * See GNU Readline's rl_set_screen_size function. 852 * 853 * Raises NotImplementedError if the using readline library does not support. 854 * 855 * Raises SecurityError exception if $SAFE is 4. 856 */ 857static VALUE 858readline_s_set_screen_size(VALUE self, VALUE rows, VALUE columns) 859{ 860 rb_secure(4); 861 rl_set_screen_size(NUM2INT(rows), NUM2INT(columns)); 862 return self; 863} 864#else 865#define readline_s_set_screen_size rb_f_notimplement 866#endif 867 868#ifdef HAVE_RL_GET_SCREEN_SIZE 869/* 870 * call-seq: 871 * Readline.get_screen_size -> [rows, columns] 872 * 873 * Returns the terminal's rows and columns. 874 * 875 * See GNU Readline's rl_get_screen_size function. 876 * 877 * Raises NotImplementedError if the using readline library does not support. 878 * 879 * Raises SecurityError exception if $SAFE is 4. 880 */ 881static VALUE 882readline_s_get_screen_size(VALUE self) 883{ 884 int rows, columns; 885 VALUE res; 886 887 rb_secure(4); 888 rl_get_screen_size(&rows, &columns); 889 res = rb_ary_new(); 890 rb_ary_push(res, INT2NUM(rows)); 891 rb_ary_push(res, INT2NUM(columns)); 892 return res; 893} 894#else 895#define readline_s_get_screen_size rb_f_notimplement 896#endif 897 898#ifdef HAVE_RL_VI_EDITING_MODE 899/* 900 * call-seq: 901 * Readline.vi_editing_mode -> nil 902 * 903 * Specifies VI editing mode. See the manual of GNU Readline for 904 * details of VI editing mode. 905 * 906 * Raises NotImplementedError if the using readline library does not support. 907 * 908 * Raises SecurityError exception if $SAFE is 4. 909 */ 910static VALUE 911readline_s_vi_editing_mode(VALUE self) 912{ 913 rb_secure(4); 914 rl_vi_editing_mode(1,0); 915 return Qnil; 916} 917#else 918#define readline_s_vi_editing_mode rb_f_notimplement 919#endif 920 921#ifdef HAVE_RL_EDITING_MODE 922/* 923 * call-seq: 924 * Readline.vi_editing_mode? -> bool 925 * 926 * Returns true if vi mode is active. Returns false if not. 927 * 928 * Raises NotImplementedError if the using readline library does not support. 929 * 930 * Raises SecurityError exception if $SAFE is 4. 931 */ 932static VALUE 933readline_s_vi_editing_mode_p(VALUE self) 934{ 935 rb_secure(4); 936 return rl_editing_mode == 0 ? Qtrue : Qfalse; 937} 938#else 939#define readline_s_vi_editing_mode_p rb_f_notimplement 940#endif 941 942#ifdef HAVE_RL_EMACS_EDITING_MODE 943/* 944 * call-seq: 945 * Readline.emacs_editing_mode -> nil 946 * 947 * Specifies Emacs editing mode. The default is this mode. See the 948 * manual of GNU Readline for details of Emacs editing mode. 949 * 950 * Raises NotImplementedError if the using readline library does not support. 951 * 952 * Raises SecurityError exception if $SAFE is 4. 953 */ 954static VALUE 955readline_s_emacs_editing_mode(VALUE self) 956{ 957 rb_secure(4); 958 rl_emacs_editing_mode(1,0); 959 return Qnil; 960} 961#else 962#define readline_s_emacs_editing_mode rb_f_notimplement 963#endif 964 965#ifdef HAVE_RL_EDITING_MODE 966/* 967 * call-seq: 968 * Readline.emacs_editing_mode? -> bool 969 * 970 * Returns true if emacs mode is active. Returns false if not. 971 * 972 * Raises NotImplementedError if the using readline library does not support. 973 * 974 * Raises SecurityError exception if $SAFE is 4. 975 */ 976static VALUE 977readline_s_emacs_editing_mode_p(VALUE self) 978{ 979 rb_secure(4); 980 return rl_editing_mode == 1 ? Qtrue : Qfalse; 981} 982#else 983#define readline_s_emacs_editing_mode_p rb_f_notimplement 984#endif 985 986#ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER 987/* 988 * call-seq: 989 * Readline.completion_append_character = char 990 * 991 * Specifies a character to be appended on completion. 992 * Nothing will be appended if an empty string ("") or nil is 993 * specified. 994 * 995 * For example: 996 * require "readline" 997 * 998 * Readline.readline("> ", true) 999 * Readline.completion_append_character = " " 1000 * 1001 * Result: 1002 * > 1003 * Input "/var/li". 1004 * 1005 * > /var/li 1006 * Press TAB key. 1007 * 1008 * > /var/lib 1009 * Completes "b" and appends " ". So, you can continuously input "/usr". 1010 * 1011 * > /var/lib /usr 1012 * 1013 * NOTE: Only one character can be specified. When "string" is 1014 * specified, sets only "s" that is the first. 1015 * 1016 * require "readline" 1017 * 1018 * Readline.completion_append_character = "string" 1019 * p Readline.completion_append_character # => "s" 1020 * 1021 * Raises NotImplementedError if the using readline library does not support. 1022 * 1023 * Raises SecurityError exception if $SAFE is 4. 1024 */ 1025static VALUE 1026readline_s_set_completion_append_character(VALUE self, VALUE str) 1027{ 1028 rb_secure(4); 1029 if (NIL_P(str)) { 1030 rl_completion_append_character = '\0'; 1031 } 1032 else { 1033 OutputStringValue(str); 1034 if (RSTRING_LEN(str) == 0) { 1035 rl_completion_append_character = '\0'; 1036 } else { 1037 rl_completion_append_character = RSTRING_PTR(str)[0]; 1038 } 1039 } 1040 return self; 1041} 1042#else 1043#define readline_s_set_completion_append_character rb_f_notimplement 1044#endif 1045 1046#ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER 1047/* 1048 * call-seq: 1049 * Readline.completion_append_character -> char 1050 * 1051 * Returns a string containing a character to be appended on 1052 * completion. The default is a space (" "). 1053 * 1054 * Raises NotImplementedError if the using readline library does not support. 1055 * 1056 * Raises SecurityError exception if $SAFE is 4. 1057 */ 1058static VALUE 1059readline_s_get_completion_append_character(VALUE self) 1060{ 1061 char buf[1]; 1062 1063 rb_secure(4); 1064 if (rl_completion_append_character == '\0') 1065 return Qnil; 1066 1067 buf[0] = (char) rl_completion_append_character; 1068 return rb_locale_str_new(buf, 1); 1069} 1070#else 1071#define readline_s_get_completion_append_character rb_f_notimplement 1072#endif 1073 1074#ifdef HAVE_RL_BASIC_WORD_BREAK_CHARACTERS 1075/* 1076 * call-seq: 1077 * Readline.basic_word_break_characters = string 1078 * 1079 * Sets the basic list of characters that signal a break between words 1080 * for the completer routine. The default is the characters which 1081 * break words for completion in Bash: " \t\n\"\\'`@$><=;|&{(". 1082 * 1083 * Raises NotImplementedError if the using readline library does not support. 1084 * 1085 * Raises SecurityError exception if $SAFE is 4. 1086 */ 1087static VALUE 1088readline_s_set_basic_word_break_characters(VALUE self, VALUE str) 1089{ 1090 static char *basic_word_break_characters = NULL; 1091 1092 rb_secure(4); 1093 OutputStringValue(str); 1094 if (basic_word_break_characters == NULL) { 1095 basic_word_break_characters = 1096 ALLOC_N(char, RSTRING_LEN(str) + 1); 1097 } 1098 else { 1099 REALLOC_N(basic_word_break_characters, char, RSTRING_LEN(str) + 1); 1100 } 1101 strncpy(basic_word_break_characters, 1102 RSTRING_PTR(str), RSTRING_LEN(str)); 1103 basic_word_break_characters[RSTRING_LEN(str)] = '\0'; 1104 rl_basic_word_break_characters = basic_word_break_characters; 1105 return self; 1106} 1107#else 1108#define readline_s_set_basic_word_break_characters rb_f_notimplement 1109#endif 1110 1111#ifdef HAVE_RL_BASIC_WORD_BREAK_CHARACTERS 1112/* 1113 * call-seq: 1114 * Readline.basic_word_break_characters -> string 1115 * 1116 * Gets the basic list of characters that signal a break between words 1117 * for the completer routine. 1118 * 1119 * Raises NotImplementedError if the using readline library does not support. 1120 * 1121 * Raises SecurityError exception if $SAFE is 4. 1122 */ 1123static VALUE 1124readline_s_get_basic_word_break_characters(VALUE self, VALUE str) 1125{ 1126 rb_secure(4); 1127 if (rl_basic_word_break_characters == NULL) 1128 return Qnil; 1129 return rb_locale_str_new_cstr(rl_basic_word_break_characters); 1130} 1131#else 1132#define readline_s_get_basic_word_break_characters rb_f_notimplement 1133#endif 1134 1135#ifdef HAVE_RL_COMPLETER_WORD_BREAK_CHARACTERS 1136/* 1137 * call-seq: 1138 * Readline.completer_word_break_characters = string 1139 * 1140 * Sets the basic list of characters that signal a break between words 1141 * for rl_complete_internal(). The default is the value of 1142 * Readline.basic_word_break_characters. 1143 * 1144 * Raises NotImplementedError if the using readline library does not support. 1145 * 1146 * Raises SecurityError exception if $SAFE is 4. 1147 */ 1148static VALUE 1149readline_s_set_completer_word_break_characters(VALUE self, VALUE str) 1150{ 1151 static char *completer_word_break_characters = NULL; 1152 1153 rb_secure(4); 1154 OutputStringValue(str); 1155 if (completer_word_break_characters == NULL) { 1156 completer_word_break_characters = 1157 ALLOC_N(char, RSTRING_LEN(str) + 1); 1158 } 1159 else { 1160 REALLOC_N(completer_word_break_characters, char, RSTRING_LEN(str) + 1); 1161 } 1162 strncpy(completer_word_break_characters, 1163 RSTRING_PTR(str), RSTRING_LEN(str)); 1164 completer_word_break_characters[RSTRING_LEN(str)] = '\0'; 1165 rl_completer_word_break_characters = completer_word_break_characters; 1166 return self; 1167} 1168#else 1169#define readline_s_set_completer_word_break_characters rb_f_notimplement 1170#endif 1171 1172#ifdef HAVE_RL_COMPLETER_WORD_BREAK_CHARACTERS 1173/* 1174 * call-seq: 1175 * Readline.completer_word_break_characters -> string 1176 * 1177 * Gets the basic list of characters that signal a break between words 1178 * for rl_complete_internal(). 1179 * 1180 * Raises NotImplementedError if the using readline library does not support. 1181 * 1182 * Raises SecurityError exception if $SAFE is 4. 1183 */ 1184static VALUE 1185readline_s_get_completer_word_break_characters(VALUE self, VALUE str) 1186{ 1187 rb_secure(4); 1188 if (rl_completer_word_break_characters == NULL) 1189 return Qnil; 1190 return rb_locale_str_new_cstr(rl_completer_word_break_characters); 1191} 1192#else 1193#define readline_s_get_completer_word_break_characters rb_f_notimplement 1194#endif 1195 1196#if defined(HAVE_RL_SPECIAL_PREFIXES) 1197/* 1198 * call-seq: 1199 * Readline.special_prefixes = string 1200 * 1201 * Sets the list of characters that are word break characters, but 1202 * should be left in text when it is passed to the completion 1203 * function. Programs can use this to help determine what kind of 1204 * completing to do. For instance, Bash sets this variable to "$@" so 1205 * that it can complete shell variables and hostnames. 1206 * 1207 * See GNU Readline's rl_special_prefixes variable. 1208 * 1209 * Raises NotImplementedError if the using readline library does not support. 1210 * 1211 * Raises SecurityError exception if $SAFE is 4. 1212 */ 1213static VALUE 1214readline_s_set_special_prefixes(VALUE self, VALUE str) 1215{ 1216 rb_secure(4); 1217 if (!NIL_P(str)) { 1218 OutputStringValue(str); 1219 str = rb_str_dup_frozen(str); 1220 RBASIC(str)->klass = 0; 1221 } 1222 rb_ivar_set(mReadline, id_special_prefixes, str); 1223 if (NIL_P(str)) { 1224 rl_special_prefixes = NULL; 1225 } 1226 else { 1227 rl_special_prefixes = RSTRING_PTR(str); 1228 } 1229 return self; 1230} 1231 1232/* 1233 * call-seq: 1234 * Readline.special_prefixes -> string 1235 * 1236 * Gets the list of characters that are word break characters, but 1237 * should be left in text when it is passed to the completion 1238 * function. 1239 * 1240 * See GNU Readline's rl_special_prefixes variable. 1241 * 1242 * Raises NotImplementedError if the using readline library does not support. 1243 * 1244 * Raises SecurityError exception if $SAFE is 4. 1245 */ 1246static VALUE 1247readline_s_get_special_prefixes(VALUE self) 1248{ 1249 VALUE str; 1250 rb_secure(4); 1251 if (rl_special_prefixes == NULL) return Qnil; 1252 str = rb_ivar_get(mReadline, id_special_prefixes); 1253 if (!NIL_P(str)) { 1254 str = rb_str_dup_frozen(str); 1255 RBASIC(str)->klass = rb_cString; 1256 } 1257 return str; 1258} 1259#else 1260#define readline_s_set_special_prefixes rb_f_notimplement 1261#define readline_s_get_special_prefixes rb_f_notimplement 1262#endif 1263 1264#ifdef HAVE_RL_BASIC_QUOTE_CHARACTERS 1265/* 1266 * call-seq: 1267 * Readline.basic_quote_characters = string 1268 * 1269 * Sets a list of quote characters which can cause a word break. 1270 * 1271 * Raises NotImplementedError if the using readline library does not support. 1272 * 1273 * Raises SecurityError exception if $SAFE is 4. 1274 */ 1275static VALUE 1276readline_s_set_basic_quote_characters(VALUE self, VALUE str) 1277{ 1278 static char *basic_quote_characters = NULL; 1279 1280 rb_secure(4); 1281 OutputStringValue(str); 1282 if (basic_quote_characters == NULL) { 1283 basic_quote_characters = 1284 ALLOC_N(char, RSTRING_LEN(str) + 1); 1285 } 1286 else { 1287 REALLOC_N(basic_quote_characters, char, RSTRING_LEN(str) + 1); 1288 } 1289 strncpy(basic_quote_characters, 1290 RSTRING_PTR(str), RSTRING_LEN(str)); 1291 basic_quote_characters[RSTRING_LEN(str)] = '\0'; 1292 rl_basic_quote_characters = basic_quote_characters; 1293 1294 return self; 1295} 1296#else 1297#define readline_s_set_basic_quote_characters rb_f_notimplement 1298#endif 1299 1300#ifdef HAVE_RL_BASIC_QUOTE_CHARACTERS 1301/* 1302 * call-seq: 1303 * Readline.basic_quote_characters -> string 1304 * 1305 * Gets a list of quote characters which can cause a word break. 1306 * 1307 * Raises NotImplementedError if the using readline library does not support. 1308 * 1309 * Raises SecurityError exception if $SAFE is 4. 1310 */ 1311static VALUE 1312readline_s_get_basic_quote_characters(VALUE self, VALUE str) 1313{ 1314 rb_secure(4); 1315 if (rl_basic_quote_characters == NULL) 1316 return Qnil; 1317 return rb_locale_str_new_cstr(rl_basic_quote_characters); 1318} 1319#else 1320#define readline_s_get_basic_quote_characters rb_f_notimplement 1321#endif 1322 1323#ifdef HAVE_RL_COMPLETER_QUOTE_CHARACTERS 1324/* 1325 * call-seq: 1326 * Readline.completer_quote_characters = string 1327 * 1328 * Sets a list of characters which can be used to quote a substring of 1329 * the line. Completion occurs on the entire substring, and within 1330 * the substring Readline.completer_word_break_characters are treated 1331 * as any other character, unless they also appear within this list. 1332 * 1333 * Raises NotImplementedError if the using readline library does not support. 1334 * 1335 * Raises SecurityError exception if $SAFE is 4. 1336 */ 1337static VALUE 1338readline_s_set_completer_quote_characters(VALUE self, VALUE str) 1339{ 1340 static char *completer_quote_characters = NULL; 1341 1342 rb_secure(4); 1343 OutputStringValue(str); 1344 if (completer_quote_characters == NULL) { 1345 completer_quote_characters = 1346 ALLOC_N(char, RSTRING_LEN(str) + 1); 1347 } 1348 else { 1349 REALLOC_N(completer_quote_characters, char, RSTRING_LEN(str) + 1); 1350 } 1351 strncpy(completer_quote_characters, RSTRING_PTR(str), RSTRING_LEN(str)); 1352 completer_quote_characters[RSTRING_LEN(str)] = '\0'; 1353 rl_completer_quote_characters = completer_quote_characters; 1354 1355 return self; 1356} 1357#else 1358#define readline_s_set_completer_quote_characters rb_f_notimplement 1359#endif 1360 1361#ifdef HAVE_RL_COMPLETER_QUOTE_CHARACTERS 1362/* 1363 * call-seq: 1364 * Readline.completer_quote_characters -> string 1365 * 1366 * Gets a list of characters which can be used to quote a substring of 1367 * the line. 1368 * 1369 * Raises NotImplementedError if the using readline library does not support. 1370 * 1371 * Raises SecurityError exception if $SAFE is 4. 1372 */ 1373static VALUE 1374readline_s_get_completer_quote_characters(VALUE self, VALUE str) 1375{ 1376 rb_secure(4); 1377 if (rl_completer_quote_characters == NULL) 1378 return Qnil; 1379 return rb_locale_str_new_cstr(rl_completer_quote_characters); 1380} 1381#else 1382#define readline_s_get_completer_quote_characters rb_f_notimplement 1383#endif 1384 1385#ifdef HAVE_RL_FILENAME_QUOTE_CHARACTERS 1386/* 1387 * call-seq: 1388 * Readline.filename_quote_characters = string 1389 * 1390 * Sets a list of characters that cause a filename to be quoted by the completer 1391 * when they appear in a completed filename. The default is nil. 1392 * 1393 * Raises NotImplementedError if the using readline library does not support. 1394 * 1395 * Raises SecurityError exception if $SAFE is 4. 1396 */ 1397static VALUE 1398readline_s_set_filename_quote_characters(VALUE self, VALUE str) 1399{ 1400 static char *filename_quote_characters = NULL; 1401 1402 rb_secure(4); 1403 OutputStringValue(str); 1404 if (filename_quote_characters == NULL) { 1405 filename_quote_characters = 1406 ALLOC_N(char, RSTRING_LEN(str) + 1); 1407 } 1408 else { 1409 REALLOC_N(filename_quote_characters, char, RSTRING_LEN(str) + 1); 1410 } 1411 strncpy(filename_quote_characters, RSTRING_PTR(str), RSTRING_LEN(str)); 1412 filename_quote_characters[RSTRING_LEN(str)] = '\0'; 1413 rl_filename_quote_characters = filename_quote_characters; 1414 1415 return self; 1416} 1417#else 1418#define readline_s_set_filename_quote_characters rb_f_notimplement 1419#endif 1420 1421#ifdef HAVE_RL_FILENAME_QUOTE_CHARACTERS 1422/* 1423 * call-seq: 1424 * Readline.filename_quote_characters -> string 1425 * 1426 * Gets a list of characters that cause a filename to be quoted by the completer 1427 * when they appear in a completed filename. 1428 * 1429 * Raises NotImplementedError if the using readline library does not support. 1430 * 1431 * Raises SecurityError exception if $SAFE is 4. 1432 */ 1433static VALUE 1434readline_s_get_filename_quote_characters(VALUE self, VALUE str) 1435{ 1436 rb_secure(4); 1437 if (rl_filename_quote_characters == NULL) 1438 return Qnil; 1439 return rb_locale_str_new_cstr(rl_filename_quote_characters); 1440} 1441#else 1442#define readline_s_get_filename_quote_characters rb_f_notimplement 1443#endif 1444 1445#ifdef HAVE_RL_REFRESH_LINE 1446/* 1447 * call-seq: 1448 * Readline.refresh_line -> nil 1449 * 1450 * Clear the current input line. 1451 * 1452 * Raises SecurityError exception if $SAFE is 4. 1453 */ 1454static VALUE 1455readline_s_refresh_line(VALUE self) 1456{ 1457 rb_secure(4); 1458 rl_refresh_line(0, 0); 1459 return Qnil; 1460} 1461#else 1462#define readline_s_refresh_line rb_f_notimplement 1463#endif 1464 1465static VALUE 1466hist_to_s(VALUE self) 1467{ 1468 return rb_str_new_cstr("HISTORY"); 1469} 1470 1471static int 1472history_get_offset_history_base(int offset) 1473{ 1474 return history_base + offset; 1475} 1476 1477static int 1478history_get_offset_0(int offset) 1479{ 1480 return offset; 1481} 1482 1483static VALUE 1484hist_get(VALUE self, VALUE index) 1485{ 1486 HIST_ENTRY *entry = NULL; 1487 int i; 1488 1489 rb_secure(4); 1490 i = NUM2INT(index); 1491 if (i < 0) { 1492 i += history_length; 1493 } 1494 if (i >= 0) { 1495 entry = history_get(history_get_offset_func(i)); 1496 } 1497 if (entry == NULL) { 1498 rb_raise(rb_eIndexError, "invalid index"); 1499 } 1500 return rb_locale_str_new_cstr(entry->line); 1501} 1502 1503#ifdef HAVE_REPLACE_HISTORY_ENTRY 1504static VALUE 1505hist_set(VALUE self, VALUE index, VALUE str) 1506{ 1507 HIST_ENTRY *entry = NULL; 1508 int i; 1509 1510 rb_secure(4); 1511 i = NUM2INT(index); 1512 OutputStringValue(str); 1513 if (i < 0) { 1514 i += history_length; 1515 } 1516 if (i >= 0) { 1517 entry = replace_history_entry(history_replace_offset_func(i), RSTRING_PTR(str), NULL); 1518 } 1519 if (entry == NULL) { 1520 rb_raise(rb_eIndexError, "invalid index"); 1521 } 1522 return str; 1523} 1524#else 1525#define hist_set rb_f_notimplement 1526#endif 1527 1528static VALUE 1529hist_push(VALUE self, VALUE str) 1530{ 1531 rb_secure(4); 1532 OutputStringValue(str); 1533 add_history(RSTRING_PTR(str)); 1534 return self; 1535} 1536 1537static VALUE 1538hist_push_method(int argc, VALUE *argv, VALUE self) 1539{ 1540 VALUE str; 1541 1542 rb_secure(4); 1543 while (argc--) { 1544 str = *argv++; 1545 OutputStringValue(str); 1546 add_history(RSTRING_PTR(str)); 1547 } 1548 return self; 1549} 1550 1551static VALUE 1552rb_remove_history(int index) 1553{ 1554#ifdef HAVE_REMOVE_HISTORY 1555 HIST_ENTRY *entry; 1556 VALUE val; 1557 1558 rb_secure(4); 1559 entry = remove_history(index); 1560 if (entry) { 1561 val = rb_locale_str_new_cstr(entry->line); 1562 free((void *) entry->line); 1563 free(entry); 1564 return val; 1565 } 1566 return Qnil; 1567#else 1568 rb_notimplement(); 1569 1570 UNREACHABLE; 1571#endif 1572} 1573 1574static VALUE 1575hist_pop(VALUE self) 1576{ 1577 rb_secure(4); 1578 if (history_length > 0) { 1579 return rb_remove_history(history_length - 1); 1580 } else { 1581 return Qnil; 1582 } 1583} 1584 1585static VALUE 1586hist_shift(VALUE self) 1587{ 1588 rb_secure(4); 1589 if (history_length > 0) { 1590 return rb_remove_history(0); 1591 } else { 1592 return Qnil; 1593 } 1594} 1595 1596static VALUE 1597hist_each(VALUE self) 1598{ 1599 HIST_ENTRY *entry; 1600 int i; 1601 1602 RETURN_ENUMERATOR(self, 0, 0); 1603 1604 rb_secure(4); 1605 for (i = 0; i < history_length; i++) { 1606 entry = history_get(history_get_offset_func(i)); 1607 if (entry == NULL) 1608 break; 1609 rb_yield(rb_locale_str_new_cstr(entry->line)); 1610 } 1611 return self; 1612} 1613 1614static VALUE 1615hist_length(VALUE self) 1616{ 1617 rb_secure(4); 1618 return INT2NUM(history_length); 1619} 1620 1621static VALUE 1622hist_empty_p(VALUE self) 1623{ 1624 rb_secure(4); 1625 return history_length == 0 ? Qtrue : Qfalse; 1626} 1627 1628static VALUE 1629hist_delete_at(VALUE self, VALUE index) 1630{ 1631 int i; 1632 1633 rb_secure(4); 1634 i = NUM2INT(index); 1635 if (i < 0) 1636 i += history_length; 1637 if (i < 0 || i > history_length - 1) { 1638 rb_raise(rb_eIndexError, "invalid index"); 1639 } 1640 return rb_remove_history(i); 1641} 1642 1643#ifdef HAVE_CLEAR_HISTORY 1644static VALUE 1645hist_clear(VALUE self) 1646{ 1647 rb_secure(4); 1648 clear_history(); 1649 return self; 1650} 1651#else 1652#define hist_clear rb_f_notimplement 1653#endif 1654 1655static VALUE 1656filename_completion_proc_call(VALUE self, VALUE str) 1657{ 1658 VALUE result; 1659 char **matches; 1660 int i; 1661 1662 matches = rl_completion_matches(StringValuePtr(str), 1663 rl_filename_completion_function); 1664 if (matches) { 1665 result = rb_ary_new(); 1666 for (i = 0; matches[i]; i++) { 1667 rb_ary_push(result, rb_locale_str_new_cstr(matches[i])); 1668 free(matches[i]); 1669 } 1670 free(matches); 1671 if (RARRAY_LEN(result) >= 2) 1672 rb_ary_shift(result); 1673 } 1674 else { 1675 result = Qnil; 1676 } 1677 return result; 1678} 1679 1680static VALUE 1681username_completion_proc_call(VALUE self, VALUE str) 1682{ 1683 VALUE result; 1684 char **matches; 1685 int i; 1686 1687 matches = rl_completion_matches(StringValuePtr(str), 1688 rl_username_completion_function); 1689 if (matches) { 1690 result = rb_ary_new(); 1691 for (i = 0; matches[i]; i++) { 1692 rb_ary_push(result, rb_locale_str_new_cstr(matches[i])); 1693 free(matches[i]); 1694 } 1695 free(matches); 1696 if (RARRAY_LEN(result) >= 2) 1697 rb_ary_shift(result); 1698 } 1699 else { 1700 result = Qnil; 1701 } 1702 return result; 1703} 1704 1705void 1706Init_readline() 1707{ 1708 VALUE history, fcomp, ucomp, version; 1709 1710 /* Allow conditional parsing of the ~/.inputrc file. */ 1711 rl_readline_name = (char *)"Ruby"; 1712 1713#if defined HAVE_RL_GETC_FUNCTION 1714 /* libedit check rl_getc_function only when rl_initialize() is called, */ 1715 /* and using_history() call rl_initialize(). */ 1716 /* This assignment should be placed before using_history() */ 1717 rl_getc_function = readline_getc; 1718#elif defined HAVE_RL_EVENT_HOOK 1719 rl_event_hook = readline_event; 1720#endif 1721 1722 using_history(); 1723 1724 completion_proc = rb_intern(COMPLETION_PROC); 1725 completion_case_fold = rb_intern(COMPLETION_CASE_FOLD); 1726#if defined(HAVE_RL_PRE_INPUT_HOOK) 1727 id_pre_input_hook = rb_intern("pre_input_hook"); 1728#endif 1729#if defined(HAVE_RL_SPECIAL_PREFIXES) 1730 id_special_prefixes = rb_intern("special_prefixes"); 1731#endif 1732 1733 mReadline = rb_define_module("Readline"); 1734 rb_define_module_function(mReadline, "readline", 1735 readline_readline, -1); 1736 rb_define_singleton_method(mReadline, "input=", 1737 readline_s_set_input, 1); 1738 rb_define_singleton_method(mReadline, "output=", 1739 readline_s_set_output, 1); 1740 rb_define_singleton_method(mReadline, "completion_proc=", 1741 readline_s_set_completion_proc, 1); 1742 rb_define_singleton_method(mReadline, "completion_proc", 1743 readline_s_get_completion_proc, 0); 1744 rb_define_singleton_method(mReadline, "completion_case_fold=", 1745 readline_s_set_completion_case_fold, 1); 1746 rb_define_singleton_method(mReadline, "completion_case_fold", 1747 readline_s_get_completion_case_fold, 0); 1748 rb_define_singleton_method(mReadline, "line_buffer", 1749 readline_s_get_line_buffer, 0); 1750 rb_define_singleton_method(mReadline, "point", 1751 readline_s_get_point, 0); 1752 rb_define_singleton_method(mReadline, "set_screen_size", 1753 readline_s_set_screen_size, 2); 1754 rb_define_singleton_method(mReadline, "get_screen_size", 1755 readline_s_get_screen_size, 0); 1756 rb_define_singleton_method(mReadline, "vi_editing_mode", 1757 readline_s_vi_editing_mode, 0); 1758 rb_define_singleton_method(mReadline, "vi_editing_mode?", 1759 readline_s_vi_editing_mode_p, 0); 1760 rb_define_singleton_method(mReadline, "emacs_editing_mode", 1761 readline_s_emacs_editing_mode, 0); 1762 rb_define_singleton_method(mReadline, "emacs_editing_mode?", 1763 readline_s_emacs_editing_mode_p, 0); 1764 rb_define_singleton_method(mReadline, "completion_append_character=", 1765 readline_s_set_completion_append_character, 1); 1766 rb_define_singleton_method(mReadline, "completion_append_character", 1767 readline_s_get_completion_append_character, 0); 1768 rb_define_singleton_method(mReadline, "basic_word_break_characters=", 1769 readline_s_set_basic_word_break_characters, 1); 1770 rb_define_singleton_method(mReadline, "basic_word_break_characters", 1771 readline_s_get_basic_word_break_characters, 0); 1772 rb_define_singleton_method(mReadline, "completer_word_break_characters=", 1773 readline_s_set_completer_word_break_characters, 1); 1774 rb_define_singleton_method(mReadline, "completer_word_break_characters", 1775 readline_s_get_completer_word_break_characters, 0); 1776 rb_define_singleton_method(mReadline, "basic_quote_characters=", 1777 readline_s_set_basic_quote_characters, 1); 1778 rb_define_singleton_method(mReadline, "basic_quote_characters", 1779 readline_s_get_basic_quote_characters, 0); 1780 rb_define_singleton_method(mReadline, "completer_quote_characters=", 1781 readline_s_set_completer_quote_characters, 1); 1782 rb_define_singleton_method(mReadline, "completer_quote_characters", 1783 readline_s_get_completer_quote_characters, 0); 1784 rb_define_singleton_method(mReadline, "filename_quote_characters=", 1785 readline_s_set_filename_quote_characters, 1); 1786 rb_define_singleton_method(mReadline, "filename_quote_characters", 1787 readline_s_get_filename_quote_characters, 0); 1788 rb_define_singleton_method(mReadline, "refresh_line", 1789 readline_s_refresh_line, 0); 1790 rb_define_singleton_method(mReadline, "pre_input_hook=", 1791 readline_s_set_pre_input_hook, 1); 1792 rb_define_singleton_method(mReadline, "pre_input_hook", 1793 readline_s_get_pre_input_hook, 0); 1794 rb_define_singleton_method(mReadline, "insert_text", 1795 readline_s_insert_text, 1); 1796 rb_define_singleton_method(mReadline, "redisplay", 1797 readline_s_redisplay, 0); 1798 rb_define_singleton_method(mReadline, "special_prefixes=", 1799 readline_s_set_special_prefixes, 1); 1800 rb_define_singleton_method(mReadline, "special_prefixes", 1801 readline_s_get_special_prefixes, 0); 1802 1803#if USE_INSERT_IGNORE_ESCAPE 1804 CONST_ID(id_orig_prompt, "orig_prompt"); 1805 CONST_ID(id_last_prompt, "last_prompt"); 1806#endif 1807 1808 history = rb_obj_alloc(rb_cObject); 1809 rb_extend_object(history, rb_mEnumerable); 1810 rb_define_singleton_method(history,"to_s", hist_to_s, 0); 1811 rb_define_singleton_method(history,"[]", hist_get, 1); 1812 rb_define_singleton_method(history,"[]=", hist_set, 2); 1813 rb_define_singleton_method(history,"<<", hist_push, 1); 1814 rb_define_singleton_method(history,"push", hist_push_method, -1); 1815 rb_define_singleton_method(history,"pop", hist_pop, 0); 1816 rb_define_singleton_method(history,"shift", hist_shift, 0); 1817 rb_define_singleton_method(history,"each", hist_each, 0); 1818 rb_define_singleton_method(history,"length", hist_length, 0); 1819 rb_define_singleton_method(history,"size", hist_length, 0); 1820 rb_define_singleton_method(history,"empty?", hist_empty_p, 0); 1821 rb_define_singleton_method(history,"delete_at", hist_delete_at, 1); 1822 rb_define_singleton_method(history,"clear", hist_clear, 0); 1823 1824 /* 1825 * The history buffer. It extends Enumerable module, so it behaves 1826 * just like an array. 1827 * For example, gets the fifth content that the user input by 1828 * HISTORY[4]. 1829 */ 1830 rb_define_const(mReadline, "HISTORY", history); 1831 1832 fcomp = rb_obj_alloc(rb_cObject); 1833 rb_define_singleton_method(fcomp, "call", 1834 filename_completion_proc_call, 1); 1835 /* 1836 * The Object with the call method that is a completion for filename. 1837 * This is sets by Readline.completion_proc= method. 1838 */ 1839 rb_define_const(mReadline, "FILENAME_COMPLETION_PROC", fcomp); 1840 1841 ucomp = rb_obj_alloc(rb_cObject); 1842 rb_define_singleton_method(ucomp, "call", 1843 username_completion_proc_call, 1); 1844 /* 1845 * The Object with the call method that is a completion for usernames. 1846 * This is sets by Readline.completion_proc= method. 1847 */ 1848 rb_define_const(mReadline, "USERNAME_COMPLETION_PROC", ucomp); 1849 history_get_offset_func = history_get_offset_history_base; 1850 history_replace_offset_func = history_get_offset_0; 1851#if defined HAVE_RL_LIBRARY_VERSION 1852 version = rb_str_new_cstr(rl_library_version); 1853#if defined HAVE_CLEAR_HISTORY || defined HAVE_REMOVE_HISTORY 1854 if (strncmp(rl_library_version, EDIT_LINE_LIBRARY_VERSION, 1855 strlen(EDIT_LINE_LIBRARY_VERSION)) == 0) { 1856 add_history("1"); 1857 if (history_get(history_get_offset_func(0)) == NULL) { 1858 history_get_offset_func = history_get_offset_0; 1859 } 1860#ifdef HAVE_REPLACE_HISTORY_ENTRY 1861 if (replace_history_entry(0, "a", NULL) == NULL) { 1862 history_replace_offset_func = history_get_offset_history_base; 1863 } 1864#endif 1865#ifdef HAVE_CLEAR_HISTORY 1866 clear_history(); 1867#else 1868 { 1869 HIST_ENTRY *entry = remove_history(0); 1870 if (entry) { 1871 free((char *)entry->line); 1872 free(entry); 1873 } 1874 } 1875#endif 1876 } 1877#endif 1878#else 1879 version = rb_str_new_cstr("2.0 or prior version"); 1880#endif 1881 /* Version string of GNU Readline or libedit. */ 1882 rb_define_const(mReadline, "VERSION", version); 1883 1884 rl_attempted_completion_function = readline_attempted_completion_function; 1885#if defined(HAVE_RL_PRE_INPUT_HOOK) 1886 rl_pre_input_hook = (rl_hook_func_t *)readline_pre_input_hook; 1887#endif 1888#ifdef HAVE_RL_CATCH_SIGNALS 1889 rl_catch_signals = 0; 1890#endif 1891#ifdef HAVE_RL_CLEAR_SIGNALS 1892 rl_clear_signals(); 1893#endif 1894 1895 readline_s_set_input(mReadline, rb_stdin); 1896} 1897