From: Jerzy Kasenberg <jerzy.kasenberg@tieto.com>
To: <linux-bluetooth@vger.kernel.org>
Cc: Jerzy Kasenberg <jerzy.kasenberg@tieto.com>
Subject: [PATCH v3 3/5] android: Add history to line editor in haltest
Date: Wed, 16 Oct 2013 16:00:10 +0200 [thread overview]
Message-ID: <1381932012-29641-4-git-send-email-jerzy.kasenberg@tieto.com> (raw)
In-Reply-To: <1381932012-29641-1-git-send-email-jerzy.kasenberg@tieto.com>
Added simple history to editor to save time.
---
android/Android.mk | 1 +
android/client/history.c | 98 +++++++++++++++++++++++++++++++++++++++++
android/client/history.h | 21 +++++++++
android/client/terminal.c | 107 +++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 227 insertions(+)
create mode 100644 android/client/history.c
create mode 100644 android/client/history.h
diff --git a/android/Android.mk b/android/Android.mk
index 2eac3ec..d49056c 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -60,6 +60,7 @@ LOCAL_SRC_FILES := \
client/haltest.c \
client/pollhandler.c \
client/terminal.c \
+ client/history.c \
LOCAL_SHARED_LIBRARIES := libhardware
diff --git a/android/client/history.c b/android/client/history.c
new file mode 100644
index 0000000..90d9952
--- /dev/null
+++ b/android/client/history.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2013 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include "history.h"
+
+/*
+ * Very simple history storage for easy usage of tool
+ */
+
+#define HISTORY_DEPTH 20
+#define LINE_SIZE 100
+static char lines[HISTORY_DEPTH][LINE_SIZE];
+static int last_line = 0;
+static int history_size = 0;
+
+/* TODO: Storing history not implemented yet */
+void history_store(const char *filename)
+{
+}
+
+/* Restoring history from file */
+void history_restore(const char *filename)
+{
+ char line[1000];
+ FILE *f = fopen(filename, "rt");
+
+ if (f == NULL)
+ return;
+
+ for (;;) {
+ if (fgets(line, 1000, f) != NULL) {
+ int l = strlen(line);
+ while (l > 0 && isspace(line[--l]))
+ line[l] = 0;
+ if (l > 0)
+ history_add_line(line);
+ } else
+ break;
+ }
+ fclose(f);
+}
+
+/* Add new line to history buffer */
+void history_add_line(const char *line)
+{
+ if (line == NULL || strlen(line) == 0)
+ return;
+
+ if (strcmp(line, lines[last_line]) == 0)
+ return;
+
+ last_line = (last_line + 1) % HISTORY_DEPTH;
+ strncpy(&lines[last_line][0], line, LINE_SIZE - 1);
+ if (history_size < HISTORY_DEPTH)
+ history_size++;
+}
+
+/*
+ * Get n-th line from history
+ * 0 - means latest
+ * -1 - means oldest
+ * return -1 if there is no such line
+ */
+int history_get_line(int n, char *buf, int buf_size)
+{
+ if (n == -1)
+ n = history_size - 1;
+
+ if (n >= history_size || buf_size == 0 || n < 0)
+ return -1;
+
+ strncpy(buf,
+ &lines[(HISTORY_DEPTH + last_line - n) % HISTORY_DEPTH][0],
+ buf_size - 1);
+ buf[buf_size - 1] = 0;
+
+ return n;
+}
+
diff --git a/android/client/history.h b/android/client/history.h
new file mode 100644
index 0000000..26085b5
--- /dev/null
+++ b/android/client/history.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2013 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+void history_store(const char *filename);
+void history_restore(const char *filename);
+void history_add_line(const char *line);
+int history_get_line(int n, char *buf, int buf_size);
diff --git a/android/client/terminal.c b/android/client/terminal.c
index 95108a0..9352328 100644
--- a/android/client/terminal.c
+++ b/android/client/terminal.c
@@ -22,6 +22,7 @@
#include <termios.h>
#include "terminal.h"
+#include "history.h"
/*
* Character sequences recognized by code in this file
@@ -107,6 +108,9 @@ static int line_buf_ix = 0;
/* current length of input line */
static int line_len = 0;
+/* line index used for fetching lines from history */
+static int line_index = 0;
+
/*
* Moves cursor to right or left
*
@@ -189,6 +193,87 @@ int terminal_vprint(const char *format, va_list args)
}
/*
+ * Call this when text in line_buf was changed
+ * and line needs to be redrawn
+ */
+static void terminal_line_replaced(void)
+{
+ int len = strlen(line_buf);
+
+ /* line is shorter that previous */
+ if (len < line_len) {
+ /* if new line is shorter move cursor to end of new end */
+ while (line_buf_ix > len) {
+ putchar('\b');
+ line_buf_ix--;
+ }
+ /* If cursor was not at the end, move it to the end */
+ if (line_buf_ix < line_len)
+ printf("%.*s", line_len - line_buf_ix,
+ line_buf + line_buf_ix);
+ /* over write end of previous line */
+ while (line_len >= len++)
+ putchar(' ');
+ }
+ /* draw new line */
+ printf("\r>%s", line_buf);
+ /* set up indexes to new line */
+ line_len = strlen(line_buf);
+ 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
+ */
+static void terminal_get_line_from_history(int new_line_index)
+{
+ new_line_index = history_get_line(new_line_index,
+ line_buf, LINE_BUF_MAX);
+
+ if (new_line_index >= 0) {
+ terminal_line_replaced();
+ line_index = new_line_index;
+ }
+}
+
+/*
+ * Function searches history back or forward for command line that starts
+ * with characters up to cursor position
+ *
+ * back - true - searches backward
+ * back - false - searches forward (more recent commands)
+ */
+static void terminal_match_hitory(bool back)
+{
+ char buf[line_buf_ix + 1];
+ int line;
+ int matching_line = -1;
+ int dir = back ? 1 : -1;
+
+ line = line_index + dir;
+ while (matching_line == -1 && line >= 0) {
+ int new_line_index;
+
+ new_line_index = history_get_line(line, buf, line_buf_ix + 1);
+ if (new_line_index < 0)
+ break;
+
+ if (0 == strncmp(line_buf, buf, line_buf_ix))
+ matching_line = line;
+ line += dir;
+ }
+
+ if (matching_line >= 0) {
+ int pos = line_buf_ix;
+ terminal_get_line_from_history(matching_line);
+ /* move back to cursor position to origianl place */
+ line_buf_ix = pos;
+ terminal_move_cursor(pos - line_len);
+ }
+}
+
+/*
* Converts terminal character sequences to single value representing
* keyboard keys
*/
@@ -335,13 +420,30 @@ void terminal_process_char(int c, void (*process_line)(char *line))
printf("%.*s", (int) (line_buf_ix - old_pos),
line_buf + old_pos);
break;
+ case KEY_SUP:
+ terminal_get_line_from_history(-1);
+ break;
+ case KEY_SDOWN:
+ if (line_index > 0)
+ terminal_get_line_from_history(0);
+ break;
case KEY_UP:
+ terminal_get_line_from_history(line_index + 1);
+ break;
case KEY_DOWN:
+ if (line_index > 0)
+ terminal_get_line_from_history(line_index - 1);
break;
case '\n':
case '\r':
+ /*
+ * On new line add line to history
+ * forget history position
+ */
+ history_add_line(line_buf);
line_len = 0;
line_buf_ix = 0;
+ line_index = -1;
/* print new line */
putchar(c);
process_line(line_buf);
@@ -383,7 +485,12 @@ void terminal_process_char(int c, void (*process_line)(char *line))
case KEY_MDOWN:
case KEY_STAB:
case KEY_M_n:
+ /* Search history forward */
+ terminal_match_hitory(false);
+ break;
case KEY_M_p:
+ /* Search history backward */
+ terminal_match_hitory(true);
break;
default:
if (!isprint(c)) {
--
1.7.9.5
next prev parent reply other threads:[~2013-10-16 14:00 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-10-16 14:00 [PATCH v3 0/5] Stack independent BT HAL test tool Jerzy Kasenberg
2013-10-16 14:00 ` [PATCH v3 1/5] android: Add haltest skeleton Jerzy Kasenberg
2013-10-16 14:00 ` [PATCH v3 2/5] android: Add line editing to haltest Jerzy Kasenberg
2013-10-16 14:00 ` Jerzy Kasenberg [this message]
2013-10-16 14:00 ` [PATCH v3 4/5] android: Add text conversion helpers " Jerzy Kasenberg
2013-10-16 14:00 ` [PATCH v3 5/5] android: Add calls to adapter methods in haltest Jerzy Kasenberg
2013-10-16 15:34 ` [PATCH v3 0/5] Stack independent BT HAL test tool Johan Hedberg
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1381932012-29641-4-git-send-email-jerzy.kasenberg@tieto.com \
--to=jerzy.kasenberg@tieto.com \
--cc=linux-bluetooth@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox