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