readline-ext 0.1.0.pre.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
+ */