Re: [PATCH v4] kconfig: nconf: Add search jump feature

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Aug 8, 2023 at 8:42 PM Jesse Taube <mr.bossman075@xxxxxxxxx> wrote:
>
> From: Jesse Taube <mr.bossman075@xxxxxxxxx>
>
> Menuconfig has a feature where you can "press the key in the (#) prefix
> to jump directly to that location. You will be returned to the current
> search results after exiting this new menu."
>
> This commit adds this feature to nconfig, with almost identical code.
>
> Signed-off-by: Jesse Taube <Mr.Bossman075@xxxxxxxxx>
> ---
> v1->v2:
>  Add selected_conf to go to menu and select a specific option.
>  Use get_line instead of creating new function.
>  Use Masahiro Yamada's new jump search implementation.
> v2->v3:
>  Change `start, end` to size_t and move scope to if
>  Removed redundant assignment of `again` to false.
> v3->v4:
>  Remove unnecessary size_t cast
>  Use ncurses to find line index in selected_conf

@randy can you please test this as well.

Thanks,
Jesse Taube
> ---
>  scripts/kconfig/nconf.c     | 113 ++++++++++++++++++++++++++++++++----
>  scripts/kconfig/nconf.gui.c |  37 ++++++++++--
>  scripts/kconfig/nconf.h     |   5 ++
>  3 files changed, 140 insertions(+), 15 deletions(-)
>
> diff --git a/scripts/kconfig/nconf.c b/scripts/kconfig/nconf.c
> index 3ba8b1af390f..143a2c351d57 100644
> --- a/scripts/kconfig/nconf.c
> +++ b/scripts/kconfig/nconf.c
> @@ -220,7 +220,7 @@ search_help[] =
>  "Location:\n"
>  "  -> Bus options (PCI, PCMCIA, EISA, ISA)\n"
>  "    -> PCI support (PCI [ = y])\n"
> -"      -> PCI access mode (<choice> [ = y])\n"
> +"(1)   -> PCI access mode (<choice> [ = y])\n"
>  "Selects: LIBCRC32\n"
>  "Selected by: BAR\n"
>  "-----------------------------------------------------------------\n"
> @@ -231,9 +231,13 @@ search_help[] =
>  "o  The 'Depends on:' line lists symbols that need to be defined for\n"
>  "   this symbol to be visible and selectable in the menu.\n"
>  "o  The 'Location:' lines tell, where in the menu structure this symbol\n"
> -"   is located.  A location followed by a [ = y] indicates that this is\n"
> -"   a selectable menu item, and the current value is displayed inside\n"
> -"   brackets.\n"
> +"   is located.\n"
> +"     A location followed by a [ = y] indicates that this is\n"
> +"     a selectable menu item, and the current value is displayed inside\n"
> +"     brackets.\n"
> +"     Press the key in the (#) prefix to jump directly to that\n"
> +"     location. You will be returned to the current search results\n"
> +"     after exiting this new menu.\n"
>  "o  The 'Selects:' line tells, what symbol will be automatically selected\n"
>  "   if this symbol is selected (y or m).\n"
>  "o  The 'Selected by' line tells what symbol has selected this symbol.\n"
> @@ -275,7 +279,9 @@ static const char *current_instructions = menu_instructions;
>
>  static char *dialog_input_result;
>  static int dialog_input_result_len;
> +static int jump_key_char;
>
> +static void selected_conf(struct menu *menu, struct menu *active_menu);
>  static void conf(struct menu *menu);
>  static void conf_choice(struct menu *menu);
>  static void conf_string(struct menu *menu);
> @@ -685,6 +691,57 @@ static int do_exit(void)
>         return 0;
>  }
>
> +struct search_data {
> +       struct list_head *head;
> +       struct menu *target;
> +};
> +
> +static int next_jump_key(int key)
> +{
> +       if (key < '1' || key > '9')
> +               return '1';
> +
> +       key++;
> +
> +       if (key > '9')
> +               key = '1';
> +
> +       return key;
> +}
> +
> +static int handle_search_keys(int key, size_t start, size_t end, void *_data)
> +{
> +       struct search_data *data = _data;
> +       struct jump_key *pos;
> +       int index = 0;
> +
> +       if (key < '1' || key > '9')
> +               return 0;
> +
> +       list_for_each_entry(pos, data->head, entries) {
> +               index = next_jump_key(index);
> +
> +               if (pos->offset < start)
> +                       continue;
> +
> +               if (pos->offset >= end)
> +                       break;
> +
> +               if (key == index) {
> +                       data->target = pos->target;
> +                       return 1;
> +               }
> +       }
> +
> +       return 0;
> +}
> +
> +int get_jump_key_char(void)
> +{
> +       jump_key_char = next_jump_key(jump_key_char);
> +
> +       return jump_key_char;
> +}
>
>  static void search_conf(void)
>  {
> @@ -692,7 +749,8 @@ static void search_conf(void)
>         struct gstr res;
>         struct gstr title;
>         char *dialog_input;
> -       int dres;
> +       int dres, vscroll = 0, hscroll = 0;
> +       bool again;
>
>         title = str_new();
>         str_printf( &title, "Enter (sub)string or regexp to search for "
> @@ -721,11 +779,28 @@ static void search_conf(void)
>                 dialog_input += strlen(CONFIG_);
>
>         sym_arr = sym_re_search(dialog_input);
> -       res = get_relations_str(sym_arr, NULL);
> +
> +       do {
> +               LIST_HEAD(head);
> +               struct search_data data = {
> +                       .head = &head,
> +                       .target = NULL,
> +               };
> +               jump_key_char = 0;
> +               res = get_relations_str(sym_arr, &head);
> +               dres = show_scroll_win_ext(main_window,
> +                               "Search Results", str_get(&res),
> +                               &vscroll, &hscroll,
> +                               handle_search_keys, &data);
> +               again = false;
> +               if (dres >= '1' && dres <= '9') {
> +                       assert(data.target != NULL);
> +                       selected_conf(data.target->parent, data.target);
> +                       again = true;
> +               }
> +               str_free(&res);
> +       } while (again);
>         free(sym_arr);
> -       show_scroll_win(main_window,
> -                       "Search Results", str_get(&res));
> -       str_free(&res);
>         str_free(&title);
>  }
>
> @@ -1062,10 +1137,15 @@ static int do_match(int key, struct match_state *state, int *ans)
>  }
>
>  static void conf(struct menu *menu)
> +{
> +       selected_conf(menu, NULL);
> +}
> +
> +static void selected_conf(struct menu *menu, struct menu *active_menu)
>  {
>         struct menu *submenu = NULL;
>         struct symbol *sym;
> -       int res;
> +       int i, res;
>         int current_index = 0;
>         int last_top_row = 0;
>         struct match_state match_state = {
> @@ -1081,6 +1161,19 @@ static void conf(struct menu *menu)
>                 if (!child_count)
>                         break;
>
> +               if (active_menu != NULL) {
> +                       for (i = 0; i < items_num; i++) {
> +                               struct mitem *mcur;
> +
> +                               mcur = (struct mitem *) item_userptr(curses_menu_items[i]);
> +                               if ((struct menu *) mcur->usrptr == active_menu) {
> +                                       current_index = i;
> +                                       break;
> +                               }
> +                       }
> +                       active_menu = NULL;
> +               }
> +
>                 show_menu(menu_get_prompt(menu), menu_instructions,
>                           current_index, &last_top_row);
>                 keypad((menu_win(curses_menu)), TRUE);
> diff --git a/scripts/kconfig/nconf.gui.c b/scripts/kconfig/nconf.gui.c
> index 9aedf40f1dc0..25a7263ef3c8 100644
> --- a/scripts/kconfig/nconf.gui.c
> +++ b/scripts/kconfig/nconf.gui.c
> @@ -497,10 +497,17 @@ void refresh_all_windows(WINDOW *main_window)
>         refresh();
>  }
>
> -/* layman's scrollable window... */
>  void show_scroll_win(WINDOW *main_window,
>                 const char *title,
>                 const char *text)
> +{
> +       (void)show_scroll_win_ext(main_window, title, (char *)text, NULL, NULL, NULL, NULL);
> +}
> +
> +/* layman's scrollable window... */
> +int show_scroll_win_ext(WINDOW *main_window, const char *title, char *text,
> +                       int *vscroll, int *hscroll,
> +                       extra_key_cb_fn extra_key_cb, void *data)
>  {
>         int res;
>         int total_lines = get_line_no(text);
> @@ -514,6 +521,12 @@ void show_scroll_win(WINDOW *main_window,
>         WINDOW *win;
>         WINDOW *pad;
>         PANEL *panel;
> +       bool done = false;
> +
> +       if (hscroll)
> +               start_x = *hscroll;
> +       if (vscroll)
> +               start_y = *vscroll;
>
>         getmaxyx(stdscr, lines, columns);
>
> @@ -549,8 +562,7 @@ void show_scroll_win(WINDOW *main_window,
>         panel = new_panel(win);
>
>         /* handle scrolling */
> -       do {
> -
> +       while (!done) {
>                 copywin(pad, win, start_y, start_x, 2, 2, text_lines,
>                                 text_cols, 0);
>                 print_in_middle(win,
> @@ -593,8 +605,18 @@ void show_scroll_win(WINDOW *main_window,
>                 case 'l':
>                         start_x++;
>                         break;
> +               default:
> +                       if (extra_key_cb) {
> +                               size_t start = (get_line(text, start_y) - text);
> +                               size_t end = (get_line(text, start_y + text_lines) - text);
> +
> +                               if (extra_key_cb(res, start, end, data)) {
> +                                       done = true;
> +                                       break;
> +                               }
> +                       }
>                 }
> -               if (res == 10 || res == 27 || res == 'q' ||
> +               if (res == 0 || res == 10 || res == 27 || res == 'q' ||
>                         res == KEY_F(F_HELP) || res == KEY_F(F_BACK) ||
>                         res == KEY_F(F_EXIT))
>                         break;
> @@ -606,9 +628,14 @@ void show_scroll_win(WINDOW *main_window,
>                         start_x = 0;
>                 if (start_x >= total_cols-text_cols)
>                         start_x = total_cols-text_cols;
> -       } while (res);
> +       }
>
> +       if (hscroll)
> +               *hscroll = start_x;
> +       if (vscroll)
> +               *vscroll = start_y;
>         del_panel(panel);
>         delwin(win);
>         refresh_all_windows(main_window);
> +       return res;
>  }
> diff --git a/scripts/kconfig/nconf.h b/scripts/kconfig/nconf.h
> index 6f925bc74eb3..ab836d582664 100644
> --- a/scripts/kconfig/nconf.h
> +++ b/scripts/kconfig/nconf.h
> @@ -67,6 +67,8 @@ typedef enum {
>
>  void set_colors(void);
>
> +typedef int (*extra_key_cb_fn)(int, size_t, size_t, void *);
> +
>  /* this changes the windows attributes !!! */
>  void print_in_middle(WINDOW *win, int y, int width, const char *str, int attrs);
>  int get_line_length(const char *line);
> @@ -78,6 +80,9 @@ int dialog_inputbox(WINDOW *main_window,
>                 const char *title, const char *prompt,
>                 const char *init, char **resultp, int *result_len);
>  void refresh_all_windows(WINDOW *main_window);
> +int show_scroll_win_ext(WINDOW *main_window, const char *title, char *text,
> +                       int *vscroll, int *hscroll,
> +                       extra_key_cb_fn extra_key_cb, void *data);
>  void show_scroll_win(WINDOW *main_window,
>                 const char *title,
>                 const char *text);
> --
> 2.40.0
>




[Index of Archives]     [Linux&nblp;USB Development]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite Secrets]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux