rubysl-readline 1.0.1 → 2.0.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7e008b127c5712512bb01363364a142756b91de2
4
- data.tar.gz: 34aaeabe0d55462b770fdb5f5518de05493aacc5
3
+ metadata.gz: 97708858670cdb3d0fe8fb515d0906f48c508ad9
4
+ data.tar.gz: 483bf34ddc9f9e43045d4fab47f7c94a211451cf
5
5
  SHA512:
6
- metadata.gz: 316884b4ef894bad7c11e4cdeff81480d7ff6ff2dff8f0f0f024bd4c581d35e4964cd7f08100648637d070b4330d14094c3c15779b98c9129ba6a0d7fc73f160
7
- data.tar.gz: c4ccf07fd7b132c71274836a1aff04a6f2027da480ebed705d43ba0301518614f6e37df50aa4e87ec7a15aedde81bd876c2830d223af4669ba5fefe13c3355f2
6
+ metadata.gz: 13e8534ceed4587306194e7525c7febd7b213cfce9a0f62480c30ec187c4f1210f1f2a984a8165451d8359dcf03c35a96a6ce5e42fca7d475aebd3e04d117e9b
7
+ data.tar.gz: 919d0c671567d6f442639b6dd031b4cb2af68fc2ad9f2b39e8e4dad46e5c114095c2b105654796a8bf474c884d2df1584879ef0509bdb0cc96d22749441c8ebd
@@ -1,8 +1,9 @@
1
1
  language: ruby
2
2
  before_install:
3
+ - rvm use $RVM --install --binary --fuzzy
3
4
  - gem update --system
4
5
  - gem --version
5
6
  - gem install rubysl-bundler
7
+ env:
8
+ - RVM=rbx-nightly-d21 RUBYLIB=lib
6
9
  script: bundle exec mspec spec
7
- rvm:
8
- - rbx-nightly-18mode
@@ -15,6 +15,14 @@ def have_readline_var(var)
15
15
  return have_var(var, $readline_headers)
16
16
  end
17
17
 
18
+ def have_readline_func(func)
19
+ return have_func(func, $readline_headers)
20
+ end
21
+
22
+ def have_readline_macro(macro)
23
+ return have_macro(macro, $readline_headers)
24
+ end
25
+
18
26
  dir_config('curses')
19
27
  dir_config('ncurses')
20
28
  dir_config('termcap')
@@ -42,9 +50,11 @@ else
42
50
  end
43
51
  end
44
52
 
45
- have_func("rl_filename_completion_function")
46
- have_func("rl_username_completion_function")
47
- have_func("rl_completion_matches")
53
+ have_readline_func("rl_getc_function")
54
+ have_readline_func("rl_filename_completion_function")
55
+ have_readline_func("rl_username_completion_function")
56
+ have_readline_func("rl_completion_matches")
57
+ have_readline_func("rl_refresh_line")
48
58
  have_readline_var("rl_deprep_term_function")
49
59
  have_readline_var("rl_completion_append_character")
50
60
  have_readline_var("rl_basic_word_break_characters")
@@ -54,11 +64,24 @@ have_readline_var("rl_completer_quote_characters")
54
64
  have_readline_var("rl_filename_quote_characters")
55
65
  have_readline_var("rl_attempted_completion_over")
56
66
  have_readline_var("rl_library_version")
57
- have_readline_var("rl_event_hook")
58
- have_func("rl_cleanup_after_signal")
59
- have_func("rl_clear_signals")
60
- have_func("rl_vi_editing_mode")
61
- have_func("rl_emacs_editing_mode")
62
- have_func("replace_history_entry")
63
- have_func("remove_history")
67
+ have_readline_var("rl_editing_mode")
68
+ have_readline_var("rl_line_buffer")
69
+ have_readline_var("rl_point")
70
+ # workaround for native windows.
71
+ /mswin|bccwin|mingw/ !~ RUBY_PLATFORM && have_readline_var("rl_event_hook")
72
+ /mswin|bccwin|mingw/ !~ RUBY_PLATFORM && have_readline_var("rl_catch_sigwinch")
73
+ /mswin|bccwin|mingw/ !~ RUBY_PLATFORM && have_readline_var("rl_catch_signals")
74
+ have_readline_func("rl_cleanup_after_signal")
75
+ have_readline_func("rl_clear_signals")
76
+ have_readline_func("rl_set_screen_size")
77
+ have_readline_func("rl_get_screen_size")
78
+ have_readline_func("rl_vi_editing_mode")
79
+ have_readline_func("rl_emacs_editing_mode")
80
+ have_readline_func("replace_history_entry")
81
+ have_readline_func("remove_history")
82
+ have_readline_func("clear_history")
83
+ have_readline_macro("RL_PROMPT_START_IGNORE")
84
+ have_readline_macro("RL_PROMPT_END_IGNORE")
85
+
86
+ create_header
64
87
  create_makefile("readline/readline")
@@ -1,135 +1,573 @@
1
- /* readline.c -- GNU Readline module
2
- Copyright (C) 1997-2001 Shugo Maeda
1
+ /************************************************
3
2
 
4
- Modified for Rubinius by Evan Phoenix and others
5
- */
3
+ readline.c - GNU Readline module
6
4
 
5
+ $Author: yugui $
6
+ created at: Wed Jan 20 13:59:32 JST 1999
7
+
8
+ Copyright (C) 1997-2008 Shugo Maeda
9
+ Copyright (C) 2008-2009 TAKAO Kouji
10
+
11
+ $Id: readline.c 30569 2011-01-16 12:35:04Z yugui $
12
+
13
+ Contact:
14
+ - TAKAO Kouji <kouji at takao7 dot net> (current maintainer)
15
+
16
+ ************************************************/
17
+
18
+ #ifdef RUBY_EXTCONF_H
19
+ #include RUBY_EXTCONF_H
20
+ #endif
21
+
22
+ #include "ruby/config.h"
7
23
  #include <errno.h>
8
24
  #include <stdio.h>
9
- #include <stdlib.h>
10
- #include <ctype.h>
11
25
  #include <string.h>
26
+ #ifdef HAVE_READLINE_READLINE_H
12
27
  #include <readline/readline.h>
28
+ #endif
29
+ #ifdef HAVE_READLINE_HISTORY_H
13
30
  #include <readline/history.h>
31
+ #endif
32
+ #ifdef HAVE_EDITLINE_READLINE_H
33
+ #include <editline/readline.h>
34
+ #endif
14
35
 
15
- #include "ruby.h"
36
+ #include "ruby/ruby.h"
37
+ #include "ruby/io.h"
16
38
 
39
+ #ifdef HAVE_UNISTD_H
17
40
  #include <unistd.h>
41
+ #endif
18
42
 
19
43
  static VALUE mReadline;
20
44
 
21
- #define TOLOWER(c) (isupper(c) ? tolower(c) : c)
45
+ #define EDIT_LINE_LIBRARY_VERSION "EditLine wrapper"
46
+ #ifndef USE_INSERT_IGNORE_ESCAPE
47
+ # if !defined(HAVE_EDITLINE_READLINE_H) && defined(HAVE_RL_PROMPT_START_IGNORE) && defined(HAVE_RL_PROMPT_END_IGNORE)
48
+ # define USE_INSERT_IGNORE_ESCAPE 1
49
+ # else
50
+ # define USE_INSERT_IGNORE_ESCAPE 0
51
+ # endif
52
+ #endif
22
53
 
23
54
  #define COMPLETION_PROC "completion_proc"
24
55
  #define COMPLETION_CASE_FOLD "completion_case_fold"
25
56
  static ID completion_proc, completion_case_fold;
57
+ #if USE_INSERT_IGNORE_ESCAPE
58
+ static ID id_orig_prompt, id_last_prompt;
59
+ #endif
60
+
61
+ #ifndef HAVE_RL_FILENAME_COMPLETION_FUNCTION
62
+ # define rl_filename_completion_function filename_completion_function
63
+ #endif
64
+ #ifndef HAVE_RL_USERNAME_COMPLETION_FUNCTION
65
+ # define rl_username_completion_function username_completion_function
66
+ #endif
67
+ #ifndef HAVE_RL_COMPLETION_MATCHES
68
+ # define rl_completion_matches completion_matches
69
+ #endif
70
+
71
+ static int (*history_get_offset_func)(int);
26
72
 
27
73
  static char **readline_attempted_completion_function(const char *text,
28
74
  int start, int end);
29
75
 
30
- static VALUE readline_unlocked(void* prompt) {
31
- return (VALUE)readline((char*)prompt);
76
+ #define OutputStringValue(str) do {\
77
+ SafeStringValue(str);\
78
+ str = rb_str_conv_enc(str, rb_enc_get(str), rb_locale_encoding());\
79
+ } while (0)\
80
+
81
+
82
+ /*
83
+ * Document-class: Readline
84
+ *
85
+ * The Readline module provides interface for GNU Readline.
86
+ * This module defines a number of methods to facilitate completion
87
+ * and accesses input history from the Ruby interpreter.
88
+ * This module supported Edit Line(libedit) too.
89
+ * libedit is compatible with GNU Readline.
90
+ *
91
+ * GNU Readline:: http://www.gnu.org/directory/readline.html
92
+ * libedit:: http://www.thrysoee.dk/editline/
93
+ *
94
+ * Reads one inputted line with line edit by Readline.readline method.
95
+ * At this time, the facilitatation completion and the key
96
+ * bind like Emacs can be operated like GNU Readline.
97
+ *
98
+ * require "readline"
99
+ * while buf = Readline.readline("> ", true)
100
+ * p buf
101
+ * end
102
+ *
103
+ * The content that the user input can be recorded to the history.
104
+ * The history can be accessed by Readline::HISTORY constant.
105
+ *
106
+ * require "readline"
107
+ * while buf = Readline.readline("> ", true)
108
+ * p Readline::HISTORY.to_a
109
+ * print("-> ", buf, "\n")
110
+ * end
111
+ *
112
+ * Most of methods raise SecurityError exception if $SAFE is 4.
113
+ *
114
+ * Documented by TAKAO Kouji <kouji at takao7 dot net>.
115
+ */
116
+
117
+ #if defined HAVE_RL_GETC_FUNCTION
118
+ static VALUE readline_instream;
119
+ static ID id_getbyte;
120
+
121
+ static int readline_getc(FILE *);
122
+ static int
123
+ readline_getc(FILE *input)
124
+ {
125
+ rb_io_t *ifp = 0;
126
+ VALUE c;
127
+ GetOpenFile(readline_instream, ifp);
128
+ c = rb_funcall(readline_instream, id_getbyte, 0, 0);
129
+ if (NIL_P(c)) return EOF;
130
+ return NUM2CHR(c);
131
+ }
132
+ #elif defined HAVE_RL_EVENT_HOOK
133
+ #define BUSY_WAIT 0
134
+
135
+ static int readline_event(void);
136
+ static int
137
+ readline_event(void)
138
+ {
139
+ #if BUSY_WAIT
140
+ rb_thread_schedule();
141
+ #else
142
+ fd_set rset;
143
+
144
+ FD_ZERO(&rset);
145
+ FD_SET(fileno(rl_instream), &rset);
146
+ rb_thread_select(fileno(rl_instream) + 1, &rset, NULL, NULL, NULL);
147
+ return 0;
148
+ #endif
32
149
  }
150
+ #endif
33
151
 
152
+ #if USE_INSERT_IGNORE_ESCAPE
34
153
  static VALUE
35
- readline_readline(VALUE self, VALUE tmp, VALUE add_hist)
154
+ insert_ignore_escape(VALUE self, VALUE prompt)
36
155
  {
37
- VALUE result;
156
+ VALUE last_prompt, orig_prompt = rb_attr_get(self, id_orig_prompt);
157
+ int ignoring = 0;
158
+ const char *s0, *s, *e;
159
+ long len;
160
+ static const char ignore_code[2] = {RL_PROMPT_START_IGNORE, RL_PROMPT_END_IGNORE};
161
+
162
+ prompt = rb_str_new_shared(prompt);
163
+ last_prompt = rb_attr_get(self, id_last_prompt);
164
+ if (orig_prompt == prompt) return last_prompt;
165
+ len = RSTRING_LEN(prompt);
166
+ if (NIL_P(last_prompt)) {
167
+ last_prompt = rb_str_tmp_new(len);
168
+ }
169
+
170
+ s = s0 = RSTRING_PTR(prompt);
171
+ e = s0 + len;
172
+ rb_str_set_len(last_prompt, 0);
173
+ while (s < e && *s) {
174
+ switch (*s) {
175
+ case RL_PROMPT_START_IGNORE:
176
+ ignoring = -1;
177
+ rb_str_cat(last_prompt, s0, ++s - s0);
178
+ s0 = s;
179
+ break;
180
+ case RL_PROMPT_END_IGNORE:
181
+ ignoring = 0;
182
+ rb_str_cat(last_prompt, s0, ++s - s0);
183
+ s0 = s;
184
+ break;
185
+ case '\033':
186
+ if (++s < e && *s == '[') {
187
+ rb_str_cat(last_prompt, s0, s - s0 - 1);
188
+ s0 = s - 1;
189
+ while (++s < e && *s) {
190
+ if (ISALPHA(*s)) {
191
+ if (!ignoring) {
192
+ ignoring = 1;
193
+ rb_str_cat(last_prompt, ignore_code+0, 1);
194
+ }
195
+ rb_str_cat(last_prompt, s0, ++s - s0);
196
+ s0 = s;
197
+ break;
198
+ }
199
+ else if (!('0' <= *s && *s <= '9' || *s == ';')) {
200
+ break;
201
+ }
202
+ }
203
+ }
204
+ break;
205
+ default:
206
+ if (ignoring > 0) {
207
+ ignoring = 0;
208
+ rb_str_cat(last_prompt, ignore_code+1, 1);
209
+ }
210
+ s++;
211
+ break;
212
+ }
213
+ }
214
+ if (ignoring > 0) {
215
+ ignoring = 0;
216
+ rb_str_cat(last_prompt, ignore_code+1, 1);
217
+ }
218
+ rb_str_cat(last_prompt, s0, s - s0);
219
+
220
+ rb_ivar_set(self, id_orig_prompt, prompt);
221
+ rb_ivar_set(self, id_last_prompt, last_prompt);
222
+
223
+ return last_prompt;
224
+ }
225
+ #endif
226
+
227
+ static VALUE
228
+ readline_get(VALUE prompt)
229
+ {
230
+ return (VALUE)readline((char *)prompt);
231
+ }
232
+
233
+ /*
234
+ * call-seq:
235
+ * Readline.readline(prompt = "", add_hist = false) -> string or nil
236
+ *
237
+ * Shows the +prompt+ and reads the inputted line with line editing.
238
+ * The inputted line is added to the history if +add_hist+ is true.
239
+ *
240
+ * Returns nil when the inputted line is empty and user inputs EOF
241
+ * (Presses ^D on UNIX).
242
+ *
243
+ * Raises IOError exception if below conditions are satisfied.
244
+ * 1. stdin is not tty.
245
+ * 2. stdin was closed. (errno is EBADF after called isatty(2).)
246
+ *
247
+ * This method supports thread. Switchs the thread context when waits
248
+ * inputting line.
249
+ *
250
+ * Supports line edit when inputs line. Provides VI and Emacs editing mode.
251
+ * Default is Emacs editing mode.
252
+ *
253
+ * NOTE: Terminates ruby interpreter and does not return the terminal
254
+ * status after user pressed '^C' when wait inputting line.
255
+ * Give 3 examples that avoid it.
256
+ *
257
+ * * Catches the Interrupt exception by pressed ^C after returns
258
+ * terminal status:
259
+ *
260
+ * require "readline"
261
+ *
262
+ * stty_save = `stty -g`.chomp
263
+ * begin
264
+ * while buf = Readline.readline
265
+ * p buf
266
+ * end
267
+ * rescue Interrupt
268
+ * system("stty", stty_save)
269
+ * exit
270
+ * end
271
+ * end
272
+ * end
273
+ *
274
+ * * Catches the INT signal by pressed ^C after returns terminal
275
+ * status:
276
+ *
277
+ * require "readline"
278
+ *
279
+ * stty_save = `stty -g`.chomp
280
+ * trap("INT") { system "stty", stty_save; exit }
281
+ *
282
+ * while buf = Readline.readline
283
+ * p buf
284
+ * end
285
+ *
286
+ * * Ignores pressing ^C:
287
+ *
288
+ * require "readline"
289
+ *
290
+ * trap("INT", "SIG_IGN")
291
+ *
292
+ * while buf = Readline.readline
293
+ * p buf
294
+ * end
295
+ *
296
+ * Can make as follows with Readline::HISTORY constant.
297
+ * It does not record to the history if the inputted line is empty or
298
+ * the same it as last one.
299
+ *
300
+ * require "readline"
301
+ *
302
+ * while buf = Readline.readline("> ", true)
303
+ * # p Readline::HISTORY.to_a
304
+ * Readline::HISTORY.pop if /^\s*$/ =~ buf
305
+ *
306
+ * begin
307
+ * if Readline::HISTORY[Readline::HISTORY.length-2] == buf
308
+ * Readline::HISTORY.pop
309
+ * end
310
+ * rescue IndexError
311
+ * end
312
+ *
313
+ * # p Readline::HISTORY.to_a
314
+ * print "-> ", buf, "\n"
315
+ * end
316
+ *
317
+ * Raises SecurityError exception if $SAFE is 4.
318
+ */
319
+ static VALUE
320
+ readline_readline(int argc, VALUE *argv, VALUE self)
321
+ {
322
+ VALUE tmp, add_hist, result;
38
323
  char *prompt = NULL;
39
324
  char *buff;
325
+ int status;
40
326
 
41
327
  rb_secure(4);
42
- SafeStringValue(tmp);
43
- prompt = RSTRING_PTR(tmp);
44
-
45
- if(!isatty(0) && errno == EBADF) rb_raise(rb_eIOError, "stdin closed");
328
+ if (rb_scan_args(argc, argv, "02", &tmp, &add_hist) > 0) {
329
+ OutputStringValue(tmp);
330
+ #if USE_INSERT_IGNORE_ESCAPE
331
+ tmp = insert_ignore_escape(self, tmp);
332
+ rb_str_locktmp(tmp);
333
+ #endif
334
+ prompt = RSTRING_PTR(tmp);
335
+ }
46
336
 
47
- buff = (char*)rb_thread_blocking_region(readline_unlocked, prompt, 0, 0);
337
+ if (!isatty(fileno(rl_instream)) && errno == EBADF) rb_raise(rb_eIOError, "closed stdin");
48
338
 
49
- if(RTEST(add_hist) && buff) {
50
- add_history(buff);
339
+ #ifdef _WIN32
340
+ rl_prep_terminal(1);
341
+ #endif
342
+ buff = (char*)rb_protect(readline_get, (VALUE)prompt, &status);
343
+ #if USE_INSERT_IGNORE_ESCAPE
344
+ if (prompt) {
345
+ rb_str_unlocktmp(tmp);
51
346
  }
52
-
53
- if(buff) {
54
- result = rb_tainted_str_new2(buff);
55
- free(buff);
56
- } else {
57
- result = Qnil;
347
+ #endif
348
+ if (status) {
349
+ #if defined HAVE_RL_CLEANUP_AFTER_SIGNAL
350
+ /* restore terminal mode and signal handler*/
351
+ rl_free_line_state();
352
+ rl_cleanup_after_signal();
353
+ #elif defined HAVE_RL_DEPREP_TERM_FUNCTION
354
+ /* restore terminal mode */
355
+ if (rl_deprep_term_function != NULL) /* NULL in libedit. [ruby-dev:29116] */
356
+ (*rl_deprep_term_function)();
357
+ else
358
+ #else
359
+ rl_deprep_terminal();
360
+ #endif
361
+ rb_jump_tag(status);
58
362
  }
59
363
 
364
+ if (RTEST(add_hist) && buff) {
365
+ add_history(buff);
366
+ }
367
+ if (buff) {
368
+ result = rb_locale_str_new_cstr(buff);
369
+ }
370
+ else
371
+ result = Qnil;
372
+ if (buff) free(buff);
60
373
  return result;
61
374
  }
62
375
 
376
+ /*
377
+ * call-seq:
378
+ * Readline.input = input
379
+ *
380
+ * Specifies a File object +input+ that is input stream for
381
+ * Readline.readline method.
382
+ *
383
+ * Raises SecurityError exception if $SAFE is 4.
384
+ */
385
+ static VALUE
386
+ readline_s_set_input(VALUE self, VALUE input)
387
+ {
388
+ rb_io_t *ifp;
389
+
390
+ rb_secure(4);
391
+ Check_Type(input, T_FILE);
392
+ GetOpenFile(input, ifp);
393
+ rl_instream = rb_io_stdio_file(ifp);
394
+ #ifdef HAVE_RL_GETC_FUNCTION
395
+ readline_instream = input;
396
+ #endif
397
+ return input;
398
+ }
399
+
400
+ /*
401
+ * call-seq:
402
+ * Readline.output = output
403
+ *
404
+ * Specifies a File object +output+ that is output stream for
405
+ * Readline.readline method.
406
+ *
407
+ * Raises SecurityError exception if $SAFE is 4.
408
+ */
409
+ static VALUE
410
+ readline_s_set_output(VALUE self, VALUE output)
411
+ {
412
+ rb_io_t *ofp;
413
+
414
+ rb_secure(4);
415
+ Check_Type(output, T_FILE);
416
+ GetOpenFile(output, ofp);
417
+ rl_outstream = rb_io_stdio_file(ofp);
418
+ return output;
419
+ }
420
+
421
+ /*
422
+ * call-seq:
423
+ * Readline.completion_proc = proc
424
+ *
425
+ * Specifies a Proc object +proc+ to determine completion behavior. It
426
+ * should take input-string, and return an array of completion
427
+ * candidates.
428
+ *
429
+ * Set default if +proc+ is nil.
430
+ *
431
+ * Raises ArgumentError exception if +proc+ does not respond to call method.
432
+ *
433
+ * Raises SecurityError exception if $SAFE is 4.
434
+ */
63
435
  static VALUE
64
- readline_s_set_completion_proc(self, proc)
65
- VALUE self;
66
- VALUE proc;
436
+ readline_s_set_completion_proc(VALUE self, VALUE proc)
67
437
  {
68
438
  rb_secure(4);
69
- if (!rb_respond_to(proc, rb_intern("call")))
70
- rb_raise(rb_eArgError, "argument must respond to `call'");
439
+ if (!NIL_P(proc) && !rb_respond_to(proc, rb_intern("call")))
440
+ rb_raise(rb_eArgError, "argument must respond to `call'");
71
441
  return rb_ivar_set(mReadline, completion_proc, proc);
72
442
  }
73
443
 
444
+ /*
445
+ * call-seq:
446
+ * Readline.completion_proc -> proc
447
+ *
448
+ * Returns the completion Proc object.
449
+ *
450
+ * Raises SecurityError exception if $SAFE is 4.
451
+ */
74
452
  static VALUE
75
- readline_s_get_completion_proc(self)
76
- VALUE self;
453
+ readline_s_get_completion_proc(VALUE self)
77
454
  {
78
455
  rb_secure(4);
79
456
  return rb_attr_get(mReadline, completion_proc);
80
457
  }
81
458
 
459
+ /*
460
+ * call-seq:
461
+ * Readline.completion_case_fold = bool
462
+ *
463
+ * Sets whether or not to ignore case on completion.
464
+ *
465
+ * Raises SecurityError exception if $SAFE is 4.
466
+ */
82
467
  static VALUE
83
- readline_s_set_completion_case_fold(self, val)
84
- VALUE self;
85
- VALUE val;
468
+ readline_s_set_completion_case_fold(VALUE self, VALUE val)
86
469
  {
87
470
  rb_secure(4);
88
471
  return rb_ivar_set(mReadline, completion_case_fold, val);
89
472
  }
90
473
 
474
+ /*
475
+ * call-seq:
476
+ * Readline.completion_case_fold -> bool
477
+ *
478
+ * Returns true if completion ignores case. If no, returns false.
479
+ *
480
+ * NOTE: Returns the same object that is specified by
481
+ * Readline.completion_case_fold= method.
482
+ *
483
+ * require "readline"
484
+ *
485
+ * Readline.completion_case_fold = "This is a String."
486
+ * p Readline.completion_case_fold # => "This is a String."
487
+ *
488
+ * Raises SecurityError exception if $SAFE is 4.
489
+ */
91
490
  static VALUE
92
- readline_s_get_completion_case_fold(self)
93
- VALUE self;
491
+ readline_s_get_completion_case_fold(VALUE self)
94
492
  {
95
493
  rb_secure(4);
96
494
  return rb_attr_get(mReadline, completion_case_fold);
97
495
  }
98
496
 
99
- struct complete_args {
100
- const char* text;
101
- int start;
102
- int end;
103
- };
497
+ #ifdef HAVE_RL_LINE_BUFFER
498
+ /*
499
+ * call-seq:
500
+ * Readline.line_buffer -> string
501
+ *
502
+ * Returns the full line that is being edited. This is useful from
503
+ * within the complete_proc for determining the context of the
504
+ * completion request.
505
+ *
506
+ * The length of +Readline.line_buffer+ and GNU Readline's rl_end are
507
+ * same.
508
+ */
509
+ static VALUE
510
+ readline_s_get_line_buffer(VALUE self)
511
+ {
512
+ rb_secure(4);
513
+ if (rl_line_buffer == NULL)
514
+ return Qnil;
515
+ return rb_locale_str_new_cstr(rl_line_buffer);
516
+ }
517
+ #else
518
+ #define readline_s_get_line_buffer rb_f_notimplement
519
+ #endif
104
520
 
105
- static void*
106
- readline_complete_locked(struct complete_args* args) {
107
- const char *text = args->text;
108
- int start = args->start;
109
- int end = args->end;
521
+ #ifdef HAVE_RL_POINT
522
+ /*
523
+ * call-seq:
524
+ * Readline.point -> int
525
+ *
526
+ * Returns the index of the current cursor position in
527
+ * +Readline.line_buffer+.
528
+ *
529
+ * The index in +Readline.line_buffer+ which matches the start of
530
+ * input-string passed to completion_proc is computed by subtracting
531
+ * the length of input-string from +Readline.point+.
532
+ *
533
+ * start = (the length of input-string) - Readline.point
534
+ */
535
+ static VALUE
536
+ readline_s_get_point(VALUE self)
537
+ {
538
+ rb_secure(4);
539
+ return INT2NUM(rl_point);
540
+ }
541
+ #else
542
+ #define readline_s_get_point rb_f_notimplement
543
+ #endif
110
544
 
545
+ static char **
546
+ readline_attempted_completion_function(const char *text, int start, int end)
547
+ {
111
548
  VALUE proc, ary, temp;
112
549
  char **result;
113
550
  int case_fold;
114
- int i, matches;
551
+ long i, matches;
115
552
 
116
553
  proc = rb_attr_get(mReadline, completion_proc);
117
554
  if (NIL_P(proc))
118
- return NULL;
555
+ return NULL;
119
556
  #ifdef HAVE_RL_ATTEMPTED_COMPLETION_OVER
120
557
  rl_attempted_completion_over = 1;
121
558
  #endif
122
559
  case_fold = RTEST(rb_attr_get(mReadline, completion_case_fold));
123
- ary = rb_funcall(proc, rb_intern("call"), 1, rb_tainted_str_new2(text));
124
- ary = rb_Array(ary);
125
-
126
- matches = rb_ary_size(ary);
127
- if (matches == 0) return NULL;
560
+ ary = rb_funcall(proc, rb_intern("call"), 1, rb_locale_str_new_cstr(text));
561
+ if (TYPE(ary) != T_ARRAY)
562
+ ary = rb_Array(ary);
563
+ matches = RARRAY_LEN(ary);
564
+ if (matches == 0)
565
+ return NULL;
128
566
  result = ALLOC_N(char *, matches + 2);
129
567
  for (i = 0; i < matches; i++) {
130
- temp = rb_obj_as_string(rb_ary_entry(ary, i));
131
- result[i + 1] = ALLOC_N(char, RSTRING_LEN(temp) + 1);
132
- strcpy(result[i + 1], RSTRING_PTR(temp));
568
+ temp = rb_obj_as_string(rb_ary_entry(ary, i));
569
+ result[i + 1] = ALLOC_N(char, RSTRING_LEN(temp) + 1);
570
+ strcpy(result[i + 1], RSTRING_PTR(temp));
133
571
  }
134
572
  result[matches + 1] = NULL;
135
573
 
@@ -137,92 +575,293 @@ readline_complete_locked(struct complete_args* args) {
137
575
  result[0] = strdup(result[1]);
138
576
  }
139
577
  else {
140
- register int i = 1;
141
- int low = 100000;
578
+ register int i = 1;
579
+ int low = 100000;
580
+
581
+ while (i < matches) {
582
+ register int c1, c2, si;
583
+
584
+ if (case_fold) {
585
+ for (si = 0;
586
+ (c1 = TOLOWER(result[i][si])) &&
587
+ (c2 = TOLOWER(result[i + 1][si]));
588
+ si++)
589
+ if (c1 != c2) break;
590
+ } else {
591
+ for (si = 0;
592
+ (c1 = result[i][si]) &&
593
+ (c2 = result[i + 1][si]);
594
+ si++)
595
+ if (c1 != c2) break;
596
+ }
597
+
598
+ if (low > si) low = si;
599
+ i++;
600
+ }
601
+ result[0] = ALLOC_N(char, low + 1);
602
+ strncpy(result[0], result[1], low);
603
+ result[0][low] = '\0';
604
+ }
605
+
606
+ return result;
607
+ }
608
+
609
+ #ifdef HAVE_RL_SET_SCREEN_SIZE
610
+ /*
611
+ * call-seq:
612
+ * Readline.set_screen_size(rows, columns) -> self
613
+ *
614
+ * Set terminal size to +rows+ and +columns+.
615
+ *
616
+ * See GNU Readline's rl_set_screen_size function.
617
+ *
618
+ * Raises NotImplementedError if the using readline library does not support.
619
+ *
620
+ * Raises SecurityError exception if $SAFE is 4.
621
+ */
622
+ static VALUE
623
+ readline_s_set_screen_size(VALUE self, VALUE rows, VALUE columns)
624
+ {
625
+ rb_secure(4);
626
+ rl_set_screen_size(NUM2INT(rows), NUM2INT(columns));
627
+ return self;
628
+ }
629
+ #else
630
+ #define readline_s_set_screen_size rb_f_notimplement
631
+ #endif
142
632
 
143
- while (i < matches) {
144
- register int c1, c2, si;
633
+ #ifdef HAVE_RL_GET_SCREEN_SIZE
634
+ /*
635
+ * call-seq:
636
+ * Readline.get_screen_size -> [rows, columns]
637
+ *
638
+ * Returns the terminal's rows and columns.
639
+ *
640
+ * See GNU Readline's rl_get_screen_size function.
641
+ *
642
+ * Raises NotImplementedError if the using readline library does not support.
643
+ *
644
+ * Raises SecurityError exception if $SAFE is 4.
645
+ */
646
+ static VALUE
647
+ readline_s_get_screen_size(VALUE self)
648
+ {
649
+ int rows, columns;
650
+ VALUE res;
145
651
 
146
- if (case_fold) {
147
- for (si = 0;
148
- (c1 = TOLOWER(result[i][si])) &&
149
- (c2 = TOLOWER(result[i + 1][si]));
150
- si++)
151
- if (c1 != c2) break;
152
- } else {
153
- for (si = 0;
154
- (c1 = result[i][si]) &&
155
- (c2 = result[i + 1][si]);
156
- si++)
157
- if (c1 != c2) break;
158
- }
652
+ rb_secure(4);
653
+ rl_get_screen_size(&rows, &columns);
654
+ res = rb_ary_new();
655
+ rb_ary_push(res, INT2NUM(rows));
656
+ rb_ary_push(res, INT2NUM(columns));
657
+ return res;
658
+ }
659
+ #else
660
+ #define readline_s_get_screen_size rb_f_notimplement
661
+ #endif
159
662
 
160
- if (low > si) low = si;
161
- i++;
162
- }
163
- result[0] = ALLOC_N(char, low + 1);
164
- strncpy(result[0], result[1], low);
165
- result[0][low] = '\0';
166
- }
663
+ #ifdef HAVE_RL_VI_EDITING_MODE
664
+ /*
665
+ * call-seq:
666
+ * Readline.vi_editing_mode -> nil
667
+ *
668
+ * Specifies VI editing mode. See the manual of GNU Readline for
669
+ * details of VI editing mode.
670
+ *
671
+ * Raises NotImplementedError if the using readline library does not support.
672
+ *
673
+ * Raises SecurityError exception if $SAFE is 4.
674
+ */
675
+ static VALUE
676
+ readline_s_vi_editing_mode(VALUE self)
677
+ {
678
+ rb_secure(4);
679
+ rl_vi_editing_mode(1,0);
680
+ return Qnil;
681
+ }
682
+ #else
683
+ #define readline_s_vi_editing_mode rb_f_notimplement
684
+ #endif
167
685
 
168
- return (void*)result;
686
+ #ifdef HAVE_RL_EDITING_MODE
687
+ /*
688
+ * call-seq:
689
+ * Readline.vi_editing_mode? -> bool
690
+ *
691
+ * Returns true if vi mode is active. Returns false if not.
692
+ *
693
+ * Raises NotImplementedError if the using readline library does not support.
694
+ *
695
+ * Raises SecurityError exception if $SAFE is 4.
696
+ */
697
+ static VALUE
698
+ readline_s_vi_editing_mode_p(VALUE self)
699
+ {
700
+ rb_secure(4);
701
+ return rl_editing_mode == 0 ? Qtrue : Qfalse;
169
702
  }
703
+ #else
704
+ #define readline_s_vi_editing_mode_p rb_f_notimplement
705
+ #endif
170
706
 
171
- static char **
172
- readline_attempted_completion_function(text, start, end)
173
- const char *text;
174
- int start;
175
- int end;
707
+ #ifdef HAVE_RL_EMACS_EDITING_MODE
708
+ /*
709
+ * call-seq:
710
+ * Readline.emacs_editing_mode -> nil
711
+ *
712
+ * Specifies Emacs editing mode. The default is this mode. See the
713
+ * manual of GNU Readline for details of Emacs editing mode.
714
+ *
715
+ * Raises NotImplementedError if the using readline library does not support.
716
+ *
717
+ * Raises SecurityError exception if $SAFE is 4.
718
+ */
719
+ static VALUE
720
+ readline_s_emacs_editing_mode(VALUE self)
721
+ {
722
+ rb_secure(4);
723
+ rl_emacs_editing_mode(1,0);
724
+ return Qnil;
725
+ }
726
+ #else
727
+ #define readline_s_emacs_editing_mode rb_f_notimplement
728
+ #endif
729
+
730
+ #ifdef HAVE_RL_EDITING_MODE
731
+ /*
732
+ * call-seq:
733
+ * Readline.emacs_editing_mode? -> bool
734
+ *
735
+ * Returns true if emacs mode is active. Returns false if not.
736
+ *
737
+ * Raises NotImplementedError if the using readline library does not support.
738
+ *
739
+ * Raises SecurityError exception if $SAFE is 4.
740
+ */
741
+ static VALUE
742
+ readline_s_emacs_editing_mode_p(VALUE self)
176
743
  {
177
- struct complete_args args = {text, start, end};
178
- void* ret = rb_thread_call_with_gvl((rb_thread_call_func)readline_complete_locked, &args);
179
- return (char**)ret;
744
+ rb_secure(4);
745
+ return rl_editing_mode == 1 ? Qtrue : Qfalse;
180
746
  }
747
+ #else
748
+ #define readline_s_emacs_editing_mode_p rb_f_notimplement
749
+ #endif
181
750
 
751
+ #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
752
+ /*
753
+ * call-seq:
754
+ * Readline.completion_append_character = char
755
+ *
756
+ * Specifies a character to be appended on completion.
757
+ * Nothing will be appended if an empty string ("") or nil is
758
+ * specified.
759
+ *
760
+ * For example:
761
+ * require "readline"
762
+ *
763
+ * Readline.readline("> ", true)
764
+ * Readline.completion_append_character = " "
765
+ *
766
+ * Result:
767
+ * >
768
+ * Input "/var/li".
769
+ *
770
+ * > /var/li
771
+ * Press TAB key.
772
+ *
773
+ * > /var/lib
774
+ * Completes "b" and appends " ". So, you can continuously input "/usr".
775
+ *
776
+ * > /var/lib /usr
777
+ *
778
+ * NOTE: Only one character can be specified. When "string" is
779
+ * specified, sets only "s" that is the first.
780
+ *
781
+ * require "readline"
782
+ *
783
+ * Readline.completion_append_character = "string"
784
+ * p Readline.completion_append_character # => "s"
785
+ *
786
+ * Raises NotImplementedError if the using readline library does not support.
787
+ *
788
+ * Raises SecurityError exception if $SAFE is 4.
789
+ */
182
790
  static VALUE
183
- readline_s_set_completion_append_character(self, str)
184
- VALUE self, str;
791
+ readline_s_set_completion_append_character(VALUE self, VALUE str)
185
792
  {
186
793
  rb_secure(4);
187
794
  if (NIL_P(str)) {
188
- rl_completion_append_character = '\0';
795
+ rl_completion_append_character = '\0';
189
796
  }
190
797
  else {
191
- SafeStringValue(str);
192
- if (RSTRING_LEN(str) == 0) {
193
- rl_completion_append_character = '\0';
194
- } else {
195
- rl_completion_append_character = RSTRING_PTR(str)[0];
196
- }
798
+ OutputStringValue(str);
799
+ if (RSTRING_LEN(str) == 0) {
800
+ rl_completion_append_character = '\0';
801
+ } else {
802
+ rl_completion_append_character = RSTRING_PTR(str)[0];
803
+ }
197
804
  }
198
805
  return self;
199
806
  }
807
+ #else
808
+ #define readline_s_set_completion_append_character rb_f_notimplement
809
+ #endif
200
810
 
811
+ #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
812
+ /*
813
+ * call-seq:
814
+ * Readline.completion_append_character -> char
815
+ *
816
+ * Returns a string containing a character to be appended on
817
+ * completion. The default is a space (" ").
818
+ *
819
+ * Raises NotImplementedError if the using readline library does not support.
820
+ *
821
+ * Raises SecurityError exception if $SAFE is 4.
822
+ */
201
823
  static VALUE
202
- readline_s_get_completion_append_character(self)
203
- VALUE self;
824
+ readline_s_get_completion_append_character(VALUE self)
204
825
  {
826
+ char buf[1];
827
+
205
828
  rb_secure(4);
206
829
  if (rl_completion_append_character == '\0')
207
- return Qnil;
830
+ return Qnil;
208
831
 
209
- return rb_str_new((char*)&rl_completion_append_character, 1);
832
+ buf[0] = (char) rl_completion_append_character;
833
+ return rb_locale_str_new(buf, 1);
210
834
  }
835
+ #else
836
+ #define readline_s_get_completion_append_character rb_f_notimplement
837
+ #endif
211
838
 
839
+ #ifdef HAVE_RL_BASIC_WORD_BREAK_CHARACTERS
840
+ /*
841
+ * call-seq:
842
+ * Readline.basic_word_break_characters = string
843
+ *
844
+ * Sets the basic list of characters that signal a break between words
845
+ * for the completer routine. The default is the characters which
846
+ * break words for completion in Bash: "\t\n\"\\'`@$><=;|&{(".
847
+ *
848
+ * Raises NotImplementedError if the using readline library does not support.
849
+ *
850
+ * Raises SecurityError exception if $SAFE is 4.
851
+ */
212
852
  static VALUE
213
- readline_s_set_basic_word_break_characters(self, str)
214
- VALUE self, str;
853
+ readline_s_set_basic_word_break_characters(VALUE self, VALUE str)
215
854
  {
216
855
  static char *basic_word_break_characters = NULL;
217
856
 
218
857
  rb_secure(4);
219
- SafeStringValue(str);
858
+ OutputStringValue(str);
220
859
  if (basic_word_break_characters == NULL) {
221
- basic_word_break_characters =
222
- ALLOC_N(char, RSTRING_LEN(str) + 1);
860
+ basic_word_break_characters =
861
+ ALLOC_N(char, RSTRING_LEN(str) + 1);
223
862
  }
224
863
  else {
225
- REALLOC_N(basic_word_break_characters, char, RSTRING_LEN(str) + 1);
864
+ REALLOC_N(basic_word_break_characters, char, RSTRING_LEN(str) + 1);
226
865
  }
227
866
  strncpy(basic_word_break_characters,
228
867
  RSTRING_PTR(str), RSTRING_LEN(str));
@@ -230,31 +869,60 @@ readline_s_set_basic_word_break_characters(self, str)
230
869
  rl_basic_word_break_characters = basic_word_break_characters;
231
870
  return self;
232
871
  }
872
+ #else
873
+ #define readline_s_set_basic_word_break_characters rb_f_notimplement
874
+ #endif
233
875
 
876
+ #ifdef HAVE_RL_BASIC_WORD_BREAK_CHARACTERS
877
+ /*
878
+ * call-seq:
879
+ * Readline.basic_word_break_characters -> string
880
+ *
881
+ * Gets the basic list of characters that signal a break between words
882
+ * for the completer routine.
883
+ *
884
+ * Raises NotImplementedError if the using readline library does not support.
885
+ *
886
+ * Raises SecurityError exception if $SAFE is 4.
887
+ */
234
888
  static VALUE
235
- readline_s_get_basic_word_break_characters(self, str)
236
- VALUE self, str;
889
+ readline_s_get_basic_word_break_characters(VALUE self, VALUE str)
237
890
  {
238
891
  rb_secure(4);
239
892
  if (rl_basic_word_break_characters == NULL)
240
- return Qnil;
241
- return rb_tainted_str_new2(rl_basic_word_break_characters);
893
+ return Qnil;
894
+ return rb_locale_str_new_cstr(rl_basic_word_break_characters);
242
895
  }
896
+ #else
897
+ #define readline_s_get_basic_word_break_characters rb_f_notimplement
898
+ #endif
243
899
 
900
+ #ifdef HAVE_RL_COMPLETER_WORD_BREAK_CHARACTERS
901
+ /*
902
+ * call-seq:
903
+ * Readline.completer_word_break_characters = string
904
+ *
905
+ * Sets the basic list of characters that signal a break between words
906
+ * for rl_complete_internal(). The default is the value of
907
+ * Readline.basic_word_break_characters.
908
+ *
909
+ * Raises NotImplementedError if the using readline library does not support.
910
+ *
911
+ * Raises SecurityError exception if $SAFE is 4.
912
+ */
244
913
  static VALUE
245
- readline_s_set_completer_word_break_characters(self, str)
246
- VALUE self, str;
914
+ readline_s_set_completer_word_break_characters(VALUE self, VALUE str)
247
915
  {
248
916
  static char *completer_word_break_characters = NULL;
249
917
 
250
918
  rb_secure(4);
251
- SafeStringValue(str);
919
+ OutputStringValue(str);
252
920
  if (completer_word_break_characters == NULL) {
253
- completer_word_break_characters =
254
- ALLOC_N(char, RSTRING_LEN(str) + 1);
921
+ completer_word_break_characters =
922
+ ALLOC_N(char, RSTRING_LEN(str) + 1);
255
923
  }
256
924
  else {
257
- REALLOC_N(completer_word_break_characters, char, RSTRING_LEN(str) + 1);
925
+ REALLOC_N(completer_word_break_characters, char, RSTRING_LEN(str) + 1);
258
926
  }
259
927
  strncpy(completer_word_break_characters,
260
928
  RSTRING_PTR(str), RSTRING_LEN(str));
@@ -262,63 +930,259 @@ readline_s_set_completer_word_break_characters(self, str)
262
930
  rl_completer_word_break_characters = completer_word_break_characters;
263
931
  return self;
264
932
  }
933
+ #else
934
+ #define readline_s_set_completer_word_break_characters rb_f_notimplement
935
+ #endif
265
936
 
937
+ #ifdef HAVE_RL_COMPLETER_WORD_BREAK_CHARACTERS
938
+ /*
939
+ * call-seq:
940
+ * Readline.completer_word_break_characters -> string
941
+ *
942
+ * Gets the basic list of characters that signal a break between words
943
+ * for rl_complete_internal().
944
+ *
945
+ * Raises NotImplementedError if the using readline library does not support.
946
+ *
947
+ * Raises SecurityError exception if $SAFE is 4.
948
+ */
266
949
  static VALUE
267
- readline_s_get_completer_word_break_characters(self, str)
268
- VALUE self, str;
950
+ readline_s_get_completer_word_break_characters(VALUE self, VALUE str)
269
951
  {
270
952
  rb_secure(4);
271
953
  if (rl_completer_word_break_characters == NULL)
272
- return Qnil;
273
- return rb_tainted_str_new2(rl_completer_word_break_characters);
954
+ return Qnil;
955
+ return rb_locale_str_new_cstr(rl_completer_word_break_characters);
956
+ }
957
+ #else
958
+ #define readline_s_get_completer_word_break_characters rb_f_notimplement
959
+ #endif
960
+
961
+ #ifdef HAVE_RL_BASIC_QUOTE_CHARACTERS
962
+ /*
963
+ * call-seq:
964
+ * Readline.basic_quote_characters = string
965
+ *
966
+ * Sets a list of quote characters which can cause a word break.
967
+ *
968
+ * Raises NotImplementedError if the using readline library does not support.
969
+ *
970
+ * Raises SecurityError exception if $SAFE is 4.
971
+ */
972
+ static VALUE
973
+ readline_s_set_basic_quote_characters(VALUE self, VALUE str)
974
+ {
975
+ static char *basic_quote_characters = NULL;
976
+
977
+ rb_secure(4);
978
+ OutputStringValue(str);
979
+ if (basic_quote_characters == NULL) {
980
+ basic_quote_characters =
981
+ ALLOC_N(char, RSTRING_LEN(str) + 1);
982
+ }
983
+ else {
984
+ REALLOC_N(basic_quote_characters, char, RSTRING_LEN(str) + 1);
985
+ }
986
+ strncpy(basic_quote_characters,
987
+ RSTRING_PTR(str), RSTRING_LEN(str));
988
+ basic_quote_characters[RSTRING_LEN(str)] = '\0';
989
+ rl_basic_quote_characters = basic_quote_characters;
990
+
991
+ return self;
992
+ }
993
+ #else
994
+ #define readline_s_set_basic_quote_characters rb_f_notimplement
995
+ #endif
996
+
997
+ #ifdef HAVE_RL_BASIC_QUOTE_CHARACTERS
998
+ /*
999
+ * call-seq:
1000
+ * Readline.basic_quote_characters -> string
1001
+ *
1002
+ * Gets a list of quote characters which can cause a word break.
1003
+ *
1004
+ * Raises NotImplementedError if the using readline library does not support.
1005
+ *
1006
+ * Raises SecurityError exception if $SAFE is 4.
1007
+ */
1008
+ static VALUE
1009
+ readline_s_get_basic_quote_characters(VALUE self, VALUE str)
1010
+ {
1011
+ rb_secure(4);
1012
+ if (rl_basic_quote_characters == NULL)
1013
+ return Qnil;
1014
+ return rb_locale_str_new_cstr(rl_basic_quote_characters);
274
1015
  }
1016
+ #else
1017
+ #define readline_s_get_basic_quote_characters rb_f_notimplement
1018
+ #endif
275
1019
 
1020
+ #ifdef HAVE_RL_COMPLETER_QUOTE_CHARACTERS
1021
+ /*
1022
+ * call-seq:
1023
+ * Readline.completer_quote_characters = string
1024
+ *
1025
+ * Sets a list of characters which can be used to quote a substring of
1026
+ * the line. Completion occurs on the entire substring, and within
1027
+ * the substring Readline.completer_word_break_characters are treated
1028
+ * as any other character, unless they also appear within this list.
1029
+ *
1030
+ * Raises NotImplementedError if the using readline library does not support.
1031
+ *
1032
+ * Raises SecurityError exception if $SAFE is 4.
1033
+ */
276
1034
  static VALUE
277
- readline_s_set_completer_quote_characters(self, str)
278
- VALUE self, str;
1035
+ readline_s_set_completer_quote_characters(VALUE self, VALUE str)
279
1036
  {
280
1037
  static char *completer_quote_characters = NULL;
281
1038
 
282
1039
  rb_secure(4);
283
- SafeStringValue(str);
1040
+ OutputStringValue(str);
284
1041
  if (completer_quote_characters == NULL) {
285
- completer_quote_characters =
286
- ALLOC_N(char, RSTRING_LEN(str) + 1);
1042
+ completer_quote_characters =
1043
+ ALLOC_N(char, RSTRING_LEN(str) + 1);
287
1044
  }
288
1045
  else {
289
- REALLOC_N(completer_quote_characters, char, RSTRING_LEN(str) + 1);
1046
+ REALLOC_N(completer_quote_characters, char, RSTRING_LEN(str) + 1);
290
1047
  }
291
- strncpy(completer_quote_characters,
292
- RSTRING_PTR(str), RSTRING_LEN(str));
1048
+ strncpy(completer_quote_characters, RSTRING_PTR(str), RSTRING_LEN(str));
293
1049
  completer_quote_characters[RSTRING_LEN(str)] = '\0';
294
1050
  rl_completer_quote_characters = completer_quote_characters;
295
1051
 
296
1052
  return self;
297
1053
  }
1054
+ #else
1055
+ #define readline_s_set_completer_quote_characters rb_f_notimplement
1056
+ #endif
298
1057
 
1058
+ #ifdef HAVE_RL_COMPLETER_QUOTE_CHARACTERS
1059
+ /*
1060
+ * call-seq:
1061
+ * Readline.completer_quote_characters -> string
1062
+ *
1063
+ * Gets a list of characters which can be used to quote a substring of
1064
+ * the line.
1065
+ *
1066
+ * Raises NotImplementedError if the using readline library does not support.
1067
+ *
1068
+ * Raises SecurityError exception if $SAFE is 4.
1069
+ */
299
1070
  static VALUE
300
- readline_s_get_completer_quote_characters(self, str)
301
- VALUE self, str;
1071
+ readline_s_get_completer_quote_characters(VALUE self, VALUE str)
302
1072
  {
303
1073
  rb_secure(4);
304
1074
  if (rl_completer_quote_characters == NULL)
305
- return Qnil;
306
- return rb_tainted_str_new2(rl_completer_quote_characters);
1075
+ return Qnil;
1076
+ return rb_locale_str_new_cstr(rl_completer_quote_characters);
307
1077
  }
1078
+ #else
1079
+ #define readline_s_get_completer_quote_characters rb_f_notimplement
1080
+ #endif
308
1081
 
1082
+ #ifdef HAVE_RL_FILENAME_QUOTE_CHARACTERS
1083
+ /*
1084
+ * call-seq:
1085
+ * Readline.filename_quote_characters = string
1086
+ *
1087
+ * Sets a list of characters that cause a filename to be quoted by the completer
1088
+ * when they appear in a completed filename. The default is nil.
1089
+ *
1090
+ * Raises NotImplementedError if the using readline library does not support.
1091
+ *
1092
+ * Raises SecurityError exception if $SAFE is 4.
1093
+ */
309
1094
  static VALUE
310
- hist_to_s(self)
311
- VALUE self;
1095
+ readline_s_set_filename_quote_characters(VALUE self, VALUE str)
312
1096
  {
313
- return rb_str_new2("HISTORY");
1097
+ static char *filename_quote_characters = NULL;
1098
+
1099
+ rb_secure(4);
1100
+ OutputStringValue(str);
1101
+ if (filename_quote_characters == NULL) {
1102
+ filename_quote_characters =
1103
+ ALLOC_N(char, RSTRING_LEN(str) + 1);
1104
+ }
1105
+ else {
1106
+ REALLOC_N(filename_quote_characters, char, RSTRING_LEN(str) + 1);
1107
+ }
1108
+ strncpy(filename_quote_characters, RSTRING_PTR(str), RSTRING_LEN(str));
1109
+ filename_quote_characters[RSTRING_LEN(str)] = '\0';
1110
+ rl_filename_quote_characters = filename_quote_characters;
1111
+
1112
+ return self;
314
1113
  }
1114
+ #else
1115
+ #define readline_s_set_filename_quote_characters rb_f_notimplement
1116
+ #endif
315
1117
 
1118
+ #ifdef HAVE_RL_FILENAME_QUOTE_CHARACTERS
1119
+ /*
1120
+ * call-seq:
1121
+ * Readline.filename_quote_characters -> string
1122
+ *
1123
+ * Gets a list of characters that cause a filename to be quoted by the completer
1124
+ * when they appear in a completed filename.
1125
+ *
1126
+ * Raises NotImplementedError if the using readline library does not support.
1127
+ *
1128
+ * Raises SecurityError exception if $SAFE is 4.
1129
+ */
316
1130
  static VALUE
317
- hist_get(self, index)
318
- VALUE self;
319
- VALUE index;
1131
+ readline_s_get_filename_quote_characters(VALUE self, VALUE str)
320
1132
  {
321
- HIST_ENTRY *entry;
1133
+ rb_secure(4);
1134
+ if (rl_filename_quote_characters == NULL)
1135
+ return Qnil;
1136
+ return rb_locale_str_new_cstr(rl_filename_quote_characters);
1137
+ }
1138
+ #else
1139
+ #define readline_s_get_filename_quote_characters rb_f_notimplement
1140
+ #endif
1141
+
1142
+ #ifdef HAVE_RL_REFRESH_LINE
1143
+ /*
1144
+ * call-seq:
1145
+ * Readline.refresh_line -> nil
1146
+ *
1147
+ * Clear the current input line.
1148
+ *
1149
+ * Raises SecurityError exception if $SAFE is 4.
1150
+ */
1151
+ static VALUE
1152
+ readline_s_refresh_line(VALUE self)
1153
+ {
1154
+ rb_secure(4);
1155
+ rl_refresh_line(0, 0);
1156
+ return Qnil;
1157
+ }
1158
+ #else
1159
+ #define readline_s_refresh_line rb_f_notimplement
1160
+ #endif
1161
+
1162
+ static VALUE
1163
+ hist_to_s(VALUE self)
1164
+ {
1165
+ return rb_str_new_cstr("HISTORY");
1166
+ }
1167
+
1168
+ #ifdef HAVE_READLINE_HISTORY_H
1169
+ static int
1170
+ history_get_offset_history_base(int offset)
1171
+ {
1172
+ return history_base + offset;
1173
+ }
1174
+ #endif
1175
+
1176
+ static int
1177
+ history_get_offset_0(int offset)
1178
+ {
1179
+ return offset;
1180
+ }
1181
+
1182
+ static VALUE
1183
+ hist_get(VALUE self, VALUE index)
1184
+ {
1185
+ HIST_ENTRY *entry = NULL;
322
1186
  int i;
323
1187
 
324
1188
  rb_secure(4);
@@ -326,142 +1190,144 @@ hist_get(self, index)
326
1190
  if (i < 0) {
327
1191
  i += history_length;
328
1192
  }
329
- entry = history_get(history_base + i);
1193
+ if (i >= 0) {
1194
+ entry = history_get(history_get_offset_func(i));
1195
+ }
330
1196
  if (entry == NULL) {
331
- rb_raise(rb_eIndexError, "invalid index");
1197
+ rb_raise(rb_eIndexError, "invalid index");
332
1198
  }
333
- return rb_tainted_str_new2(entry->line);
1199
+ return rb_locale_str_new_cstr(entry->line);
334
1200
  }
335
1201
 
1202
+ #ifdef HAVE_REPLACE_HISTORY_ENTRY
336
1203
  static VALUE
337
- hist_set(self, index, str)
338
- VALUE self;
339
- VALUE index;
340
- VALUE str;
1204
+ hist_set(VALUE self, VALUE index, VALUE str)
341
1205
  {
342
- HIST_ENTRY *entry;
1206
+ HIST_ENTRY *entry = NULL;
343
1207
  int i;
344
1208
 
345
1209
  rb_secure(4);
346
1210
  i = NUM2INT(index);
347
- SafeStringValue(str);
1211
+ OutputStringValue(str);
348
1212
  if (i < 0) {
349
1213
  i += history_length;
350
1214
  }
351
- entry = replace_history_entry(i, RSTRING_PTR(str), NULL);
1215
+ if (i >= 0) {
1216
+ entry = replace_history_entry(i, RSTRING_PTR(str), NULL);
1217
+ }
352
1218
  if (entry == NULL) {
353
- rb_raise(rb_eIndexError, "invalid index");
1219
+ rb_raise(rb_eIndexError, "invalid index");
354
1220
  }
355
1221
  return str;
356
1222
  }
1223
+ #else
1224
+ #define hist_set rb_f_notimplement
1225
+ #endif
357
1226
 
358
1227
  static VALUE
359
- hist_push(self, str)
360
- VALUE self;
361
- VALUE str;
1228
+ hist_push(VALUE self, VALUE str)
362
1229
  {
363
1230
  rb_secure(4);
364
- SafeStringValue(str);
1231
+ OutputStringValue(str);
365
1232
  add_history(RSTRING_PTR(str));
366
1233
  return self;
367
1234
  }
368
1235
 
369
1236
  static VALUE
370
- hist_push_method(argc, argv, self)
371
- int argc;
372
- VALUE *argv;
373
- VALUE self;
1237
+ hist_push_method(int argc, VALUE *argv, VALUE self)
374
1238
  {
375
1239
  VALUE str;
376
1240
 
377
1241
  rb_secure(4);
378
1242
  while (argc--) {
379
- str = *argv++;
380
- SafeStringValue(str);
381
- add_history(RSTRING_PTR(str));
1243
+ str = *argv++;
1244
+ OutputStringValue(str);
1245
+ add_history(RSTRING_PTR(str));
382
1246
  }
383
1247
  return self;
384
1248
  }
385
1249
 
386
1250
  static VALUE
387
- rb_remove_history(index)
388
- int index;
1251
+ rb_remove_history(int index)
389
1252
  {
1253
+ #ifdef HAVE_REMOVE_HISTORY
390
1254
  HIST_ENTRY *entry;
391
1255
  VALUE val;
392
1256
 
393
1257
  rb_secure(4);
394
1258
  entry = remove_history(index);
395
1259
  if (entry) {
396
- val = rb_tainted_str_new2(entry->line);
397
- free((char*)entry->line);
1260
+ val = rb_locale_str_new_cstr(entry->line);
1261
+ free((void *) entry->line);
398
1262
  free(entry);
399
1263
  return val;
400
1264
  }
401
1265
  return Qnil;
1266
+ #else
1267
+ rb_notimplement();
1268
+ return Qnil; /* not reached */
1269
+ #endif
402
1270
  }
403
1271
 
404
1272
  static VALUE
405
- hist_pop(self)
406
- VALUE self;
1273
+ hist_pop(VALUE self)
407
1274
  {
408
1275
  rb_secure(4);
409
1276
  if (history_length > 0) {
410
- return rb_remove_history(history_length - 1);
1277
+ return rb_remove_history(history_length - 1);
411
1278
  } else {
412
- return Qnil;
1279
+ return Qnil;
413
1280
  }
414
1281
  }
415
1282
 
416
1283
  static VALUE
417
- hist_shift(self)
418
- VALUE self;
1284
+ hist_shift(VALUE self)
419
1285
  {
420
1286
  rb_secure(4);
421
1287
  if (history_length > 0) {
422
- return rb_remove_history(0);
1288
+ return rb_remove_history(0);
423
1289
  } else {
424
- return Qnil;
1290
+ return Qnil;
425
1291
  }
426
1292
  }
427
1293
 
428
1294
  static VALUE
429
- hist_each(self)
430
- VALUE self;
1295
+ hist_each(VALUE self)
431
1296
  {
432
1297
  HIST_ENTRY *entry;
433
1298
  int i;
434
1299
 
1300
+ /* TODO: turn a C-API function into an enumerator.
1301
+ *
1302
+ * RETURN_ENUMERATOR(self, 0, 0);
1303
+ */
1304
+
435
1305
  rb_secure(4);
436
1306
  for (i = 0; i < history_length; i++) {
437
- entry = history_get(history_base + i);
1307
+ entry = history_get(history_get_offset_func(i));
438
1308
  if (entry == NULL)
439
1309
  break;
440
- rb_yield(rb_tainted_str_new2(entry->line));
1310
+ rb_yield(rb_locale_str_new_cstr(entry->line));
441
1311
  }
442
1312
  return self;
443
1313
  }
444
1314
 
445
1315
  static VALUE
446
- hist_length(self)
447
- VALUE self;
1316
+ hist_length(VALUE self)
448
1317
  {
449
1318
  rb_secure(4);
450
1319
  return INT2NUM(history_length);
451
1320
  }
452
1321
 
453
1322
  static VALUE
454
- hist_empty_p(self)
455
- VALUE self;
1323
+ hist_empty_p(VALUE self)
456
1324
  {
457
1325
  rb_secure(4);
458
1326
  return history_length == 0 ? Qtrue : Qfalse;
459
1327
  }
460
1328
 
461
1329
  static VALUE
462
- hist_delete_at(self, index)
463
- VALUE self;
464
- VALUE index;
1330
+ hist_delete_at(VALUE self, VALUE index)
465
1331
  {
466
1332
  int i;
467
1333
 
@@ -470,18 +1336,80 @@ hist_delete_at(self, index)
470
1336
  if (i < 0)
471
1337
  i += history_length;
472
1338
  if (i < 0 || i > history_length - 1) {
473
- rb_raise(rb_eIndexError, "invalid index");
1339
+ rb_raise(rb_eIndexError, "invalid index");
474
1340
  }
475
1341
  return rb_remove_history(i);
476
1342
  }
477
1343
 
1344
+ #ifdef HAVE_CLEAR_HISTORY
1345
+ static VALUE
1346
+ hist_clear(VALUE self)
1347
+ {
1348
+ rb_secure(4);
1349
+ clear_history();
1350
+ return self;
1351
+ }
1352
+ #else
1353
+ #define hist_clear rb_f_notimplement
1354
+ #endif
1355
+
1356
+ static VALUE
1357
+ filename_completion_proc_call(VALUE self, VALUE str)
1358
+ {
1359
+ VALUE result;
1360
+ char **matches;
1361
+ int i;
1362
+
1363
+ matches = rl_completion_matches(StringValuePtr(str),
1364
+ rl_filename_completion_function);
1365
+ if (matches) {
1366
+ result = rb_ary_new();
1367
+ for (i = 0; matches[i]; i++) {
1368
+ rb_ary_push(result, rb_locale_str_new_cstr(matches[i]));
1369
+ free(matches[i]);
1370
+ }
1371
+ free(matches);
1372
+ if (RARRAY_LEN(result) >= 2)
1373
+ rb_ary_shift(result);
1374
+ }
1375
+ else {
1376
+ result = Qnil;
1377
+ }
1378
+ return result;
1379
+ }
1380
+
1381
+ static VALUE
1382
+ username_completion_proc_call(VALUE self, VALUE str)
1383
+ {
1384
+ VALUE result;
1385
+ char **matches;
1386
+ int i;
1387
+
1388
+ matches = rl_completion_matches(StringValuePtr(str),
1389
+ rl_username_completion_function);
1390
+ if (matches) {
1391
+ result = rb_ary_new();
1392
+ for (i = 0; matches[i]; i++) {
1393
+ rb_ary_push(result, rb_locale_str_new_cstr(matches[i]));
1394
+ free(matches[i]);
1395
+ }
1396
+ free(matches);
1397
+ if (RARRAY_LEN(result) >= 2)
1398
+ rb_ary_shift(result);
1399
+ }
1400
+ else {
1401
+ result = Qnil;
1402
+ }
1403
+ return result;
1404
+ }
1405
+
478
1406
  void
479
1407
  Init_readline()
480
1408
  {
481
- VALUE history;
1409
+ VALUE history, fcomp, ucomp, version;
482
1410
 
483
1411
  /* Allow conditional parsing of the ~/.inputrc file. */
484
- rl_readline_name = "Ruby";
1412
+ rl_readline_name = (char *)"Ruby";
485
1413
 
486
1414
  using_history();
487
1415
 
@@ -489,34 +1417,70 @@ Init_readline()
489
1417
  completion_case_fold = rb_intern(COMPLETION_CASE_FOLD);
490
1418
 
491
1419
  mReadline = rb_define_module("Readline");
492
- rb_define_singleton_method(mReadline, "perform_readline",
493
- readline_readline, 2);
1420
+ rb_define_module_function(mReadline, "perform_readline",
1421
+ readline_readline, -1);
1422
+ rb_define_singleton_method(mReadline, "input=",
1423
+ readline_s_set_input, 1);
1424
+ rb_define_singleton_method(mReadline, "output=",
1425
+ readline_s_set_output, 1);
494
1426
  rb_define_singleton_method(mReadline, "completion_proc=",
495
- readline_s_set_completion_proc, 1);
1427
+ readline_s_set_completion_proc, 1);
496
1428
  rb_define_singleton_method(mReadline, "completion_proc",
497
- readline_s_get_completion_proc, 0);
1429
+ readline_s_get_completion_proc, 0);
498
1430
  rb_define_singleton_method(mReadline, "completion_case_fold=",
499
- readline_s_set_completion_case_fold, 1);
1431
+ readline_s_set_completion_case_fold, 1);
500
1432
  rb_define_singleton_method(mReadline, "completion_case_fold",
501
- readline_s_get_completion_case_fold, 0);
1433
+ readline_s_get_completion_case_fold, 0);
1434
+ rb_define_singleton_method(mReadline, "line_buffer",
1435
+ readline_s_get_line_buffer, 0);
1436
+ rb_define_singleton_method(mReadline, "point",
1437
+ readline_s_get_point, 0);
1438
+ rb_define_singleton_method(mReadline, "set_screen_size",
1439
+ readline_s_set_screen_size, 2);
1440
+ rb_define_singleton_method(mReadline, "get_screen_size",
1441
+ readline_s_get_screen_size, 0);
1442
+ rb_define_singleton_method(mReadline, "vi_editing_mode",
1443
+ readline_s_vi_editing_mode, 0);
1444
+ rb_define_singleton_method(mReadline, "vi_editing_mode?",
1445
+ readline_s_vi_editing_mode_p, 0);
1446
+ rb_define_singleton_method(mReadline, "emacs_editing_mode",
1447
+ readline_s_emacs_editing_mode, 0);
1448
+ rb_define_singleton_method(mReadline, "emacs_editing_mode?",
1449
+ readline_s_emacs_editing_mode_p, 0);
502
1450
  rb_define_singleton_method(mReadline, "completion_append_character=",
503
- readline_s_set_completion_append_character, 1);
1451
+ readline_s_set_completion_append_character, 1);
504
1452
  rb_define_singleton_method(mReadline, "completion_append_character",
505
- readline_s_get_completion_append_character, 0);
1453
+ readline_s_get_completion_append_character, 0);
506
1454
  rb_define_singleton_method(mReadline, "basic_word_break_characters=",
507
- readline_s_set_basic_word_break_characters, 1);
1455
+ readline_s_set_basic_word_break_characters, 1);
508
1456
  rb_define_singleton_method(mReadline, "basic_word_break_characters",
509
- readline_s_get_basic_word_break_characters, 0);
1457
+ readline_s_get_basic_word_break_characters, 0);
510
1458
  rb_define_singleton_method(mReadline, "completer_word_break_characters=",
511
- readline_s_set_completer_word_break_characters, 1);
1459
+ readline_s_set_completer_word_break_characters, 1);
512
1460
  rb_define_singleton_method(mReadline, "completer_word_break_characters",
513
- readline_s_get_completer_word_break_characters, 0);
1461
+ readline_s_get_completer_word_break_characters, 0);
1462
+ rb_define_singleton_method(mReadline, "basic_quote_characters=",
1463
+ readline_s_set_basic_quote_characters, 1);
1464
+ rb_define_singleton_method(mReadline, "basic_quote_characters",
1465
+ readline_s_get_basic_quote_characters, 0);
514
1466
  rb_define_singleton_method(mReadline, "completer_quote_characters=",
515
- readline_s_set_completer_quote_characters, 1);
1467
+ readline_s_set_completer_quote_characters, 1);
516
1468
  rb_define_singleton_method(mReadline, "completer_quote_characters",
517
- readline_s_get_completer_quote_characters, 0);
1469
+ readline_s_get_completer_quote_characters, 0);
1470
+ rb_define_singleton_method(mReadline, "filename_quote_characters=",
1471
+ readline_s_set_filename_quote_characters, 1);
1472
+ rb_define_singleton_method(mReadline, "filename_quote_characters",
1473
+ readline_s_get_filename_quote_characters, 0);
1474
+ rb_define_singleton_method(mReadline, "refresh_line",
1475
+ readline_s_refresh_line, 0);
1476
+
1477
+ #if USE_INSERT_IGNORE_ESCAPE
1478
+ CONST_ID(id_orig_prompt, "orig_prompt");
1479
+ CONST_ID(id_last_prompt, "last_prompt");
1480
+ #endif
518
1481
 
519
1482
  history = rb_obj_alloc(rb_cObject);
1483
+ rb_extend_object(history, rb_mEnumerable);
520
1484
  rb_define_singleton_method(history,"to_s", hist_to_s, 0);
521
1485
  rb_define_singleton_method(history,"[]", hist_get, 1);
522
1486
  rb_define_singleton_method(history,"[]=", hist_set, 2);
@@ -529,9 +1493,78 @@ Init_readline()
529
1493
  rb_define_singleton_method(history,"size", hist_length, 0);
530
1494
  rb_define_singleton_method(history,"empty?", hist_empty_p, 0);
531
1495
  rb_define_singleton_method(history,"delete_at", hist_delete_at, 1);
1496
+ rb_define_singleton_method(history,"clear", hist_clear, 0);
1497
+
1498
+ /*
1499
+ * The history buffer. It extends Enumerable module, so it behaves
1500
+ * just like an array.
1501
+ * For example, gets the fifth content that the user input by
1502
+ * HISTORY[4].
1503
+ */
532
1504
  rb_define_const(mReadline, "HISTORY", history);
533
1505
 
534
- rb_define_const(mReadline, "VERSION", rb_str_new2(rl_library_version));
1506
+ fcomp = rb_obj_alloc(rb_cObject);
1507
+ rb_define_singleton_method(fcomp, "call",
1508
+ filename_completion_proc_call, 1);
1509
+ /*
1510
+ * The Object with the call method that is a completion for filename.
1511
+ * This is sets by Readline.completion_proc= method.
1512
+ */
1513
+ rb_define_const(mReadline, "FILENAME_COMPLETION_PROC", fcomp);
1514
+
1515
+ ucomp = rb_obj_alloc(rb_cObject);
1516
+ rb_define_singleton_method(ucomp, "call",
1517
+ username_completion_proc_call, 1);
1518
+ /*
1519
+ * The Object with the call method that is a completion for usernames.
1520
+ * This is sets by Readline.completion_proc= method.
1521
+ */
1522
+ rb_define_const(mReadline, "USERNAME_COMPLETION_PROC", ucomp);
1523
+ history_get_offset_func = history_get_offset_history_base;
1524
+ #if defined HAVE_RL_LIBRARY_VERSION
1525
+ version = rb_str_new_cstr(rl_library_version);
1526
+ #if defined HAVE_CLEAR_HISTORY || defined HAVE_REMOVE_HISTORY
1527
+ if (strncmp(rl_library_version, EDIT_LINE_LIBRARY_VERSION,
1528
+ strlen(EDIT_LINE_LIBRARY_VERSION)) == 0) {
1529
+ add_history("1");
1530
+ if (history_get(history_get_offset_func(0)) == NULL) {
1531
+ history_get_offset_func = history_get_offset_0;
1532
+ }
1533
+ #if !defined HAVE_CLEAR_HISTORY
1534
+ clear_history();
1535
+ #else
1536
+ {
1537
+ HIST_ENTRY *entry = remove_history(0);
1538
+ if (entry) {
1539
+ free((char *)entry->line);
1540
+ free(entry);
1541
+ }
1542
+ }
1543
+ #endif
1544
+ }
1545
+ #endif
1546
+ #else
1547
+ version = rb_str_new_cstr("2.0 or prior version");
1548
+ #endif
1549
+ /* Version string of GNU Readline or libedit. */
1550
+ rb_define_const(mReadline, "VERSION", version);
535
1551
 
536
1552
  rl_attempted_completion_function = readline_attempted_completion_function;
1553
+ #if defined HAVE_RL_GETC_FUNCTION
1554
+ rl_getc_function = readline_getc;
1555
+ id_getbyte = rb_intern("getbyte");
1556
+ #elif defined HAVE_RL_EVENT_HOOK
1557
+ rl_event_hook = readline_event;
1558
+ #endif
1559
+ #ifdef HAVE_RL_CATCH_SIGNALS
1560
+ rl_catch_signals = 0;
1561
+ #endif
1562
+ #ifdef HAVE_RL_CATCH_SIGWINCH
1563
+ rl_catch_sigwinch = 0;
1564
+ #endif
1565
+ #ifdef HAVE_RL_CLEAR_SIGNALS
1566
+ rl_clear_signals();
1567
+ #endif
1568
+
1569
+ readline_s_set_input(mReadline, rb_stdin);
537
1570
  }