From: Julian Braha <julianbraha@gmail.com>
To: nathan@kernel.org, nsc@kernel.org
Cc: ojeda@kernel.org, a.hindborg@kernel.org, nico@fluxnic.net,
rdunlap@infradead.org, grahamr@qti.qualcomm.com,
jakub.git@horky.net, linux-kbuild@vger.kernel.org,
linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org,
Julian Braha <julianbraha@gmail.com>
Subject: [PATCH] kconfig: wrap long expressions in menuconfig
Date: Sat, 10 Oct 2026 10:50:01 +0100 [thread overview]
Message-ID: <20261010095001.265759-1-julianbraha@gmail.com> (raw)
In an offline conversation, Miguel Ojeda reported that scrolling
horizontally in menuconfig's search to read RUST's dependencies has been
slowing down debugging.
Let's wrap expressions (like in the 'Depends on', 'Selected by', or
'Range' sections) between tokens at the end of the window, such that each
line begins with the same indentation. Ensure the '!' negation stays
attached to the left side of the option symbol, and keep the value
annotation attached to the right side when wrapping.
Note that the 'help' textbox uses the same expression printer as search,
so this has the side effect of improving the formatting in 'help', too.
In the future, we should consider a larger revamp that would wrap all text
in the search window, allowing us to safely disable horizontal scrolling.
Assisted-by: LLM
Signed-off-by: Julian Braha <julianbraha@gmail.com>
---
scripts/kconfig/expr.c | 24 ++++++++++++++++--------
scripts/kconfig/lkc.h | 5 ++++-
scripts/kconfig/mconf.c | 2 +-
| 7 ++++++-
scripts/kconfig/nconf.c | 2 +-
scripts/kconfig/util.c | 1 +
6 files changed, 29 insertions(+), 12 deletions(-)
diff --git a/scripts/kconfig/expr.c b/scripts/kconfig/expr.c
index 2b91d16bf14f..f1e100c3c755 100644
--- a/scripts/kconfig/expr.c
+++ b/scripts/kconfig/expr.c
@@ -1155,21 +1155,28 @@ static void expr_print_gstr_helper(void *data, struct symbol *sym, const char *s
if (sym)
sym_str = sym_get_string_value(sym);
- if (gs->max_width) {
+ if (gs->max_width && !strchr(str, '\n')) {
unsigned extra_length = strlen(str);
const char *last_cr = strrchr(gs->s, '\n');
unsigned last_line_length;
-
- if (sym_str)
+ /* Ensure the value annotation stays attached to the symbol on wrap */
+ if (sym_str && sym->type != S_UNKNOWN)
extra_length += 4 + strlen(sym_str);
- if (!last_cr)
- last_cr = gs->s;
+ last_line_length = strlen(last_cr ? last_cr + 1 : gs->s);
- last_line_length = strlen(gs->s) - (last_cr - gs->s);
+ if (last_line_length > gs->indent &&
+ last_line_length + extra_length > gs->max_width) {
+ /* Ensure '!' stays attached to the symbol on wrap */
+ char *last = gs->s + strlen(gs->s) - 1;
+ bool negated = *last == '!';
- if ((last_line_length + extra_length) > gs->max_width)
- str_append(gs, "\\\n");
+ if (negated)
+ *last = '\0';
+ str_printf(gs, "\n%*s%s", gs->indent, "",
+ negated ? "!" : "");
+ str += strspn(str, " ");
+ }
}
str_append(gs, str);
@@ -1209,5 +1216,6 @@ static void expr_print_revdep(struct expr *e,
void expr_gstr_print_revdep(struct expr *e, struct gstr *gs,
tristate pr_type, const char *title)
{
+ gs->indent = strlen(" - ");
expr_print_revdep(e, expr_print_gstr_helper, gs, pr_type, &title);
}
diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h
index bbc99f75b416..f5fe3731db0c 100644
--- a/scripts/kconfig/lkc.h
+++ b/scripts/kconfig/lkc.h
@@ -65,6 +65,8 @@ struct gstr {
* wrapped not to exceed the max_width value
*/
int max_width;
+ /* Indentation of wrapped expression lines. */
+ int indent;
};
struct gstr str_new(void);
void str_free(struct gstr *gs);
@@ -101,7 +103,8 @@ const char *menu_get_prompt(const struct menu *menu);
struct menu *menu_get_parent_menu(struct menu *menu);
struct menu *menu_get_menu_or_parent_menu(struct menu *menu);
int get_jump_key_char(void);
-struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head);
+struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head,
+ int max_width);
void menu_get_ext_help(struct menu *menu, struct gstr *help);
void menu_dump(void);
diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c
index b8b7bba84a65..fb87f944d3f9 100644
--- a/scripts/kconfig/mconf.c
+++ b/scripts/kconfig/mconf.c
@@ -431,7 +431,7 @@ static void search_conf(void)
struct jump_key *pos, *tmp;
jump_key_char = 0;
- res = get_relations_str(sym_arr, &head);
+ res = get_relations_str(sym_arr, &head, getmaxx(stdscr) - 10);
set_subtitle();
dres = show_textbox_ext("Search Results", str_get(&res), 0, 0,
&vscroll, &hscroll,
--git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
index bda3e2650216..31f12cfe981b 100644
--- a/scripts/kconfig/menu.c
+++ b/scripts/kconfig/menu.c
@@ -668,6 +668,7 @@ static void get_dep_str(struct gstr *r, const struct expr *expr,
{
if (!expr_is_yes(expr)) {
str_append(r, prefix);
+ r->indent = strlen(prefix);
expr_gstr_print(expr, r);
str_append(r, "\n");
}
@@ -743,6 +744,7 @@ static void get_symbol_props_str(struct gstr *r, struct symbol *sym,
bool hit = false;
struct property *prop;
+ r->indent = strlen(prefix);
for_all_properties(sym, prop, tok) {
if (!hit) {
str_append(r, prefix);
@@ -772,6 +774,7 @@ static void get_symbol_str(struct gstr *r, struct symbol *sym,
prop = sym_get_range_prop(sym);
if (prop) {
str_printf(r, "Range : ");
+ r->indent = strlen("Range : ");
expr_gstr_print(prop->expr, r);
str_append(r, "\n");
}
@@ -810,12 +813,14 @@ static void get_symbol_str(struct gstr *r, struct symbol *sym,
str_append(r, "\n\n");
}
-struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head)
+struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head,
+ int max_width)
{
struct symbol *sym;
struct gstr res = str_new();
int i;
+ res.max_width = max_width;
for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
get_symbol_str(&res, sym, head);
if (!i)
diff --git a/scripts/kconfig/nconf.c b/scripts/kconfig/nconf.c
index 521700ed7152..fc39830a850b 100644
--- a/scripts/kconfig/nconf.c
+++ b/scripts/kconfig/nconf.c
@@ -741,7 +741,7 @@ static void search_conf(void)
.target = NULL,
};
jump_key_char = 0;
- res = get_relations_str(sym_arr, &head);
+ res = get_relations_str(sym_arr, &head, 0);
dres = show_scroll_win_ext(main_window,
"Search Results", str_get(&res),
&vscroll, &hscroll,
diff --git a/scripts/kconfig/util.c b/scripts/kconfig/util.c
index 0809aa061b6a..1de072e45ca3 100644
--- a/scripts/kconfig/util.c
+++ b/scripts/kconfig/util.c
@@ -77,6 +77,7 @@ struct gstr str_new(void)
gs.s = xmalloc(sizeof(char) * 64);
gs.len = 64;
gs.max_width = 0;
+ gs.indent = 0;
strcpy(gs.s, "\0");
return gs;
}
--
2.55.0
next reply other threads:[~2026-10-10 9:50 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-10 9:50 Julian Braha [this message]
2026-10-11 16:20 ` Miguel Ojeda
2026-10-11 18:22 ` Julian Braha
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=20261010095001.265759-1-julianbraha@gmail.com \
--to=julianbraha@gmail.com \
--cc=a.hindborg@kernel.org \
--cc=grahamr@qti.qualcomm.com \
--cc=jakub.git@horky.net \
--cc=linux-kbuild@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=nathan@kernel.org \
--cc=nico@fluxnic.net \
--cc=nsc@kernel.org \
--cc=ojeda@kernel.org \
--cc=rdunlap@infradead.org \
--cc=rust-for-linux@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
all inboxes | Powered by JetHome®