rubysl-readline 1.0.1 → 2.0.2

Sign up to get free protection for your applications and to get access to all the features.
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
  }