]> git.ipfire.org Git - thirdparty/bird.git/blame - client/birdc.c
Doc: Update prefix set comment
[thirdparty/bird.git] / client / birdc.c
CommitLineData
a5e9f3d2
OZ
1/*
2 * BIRD Client - Readline variant I/O
3 *
4 * (c) 1999--2004 Martin Mares <mj@ucw.cz>
5 *
6 * Can be freely distributed and used under the terms of the GNU GPL.
7 */
8
9#include <stdio.h>
10#include <stdlib.h>
11#include <unistd.h>
12#include <termios.h>
13
14#include <readline/readline.h>
15#include <readline/history.h>
16#include <curses.h>
17
18#include "nest/bird.h"
19#include "lib/resource.h"
20#include "lib/string.h"
21#include "client/client.h"
a5e9f3d2
OZ
22
23static int input_hidden_end;
24static int prompt_active;
25
26/*** Input ***/
27
28/* HACK: libreadline internals we need to access */
29extern int _rl_vis_botlin;
30extern void _rl_move_vert(int);
a5e9f3d2 31
b880e3ff
JMM
32#define HISTORY "/.birdc_history"
33static char *history_file;
34
a5e9f3d2
OZ
35static void
36add_history_dedup(char *cmd)
37{
38 /* Add history line if it differs from the last one */
39 HIST_ENTRY *he = history_get(history_length);
40 if (!he || strcmp(he->line, cmd))
41 add_history(cmd);
42}
43
44static void
45input_got_line(char *cmd_buffer)
46{
47 if (!cmd_buffer)
48 {
49 cleanup();
50 exit(0);
51 }
52
53 if (cmd_buffer[0])
54 {
55 add_history_dedup(cmd_buffer);
56 submit_command(cmd_buffer);
57 }
58
59 free(cmd_buffer);
60}
61
62void
63input_start_list(void)
64{
65 /* Leave the currently edited line and make space for listing */
66 _rl_move_vert(_rl_vis_botlin);
67#ifdef HAVE_RL_CRLF
68 rl_crlf();
69#endif
70}
71
72void
73input_stop_list(void)
74{
75 /* Reprint the currently edited line after listing */
76 rl_on_new_line();
77 rl_redisplay();
78}
79
80static int
81input_complete(int arg UNUSED, int key UNUSED)
82{
83 static int complete_flag;
84 char buf[256];
85
86 if (rl_last_func != input_complete)
87 complete_flag = 0;
88 switch (cmd_complete(rl_line_buffer, rl_point, buf, complete_flag))
89 {
90 case 0:
91 complete_flag = 1;
92 break;
93 case 1:
94 rl_insert_text(buf);
95 break;
96 default:
97 complete_flag = 1;
98#ifdef HAVE_RL_DING
99 rl_ding();
100#endif
101 }
102 return 0;
103}
104
105static int
106input_help(int arg, int key UNUSED)
107{
108 int i, in_string, in_bracket;
109
110 if (arg != 1)
111 return rl_insert(arg, '?');
112
113 in_string = in_bracket = 0;
114 for (i = 0; i < rl_point; i++)
115 {
116
117 if (rl_line_buffer[i] == '"')
118 in_string = ! in_string;
119 else if (! in_string)
120 {
121 if (rl_line_buffer[i] == '[')
122 in_bracket++;
123 else if (rl_line_buffer[i] == ']')
124 in_bracket--;
125 }
126 }
127
128 /* `?' inside string or path -> insert */
129 if (in_string || in_bracket)
130 return rl_insert(1, '?');
131
132 rl_begin_undo_group(); /* HACK: We want to display `?' at point position */
133 rl_insert_text("?");
134 rl_redisplay();
135 rl_end_undo_group();
136 input_start_list();
137 cmd_help(rl_line_buffer, rl_point);
138 rl_undo_command(1, 0);
139 input_stop_list();
140 return 0;
141}
142
b880e3ff
JMM
143void
144history_init(void)
145{
146 const char *homedir = getenv("HOME");
147 if (!homedir)
148 homedir = ".";
149 history_file = malloc(strlen(homedir) + sizeof(HISTORY));
150 if (!history_file)
151 die("couldn't alloc enough memory for history file name");
152
153 sprintf(history_file, "%s%s", homedir, HISTORY);
154 read_history(history_file);
155}
156
a5e9f3d2
OZ
157void
158input_init(void)
159{
31874783
JMM
160 if (interactive)
161 history_init();
a5e9f3d2
OZ
162 rl_readline_name = "birdc";
163 rl_add_defun("bird-complete", input_complete, '\t');
164 rl_add_defun("bird-help", input_help, '?');
165 rl_callback_handler_install("bird> ", input_got_line);
166
167 // rl_get_screen_size();
4d4979c6
OZ
168 term_lns = LINES;
169 term_cls = COLS;
a5e9f3d2
OZ
170
171 prompt_active = 1;
172
173 // readline library does strange things when stdin is nonblocking.
174 // if (fcntl(0, F_SETFL, O_NONBLOCK) < 0)
3f2c7600 175 // DIE("fcntl");
a5e9f3d2
OZ
176}
177
178static void
179input_reveal(void)
180{
181 /* need this, otherwise some lib seems to eat pending output when
182 the prompt is displayed */
183 fflush(stdout);
184 tcdrain(STDOUT_FILENO);
185
186 rl_end = input_hidden_end;
187 rl_expand_prompt("bird> ");
188 rl_forced_update_display();
189
190 prompt_active = 1;
191}
192
193static void
194input_hide(void)
195{
196 input_hidden_end = rl_end;
197 rl_end = 0;
198 rl_expand_prompt("");
199 rl_redisplay();
200
201 prompt_active = 0;
202}
203
204void
205input_notify(int prompt)
206{
207 if (prompt == prompt_active)
208 return;
209
210 if (prompt)
211 input_reveal();
212 else
213 input_hide();
214}
215
216void
217input_read(void)
218{
219 rl_callback_read_char();
220}
221
222void
223more_begin(void)
224{
225}
226
227void
228more_end(void)
229{
230}
231
232void
233cleanup(void)
234{
235 if (init)
236 return;
237
238 input_hide();
31874783
JMM
239 if (interactive)
240 write_history(history_file);
a5e9f3d2
OZ
241 rl_callback_handler_remove();
242}