readline-ext 0.1.0.pre.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,19 @@
1
+ # AUTOGENERATED DEPENDENCIES START
2
+ readline.o: $(RUBY_EXTCONF_H)
3
+ readline.o: $(arch_hdrdir)/ruby/config.h
4
+ readline.o: $(hdrdir)/ruby.h
5
+ readline.o: $(hdrdir)/ruby/assert.h
6
+ readline.o: $(hdrdir)/ruby/backward.h
7
+ readline.o: $(hdrdir)/ruby/defines.h
8
+ readline.o: $(hdrdir)/ruby/encoding.h
9
+ readline.o: $(hdrdir)/ruby/intern.h
10
+ readline.o: $(hdrdir)/ruby/io.h
11
+ readline.o: $(hdrdir)/ruby/missing.h
12
+ readline.o: $(hdrdir)/ruby/onigmo.h
13
+ readline.o: $(hdrdir)/ruby/oniguruma.h
14
+ readline.o: $(hdrdir)/ruby/ruby.h
15
+ readline.o: $(hdrdir)/ruby/st.h
16
+ readline.o: $(hdrdir)/ruby/subst.h
17
+ readline.o: $(hdrdir)/ruby/thread.h
18
+ readline.o: readline.c
19
+ # AUTOGENERATED DEPENDENCIES END
@@ -0,0 +1,113 @@
1
+ # frozen_string_literal: false
2
+ require "mkmf"
3
+
4
+ readline = Struct.new(:headers, :extra_check).new(["stdio.h"])
5
+
6
+ def readline.have_header(header)
7
+ if super(header, &extra_check)
8
+ headers.push(header)
9
+ return true
10
+ else
11
+ return false
12
+ end
13
+ end
14
+
15
+ def readline.have_var(var)
16
+ return super(var, headers)
17
+ end
18
+
19
+ def readline.have_func(func)
20
+ return super(func, headers)
21
+ end
22
+
23
+ def readline.have_type(type)
24
+ return super(type, headers)
25
+ end
26
+
27
+ dir_config('curses')
28
+ dir_config('ncurses')
29
+ dir_config('termcap')
30
+ dir_config("readline")
31
+ enable_libedit = enable_config("libedit")
32
+
33
+ have_library("user32", nil) if /cygwin/ === RUBY_PLATFORM
34
+ have_library("ncurses", "tgetnum") ||
35
+ have_library("termcap", "tgetnum") ||
36
+ have_library("curses", "tgetnum")
37
+
38
+ case enable_libedit
39
+ when true
40
+ # --enable-libedit
41
+ dir_config("libedit")
42
+ unless (readline.have_header("editline/readline.h") ||
43
+ readline.have_header("readline/readline.h")) &&
44
+ have_library("edit", "readline")
45
+ raise "libedit not found"
46
+ end
47
+ when false
48
+ # --disable-libedit
49
+ unless ((readline.have_header("readline/readline.h") &&
50
+ readline.have_header("readline/history.h")) &&
51
+ have_library("readline", "readline"))
52
+ raise "readline not found"
53
+ end
54
+ else
55
+ # does not specify
56
+ unless ((readline.have_header("readline/readline.h") &&
57
+ readline.have_header("readline/history.h")) &&
58
+ (have_library("readline", "readline") ||
59
+ have_library("edit", "readline"))) ||
60
+ (readline.have_header("editline/readline.h") &&
61
+ have_library("edit", "readline"))
62
+ raise "Neither readline nor libedit was found"
63
+ end
64
+ end
65
+
66
+ readline.have_func("rl_getc")
67
+ readline.have_func("rl_getc_function")
68
+ readline.have_func("rl_filename_completion_function")
69
+ readline.have_func("rl_username_completion_function")
70
+ readline.have_func("rl_completion_matches")
71
+ readline.have_func("rl_refresh_line")
72
+ readline.have_var("rl_deprep_term_function")
73
+ readline.have_var("rl_completion_append_character")
74
+ readline.have_var("rl_completion_quote_character")
75
+ readline.have_var("rl_basic_word_break_characters")
76
+ readline.have_var("rl_completer_word_break_characters")
77
+ readline.have_var("rl_basic_quote_characters")
78
+ readline.have_var("rl_completer_quote_characters")
79
+ readline.have_var("rl_filename_quote_characters")
80
+ readline.have_var("rl_attempted_completion_over")
81
+ readline.have_var("rl_library_version")
82
+ readline.have_var("rl_editing_mode")
83
+ readline.have_var("rl_line_buffer")
84
+ readline.have_var("rl_point")
85
+ readline.have_var("rl_char_is_quoted_p")
86
+ # workaround for native windows.
87
+ /mswin|bccwin/ !~ RUBY_PLATFORM && readline.have_var("rl_event_hook")
88
+ /mswin|bccwin/ !~ RUBY_PLATFORM && readline.have_var("rl_catch_sigwinch")
89
+ /mswin|bccwin/ !~ RUBY_PLATFORM && readline.have_var("rl_catch_signals")
90
+ readline.have_var("rl_pre_input_hook")
91
+ readline.have_var("rl_special_prefixes")
92
+ readline.have_func("rl_cleanup_after_signal")
93
+ readline.have_func("rl_free_line_state")
94
+ readline.have_func("rl_clear_signals")
95
+ readline.have_func("rl_set_screen_size")
96
+ readline.have_func("rl_get_screen_size")
97
+ readline.have_func("rl_vi_editing_mode")
98
+ readline.have_func("rl_emacs_editing_mode")
99
+ readline.have_func("replace_history_entry")
100
+ readline.have_func("remove_history")
101
+ readline.have_func("clear_history")
102
+ readline.have_func("rl_redisplay")
103
+ readline.have_func("rl_insert_text")
104
+ readline.have_func("rl_delete_text")
105
+ unless readline.have_type("rl_hook_func_t*")
106
+ # rl_hook_func_t is available since readline-4.2 (2001).
107
+ # Function is removed at readline-6.3 (2014).
108
+ # However, editline (NetBSD 6.1.3, 2014) doesn't have rl_hook_func_t.
109
+ $defs << "-Drl_hook_func_t=Function"
110
+ end
111
+
112
+ $INCFLAGS << " -I$(top_srcdir)"
113
+ create_makefile("readline")
@@ -0,0 +1,2142 @@
1
+ /************************************************
2
+
3
+ readline.c - GNU Readline module
4
+
5
+ $Author$
6
+ created at: Wed Jan 20 13:59:32 JST 1999
7
+
8
+ Copyright (C) 1997-2008 Shugo Maeda
9
+ Copyright (C) 2008-2013 Kouji Takao
10
+
11
+ $Id$
12
+
13
+ Contact:
14
+ - Kouji Takao <kouji dot takao at gmail dot com> (current maintainer)
15
+
16
+ ************************************************/
17
+
18
+ #ifdef RUBY_EXTCONF_H
19
+ #include RUBY_EXTCONF_H
20
+ #endif
21
+
22
+ #include "ruby/config.h"
23
+ #include <errno.h>
24
+ #include <stdio.h>
25
+ #include <string.h>
26
+ #ifdef HAVE_READLINE_READLINE_H
27
+ #include <readline/readline.h>
28
+ #endif
29
+ #ifdef HAVE_READLINE_HISTORY_H
30
+ #include <readline/history.h>
31
+ #endif
32
+ #ifdef HAVE_EDITLINE_READLINE_H
33
+ #include <editline/readline.h>
34
+ #endif
35
+
36
+ #include "ruby/io.h"
37
+ #include "ruby/thread.h"
38
+
39
+ #ifdef HAVE_UNISTD_H
40
+ #include <unistd.h>
41
+ #endif
42
+
43
+ #ifdef HAVE_SYS_STAT_H
44
+ #include <sys/stat.h>
45
+ #endif
46
+
47
+ static VALUE mReadline;
48
+
49
+ #define EDIT_LINE_LIBRARY_VERSION "EditLine wrapper"
50
+ #ifndef USE_INSERT_IGNORE_ESCAPE
51
+ # if !defined(HAVE_EDITLINE_READLINE_H) && defined(RL_PROMPT_START_IGNORE) && defined(RL_PROMPT_END_IGNORE)
52
+ # define USE_INSERT_IGNORE_ESCAPE 1
53
+ # else
54
+ # define USE_INSERT_IGNORE_ESCAPE 0
55
+ # endif
56
+ #endif
57
+
58
+ #define COMPLETION_PROC "completion_proc"
59
+ #define COMPLETION_CASE_FOLD "completion_case_fold"
60
+ static ID id_call, completion_proc, completion_case_fold;
61
+ #if defined HAVE_RL_CHAR_IS_QUOTED_P
62
+ #define QUOTING_DETECTION_PROC "quoting_detection_proc"
63
+ static ID quoting_detection_proc;
64
+ #endif
65
+ #if USE_INSERT_IGNORE_ESCAPE
66
+ static ID id_orig_prompt, id_last_prompt;
67
+ #endif
68
+ #if defined(HAVE_RL_PRE_INPUT_HOOK)
69
+ static ID id_pre_input_hook;
70
+ #endif
71
+ #if defined(HAVE_RL_SPECIAL_PREFIXES)
72
+ static ID id_special_prefixes;
73
+ #endif
74
+
75
+ #ifndef HAVE_RL_FILENAME_COMPLETION_FUNCTION
76
+ # define rl_filename_completion_function filename_completion_function
77
+ #endif
78
+ #ifndef HAVE_RL_USERNAME_COMPLETION_FUNCTION
79
+ # define rl_username_completion_function username_completion_function
80
+ #else
81
+ char *rl_username_completion_function(const char *, int);
82
+ #endif
83
+ #ifndef HAVE_RL_COMPLETION_MATCHES
84
+ # define rl_completion_matches completion_matches
85
+ #endif
86
+
87
+ static int (*history_get_offset_func)(int);
88
+ static int (*history_replace_offset_func)(int);
89
+ #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
90
+ static int readline_completion_append_character;
91
+ #endif
92
+
93
+ static char **readline_attempted_completion_function(const char *text,
94
+ int start, int end);
95
+
96
+ #define OutputStringValue(str) do {\
97
+ StringValueCStr(str);\
98
+ rb_check_safe_obj(str);\
99
+ (str) = rb_str_conv_enc((str), rb_enc_get(str), rb_locale_encoding());\
100
+ } while (0)\
101
+
102
+
103
+ /*
104
+ * Document-class: Readline
105
+ *
106
+ * The Readline module provides interface for GNU Readline.
107
+ * This module defines a number of methods to facilitate completion
108
+ * and accesses input history from the Ruby interpreter.
109
+ * This module supported Edit Line(libedit) too.
110
+ * libedit is compatible with GNU Readline.
111
+ *
112
+ * GNU Readline:: http://www.gnu.org/directory/readline.html
113
+ * libedit:: http://www.thrysoee.dk/editline/
114
+ *
115
+ * Reads one inputted line with line edit by Readline.readline method.
116
+ * At this time, the facilitatation completion and the key
117
+ * bind like Emacs can be operated like GNU Readline.
118
+ *
119
+ * require "readline"
120
+ * while buf = Readline.readline("> ", true)
121
+ * p buf
122
+ * end
123
+ *
124
+ * The content that the user input can be recorded to the history.
125
+ * The history can be accessed by Readline::HISTORY constant.
126
+ *
127
+ * require "readline"
128
+ * while buf = Readline.readline("> ", true)
129
+ * p Readline::HISTORY.to_a
130
+ * print("-> ", buf, "\n")
131
+ * end
132
+ *
133
+ * Documented by Kouji Takao <kouji dot takao at gmail dot com>.
134
+ */
135
+
136
+ static VALUE readline_instream;
137
+ static VALUE readline_outstream;
138
+ static FILE *readline_rl_instream;
139
+ static FILE *readline_rl_outstream;
140
+
141
+ static void
142
+ mustbe_callable(VALUE proc)
143
+ {
144
+ if (!NIL_P(proc) && !rb_respond_to(proc, id_call))
145
+ rb_raise(rb_eArgError, "argument must respond to `call'");
146
+ }
147
+
148
+ #if defined HAVE_RL_GETC_FUNCTION
149
+
150
+ #ifndef HAVE_RL_GETC
151
+ #define rl_getc(f) EOF
152
+ #endif
153
+
154
+ struct getc_struct {
155
+ FILE *input;
156
+ int fd;
157
+ int ret;
158
+ int err;
159
+ };
160
+
161
+ static int
162
+ getc_body(struct getc_struct *p)
163
+ {
164
+ char ch;
165
+ ssize_t ss;
166
+
167
+ #if defined(_WIN32)
168
+ {
169
+ INPUT_RECORD ir;
170
+ DWORD n;
171
+ static int prior_key = '0';
172
+ for (;;) {
173
+ HANDLE h;
174
+ if (prior_key > 0xff) {
175
+ prior_key = rl_getc(p->input);
176
+ return prior_key;
177
+ }
178
+ h = (HANDLE)_get_osfhandle(p->fd);
179
+ if (PeekConsoleInput(h, &ir, 1, &n)) {
180
+ if (n == 1) {
181
+ if (ir.EventType == KEY_EVENT && ir.Event.KeyEvent.bKeyDown) {
182
+ prior_key = rl_getc(p->input);
183
+ return prior_key;
184
+ } else {
185
+ ReadConsoleInput(h, &ir, 1, &n);
186
+ }
187
+ } else {
188
+ rb_w32_wait_events_blocking(&h, 1, INFINITE);
189
+ }
190
+ } else {
191
+ break;
192
+ }
193
+ }
194
+ }
195
+ #endif
196
+
197
+ ss = read(p->fd, &ch, 1);
198
+ if (ss == 0) {
199
+ errno = 0;
200
+ return EOF;
201
+ }
202
+ if (ss != 1)
203
+ return EOF;
204
+ return (unsigned char)ch;
205
+ }
206
+
207
+ static void *
208
+ getc_func(void *data1)
209
+ {
210
+ struct getc_struct *p = data1;
211
+ errno = 0;
212
+ p->ret = getc_body(p);
213
+ p->err = errno;
214
+ return NULL;
215
+ }
216
+
217
+ static int
218
+ readline_getc(FILE *input)
219
+ {
220
+ struct getc_struct data;
221
+ if (input == NULL) /* editline may give NULL as input. */
222
+ input = stdin;
223
+ data.input = input;
224
+ data.fd = fileno(input);
225
+ again:
226
+ data.ret = EOF;
227
+ data.err = EINTR; /* getc_func is not called if already interrupted. */
228
+ rb_thread_call_without_gvl2(getc_func, &data, RUBY_UBF_IO, NULL);
229
+ if (data.ret == EOF) {
230
+ if (data.err == 0) {
231
+ return EOF;
232
+ }
233
+ if (data.err == EINTR) {
234
+ rb_thread_check_ints();
235
+ goto again;
236
+ }
237
+ if (data.err == EWOULDBLOCK || data.err == EAGAIN) {
238
+ int ret;
239
+ if (fileno(input) != data.fd)
240
+ rb_bug("readline_getc: input closed unexpectedly or memory corrupted");
241
+ ret = rb_wait_for_single_fd(data.fd, RB_WAITFD_IN, NULL);
242
+ if (ret != -1 || errno == EINTR)
243
+ goto again;
244
+ rb_sys_fail("rb_wait_for_single_fd");
245
+ }
246
+ rb_syserr_fail(data.err, "read");
247
+ }
248
+ return data.ret;
249
+ }
250
+
251
+ #elif defined HAVE_RL_EVENT_HOOK
252
+ #define BUSY_WAIT 0
253
+
254
+ static int readline_event(void);
255
+ static int
256
+ readline_event(void)
257
+ {
258
+ #if BUSY_WAIT
259
+ rb_thread_schedule();
260
+ #else
261
+ rb_wait_for_single_fd(fileno(rl_instream), RB_WAITFD_IN, NULL);
262
+ return 0;
263
+ #endif
264
+ }
265
+ #endif
266
+
267
+ #if USE_INSERT_IGNORE_ESCAPE
268
+ static VALUE
269
+ insert_ignore_escape(VALUE self, VALUE prompt)
270
+ {
271
+ VALUE last_prompt, orig_prompt = rb_attr_get(self, id_orig_prompt);
272
+ int ignoring = 0;
273
+ const char *s0, *s, *e;
274
+ long len;
275
+ static const char ignore_code[2] = {RL_PROMPT_START_IGNORE, RL_PROMPT_END_IGNORE};
276
+
277
+ prompt = rb_str_new_shared(prompt);
278
+ last_prompt = rb_attr_get(self, id_last_prompt);
279
+ if (orig_prompt == prompt) return last_prompt;
280
+ len = RSTRING_LEN(prompt);
281
+ if (NIL_P(last_prompt)) {
282
+ last_prompt = rb_str_tmp_new(len);
283
+ }
284
+
285
+ s = s0 = RSTRING_PTR(prompt);
286
+ e = s0 + len;
287
+ rb_str_set_len(last_prompt, 0);
288
+ while (s < e && *s) {
289
+ switch (*s) {
290
+ case RL_PROMPT_START_IGNORE:
291
+ ignoring = -1;
292
+ rb_str_cat(last_prompt, s0, ++s - s0);
293
+ s0 = s;
294
+ break;
295
+ case RL_PROMPT_END_IGNORE:
296
+ ignoring = 0;
297
+ rb_str_cat(last_prompt, s0, ++s - s0);
298
+ s0 = s;
299
+ break;
300
+ case '\033':
301
+ if (++s < e && *s == '[') {
302
+ rb_str_cat(last_prompt, s0, s - s0 - 1);
303
+ s0 = s - 1;
304
+ while (++s < e && *s) {
305
+ if (ISALPHA(*(unsigned char *)s)) {
306
+ if (!ignoring) {
307
+ ignoring = 1;
308
+ rb_str_cat(last_prompt, ignore_code+0, 1);
309
+ }
310
+ rb_str_cat(last_prompt, s0, ++s - s0);
311
+ s0 = s;
312
+ break;
313
+ }
314
+ else if (!(('0' <= *s && *s <= '9') || *s == ';')) {
315
+ break;
316
+ }
317
+ }
318
+ }
319
+ break;
320
+ default:
321
+ if (ignoring > 0) {
322
+ ignoring = 0;
323
+ rb_str_cat(last_prompt, ignore_code+1, 1);
324
+ }
325
+ s++;
326
+ break;
327
+ }
328
+ }
329
+ if (ignoring > 0) {
330
+ ignoring = 0;
331
+ rb_str_cat(last_prompt, ignore_code+1, 1);
332
+ }
333
+ rb_str_cat(last_prompt, s0, s - s0);
334
+
335
+ rb_ivar_set(self, id_orig_prompt, prompt);
336
+ rb_ivar_set(self, id_last_prompt, last_prompt);
337
+
338
+ return last_prompt;
339
+ }
340
+ #endif
341
+
342
+ static VALUE
343
+ readline_get(VALUE prompt)
344
+ {
345
+ #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
346
+ readline_completion_append_character = rl_completion_append_character;
347
+ #endif
348
+ return (VALUE)readline((char *)prompt);
349
+ }
350
+
351
+ static void
352
+ clear_rl_instream(void)
353
+ {
354
+ if (readline_rl_instream) {
355
+ fclose(readline_rl_instream);
356
+ if (rl_instream == readline_rl_instream)
357
+ rl_instream = NULL;
358
+ readline_rl_instream = NULL;
359
+ }
360
+ readline_instream = Qfalse;
361
+ }
362
+
363
+ static void
364
+ clear_rl_outstream(void)
365
+ {
366
+ if (readline_rl_outstream) {
367
+ fclose(readline_rl_outstream);
368
+ if (rl_outstream == readline_rl_outstream)
369
+ rl_outstream = NULL;
370
+ readline_rl_outstream = NULL;
371
+ }
372
+ readline_outstream = Qfalse;
373
+ }
374
+
375
+ static void
376
+ prepare_readline(void)
377
+ {
378
+ static int initialized = 0;
379
+ if (!initialized) {
380
+ rl_initialize();
381
+ initialized = 1;
382
+ }
383
+
384
+ if (readline_instream) {
385
+ rb_io_t *ifp;
386
+ rb_io_check_initialized(ifp = RFILE(rb_io_taint_check(readline_instream))->fptr);
387
+ if (ifp->fd < 0) {
388
+ clear_rl_instream();
389
+ rb_raise(rb_eIOError, "closed readline input");
390
+ }
391
+ }
392
+
393
+ if (readline_outstream) {
394
+ rb_io_t *ofp;
395
+ rb_io_check_initialized(ofp = RFILE(rb_io_taint_check(readline_outstream))->fptr);
396
+ if (ofp->fd < 0) {
397
+ clear_rl_outstream();
398
+ rb_raise(rb_eIOError, "closed readline output");
399
+ }
400
+ }
401
+ }
402
+
403
+ /*
404
+ * call-seq:
405
+ * Readline.readline(prompt = "", add_hist = false) -> string or nil
406
+ *
407
+ * Shows the +prompt+ and reads the inputted line with line editing.
408
+ * The inputted line is added to the history if +add_hist+ is true.
409
+ *
410
+ * Returns nil when the inputted line is empty and user inputs EOF
411
+ * (Presses ^D on UNIX).
412
+ *
413
+ * Raises IOError exception if one of below conditions are satisfied.
414
+ * 1. stdin was closed.
415
+ * 2. stdout was closed.
416
+ *
417
+ * This method supports thread. Switches the thread context when waits
418
+ * inputting line.
419
+ *
420
+ * Supports line edit when inputs line. Provides VI and Emacs editing mode.
421
+ * Default is Emacs editing mode.
422
+ *
423
+ * NOTE: Terminates ruby interpreter and does not return the terminal
424
+ * status after user pressed '^C' when wait inputting line.
425
+ * Give 3 examples that avoid it.
426
+ *
427
+ * * Catches the Interrupt exception by pressed ^C after returns
428
+ * terminal status:
429
+ *
430
+ * require "readline"
431
+ *
432
+ * stty_save = `stty -g`.chomp
433
+ * begin
434
+ * while buf = Readline.readline
435
+ * p buf
436
+ * end
437
+ * rescue Interrupt
438
+ * system("stty", stty_save)
439
+ * exit
440
+ * end
441
+ * end
442
+ * end
443
+ *
444
+ * * Catches the INT signal by pressed ^C after returns terminal
445
+ * status:
446
+ *
447
+ * require "readline"
448
+ *
449
+ * stty_save = `stty -g`.chomp
450
+ * trap("INT") { system "stty", stty_save; exit }
451
+ *
452
+ * while buf = Readline.readline
453
+ * p buf
454
+ * end
455
+ *
456
+ * * Ignores pressing ^C:
457
+ *
458
+ * require "readline"
459
+ *
460
+ * trap("INT", "SIG_IGN")
461
+ *
462
+ * while buf = Readline.readline
463
+ * p buf
464
+ * end
465
+ *
466
+ * Can make as follows with Readline::HISTORY constant.
467
+ * It does not record to the history if the inputted line is empty or
468
+ * the same it as last one.
469
+ *
470
+ * require "readline"
471
+ *
472
+ * while buf = Readline.readline("> ", true)
473
+ * # p Readline::HISTORY.to_a
474
+ * Readline::HISTORY.pop if /^\s*$/ =~ buf
475
+ *
476
+ * begin
477
+ * if Readline::HISTORY[Readline::HISTORY.length-2] == buf
478
+ * Readline::HISTORY.pop
479
+ * end
480
+ * rescue IndexError
481
+ * end
482
+ *
483
+ * # p Readline::HISTORY.to_a
484
+ * print "-> ", buf, "\n"
485
+ * end
486
+ */
487
+ static VALUE
488
+ readline_readline(int argc, VALUE *argv, VALUE self)
489
+ {
490
+ VALUE tmp, add_hist, result;
491
+ char *prompt = NULL;
492
+ char *buff;
493
+ int status;
494
+
495
+ if (rb_scan_args(argc, argv, "02", &tmp, &add_hist) > 0) {
496
+ OutputStringValue(tmp);
497
+ #if USE_INSERT_IGNORE_ESCAPE
498
+ tmp = insert_ignore_escape(self, tmp);
499
+ rb_str_locktmp(tmp);
500
+ #endif
501
+ prompt = RSTRING_PTR(tmp);
502
+ }
503
+
504
+ prepare_readline();
505
+
506
+ #ifdef _WIN32
507
+ rl_prep_terminal(1);
508
+ #endif
509
+ buff = (char*)rb_protect(readline_get, (VALUE)prompt, &status);
510
+ #if USE_INSERT_IGNORE_ESCAPE
511
+ if (prompt) {
512
+ rb_str_unlocktmp(tmp);
513
+ }
514
+ #endif
515
+ if (status) {
516
+ #if defined HAVE_RL_CLEANUP_AFTER_SIGNAL
517
+ /* restore terminal mode and signal handler*/
518
+ #if defined HAVE_RL_FREE_LINE_STATE
519
+ rl_free_line_state();
520
+ #endif
521
+ rl_cleanup_after_signal();
522
+ #elif defined HAVE_RL_DEPREP_TERM_FUNCTION
523
+ /* restore terminal mode */
524
+ if (rl_deprep_term_function != NULL) /* NULL in libedit. [ruby-dev:29116] */
525
+ (*rl_deprep_term_function)();
526
+ else
527
+ #else
528
+ rl_deprep_terminal();
529
+ #endif
530
+ rb_jump_tag(status);
531
+ }
532
+
533
+ if (RTEST(add_hist) && buff) {
534
+ add_history(buff);
535
+ }
536
+ if (buff) {
537
+ result = rb_locale_str_new_cstr(buff);
538
+ }
539
+ else
540
+ result = Qnil;
541
+ if (buff) free(buff);
542
+ return result;
543
+ }
544
+
545
+ /*
546
+ * call-seq:
547
+ * Readline.input = input
548
+ *
549
+ * Specifies a File object +input+ that is input stream for
550
+ * Readline.readline method.
551
+ */
552
+ static VALUE
553
+ readline_s_set_input(VALUE self, VALUE input)
554
+ {
555
+ rb_io_t *ifp;
556
+ int fd;
557
+ FILE *f;
558
+
559
+ if (NIL_P(input)) {
560
+ clear_rl_instream();
561
+ }
562
+ else {
563
+ Check_Type(input, T_FILE);
564
+ GetOpenFile(input, ifp);
565
+ clear_rl_instream();
566
+ fd = rb_cloexec_dup(ifp->fd);
567
+ if (fd == -1)
568
+ rb_sys_fail("dup");
569
+ f = fdopen(fd, "r");
570
+ if (f == NULL) {
571
+ int save_errno = errno;
572
+ close(fd);
573
+ rb_syserr_fail(save_errno, "fdopen");
574
+ }
575
+ rl_instream = readline_rl_instream = f;
576
+ readline_instream = input;
577
+ }
578
+ return input;
579
+ }
580
+
581
+ /*
582
+ * call-seq:
583
+ * Readline.output = output
584
+ *
585
+ * Specifies a File object +output+ that is output stream for
586
+ * Readline.readline method.
587
+ */
588
+ static VALUE
589
+ readline_s_set_output(VALUE self, VALUE output)
590
+ {
591
+ rb_io_t *ofp;
592
+ int fd;
593
+ FILE *f;
594
+
595
+ if (NIL_P(output)) {
596
+ clear_rl_outstream();
597
+ }
598
+ else {
599
+ Check_Type(output, T_FILE);
600
+ GetOpenFile(output, ofp);
601
+ clear_rl_outstream();
602
+ fd = rb_cloexec_dup(ofp->fd);
603
+ if (fd == -1)
604
+ rb_sys_fail("dup");
605
+ f = fdopen(fd, "w");
606
+ if (f == NULL) {
607
+ int save_errno = errno;
608
+ close(fd);
609
+ rb_syserr_fail(save_errno, "fdopen");
610
+ }
611
+ rl_outstream = readline_rl_outstream = f;
612
+ readline_outstream = output;
613
+ }
614
+ return output;
615
+ }
616
+
617
+ #if defined(HAVE_RL_PRE_INPUT_HOOK)
618
+ /*
619
+ * call-seq:
620
+ * Readline.pre_input_hook = proc
621
+ *
622
+ * Specifies a Proc object +proc+ to call after the first prompt has
623
+ * been printed and just before readline starts reading input
624
+ * characters.
625
+ *
626
+ * See GNU Readline's rl_pre_input_hook variable.
627
+ *
628
+ * Raises ArgumentError if +proc+ does not respond to the call method.
629
+ *
630
+ * Raises NotImplementedError if the using readline library does not support.
631
+ */
632
+ static VALUE
633
+ readline_s_set_pre_input_hook(VALUE self, VALUE proc)
634
+ {
635
+ mustbe_callable(proc);
636
+ return rb_ivar_set(mReadline, id_pre_input_hook, proc);
637
+ }
638
+
639
+ /*
640
+ * call-seq:
641
+ * Readline.pre_input_hook -> proc
642
+ *
643
+ * Returns a Proc object +proc+ to call after the first prompt has
644
+ * been printed and just before readline starts reading input
645
+ * characters. The default is nil.
646
+ *
647
+ * Raises NotImplementedError if the using readline library does not support.
648
+ */
649
+ static VALUE
650
+ readline_s_get_pre_input_hook(VALUE self)
651
+ {
652
+ return rb_attr_get(mReadline, id_pre_input_hook);
653
+ }
654
+
655
+ static int
656
+ readline_pre_input_hook(void)
657
+ {
658
+ VALUE proc;
659
+
660
+ proc = rb_attr_get(mReadline, id_pre_input_hook);
661
+ if (!NIL_P(proc))
662
+ rb_funcall(proc, id_call, 0);
663
+ return 0;
664
+ }
665
+ #else
666
+ #define readline_s_set_pre_input_hook rb_f_notimplement
667
+ #define readline_s_get_pre_input_hook rb_f_notimplement
668
+ #endif
669
+
670
+ #if defined(HAVE_RL_INSERT_TEXT)
671
+ /*
672
+ * call-seq:
673
+ * Readline.insert_text(string) -> self
674
+ *
675
+ * Insert text into the line at the current cursor position.
676
+ *
677
+ * See GNU Readline's rl_insert_text function.
678
+ *
679
+ * Raises NotImplementedError if the using readline library does not support.
680
+ */
681
+ static VALUE
682
+ readline_s_insert_text(VALUE self, VALUE str)
683
+ {
684
+ OutputStringValue(str);
685
+ rl_insert_text(RSTRING_PTR(str));
686
+ return self;
687
+ }
688
+ #else
689
+ #define readline_s_insert_text rb_f_notimplement
690
+ #endif
691
+
692
+ #if defined(HAVE_RL_DELETE_TEXT)
693
+ int rl_delete_text(int, int);
694
+ static const char *
695
+ str_subpos(const char *ptr, const char *end, long beg, long *sublen, rb_encoding *enc)
696
+ {
697
+ VALUE str = rb_enc_str_new_static(ptr, end-ptr, enc);
698
+ OBJ_FREEZE(str);
699
+ ptr = rb_str_subpos(str, beg, sublen);
700
+ rb_gc_force_recycle(str);
701
+ return ptr;
702
+ }
703
+
704
+ /*
705
+ * call-seq:
706
+ * Readline.delete_text([start[, length]]) -> self
707
+ * Readline.delete_text(start..end) -> self
708
+ * Readline.delete_text() -> self
709
+ *
710
+ * Delete text between start and end in the current line.
711
+ *
712
+ * See GNU Readline's rl_delete_text function.
713
+ *
714
+ * Raises NotImplementedError if the using readline library does not support.
715
+ */
716
+ static VALUE
717
+ readline_s_delete_text(int argc, VALUE *argv, VALUE self)
718
+ {
719
+ rb_check_arity(argc, 0, 2);
720
+ if (rl_line_buffer) {
721
+ const char *p, *ptr = rl_line_buffer;
722
+ long beg = 0, len = strlen(ptr);
723
+ const char *end = ptr + len;
724
+ rb_encoding *enc = rb_locale_encoding();
725
+ if (argc == 2) {
726
+ beg = NUM2LONG(argv[0]);
727
+ len = NUM2LONG(argv[1]);
728
+ num_pos:
729
+ p = str_subpos(ptr, end, beg, &len, enc);
730
+ if (!p) rb_raise(rb_eArgError, "invalid index");
731
+ beg = p - ptr;
732
+ }
733
+ else if (argc == 1) {
734
+ len = rb_enc_strlen(ptr, ptr + len, enc);
735
+ if (!rb_range_beg_len(argv[0], &beg, &len, len, 1)) {
736
+ beg = NUM2LONG(argv[0]);
737
+ goto num_pos;
738
+ }
739
+ }
740
+ rl_delete_text(rb_long2int(beg), rb_long2int(beg + len));
741
+ }
742
+ return self;
743
+ }
744
+ #else
745
+ #define readline_s_delete_text rb_f_notimplement
746
+ #endif
747
+
748
+ #if defined(HAVE_RL_REDISPLAY)
749
+ /*
750
+ * call-seq:
751
+ * Readline.redisplay -> self
752
+ *
753
+ * Change what's displayed on the screen to reflect the current
754
+ * contents.
755
+ *
756
+ * See GNU Readline's rl_redisplay function.
757
+ *
758
+ * Raises NotImplementedError if the using readline library does not support.
759
+ */
760
+ static VALUE
761
+ readline_s_redisplay(VALUE self)
762
+ {
763
+ rl_redisplay();
764
+ return self;
765
+ }
766
+ #else
767
+ #define readline_s_redisplay rb_f_notimplement
768
+ #endif
769
+
770
+ /*
771
+ * call-seq:
772
+ * Readline.completion_proc = proc
773
+ *
774
+ * Specifies a Proc object +proc+ to determine completion behavior. It
775
+ * should take input string and return an array of completion candidates.
776
+ *
777
+ * The default completion is used if +proc+ is nil.
778
+ *
779
+ * The String that is passed to the Proc depends on the
780
+ * Readline.completer_word_break_characters property. By default the word
781
+ * under the cursor is passed to the Proc. For example, if the input is "foo
782
+ * bar" then only "bar" would be passed to the completion Proc.
783
+ *
784
+ * Upon successful completion the Readline.completion_append_character will be
785
+ * appended to the input so the user can start working on their next argument.
786
+ *
787
+ * = Examples
788
+ *
789
+ * == Completion for a Static List
790
+ *
791
+ * require 'readline'
792
+ *
793
+ * LIST = [
794
+ * 'search', 'download', 'open',
795
+ * 'help', 'history', 'quit',
796
+ * 'url', 'next', 'clear',
797
+ * 'prev', 'past'
798
+ * ].sort
799
+ *
800
+ * comp = proc { |s| LIST.grep(/^#{Regexp.escape(s)}/) }
801
+ *
802
+ * Readline.completion_append_character = " "
803
+ * Readline.completion_proc = comp
804
+ *
805
+ * while line = Readline.readline('> ', true)
806
+ * p line
807
+ * end
808
+ *
809
+ * == Completion For Directory Contents
810
+ *
811
+ * require 'readline'
812
+ *
813
+ * Readline.completion_append_character = " "
814
+ * Readline.completion_proc = Proc.new do |str|
815
+ * Dir[str+'*'].grep(/^#{Regexp.escape(str)}/)
816
+ * end
817
+ *
818
+ * while line = Readline.readline('> ', true)
819
+ * p line
820
+ * end
821
+ *
822
+ * = Autocomplete strategies
823
+ *
824
+ * When working with auto-complete there are some strategies that work well.
825
+ * To get some ideas you can take a look at the
826
+ * completion.rb[https://git.ruby-lang.org/ruby.git/tree/lib/irb/completion.rb]
827
+ * file for irb.
828
+ *
829
+ * The common strategy is to take a list of possible completions and filter it
830
+ * down to those completions that start with the user input. In the above
831
+ * examples Enumerator.grep is used. The input is escaped to prevent Regexp
832
+ * special characters from interfering with the matching.
833
+ *
834
+ * It may also be helpful to use the Abbrev library to generate completions.
835
+ *
836
+ * Raises ArgumentError if +proc+ does not respond to the call method.
837
+ */
838
+ static VALUE
839
+ readline_s_set_completion_proc(VALUE self, VALUE proc)
840
+ {
841
+ mustbe_callable(proc);
842
+ return rb_ivar_set(mReadline, completion_proc, proc);
843
+ }
844
+
845
+ /*
846
+ * call-seq:
847
+ * Readline.completion_proc -> proc
848
+ *
849
+ * Returns the completion Proc object.
850
+ */
851
+ static VALUE
852
+ readline_s_get_completion_proc(VALUE self)
853
+ {
854
+ return rb_attr_get(mReadline, completion_proc);
855
+ }
856
+
857
+ #ifdef HAVE_RL_CHAR_IS_QUOTED_P
858
+ /*
859
+ * call-seq:
860
+ * Readline.quoting_detection_proc = proc
861
+ *
862
+ * Specifies a Proc object +proc+ to determine if a character in the user's
863
+ * input is escaped. It should take the user's input and the index of the
864
+ * character in question as input, and return a boolean (true if the specified
865
+ * character is escaped).
866
+ *
867
+ * Readline will only call this proc with characters specified in
868
+ * +completer_quote_characters+, to discover if they indicate the end of a
869
+ * quoted argument, or characters specified in
870
+ * +completer_word_break_characters+, to discover if they indicate a break
871
+ * between arguments.
872
+ *
873
+ * If +completer_quote_characters+ is not set, or if the user input doesn't
874
+ * contain one of the +completer_quote_characters+ or a +\+ character,
875
+ * Readline will not attempt to use this proc at all.
876
+ *
877
+ * Raises ArgumentError if +proc+ does not respond to the call method.
878
+ */
879
+ static VALUE
880
+ readline_s_set_quoting_detection_proc(VALUE self, VALUE proc)
881
+ {
882
+ mustbe_callable(proc);
883
+ return rb_ivar_set(mReadline, quoting_detection_proc, proc);
884
+ }
885
+
886
+ /*
887
+ * call-seq:
888
+ * Readline.quoting_detection_proc -> proc
889
+ *
890
+ * Returns the quoting detection Proc object.
891
+ */
892
+ static VALUE
893
+ readline_s_get_quoting_detection_proc(VALUE self)
894
+ {
895
+ return rb_attr_get(mReadline, quoting_detection_proc);
896
+ }
897
+ #else
898
+ #define readline_s_set_quoting_detection_proc rb_f_notimplement
899
+ #define readline_s_get_quoting_detection_proc rb_f_notimplement
900
+ #endif
901
+
902
+ /*
903
+ * call-seq:
904
+ * Readline.completion_case_fold = bool
905
+ *
906
+ * Sets whether or not to ignore case on completion.
907
+ */
908
+ static VALUE
909
+ readline_s_set_completion_case_fold(VALUE self, VALUE val)
910
+ {
911
+ return rb_ivar_set(mReadline, completion_case_fold, val);
912
+ }
913
+
914
+ /*
915
+ * call-seq:
916
+ * Readline.completion_case_fold -> bool
917
+ *
918
+ * Returns true if completion ignores case. If no, returns false.
919
+ *
920
+ * NOTE: Returns the same object that is specified by
921
+ * Readline.completion_case_fold= method.
922
+ *
923
+ * require "readline"
924
+ *
925
+ * Readline.completion_case_fold = "This is a String."
926
+ * p Readline.completion_case_fold # => "This is a String."
927
+ */
928
+ static VALUE
929
+ readline_s_get_completion_case_fold(VALUE self)
930
+ {
931
+ return rb_attr_get(mReadline, completion_case_fold);
932
+ }
933
+
934
+ #ifdef HAVE_RL_LINE_BUFFER
935
+ /*
936
+ * call-seq:
937
+ * Readline.line_buffer -> string
938
+ *
939
+ * Returns the full line that is being edited. This is useful from
940
+ * within the complete_proc for determining the context of the
941
+ * completion request.
942
+ *
943
+ * The length of +Readline.line_buffer+ and GNU Readline's rl_end are
944
+ * same.
945
+ *
946
+ * Raises NotImplementedError if the using readline library does not support.
947
+ */
948
+ static VALUE
949
+ readline_s_get_line_buffer(VALUE self)
950
+ {
951
+ if (rl_line_buffer == NULL)
952
+ return Qnil;
953
+ return rb_locale_str_new_cstr(rl_line_buffer);
954
+ }
955
+ #else
956
+ #define readline_s_get_line_buffer rb_f_notimplement
957
+ #endif
958
+
959
+ #ifdef HAVE_RL_POINT
960
+ /*
961
+ * call-seq:
962
+ * Readline.point -> int
963
+ *
964
+ * Returns the index of the current cursor position in
965
+ * +Readline.line_buffer+.
966
+ *
967
+ * The index in +Readline.line_buffer+ which matches the start of
968
+ * input-string passed to completion_proc is computed by subtracting
969
+ * the length of input-string from +Readline.point+.
970
+ *
971
+ * start = (the length of input-string) - Readline.point
972
+ *
973
+ * Raises NotImplementedError if the using readline library does not support.
974
+ */
975
+ static VALUE
976
+ readline_s_get_point(VALUE self)
977
+ {
978
+ return INT2NUM(rl_point);
979
+ }
980
+
981
+ /*
982
+ * call-seq:
983
+ * Readline.point = int
984
+ *
985
+ * Set the index of the current cursor position in
986
+ * +Readline.line_buffer+.
987
+ *
988
+ * Raises NotImplementedError if the using readline library does not support.
989
+ *
990
+ * See +Readline.point+.
991
+ */
992
+ static VALUE
993
+ readline_s_set_point(VALUE self, VALUE pos)
994
+ {
995
+ rl_point = NUM2INT(pos);
996
+ return pos;
997
+ }
998
+ #else
999
+ #define readline_s_get_point rb_f_notimplement
1000
+ #define readline_s_set_point rb_f_notimplement
1001
+ #endif
1002
+
1003
+ static char **
1004
+ readline_attempted_completion_function(const char *text, int start, int end)
1005
+ {
1006
+ VALUE proc, ary, temp;
1007
+ char **result;
1008
+ int case_fold;
1009
+ long i, matches;
1010
+ rb_encoding *enc;
1011
+ VALUE encobj;
1012
+
1013
+ proc = rb_attr_get(mReadline, completion_proc);
1014
+ if (NIL_P(proc))
1015
+ return NULL;
1016
+ #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
1017
+ rl_completion_append_character = readline_completion_append_character;
1018
+ #endif
1019
+ #ifdef HAVE_RL_ATTEMPTED_COMPLETION_OVER
1020
+ rl_attempted_completion_over = 1;
1021
+ #endif
1022
+ case_fold = RTEST(rb_attr_get(mReadline, completion_case_fold));
1023
+ ary = rb_funcall(proc, id_call, 1, rb_locale_str_new_cstr(text));
1024
+ if (!RB_TYPE_P(ary, T_ARRAY))
1025
+ ary = rb_Array(ary);
1026
+ matches = RARRAY_LEN(ary);
1027
+ if (matches == 0) return NULL;
1028
+ result = (char**)malloc((matches + 2)*sizeof(char*));
1029
+ if (result == NULL) rb_memerror();
1030
+ enc = rb_locale_encoding();
1031
+ encobj = rb_enc_from_encoding(enc);
1032
+ for (i = 0; i < matches; i++) {
1033
+ temp = rb_obj_as_string(RARRAY_AREF(ary, i));
1034
+ StringValueCStr(temp); /* must be NUL-terminated */
1035
+ rb_enc_check(encobj, temp);
1036
+ result[i + 1] = (char*)malloc(RSTRING_LEN(temp) + 1);
1037
+ if (result[i + 1] == NULL) rb_memerror();
1038
+ strcpy(result[i + 1], RSTRING_PTR(temp));
1039
+ }
1040
+ result[matches + 1] = NULL;
1041
+
1042
+ if (matches == 1) {
1043
+ result[0] = strdup(result[1]);
1044
+ }
1045
+ else {
1046
+ const char *result1 = result[1];
1047
+ long low = strlen(result1);
1048
+
1049
+ for (i = 1; i < matches; ++i) {
1050
+ register int c1, c2;
1051
+ long i1, i2, l2;
1052
+ int n1, n2;
1053
+ const char *p2 = result[i + 1];
1054
+
1055
+ l2 = strlen(p2);
1056
+ for (i1 = i2 = 0; i1 < low && i2 < l2; i1 += n1, i2 += n2) {
1057
+ c1 = rb_enc_codepoint_len(result1 + i1, result1 + low, &n1, enc);
1058
+ c2 = rb_enc_codepoint_len(p2 + i2, p2 + l2, &n2, enc);
1059
+ if (case_fold) {
1060
+ c1 = rb_tolower(c1);
1061
+ c2 = rb_tolower(c2);
1062
+ }
1063
+ if (c1 != c2) break;
1064
+ }
1065
+
1066
+ low = i1;
1067
+ }
1068
+ result[0] = (char*)malloc(low + 1);
1069
+ if (result[0] == NULL) rb_memerror();
1070
+ strncpy(result[0], result[1], low);
1071
+ result[0][low] = '\0';
1072
+ }
1073
+
1074
+ return result;
1075
+ }
1076
+
1077
+ #ifdef HAVE_RL_CHAR_IS_QUOTED_P
1078
+ static int
1079
+ readline_char_is_quoted(char *text, int byte_index)
1080
+ {
1081
+ VALUE proc, result, str;
1082
+ long char_index;
1083
+ size_t len;
1084
+
1085
+ proc = rb_attr_get(mReadline, quoting_detection_proc);
1086
+ if (NIL_P(proc)) {
1087
+ return 0;
1088
+ }
1089
+
1090
+ len = strlen(text);
1091
+ if (byte_index < 0 || len < (size_t)byte_index) {
1092
+ rb_raise(rb_eIndexError, "invalid byte index (%d in %"PRIdSIZE")",
1093
+ byte_index, len);
1094
+ }
1095
+
1096
+ str = rb_locale_str_new(text, len);
1097
+ char_index = rb_str_sublen(str, byte_index);
1098
+ result = rb_funcall(proc, id_call, 2, str, LONG2FIX(char_index));
1099
+ return RTEST(result);
1100
+ }
1101
+ #endif
1102
+
1103
+ #ifdef HAVE_RL_SET_SCREEN_SIZE
1104
+ /*
1105
+ * call-seq:
1106
+ * Readline.set_screen_size(rows, columns) -> self
1107
+ *
1108
+ * Set terminal size to +rows+ and +columns+.
1109
+ *
1110
+ * See GNU Readline's rl_set_screen_size function.
1111
+ *
1112
+ * Raises NotImplementedError if the using readline library does not support.
1113
+ */
1114
+ static VALUE
1115
+ readline_s_set_screen_size(VALUE self, VALUE rows, VALUE columns)
1116
+ {
1117
+ rl_set_screen_size(NUM2INT(rows), NUM2INT(columns));
1118
+ return self;
1119
+ }
1120
+ #else
1121
+ #define readline_s_set_screen_size rb_f_notimplement
1122
+ #endif
1123
+
1124
+ #ifdef HAVE_RL_GET_SCREEN_SIZE
1125
+ /*
1126
+ * call-seq:
1127
+ * Readline.get_screen_size -> [rows, columns]
1128
+ *
1129
+ * Returns the terminal's rows and columns.
1130
+ *
1131
+ * See GNU Readline's rl_get_screen_size function.
1132
+ *
1133
+ * Raises NotImplementedError if the using readline library does not support.
1134
+ */
1135
+ static VALUE
1136
+ readline_s_get_screen_size(VALUE self)
1137
+ {
1138
+ int rows, columns;
1139
+ VALUE res;
1140
+
1141
+ rl_get_screen_size(&rows, &columns);
1142
+ res = rb_ary_new();
1143
+ rb_ary_push(res, INT2NUM(rows));
1144
+ rb_ary_push(res, INT2NUM(columns));
1145
+ return res;
1146
+ }
1147
+ #else
1148
+ #define readline_s_get_screen_size rb_f_notimplement
1149
+ #endif
1150
+
1151
+ #ifdef HAVE_RL_VI_EDITING_MODE
1152
+ int rl_vi_editing_mode(int, int);
1153
+ /*
1154
+ * call-seq:
1155
+ * Readline.vi_editing_mode -> nil
1156
+ *
1157
+ * Specifies VI editing mode. See the manual of GNU Readline for
1158
+ * details of VI editing mode.
1159
+ *
1160
+ * Raises NotImplementedError if the using readline library does not support.
1161
+ */
1162
+ static VALUE
1163
+ readline_s_vi_editing_mode(VALUE self)
1164
+ {
1165
+ rl_vi_editing_mode(1,0);
1166
+ return Qnil;
1167
+ }
1168
+ #else
1169
+ #define readline_s_vi_editing_mode rb_f_notimplement
1170
+ #endif
1171
+
1172
+ #ifdef HAVE_RL_EDITING_MODE
1173
+ /*
1174
+ * call-seq:
1175
+ * Readline.vi_editing_mode? -> bool
1176
+ *
1177
+ * Returns true if vi mode is active. Returns false if not.
1178
+ *
1179
+ * Raises NotImplementedError if the using readline library does not support.
1180
+ */
1181
+ static VALUE
1182
+ readline_s_vi_editing_mode_p(VALUE self)
1183
+ {
1184
+ return rl_editing_mode == 0 ? Qtrue : Qfalse;
1185
+ }
1186
+ #else
1187
+ #define readline_s_vi_editing_mode_p rb_f_notimplement
1188
+ #endif
1189
+
1190
+ #ifdef HAVE_RL_EMACS_EDITING_MODE
1191
+ int rl_emacs_editing_mode(int, int);
1192
+ /*
1193
+ * call-seq:
1194
+ * Readline.emacs_editing_mode -> nil
1195
+ *
1196
+ * Specifies Emacs editing mode. The default is this mode. See the
1197
+ * manual of GNU Readline for details of Emacs editing mode.
1198
+ *
1199
+ * Raises NotImplementedError if the using readline library does not support.
1200
+ */
1201
+ static VALUE
1202
+ readline_s_emacs_editing_mode(VALUE self)
1203
+ {
1204
+ rl_emacs_editing_mode(1,0);
1205
+ return Qnil;
1206
+ }
1207
+ #else
1208
+ #define readline_s_emacs_editing_mode rb_f_notimplement
1209
+ #endif
1210
+
1211
+ #ifdef HAVE_RL_EDITING_MODE
1212
+ /*
1213
+ * call-seq:
1214
+ * Readline.emacs_editing_mode? -> bool
1215
+ *
1216
+ * Returns true if emacs mode is active. Returns false if not.
1217
+ *
1218
+ * Raises NotImplementedError if the using readline library does not support.
1219
+ */
1220
+ static VALUE
1221
+ readline_s_emacs_editing_mode_p(VALUE self)
1222
+ {
1223
+ return rl_editing_mode == 1 ? Qtrue : Qfalse;
1224
+ }
1225
+ #else
1226
+ #define readline_s_emacs_editing_mode_p rb_f_notimplement
1227
+ #endif
1228
+
1229
+ #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
1230
+ /*
1231
+ * call-seq:
1232
+ * Readline.completion_append_character = char
1233
+ *
1234
+ * Specifies a character to be appended on completion.
1235
+ * Nothing will be appended if an empty string ("") or nil is
1236
+ * specified.
1237
+ *
1238
+ * For example:
1239
+ * require "readline"
1240
+ *
1241
+ * Readline.readline("> ", true)
1242
+ * Readline.completion_append_character = " "
1243
+ *
1244
+ * Result:
1245
+ * >
1246
+ * Input "/var/li".
1247
+ *
1248
+ * > /var/li
1249
+ * Press TAB key.
1250
+ *
1251
+ * > /var/lib
1252
+ * Completes "b" and appends " ". So, you can continuously input "/usr".
1253
+ *
1254
+ * > /var/lib /usr
1255
+ *
1256
+ * NOTE: Only one character can be specified. When "string" is
1257
+ * specified, sets only "s" that is the first.
1258
+ *
1259
+ * require "readline"
1260
+ *
1261
+ * Readline.completion_append_character = "string"
1262
+ * p Readline.completion_append_character # => "s"
1263
+ *
1264
+ * Raises NotImplementedError if the using readline library does not support.
1265
+ */
1266
+ static VALUE
1267
+ readline_s_set_completion_append_character(VALUE self, VALUE str)
1268
+ {
1269
+ if (NIL_P(str)) {
1270
+ rl_completion_append_character = '\0';
1271
+ }
1272
+ else {
1273
+ OutputStringValue(str);
1274
+ if (RSTRING_LEN(str) == 0) {
1275
+ rl_completion_append_character = '\0';
1276
+ } else {
1277
+ rl_completion_append_character = RSTRING_PTR(str)[0];
1278
+ }
1279
+ }
1280
+ return self;
1281
+ }
1282
+ #else
1283
+ #define readline_s_set_completion_append_character rb_f_notimplement
1284
+ #endif
1285
+
1286
+ #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
1287
+ /*
1288
+ * call-seq:
1289
+ * Readline.completion_append_character -> char
1290
+ *
1291
+ * Returns a string containing a character to be appended on
1292
+ * completion. The default is a space (" ").
1293
+ *
1294
+ * Raises NotImplementedError if the using readline library does not support.
1295
+ */
1296
+ static VALUE
1297
+ readline_s_get_completion_append_character(VALUE self)
1298
+ {
1299
+ char buf[1];
1300
+
1301
+ if (rl_completion_append_character == '\0')
1302
+ return Qnil;
1303
+
1304
+ buf[0] = (char) rl_completion_append_character;
1305
+ return rb_locale_str_new(buf, 1);
1306
+ }
1307
+ #else
1308
+ #define readline_s_get_completion_append_character rb_f_notimplement
1309
+ #endif
1310
+
1311
+ #ifdef HAVE_RL_COMPLETION_QUOTE_CHARACTER
1312
+ /*
1313
+ * call-seq:
1314
+ * Readline.completion_quote_character -> char
1315
+ *
1316
+ * When called during a completion (e.g. from within your completion_proc),
1317
+ * it will return a string containing the character used to quote the
1318
+ * argument being completed, or nil if the argument is unquoted.
1319
+ *
1320
+ * When called at other times, it will always return nil.
1321
+ *
1322
+ * Note that Readline.completer_quote_characters must be set,
1323
+ * or this method will always return nil.
1324
+ */
1325
+ static VALUE
1326
+ readline_s_get_completion_quote_character(VALUE self)
1327
+ {
1328
+ char buf[1];
1329
+
1330
+ if (rl_completion_quote_character == '\0')
1331
+ return Qnil;
1332
+
1333
+ buf[0] = (char) rl_completion_quote_character;
1334
+ return rb_locale_str_new(buf, 1);
1335
+ }
1336
+ #else
1337
+ #define readline_s_get_completion_quote_character rb_f_notimplement
1338
+ #endif
1339
+
1340
+ #ifdef HAVE_RL_BASIC_WORD_BREAK_CHARACTERS
1341
+ /*
1342
+ * call-seq:
1343
+ * Readline.basic_word_break_characters = string
1344
+ *
1345
+ * Sets the basic list of characters that signal a break between words
1346
+ * for the completer routine. The default is the characters which
1347
+ * break words for completion in Bash: " \t\n\"\\'`@$><=;|&{(".
1348
+ *
1349
+ * Raises NotImplementedError if the using readline library does not support.
1350
+ */
1351
+ static VALUE
1352
+ readline_s_set_basic_word_break_characters(VALUE self, VALUE str)
1353
+ {
1354
+ static char *basic_word_break_characters = NULL;
1355
+
1356
+ OutputStringValue(str);
1357
+ if (basic_word_break_characters == NULL) {
1358
+ basic_word_break_characters =
1359
+ ALLOC_N(char, RSTRING_LEN(str) + 1);
1360
+ }
1361
+ else {
1362
+ REALLOC_N(basic_word_break_characters, char, RSTRING_LEN(str) + 1);
1363
+ }
1364
+ strncpy(basic_word_break_characters,
1365
+ RSTRING_PTR(str), RSTRING_LEN(str));
1366
+ basic_word_break_characters[RSTRING_LEN(str)] = '\0';
1367
+ rl_basic_word_break_characters = basic_word_break_characters;
1368
+ return self;
1369
+ }
1370
+ #else
1371
+ #define readline_s_set_basic_word_break_characters rb_f_notimplement
1372
+ #endif
1373
+
1374
+ #ifdef HAVE_RL_BASIC_WORD_BREAK_CHARACTERS
1375
+ /*
1376
+ * call-seq:
1377
+ * Readline.basic_word_break_characters -> string
1378
+ *
1379
+ * Gets the basic list of characters that signal a break between words
1380
+ * for the completer routine.
1381
+ *
1382
+ * Raises NotImplementedError if the using readline library does not support.
1383
+ */
1384
+ static VALUE
1385
+ readline_s_get_basic_word_break_characters(VALUE self, VALUE str)
1386
+ {
1387
+ if (rl_basic_word_break_characters == NULL)
1388
+ return Qnil;
1389
+ return rb_locale_str_new_cstr(rl_basic_word_break_characters);
1390
+ }
1391
+ #else
1392
+ #define readline_s_get_basic_word_break_characters rb_f_notimplement
1393
+ #endif
1394
+
1395
+ #ifdef HAVE_RL_COMPLETER_WORD_BREAK_CHARACTERS
1396
+ /*
1397
+ * call-seq:
1398
+ * Readline.completer_word_break_characters = string
1399
+ *
1400
+ * Sets the basic list of characters that signal a break between words
1401
+ * for rl_complete_internal(). The default is the value of
1402
+ * Readline.basic_word_break_characters.
1403
+ *
1404
+ * Raises NotImplementedError if the using readline library does not support.
1405
+ */
1406
+ static VALUE
1407
+ readline_s_set_completer_word_break_characters(VALUE self, VALUE str)
1408
+ {
1409
+ static char *completer_word_break_characters = NULL;
1410
+
1411
+ OutputStringValue(str);
1412
+ if (completer_word_break_characters == NULL) {
1413
+ completer_word_break_characters =
1414
+ ALLOC_N(char, RSTRING_LEN(str) + 1);
1415
+ }
1416
+ else {
1417
+ REALLOC_N(completer_word_break_characters, char, RSTRING_LEN(str) + 1);
1418
+ }
1419
+ strncpy(completer_word_break_characters,
1420
+ RSTRING_PTR(str), RSTRING_LEN(str));
1421
+ completer_word_break_characters[RSTRING_LEN(str)] = '\0';
1422
+ rl_completer_word_break_characters = completer_word_break_characters;
1423
+ return self;
1424
+ }
1425
+ #else
1426
+ #define readline_s_set_completer_word_break_characters rb_f_notimplement
1427
+ #endif
1428
+
1429
+ #ifdef HAVE_RL_COMPLETER_WORD_BREAK_CHARACTERS
1430
+ /*
1431
+ * call-seq:
1432
+ * Readline.completer_word_break_characters -> string
1433
+ *
1434
+ * Gets the basic list of characters that signal a break between words
1435
+ * for rl_complete_internal().
1436
+ *
1437
+ * Raises NotImplementedError if the using readline library does not support.
1438
+ */
1439
+ static VALUE
1440
+ readline_s_get_completer_word_break_characters(VALUE self, VALUE str)
1441
+ {
1442
+ if (rl_completer_word_break_characters == NULL)
1443
+ return Qnil;
1444
+ return rb_locale_str_new_cstr(rl_completer_word_break_characters);
1445
+ }
1446
+ #else
1447
+ #define readline_s_get_completer_word_break_characters rb_f_notimplement
1448
+ #endif
1449
+
1450
+ #if defined(HAVE_RL_SPECIAL_PREFIXES)
1451
+ /*
1452
+ * call-seq:
1453
+ * Readline.special_prefixes = string
1454
+ *
1455
+ * Sets the list of characters that are word break characters, but
1456
+ * should be left in text when it is passed to the completion
1457
+ * function. Programs can use this to help determine what kind of
1458
+ * completing to do. For instance, Bash sets this variable to "$@" so
1459
+ * that it can complete shell variables and hostnames.
1460
+ *
1461
+ * See GNU Readline's rl_special_prefixes variable.
1462
+ *
1463
+ * Raises NotImplementedError if the using readline library does not support.
1464
+ */
1465
+ static VALUE
1466
+ readline_s_set_special_prefixes(VALUE self, VALUE str)
1467
+ {
1468
+ if (!NIL_P(str)) {
1469
+ OutputStringValue(str);
1470
+ str = rb_str_dup_frozen(str);
1471
+ rb_obj_hide(str);
1472
+ }
1473
+ rb_ivar_set(mReadline, id_special_prefixes, str);
1474
+ if (NIL_P(str)) {
1475
+ rl_special_prefixes = NULL;
1476
+ }
1477
+ else {
1478
+ rl_special_prefixes = RSTRING_PTR(str);
1479
+ }
1480
+ return self;
1481
+ }
1482
+
1483
+ /*
1484
+ * call-seq:
1485
+ * Readline.special_prefixes -> string
1486
+ *
1487
+ * Gets the list of characters that are word break characters, but
1488
+ * should be left in text when it is passed to the completion
1489
+ * function.
1490
+ *
1491
+ * See GNU Readline's rl_special_prefixes variable.
1492
+ *
1493
+ * Raises NotImplementedError if the using readline library does not support.
1494
+ */
1495
+ static VALUE
1496
+ readline_s_get_special_prefixes(VALUE self)
1497
+ {
1498
+ VALUE str;
1499
+ if (rl_special_prefixes == NULL) return Qnil;
1500
+ str = rb_ivar_get(mReadline, id_special_prefixes);
1501
+ if (!NIL_P(str)) {
1502
+ str = rb_str_dup_frozen(str);
1503
+ rb_obj_reveal(str, rb_cString);
1504
+ }
1505
+ return str;
1506
+ }
1507
+ #else
1508
+ #define readline_s_set_special_prefixes rb_f_notimplement
1509
+ #define readline_s_get_special_prefixes rb_f_notimplement
1510
+ #endif
1511
+
1512
+ #ifdef HAVE_RL_BASIC_QUOTE_CHARACTERS
1513
+ /*
1514
+ * call-seq:
1515
+ * Readline.basic_quote_characters = string
1516
+ *
1517
+ * Sets a list of quote characters which can cause a word break.
1518
+ *
1519
+ * Raises NotImplementedError if the using readline library does not support.
1520
+ */
1521
+ static VALUE
1522
+ readline_s_set_basic_quote_characters(VALUE self, VALUE str)
1523
+ {
1524
+ static char *basic_quote_characters = NULL;
1525
+
1526
+ OutputStringValue(str);
1527
+ if (basic_quote_characters == NULL) {
1528
+ basic_quote_characters =
1529
+ ALLOC_N(char, RSTRING_LEN(str) + 1);
1530
+ }
1531
+ else {
1532
+ REALLOC_N(basic_quote_characters, char, RSTRING_LEN(str) + 1);
1533
+ }
1534
+ strncpy(basic_quote_characters,
1535
+ RSTRING_PTR(str), RSTRING_LEN(str));
1536
+ basic_quote_characters[RSTRING_LEN(str)] = '\0';
1537
+ rl_basic_quote_characters = basic_quote_characters;
1538
+
1539
+ return self;
1540
+ }
1541
+ #else
1542
+ #define readline_s_set_basic_quote_characters rb_f_notimplement
1543
+ #endif
1544
+
1545
+ #ifdef HAVE_RL_BASIC_QUOTE_CHARACTERS
1546
+ /*
1547
+ * call-seq:
1548
+ * Readline.basic_quote_characters -> string
1549
+ *
1550
+ * Gets a list of quote characters which can cause a word break.
1551
+ *
1552
+ * Raises NotImplementedError if the using readline library does not support.
1553
+ */
1554
+ static VALUE
1555
+ readline_s_get_basic_quote_characters(VALUE self, VALUE str)
1556
+ {
1557
+ if (rl_basic_quote_characters == NULL)
1558
+ return Qnil;
1559
+ return rb_locale_str_new_cstr(rl_basic_quote_characters);
1560
+ }
1561
+ #else
1562
+ #define readline_s_get_basic_quote_characters rb_f_notimplement
1563
+ #endif
1564
+
1565
+ #ifdef HAVE_RL_COMPLETER_QUOTE_CHARACTERS
1566
+ /*
1567
+ * call-seq:
1568
+ * Readline.completer_quote_characters = string
1569
+ *
1570
+ * Sets a list of characters which can be used to quote a substring of
1571
+ * the line. Completion occurs on the entire substring, and within
1572
+ * the substring Readline.completer_word_break_characters are treated
1573
+ * as any other character, unless they also appear within this list.
1574
+ *
1575
+ * Raises NotImplementedError if the using readline library does not support.
1576
+ */
1577
+ static VALUE
1578
+ readline_s_set_completer_quote_characters(VALUE self, VALUE str)
1579
+ {
1580
+ static char *completer_quote_characters = NULL;
1581
+
1582
+ OutputStringValue(str);
1583
+ if (completer_quote_characters == NULL) {
1584
+ completer_quote_characters =
1585
+ ALLOC_N(char, RSTRING_LEN(str) + 1);
1586
+ }
1587
+ else {
1588
+ REALLOC_N(completer_quote_characters, char, RSTRING_LEN(str) + 1);
1589
+ }
1590
+ strncpy(completer_quote_characters, RSTRING_PTR(str), RSTRING_LEN(str));
1591
+ completer_quote_characters[RSTRING_LEN(str)] = '\0';
1592
+ rl_completer_quote_characters = completer_quote_characters;
1593
+
1594
+ return self;
1595
+ }
1596
+ #else
1597
+ #define readline_s_set_completer_quote_characters rb_f_notimplement
1598
+ #endif
1599
+
1600
+ #ifdef HAVE_RL_COMPLETER_QUOTE_CHARACTERS
1601
+ /*
1602
+ * call-seq:
1603
+ * Readline.completer_quote_characters -> string
1604
+ *
1605
+ * Gets a list of characters which can be used to quote a substring of
1606
+ * the line.
1607
+ *
1608
+ * Raises NotImplementedError if the using readline library does not support.
1609
+ */
1610
+ static VALUE
1611
+ readline_s_get_completer_quote_characters(VALUE self, VALUE str)
1612
+ {
1613
+ if (rl_completer_quote_characters == NULL)
1614
+ return Qnil;
1615
+ return rb_locale_str_new_cstr(rl_completer_quote_characters);
1616
+ }
1617
+ #else
1618
+ #define readline_s_get_completer_quote_characters rb_f_notimplement
1619
+ #endif
1620
+
1621
+ #ifdef HAVE_RL_FILENAME_QUOTE_CHARACTERS
1622
+ /*
1623
+ * call-seq:
1624
+ * Readline.filename_quote_characters = string
1625
+ *
1626
+ * Sets a list of characters that cause a filename to be quoted by the completer
1627
+ * when they appear in a completed filename. The default is nil.
1628
+ *
1629
+ * Raises NotImplementedError if the using readline library does not support.
1630
+ */
1631
+ static VALUE
1632
+ readline_s_set_filename_quote_characters(VALUE self, VALUE str)
1633
+ {
1634
+ static char *filename_quote_characters = NULL;
1635
+
1636
+ OutputStringValue(str);
1637
+ if (filename_quote_characters == NULL) {
1638
+ filename_quote_characters =
1639
+ ALLOC_N(char, RSTRING_LEN(str) + 1);
1640
+ }
1641
+ else {
1642
+ REALLOC_N(filename_quote_characters, char, RSTRING_LEN(str) + 1);
1643
+ }
1644
+ strncpy(filename_quote_characters, RSTRING_PTR(str), RSTRING_LEN(str));
1645
+ filename_quote_characters[RSTRING_LEN(str)] = '\0';
1646
+ rl_filename_quote_characters = filename_quote_characters;
1647
+
1648
+ return self;
1649
+ }
1650
+ #else
1651
+ #define readline_s_set_filename_quote_characters rb_f_notimplement
1652
+ #endif
1653
+
1654
+ #ifdef HAVE_RL_FILENAME_QUOTE_CHARACTERS
1655
+ /*
1656
+ * call-seq:
1657
+ * Readline.filename_quote_characters -> string
1658
+ *
1659
+ * Gets a list of characters that cause a filename to be quoted by the completer
1660
+ * when they appear in a completed filename.
1661
+ *
1662
+ * Raises NotImplementedError if the using readline library does not support.
1663
+ */
1664
+ static VALUE
1665
+ readline_s_get_filename_quote_characters(VALUE self, VALUE str)
1666
+ {
1667
+ if (rl_filename_quote_characters == NULL)
1668
+ return Qnil;
1669
+ return rb_locale_str_new_cstr(rl_filename_quote_characters);
1670
+ }
1671
+ #else
1672
+ #define readline_s_get_filename_quote_characters rb_f_notimplement
1673
+ #endif
1674
+
1675
+ #ifdef HAVE_RL_REFRESH_LINE
1676
+ int rl_refresh_line(int, int);
1677
+ /*
1678
+ * call-seq:
1679
+ * Readline.refresh_line -> nil
1680
+ *
1681
+ * Clear the current input line.
1682
+ */
1683
+ static VALUE
1684
+ readline_s_refresh_line(VALUE self)
1685
+ {
1686
+ prepare_readline();
1687
+ rl_refresh_line(0, 0);
1688
+ return Qnil;
1689
+ }
1690
+ #else
1691
+ #define readline_s_refresh_line rb_f_notimplement
1692
+ #endif
1693
+
1694
+ static VALUE
1695
+ hist_to_s(VALUE self)
1696
+ {
1697
+ return rb_str_new_cstr("HISTORY");
1698
+ }
1699
+
1700
+ static int
1701
+ history_get_offset_history_base(int offset)
1702
+ {
1703
+ return history_base + offset;
1704
+ }
1705
+
1706
+ static int
1707
+ history_get_offset_0(int offset)
1708
+ {
1709
+ return offset;
1710
+ }
1711
+
1712
+ static VALUE
1713
+ hist_get(VALUE self, VALUE index)
1714
+ {
1715
+ HIST_ENTRY *entry = NULL;
1716
+ int i;
1717
+
1718
+ i = NUM2INT(index);
1719
+ if (i < 0) {
1720
+ i += history_length;
1721
+ }
1722
+ if (i >= 0) {
1723
+ entry = history_get(history_get_offset_func(i));
1724
+ }
1725
+ if (entry == NULL) {
1726
+ rb_raise(rb_eIndexError, "invalid index");
1727
+ }
1728
+ return rb_locale_str_new_cstr(entry->line);
1729
+ }
1730
+
1731
+ #ifdef HAVE_REPLACE_HISTORY_ENTRY
1732
+ static VALUE
1733
+ hist_set(VALUE self, VALUE index, VALUE str)
1734
+ {
1735
+ HIST_ENTRY *entry = NULL;
1736
+ int i;
1737
+
1738
+ i = NUM2INT(index);
1739
+ OutputStringValue(str);
1740
+ if (i < 0) {
1741
+ i += history_length;
1742
+ }
1743
+ if (i >= 0) {
1744
+ entry = replace_history_entry(history_replace_offset_func(i), RSTRING_PTR(str), NULL);
1745
+ }
1746
+ if (entry == NULL) {
1747
+ rb_raise(rb_eIndexError, "invalid index");
1748
+ }
1749
+ return str;
1750
+ }
1751
+ #else
1752
+ #define hist_set rb_f_notimplement
1753
+ #endif
1754
+
1755
+ static VALUE
1756
+ hist_push(VALUE self, VALUE str)
1757
+ {
1758
+ OutputStringValue(str);
1759
+ add_history(RSTRING_PTR(str));
1760
+ return self;
1761
+ }
1762
+
1763
+ static VALUE
1764
+ hist_push_method(int argc, VALUE *argv, VALUE self)
1765
+ {
1766
+ VALUE str;
1767
+
1768
+ while (argc--) {
1769
+ str = *argv++;
1770
+ OutputStringValue(str);
1771
+ add_history(RSTRING_PTR(str));
1772
+ }
1773
+ return self;
1774
+ }
1775
+
1776
+ static VALUE
1777
+ rb_remove_history(int index)
1778
+ {
1779
+ #ifdef HAVE_REMOVE_HISTORY
1780
+ HIST_ENTRY *entry;
1781
+ VALUE val;
1782
+
1783
+ entry = remove_history(index);
1784
+ if (entry) {
1785
+ val = rb_locale_str_new_cstr(entry->line);
1786
+ free((void *) entry->line);
1787
+ free(entry);
1788
+ return val;
1789
+ }
1790
+ return Qnil;
1791
+ #else
1792
+ rb_notimplement();
1793
+
1794
+ UNREACHABLE_RETURN(Qnil);
1795
+ #endif
1796
+ }
1797
+
1798
+ static VALUE
1799
+ hist_pop(VALUE self)
1800
+ {
1801
+ if (history_length > 0) {
1802
+ return rb_remove_history(history_length - 1);
1803
+ } else {
1804
+ return Qnil;
1805
+ }
1806
+ }
1807
+
1808
+ static VALUE
1809
+ hist_shift(VALUE self)
1810
+ {
1811
+ if (history_length > 0) {
1812
+ return rb_remove_history(0);
1813
+ } else {
1814
+ return Qnil;
1815
+ }
1816
+ }
1817
+
1818
+ static VALUE
1819
+ hist_each(VALUE self)
1820
+ {
1821
+ HIST_ENTRY *entry;
1822
+ int i;
1823
+
1824
+ RETURN_ENUMERATOR(self, 0, 0);
1825
+
1826
+ for (i = 0; i < history_length; i++) {
1827
+ entry = history_get(history_get_offset_func(i));
1828
+ if (entry == NULL)
1829
+ break;
1830
+ rb_yield(rb_locale_str_new_cstr(entry->line));
1831
+ }
1832
+ return self;
1833
+ }
1834
+
1835
+ static VALUE
1836
+ hist_length(VALUE self)
1837
+ {
1838
+ return INT2NUM(history_length);
1839
+ }
1840
+
1841
+ static VALUE
1842
+ hist_empty_p(VALUE self)
1843
+ {
1844
+ return history_length == 0 ? Qtrue : Qfalse;
1845
+ }
1846
+
1847
+ static VALUE
1848
+ hist_delete_at(VALUE self, VALUE index)
1849
+ {
1850
+ int i;
1851
+
1852
+ i = NUM2INT(index);
1853
+ if (i < 0)
1854
+ i += history_length;
1855
+ if (i < 0 || i > history_length - 1) {
1856
+ rb_raise(rb_eIndexError, "invalid index");
1857
+ }
1858
+ return rb_remove_history(i);
1859
+ }
1860
+
1861
+ #ifdef HAVE_CLEAR_HISTORY
1862
+ static VALUE
1863
+ hist_clear(VALUE self)
1864
+ {
1865
+ clear_history();
1866
+ return self;
1867
+ }
1868
+ #else
1869
+ #define hist_clear rb_f_notimplement
1870
+ #endif
1871
+
1872
+ static VALUE
1873
+ filename_completion_proc_call(VALUE self, VALUE str)
1874
+ {
1875
+ VALUE result;
1876
+ char **matches;
1877
+ int i;
1878
+
1879
+ matches = rl_completion_matches(StringValuePtr(str),
1880
+ rl_filename_completion_function);
1881
+ if (matches) {
1882
+ result = rb_ary_new();
1883
+ for (i = 0; matches[i]; i++) {
1884
+ rb_ary_push(result, rb_locale_str_new_cstr(matches[i]));
1885
+ free(matches[i]);
1886
+ }
1887
+ free(matches);
1888
+ if (RARRAY_LEN(result) >= 2)
1889
+ rb_ary_shift(result);
1890
+ }
1891
+ else {
1892
+ result = Qnil;
1893
+ }
1894
+ return result;
1895
+ }
1896
+
1897
+ static VALUE
1898
+ username_completion_proc_call(VALUE self, VALUE str)
1899
+ {
1900
+ VALUE result;
1901
+ char **matches;
1902
+ int i;
1903
+
1904
+ matches = rl_completion_matches(StringValuePtr(str),
1905
+ rl_username_completion_function);
1906
+ if (matches) {
1907
+ result = rb_ary_new();
1908
+ for (i = 0; matches[i]; i++) {
1909
+ rb_ary_push(result, rb_locale_str_new_cstr(matches[i]));
1910
+ free(matches[i]);
1911
+ }
1912
+ free(matches);
1913
+ if (RARRAY_LEN(result) >= 2)
1914
+ rb_ary_shift(result);
1915
+ }
1916
+ else {
1917
+ result = Qnil;
1918
+ }
1919
+ return result;
1920
+ }
1921
+
1922
+ #ifdef HAVE_RL_CLEAR_SIGNALS
1923
+ int rl_clear_signals(void);
1924
+ #endif
1925
+
1926
+ #undef rb_intern
1927
+ void
1928
+ Init_readline(void)
1929
+ {
1930
+ VALUE history, fcomp, ucomp, version;
1931
+
1932
+ /* Allow conditional parsing of the ~/.inputrc file. */
1933
+ rl_readline_name = (char *)"Ruby";
1934
+
1935
+ #if defined HAVE_RL_GETC_FUNCTION
1936
+ /* libedit check rl_getc_function only when rl_initialize() is called, */
1937
+ /* and using_history() call rl_initialize(). */
1938
+ /* This assignment should be placed before using_history() */
1939
+ rl_getc_function = readline_getc;
1940
+ #elif defined HAVE_RL_EVENT_HOOK
1941
+ rl_event_hook = readline_event;
1942
+ #endif
1943
+
1944
+ using_history();
1945
+
1946
+ id_call = rb_intern("call");
1947
+ completion_proc = rb_intern(COMPLETION_PROC);
1948
+ completion_case_fold = rb_intern(COMPLETION_CASE_FOLD);
1949
+ #if defined(HAVE_RL_PRE_INPUT_HOOK)
1950
+ id_pre_input_hook = rb_intern("pre_input_hook");
1951
+ #endif
1952
+ #if defined(HAVE_RL_SPECIAL_PREFIXES)
1953
+ id_special_prefixes = rb_intern("special_prefixes");
1954
+ #endif
1955
+ #if defined HAVE_RL_CHAR_IS_QUOTED_P
1956
+ quoting_detection_proc = rb_intern(QUOTING_DETECTION_PROC);
1957
+ #endif
1958
+
1959
+ mReadline = rb_define_module("Readline");
1960
+ rb_define_module_function(mReadline, "readline",
1961
+ readline_readline, -1);
1962
+ rb_define_singleton_method(mReadline, "input=",
1963
+ readline_s_set_input, 1);
1964
+ rb_define_singleton_method(mReadline, "output=",
1965
+ readline_s_set_output, 1);
1966
+ rb_define_singleton_method(mReadline, "completion_proc=",
1967
+ readline_s_set_completion_proc, 1);
1968
+ rb_define_singleton_method(mReadline, "completion_proc",
1969
+ readline_s_get_completion_proc, 0);
1970
+ rb_define_singleton_method(mReadline, "quoting_detection_proc=",
1971
+ readline_s_set_quoting_detection_proc, 1);
1972
+ rb_define_singleton_method(mReadline, "quoting_detection_proc",
1973
+ readline_s_get_quoting_detection_proc, 0);
1974
+ rb_define_singleton_method(mReadline, "completion_case_fold=",
1975
+ readline_s_set_completion_case_fold, 1);
1976
+ rb_define_singleton_method(mReadline, "completion_case_fold",
1977
+ readline_s_get_completion_case_fold, 0);
1978
+ rb_define_singleton_method(mReadline, "line_buffer",
1979
+ readline_s_get_line_buffer, 0);
1980
+ rb_define_singleton_method(mReadline, "point",
1981
+ readline_s_get_point, 0);
1982
+ rb_define_singleton_method(mReadline, "point=",
1983
+ readline_s_set_point, 1);
1984
+ rb_define_singleton_method(mReadline, "set_screen_size",
1985
+ readline_s_set_screen_size, 2);
1986
+ rb_define_singleton_method(mReadline, "get_screen_size",
1987
+ readline_s_get_screen_size, 0);
1988
+ rb_define_singleton_method(mReadline, "vi_editing_mode",
1989
+ readline_s_vi_editing_mode, 0);
1990
+ rb_define_singleton_method(mReadline, "vi_editing_mode?",
1991
+ readline_s_vi_editing_mode_p, 0);
1992
+ rb_define_singleton_method(mReadline, "emacs_editing_mode",
1993
+ readline_s_emacs_editing_mode, 0);
1994
+ rb_define_singleton_method(mReadline, "emacs_editing_mode?",
1995
+ readline_s_emacs_editing_mode_p, 0);
1996
+ rb_define_singleton_method(mReadline, "completion_append_character=",
1997
+ readline_s_set_completion_append_character, 1);
1998
+ rb_define_singleton_method(mReadline, "completion_append_character",
1999
+ readline_s_get_completion_append_character, 0);
2000
+ rb_define_singleton_method(mReadline, "completion_quote_character",
2001
+ readline_s_get_completion_quote_character, 0);
2002
+ rb_define_singleton_method(mReadline, "basic_word_break_characters=",
2003
+ readline_s_set_basic_word_break_characters, 1);
2004
+ rb_define_singleton_method(mReadline, "basic_word_break_characters",
2005
+ readline_s_get_basic_word_break_characters, 0);
2006
+ rb_define_singleton_method(mReadline, "completer_word_break_characters=",
2007
+ readline_s_set_completer_word_break_characters, 1);
2008
+ rb_define_singleton_method(mReadline, "completer_word_break_characters",
2009
+ readline_s_get_completer_word_break_characters, 0);
2010
+ rb_define_singleton_method(mReadline, "basic_quote_characters=",
2011
+ readline_s_set_basic_quote_characters, 1);
2012
+ rb_define_singleton_method(mReadline, "basic_quote_characters",
2013
+ readline_s_get_basic_quote_characters, 0);
2014
+ rb_define_singleton_method(mReadline, "completer_quote_characters=",
2015
+ readline_s_set_completer_quote_characters, 1);
2016
+ rb_define_singleton_method(mReadline, "completer_quote_characters",
2017
+ readline_s_get_completer_quote_characters, 0);
2018
+ rb_define_singleton_method(mReadline, "filename_quote_characters=",
2019
+ readline_s_set_filename_quote_characters, 1);
2020
+ rb_define_singleton_method(mReadline, "filename_quote_characters",
2021
+ readline_s_get_filename_quote_characters, 0);
2022
+ rb_define_singleton_method(mReadline, "refresh_line",
2023
+ readline_s_refresh_line, 0);
2024
+ rb_define_singleton_method(mReadline, "pre_input_hook=",
2025
+ readline_s_set_pre_input_hook, 1);
2026
+ rb_define_singleton_method(mReadline, "pre_input_hook",
2027
+ readline_s_get_pre_input_hook, 0);
2028
+ rb_define_singleton_method(mReadline, "insert_text",
2029
+ readline_s_insert_text, 1);
2030
+ rb_define_singleton_method(mReadline, "delete_text",
2031
+ readline_s_delete_text, -1);
2032
+ rb_define_singleton_method(mReadline, "redisplay",
2033
+ readline_s_redisplay, 0);
2034
+ rb_define_singleton_method(mReadline, "special_prefixes=",
2035
+ readline_s_set_special_prefixes, 1);
2036
+ rb_define_singleton_method(mReadline, "special_prefixes",
2037
+ readline_s_get_special_prefixes, 0);
2038
+
2039
+ #if USE_INSERT_IGNORE_ESCAPE
2040
+ id_orig_prompt = rb_intern("orig_prompt");
2041
+ id_last_prompt = rb_intern("last_prompt");
2042
+ #endif
2043
+
2044
+ history = rb_obj_alloc(rb_cObject);
2045
+ rb_extend_object(history, rb_mEnumerable);
2046
+ rb_define_singleton_method(history,"to_s", hist_to_s, 0);
2047
+ rb_define_singleton_method(history,"[]", hist_get, 1);
2048
+ rb_define_singleton_method(history,"[]=", hist_set, 2);
2049
+ rb_define_singleton_method(history,"<<", hist_push, 1);
2050
+ rb_define_singleton_method(history,"push", hist_push_method, -1);
2051
+ rb_define_singleton_method(history,"pop", hist_pop, 0);
2052
+ rb_define_singleton_method(history,"shift", hist_shift, 0);
2053
+ rb_define_singleton_method(history,"each", hist_each, 0);
2054
+ rb_define_singleton_method(history,"length", hist_length, 0);
2055
+ rb_define_singleton_method(history,"size", hist_length, 0);
2056
+ rb_define_singleton_method(history,"empty?", hist_empty_p, 0);
2057
+ rb_define_singleton_method(history,"delete_at", hist_delete_at, 1);
2058
+ rb_define_singleton_method(history,"clear", hist_clear, 0);
2059
+
2060
+ /*
2061
+ * The history buffer. It extends Enumerable module, so it behaves
2062
+ * just like an array.
2063
+ * For example, gets the fifth content that the user input by
2064
+ * HISTORY[4].
2065
+ */
2066
+ rb_define_const(mReadline, "HISTORY", history);
2067
+
2068
+ fcomp = rb_obj_alloc(rb_cObject);
2069
+ rb_define_singleton_method(fcomp, "call",
2070
+ filename_completion_proc_call, 1);
2071
+ /*
2072
+ * The Object with the call method that is a completion for filename.
2073
+ * This is sets by Readline.completion_proc= method.
2074
+ */
2075
+ rb_define_const(mReadline, "FILENAME_COMPLETION_PROC", fcomp);
2076
+
2077
+ ucomp = rb_obj_alloc(rb_cObject);
2078
+ rb_define_singleton_method(ucomp, "call",
2079
+ username_completion_proc_call, 1);
2080
+ /*
2081
+ * The Object with the call method that is a completion for usernames.
2082
+ * This is sets by Readline.completion_proc= method.
2083
+ */
2084
+ rb_define_const(mReadline, "USERNAME_COMPLETION_PROC", ucomp);
2085
+ history_get_offset_func = history_get_offset_history_base;
2086
+ history_replace_offset_func = history_get_offset_0;
2087
+ #if defined HAVE_RL_LIBRARY_VERSION
2088
+ version = rb_str_new_cstr(rl_library_version);
2089
+ #if defined HAVE_CLEAR_HISTORY || defined HAVE_REMOVE_HISTORY
2090
+ if (strncmp(rl_library_version, EDIT_LINE_LIBRARY_VERSION,
2091
+ strlen(EDIT_LINE_LIBRARY_VERSION)) == 0) {
2092
+ add_history("1");
2093
+ if (history_get(history_get_offset_func(0)) == NULL) {
2094
+ history_get_offset_func = history_get_offset_0;
2095
+ }
2096
+ #ifdef HAVE_REPLACE_HISTORY_ENTRY
2097
+ if (replace_history_entry(0, "a", NULL) == NULL) {
2098
+ history_replace_offset_func = history_get_offset_history_base;
2099
+ }
2100
+ #endif
2101
+ #ifdef HAVE_CLEAR_HISTORY
2102
+ clear_history();
2103
+ #else
2104
+ {
2105
+ HIST_ENTRY *entry = remove_history(0);
2106
+ if (entry) {
2107
+ free((char *)entry->line);
2108
+ free(entry);
2109
+ }
2110
+ }
2111
+ #endif
2112
+ }
2113
+ #endif
2114
+ #else
2115
+ version = rb_str_new_cstr("2.0 or prior version");
2116
+ #endif
2117
+ /* Version string of GNU Readline or libedit. */
2118
+ rb_define_const(mReadline, "VERSION", version);
2119
+
2120
+ rl_attempted_completion_function = readline_attempted_completion_function;
2121
+ #if defined(HAVE_RL_PRE_INPUT_HOOK)
2122
+ rl_pre_input_hook = (rl_hook_func_t *)readline_pre_input_hook;
2123
+ #endif
2124
+ #if defined HAVE_RL_CHAR_IS_QUOTED_P
2125
+ rl_char_is_quoted_p = &readline_char_is_quoted;
2126
+ #endif
2127
+ #ifdef HAVE_RL_CATCH_SIGNALS
2128
+ rl_catch_signals = 0;
2129
+ #endif
2130
+ #ifdef HAVE_RL_CLEAR_SIGNALS
2131
+ rl_clear_signals();
2132
+ #endif
2133
+
2134
+ rb_gc_register_address(&readline_instream);
2135
+ rb_gc_register_address(&readline_outstream);
2136
+ }
2137
+
2138
+ /*
2139
+ * Local variables:
2140
+ * indent-tabs-mode: nil
2141
+ * end:
2142
+ */