aboutsummaryrefslogtreecommitdiff
path: root/src/input-rl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/input-rl.c')
-rw-r--r--src/input-rl.c235
1 files changed, 235 insertions, 0 deletions
diff --git a/src/input-rl.c b/src/input-rl.c
new file mode 100644
index 0000000..f435ed4
--- /dev/null
+++ b/src/input-rl.c
@@ -0,0 +1,235 @@
1/* This file is part of GDBM, the GNU data base manager.
2 Copyright (C) 2016 Free Software Foundation, Inc.
3
4 GDBM is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 GDBM is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with GDBM. If not, see <http://www.gnu.org/licenses/>. */
16
17#include "gdbmtool.h"
18#include <readline/readline.h>
19#include <readline/history.h>
20
21static char *pre_input_line;
22
23static int
24pre_input (void)
25{
26 if (pre_input_line)
27 {
28 rl_insert_text (pre_input_line);
29 free (pre_input_line);
30 pre_input_line = NULL;
31 rl_redisplay ();
32 }
33 return 0;
34}
35
36static int
37retrieve_history (char *str)
38{
39 char *out;
40 int rc;
41
42 rc = history_expand (str, &out);
43 switch (rc)
44 {
45 case -1:
46 yyerror (out);
47 free (out);
48 return 1;
49
50 case 0:
51 break;
52
53 case 1:
54 pre_input_line = out;
55 return 1;
56
57 case 2:
58 printf ("%s\n", out);
59 free (out);
60 return 1;
61 }
62 return 0;
63}
64
65ssize_t
66input_read (FILE *fp, char *buf, size_t size)
67{
68 static char *input_line;
69 static size_t input_length;
70 static size_t input_off;
71#define input_ptr() (input_line + input_off)
72#define input_size() (input_length - input_off)
73
74 if (interactive)
75 {
76 size_t len = input_size ();
77 if (!len)
78 {
79 if (input_line)
80 {
81 newline:
82 free (input_line);
83 input_line = NULL;
84 buf[0] = '\n';
85 return 1;
86 }
87 else
88 {
89 char *prompt;
90 again:
91 prompt = make_prompt ();
92 input_line = readline (prompt);
93 free (prompt);
94 if (!input_line)
95 return 0;
96 input_length = strlen (input_line);
97 input_off = 0;
98 if (input_length)
99 {
100 if (retrieve_history (input_line))
101 {
102 free (input_line);
103 goto again;
104 }
105 }
106 else
107 goto newline;
108 len = input_size ();
109 add_history (input_line);
110 }
111 }
112
113 if (len > size)
114 len = size;
115 memcpy (buf, input_ptr (), len);
116 input_off += len;
117
118 return len;
119 }
120 return fread (buf, 1, size, fp);
121}
122
123struct history_param
124{
125 int from;
126 int count;
127};
128
129int
130input_history_begin (struct handler_param *param, size_t *exp_count)
131{
132 struct history_param *p;
133 int from = 0, count = history_length;
134
135 switch (param->argc)
136 {
137 case 1:
138 if (getnum (&count, param->argv[0]->v.string, NULL))
139 return 1;
140 if (count > history_length)
141 count = history_length;
142 else
143 from = history_length - count;
144 break;
145
146 case 2:
147 if (getnum (&from, param->argv[0]->v.string, NULL))
148 return 1;
149 if (from)
150 --from;
151 if (getnum (&count, param->argv[1]->v.string, NULL))
152 return 1;
153
154 if (count > history_length)
155 count = history_length;
156 }
157 p = emalloc (sizeof *p);
158 p->from = from;
159 p->count = count;
160 param->data = p;
161 if (exp_count)
162 *exp_count = count;
163 return 0;
164}
165
166void
167input_history_handler (struct handler_param *param)
168{
169 struct history_param *p = param->data;
170 int i;
171 HIST_ENTRY **hlist;
172 FILE *fp = param->fp;
173
174 hlist = history_list ();
175 for (i = 0; i < p->count; i++)
176 fprintf (fp, "%4d) %s\n", p->from + i + 1, hlist[p->from + i]->line);
177}
178
179#define HISTFILE_PREFIX "~/."
180#define HISTFILE_SUFFIX "_history"
181
182static char *
183get_history_file_name ()
184{
185 static char *filename = NULL;
186
187 if (!filename)
188 {
189 char *hname;
190
191 hname = emalloc (sizeof HISTFILE_PREFIX + strlen (rl_readline_name) +
192 sizeof HISTFILE_SUFFIX - 1);
193 strcpy (hname, HISTFILE_PREFIX);
194 strcat (hname, rl_readline_name);
195 strcat (hname, HISTFILE_SUFFIX);
196 filename = tildexpand (hname);
197 free (hname);
198 }
199 return filename;
200}
201
202static char **
203shell_completion (const char *text, int start, int end)
204{
205 char **matches;
206
207 matches = (char **) NULL;
208
209 /* If this word is at the start of the line, then it is a command
210 to complete. Otherwise it is the name of a file in the current
211 directory. */
212 if (start == 0)
213 matches = rl_completion_matches (text, command_generator);
214
215 return (matches);
216}
217
218void
219input_init (void)
220{
221 /* Allow conditional parsing of the ~/.inputrc file. */
222 rl_readline_name = (char *) progname;
223 rl_attempted_completion_function = shell_completion;
224 rl_pre_input_hook = pre_input;
225 if (interactive)
226 read_history (get_history_file_name ());
227}
228
229void
230input_done (void)
231{
232 if (interactive)
233 write_history (get_history_file_name ());
234}
235

Return to:

Send suggestions and report system problems to the System administrator.