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