- Adds handling of Ctrl-c Ctrl-d as requested
- Prompted changed to includ space
- Added commands: quit exit help
- Added completion for help
- Terminal settings restored on exit
Jerzy Kasenberg (3):
android: Add space in prompt in haltest
android: Add handling of Ctrl-c to haltest
android: Add help and quit to haltest
android/client/haltest.c | 151 ++++++++++++++++++++++++++++++++++------
android/client/if-main.h | 6 ++
android/client/tabcompletion.c | 151 ++++++++++++++++++++++++++++------------
android/client/terminal.c | 100 ++++++++++++++++++--------
4 files changed, 312 insertions(+), 96 deletions(-)
--
1.7.9.5
Hi Jerzy,
On Tue, Oct 22, 2013, Jerzy Kasenberg wrote:
> On 21 October 2013 18:18, Johan Hedberg <[email protected]> wrote:
> > Hi Jerzy,
> >
> > On Mon, Oct 21, 2013, Jerzy Kasenberg wrote:
> >> - Adds handling of Ctrl-c Ctrl-d as requested
> >> - Prompted changed to includ space
> >> - Added commands: quit exit help
> >> - Added completion for help
> >> - Terminal settings restored on exit
> >>
> >> Jerzy Kasenberg (3):
> >> android: Add space in prompt in haltest
> >> android: Add handling of Ctrl-c to haltest
> >> android: Add help and quit to haltest
> >>
> >> android/client/haltest.c | 151 ++++++++++++++++++++++++++++++++++------
> >> android/client/if-main.h | 6 ++
> >> android/client/tabcompletion.c | 151 ++++++++++++++++++++++++++++------------
> >> android/client/terminal.c | 100 ++++++++++++++++++--------
> >> 4 files changed, 312 insertions(+), 96 deletions(-)
> >
> > Patches 1 and 3 have been applied. It seems we had a bit of a
> > misunderstanding about 2 though. I was looking for ctrl-d (i.e. EOF)
> > support. Sorry for not being more precise here. Right now when I try
> > it the following just happens:
> >
> > jh@x220:bluez{master}$ android/haltest
> >> char-0x04
>
> Patch 2 handles Ctrl-c and Ctrl-d.
> When I tried on two terminals in bash Ctrl-d act like delete if line
> is not empty.
Seems you're right. Anyway, this was part of the same request as adding
basic "exit" or "quit" commands. When a user ends up in an unknown shell
and wants to get out from it those are usually the first things tried
(including ctrl-d).
> You or Szymon asked me to add Ctrl-c to clear current line like in
> other tools.
It wasn't me since ctrl-c was already getting me out from the tool.
> So maybe it wold be better to put Ctrl-d in patch title instead of
> Ctrl-c
Ctrl-d should be generating an EOF indicator just like feeding a file to
the program through stdin does. So in this sense "ctrl-d" isn't really
the best description as there are more ways of accomplishing the same.
> This is what patch 2 handles by setting atexit() cleanup function
> that restore terminal settings.
Sounds like this should have been split into a separate patch then.
Johan
Hi Johan,
On 21 October 2013 18:18, Johan Hedberg <[email protected]> wrote:
> Hi Jerzy,
>
> On Mon, Oct 21, 2013, Jerzy Kasenberg wrote:
>> - Adds handling of Ctrl-c Ctrl-d as requested
>> - Prompted changed to includ space
>> - Added commands: quit exit help
>> - Added completion for help
>> - Terminal settings restored on exit
>>
>> Jerzy Kasenberg (3):
>> android: Add space in prompt in haltest
>> android: Add handling of Ctrl-c to haltest
>> android: Add help and quit to haltest
>>
>> android/client/haltest.c | 151 ++++++++++++++++++++++++++++++++++------
>> android/client/if-main.h | 6 ++
>> android/client/tabcompletion.c | 151 ++++++++++++++++++++++++++++------------
>> android/client/terminal.c | 100 ++++++++++++++++++--------
>> 4 files changed, 312 insertions(+), 96 deletions(-)
>
> Patches 1 and 3 have been applied. It seems we had a bit of a
> misunderstanding about 2 though. I was looking for ctrl-d (i.e. EOF)
> support. Sorry for not being more precise here. Right now when I try
> it the following just happens:
>
> jh@x220:bluez{master}$ android/haltest
>> char-0x04
Patch 2 handles Ctrl-c and Ctrl-d.
When I tried on two terminals in bash Ctrl-d act like delete if line
is not empty.
(this is emax style). When line is empty it terminates.
You or Szymon asked me to add Ctrl-c to clear current line like in other tools.
So maybe it wold be better to put Ctrl-d in patch title instead of Ctrl-c
>
> I wouldn't have expected this to be an issue if stdin is processed
> properly, but it seems even something like the following doesn't result
> in the expected behavior right now (to run all commands in the file and
> then exit the tool):
>
> $ tools/haltest < my-script.txt
This I haven't tried yet so this will probably not work.
But I can handle it some other way not related to Ctrl-d (later :)).
>
> Another thing I'd like to see fixed is getting the terminal back to a
> sane state when exiting. Right now even after a clean exit I seem to
> have to do a hard terminal reset to get normal behavior back. As an
> example, the following is what I get after cleanly exiting using "exit"
> and then pressing enter a couple of times:
>
> jh@x220:bluez{master}$ android/haltest
>> exit
This is what patch 2 handles by setting atexit() cleanup function that restore
terminal settings. Before there was exit command, ctrl-c did it automatically.
> jh@x220:bluez{master}$ jh@x220:bluez{master}$ jh@x220:bluez{master}$
>
> Johan
--
Jerzy Kasenberg
Hi Jerzy,
On Mon, Oct 21, 2013, Jerzy Kasenberg wrote:
> - Adds handling of Ctrl-c Ctrl-d as requested
> - Prompted changed to includ space
> - Added commands: quit exit help
> - Added completion for help
> - Terminal settings restored on exit
>
> Jerzy Kasenberg (3):
> android: Add space in prompt in haltest
> android: Add handling of Ctrl-c to haltest
> android: Add help and quit to haltest
>
> android/client/haltest.c | 151 ++++++++++++++++++++++++++++++++++------
> android/client/if-main.h | 6 ++
> android/client/tabcompletion.c | 151 ++++++++++++++++++++++++++++------------
> android/client/terminal.c | 100 ++++++++++++++++++--------
> 4 files changed, 312 insertions(+), 96 deletions(-)
Patches 1 and 3 have been applied. It seems we had a bit of a
misunderstanding about 2 though. I was looking for ctrl-d (i.e. EOF)
support. Sorry for not being more precise here. Right now when I try
it the following just happens:
jh@x220:bluez{master}$ android/haltest
> char-0x04
I wouldn't have expected this to be an issue if stdin is processed
properly, but it seems even something like the following doesn't result
in the expected behavior right now (to run all commands in the file and
then exit the tool):
$ tools/haltest < my-script.txt
Another thing I'd like to see fixed is getting the terminal back to a
sane state when exiting. Right now even after a clean exit I seem to
have to do a hard terminal reset to get normal behavior back. As an
example, the following is what I get after cleanly exiting using "exit"
and then pressing enter a couple of times:
jh@x220:bluez{master}$ android/haltest
> exit
jh@x220:bluez{master}$ jh@x220:bluez{master}$ jh@x220:bluez{master}$
Johan
This patch makes prompt more consistent with other bluez tools.
This also fixes small issue when prompt was printed twice.
---
android/client/terminal.c | 17 ++++++++++-------
1 file changed, 10 insertions(+), 7 deletions(-)
diff --git a/android/client/terminal.c b/android/client/terminal.c
index 8dd3a25..fb4d5d8 100644
--- a/android/client/terminal.c
+++ b/android/client/terminal.c
@@ -111,6 +111,8 @@ static int line_len = 0;
/* line index used for fetching lines from history */
static int line_index = 0;
+static char prompt_buf[10] = "> ";
+static const char *prompt = prompt_buf;
/*
* Moves cursor to right or left
*
@@ -135,9 +137,9 @@ void terminal_draw_command_line(void)
* before parsing event though line_len and line_buf_ix are
*/
if (line_len > 0)
- printf(">%s", line_buf);
+ printf("%s%s", prompt, line_buf);
else
- putchar('>');
+ printf("%s", prompt);
/* move cursor to it's place */
terminal_move_cursor(line_buf_ix - line_len);
@@ -216,7 +218,7 @@ static void terminal_line_replaced(void)
putchar(' ');
}
/* draw new line */
- printf("\r>%s", line_buf);
+ printf("\r%s%s", prompt, line_buf);
/* set up indexes to new line */
line_len = strlen(line_buf);
line_buf_ix = line_len;
@@ -343,8 +345,7 @@ void terminal_process_char(int c, void (*process_line)(char *line))
break;
case KEY_HOME:
/* move to beginning of line and update position */
- putchar('\r');
- putchar('>');
+ printf("\r%s", prompt);
line_buf_ix = 0;
break;
case KEY_END:
@@ -446,10 +447,12 @@ void terminal_process_char(int c, void (*process_line)(char *line))
line_index = -1;
/* print new line */
putchar(c);
+ prompt = "";
process_line(line_buf);
/* clear current line */
line_buf[0] = '\0';
- putchar('>');
+ prompt = prompt_buf;
+ printf("%s", prompt);
break;
case '\t':
/* tab processing */
@@ -533,5 +536,5 @@ void terminal_setup(void)
tcgetattr(0, &tios);
tios.c_lflag &= ~(ICANON | ECHO);
tcsetattr(0, TCSANOW, &tios);
- putchar('>');
+ printf("%s", prompt);
}
--
1.7.9.5
This patch adds help and quit commands.
It also adds tab completion for commands (it used to work
for interfaces).
---
android/client/haltest.c | 151 ++++++++++++++++++++++++++++++++++------
android/client/if-main.h | 6 ++
android/client/tabcompletion.c | 151 ++++++++++++++++++++++++++++------------
3 files changed, 240 insertions(+), 68 deletions(-)
diff --git a/android/client/haltest.c b/android/client/haltest.c
index 6b37f33..4864de1 100644
--- a/android/client/haltest.c
+++ b/android/client/haltest.c
@@ -34,6 +34,31 @@ const struct interface *interfaces[] = {
NULL
};
+static struct method commands[];
+
+struct method *get_method(struct method *methods, const char *name)
+{
+ while (strcmp(methods->name, "") != 0) {
+ if (strcmp(methods->name, name) == 0)
+ return methods;
+ methods++;
+ }
+ return NULL;
+}
+
+/* function returns interface of given name or NULL if not found */
+const struct interface *get_interface(const char *name)
+{
+ int i;
+
+ for (i = 0; interfaces[i] != NULL; ++i) {
+ if (strcmp(interfaces[i]->name, name) == 0)
+ break;
+ }
+
+ return interfaces[i];
+}
+
int haltest_error(const char *format, ...)
{
va_list args;
@@ -64,6 +89,95 @@ int haltest_warn(const char *format, ...)
return ret;
}
+static void help_print_interface(const struct interface *i)
+{
+ struct method *m;
+
+ for (m = i->methods; strcmp(m->name, "") != 0; m++)
+ haltest_info("%s %s %s\n", i->name, m->name,
+ (m->help ? m->help : ""));
+}
+
+/* Help completion */
+static void help_c(int argc, const char **argv,
+ enum_func *penum_func, void **puser)
+{
+ if (argc == 2)
+ *penum_func = interface_name;
+}
+
+/* Help execution */
+static void help_p(int argc, const char **argv)
+{
+ const struct method *m = commands;
+ const struct interface **ip = interfaces;
+ const struct interface *i;
+
+ if (argc == 1) {
+ terminal_print("haltest allows to call Android HAL methods.\n");
+ terminal_print("\nAvailable commands:\n");
+ while (0 != strcmp(m->name, "")) {
+ terminal_print("\t%s %s\n", m->name,
+ (m->help ? m->help : ""));
+ m++;
+ }
+ terminal_print("\nAvailable interfaces to use:\n");
+ while (NULL != *ip) {
+ terminal_print("\t%s\n", (*ip)->name);
+ ip++;
+ }
+ terminal_print("\nTo get help on methods for each interface type:\n");
+ terminal_print("\n\thelp <inerface>\n");
+ terminal_print("\nBasic scenario:\n\tadapter init\n");
+ terminal_print("\tadapter enable\n\tadapter start_discovery\n");
+ terminal_print("\tadapter get_profile_interface handsfree\n");
+ terminal_print("\thandsfree init\n\n");
+ return;
+ }
+ i = get_interface(argv[1]);
+ if (i == NULL) {
+ haltest_error("No such interface\n");
+ return;
+ }
+ help_print_interface(i);
+}
+
+/* quit/exit execution */
+static void quit_p(int argc, const char **argv)
+{
+ exit(0);
+}
+
+/* Commands available without interface */
+static struct method commands[] = {
+ STD_METHODCH(help, "[<interface>]"),
+ STD_METHOD(quit),
+ METHOD("exit", quit_p, NULL, NULL),
+ END_METHOD
+};
+
+/* Gets comman by name */
+struct method *get_command(const char *name)
+{
+ return get_method(commands, name);
+}
+
+/* Function to enumerate interface names */
+const char *interface_name(void *v, int i)
+{
+ return interfaces[i] ? interfaces[i]->name : NULL;
+}
+
+/* Function to enumerate command and interface names */
+const char *command_name(void *v, int i)
+{
+ int cmd_cnt = (int) (sizeof(commands)/sizeof(commands[0]) - 1);
+ if (i >= cmd_cnt)
+ return interface_name(v, i - cmd_cnt);
+ else
+ return commands[i].name;
+}
+
/*
* This function changes input parameter line_buffer so it has
* null termination after each token (due to strtok)
@@ -91,7 +205,7 @@ static void process_line(char *line_buffer)
char *argv[10];
int argc;
int i = 0;
- int j;
+ struct method *m;
argc = command_line_to_argv(line_buffer, argv, 10);
if (argc < 1)
@@ -103,32 +217,23 @@ static void process_line(char *line_buffer)
continue;
}
if (argc < 2 || strcmp(argv[1], "?") == 0) {
- struct method *m = &interfaces[i]->methods[0];
- while (strcmp(m->name, "")) {
- haltest_info("%s %s %s\n", argv[0],
- m->name,
- (m->help ? m->help : ""));
- m++;
- }
+ help_print_interface(interfaces[i]);
return;
}
- j = 0;
- while (strcmp(interfaces[i]->methods[j].name, "")) {
- if (strcmp(interfaces[i]->methods[j].name, argv[1])) {
- j++;
- continue;
- }
- interfaces[i]->methods[j].func(argc,
- (const char **)argv);
- break;
+ m = get_method(interfaces[i]->methods, argv[1]);
+ if (m != NULL) {
+ m->func(argc, (const char **) argv);
+ return;
}
- if (strcmp(interfaces[i]->methods[j].name, "") == 0)
- printf("No function %s found\n", argv[1]);
- break;
+ haltest_error("No function %s found\n", argv[1]);
+ return;
}
-
- if (interfaces[i] == NULL)
- printf("No such interface %s\n", argv[0]);
+ /* No interface, try commands */
+ m = get_command(argv[0]);
+ if (m == NULL)
+ haltest_error("No such command %s\n", argv[0]);
+ else
+ m->func(argc, (const char **) argv);
}
/* called when there is something on stdin */
diff --git a/android/client/if-main.h b/android/client/if-main.h
index b6bbf05..6d2b0cb 100644
--- a/android/client/if-main.h
+++ b/android/client/if-main.h
@@ -107,8 +107,14 @@ int haltest_warn(const char *format, ...);
* Enumerator for discovered devices, to be used as tab completion enum_func
*/
const char *enum_devices(void *v, int i);
+const char *interface_name(void *v, int i);
+const char *command_name(void *v, int i);
void add_remote_device(const bt_bdaddr_t *addr);
+const struct interface *get_interface(const char *name);
+struct method *get_method(struct method *methods, const char *name);
+struct method *get_command(const char *name);
+
/* Helper macro for executing function on interface and printing BT_STATUS */
#define EXEC(f, ...) \
{ \
diff --git a/android/client/tabcompletion.c b/android/client/tabcompletion.c
index e9c9921..2b95591 100644
--- a/android/client/tabcompletion.c
+++ b/android/client/tabcompletion.c
@@ -29,33 +29,16 @@ typedef struct split_arg {
char ntcopy[1]; /* null terminated copy of argument */
} split_arg_t;
-/* function returns interface of given name or NULL if not found */
-static const struct interface *get_interface(const char *name)
-{
- int i;
-
- for (i = 0; interfaces[i] != NULL; ++i) {
- if (strcmp(interfaces[i]->name, name) == 0)
- break;
- }
-
- return interfaces[i];
-}
-
/* function returns method of given name or NULL if not found */
-static const struct method *get_method(const char *iname, const char *mname)
+static const struct method *get_interface_method(const char *iname,
+ const char *mname)
{
- int i;
const struct interface *iface = get_interface(iname);
if (iface == NULL)
return NULL;
- for (i = 0; iface->methods[i].name[0]; ++i) {
- if (0 == strcmp(iface->methods[i].name, mname))
- return &iface->methods[i];
- }
- return NULL;
+ return get_method(iface->methods, mname);
}
/* prints matching elements */
@@ -113,12 +96,6 @@ static int split_command(const char *line_buffer, int size,
return argc;
}
-/* Function to enumerate interface names */
-static const char *interface_name(void *v, int i)
-{
- return interfaces[i] ? interfaces[i]->name : NULL;
-}
-
/* Function to enumerate method names */
static const char *methods_name(void *v, int i)
{
@@ -142,7 +119,7 @@ struct command_completion_args {
/*
* complete command line
*/
-static void command_completion(struct command_completion_args *args)
+static void tab_completion(struct command_completion_args *args)
{
const char *name = args->typed;
const int len = strlen(name);
@@ -211,15 +188,15 @@ static void command_completion(struct command_completion_args *args)
}
/* interface completion */
-static void interface_completion(split_arg_t *arg)
+static void command_completion(split_arg_t *arg)
{
struct command_completion_args args = {
.arg = arg,
.typed = arg->ntcopy,
- .func = interface_name
+ .func = command_name
};
- command_completion(&args);
+ tab_completion(&args);
}
/* method completion */
@@ -235,17 +212,86 @@ static void method_completion(const struct interface *iface, split_arg_t *arg)
if (iface == NULL)
return;
- command_completion(&args);
+ tab_completion(&args);
+}
+
+static const char *bold = "\x1b[1m";
+static const char *normal = "\x1b[0m";
+
+static bool find_nth_argument(const char *str, int n,
+ const char **s, const char **e)
+{
+ const char *p = str;
+ int argc = 0;
+ *e = NULL;
+
+ while (p != NULL && *p != 0) {
+
+ while (isspace(*p))
+ ++p;
+
+ if (n == argc)
+ *s = p;
+
+ if (*p == '[') {
+ p = strchr(p, ']');
+ if (p != NULL)
+ *e = ++p;
+ } else if (*p == '<') {
+ p = strchr(p, '>');
+ if (p != NULL)
+ *e = ++p;
+ } else {
+ *e = strchr(p, ' ');
+ if (*e == NULL)
+ *e = p + strlen(p);
+ p = *e;
+ }
+
+ if (n == argc)
+ break;
+
+ argc++;
+ *e = NULL;
+ }
+ return *e != NULL;
}
/* prints short help on method for interface */
static void method_help(struct command_completion_args *args)
{
+ int argc;
+ const split_arg_t *arg = args->arg;
+ const char *sb = NULL;
+ const char *eb = NULL;
+ const char *arg1 = "";
+ int arg1_size = 0; /* size of method field (for methods > 0) */
+
if (args->user_help == NULL)
return;
- haltest_info("%s %s %s\n", args->arg->ntcopy,
- args->arg->next->ntcopy, args->user_help);
+ for (argc = 0; arg != NULL; argc++)
+ arg = arg->next;
+
+ /* Check if this is method from interface */
+ if (get_command(args->arg->ntcopy) == NULL) {
+ /* if so help is missing interface and method name */
+ arg1 = args->arg->next->ntcopy;
+ arg1_size = strlen(arg1) + 1;
+ }
+
+ find_nth_argument(args->user_help, argc - (arg1_size ? 3 : 2),
+ &sb, &eb);
+
+ if (eb != NULL)
+ haltest_info("%s %-*s%.*s%s%.*s%s%s\n", args->arg->ntcopy,
+ arg1_size, arg1,
+ sb - (const char *) args->user_help,
+ args->user_help,
+ bold, eb - sb, sb, normal, eb);
+ else
+ haltest_info("%s %-*s%s\n", args->arg->ntcopy,
+ arg1_size, arg1, args->user_help);
}
/* So we have empty enumeration */
@@ -254,10 +300,15 @@ static const char *return_null(void *user, int i)
return NULL;
}
-/* parameter completion function */
-static void param_completion(int argc, const split_arg_t *arg)
+/*
+ * parameter completion function
+ * argc - number of elements in arg list
+ * arg - list of arguments
+ * megthod - method to get completion from (can be NULL)
+ */
+static void param_completion(int argc, const split_arg_t *arg,
+ const struct method *method, int hlpix)
{
- const struct method *method;
int i;
const char *argv[argc];
const split_arg_t *tmp = arg;
@@ -272,9 +323,6 @@ static void param_completion(int argc, const split_arg_t *arg)
tmp = tmp->next;
}
- /* Find method for <interface, name> pair */
- method = get_method(argv[0], argv[1]);
-
if (method != NULL && method->complete != NULL) {
/* ask method for completion function */
method->complete(argc, argv, &args.func, &args.user);
@@ -286,7 +334,7 @@ static void param_completion(int argc, const split_arg_t *arg)
args.help = method_help;
args.user_help = (void *) method->help;
- command_completion(&args);
+ tab_completion(&args);
}
}
@@ -300,14 +348,27 @@ void process_tab(const char *line, int len)
{
int argc;
static split_arg_t buf[(LINE_BUF_MAX * 2) / sizeof(split_arg_t)];
+ const struct method *method;
argc = split_command(line, len, buf, sizeof(buf));
tab_hit_count++;
- if (argc == 1)
- interface_completion(buf);
- else if (argc == 2)
+ if (argc == 0)
+ return;
+
+ if (argc == 1) {
+ command_completion(buf);
+ return;
+ }
+ method = get_command(buf[0].ntcopy);
+ if (method != NULL) {
+ param_completion(argc, buf, method, 1);
+ } else if (argc == 2) {
method_completion(get_interface(buf[0].ntcopy), buf);
- else if (argc > 2)
- param_completion(argc, buf);
+ } else {
+ /* Find method for <interface, name> pair */
+ method = get_interface_method(buf[0].ntcopy,
+ buf[0].next->ntcopy);
+ param_completion(argc, buf, method, 2);
+ }
}
--
1.7.9.5
This patch adds handling of Ctrl-C so it does not break tool.
To exit tool Ctrl-D is used on empty command line.
Ctrl-D on not empty command line works like Delete key.
---
android/client/terminal.c | 83 +++++++++++++++++++++++++++++++++------------
1 file changed, 62 insertions(+), 21 deletions(-)
diff --git a/android/client/terminal.c b/android/client/terminal.c
index fb4d5d8..a57068a 100644
--- a/android/client/terminal.c
+++ b/android/client/terminal.c
@@ -20,6 +20,7 @@
#include <ctype.h>
#include <stdbool.h>
#include <termios.h>
+#include <stdlib.h>
#include "terminal.h"
#include "history.h"
@@ -90,6 +91,10 @@ static const struct ansii_sequence ansii_sequnces[] = {
{ 0, NULL }
};
+#define KEY_SEQUNCE_NOT_FINISHED -1
+#define KEY_C_C 3
+#define KEY_C_D 4
+
#define isseqence(c) ((c) == 0x1B)
/*
@@ -224,6 +229,30 @@ static void terminal_line_replaced(void)
line_buf_ix = line_len;
}
+static void terminal_clear_line(void)
+{
+ line_buf[0] = '\0';
+ terminal_line_replaced();
+}
+
+static void terminal_delete_char(void)
+{
+ /* delete character under cursor if not at the very end */
+ if (line_buf_ix >= line_len)
+ return;
+ /*
+ * Prepare buffer with one character missing
+ * trailing 0 is moved
+ */
+ line_len--;
+ memmove(line_buf + line_buf_ix, line_buf + line_buf_ix + 1,
+ line_len - line_buf_ix + 1);
+ /* print rest of line from current cursor position */
+ printf("%s \b", line_buf + line_buf_ix);
+ /* move back cursor */
+ terminal_move_cursor(line_buf_ix - line_len);
+}
+
/*
* Function tries to replace current line with specified line in history
* new_line_index - new line to show, -1 to show oldest
@@ -288,7 +317,7 @@ static int terminal_convert_sequence(int c)
/* Is ansii sequence detected by 0x1B ? */
if (isseqence(c)) {
current_sequence_len++;
- return 0;
+ return KEY_SEQUNCE_NOT_FINISHED;
}
return c;
}
@@ -307,7 +336,7 @@ static int terminal_convert_sequence(int c)
return ansii_sequnces[i].code;
}
/* partial match (not whole sequence yet) */
- return 0;
+ return KEY_SEQUNCE_NOT_FINISHED;
}
terminal_print("ansii char 0x%X %c\n", c);
/*
@@ -326,7 +355,7 @@ void terminal_process_char(int c, void (*process_line)(char *line))
c = terminal_convert_sequence(c);
switch (c) {
- case 0:
+ case KEY_SEQUNCE_NOT_FINISHED:
break;
case KEY_LEFT:
/* if not at the beginning move to previous character */
@@ -358,21 +387,7 @@ void terminal_process_char(int c, void (*process_line)(char *line))
}
break;
case KEY_DELETE:
- /* delete character under cursor if not at the very end */
- if (line_buf_ix >= line_len)
- break;
- /*
- * Prepare buffer with one character missing
- * trailing 0 is moved
- */
- line_len--;
- memmove(line_buf + line_buf_ix,
- line_buf + line_buf_ix + 1,
- line_len - line_buf_ix + 1);
- /* print rest of line from current cursor position */
- printf("%s \b", line_buf + line_buf_ix);
- /* move back cursor */
- terminal_move_cursor(line_buf_ix - line_len);
+ terminal_delete_char();
break;
case KEY_CLEFT:
/*
@@ -495,6 +510,17 @@ void terminal_process_char(int c, void (*process_line)(char *line))
/* Search history backward */
terminal_match_hitory(true);
break;
+ case KEY_C_C:
+ terminal_clear_line();
+ break;
+ case KEY_C_D:
+ if (line_len > 0) {
+ terminal_delete_char();
+ } else {
+ puts("");
+ exit(0);
+ }
+ break;
default:
if (!isprint(c)) {
/*
@@ -528,13 +554,28 @@ void terminal_process_char(int c, void (*process_line)(char *line))
}
}
+static struct termios origianl_tios;
+
+static void terminal_cleanup(void)
+{
+ tcsetattr(0, TCSANOW, &origianl_tios);
+}
+
void terminal_setup(void)
{
struct termios tios;
+ tcgetattr(0, &origianl_tios);
+ tios = origianl_tios;
- /* Turn off echo since all editing is done by hand */
- tcgetattr(0, &tios);
- tios.c_lflag &= ~(ICANON | ECHO);
+ /*
+ * Turn off echo since all editing is done by hand,
+ * Ctrl-c handled internaly
+ */
+ tios.c_lflag &= ~(ICANON | ECHO | BRKINT | IGNBRK);
tcsetattr(0, TCSANOW, &tios);
+
+ /* Restore terminal at exit */
+ atexit(terminal_cleanup);
+
printf("%s", prompt);
}
--
1.7.9.5