DEFINITIONS
This source file includes following functions.
- readline_event
- readline_readline
- readline_s_set_completion_proc
- readline_s_get_completion_proc
- readline_s_set_completion_case_fold
- readline_s_get_completion_case_fold
- readline_attempted_completion_function
- readline_s_vi_editing_mode
- readline_s_emacs_editing_mode
- readline_s_set_completion_append_character
- readline_s_get_completion_append_character
- readline_s_set_basic_word_break_characters
- readline_s_get_basic_word_break_characters
- readline_s_set_completer_word_break_characters
- readline_s_get_completer_word_break_characters
- readline_s_set_basic_quote_characters
- readline_s_get_basic_quote_characters
- readline_s_set_completer_quote_characters
- readline_s_get_completer_quote_characters
- readline_s_set_filename_quote_characters
- readline_s_get_filename_quote_characters
- rb_remove_history
- hist_to_s
- hist_get
- hist_set
- hist_push
- hist_push_method
- hist_pop
- hist_shift
- hist_each
- hist_length
- hist_empty_p
- hist_delete_at
- filename_completion_proc_call
- username_completion_proc_call
- Init_readline
1
2
3
4 #include <errno.h>
5 #include <stdio.h>
6 #include <readline/readline.h>
7 #include <readline/history.h>
8
9 #include "ruby.h"
10 #include "rubysig.h"
11
12 static VALUE mReadline;
13
14 #define TOLOWER(c) (isupper(c) ? tolower(c) : c)
15
16 #define COMPLETION_PROC "completion_proc"
17 #define COMPLETION_CASE_FOLD "completion_case_fold"
18
19 #ifndef READLINE_42_OR_LATER
20 # define rl_filename_completion_function filename_completion_function
21 # define rl_username_completion_function username_completion_function
22 # define rl_completion_matches completion_matches
23 #endif
24
25 static int
26 readline_event()
27 {
28 CHECK_INTS;
29 rb_thread_schedule();
30 return 0;
31 }
32
33 static VALUE
34 readline_readline(argc, argv, self)
35 int argc;
36 VALUE *argv;
37 VALUE self;
38 {
39 VALUE tmp, add_hist, result;
40 char *prompt = NULL;
41 char *buff;
42 int status;
43
44 if (rb_scan_args(argc, argv, "02", &tmp, &add_hist) > 0) {
45 prompt = StringValuePtr(tmp);
46 }
47
48 if (!isatty(0) && errno == EBADF) rb_raise(rb_eIOError, "stdin closed");
49
50 buff = (char*)rb_protect((VALUE(*)_((VALUE)))readline, (VALUE)prompt,
51 &status);
52 if (status) {
53 #if READLINE_40_OR_LATER
54
55 rl_cleanup_after_signal();
56 #elif READLINE_21_OR_LATER
57
58 (*rl_deprep_term_function)();
59 #else
60 rl_deprep_terminal();
61 #endif
62 rb_jump_tag(status);
63 }
64
65 if (RTEST(add_hist) && buff) {
66 add_history(buff);
67 }
68 if (buff)
69 result = rb_tainted_str_new2(buff);
70 else
71 result = Qnil;
72 if (buff) free(buff);
73 return result;
74 }
75
76 static VALUE
77 readline_s_set_completion_proc(self, proc)
78 VALUE self;
79 VALUE proc;
80 {
81 if (!rb_respond_to(proc, rb_intern("call")))
82 rb_raise(rb_eArgError, "argument have to respond to `call'");
83 return rb_iv_set(mReadline, COMPLETION_PROC, proc);
84 }
85
86 static VALUE
87 readline_s_get_completion_proc(self)
88 VALUE self;
89 {
90 return rb_iv_get(mReadline, COMPLETION_PROC);
91 }
92
93 static VALUE
94 readline_s_set_completion_case_fold(self, val)
95 VALUE self;
96 VALUE val;
97 {
98 return rb_iv_set(mReadline, COMPLETION_CASE_FOLD, val);
99 }
100
101 static VALUE
102 readline_s_get_completion_case_fold(self)
103 VALUE self;
104 {
105 return rb_iv_get(mReadline, COMPLETION_CASE_FOLD);
106 }
107
108 static char **
109 readline_attempted_completion_function(text, start, end)
110 char *text;
111 int start;
112 int end;
113 {
114 VALUE proc, ary, temp;
115 char **result;
116 int case_fold;
117 int i, matches;
118
119 proc = rb_iv_get(mReadline, COMPLETION_PROC);
120 if (NIL_P(proc))
121 return NULL;
122 rl_attempted_completion_over = 1;
123 case_fold = RTEST(rb_iv_get(mReadline, COMPLETION_CASE_FOLD));
124 ary = rb_funcall(proc, rb_intern("call"), 1, rb_tainted_str_new2(text));
125 if (TYPE(ary) != T_ARRAY)
126 ary = rb_Array(ary);
127 matches = RARRAY(ary)->len;
128 if (matches == 0)
129 return NULL;
130 result = ALLOC_N(char *, matches + 2);
131 for (i = 0; i < matches; i++) {
132 temp = rb_obj_as_string(RARRAY(ary)->ptr[i]);
133 result[i + 1] = ALLOC_N(char, RSTRING(temp)->len + 1);
134 strcpy(result[i + 1], RSTRING(temp)->ptr);
135 }
136 result[matches + 1] = NULL;
137
138 if (matches == 1) {
139 result[0] = result[1];
140 result[1] = NULL;
141 } else {
142 register int i = 1;
143 int low = 100000;
144
145 while (i < matches) {
146 register int c1, c2, si;
147
148 if (case_fold) {
149 for (si = 0;
150 (c1 = TOLOWER(result[i][si])) &&
151 (c2 = TOLOWER(result[i + 1][si]));
152 si++)
153 if (c1 != c2) break;
154 } else {
155 for (si = 0;
156 (c1 = result[i][si]) &&
157 (c2 = result[i + 1][si]);
158 si++)
159 if (c1 != c2) break;
160 }
161
162 if (low > si) low = si;
163 i++;
164 }
165 result[0] = ALLOC_N(char, low + 1);
166 strncpy(result[0], result[1], low);
167 result[0][low] = '\0';
168 }
169
170 return result;
171 }
172
173 static VALUE
174 readline_s_vi_editing_mode(self)
175 VALUE self;
176 {
177 rl_vi_editing_mode(1,0);
178 return Qnil;
179 }
180
181 static VALUE
182 readline_s_emacs_editing_mode(self)
183 VALUE self;
184 {
185 rl_emacs_editing_mode(1,0);
186 return Qnil;
187 }
188
189 static VALUE
190 readline_s_set_completion_append_character(self, str)
191 VALUE self, str;
192 {
193 #ifdef READLINE_21_OR_LATER
194 if (NIL_P(str) || !StringValuePtr(str) || !RSTRING(str)->len) {
195 rl_completion_append_character = '\0';
196 } else {
197 rl_completion_append_character = RSTRING(str)->ptr[0];
198 }
199
200 return self;
201 #else
202 rb_notimplement();
203 #endif
204 }
205
206 static VALUE
207 readline_s_get_completion_append_character(self)
208 VALUE self;
209 {
210 #ifdef READLINE_21_OR_LATER
211 VALUE str;
212
213 if (rl_completion_append_character == '\0')
214 return Qnil;
215
216 str = rb_str_new("", 1);
217 RSTRING(str)->ptr[0] = rl_completion_append_character;
218
219 return str;
220 #else
221 rb_notimplement();
222 #endif
223 }
224
225 static VALUE
226 readline_s_set_basic_word_break_characters(self, str)
227 VALUE self, str;
228 {
229 #ifdef READLINE_21_OR_LATER
230 static char *basic_word_break_characters = NULL;
231 char *s;
232
233 StringValue(str);
234 if (basic_word_break_characters == NULL) {
235 basic_word_break_characters =
236 ALLOC_N(char, RSTRING(str)->len + 1);
237 }
238 else {
239 REALLOC_N(basic_word_break_characters, char, RSTRING(str)->len + 1);
240 }
241 strncpy(basic_word_break_characters,
242 RSTRING(str)->ptr, RSTRING(str)->len);
243 basic_word_break_characters[RSTRING(str)->len] = '\0';
244 rl_basic_word_break_characters = basic_word_break_characters;
245
246 return self;
247 #else
248 rb_notimplement();
249 #endif
250 }
251
252 static VALUE
253 readline_s_get_basic_word_break_characters(self, str)
254 VALUE self, str;
255 {
256 #ifdef READLINE_21_OR_LATER
257 if (rl_basic_word_break_characters == NULL)
258 return Qnil;
259 return rb_str_new2(rl_basic_word_break_characters);
260 #else
261 rb_notimplement();
262 #endif
263 }
264
265 static VALUE
266 readline_s_set_completer_word_break_characters(self, str)
267 VALUE self, str;
268 {
269 #ifdef READLINE_21_OR_LATER
270 static char *completer_word_break_characters = NULL;
271 char *s;
272
273 StringValue(str);
274 if (completer_word_break_characters == NULL) {
275 completer_word_break_characters =
276 ALLOC_N(char, RSTRING(str)->len + 1);
277 }
278 else {
279 REALLOC_N(completer_word_break_characters, char, RSTRING(str)->len + 1);
280 }
281 strncpy(completer_word_break_characters,
282 RSTRING(str)->ptr, RSTRING(str)->len);
283 completer_word_break_characters[RSTRING(str)->len] = '\0';
284 rl_completer_word_break_characters = completer_word_break_characters;
285
286 return self;
287 #else
288 rb_notimplement();
289 #endif
290 }
291
292 static VALUE
293 readline_s_get_completer_word_break_characters(self, str)
294 VALUE self, str;
295 {
296 #ifdef READLINE_21_OR_LATER
297 if (rl_completer_word_break_characters == NULL)
298 return Qnil;
299 return rb_str_new2(rl_completer_word_break_characters);
300 #else
301 rb_notimplement();
302 #endif
303 }
304
305 static VALUE
306 readline_s_set_basic_quote_characters(self, str)
307 VALUE self, str;
308 {
309 #ifdef READLINE_21_OR_LATER
310 static char *basic_quote_characters = NULL;
311 char *s;
312
313 StringValue(str);
314 if (basic_quote_characters == NULL) {
315 basic_quote_characters =
316 ALLOC_N(char, RSTRING(str)->len + 1);
317 }
318 else {
319 REALLOC_N(basic_quote_characters, char, RSTRING(str)->len + 1);
320 }
321 strncpy(basic_quote_characters,
322 RSTRING(str)->ptr, RSTRING(str)->len);
323 basic_quote_characters[RSTRING(str)->len] = '\0';
324 rl_basic_quote_characters = basic_quote_characters;
325
326 return self;
327 #else
328 rb_notimplement();
329 #endif
330 }
331
332 static VALUE
333 readline_s_get_basic_quote_characters(self, str)
334 VALUE self, str;
335 {
336 #ifdef READLINE_21_OR_LATER
337 if (rl_basic_quote_characters == NULL)
338 return Qnil;
339 return rb_str_new2(rl_basic_quote_characters);
340 #else
341 rb_notimplement();
342 #endif
343 }
344
345 static VALUE
346 readline_s_set_completer_quote_characters(self, str)
347 VALUE self, str;
348 {
349 #ifdef READLINE_21_OR_LATER
350 static char *completer_quote_characters = NULL;
351 char *s;
352
353 StringValue(str);
354 if (completer_quote_characters == NULL) {
355 completer_quote_characters =
356 ALLOC_N(char, RSTRING(str)->len + 1);
357 }
358 else {
359 REALLOC_N(completer_quote_characters, char, RSTRING(str)->len + 1);
360 }
361 strncpy(completer_quote_characters,
362 RSTRING(str)->ptr, RSTRING(str)->len);
363 completer_quote_characters[RSTRING(str)->len] = '\0';
364 rl_completer_quote_characters = completer_quote_characters;
365
366 return self;
367 #else
368 rb_notimplement();
369 #endif
370 }
371
372 static VALUE
373 readline_s_get_completer_quote_characters(self, str)
374 VALUE self, str;
375 {
376 #ifdef READLINE_21_OR_LATER
377 if (rl_completer_quote_characters == NULL)
378 return Qnil;
379 return rb_str_new2(rl_completer_quote_characters);
380 #else
381 rb_notimplement();
382 #endif
383 }
384
385 static VALUE
386 readline_s_set_filename_quote_characters(self, str)
387 VALUE self, str;
388 {
389 #ifdef READLINE_21_OR_LATER
390 static char *filename_quote_characters = NULL;
391 char *s;
392
393 StringValue(str);
394 if (filename_quote_characters == NULL) {
395 filename_quote_characters =
396 ALLOC_N(char, RSTRING(str)->len + 1);
397 }
398 else {
399 REALLOC_N(filename_quote_characters, char, RSTRING(str)->len + 1);
400 }
401 strncpy(filename_quote_characters,
402 RSTRING(str)->ptr, RSTRING(str)->len);
403 filename_quote_characters[RSTRING(str)->len] = '\0';
404 rl_filename_quote_characters = filename_quote_characters;
405
406 return self;
407 #else
408 rb_notimplement();
409 #endif
410 }
411
412 static VALUE
413 readline_s_get_filename_quote_characters(self, str)
414 VALUE self, str;
415 {
416 #ifdef READLINE_21_OR_LATER
417 if (rl_filename_quote_characters == NULL)
418 return Qnil;
419 return rb_str_new2(rl_filename_quote_characters);
420 #else
421 rb_notimplement();
422 #endif
423 }
424
425 static VALUE
426 rb_remove_history(index)
427 int index;
428 {
429 HIST_ENTRY *entry;
430 VALUE val;
431
432 entry = remove_history(index);
433 if (entry) {
434 val = rb_tainted_str_new2(entry->line);
435 free(entry->line);
436 free(entry);
437 return val;
438 }
439 return Qnil;
440 }
441
442 static VALUE
443 hist_to_s(self)
444 VALUE self;
445 {
446 return rb_str_new2("HISTORY");
447 }
448
449 static VALUE
450 hist_get(self, index)
451 VALUE self;
452 VALUE index;
453 {
454 HISTORY_STATE *state;
455 int i;
456
457 state = history_get_history_state();
458 i = NUM2INT(index);
459 if (i < 0) {
460 i += state->length;
461 }
462 if (i < 0 || i > state->length - 1) {
463 rb_raise(rb_eIndexError, "Invalid index");
464 }
465 return rb_tainted_str_new2(state->entries[i]->line);
466 }
467
468 static VALUE
469 hist_set(self, index, str)
470 VALUE self;
471 VALUE index;
472 VALUE str;
473 {
474 HISTORY_STATE *state;
475 VALUE s = str;
476 int i;
477
478 state = history_get_history_state();
479 i = NUM2INT(index);
480 if (i < 0) {
481 i += state->length;
482 }
483 if (i < 0 || i > state->length - 1) {
484 rb_raise(rb_eIndexError, "Invalid index");
485 }
486 replace_history_entry(i, StringValuePtr(s), NULL);
487 return str;
488 }
489
490 static VALUE
491 hist_push(self, str)
492 VALUE self;
493 VALUE str;
494 {
495 add_history(StringValuePtr(str));
496 return self;
497 }
498
499 static VALUE
500 hist_push_method(argc, argv, self)
501 int argc;
502 VALUE *argv;
503 VALUE self;
504 {
505 VALUE str;
506
507 while (argc--) {
508 str = *argv++;
509 add_history(StringValuePtr(str));
510 }
511 return self;
512 }
513
514 static VALUE
515 hist_pop(self)
516 VALUE self;
517 {
518 HISTORY_STATE *state;
519
520 state = history_get_history_state();
521 if (state->length > 0) {
522 return rb_remove_history(state->length - 1);
523 } else {
524 return Qnil;
525 }
526 }
527
528 static VALUE
529 hist_shift(self)
530 VALUE self;
531 {
532 HISTORY_STATE *state;
533
534 state = history_get_history_state();
535 if (state->length > 0) {
536 return rb_remove_history(0);
537 } else {
538 return Qnil;
539 }
540 }
541
542 static VALUE
543 hist_each(self)
544 VALUE self;
545 {
546 HISTORY_STATE *state;
547 int i;
548
549 state = history_get_history_state();
550 for (i = 0; i < state->length; i++) {
551 rb_yield(rb_tainted_str_new2(state->entries[i]->line));
552 }
553 return self;
554 }
555
556 static VALUE
557 hist_length(self)
558 VALUE self;
559 {
560 HISTORY_STATE *state;
561
562 state = history_get_history_state();
563 return INT2NUM(state->length);
564 }
565
566 static VALUE
567 hist_empty_p(self)
568 VALUE self;
569 {
570 HISTORY_STATE *state;
571
572 state = history_get_history_state();
573 if (state->length == 0)
574 return Qtrue;
575 else
576 return Qfalse;
577 }
578
579 static VALUE
580 hist_delete_at(self, index)
581 VALUE self;
582 VALUE index;
583 {
584 HISTORY_STATE *state;
585 int i;
586
587 state = history_get_history_state();
588 i = NUM2INT(index);
589 if (i < 0)
590 i += state->length;
591 if (i < 0 || i > state->length - 1) {
592 rb_raise(rb_eIndexError, "Invalid index");
593 }
594 return rb_remove_history(i);
595 }
596
597 static VALUE
598 filename_completion_proc_call(self, str)
599 VALUE self;
600 VALUE str;
601 {
602 VALUE result;
603 char **matches;
604 int i;
605
606 matches = rl_completion_matches(StringValuePtr(str),
607 rl_filename_completion_function);
608 if (matches) {
609 result = rb_ary_new();
610 for (i = 0; matches[i]; i++) {
611 rb_ary_push(result, rb_tainted_str_new2(matches[i]));
612 free(matches[i]);
613 }
614 free(matches);
615 if (RARRAY(result)->len >= 2)
616 rb_ary_shift(result);
617 }
618 else {
619 result = Qnil;
620 }
621 return result;
622 }
623
624 static VALUE
625 username_completion_proc_call(self, str)
626 VALUE self;
627 VALUE str;
628 {
629 VALUE result;
630 char **matches;
631 int i;
632
633 matches = rl_completion_matches(StringValuePtr(str),
634 rl_username_completion_function);
635 if (matches) {
636 result = rb_ary_new();
637 for (i = 0; matches[i]; i++) {
638 rb_ary_push(result, rb_tainted_str_new2(matches[i]));
639 free(matches[i]);
640 }
641 free(matches);
642 if (RARRAY(result)->len >= 2)
643 rb_ary_shift(result);
644 }
645 else {
646 result = Qnil;
647 }
648 return result;
649 }
650
651 void
652 Init_readline()
653 {
654 VALUE history, fcomp, ucomp;
655
656
657 rl_readline_name = "Ruby";
658
659 using_history();
660
661 mReadline = rb_define_module("Readline");
662 rb_define_module_function(mReadline, "readline",
663 readline_readline, -1);
664 rb_define_singleton_method(mReadline, "completion_proc=",
665 readline_s_set_completion_proc, 1);
666 rb_define_singleton_method(mReadline, "completion_proc",
667 readline_s_get_completion_proc, 0);
668 rb_define_singleton_method(mReadline, "completion_case_fold=",
669 readline_s_set_completion_case_fold, 1);
670 rb_define_singleton_method(mReadline, "completion_case_fold",
671 readline_s_get_completion_case_fold, 0);
672 rb_define_singleton_method(mReadline, "vi_editing_mode",
673 readline_s_vi_editing_mode, 0);
674 rb_define_singleton_method(mReadline, "emacs_editing_mode",
675 readline_s_emacs_editing_mode, 0);
676 rb_define_singleton_method(mReadline, "completion_append_character=",
677 readline_s_set_completion_append_character, 1);
678 rb_define_singleton_method(mReadline, "completion_append_character",
679 readline_s_get_completion_append_character, 0);
680 rb_define_singleton_method(mReadline, "basic_word_break_characters=",
681 readline_s_set_basic_word_break_characters, 1);
682 rb_define_singleton_method(mReadline, "basic_word_break_characters",
683 readline_s_get_basic_word_break_characters, 0);
684 rb_define_singleton_method(mReadline, "completer_word_break_characters=",
685 readline_s_set_completer_word_break_characters, 1);
686 rb_define_singleton_method(mReadline, "completer_word_break_characters",
687 readline_s_get_completer_word_break_characters, 0);
688 rb_define_singleton_method(mReadline, "basic_quote_characters=",
689 readline_s_set_basic_quote_characters, 1);
690 rb_define_singleton_method(mReadline, "basic_quote_characters",
691 readline_s_get_basic_quote_characters, 0);
692 rb_define_singleton_method(mReadline, "completer_quote_characters=",
693 readline_s_set_completer_quote_characters, 1);
694 rb_define_singleton_method(mReadline, "completer_quote_characters",
695 readline_s_get_completer_quote_characters, 0);
696 rb_define_singleton_method(mReadline, "filename_quote_characters=",
697 readline_s_set_filename_quote_characters, 1);
698 rb_define_singleton_method(mReadline, "filename_quote_characters",
699 readline_s_get_filename_quote_characters, 0);
700
701 history = rb_obj_alloc(rb_cObject);
702 rb_extend_object(history, rb_mEnumerable);
703 rb_define_singleton_method(history,"to_s", hist_to_s, 0);
704 rb_define_singleton_method(history,"[]", hist_get, 1);
705 rb_define_singleton_method(history,"[]=", hist_set, 2);
706 rb_define_singleton_method(history,"<<", hist_push, 1);
707 rb_define_singleton_method(history,"push", hist_push_method, -1);
708 rb_define_singleton_method(history,"pop", hist_pop, 0);
709 rb_define_singleton_method(history,"shift", hist_shift, 0);
710 rb_define_singleton_method(history,"each", hist_each, 0);
711 rb_define_singleton_method(history,"length", hist_length, 0);
712 rb_define_singleton_method(history,"size", hist_length, 0);
713
714 rb_define_singleton_method(history,"empty?", hist_empty_p, 0);
715 rb_define_singleton_method(history,"delete_at", hist_delete_at, 1);
716 rb_define_const(mReadline, "HISTORY", history);
717
718 fcomp = rb_obj_alloc(rb_cObject);
719 rb_define_singleton_method(fcomp, "call",
720 filename_completion_proc_call, 1);
721 rb_define_const(mReadline, "FILENAME_COMPLETION_PROC", fcomp);
722
723 ucomp = rb_obj_alloc(rb_cObject);
724 rb_define_singleton_method(ucomp, "call",
725 username_completion_proc_call, 1);
726 rb_define_const(mReadline, "USERNAME_COMPLETION_PROC", ucomp);
727 #if READLINE_21_OR_LATER
728 rb_define_const(mReadline, "VERSION", rb_str_new2(rl_library_version));
729 #else
730 rb_define_const(mReadline, "VERSION",
731 rb_str_new2("2.0 or before version"));
732 #endif
733
734 rl_attempted_completion_function
735 = (CPPFunction *) readline_attempted_completion_function;
736 rl_event_hook = readline_event;
737 rl_clear_signals();
738 }