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