ext/readline/readline.c

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

Generated on 19 Jul 2016 for Ruby by  doxygen 1.4.7