Ruby
2.0.0p247(2013-06-27revision41674)
|
00001 /************************************************ 00002 00003 readline.c - GNU Readline module 00004 00005 $Author: shugo $ 00006 created at: Wed Jan 20 13:59:32 JST 1999 00007 00008 Copyright (C) 1997-2008 Shugo Maeda 00009 Copyright (C) 2008-2009 TAKAO Kouji 00010 00011 $Id: readline.c 39002 2013-02-01 05:37:29Z shugo $ 00012 00013 Contact: 00014 - TAKAO Kouji <kouji at takao7 dot net> (current maintainer) 00015 00016 ************************************************/ 00017 00018 #ifdef RUBY_EXTCONF_H 00019 #include RUBY_EXTCONF_H 00020 #endif 00021 00022 #include "ruby/config.h" 00023 #include <errno.h> 00024 #include <stdio.h> 00025 #include <string.h> 00026 #ifdef HAVE_READLINE_READLINE_H 00027 #include <readline/readline.h> 00028 #endif 00029 #ifdef HAVE_READLINE_HISTORY_H 00030 #include <readline/history.h> 00031 #endif 00032 #ifdef HAVE_EDITLINE_READLINE_H 00033 #include <editline/readline.h> 00034 #endif 00035 00036 #include "ruby/ruby.h" 00037 #include "ruby/io.h" 00038 00039 #ifdef HAVE_UNISTD_H 00040 #include <unistd.h> 00041 #endif 00042 00043 #ifdef HAVE_SYS_STAT_H 00044 #include <sys/stat.h> 00045 #endif 00046 00047 static VALUE mReadline; 00048 00049 #define EDIT_LINE_LIBRARY_VERSION "EditLine wrapper" 00050 #ifndef USE_INSERT_IGNORE_ESCAPE 00051 # if !defined(HAVE_EDITLINE_READLINE_H) && defined(RL_PROMPT_START_IGNORE) && defined(RL_PROMPT_END_IGNORE) 00052 # define USE_INSERT_IGNORE_ESCAPE 1 00053 # else 00054 # define USE_INSERT_IGNORE_ESCAPE 0 00055 # endif 00056 #endif 00057 00058 #define COMPLETION_PROC "completion_proc" 00059 #define COMPLETION_CASE_FOLD "completion_case_fold" 00060 static ID completion_proc, completion_case_fold; 00061 #if USE_INSERT_IGNORE_ESCAPE 00062 static ID id_orig_prompt, id_last_prompt; 00063 #endif 00064 #if defined(HAVE_RL_PRE_INPUT_HOOK) 00065 static ID id_pre_input_hook; 00066 #endif 00067 #if defined(HAVE_RL_SPECIAL_PREFIXES) 00068 static ID id_special_prefixes; 00069 #endif 00070 00071 #ifndef HAVE_RL_FILENAME_COMPLETION_FUNCTION 00072 # define rl_filename_completion_function filename_completion_function 00073 #endif 00074 #ifndef HAVE_RL_USERNAME_COMPLETION_FUNCTION 00075 # define rl_username_completion_function username_completion_function 00076 #endif 00077 #ifndef HAVE_RL_COMPLETION_MATCHES 00078 # define rl_completion_matches completion_matches 00079 #endif 00080 00081 static int (*history_get_offset_func)(int); 00082 static int (*history_replace_offset_func)(int); 00083 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER 00084 static int readline_completion_append_character; 00085 #endif 00086 00087 static char **readline_attempted_completion_function(const char *text, 00088 int start, int end); 00089 00090 #define OutputStringValue(str) do {\ 00091 SafeStringValue(str);\ 00092 (str) = rb_str_conv_enc((str), rb_enc_get(str), rb_locale_encoding());\ 00093 } while (0)\ 00094 00095 00096 /* 00097 * Document-class: Readline 00098 * 00099 * The Readline module provides interface for GNU Readline. 00100 * This module defines a number of methods to facilitate completion 00101 * and accesses input history from the Ruby interpreter. 00102 * This module supported Edit Line(libedit) too. 00103 * libedit is compatible with GNU Readline. 00104 * 00105 * GNU Readline:: http://www.gnu.org/directory/readline.html 00106 * libedit:: http://www.thrysoee.dk/editline/ 00107 * 00108 * Reads one inputted line with line edit by Readline.readline method. 00109 * At this time, the facilitatation completion and the key 00110 * bind like Emacs can be operated like GNU Readline. 00111 * 00112 * require "readline" 00113 * while buf = Readline.readline("> ", true) 00114 * p buf 00115 * end 00116 * 00117 * The content that the user input can be recorded to the history. 00118 * The history can be accessed by Readline::HISTORY constant. 00119 * 00120 * require "readline" 00121 * while buf = Readline.readline("> ", true) 00122 * p Readline::HISTORY.to_a 00123 * print("-> ", buf, "\n") 00124 * end 00125 * 00126 * Most of methods raise SecurityError exception if $SAFE is 4. 00127 * 00128 * Documented by TAKAO Kouji <kouji at takao7 dot net>. 00129 */ 00130 00131 #if defined HAVE_RL_GETC_FUNCTION 00132 static VALUE readline_instream; 00133 00134 #ifndef HAVE_RL_GETC 00135 #define rl_getc(f) EOF 00136 #endif 00137 00138 static int readline_getc(FILE *); 00139 static int 00140 readline_getc(FILE *input) 00141 { 00142 rb_io_t *ifp = 0; 00143 VALUE c; 00144 if (!readline_instream) return rl_getc(input); 00145 GetOpenFile(readline_instream, ifp); 00146 if (rl_instream != ifp->stdio_file) return rl_getc(input); 00147 #if defined(_WIN32) 00148 { 00149 INPUT_RECORD ir; 00150 int n; 00151 static int prior_key = '0'; 00152 for (;;) { 00153 if (prior_key > 0xff) { 00154 prior_key = rl_getc(ifp->stdio_file); 00155 return prior_key; 00156 } 00157 if (PeekConsoleInput((HANDLE)_get_osfhandle(ifp->fd), &ir, 1, &n)) { 00158 if (n == 1) { 00159 if (ir.EventType == KEY_EVENT && ir.Event.KeyEvent.bKeyDown) { 00160 prior_key = rl_getc(ifp->stdio_file); 00161 return prior_key; 00162 } else { 00163 ReadConsoleInput((HANDLE)_get_osfhandle(ifp->fd), &ir, 1, &n); 00164 } 00165 } else { 00166 HANDLE h = (HANDLE)_get_osfhandle(ifp->fd); 00167 rb_w32_wait_events(&h, 1, INFINITE); 00168 } 00169 } else { 00170 break; 00171 } 00172 } 00173 } 00174 #endif 00175 c = rb_io_getbyte(readline_instream); 00176 if (NIL_P(c)) return EOF; 00177 #ifdef ESC 00178 if (c == INT2FIX(ESC) && 00179 RL_ISSTATE(RL_STATE_ISEARCH) && /* isn't needed in other states? */ 00180 rb_io_read_pending(ifp)) { 00181 int meta = 0; 00182 c = rb_io_getbyte(readline_instream); 00183 if (FIXNUM_P(c) && isascii(FIX2INT(c))) meta = 1; 00184 rb_io_ungetbyte(readline_instream, c); 00185 if (meta) rl_execute_next(ESC); 00186 return ESC; 00187 } 00188 #endif 00189 return FIX2INT(c); 00190 } 00191 #elif defined HAVE_RL_EVENT_HOOK 00192 #define BUSY_WAIT 0 00193 00194 static int readline_event(void); 00195 static int 00196 readline_event(void) 00197 { 00198 #if BUSY_WAIT 00199 rb_thread_schedule(); 00200 #else 00201 rb_wait_for_single_fd(fileno(rl_instream), RB_WAITFD_IN, NULL); 00202 return 0; 00203 #endif 00204 } 00205 #endif 00206 00207 #if USE_INSERT_IGNORE_ESCAPE 00208 static VALUE 00209 insert_ignore_escape(VALUE self, VALUE prompt) 00210 { 00211 VALUE last_prompt, orig_prompt = rb_attr_get(self, id_orig_prompt); 00212 int ignoring = 0; 00213 const char *s0, *s, *e; 00214 long len; 00215 static const char ignore_code[2] = {RL_PROMPT_START_IGNORE, RL_PROMPT_END_IGNORE}; 00216 00217 prompt = rb_str_new_shared(prompt); 00218 last_prompt = rb_attr_get(self, id_last_prompt); 00219 if (orig_prompt == prompt) return last_prompt; 00220 len = RSTRING_LEN(prompt); 00221 if (NIL_P(last_prompt)) { 00222 last_prompt = rb_str_tmp_new(len); 00223 } 00224 00225 s = s0 = RSTRING_PTR(prompt); 00226 e = s0 + len; 00227 rb_str_set_len(last_prompt, 0); 00228 while (s < e && *s) { 00229 switch (*s) { 00230 case RL_PROMPT_START_IGNORE: 00231 ignoring = -1; 00232 rb_str_cat(last_prompt, s0, ++s - s0); 00233 s0 = s; 00234 break; 00235 case RL_PROMPT_END_IGNORE: 00236 ignoring = 0; 00237 rb_str_cat(last_prompt, s0, ++s - s0); 00238 s0 = s; 00239 break; 00240 case '\033': 00241 if (++s < e && *s == '[') { 00242 rb_str_cat(last_prompt, s0, s - s0 - 1); 00243 s0 = s - 1; 00244 while (++s < e && *s) { 00245 if (ISALPHA(*s)) { 00246 if (!ignoring) { 00247 ignoring = 1; 00248 rb_str_cat(last_prompt, ignore_code+0, 1); 00249 } 00250 rb_str_cat(last_prompt, s0, ++s - s0); 00251 s0 = s; 00252 break; 00253 } 00254 else if (!('0' <= *s && *s <= '9' || *s == ';')) { 00255 break; 00256 } 00257 } 00258 } 00259 break; 00260 default: 00261 if (ignoring > 0) { 00262 ignoring = 0; 00263 rb_str_cat(last_prompt, ignore_code+1, 1); 00264 } 00265 s++; 00266 break; 00267 } 00268 } 00269 if (ignoring > 0) { 00270 ignoring = 0; 00271 rb_str_cat(last_prompt, ignore_code+1, 1); 00272 } 00273 rb_str_cat(last_prompt, s0, s - s0); 00274 00275 rb_ivar_set(self, id_orig_prompt, prompt); 00276 rb_ivar_set(self, id_last_prompt, last_prompt); 00277 00278 return last_prompt; 00279 } 00280 #endif 00281 00282 static VALUE 00283 readline_get(VALUE prompt) 00284 { 00285 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER 00286 readline_completion_append_character = rl_completion_append_character; 00287 #endif 00288 return (VALUE)readline((char *)prompt); 00289 } 00290 00291 /* 00292 * call-seq: 00293 * Readline.readline(prompt = "", add_hist = false) -> string or nil 00294 * 00295 * Shows the +prompt+ and reads the inputted line with line editing. 00296 * The inputted line is added to the history if +add_hist+ is true. 00297 * 00298 * Returns nil when the inputted line is empty and user inputs EOF 00299 * (Presses ^D on UNIX). 00300 * 00301 * Raises IOError exception if below conditions are satisfied. 00302 * 1. stdin is not tty. 00303 * 2. stdin was closed. (errno is EBADF after called isatty(2).) 00304 * 00305 * This method supports thread. Switchs the thread context when waits 00306 * inputting line. 00307 * 00308 * Supports line edit when inputs line. Provides VI and Emacs editing mode. 00309 * Default is Emacs editing mode. 00310 * 00311 * NOTE: Terminates ruby interpreter and does not return the terminal 00312 * status after user pressed '^C' when wait inputting line. 00313 * Give 3 examples that avoid it. 00314 * 00315 * * Catches the Interrupt exception by pressed ^C after returns 00316 * terminal status: 00317 * 00318 * require "readline" 00319 * 00320 * stty_save = `stty -g`.chomp 00321 * begin 00322 * while buf = Readline.readline 00323 * p buf 00324 * end 00325 * rescue Interrupt 00326 * system("stty", stty_save) 00327 * exit 00328 * end 00329 * end 00330 * end 00331 * 00332 * * Catches the INT signal by pressed ^C after returns terminal 00333 * status: 00334 * 00335 * require "readline" 00336 * 00337 * stty_save = `stty -g`.chomp 00338 * trap("INT") { system "stty", stty_save; exit } 00339 * 00340 * while buf = Readline.readline 00341 * p buf 00342 * end 00343 * 00344 * * Ignores pressing ^C: 00345 * 00346 * require "readline" 00347 * 00348 * trap("INT", "SIG_IGN") 00349 * 00350 * while buf = Readline.readline 00351 * p buf 00352 * end 00353 * 00354 * Can make as follows with Readline::HISTORY constant. 00355 * It does not record to the history if the inputted line is empty or 00356 * the same it as last one. 00357 * 00358 * require "readline" 00359 * 00360 * while buf = Readline.readline("> ", true) 00361 * # p Readline::HISTORY.to_a 00362 * Readline::HISTORY.pop if /^\s*$/ =~ buf 00363 * 00364 * begin 00365 * if Readline::HISTORY[Readline::HISTORY.length-2] == buf 00366 * Readline::HISTORY.pop 00367 * end 00368 * rescue IndexError 00369 * end 00370 * 00371 * # p Readline::HISTORY.to_a 00372 * print "-> ", buf, "\n" 00373 * end 00374 * 00375 * Raises SecurityError exception if $SAFE is 4. 00376 */ 00377 static VALUE 00378 readline_readline(int argc, VALUE *argv, VALUE self) 00379 { 00380 VALUE tmp, add_hist, result; 00381 char *prompt = NULL; 00382 char *buff; 00383 int status; 00384 00385 rb_secure(4); 00386 if (rb_scan_args(argc, argv, "02", &tmp, &add_hist) > 0) { 00387 OutputStringValue(tmp); 00388 #if USE_INSERT_IGNORE_ESCAPE 00389 tmp = insert_ignore_escape(self, tmp); 00390 rb_str_locktmp(tmp); 00391 #endif 00392 prompt = RSTRING_PTR(tmp); 00393 } 00394 00395 if (!isatty(fileno(rl_instream)) && errno == EBADF) rb_raise(rb_eIOError, "closed stdin"); 00396 if (rl_outstream) { 00397 struct stat stbuf; 00398 int fd = fileno(rl_outstream); 00399 if (fd < 0 || fstat(fd, &stbuf) != 0) { 00400 rb_raise(rb_eIOError, "closed stdout"); 00401 } 00402 } 00403 00404 #ifdef _WIN32 00405 rl_prep_terminal(1); 00406 #endif 00407 buff = (char*)rb_protect(readline_get, (VALUE)prompt, &status); 00408 #if USE_INSERT_IGNORE_ESCAPE 00409 if (prompt) { 00410 rb_str_unlocktmp(tmp); 00411 } 00412 #endif 00413 if (status) { 00414 #if defined HAVE_RL_CLEANUP_AFTER_SIGNAL 00415 /* restore terminal mode and signal handler*/ 00416 #if defined HAVE_RL_FREE_LINE_STATE 00417 rl_free_line_state(); 00418 #endif 00419 rl_cleanup_after_signal(); 00420 #elif defined HAVE_RL_DEPREP_TERM_FUNCTION 00421 /* restore terminal mode */ 00422 if (rl_deprep_term_function != NULL) /* NULL in libedit. [ruby-dev:29116] */ 00423 (*rl_deprep_term_function)(); 00424 else 00425 #else 00426 rl_deprep_terminal(); 00427 #endif 00428 rb_jump_tag(status); 00429 } 00430 00431 if (RTEST(add_hist) && buff) { 00432 add_history(buff); 00433 } 00434 if (buff) { 00435 result = rb_locale_str_new_cstr(buff); 00436 } 00437 else 00438 result = Qnil; 00439 if (buff) free(buff); 00440 return result; 00441 } 00442 00443 /* 00444 * call-seq: 00445 * Readline.input = input 00446 * 00447 * Specifies a File object +input+ that is input stream for 00448 * Readline.readline method. 00449 * 00450 * Raises SecurityError exception if $SAFE is 4. 00451 */ 00452 static VALUE 00453 readline_s_set_input(VALUE self, VALUE input) 00454 { 00455 rb_io_t *ifp; 00456 00457 rb_secure(4); 00458 Check_Type(input, T_FILE); 00459 GetOpenFile(input, ifp); 00460 rl_instream = rb_io_stdio_file(ifp); 00461 #ifdef HAVE_RL_GETC_FUNCTION 00462 readline_instream = input; 00463 #endif 00464 return input; 00465 } 00466 00467 /* 00468 * call-seq: 00469 * Readline.output = output 00470 * 00471 * Specifies a File object +output+ that is output stream for 00472 * Readline.readline method. 00473 * 00474 * Raises SecurityError exception if $SAFE is 4. 00475 */ 00476 static VALUE 00477 readline_s_set_output(VALUE self, VALUE output) 00478 { 00479 rb_io_t *ofp; 00480 00481 rb_secure(4); 00482 Check_Type(output, T_FILE); 00483 GetOpenFile(output, ofp); 00484 rl_outstream = rb_io_stdio_file(ofp); 00485 return output; 00486 } 00487 00488 #if defined(HAVE_RL_PRE_INPUT_HOOK) 00489 /* 00490 * call-seq: 00491 * Readline.pre_input_hook = proc 00492 * 00493 * Specifies a Proc object +proc+ to call after the first prompt has 00494 * been printed and just before readline starts reading input 00495 * characters. 00496 * 00497 * See GNU Readline's rl_pre_input_hook variable. 00498 * 00499 * Raises ArgumentError if +proc+ does not respond to the call method. 00500 * 00501 * Raises SecurityError if $SAFE is 4. 00502 */ 00503 static VALUE 00504 readline_s_set_pre_input_hook(VALUE self, VALUE proc) 00505 { 00506 rb_secure(4); 00507 if (!NIL_P(proc) && !rb_respond_to(proc, rb_intern("call"))) 00508 rb_raise(rb_eArgError, "argument must respond to `call'"); 00509 return rb_ivar_set(mReadline, id_pre_input_hook, proc); 00510 } 00511 00512 /* 00513 * call-seq: 00514 * Readline.pre_input_hook -> proc 00515 * 00516 * Returns a Proc object +proc+ to call after the first prompt has 00517 * been printed and just before readline starts reading input 00518 * characters. The default is nil. 00519 * 00520 * Raises SecurityError if $SAFE is 4. 00521 */ 00522 static VALUE 00523 readline_s_get_pre_input_hook(VALUE self) 00524 { 00525 rb_secure(4); 00526 return rb_attr_get(mReadline, id_pre_input_hook); 00527 } 00528 00529 static int 00530 readline_pre_input_hook(void) 00531 { 00532 VALUE proc; 00533 00534 proc = rb_attr_get(mReadline, id_pre_input_hook); 00535 if (!NIL_P(proc)) 00536 rb_funcall(proc, rb_intern("call"), 0); 00537 return 0; 00538 } 00539 #else 00540 #define readline_s_set_pre_input_hook rb_f_notimplement 00541 #define readline_s_get_pre_input_hook rb_f_notimplement 00542 #endif 00543 00544 #if defined(HAVE_RL_INSERT_TEXT) 00545 /* 00546 * call-seq: 00547 * Readline.insert_text(string) -> self 00548 * 00549 * Insert text into the line at the current cursor position. 00550 * 00551 * See GNU Readline's rl_insert_text function. 00552 * 00553 * Raises SecurityError if $SAFE is 4. 00554 */ 00555 static VALUE 00556 readline_s_insert_text(VALUE self, VALUE str) 00557 { 00558 rb_secure(4); 00559 OutputStringValue(str); 00560 rl_insert_text(RSTRING_PTR(str)); 00561 return self; 00562 } 00563 #else 00564 #define readline_s_insert_text rb_f_notimplement 00565 #endif 00566 00567 #if defined(HAVE_RL_REDISPLAY) 00568 /* 00569 * call-seq: 00570 * Readline.redisplay -> self 00571 * 00572 * Change what's displayed on the screen to reflect the current 00573 * contents. 00574 * 00575 * See GNU Readline's rl_redisplay function. 00576 * 00577 * Raises SecurityError if $SAFE is 4. 00578 */ 00579 static VALUE 00580 readline_s_redisplay(VALUE self) 00581 { 00582 rb_secure(4); 00583 rl_redisplay(); 00584 return self; 00585 } 00586 #else 00587 #define readline_s_redisplay rb_f_notimplement 00588 #endif 00589 00590 /* 00591 * call-seq: 00592 * Readline.completion_proc = proc 00593 * 00594 * Specifies a Proc object +proc+ to determine completion behavior. It 00595 * should take input string and return an array of completion candidates. 00596 * 00597 * The default completion is used if +proc+ is nil. 00598 * 00599 * The String that is passed to the Proc depends on the 00600 * Readline.completer_word_break_characters property. By default the word 00601 * under the cursor is passed to the Proc. For example, if the input is "foo 00602 * bar" then only "bar" would be passed to the completion Proc. 00603 * 00604 * Upon successful completion the Readline.completion_append_character will be 00605 * appended to the input so the user can start working on their next argument. 00606 * 00607 * = Examples 00608 * 00609 * == Completion for a Static List 00610 * 00611 * require 'readline' 00612 * 00613 * LIST = [ 00614 * 'search', 'download', 'open', 00615 * 'help', 'history', 'quit', 00616 * 'url', 'next', 'clear', 00617 * 'prev', 'past' 00618 * ].sort 00619 * 00620 * comp = proc { |s| LIST.grep(/^#{Regexp.escape(s)}/) } 00621 * 00622 * Readline.completion_append_character = " " 00623 * Readline.completion_proc = comp 00624 * 00625 * while line = Readline.readline('> ', true) 00626 * p line 00627 * end 00628 * 00629 * == Completion For Directory Contents 00630 * 00631 * require 'readline' 00632 * 00633 * Readline.completion_append_character = " " 00634 * Readline.completion_proc = Proc.new do |str| 00635 * Dir[str+'*'].grep(/^#{Regexp.escape(str)}/) 00636 * end 00637 * 00638 * while line = Readline.readline('> ', true) 00639 * p line 00640 * end 00641 * 00642 * = Autocomplete strategies 00643 * 00644 * When working with auto-complete there are some strategies that work well. 00645 * To get some ideas you can take a look at the 00646 * completion.rb[http://svn.ruby-lang.org/repos/ruby/trunk/lib/irb/completion.rb] 00647 * file for irb. 00648 * 00649 * The common strategy is to take a list of possible completions and filter it 00650 * down to those completions that start with the user input. In the above 00651 * examples Enumerator.grep is used. The input is escaped to prevent Regexp 00652 * special characters from interfering with the matching. 00653 * 00654 * It may also be helpful to use the Abbrev library to generate completions. 00655 * 00656 * Raises ArgumentError if +proc+ does not respond to the call method. 00657 * 00658 * Raises SecurityError if $SAFE is 4. 00659 */ 00660 static VALUE 00661 readline_s_set_completion_proc(VALUE self, VALUE proc) 00662 { 00663 rb_secure(4); 00664 if (!NIL_P(proc) && !rb_respond_to(proc, rb_intern("call"))) 00665 rb_raise(rb_eArgError, "argument must respond to `call'"); 00666 return rb_ivar_set(mReadline, completion_proc, proc); 00667 } 00668 00669 /* 00670 * call-seq: 00671 * Readline.completion_proc -> proc 00672 * 00673 * Returns the completion Proc object. 00674 * 00675 * Raises SecurityError exception if $SAFE is 4. 00676 */ 00677 static VALUE 00678 readline_s_get_completion_proc(VALUE self) 00679 { 00680 rb_secure(4); 00681 return rb_attr_get(mReadline, completion_proc); 00682 } 00683 00684 /* 00685 * call-seq: 00686 * Readline.completion_case_fold = bool 00687 * 00688 * Sets whether or not to ignore case on completion. 00689 * 00690 * Raises SecurityError exception if $SAFE is 4. 00691 */ 00692 static VALUE 00693 readline_s_set_completion_case_fold(VALUE self, VALUE val) 00694 { 00695 rb_secure(4); 00696 return rb_ivar_set(mReadline, completion_case_fold, val); 00697 } 00698 00699 /* 00700 * call-seq: 00701 * Readline.completion_case_fold -> bool 00702 * 00703 * Returns true if completion ignores case. If no, returns false. 00704 * 00705 * NOTE: Returns the same object that is specified by 00706 * Readline.completion_case_fold= method. 00707 * 00708 * require "readline" 00709 * 00710 * Readline.completion_case_fold = "This is a String." 00711 * p Readline.completion_case_fold # => "This is a String." 00712 * 00713 * Raises SecurityError exception if $SAFE is 4. 00714 */ 00715 static VALUE 00716 readline_s_get_completion_case_fold(VALUE self) 00717 { 00718 rb_secure(4); 00719 return rb_attr_get(mReadline, completion_case_fold); 00720 } 00721 00722 #ifdef HAVE_RL_LINE_BUFFER 00723 /* 00724 * call-seq: 00725 * Readline.line_buffer -> string 00726 * 00727 * Returns the full line that is being edited. This is useful from 00728 * within the complete_proc for determining the context of the 00729 * completion request. 00730 * 00731 * The length of +Readline.line_buffer+ and GNU Readline's rl_end are 00732 * same. 00733 */ 00734 static VALUE 00735 readline_s_get_line_buffer(VALUE self) 00736 { 00737 rb_secure(4); 00738 if (rl_line_buffer == NULL) 00739 return Qnil; 00740 return rb_locale_str_new_cstr(rl_line_buffer); 00741 } 00742 #else 00743 #define readline_s_get_line_buffer rb_f_notimplement 00744 #endif 00745 00746 #ifdef HAVE_RL_POINT 00747 /* 00748 * call-seq: 00749 * Readline.point -> int 00750 * 00751 * Returns the index of the current cursor position in 00752 * +Readline.line_buffer+. 00753 * 00754 * The index in +Readline.line_buffer+ which matches the start of 00755 * input-string passed to completion_proc is computed by subtracting 00756 * the length of input-string from +Readline.point+. 00757 * 00758 * start = (the length of input-string) - Readline.point 00759 */ 00760 static VALUE 00761 readline_s_get_point(VALUE self) 00762 { 00763 rb_secure(4); 00764 return INT2NUM(rl_point); 00765 } 00766 #else 00767 #define readline_s_get_point rb_f_notimplement 00768 #endif 00769 00770 static char ** 00771 readline_attempted_completion_function(const char *text, int start, int end) 00772 { 00773 VALUE proc, ary, temp; 00774 char **result; 00775 int case_fold; 00776 long i, matches; 00777 rb_encoding *enc; 00778 VALUE encobj; 00779 00780 proc = rb_attr_get(mReadline, completion_proc); 00781 if (NIL_P(proc)) 00782 return NULL; 00783 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER 00784 rl_completion_append_character = readline_completion_append_character; 00785 #endif 00786 #ifdef HAVE_RL_ATTEMPTED_COMPLETION_OVER 00787 rl_attempted_completion_over = 1; 00788 #endif 00789 case_fold = RTEST(rb_attr_get(mReadline, completion_case_fold)); 00790 ary = rb_funcall(proc, rb_intern("call"), 1, rb_locale_str_new_cstr(text)); 00791 if (!RB_TYPE_P(ary, T_ARRAY)) 00792 ary = rb_Array(ary); 00793 matches = RARRAY_LEN(ary); 00794 if (matches == 0) return NULL; 00795 result = (char**)malloc((matches + 2)*sizeof(char*)); 00796 if (result == NULL) rb_memerror(); 00797 enc = rb_locale_encoding(); 00798 encobj = rb_enc_from_encoding(enc); 00799 for (i = 0; i < matches; i++) { 00800 temp = rb_obj_as_string(RARRAY_PTR(ary)[i]); 00801 StringValueCStr(temp); /* must be NUL-terminated */ 00802 rb_enc_check(encobj, temp); 00803 result[i + 1] = (char*)malloc(RSTRING_LEN(temp) + 1); 00804 if (result[i + 1] == NULL) rb_memerror(); 00805 strcpy(result[i + 1], RSTRING_PTR(temp)); 00806 } 00807 result[matches + 1] = NULL; 00808 00809 if (matches == 1) { 00810 result[0] = strdup(result[1]); 00811 } 00812 else { 00813 const char *result1 = result[1]; 00814 long low = strlen(result1); 00815 00816 for (i = 1; i < matches; ++i) { 00817 register int c1, c2; 00818 long i1, i2, l2; 00819 int n1, n2; 00820 const char *p2 = result[i + 1]; 00821 00822 l2 = strlen(p2); 00823 for (i1 = i2 = 0; i1 < low && i2 < l2; i1 += n1, i2 += n2) { 00824 c1 = rb_enc_codepoint_len(result1 + i1, result1 + low, &n1, enc); 00825 c2 = rb_enc_codepoint_len(p2 + i2, p2 + l2, &n2, enc); 00826 if (case_fold) { 00827 c1 = rb_tolower(c1); 00828 c2 = rb_tolower(c2); 00829 } 00830 if (c1 != c2) break; 00831 } 00832 00833 low = i1; 00834 } 00835 result[0] = (char*)malloc(low + 1); 00836 if (result[0] == NULL) rb_memerror(); 00837 strncpy(result[0], result[1], low); 00838 result[0][low] = '\0'; 00839 } 00840 00841 return result; 00842 } 00843 00844 #ifdef HAVE_RL_SET_SCREEN_SIZE 00845 /* 00846 * call-seq: 00847 * Readline.set_screen_size(rows, columns) -> self 00848 * 00849 * Set terminal size to +rows+ and +columns+. 00850 * 00851 * See GNU Readline's rl_set_screen_size function. 00852 * 00853 * Raises NotImplementedError if the using readline library does not support. 00854 * 00855 * Raises SecurityError exception if $SAFE is 4. 00856 */ 00857 static VALUE 00858 readline_s_set_screen_size(VALUE self, VALUE rows, VALUE columns) 00859 { 00860 rb_secure(4); 00861 rl_set_screen_size(NUM2INT(rows), NUM2INT(columns)); 00862 return self; 00863 } 00864 #else 00865 #define readline_s_set_screen_size rb_f_notimplement 00866 #endif 00867 00868 #ifdef HAVE_RL_GET_SCREEN_SIZE 00869 /* 00870 * call-seq: 00871 * Readline.get_screen_size -> [rows, columns] 00872 * 00873 * Returns the terminal's rows and columns. 00874 * 00875 * See GNU Readline's rl_get_screen_size function. 00876 * 00877 * Raises NotImplementedError if the using readline library does not support. 00878 * 00879 * Raises SecurityError exception if $SAFE is 4. 00880 */ 00881 static VALUE 00882 readline_s_get_screen_size(VALUE self) 00883 { 00884 int rows, columns; 00885 VALUE res; 00886 00887 rb_secure(4); 00888 rl_get_screen_size(&rows, &columns); 00889 res = rb_ary_new(); 00890 rb_ary_push(res, INT2NUM(rows)); 00891 rb_ary_push(res, INT2NUM(columns)); 00892 return res; 00893 } 00894 #else 00895 #define readline_s_get_screen_size rb_f_notimplement 00896 #endif 00897 00898 #ifdef HAVE_RL_VI_EDITING_MODE 00899 /* 00900 * call-seq: 00901 * Readline.vi_editing_mode -> nil 00902 * 00903 * Specifies VI editing mode. See the manual of GNU Readline for 00904 * details of VI editing mode. 00905 * 00906 * Raises NotImplementedError if the using readline library does not support. 00907 * 00908 * Raises SecurityError exception if $SAFE is 4. 00909 */ 00910 static VALUE 00911 readline_s_vi_editing_mode(VALUE self) 00912 { 00913 rb_secure(4); 00914 rl_vi_editing_mode(1,0); 00915 return Qnil; 00916 } 00917 #else 00918 #define readline_s_vi_editing_mode rb_f_notimplement 00919 #endif 00920 00921 #ifdef HAVE_RL_EDITING_MODE 00922 /* 00923 * call-seq: 00924 * Readline.vi_editing_mode? -> bool 00925 * 00926 * Returns true if vi mode is active. Returns false if not. 00927 * 00928 * Raises NotImplementedError if the using readline library does not support. 00929 * 00930 * Raises SecurityError exception if $SAFE is 4. 00931 */ 00932 static VALUE 00933 readline_s_vi_editing_mode_p(VALUE self) 00934 { 00935 rb_secure(4); 00936 return rl_editing_mode == 0 ? Qtrue : Qfalse; 00937 } 00938 #else 00939 #define readline_s_vi_editing_mode_p rb_f_notimplement 00940 #endif 00941 00942 #ifdef HAVE_RL_EMACS_EDITING_MODE 00943 /* 00944 * call-seq: 00945 * Readline.emacs_editing_mode -> nil 00946 * 00947 * Specifies Emacs editing mode. The default is this mode. See the 00948 * manual of GNU Readline for details of Emacs editing mode. 00949 * 00950 * Raises NotImplementedError if the using readline library does not support. 00951 * 00952 * Raises SecurityError exception if $SAFE is 4. 00953 */ 00954 static VALUE 00955 readline_s_emacs_editing_mode(VALUE self) 00956 { 00957 rb_secure(4); 00958 rl_emacs_editing_mode(1,0); 00959 return Qnil; 00960 } 00961 #else 00962 #define readline_s_emacs_editing_mode rb_f_notimplement 00963 #endif 00964 00965 #ifdef HAVE_RL_EDITING_MODE 00966 /* 00967 * call-seq: 00968 * Readline.emacs_editing_mode? -> bool 00969 * 00970 * Returns true if emacs mode is active. Returns false if not. 00971 * 00972 * Raises NotImplementedError if the using readline library does not support. 00973 * 00974 * Raises SecurityError exception if $SAFE is 4. 00975 */ 00976 static VALUE 00977 readline_s_emacs_editing_mode_p(VALUE self) 00978 { 00979 rb_secure(4); 00980 return rl_editing_mode == 1 ? Qtrue : Qfalse; 00981 } 00982 #else 00983 #define readline_s_emacs_editing_mode_p rb_f_notimplement 00984 #endif 00985 00986 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER 00987 /* 00988 * call-seq: 00989 * Readline.completion_append_character = char 00990 * 00991 * Specifies a character to be appended on completion. 00992 * Nothing will be appended if an empty string ("") or nil is 00993 * specified. 00994 * 00995 * For example: 00996 * require "readline" 00997 * 00998 * Readline.readline("> ", true) 00999 * Readline.completion_append_character = " " 01000 * 01001 * Result: 01002 * > 01003 * Input "/var/li". 01004 * 01005 * > /var/li 01006 * Press TAB key. 01007 * 01008 * > /var/lib 01009 * Completes "b" and appends " ". So, you can continuously input "/usr". 01010 * 01011 * > /var/lib /usr 01012 * 01013 * NOTE: Only one character can be specified. When "string" is 01014 * specified, sets only "s" that is the first. 01015 * 01016 * require "readline" 01017 * 01018 * Readline.completion_append_character = "string" 01019 * p Readline.completion_append_character # => "s" 01020 * 01021 * Raises NotImplementedError if the using readline library does not support. 01022 * 01023 * Raises SecurityError exception if $SAFE is 4. 01024 */ 01025 static VALUE 01026 readline_s_set_completion_append_character(VALUE self, VALUE str) 01027 { 01028 rb_secure(4); 01029 if (NIL_P(str)) { 01030 rl_completion_append_character = '\0'; 01031 } 01032 else { 01033 OutputStringValue(str); 01034 if (RSTRING_LEN(str) == 0) { 01035 rl_completion_append_character = '\0'; 01036 } else { 01037 rl_completion_append_character = RSTRING_PTR(str)[0]; 01038 } 01039 } 01040 return self; 01041 } 01042 #else 01043 #define readline_s_set_completion_append_character rb_f_notimplement 01044 #endif 01045 01046 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER 01047 /* 01048 * call-seq: 01049 * Readline.completion_append_character -> char 01050 * 01051 * Returns a string containing a character to be appended on 01052 * completion. The default is a space (" "). 01053 * 01054 * Raises NotImplementedError if the using readline library does not support. 01055 * 01056 * Raises SecurityError exception if $SAFE is 4. 01057 */ 01058 static VALUE 01059 readline_s_get_completion_append_character(VALUE self) 01060 { 01061 char buf[1]; 01062 01063 rb_secure(4); 01064 if (rl_completion_append_character == '\0') 01065 return Qnil; 01066 01067 buf[0] = (char) rl_completion_append_character; 01068 return rb_locale_str_new(buf, 1); 01069 } 01070 #else 01071 #define readline_s_get_completion_append_character rb_f_notimplement 01072 #endif 01073 01074 #ifdef HAVE_RL_BASIC_WORD_BREAK_CHARACTERS 01075 /* 01076 * call-seq: 01077 * Readline.basic_word_break_characters = string 01078 * 01079 * Sets the basic list of characters that signal a break between words 01080 * for the completer routine. The default is the characters which 01081 * break words for completion in Bash: " \t\n\"\\'`@$><=;|&{(". 01082 * 01083 * Raises NotImplementedError if the using readline library does not support. 01084 * 01085 * Raises SecurityError exception if $SAFE is 4. 01086 */ 01087 static VALUE 01088 readline_s_set_basic_word_break_characters(VALUE self, VALUE str) 01089 { 01090 static char *basic_word_break_characters = NULL; 01091 01092 rb_secure(4); 01093 OutputStringValue(str); 01094 if (basic_word_break_characters == NULL) { 01095 basic_word_break_characters = 01096 ALLOC_N(char, RSTRING_LEN(str) + 1); 01097 } 01098 else { 01099 REALLOC_N(basic_word_break_characters, char, RSTRING_LEN(str) + 1); 01100 } 01101 strncpy(basic_word_break_characters, 01102 RSTRING_PTR(str), RSTRING_LEN(str)); 01103 basic_word_break_characters[RSTRING_LEN(str)] = '\0'; 01104 rl_basic_word_break_characters = basic_word_break_characters; 01105 return self; 01106 } 01107 #else 01108 #define readline_s_set_basic_word_break_characters rb_f_notimplement 01109 #endif 01110 01111 #ifdef HAVE_RL_BASIC_WORD_BREAK_CHARACTERS 01112 /* 01113 * call-seq: 01114 * Readline.basic_word_break_characters -> string 01115 * 01116 * Gets the basic list of characters that signal a break between words 01117 * for the completer routine. 01118 * 01119 * Raises NotImplementedError if the using readline library does not support. 01120 * 01121 * Raises SecurityError exception if $SAFE is 4. 01122 */ 01123 static VALUE 01124 readline_s_get_basic_word_break_characters(VALUE self, VALUE str) 01125 { 01126 rb_secure(4); 01127 if (rl_basic_word_break_characters == NULL) 01128 return Qnil; 01129 return rb_locale_str_new_cstr(rl_basic_word_break_characters); 01130 } 01131 #else 01132 #define readline_s_get_basic_word_break_characters rb_f_notimplement 01133 #endif 01134 01135 #ifdef HAVE_RL_COMPLETER_WORD_BREAK_CHARACTERS 01136 /* 01137 * call-seq: 01138 * Readline.completer_word_break_characters = string 01139 * 01140 * Sets the basic list of characters that signal a break between words 01141 * for rl_complete_internal(). The default is the value of 01142 * Readline.basic_word_break_characters. 01143 * 01144 * Raises NotImplementedError if the using readline library does not support. 01145 * 01146 * Raises SecurityError exception if $SAFE is 4. 01147 */ 01148 static VALUE 01149 readline_s_set_completer_word_break_characters(VALUE self, VALUE str) 01150 { 01151 static char *completer_word_break_characters = NULL; 01152 01153 rb_secure(4); 01154 OutputStringValue(str); 01155 if (completer_word_break_characters == NULL) { 01156 completer_word_break_characters = 01157 ALLOC_N(char, RSTRING_LEN(str) + 1); 01158 } 01159 else { 01160 REALLOC_N(completer_word_break_characters, char, RSTRING_LEN(str) + 1); 01161 } 01162 strncpy(completer_word_break_characters, 01163 RSTRING_PTR(str), RSTRING_LEN(str)); 01164 completer_word_break_characters[RSTRING_LEN(str)] = '\0'; 01165 rl_completer_word_break_characters = completer_word_break_characters; 01166 return self; 01167 } 01168 #else 01169 #define readline_s_set_completer_word_break_characters rb_f_notimplement 01170 #endif 01171 01172 #ifdef HAVE_RL_COMPLETER_WORD_BREAK_CHARACTERS 01173 /* 01174 * call-seq: 01175 * Readline.completer_word_break_characters -> string 01176 * 01177 * Gets the basic list of characters that signal a break between words 01178 * for rl_complete_internal(). 01179 * 01180 * Raises NotImplementedError if the using readline library does not support. 01181 * 01182 * Raises SecurityError exception if $SAFE is 4. 01183 */ 01184 static VALUE 01185 readline_s_get_completer_word_break_characters(VALUE self, VALUE str) 01186 { 01187 rb_secure(4); 01188 if (rl_completer_word_break_characters == NULL) 01189 return Qnil; 01190 return rb_locale_str_new_cstr(rl_completer_word_break_characters); 01191 } 01192 #else 01193 #define readline_s_get_completer_word_break_characters rb_f_notimplement 01194 #endif 01195 01196 #if defined(HAVE_RL_SPECIAL_PREFIXES) 01197 /* 01198 * call-seq: 01199 * Readline.special_prefixes = string 01200 * 01201 * Sets the list of characters that are word break characters, but 01202 * should be left in text when it is passed to the completion 01203 * function. Programs can use this to help determine what kind of 01204 * completing to do. For instance, Bash sets this variable to "$@" so 01205 * that it can complete shell variables and hostnames. 01206 * 01207 * See GNU Readline's rl_special_prefixes variable. 01208 * 01209 * Raises NotImplementedError if the using readline library does not support. 01210 * 01211 * Raises SecurityError exception if $SAFE is 4. 01212 */ 01213 static VALUE 01214 readline_s_set_special_prefixes(VALUE self, VALUE str) 01215 { 01216 rb_secure(4); 01217 if (!NIL_P(str)) { 01218 OutputStringValue(str); 01219 str = rb_str_dup_frozen(str); 01220 RBASIC(str)->klass = 0; 01221 } 01222 rb_ivar_set(mReadline, id_special_prefixes, str); 01223 if (NIL_P(str)) { 01224 rl_special_prefixes = NULL; 01225 } 01226 else { 01227 rl_special_prefixes = RSTRING_PTR(str); 01228 } 01229 return self; 01230 } 01231 01232 /* 01233 * call-seq: 01234 * Readline.special_prefixes -> string 01235 * 01236 * Gets the list of characters that are word break characters, but 01237 * should be left in text when it is passed to the completion 01238 * function. 01239 * 01240 * See GNU Readline's rl_special_prefixes variable. 01241 * 01242 * Raises NotImplementedError if the using readline library does not support. 01243 * 01244 * Raises SecurityError exception if $SAFE is 4. 01245 */ 01246 static VALUE 01247 readline_s_get_special_prefixes(VALUE self) 01248 { 01249 VALUE str; 01250 rb_secure(4); 01251 if (rl_special_prefixes == NULL) return Qnil; 01252 str = rb_ivar_get(mReadline, id_special_prefixes); 01253 if (!NIL_P(str)) { 01254 str = rb_str_dup_frozen(str); 01255 RBASIC(str)->klass = rb_cString; 01256 } 01257 return str; 01258 } 01259 #else 01260 #define readline_s_set_special_prefixes rb_f_notimplement 01261 #define readline_s_get_special_prefixes rb_f_notimplement 01262 #endif 01263 01264 #ifdef HAVE_RL_BASIC_QUOTE_CHARACTERS 01265 /* 01266 * call-seq: 01267 * Readline.basic_quote_characters = string 01268 * 01269 * Sets a list of quote characters which can cause a word break. 01270 * 01271 * Raises NotImplementedError if the using readline library does not support. 01272 * 01273 * Raises SecurityError exception if $SAFE is 4. 01274 */ 01275 static VALUE 01276 readline_s_set_basic_quote_characters(VALUE self, VALUE str) 01277 { 01278 static char *basic_quote_characters = NULL; 01279 01280 rb_secure(4); 01281 OutputStringValue(str); 01282 if (basic_quote_characters == NULL) { 01283 basic_quote_characters = 01284 ALLOC_N(char, RSTRING_LEN(str) + 1); 01285 } 01286 else { 01287 REALLOC_N(basic_quote_characters, char, RSTRING_LEN(str) + 1); 01288 } 01289 strncpy(basic_quote_characters, 01290 RSTRING_PTR(str), RSTRING_LEN(str)); 01291 basic_quote_characters[RSTRING_LEN(str)] = '\0'; 01292 rl_basic_quote_characters = basic_quote_characters; 01293 01294 return self; 01295 } 01296 #else 01297 #define readline_s_set_basic_quote_characters rb_f_notimplement 01298 #endif 01299 01300 #ifdef HAVE_RL_BASIC_QUOTE_CHARACTERS 01301 /* 01302 * call-seq: 01303 * Readline.basic_quote_characters -> string 01304 * 01305 * Gets a list of quote characters which can cause a word break. 01306 * 01307 * Raises NotImplementedError if the using readline library does not support. 01308 * 01309 * Raises SecurityError exception if $SAFE is 4. 01310 */ 01311 static VALUE 01312 readline_s_get_basic_quote_characters(VALUE self, VALUE str) 01313 { 01314 rb_secure(4); 01315 if (rl_basic_quote_characters == NULL) 01316 return Qnil; 01317 return rb_locale_str_new_cstr(rl_basic_quote_characters); 01318 } 01319 #else 01320 #define readline_s_get_basic_quote_characters rb_f_notimplement 01321 #endif 01322 01323 #ifdef HAVE_RL_COMPLETER_QUOTE_CHARACTERS 01324 /* 01325 * call-seq: 01326 * Readline.completer_quote_characters = string 01327 * 01328 * Sets a list of characters which can be used to quote a substring of 01329 * the line. Completion occurs on the entire substring, and within 01330 * the substring Readline.completer_word_break_characters are treated 01331 * as any other character, unless they also appear within this list. 01332 * 01333 * Raises NotImplementedError if the using readline library does not support. 01334 * 01335 * Raises SecurityError exception if $SAFE is 4. 01336 */ 01337 static VALUE 01338 readline_s_set_completer_quote_characters(VALUE self, VALUE str) 01339 { 01340 static char *completer_quote_characters = NULL; 01341 01342 rb_secure(4); 01343 OutputStringValue(str); 01344 if (completer_quote_characters == NULL) { 01345 completer_quote_characters = 01346 ALLOC_N(char, RSTRING_LEN(str) + 1); 01347 } 01348 else { 01349 REALLOC_N(completer_quote_characters, char, RSTRING_LEN(str) + 1); 01350 } 01351 strncpy(completer_quote_characters, RSTRING_PTR(str), RSTRING_LEN(str)); 01352 completer_quote_characters[RSTRING_LEN(str)] = '\0'; 01353 rl_completer_quote_characters = completer_quote_characters; 01354 01355 return self; 01356 } 01357 #else 01358 #define readline_s_set_completer_quote_characters rb_f_notimplement 01359 #endif 01360 01361 #ifdef HAVE_RL_COMPLETER_QUOTE_CHARACTERS 01362 /* 01363 * call-seq: 01364 * Readline.completer_quote_characters -> string 01365 * 01366 * Gets a list of characters which can be used to quote a substring of 01367 * the line. 01368 * 01369 * Raises NotImplementedError if the using readline library does not support. 01370 * 01371 * Raises SecurityError exception if $SAFE is 4. 01372 */ 01373 static VALUE 01374 readline_s_get_completer_quote_characters(VALUE self, VALUE str) 01375 { 01376 rb_secure(4); 01377 if (rl_completer_quote_characters == NULL) 01378 return Qnil; 01379 return rb_locale_str_new_cstr(rl_completer_quote_characters); 01380 } 01381 #else 01382 #define readline_s_get_completer_quote_characters rb_f_notimplement 01383 #endif 01384 01385 #ifdef HAVE_RL_FILENAME_QUOTE_CHARACTERS 01386 /* 01387 * call-seq: 01388 * Readline.filename_quote_characters = string 01389 * 01390 * Sets a list of characters that cause a filename to be quoted by the completer 01391 * when they appear in a completed filename. The default is nil. 01392 * 01393 * Raises NotImplementedError if the using readline library does not support. 01394 * 01395 * Raises SecurityError exception if $SAFE is 4. 01396 */ 01397 static VALUE 01398 readline_s_set_filename_quote_characters(VALUE self, VALUE str) 01399 { 01400 static char *filename_quote_characters = NULL; 01401 01402 rb_secure(4); 01403 OutputStringValue(str); 01404 if (filename_quote_characters == NULL) { 01405 filename_quote_characters = 01406 ALLOC_N(char, RSTRING_LEN(str) + 1); 01407 } 01408 else { 01409 REALLOC_N(filename_quote_characters, char, RSTRING_LEN(str) + 1); 01410 } 01411 strncpy(filename_quote_characters, RSTRING_PTR(str), RSTRING_LEN(str)); 01412 filename_quote_characters[RSTRING_LEN(str)] = '\0'; 01413 rl_filename_quote_characters = filename_quote_characters; 01414 01415 return self; 01416 } 01417 #else 01418 #define readline_s_set_filename_quote_characters rb_f_notimplement 01419 #endif 01420 01421 #ifdef HAVE_RL_FILENAME_QUOTE_CHARACTERS 01422 /* 01423 * call-seq: 01424 * Readline.filename_quote_characters -> string 01425 * 01426 * Gets a list of characters that cause a filename to be quoted by the completer 01427 * when they appear in a completed filename. 01428 * 01429 * Raises NotImplementedError if the using readline library does not support. 01430 * 01431 * Raises SecurityError exception if $SAFE is 4. 01432 */ 01433 static VALUE 01434 readline_s_get_filename_quote_characters(VALUE self, VALUE str) 01435 { 01436 rb_secure(4); 01437 if (rl_filename_quote_characters == NULL) 01438 return Qnil; 01439 return rb_locale_str_new_cstr(rl_filename_quote_characters); 01440 } 01441 #else 01442 #define readline_s_get_filename_quote_characters rb_f_notimplement 01443 #endif 01444 01445 #ifdef HAVE_RL_REFRESH_LINE 01446 /* 01447 * call-seq: 01448 * Readline.refresh_line -> nil 01449 * 01450 * Clear the current input line. 01451 * 01452 * Raises SecurityError exception if $SAFE is 4. 01453 */ 01454 static VALUE 01455 readline_s_refresh_line(VALUE self) 01456 { 01457 rb_secure(4); 01458 rl_refresh_line(0, 0); 01459 return Qnil; 01460 } 01461 #else 01462 #define readline_s_refresh_line rb_f_notimplement 01463 #endif 01464 01465 static VALUE 01466 hist_to_s(VALUE self) 01467 { 01468 return rb_str_new_cstr("HISTORY"); 01469 } 01470 01471 static int 01472 history_get_offset_history_base(int offset) 01473 { 01474 return history_base + offset; 01475 } 01476 01477 static int 01478 history_get_offset_0(int offset) 01479 { 01480 return offset; 01481 } 01482 01483 static VALUE 01484 hist_get(VALUE self, VALUE index) 01485 { 01486 HIST_ENTRY *entry = NULL; 01487 int i; 01488 01489 rb_secure(4); 01490 i = NUM2INT(index); 01491 if (i < 0) { 01492 i += history_length; 01493 } 01494 if (i >= 0) { 01495 entry = history_get(history_get_offset_func(i)); 01496 } 01497 if (entry == NULL) { 01498 rb_raise(rb_eIndexError, "invalid index"); 01499 } 01500 return rb_locale_str_new_cstr(entry->line); 01501 } 01502 01503 #ifdef HAVE_REPLACE_HISTORY_ENTRY 01504 static VALUE 01505 hist_set(VALUE self, VALUE index, VALUE str) 01506 { 01507 HIST_ENTRY *entry = NULL; 01508 int i; 01509 01510 rb_secure(4); 01511 i = NUM2INT(index); 01512 OutputStringValue(str); 01513 if (i < 0) { 01514 i += history_length; 01515 } 01516 if (i >= 0) { 01517 entry = replace_history_entry(history_replace_offset_func(i), RSTRING_PTR(str), NULL); 01518 } 01519 if (entry == NULL) { 01520 rb_raise(rb_eIndexError, "invalid index"); 01521 } 01522 return str; 01523 } 01524 #else 01525 #define hist_set rb_f_notimplement 01526 #endif 01527 01528 static VALUE 01529 hist_push(VALUE self, VALUE str) 01530 { 01531 rb_secure(4); 01532 OutputStringValue(str); 01533 add_history(RSTRING_PTR(str)); 01534 return self; 01535 } 01536 01537 static VALUE 01538 hist_push_method(int argc, VALUE *argv, VALUE self) 01539 { 01540 VALUE str; 01541 01542 rb_secure(4); 01543 while (argc--) { 01544 str = *argv++; 01545 OutputStringValue(str); 01546 add_history(RSTRING_PTR(str)); 01547 } 01548 return self; 01549 } 01550 01551 static VALUE 01552 rb_remove_history(int index) 01553 { 01554 #ifdef HAVE_REMOVE_HISTORY 01555 HIST_ENTRY *entry; 01556 VALUE val; 01557 01558 rb_secure(4); 01559 entry = remove_history(index); 01560 if (entry) { 01561 val = rb_locale_str_new_cstr(entry->line); 01562 free((void *) entry->line); 01563 free(entry); 01564 return val; 01565 } 01566 return Qnil; 01567 #else 01568 rb_notimplement(); 01569 01570 UNREACHABLE; 01571 #endif 01572 } 01573 01574 static VALUE 01575 hist_pop(VALUE self) 01576 { 01577 rb_secure(4); 01578 if (history_length > 0) { 01579 return rb_remove_history(history_length - 1); 01580 } else { 01581 return Qnil; 01582 } 01583 } 01584 01585 static VALUE 01586 hist_shift(VALUE self) 01587 { 01588 rb_secure(4); 01589 if (history_length > 0) { 01590 return rb_remove_history(0); 01591 } else { 01592 return Qnil; 01593 } 01594 } 01595 01596 static VALUE 01597 hist_each(VALUE self) 01598 { 01599 HIST_ENTRY *entry; 01600 int i; 01601 01602 RETURN_ENUMERATOR(self, 0, 0); 01603 01604 rb_secure(4); 01605 for (i = 0; i < history_length; i++) { 01606 entry = history_get(history_get_offset_func(i)); 01607 if (entry == NULL) 01608 break; 01609 rb_yield(rb_locale_str_new_cstr(entry->line)); 01610 } 01611 return self; 01612 } 01613 01614 static VALUE 01615 hist_length(VALUE self) 01616 { 01617 rb_secure(4); 01618 return INT2NUM(history_length); 01619 } 01620 01621 static VALUE 01622 hist_empty_p(VALUE self) 01623 { 01624 rb_secure(4); 01625 return history_length == 0 ? Qtrue : Qfalse; 01626 } 01627 01628 static VALUE 01629 hist_delete_at(VALUE self, VALUE index) 01630 { 01631 int i; 01632 01633 rb_secure(4); 01634 i = NUM2INT(index); 01635 if (i < 0) 01636 i += history_length; 01637 if (i < 0 || i > history_length - 1) { 01638 rb_raise(rb_eIndexError, "invalid index"); 01639 } 01640 return rb_remove_history(i); 01641 } 01642 01643 #ifdef HAVE_CLEAR_HISTORY 01644 static VALUE 01645 hist_clear(VALUE self) 01646 { 01647 rb_secure(4); 01648 clear_history(); 01649 return self; 01650 } 01651 #else 01652 #define hist_clear rb_f_notimplement 01653 #endif 01654 01655 static VALUE 01656 filename_completion_proc_call(VALUE self, VALUE str) 01657 { 01658 VALUE result; 01659 char **matches; 01660 int i; 01661 01662 matches = rl_completion_matches(StringValuePtr(str), 01663 rl_filename_completion_function); 01664 if (matches) { 01665 result = rb_ary_new(); 01666 for (i = 0; matches[i]; i++) { 01667 rb_ary_push(result, rb_locale_str_new_cstr(matches[i])); 01668 free(matches[i]); 01669 } 01670 free(matches); 01671 if (RARRAY_LEN(result) >= 2) 01672 rb_ary_shift(result); 01673 } 01674 else { 01675 result = Qnil; 01676 } 01677 return result; 01678 } 01679 01680 static VALUE 01681 username_completion_proc_call(VALUE self, VALUE str) 01682 { 01683 VALUE result; 01684 char **matches; 01685 int i; 01686 01687 matches = rl_completion_matches(StringValuePtr(str), 01688 rl_username_completion_function); 01689 if (matches) { 01690 result = rb_ary_new(); 01691 for (i = 0; matches[i]; i++) { 01692 rb_ary_push(result, rb_locale_str_new_cstr(matches[i])); 01693 free(matches[i]); 01694 } 01695 free(matches); 01696 if (RARRAY_LEN(result) >= 2) 01697 rb_ary_shift(result); 01698 } 01699 else { 01700 result = Qnil; 01701 } 01702 return result; 01703 } 01704 01705 void 01706 Init_readline() 01707 { 01708 VALUE history, fcomp, ucomp, version; 01709 01710 /* Allow conditional parsing of the ~/.inputrc file. */ 01711 rl_readline_name = (char *)"Ruby"; 01712 01713 #if defined HAVE_RL_GETC_FUNCTION 01714 /* libedit check rl_getc_function only when rl_initialize() is called, */ 01715 /* and using_history() call rl_initialize(). */ 01716 /* This assignment should be placed before using_history() */ 01717 rl_getc_function = readline_getc; 01718 #elif defined HAVE_RL_EVENT_HOOK 01719 rl_event_hook = readline_event; 01720 #endif 01721 01722 using_history(); 01723 01724 completion_proc = rb_intern(COMPLETION_PROC); 01725 completion_case_fold = rb_intern(COMPLETION_CASE_FOLD); 01726 #if defined(HAVE_RL_PRE_INPUT_HOOK) 01727 id_pre_input_hook = rb_intern("pre_input_hook"); 01728 #endif 01729 #if defined(HAVE_RL_SPECIAL_PREFIXES) 01730 id_special_prefixes = rb_intern("special_prefixes"); 01731 #endif 01732 01733 mReadline = rb_define_module("Readline"); 01734 rb_define_module_function(mReadline, "readline", 01735 readline_readline, -1); 01736 rb_define_singleton_method(mReadline, "input=", 01737 readline_s_set_input, 1); 01738 rb_define_singleton_method(mReadline, "output=", 01739 readline_s_set_output, 1); 01740 rb_define_singleton_method(mReadline, "completion_proc=", 01741 readline_s_set_completion_proc, 1); 01742 rb_define_singleton_method(mReadline, "completion_proc", 01743 readline_s_get_completion_proc, 0); 01744 rb_define_singleton_method(mReadline, "completion_case_fold=", 01745 readline_s_set_completion_case_fold, 1); 01746 rb_define_singleton_method(mReadline, "completion_case_fold", 01747 readline_s_get_completion_case_fold, 0); 01748 rb_define_singleton_method(mReadline, "line_buffer", 01749 readline_s_get_line_buffer, 0); 01750 rb_define_singleton_method(mReadline, "point", 01751 readline_s_get_point, 0); 01752 rb_define_singleton_method(mReadline, "set_screen_size", 01753 readline_s_set_screen_size, 2); 01754 rb_define_singleton_method(mReadline, "get_screen_size", 01755 readline_s_get_screen_size, 0); 01756 rb_define_singleton_method(mReadline, "vi_editing_mode", 01757 readline_s_vi_editing_mode, 0); 01758 rb_define_singleton_method(mReadline, "vi_editing_mode?", 01759 readline_s_vi_editing_mode_p, 0); 01760 rb_define_singleton_method(mReadline, "emacs_editing_mode", 01761 readline_s_emacs_editing_mode, 0); 01762 rb_define_singleton_method(mReadline, "emacs_editing_mode?", 01763 readline_s_emacs_editing_mode_p, 0); 01764 rb_define_singleton_method(mReadline, "completion_append_character=", 01765 readline_s_set_completion_append_character, 1); 01766 rb_define_singleton_method(mReadline, "completion_append_character", 01767 readline_s_get_completion_append_character, 0); 01768 rb_define_singleton_method(mReadline, "basic_word_break_characters=", 01769 readline_s_set_basic_word_break_characters, 1); 01770 rb_define_singleton_method(mReadline, "basic_word_break_characters", 01771 readline_s_get_basic_word_break_characters, 0); 01772 rb_define_singleton_method(mReadline, "completer_word_break_characters=", 01773 readline_s_set_completer_word_break_characters, 1); 01774 rb_define_singleton_method(mReadline, "completer_word_break_characters", 01775 readline_s_get_completer_word_break_characters, 0); 01776 rb_define_singleton_method(mReadline, "basic_quote_characters=", 01777 readline_s_set_basic_quote_characters, 1); 01778 rb_define_singleton_method(mReadline, "basic_quote_characters", 01779 readline_s_get_basic_quote_characters, 0); 01780 rb_define_singleton_method(mReadline, "completer_quote_characters=", 01781 readline_s_set_completer_quote_characters, 1); 01782 rb_define_singleton_method(mReadline, "completer_quote_characters", 01783 readline_s_get_completer_quote_characters, 0); 01784 rb_define_singleton_method(mReadline, "filename_quote_characters=", 01785 readline_s_set_filename_quote_characters, 1); 01786 rb_define_singleton_method(mReadline, "filename_quote_characters", 01787 readline_s_get_filename_quote_characters, 0); 01788 rb_define_singleton_method(mReadline, "refresh_line", 01789 readline_s_refresh_line, 0); 01790 rb_define_singleton_method(mReadline, "pre_input_hook=", 01791 readline_s_set_pre_input_hook, 1); 01792 rb_define_singleton_method(mReadline, "pre_input_hook", 01793 readline_s_get_pre_input_hook, 0); 01794 rb_define_singleton_method(mReadline, "insert_text", 01795 readline_s_insert_text, 1); 01796 rb_define_singleton_method(mReadline, "redisplay", 01797 readline_s_redisplay, 0); 01798 rb_define_singleton_method(mReadline, "special_prefixes=", 01799 readline_s_set_special_prefixes, 1); 01800 rb_define_singleton_method(mReadline, "special_prefixes", 01801 readline_s_get_special_prefixes, 0); 01802 01803 #if USE_INSERT_IGNORE_ESCAPE 01804 CONST_ID(id_orig_prompt, "orig_prompt"); 01805 CONST_ID(id_last_prompt, "last_prompt"); 01806 #endif 01807 01808 history = rb_obj_alloc(rb_cObject); 01809 rb_extend_object(history, rb_mEnumerable); 01810 rb_define_singleton_method(history,"to_s", hist_to_s, 0); 01811 rb_define_singleton_method(history,"[]", hist_get, 1); 01812 rb_define_singleton_method(history,"[]=", hist_set, 2); 01813 rb_define_singleton_method(history,"<<", hist_push, 1); 01814 rb_define_singleton_method(history,"push", hist_push_method, -1); 01815 rb_define_singleton_method(history,"pop", hist_pop, 0); 01816 rb_define_singleton_method(history,"shift", hist_shift, 0); 01817 rb_define_singleton_method(history,"each", hist_each, 0); 01818 rb_define_singleton_method(history,"length", hist_length, 0); 01819 rb_define_singleton_method(history,"size", hist_length, 0); 01820 rb_define_singleton_method(history,"empty?", hist_empty_p, 0); 01821 rb_define_singleton_method(history,"delete_at", hist_delete_at, 1); 01822 rb_define_singleton_method(history,"clear", hist_clear, 0); 01823 01824 /* 01825 * The history buffer. It extends Enumerable module, so it behaves 01826 * just like an array. 01827 * For example, gets the fifth content that the user input by 01828 * HISTORY[4]. 01829 */ 01830 rb_define_const(mReadline, "HISTORY", history); 01831 01832 fcomp = rb_obj_alloc(rb_cObject); 01833 rb_define_singleton_method(fcomp, "call", 01834 filename_completion_proc_call, 1); 01835 /* 01836 * The Object with the call method that is a completion for filename. 01837 * This is sets by Readline.completion_proc= method. 01838 */ 01839 rb_define_const(mReadline, "FILENAME_COMPLETION_PROC", fcomp); 01840 01841 ucomp = rb_obj_alloc(rb_cObject); 01842 rb_define_singleton_method(ucomp, "call", 01843 username_completion_proc_call, 1); 01844 /* 01845 * The Object with the call method that is a completion for usernames. 01846 * This is sets by Readline.completion_proc= method. 01847 */ 01848 rb_define_const(mReadline, "USERNAME_COMPLETION_PROC", ucomp); 01849 history_get_offset_func = history_get_offset_history_base; 01850 history_replace_offset_func = history_get_offset_0; 01851 #if defined HAVE_RL_LIBRARY_VERSION 01852 version = rb_str_new_cstr(rl_library_version); 01853 #if defined HAVE_CLEAR_HISTORY || defined HAVE_REMOVE_HISTORY 01854 if (strncmp(rl_library_version, EDIT_LINE_LIBRARY_VERSION, 01855 strlen(EDIT_LINE_LIBRARY_VERSION)) == 0) { 01856 add_history("1"); 01857 if (history_get(history_get_offset_func(0)) == NULL) { 01858 history_get_offset_func = history_get_offset_0; 01859 } 01860 #ifdef HAVE_REPLACE_HISTORY_ENTRY 01861 if (replace_history_entry(0, "a", NULL) == NULL) { 01862 history_replace_offset_func = history_get_offset_history_base; 01863 } 01864 #endif 01865 #ifdef HAVE_CLEAR_HISTORY 01866 clear_history(); 01867 #else 01868 { 01869 HIST_ENTRY *entry = remove_history(0); 01870 if (entry) { 01871 free((char *)entry->line); 01872 free(entry); 01873 } 01874 } 01875 #endif 01876 } 01877 #endif 01878 #else 01879 version = rb_str_new_cstr("2.0 or prior version"); 01880 #endif 01881 /* Version string of GNU Readline or libedit. */ 01882 rb_define_const(mReadline, "VERSION", version); 01883 01884 rl_attempted_completion_function = readline_attempted_completion_function; 01885 #if defined(HAVE_RL_PRE_INPUT_HOOK) 01886 rl_pre_input_hook = (Function *)readline_pre_input_hook; 01887 #endif 01888 #ifdef HAVE_RL_CATCH_SIGNALS 01889 rl_catch_signals = 0; 01890 #endif 01891 #ifdef HAVE_RL_CLEAR_SIGNALS 01892 rl_clear_signals(); 01893 #endif 01894 01895 readline_s_set_input(mReadline, rb_stdin); 01896 } 01897