linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC v4 0/1] i-search functionality for mconf
@ 2018-06-08 18:46 Dirk Gouders
  2018-06-08 18:46 ` [RFC v4 1/1] " Dirk Gouders
  2018-06-08 21:56 ` [RFC v4 0/1] " Sam Ravnborg
  0 siblings, 2 replies; 5+ messages in thread
From: Dirk Gouders @ 2018-06-08 18:46 UTC (permalink / raw)
  To: Masahiro Yamada, Randy Dunlap, Linux Kbuild mailing list,
	Linux Kernel Mailing List, Segher Boessenkool, Sam Ravnborg
  Cc: Dirk Gouders

Hello,

this version is a prototype of the idea, Sam suggested -- I hope I
undestood it correctly.

This is a remarkable change to mconf in it's behavior; mainly it now
differentiates two focuses and operates differently, depending on the
focus.  When the focus is on the menu, mconf is in i-search mode, for
a detailed description see 1/1.

As stated earlier, this is just a prototype, documentation is missing
and the code is not ready for a real commit.

Dirk

Dirk Gouders (1):
  Isearch functionality for mconf

 scripts/kconfig/lxdialog/dialog.h  |   3 +
 scripts/kconfig/lxdialog/menubox.c | 207 +++++++++++++++++++++++++++++++++----
 2 files changed, 189 insertions(+), 21 deletions(-)

-- 
2.16.4

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [RFC v4 1/1] i-search functionality for mconf
  2018-06-08 18:46 [RFC v4 0/1] i-search functionality for mconf Dirk Gouders
@ 2018-06-08 18:46 ` Dirk Gouders
  2018-06-09  0:59   ` Randy Dunlap
  2018-06-08 21:56 ` [RFC v4 0/1] " Sam Ravnborg
  1 sibling, 1 reply; 5+ messages in thread
From: Dirk Gouders @ 2018-06-08 18:46 UTC (permalink / raw)
  To: Masahiro Yamada, Randy Dunlap, Linux Kbuild mailing list,
	Linux Kernel Mailing List, Segher Boessenkool, Sam Ravnborg
  Cc: Dirk Gouders

This patch prototypes isearch functionality for mconf based on an idea of
Sam Ravnborg:

* mconf now distinguishes if the focus is on the menu items or the
  buttons below it.

* At startup focus is on the menu items and alphanumeric
  characters or space entered are used to form a string that is
  searched for.

* BACKSPACE is used to remove the last character of the search string.

* ENTER can be used to enter a submenu.

* Horizontal arrow keys put focus on the buttons with the known
  behavior.

* The TAB key is now exclusively used to toggle the focus.

* Vertical arrow keys work anywhere.

* When the focus is on the buttons, all keys (e.g. hotkeys) work the
  same as before this change.

* '\' can be used to search for other occurences of an already entered
  string.

* To use y|n|m on an item, focus has to be on the buttons.

An example to navigate into the USB support menu under Device Drivers:

   1) de		# Navigates to the item "Device Drivers"
   2) ENTER		# Enter the submenu
   3) USB		# Navigate to the item "USB support"
   4) ENTER		# Enter the submenu

---
 scripts/kconfig/lxdialog/dialog.h  |   3 +
 scripts/kconfig/lxdialog/menubox.c | 207 +++++++++++++++++++++++++++++++++----
 2 files changed, 189 insertions(+), 21 deletions(-)

diff --git a/scripts/kconfig/lxdialog/dialog.h b/scripts/kconfig/lxdialog/dialog.h
index 0b00be5abaa6..02b036435919 100644
--- a/scripts/kconfig/lxdialog/dialog.h
+++ b/scripts/kconfig/lxdialog/dialog.h
@@ -50,6 +50,8 @@
 #define TR(params) _tracef params
 
 #define KEY_ESC 27
+#define KEY_CTRL_S 19
+#define KEY_ENTR 10
 #define TAB 9
 #define MAX_LEN 2048
 #define BUF_SIZE (10*1024)
@@ -238,6 +240,7 @@ int dialog_checklist(const char *title, const char *prompt, int height,
 		     int width, int list_height);
 int dialog_inputbox(const char *title, const char *prompt, int height,
 		    int width, const char *init);
+int do_isearch(char *str, int choice, int scroll);
 
 /*
  * This is the base for fictitious keys, which activate
diff --git a/scripts/kconfig/lxdialog/menubox.c b/scripts/kconfig/lxdialog/menubox.c
index d70cab36137e..e49280115b52 100644
--- a/scripts/kconfig/lxdialog/menubox.c
+++ b/scripts/kconfig/lxdialog/menubox.c
@@ -56,10 +56,17 @@
  * fscanf would read in 'scroll', and eventually that value would get used.
  */
 
+#include <string.h>
 #include "dialog.h"
 
+#define ISEARCH_LEN 32
+#define ISEARCH_INDICATOR_LEN (ISEARCH_LEN + 8)
+static char isearch_str[ISEARCH_LEN] = "";
+
 static int menu_width, item_x;
 
+static int focus_on_buttons;
+
 /*
  * Print menu item
  */
@@ -85,7 +92,10 @@ static void do_print_item(WINDOW * win, const char *item, int line_y,
 #else
 	wclrtoeol(win);
 #endif
-	wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr);
+	if (focus_on_buttons)
+		wattrset(win, selected ? A_UNDERLINE : dlg.item.atr);
+	else
+		wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr);
 	mvwaddstr(win, line_y, item_x, menu_item);
 	if (hotkey) {
 		wattrset(win, selected ? dlg.tag_key_selected.atr
@@ -105,6 +115,32 @@ do {									\
 	do_print_item(menu, item_str(), choice, selected, !item_is_tag(':')); \
 } while (0)
 
+
+/*
+* Print the isearch indicator.
+*/
+static void print_isearch(WINDOW * win, int y, int x, int height, bool isearch)
+{
+	unsigned char i = 0;
+
+	wmove(win, y, x);
+
+	y = y + height + 1;
+	wmove(win, y, x);
+
+	if (isearch) {
+		wattrset(win, dlg.button_key_inactive.atr);
+		waddstr(win, "isearch: ");
+		waddstr(win, isearch_str);
+		i = ISEARCH_INDICATOR_LEN - strlen(isearch_str);
+	}
+
+	wattrset(win, dlg.menubox_border.atr);
+
+	for ( ; i < ISEARCH_INDICATOR_LEN; i++ )
+		waddch(win, ACS_HLINE);
+}
+
 /*
  * Print the scroll indicators.
  */
@@ -157,6 +193,9 @@ static void print_buttons(WINDOW * win, int height, int width, int selected)
 	int x = width / 2 - 28;
 	int y = height - 2;
 
+	if (!focus_on_buttons)
+		selected = -1;
+
 	print_button(win, "Select", y, x, selected == 0);
 	print_button(win, " Exit ", y, x + 12, selected == 1);
 	print_button(win, " Help ", y, x + 24, selected == 2);
@@ -178,6 +217,32 @@ static void do_scroll(WINDOW *win, int *scroll, int n)
 	wrefresh(win);
 }
 
+/*
+ * Incremental search for text in dialog menu entries.
+ * The search operates as a ring search, continuing at the top after
+ * the last entry has been visited.
+ *
+ * Returned is -1 if no match was found, else the absolute index of
+ * the matching item.
+ */
+int do_isearch(char *str, int choice, int scroll)
+{
+	int found = 0;
+	int i;
+
+	for (i = 0; i < item_count(); i++) {
+		item_set((choice + scroll + i)%item_count());
+		if (strcasestr(item_str(), str)) {
+			found = 1;
+			break;
+		}
+	}
+
+	if (found)
+		return (choice + scroll + i)%item_count();
+	return -1;
+}
+
 /*
  * Display a menu for choosing among a number of options
  */
@@ -275,6 +340,7 @@ int dialog_menu(const char *title, const char *prompt,
 	print_arrows(dialog, item_count(), scroll,
 		     box_y, box_x + item_x + 1, menu_height);
 
+	print_isearch(dialog, box_y, box_x + item_x + 5, menu_height, !focus_on_buttons);
 	print_buttons(dialog, height, width, 0);
 	wmove(menu, choice, item_x + 1);
 	wrefresh(menu);
@@ -285,22 +351,27 @@ int dialog_menu(const char *title, const char *prompt,
 		if (key < 256 && isalpha(key))
 			key = tolower(key);
 
-		if (strchr("ynmh", key))
-			i = max_choice;
-		else {
-			for (i = choice + 1; i < max_choice; i++) {
-				item_set(scroll + i);
-				j = first_alpha(item_str(), "YyNnMmHh");
-				if (key == tolower(item_str()[j]))
-					break;
-			}
-			if (i == max_choice)
-				for (i = 0; i < max_choice; i++) {
+		if (focus_on_buttons) {
+			/*
+			 * Find item matching hot key.
+			 */
+			if (strchr("ynmh", key))
+				i = max_choice;
+			else {
+				for (i = choice + 1; i < max_choice; i++) {
 					item_set(scroll + i);
 					j = first_alpha(item_str(), "YyNnMmHh");
 					if (key == tolower(item_str()[j]))
 						break;
 				}
+				if (i == max_choice)
+					for (i = 0; i < max_choice; i++) {
+						item_set(scroll + i);
+						j = first_alpha(item_str(), "YyNnMmHh");
+						if (key == tolower(item_str()[j]))
+							break;
+					}
+			}
 		}
 
 		if (item_count() != 0 &&
@@ -370,16 +441,117 @@ int dialog_menu(const char *title, const char *prompt,
 			continue;	/* wait for another key press */
 		}
 
+		if (!focus_on_buttons) {
+			i = -1;
+
+			if (key == '\n') {
+				/* save scroll info */
+				*s_scroll = scroll;
+				delwin(menu);
+				delwin(dialog);
+				item_set(scroll + choice);
+				item_set_selected(1);
+				isearch_str[0] = '\0';
+				return 0; /* 0 means first button "Select" */
+			}
+
+			if ( key == KEY_BACKSPACE && isearch_str[0] ) {
+				isearch_str[i = (strlen(isearch_str) - 1)] = '\0';
+				i = -1;
+			}
+
+			if (key < 256 && (isalnum(key) || key == ' ')) {
+				if (strlen(isearch_str) < ISEARCH_LEN - 1) {
+					isearch_str[i = strlen(isearch_str)] = key;
+					isearch_str[i+1] = '\0';
+				}
+
+				/* Remove highligt of current item */
+				print_item(scroll + choice, choice, FALSE);
+				i = do_isearch(isearch_str, choice, scroll);
+			}
+
+			if (key == '\\') {
+				/* Remove highligt of current item */
+				print_item(scroll + choice, choice, FALSE);
+				i = do_isearch(isearch_str, choice + 1, scroll);
+			}
+
+			/*
+			 * Handle matches
+			 */
+			if (i >= 0) {
+				i -= scroll;
+
+				if (i >= max_choice)
+					/*
+					 * Handle matches below the currently visible menu entries.
+					 */
+					while (i >= max_choice) {
+						do_scroll(menu, &scroll, 1);
+						i--;
+						print_item(max_choice + scroll - 1, max_choice - 1, false);
+					}
+				else if (i < 0)
+					/*
+					 * Handle matches higher in the menu (ring search).
+					 */
+					while (i < 0) {
+						do_scroll(menu, &scroll, -1);
+						i++;
+						print_item(scroll, 0, false);
+					}
+				choice = i;
+			} else {
+				i = choice;
+				goto a;
+			}
+
+			print_item(scroll + choice, choice, TRUE);
+			print_isearch(dialog, box_y, box_x + item_x + 5, menu_height, true);
+			print_arrows(dialog, item_count(), scroll,
+				     box_y, box_x + item_x + 1, menu_height);
+
+			wnoutrefresh(dialog);
+			wrefresh(menu);
+			i = max_choice;
+			continue;
+		}
+	a:
 		switch (key) {
-		case KEY_LEFT:
 		case TAB:
+			focus_on_buttons = 1 - focus_on_buttons;
+			print_isearch(dialog, box_y, box_x + item_x + 5, menu_height, !focus_on_buttons);
+
+			print_item(scroll + choice, choice, TRUE);
+			print_buttons(dialog, height, width, button);
+			wrefresh(menu);
+			break;
+		case KEY_LEFT:
 		case KEY_RIGHT:
+			focus_on_buttons = 1;
 			button = ((key == KEY_LEFT ? --button : ++button) < 0)
 			    ? 4 : (button > 4 ? 0 : button);
 
+			print_isearch(dialog, box_y, box_x + item_x + 5, menu_height, !focus_on_buttons);
+			print_item(scroll + choice, choice, TRUE);
 			print_buttons(dialog, height, width, button);
 			wrefresh(menu);
 			break;
+		case KEY_ESC:
+			key = on_key_esc(menu);
+			break;
+		case KEY_RESIZE:
+			on_key_resize();
+			delwin(menu);
+			delwin(dialog);
+			goto do_resize;
+		}
+
+		/*
+		 * Focus is on buttons, handle keys appropriately
+		 */
+		switch (key) {
 		case ' ':
 		case 's':
 		case 'y':
@@ -390,6 +562,7 @@ int dialog_menu(const char *title, const char *prompt,
 		case '?':
 		case 'z':
 		case '\n':
+			isearch_str[0] = '\0';
 			/* save scroll info */
 			*s_scroll = scroll;
 			delwin(menu);
@@ -421,14 +594,6 @@ int dialog_menu(const char *title, const char *prompt,
 		case 'x':
 			key = KEY_ESC;
 			break;
-		case KEY_ESC:
-			key = on_key_esc(menu);
-			break;
-		case KEY_RESIZE:
-			on_key_resize();
-			delwin(menu);
-			delwin(dialog);
-			goto do_resize;
 		}
 	}
 	delwin(menu);
-- 
2.16.4

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [RFC v4 0/1] i-search functionality for mconf
  2018-06-08 18:46 [RFC v4 0/1] i-search functionality for mconf Dirk Gouders
  2018-06-08 18:46 ` [RFC v4 1/1] " Dirk Gouders
@ 2018-06-08 21:56 ` Sam Ravnborg
  2018-06-09  7:40   ` Dirk Gouders
  1 sibling, 1 reply; 5+ messages in thread
From: Sam Ravnborg @ 2018-06-08 21:56 UTC (permalink / raw)
  To: Dirk Gouders
  Cc: Masahiro Yamada, Randy Dunlap, Linux Kbuild mailing list,
	Linux Kernel Mailing List, Segher Boessenkool

Hi Dirk.

On Fri, Jun 08, 2018 at 08:46:05PM +0200, Dirk Gouders wrote:
> Hello,
> 
> this version is a prototype of the idea, Sam suggested -- I hope I
> undestood it correctly.
> 
> This is a remarkable change to mconf in it's behavior; mainly it now
> differentiates two focuses and operates differently, depending on the
> focus.  When the focus is on the menu, mconf is in i-search mode, for
> a detailed description see 1/1.
> 
> As stated earlier, this is just a prototype, documentation is missing
> and the code is not ready for a real commit.

When trying this out it started to work as envisioned.
But somehw I manage to get stuck in the menus and cannot navigate to
the buttons.

Consider to remove the old short-cut for the menus.
(Most/all the first_alph thingy in menubox.c)
That will avoid two confliting navigations principles and likely
make the code simpler to read.

I am not sure, but maybe you can get rid of all the hotkey
support in print_item with this change too.

	Sam

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [RFC v4 1/1] i-search functionality for mconf
  2018-06-08 18:46 ` [RFC v4 1/1] " Dirk Gouders
@ 2018-06-09  0:59   ` Randy Dunlap
  0 siblings, 0 replies; 5+ messages in thread
From: Randy Dunlap @ 2018-06-09  0:59 UTC (permalink / raw)
  To: Dirk Gouders, Masahiro Yamada, Linux Kbuild mailing list,
	Linux Kernel Mailing List, Segher Boessenkool, Sam Ravnborg

On 06/08/2018 11:46 AM, Dirk Gouders wrote:
> This patch prototypes isearch functionality for mconf based on an idea of
> Sam Ravnborg:
> 
> * mconf now distinguishes if the focus is on the menu items or the
>   buttons below it.
> 
> * At startup focus is on the menu items and alphanumeric
>   characters or space entered are used to form a string that is
>   searched for.
> 
> * BACKSPACE is used to remove the last character of the search string.
> 
> * ENTER can be used to enter a submenu.
> 
> * Horizontal arrow keys put focus on the buttons with the known
>   behavior.
> 
> * The TAB key is now exclusively used to toggle the focus.
> 
> * Vertical arrow keys work anywhere.
> 
> * When the focus is on the buttons, all keys (e.g. hotkeys) work the
>   same as before this change.
> 
> * '\' can be used to search for other occurences of an already entered
>   string.
> 
> * To use y|n|m on an item, focus has to be on the buttons.
> 
> An example to navigate into the USB support menu under Device Drivers:
> 
>    1) de		# Navigates to the item "Device Drivers"
>    2) ENTER		# Enter the submenu
>    3) USB		# Navigate to the item "USB support"
>    4) ENTER		# Enter the submenu

Hi Dirk,

Much like Sam, I got locked in isearch mode.  The TAB key would not switch
into the buttons focus.  I had to kill it.


-- 
~Randy

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [RFC v4 0/1] i-search functionality for mconf
  2018-06-08 21:56 ` [RFC v4 0/1] " Sam Ravnborg
@ 2018-06-09  7:40   ` Dirk Gouders
  0 siblings, 0 replies; 5+ messages in thread
From: Dirk Gouders @ 2018-06-09  7:40 UTC (permalink / raw)
  To: Sam Ravnborg
  Cc: Masahiro Yamada, Randy Dunlap, Linux Kbuild mailing list,
	Linux Kernel Mailing List, Segher Boessenkool

Sam Ravnborg <sam@ravnborg.org> writes:

> Hi Dirk.
>
> On Fri, Jun 08, 2018 at 08:46:05PM +0200, Dirk Gouders wrote:
>> Hello,
>> 
>> this version is a prototype of the idea, Sam suggested -- I hope I
>> undestood it correctly.
>> 
>> This is a remarkable change to mconf in it's behavior; mainly it now
>> differentiates two focuses and operates differently, depending on the
>> focus.  When the focus is on the menu, mconf is in i-search mode, for
>> a detailed description see 1/1.
>> 
>> As stated earlier, this is just a prototype, documentation is missing
>> and the code is not ready for a real commit.
>
> When trying this out it started to work as envisioned.
> But somehw I manage to get stuck in the menus and cannot navigate to
> the buttons.
>
> Consider to remove the old short-cut for the menus.
> (Most/all the first_alph thingy in menubox.c)
> That will avoid two confliting navigations principles and likely
> make the code simpler to read.
>
> I am not sure, but maybe you can get rid of all the hotkey
> support in print_item with this change too.

Hi Sam,

thank you (and also to Randy) for having a look at it.

Next, I will prepare a patch, more thorougly tested,
documentation included and with hotkey support removed.

You are right, trying to support two navigation principles makes
everything too complex and I was too eager to keep as much of today's
functionality as possible.

Dirk

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2018-06-09  7:49 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-06-08 18:46 [RFC v4 0/1] i-search functionality for mconf Dirk Gouders
2018-06-08 18:46 ` [RFC v4 1/1] " Dirk Gouders
2018-06-09  0:59   ` Randy Dunlap
2018-06-08 21:56 ` [RFC v4 0/1] " Sam Ravnborg
2018-06-09  7:40   ` Dirk Gouders

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).