00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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(HAVE_RL_PROMPT_START_IGNORE) && defined(HAVE_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
00065 #ifndef HAVE_RL_FILENAME_COMPLETION_FUNCTION
00066 # define rl_filename_completion_function filename_completion_function
00067 #endif
00068 #ifndef HAVE_RL_USERNAME_COMPLETION_FUNCTION
00069 # define rl_username_completion_function username_completion_function
00070 #endif
00071 #ifndef HAVE_RL_COMPLETION_MATCHES
00072 # define rl_completion_matches completion_matches
00073 #endif
00074
00075 static int (*history_get_offset_func)(int);
00076 static int (*history_replace_offset_func)(int);
00077 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
00078 static int readline_completion_append_character;
00079 #endif
00080
00081 static char **readline_attempted_completion_function(const char *text,
00082 int start, int end);
00083
00084 #define OutputStringValue(str) do {\
00085 SafeStringValue(str);\
00086 (str) = rb_str_conv_enc((str), rb_enc_get(str), rb_locale_encoding());\
00087 } while (0)\
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125 #if defined HAVE_RL_GETC_FUNCTION
00126 static VALUE readline_instream;
00127 static ID id_getbyte;
00128
00129 #ifndef HAVE_RL_GETC
00130 #define rl_getc(f) EOF
00131 #endif
00132
00133 static int readline_getc(FILE *);
00134 static int
00135 readline_getc(FILE *input)
00136 {
00137 rb_io_t *ifp = 0;
00138 VALUE c;
00139 if (!readline_instream) return rl_getc(input);
00140 GetOpenFile(readline_instream, ifp);
00141 if (rl_instream != ifp->stdio_file) return rl_getc(input);
00142 #if defined(_WIN32)
00143 {
00144 INPUT_RECORD ir;
00145 int n;
00146 static int prior_key = '0';
00147 for (;;) {
00148 if (prior_key > 0xff) {
00149 prior_key = rl_getc(ifp->stdio_file);
00150 return prior_key;
00151 }
00152 if (PeekConsoleInput((HANDLE)_get_osfhandle(ifp->fd), &ir, 1, &n)) {
00153 if (n == 1) {
00154 if (ir.EventType == KEY_EVENT && ir.Event.KeyEvent.bKeyDown) {
00155 prior_key = rl_getc(ifp->stdio_file);
00156 return prior_key;
00157 } else {
00158 ReadConsoleInput((HANDLE)_get_osfhandle(ifp->fd), &ir, 1, &n);
00159 }
00160 } else {
00161 HANDLE h = (HANDLE)_get_osfhandle(ifp->fd);
00162 rb_w32_wait_events(&h, 1, INFINITE);
00163 }
00164 } else {
00165 break;
00166 }
00167 }
00168 }
00169 #endif
00170 c = rb_funcall(readline_instream, id_getbyte, 0, 0);
00171 if (NIL_P(c)) return EOF;
00172 return NUM2CHR(c);
00173 }
00174 #elif defined HAVE_RL_EVENT_HOOK
00175 #define BUSY_WAIT 0
00176
00177 static int readline_event(void);
00178 static int
00179 readline_event(void)
00180 {
00181 #if BUSY_WAIT
00182 rb_thread_schedule();
00183 #else
00184 rb_wait_for_single_fd(fileno(rl_instream), RB_WAITFD_IN, NULL);
00185 return 0;
00186 #endif
00187 }
00188 #endif
00189
00190 #if USE_INSERT_IGNORE_ESCAPE
00191 static VALUE
00192 insert_ignore_escape(VALUE self, VALUE prompt)
00193 {
00194 VALUE last_prompt, orig_prompt = rb_attr_get(self, id_orig_prompt);
00195 int ignoring = 0;
00196 const char *s0, *s, *e;
00197 long len;
00198 static const char ignore_code[2] = {RL_PROMPT_START_IGNORE, RL_PROMPT_END_IGNORE};
00199
00200 prompt = rb_str_new_shared(prompt);
00201 last_prompt = rb_attr_get(self, id_last_prompt);
00202 if (orig_prompt == prompt) return last_prompt;
00203 len = RSTRING_LEN(prompt);
00204 if (NIL_P(last_prompt)) {
00205 last_prompt = rb_str_tmp_new(len);
00206 }
00207
00208 s = s0 = RSTRING_PTR(prompt);
00209 e = s0 + len;
00210 rb_str_set_len(last_prompt, 0);
00211 while (s < e && *s) {
00212 switch (*s) {
00213 case RL_PROMPT_START_IGNORE:
00214 ignoring = -1;
00215 rb_str_cat(last_prompt, s0, ++s - s0);
00216 s0 = s;
00217 break;
00218 case RL_PROMPT_END_IGNORE:
00219 ignoring = 0;
00220 rb_str_cat(last_prompt, s0, ++s - s0);
00221 s0 = s;
00222 break;
00223 case '\033':
00224 if (++s < e && *s == '[') {
00225 rb_str_cat(last_prompt, s0, s - s0 - 1);
00226 s0 = s - 1;
00227 while (++s < e && *s) {
00228 if (ISALPHA(*s)) {
00229 if (!ignoring) {
00230 ignoring = 1;
00231 rb_str_cat(last_prompt, ignore_code+0, 1);
00232 }
00233 rb_str_cat(last_prompt, s0, ++s - s0);
00234 s0 = s;
00235 break;
00236 }
00237 else if (!('0' <= *s && *s <= '9' || *s == ';')) {
00238 break;
00239 }
00240 }
00241 }
00242 break;
00243 default:
00244 if (ignoring > 0) {
00245 ignoring = 0;
00246 rb_str_cat(last_prompt, ignore_code+1, 1);
00247 }
00248 s++;
00249 break;
00250 }
00251 }
00252 if (ignoring > 0) {
00253 ignoring = 0;
00254 rb_str_cat(last_prompt, ignore_code+1, 1);
00255 }
00256 rb_str_cat(last_prompt, s0, s - s0);
00257
00258 rb_ivar_set(self, id_orig_prompt, prompt);
00259 rb_ivar_set(self, id_last_prompt, last_prompt);
00260
00261 return last_prompt;
00262 }
00263 #endif
00264
00265 static VALUE
00266 readline_get(VALUE prompt)
00267 {
00268 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
00269 readline_completion_append_character = rl_completion_append_character;
00270 #endif
00271 return (VALUE)readline((char *)prompt);
00272 }
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360 static VALUE
00361 readline_readline(int argc, VALUE *argv, VALUE self)
00362 {
00363 VALUE tmp, add_hist, result;
00364 char *prompt = NULL;
00365 char *buff;
00366 int status;
00367
00368 rb_secure(4);
00369 if (rb_scan_args(argc, argv, "02", &tmp, &add_hist) > 0) {
00370 OutputStringValue(tmp);
00371 #if USE_INSERT_IGNORE_ESCAPE
00372 tmp = insert_ignore_escape(self, tmp);
00373 rb_str_locktmp(tmp);
00374 #endif
00375 prompt = RSTRING_PTR(tmp);
00376 }
00377
00378 if (!isatty(fileno(rl_instream)) && errno == EBADF) rb_raise(rb_eIOError, "closed stdin");
00379 if (rl_outstream) {
00380 struct stat stbuf;
00381 int fd = fileno(rl_outstream);
00382 if (fd < 0 || fstat(fd, &stbuf) != 0) {
00383 rb_raise(rb_eIOError, "closed stdout");
00384 }
00385 }
00386
00387 #ifdef _WIN32
00388 rl_prep_terminal(1);
00389 #endif
00390 buff = (char*)rb_protect(readline_get, (VALUE)prompt, &status);
00391 #if USE_INSERT_IGNORE_ESCAPE
00392 if (prompt) {
00393 rb_str_unlocktmp(tmp);
00394 }
00395 #endif
00396 if (status) {
00397 #if defined HAVE_RL_CLEANUP_AFTER_SIGNAL
00398
00399 #if defined HAVE_RL_FREE_LINE_STATE
00400 rl_free_line_state();
00401 #endif
00402 rl_cleanup_after_signal();
00403 #elif defined HAVE_RL_DEPREP_TERM_FUNCTION
00404
00405 if (rl_deprep_term_function != NULL)
00406 (*rl_deprep_term_function)();
00407 else
00408 #else
00409 rl_deprep_terminal();
00410 #endif
00411 rb_jump_tag(status);
00412 }
00413
00414 if (RTEST(add_hist) && buff) {
00415 add_history(buff);
00416 }
00417 if (buff) {
00418 result = rb_locale_str_new_cstr(buff);
00419 }
00420 else
00421 result = Qnil;
00422 if (buff) free(buff);
00423 return result;
00424 }
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435 static VALUE
00436 readline_s_set_input(VALUE self, VALUE input)
00437 {
00438 rb_io_t *ifp;
00439
00440 rb_secure(4);
00441 Check_Type(input, T_FILE);
00442 GetOpenFile(input, ifp);
00443 rl_instream = rb_io_stdio_file(ifp);
00444 #ifdef HAVE_RL_GETC_FUNCTION
00445 readline_instream = input;
00446 #endif
00447 return input;
00448 }
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459 static VALUE
00460 readline_s_set_output(VALUE self, VALUE output)
00461 {
00462 rb_io_t *ofp;
00463
00464 rb_secure(4);
00465 Check_Type(output, T_FILE);
00466 GetOpenFile(output, ofp);
00467 rl_outstream = rb_io_stdio_file(ofp);
00468 return output;
00469 }
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541 static VALUE
00542 readline_s_set_completion_proc(VALUE self, VALUE proc)
00543 {
00544 rb_secure(4);
00545 if (!NIL_P(proc) && !rb_respond_to(proc, rb_intern("call")))
00546 rb_raise(rb_eArgError, "argument must respond to `call'");
00547 return rb_ivar_set(mReadline, completion_proc, proc);
00548 }
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558 static VALUE
00559 readline_s_get_completion_proc(VALUE self)
00560 {
00561 rb_secure(4);
00562 return rb_attr_get(mReadline, completion_proc);
00563 }
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573 static VALUE
00574 readline_s_set_completion_case_fold(VALUE self, VALUE val)
00575 {
00576 rb_secure(4);
00577 return rb_ivar_set(mReadline, completion_case_fold, val);
00578 }
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596 static VALUE
00597 readline_s_get_completion_case_fold(VALUE self)
00598 {
00599 rb_secure(4);
00600 return rb_attr_get(mReadline, completion_case_fold);
00601 }
00602
00603 #ifdef HAVE_RL_LINE_BUFFER
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615 static VALUE
00616 readline_s_get_line_buffer(VALUE self)
00617 {
00618 rb_secure(4);
00619 if (rl_line_buffer == NULL)
00620 return Qnil;
00621 return rb_locale_str_new_cstr(rl_line_buffer);
00622 }
00623 #else
00624 #define readline_s_get_line_buffer rb_f_notimplement
00625 #endif
00626
00627 #ifdef HAVE_RL_POINT
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641 static VALUE
00642 readline_s_get_point(VALUE self)
00643 {
00644 rb_secure(4);
00645 return INT2NUM(rl_point);
00646 }
00647 #else
00648 #define readline_s_get_point rb_f_notimplement
00649 #endif
00650
00651 static char **
00652 readline_attempted_completion_function(const char *text, int start, int end)
00653 {
00654 VALUE proc, ary, temp;
00655 char **result;
00656 int case_fold;
00657 long i, matches;
00658 rb_encoding *enc;
00659 VALUE encobj;
00660
00661 proc = rb_attr_get(mReadline, completion_proc);
00662 if (NIL_P(proc))
00663 return NULL;
00664 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
00665 rl_completion_append_character = readline_completion_append_character;
00666 #endif
00667 #ifdef HAVE_RL_ATTEMPTED_COMPLETION_OVER
00668 rl_attempted_completion_over = 1;
00669 #endif
00670 case_fold = RTEST(rb_attr_get(mReadline, completion_case_fold));
00671 ary = rb_funcall(proc, rb_intern("call"), 1, rb_locale_str_new_cstr(text));
00672 if (!RB_TYPE_P(ary, T_ARRAY))
00673 ary = rb_Array(ary);
00674 matches = RARRAY_LEN(ary);
00675 if (matches == 0) return NULL;
00676 result = (char**)malloc((matches + 2)*sizeof(char*));
00677 if (result == NULL) rb_raise(rb_eNoMemError, "failed to allocate memory");
00678 enc = rb_locale_encoding();
00679 encobj = rb_enc_from_encoding(enc);
00680 for (i = 0; i < matches; i++) {
00681 temp = rb_obj_as_string(RARRAY_PTR(ary)[i]);
00682 StringValueCStr(temp);
00683 rb_enc_check(encobj, temp);
00684 result[i + 1] = (char*)malloc(RSTRING_LEN(temp) + 1);
00685 if (result[i + 1] == NULL) rb_memerror();
00686 strcpy(result[i + 1], RSTRING_PTR(temp));
00687 }
00688 result[matches + 1] = NULL;
00689
00690 if (matches == 1) {
00691 result[0] = strdup(result[1]);
00692 }
00693 else {
00694 const char *result1 = result[1];
00695 long low = strlen(result1);
00696
00697 for (i = 1; i < matches; ++i) {
00698 register int c1, c2;
00699 long i1, i2, l2;
00700 int n1, n2;
00701 const char *p2 = result[i + 1];
00702
00703 l2 = strlen(p2);
00704 for (i1 = i2 = 0; i1 < low && i2 < l2; i1 += n1, i2 += n2) {
00705 c1 = rb_enc_codepoint_len(result1 + i1, result1 + low, &n1, enc);
00706 c2 = rb_enc_codepoint_len(p2 + i2, p2 + l2, &n2, enc);
00707 if (case_fold) {
00708 c1 = rb_tolower(c1);
00709 c2 = rb_tolower(c2);
00710 }
00711 if (c1 != c2) break;
00712 }
00713
00714 low = i1;
00715 }
00716 result[0] = ALLOC_N(char, low + 1);
00717 strncpy(result[0], result[1], low);
00718 result[0][low] = '\0';
00719 }
00720
00721 return result;
00722 }
00723
00724 #ifdef HAVE_RL_SET_SCREEN_SIZE
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737 static VALUE
00738 readline_s_set_screen_size(VALUE self, VALUE rows, VALUE columns)
00739 {
00740 rb_secure(4);
00741 rl_set_screen_size(NUM2INT(rows), NUM2INT(columns));
00742 return self;
00743 }
00744 #else
00745 #define readline_s_set_screen_size rb_f_notimplement
00746 #endif
00747
00748 #ifdef HAVE_RL_GET_SCREEN_SIZE
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761 static VALUE
00762 readline_s_get_screen_size(VALUE self)
00763 {
00764 int rows, columns;
00765 VALUE res;
00766
00767 rb_secure(4);
00768 rl_get_screen_size(&rows, &columns);
00769 res = rb_ary_new();
00770 rb_ary_push(res, INT2NUM(rows));
00771 rb_ary_push(res, INT2NUM(columns));
00772 return res;
00773 }
00774 #else
00775 #define readline_s_get_screen_size rb_f_notimplement
00776 #endif
00777
00778 #ifdef HAVE_RL_VI_EDITING_MODE
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790 static VALUE
00791 readline_s_vi_editing_mode(VALUE self)
00792 {
00793 rb_secure(4);
00794 rl_vi_editing_mode(1,0);
00795 return Qnil;
00796 }
00797 #else
00798 #define readline_s_vi_editing_mode rb_f_notimplement
00799 #endif
00800
00801 #ifdef HAVE_RL_EDITING_MODE
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812 static VALUE
00813 readline_s_vi_editing_mode_p(VALUE self)
00814 {
00815 rb_secure(4);
00816 return rl_editing_mode == 0 ? Qtrue : Qfalse;
00817 }
00818 #else
00819 #define readline_s_vi_editing_mode_p rb_f_notimplement
00820 #endif
00821
00822 #ifdef HAVE_RL_EMACS_EDITING_MODE
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834 static VALUE
00835 readline_s_emacs_editing_mode(VALUE self)
00836 {
00837 rb_secure(4);
00838 rl_emacs_editing_mode(1,0);
00839 return Qnil;
00840 }
00841 #else
00842 #define readline_s_emacs_editing_mode rb_f_notimplement
00843 #endif
00844
00845 #ifdef HAVE_RL_EDITING_MODE
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856 static VALUE
00857 readline_s_emacs_editing_mode_p(VALUE self)
00858 {
00859 rb_secure(4);
00860 return rl_editing_mode == 1 ? Qtrue : Qfalse;
00861 }
00862 #else
00863 #define readline_s_emacs_editing_mode_p rb_f_notimplement
00864 #endif
00865
00866 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905 static VALUE
00906 readline_s_set_completion_append_character(VALUE self, VALUE str)
00907 {
00908 rb_secure(4);
00909 if (NIL_P(str)) {
00910 rl_completion_append_character = '\0';
00911 }
00912 else {
00913 OutputStringValue(str);
00914 if (RSTRING_LEN(str) == 0) {
00915 rl_completion_append_character = '\0';
00916 } else {
00917 rl_completion_append_character = RSTRING_PTR(str)[0];
00918 }
00919 }
00920 return self;
00921 }
00922 #else
00923 #define readline_s_set_completion_append_character rb_f_notimplement
00924 #endif
00925
00926 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938 static VALUE
00939 readline_s_get_completion_append_character(VALUE self)
00940 {
00941 char buf[1];
00942
00943 rb_secure(4);
00944 if (rl_completion_append_character == '\0')
00945 return Qnil;
00946
00947 buf[0] = (char) rl_completion_append_character;
00948 return rb_locale_str_new(buf, 1);
00949 }
00950 #else
00951 #define readline_s_get_completion_append_character rb_f_notimplement
00952 #endif
00953
00954 #ifdef HAVE_RL_BASIC_WORD_BREAK_CHARACTERS
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967 static VALUE
00968 readline_s_set_basic_word_break_characters(VALUE self, VALUE str)
00969 {
00970 static char *basic_word_break_characters = NULL;
00971
00972 rb_secure(4);
00973 OutputStringValue(str);
00974 if (basic_word_break_characters == NULL) {
00975 basic_word_break_characters =
00976 ALLOC_N(char, RSTRING_LEN(str) + 1);
00977 }
00978 else {
00979 REALLOC_N(basic_word_break_characters, char, RSTRING_LEN(str) + 1);
00980 }
00981 strncpy(basic_word_break_characters,
00982 RSTRING_PTR(str), RSTRING_LEN(str));
00983 basic_word_break_characters[RSTRING_LEN(str)] = '\0';
00984 rl_basic_word_break_characters = basic_word_break_characters;
00985 return self;
00986 }
00987 #else
00988 #define readline_s_set_basic_word_break_characters rb_f_notimplement
00989 #endif
00990
00991 #ifdef HAVE_RL_BASIC_WORD_BREAK_CHARACTERS
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003 static VALUE
01004 readline_s_get_basic_word_break_characters(VALUE self, VALUE str)
01005 {
01006 rb_secure(4);
01007 if (rl_basic_word_break_characters == NULL)
01008 return Qnil;
01009 return rb_locale_str_new_cstr(rl_basic_word_break_characters);
01010 }
01011 #else
01012 #define readline_s_get_basic_word_break_characters rb_f_notimplement
01013 #endif
01014
01015 #ifdef HAVE_RL_COMPLETER_WORD_BREAK_CHARACTERS
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028 static VALUE
01029 readline_s_set_completer_word_break_characters(VALUE self, VALUE str)
01030 {
01031 static char *completer_word_break_characters = NULL;
01032
01033 rb_secure(4);
01034 OutputStringValue(str);
01035 if (completer_word_break_characters == NULL) {
01036 completer_word_break_characters =
01037 ALLOC_N(char, RSTRING_LEN(str) + 1);
01038 }
01039 else {
01040 REALLOC_N(completer_word_break_characters, char, RSTRING_LEN(str) + 1);
01041 }
01042 strncpy(completer_word_break_characters,
01043 RSTRING_PTR(str), RSTRING_LEN(str));
01044 completer_word_break_characters[RSTRING_LEN(str)] = '\0';
01045 rl_completer_word_break_characters = completer_word_break_characters;
01046 return self;
01047 }
01048 #else
01049 #define readline_s_set_completer_word_break_characters rb_f_notimplement
01050 #endif
01051
01052 #ifdef HAVE_RL_COMPLETER_WORD_BREAK_CHARACTERS
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064 static VALUE
01065 readline_s_get_completer_word_break_characters(VALUE self, VALUE str)
01066 {
01067 rb_secure(4);
01068 if (rl_completer_word_break_characters == NULL)
01069 return Qnil;
01070 return rb_locale_str_new_cstr(rl_completer_word_break_characters);
01071 }
01072 #else
01073 #define readline_s_get_completer_word_break_characters rb_f_notimplement
01074 #endif
01075
01076 #ifdef HAVE_RL_BASIC_QUOTE_CHARACTERS
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087 static VALUE
01088 readline_s_set_basic_quote_characters(VALUE self, VALUE str)
01089 {
01090 static char *basic_quote_characters = NULL;
01091
01092 rb_secure(4);
01093 OutputStringValue(str);
01094 if (basic_quote_characters == NULL) {
01095 basic_quote_characters =
01096 ALLOC_N(char, RSTRING_LEN(str) + 1);
01097 }
01098 else {
01099 REALLOC_N(basic_quote_characters, char, RSTRING_LEN(str) + 1);
01100 }
01101 strncpy(basic_quote_characters,
01102 RSTRING_PTR(str), RSTRING_LEN(str));
01103 basic_quote_characters[RSTRING_LEN(str)] = '\0';
01104 rl_basic_quote_characters = basic_quote_characters;
01105
01106 return self;
01107 }
01108 #else
01109 #define readline_s_set_basic_quote_characters rb_f_notimplement
01110 #endif
01111
01112 #ifdef HAVE_RL_BASIC_QUOTE_CHARACTERS
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123 static VALUE
01124 readline_s_get_basic_quote_characters(VALUE self, VALUE str)
01125 {
01126 rb_secure(4);
01127 if (rl_basic_quote_characters == NULL)
01128 return Qnil;
01129 return rb_locale_str_new_cstr(rl_basic_quote_characters);
01130 }
01131 #else
01132 #define readline_s_get_basic_quote_characters rb_f_notimplement
01133 #endif
01134
01135 #ifdef HAVE_RL_COMPLETER_QUOTE_CHARACTERS
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149 static VALUE
01150 readline_s_set_completer_quote_characters(VALUE self, VALUE str)
01151 {
01152 static char *completer_quote_characters = NULL;
01153
01154 rb_secure(4);
01155 OutputStringValue(str);
01156 if (completer_quote_characters == NULL) {
01157 completer_quote_characters =
01158 ALLOC_N(char, RSTRING_LEN(str) + 1);
01159 }
01160 else {
01161 REALLOC_N(completer_quote_characters, char, RSTRING_LEN(str) + 1);
01162 }
01163 strncpy(completer_quote_characters, RSTRING_PTR(str), RSTRING_LEN(str));
01164 completer_quote_characters[RSTRING_LEN(str)] = '\0';
01165 rl_completer_quote_characters = completer_quote_characters;
01166
01167 return self;
01168 }
01169 #else
01170 #define readline_s_set_completer_quote_characters rb_f_notimplement
01171 #endif
01172
01173 #ifdef HAVE_RL_COMPLETER_QUOTE_CHARACTERS
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185 static VALUE
01186 readline_s_get_completer_quote_characters(VALUE self, VALUE str)
01187 {
01188 rb_secure(4);
01189 if (rl_completer_quote_characters == NULL)
01190 return Qnil;
01191 return rb_locale_str_new_cstr(rl_completer_quote_characters);
01192 }
01193 #else
01194 #define readline_s_get_completer_quote_characters rb_f_notimplement
01195 #endif
01196
01197 #ifdef HAVE_RL_FILENAME_QUOTE_CHARACTERS
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209 static VALUE
01210 readline_s_set_filename_quote_characters(VALUE self, VALUE str)
01211 {
01212 static char *filename_quote_characters = NULL;
01213
01214 rb_secure(4);
01215 OutputStringValue(str);
01216 if (filename_quote_characters == NULL) {
01217 filename_quote_characters =
01218 ALLOC_N(char, RSTRING_LEN(str) + 1);
01219 }
01220 else {
01221 REALLOC_N(filename_quote_characters, char, RSTRING_LEN(str) + 1);
01222 }
01223 strncpy(filename_quote_characters, RSTRING_PTR(str), RSTRING_LEN(str));
01224 filename_quote_characters[RSTRING_LEN(str)] = '\0';
01225 rl_filename_quote_characters = filename_quote_characters;
01226
01227 return self;
01228 }
01229 #else
01230 #define readline_s_set_filename_quote_characters rb_f_notimplement
01231 #endif
01232
01233 #ifdef HAVE_RL_FILENAME_QUOTE_CHARACTERS
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245 static VALUE
01246 readline_s_get_filename_quote_characters(VALUE self, VALUE str)
01247 {
01248 rb_secure(4);
01249 if (rl_filename_quote_characters == NULL)
01250 return Qnil;
01251 return rb_locale_str_new_cstr(rl_filename_quote_characters);
01252 }
01253 #else
01254 #define readline_s_get_filename_quote_characters rb_f_notimplement
01255 #endif
01256
01257 #ifdef HAVE_RL_REFRESH_LINE
01258
01259
01260
01261
01262
01263
01264
01265
01266 static VALUE
01267 readline_s_refresh_line(VALUE self)
01268 {
01269 rb_secure(4);
01270 rl_refresh_line(0, 0);
01271 return Qnil;
01272 }
01273 #else
01274 #define readline_s_refresh_line rb_f_notimplement
01275 #endif
01276
01277 static VALUE
01278 hist_to_s(VALUE self)
01279 {
01280 return rb_str_new_cstr("HISTORY");
01281 }
01282
01283 static int
01284 history_get_offset_history_base(int offset)
01285 {
01286 return history_base + offset;
01287 }
01288
01289 static int
01290 history_get_offset_0(int offset)
01291 {
01292 return offset;
01293 }
01294
01295 static VALUE
01296 hist_get(VALUE self, VALUE index)
01297 {
01298 HIST_ENTRY *entry = NULL;
01299 int i;
01300
01301 rb_secure(4);
01302 i = NUM2INT(index);
01303 if (i < 0) {
01304 i += history_length;
01305 }
01306 if (i >= 0) {
01307 entry = history_get(history_get_offset_func(i));
01308 }
01309 if (entry == NULL) {
01310 rb_raise(rb_eIndexError, "invalid index");
01311 }
01312 return rb_locale_str_new_cstr(entry->line);
01313 }
01314
01315 #ifdef HAVE_REPLACE_HISTORY_ENTRY
01316 static VALUE
01317 hist_set(VALUE self, VALUE index, VALUE str)
01318 {
01319 HIST_ENTRY *entry = NULL;
01320 int i;
01321
01322 rb_secure(4);
01323 i = NUM2INT(index);
01324 OutputStringValue(str);
01325 if (i < 0) {
01326 i += history_length;
01327 }
01328 if (i >= 0) {
01329 entry = replace_history_entry(history_replace_offset_func(i), RSTRING_PTR(str), NULL);
01330 }
01331 if (entry == NULL) {
01332 rb_raise(rb_eIndexError, "invalid index");
01333 }
01334 return str;
01335 }
01336 #else
01337 #define hist_set rb_f_notimplement
01338 #endif
01339
01340 static VALUE
01341 hist_push(VALUE self, VALUE str)
01342 {
01343 rb_secure(4);
01344 OutputStringValue(str);
01345 add_history(RSTRING_PTR(str));
01346 return self;
01347 }
01348
01349 static VALUE
01350 hist_push_method(int argc, VALUE *argv, VALUE self)
01351 {
01352 VALUE str;
01353
01354 rb_secure(4);
01355 while (argc--) {
01356 str = *argv++;
01357 OutputStringValue(str);
01358 add_history(RSTRING_PTR(str));
01359 }
01360 return self;
01361 }
01362
01363 static VALUE
01364 rb_remove_history(int index)
01365 {
01366 #ifdef HAVE_REMOVE_HISTORY
01367 HIST_ENTRY *entry;
01368 VALUE val;
01369
01370 rb_secure(4);
01371 entry = remove_history(index);
01372 if (entry) {
01373 val = rb_locale_str_new_cstr(entry->line);
01374 free((void *) entry->line);
01375 free(entry);
01376 return val;
01377 }
01378 return Qnil;
01379 #else
01380 rb_notimplement();
01381 return Qnil;
01382 #endif
01383 }
01384
01385 static VALUE
01386 hist_pop(VALUE self)
01387 {
01388 rb_secure(4);
01389 if (history_length > 0) {
01390 return rb_remove_history(history_length - 1);
01391 } else {
01392 return Qnil;
01393 }
01394 }
01395
01396 static VALUE
01397 hist_shift(VALUE self)
01398 {
01399 rb_secure(4);
01400 if (history_length > 0) {
01401 return rb_remove_history(0);
01402 } else {
01403 return Qnil;
01404 }
01405 }
01406
01407 static VALUE
01408 hist_each(VALUE self)
01409 {
01410 HIST_ENTRY *entry;
01411 int i;
01412
01413 RETURN_ENUMERATOR(self, 0, 0);
01414
01415 rb_secure(4);
01416 for (i = 0; i < history_length; i++) {
01417 entry = history_get(history_get_offset_func(i));
01418 if (entry == NULL)
01419 break;
01420 rb_yield(rb_locale_str_new_cstr(entry->line));
01421 }
01422 return self;
01423 }
01424
01425 static VALUE
01426 hist_length(VALUE self)
01427 {
01428 rb_secure(4);
01429 return INT2NUM(history_length);
01430 }
01431
01432 static VALUE
01433 hist_empty_p(VALUE self)
01434 {
01435 rb_secure(4);
01436 return history_length == 0 ? Qtrue : Qfalse;
01437 }
01438
01439 static VALUE
01440 hist_delete_at(VALUE self, VALUE index)
01441 {
01442 int i;
01443
01444 rb_secure(4);
01445 i = NUM2INT(index);
01446 if (i < 0)
01447 i += history_length;
01448 if (i < 0 || i > history_length - 1) {
01449 rb_raise(rb_eIndexError, "invalid index");
01450 }
01451 return rb_remove_history(i);
01452 }
01453
01454 #ifdef HAVE_CLEAR_HISTORY
01455 static VALUE
01456 hist_clear(VALUE self)
01457 {
01458 rb_secure(4);
01459 clear_history();
01460 return self;
01461 }
01462 #else
01463 #define hist_clear rb_f_notimplement
01464 #endif
01465
01466 static VALUE
01467 filename_completion_proc_call(VALUE self, VALUE str)
01468 {
01469 VALUE result;
01470 char **matches;
01471 int i;
01472
01473 matches = rl_completion_matches(StringValuePtr(str),
01474 rl_filename_completion_function);
01475 if (matches) {
01476 result = rb_ary_new();
01477 for (i = 0; matches[i]; i++) {
01478 rb_ary_push(result, rb_locale_str_new_cstr(matches[i]));
01479 free(matches[i]);
01480 }
01481 free(matches);
01482 if (RARRAY_LEN(result) >= 2)
01483 rb_ary_shift(result);
01484 }
01485 else {
01486 result = Qnil;
01487 }
01488 return result;
01489 }
01490
01491 static VALUE
01492 username_completion_proc_call(VALUE self, VALUE str)
01493 {
01494 VALUE result;
01495 char **matches;
01496 int i;
01497
01498 matches = rl_completion_matches(StringValuePtr(str),
01499 rl_username_completion_function);
01500 if (matches) {
01501 result = rb_ary_new();
01502 for (i = 0; matches[i]; i++) {
01503 rb_ary_push(result, rb_locale_str_new_cstr(matches[i]));
01504 free(matches[i]);
01505 }
01506 free(matches);
01507 if (RARRAY_LEN(result) >= 2)
01508 rb_ary_shift(result);
01509 }
01510 else {
01511 result = Qnil;
01512 }
01513 return result;
01514 }
01515
01516 void
01517 Init_readline()
01518 {
01519 VALUE history, fcomp, ucomp, version;
01520
01521
01522 rl_readline_name = (char *)"Ruby";
01523
01524 #if defined HAVE_RL_GETC_FUNCTION
01525
01526
01527
01528 rl_getc_function = readline_getc;
01529 id_getbyte = rb_intern_const("getbyte");
01530 #elif defined HAVE_RL_EVENT_HOOK
01531 rl_event_hook = readline_event;
01532 #endif
01533
01534 using_history();
01535
01536 completion_proc = rb_intern(COMPLETION_PROC);
01537 completion_case_fold = rb_intern(COMPLETION_CASE_FOLD);
01538
01539 mReadline = rb_define_module("Readline");
01540 rb_define_module_function(mReadline, "readline",
01541 readline_readline, -1);
01542 rb_define_singleton_method(mReadline, "input=",
01543 readline_s_set_input, 1);
01544 rb_define_singleton_method(mReadline, "output=",
01545 readline_s_set_output, 1);
01546 rb_define_singleton_method(mReadline, "completion_proc=",
01547 readline_s_set_completion_proc, 1);
01548 rb_define_singleton_method(mReadline, "completion_proc",
01549 readline_s_get_completion_proc, 0);
01550 rb_define_singleton_method(mReadline, "completion_case_fold=",
01551 readline_s_set_completion_case_fold, 1);
01552 rb_define_singleton_method(mReadline, "completion_case_fold",
01553 readline_s_get_completion_case_fold, 0);
01554 rb_define_singleton_method(mReadline, "line_buffer",
01555 readline_s_get_line_buffer, 0);
01556 rb_define_singleton_method(mReadline, "point",
01557 readline_s_get_point, 0);
01558 rb_define_singleton_method(mReadline, "set_screen_size",
01559 readline_s_set_screen_size, 2);
01560 rb_define_singleton_method(mReadline, "get_screen_size",
01561 readline_s_get_screen_size, 0);
01562 rb_define_singleton_method(mReadline, "vi_editing_mode",
01563 readline_s_vi_editing_mode, 0);
01564 rb_define_singleton_method(mReadline, "vi_editing_mode?",
01565 readline_s_vi_editing_mode_p, 0);
01566 rb_define_singleton_method(mReadline, "emacs_editing_mode",
01567 readline_s_emacs_editing_mode, 0);
01568 rb_define_singleton_method(mReadline, "emacs_editing_mode?",
01569 readline_s_emacs_editing_mode_p, 0);
01570 rb_define_singleton_method(mReadline, "completion_append_character=",
01571 readline_s_set_completion_append_character, 1);
01572 rb_define_singleton_method(mReadline, "completion_append_character",
01573 readline_s_get_completion_append_character, 0);
01574 rb_define_singleton_method(mReadline, "basic_word_break_characters=",
01575 readline_s_set_basic_word_break_characters, 1);
01576 rb_define_singleton_method(mReadline, "basic_word_break_characters",
01577 readline_s_get_basic_word_break_characters, 0);
01578 rb_define_singleton_method(mReadline, "completer_word_break_characters=",
01579 readline_s_set_completer_word_break_characters, 1);
01580 rb_define_singleton_method(mReadline, "completer_word_break_characters",
01581 readline_s_get_completer_word_break_characters, 0);
01582 rb_define_singleton_method(mReadline, "basic_quote_characters=",
01583 readline_s_set_basic_quote_characters, 1);
01584 rb_define_singleton_method(mReadline, "basic_quote_characters",
01585 readline_s_get_basic_quote_characters, 0);
01586 rb_define_singleton_method(mReadline, "completer_quote_characters=",
01587 readline_s_set_completer_quote_characters, 1);
01588 rb_define_singleton_method(mReadline, "completer_quote_characters",
01589 readline_s_get_completer_quote_characters, 0);
01590 rb_define_singleton_method(mReadline, "filename_quote_characters=",
01591 readline_s_set_filename_quote_characters, 1);
01592 rb_define_singleton_method(mReadline, "filename_quote_characters",
01593 readline_s_get_filename_quote_characters, 0);
01594 rb_define_singleton_method(mReadline, "refresh_line",
01595 readline_s_refresh_line, 0);
01596
01597 #if USE_INSERT_IGNORE_ESCAPE
01598 CONST_ID(id_orig_prompt, "orig_prompt");
01599 CONST_ID(id_last_prompt, "last_prompt");
01600 #endif
01601
01602 history = rb_obj_alloc(rb_cObject);
01603 rb_extend_object(history, rb_mEnumerable);
01604 rb_define_singleton_method(history,"to_s", hist_to_s, 0);
01605 rb_define_singleton_method(history,"[]", hist_get, 1);
01606 rb_define_singleton_method(history,"[]=", hist_set, 2);
01607 rb_define_singleton_method(history,"<<", hist_push, 1);
01608 rb_define_singleton_method(history,"push", hist_push_method, -1);
01609 rb_define_singleton_method(history,"pop", hist_pop, 0);
01610 rb_define_singleton_method(history,"shift", hist_shift, 0);
01611 rb_define_singleton_method(history,"each", hist_each, 0);
01612 rb_define_singleton_method(history,"length", hist_length, 0);
01613 rb_define_singleton_method(history,"size", hist_length, 0);
01614 rb_define_singleton_method(history,"empty?", hist_empty_p, 0);
01615 rb_define_singleton_method(history,"delete_at", hist_delete_at, 1);
01616 rb_define_singleton_method(history,"clear", hist_clear, 0);
01617
01618
01619
01620
01621
01622
01623
01624 rb_define_const(mReadline, "HISTORY", history);
01625
01626 fcomp = rb_obj_alloc(rb_cObject);
01627 rb_define_singleton_method(fcomp, "call",
01628 filename_completion_proc_call, 1);
01629
01630
01631
01632
01633 rb_define_const(mReadline, "FILENAME_COMPLETION_PROC", fcomp);
01634
01635 ucomp = rb_obj_alloc(rb_cObject);
01636 rb_define_singleton_method(ucomp, "call",
01637 username_completion_proc_call, 1);
01638
01639
01640
01641
01642 rb_define_const(mReadline, "USERNAME_COMPLETION_PROC", ucomp);
01643 history_get_offset_func = history_get_offset_history_base;
01644 history_replace_offset_func = history_get_offset_0;
01645 #if defined HAVE_RL_LIBRARY_VERSION
01646 version = rb_str_new_cstr(rl_library_version);
01647 #if defined HAVE_CLEAR_HISTORY || defined HAVE_REMOVE_HISTORY
01648 if (strncmp(rl_library_version, EDIT_LINE_LIBRARY_VERSION,
01649 strlen(EDIT_LINE_LIBRARY_VERSION)) == 0) {
01650 add_history("1");
01651 if (history_get(history_get_offset_func(0)) == NULL) {
01652 history_get_offset_func = history_get_offset_0;
01653 }
01654 #ifdef HAVE_REPLACE_HISTORY_ENTRY
01655 if (replace_history_entry(0, "a", NULL) == NULL) {
01656 history_replace_offset_func = history_get_offset_history_base;
01657 }
01658 #endif
01659 #ifdef HAVE_CLEAR_HISTORY
01660 clear_history();
01661 #else
01662 {
01663 HIST_ENTRY *entry = remove_history(0);
01664 if (entry) {
01665 free((char *)entry->line);
01666 free(entry);
01667 }
01668 }
01669 #endif
01670 }
01671 #endif
01672 #else
01673 version = rb_str_new_cstr("2.0 or prior version");
01674 #endif
01675
01676 rb_define_const(mReadline, "VERSION", version);
01677
01678 rl_attempted_completion_function = readline_attempted_completion_function;
01679 #ifdef HAVE_RL_CATCH_SIGNALS
01680 rl_catch_signals = 0;
01681 #endif
01682
01683 #ifdef HAVE_RL_CLEAR_SIGNALS
01684 rl_clear_signals();
01685 #endif
01686
01687 readline_s_set_input(mReadline, rb_stdin);
01688 }
01689