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 v2 2/3] kconfig: wrap long expressions in menuconfig
Date: Tue, 10 Nov 2026 17:35:25 +0000 [thread overview]
Message-ID: <20261110173526.1548434-3-julianbraha@gmail.com> (raw)
In-Reply-To: <20261110173526.1548434-1-julianbraha@gmail.com>
Horizontally scrolling through long expressions in menuconfig search is
overly time-consuming.
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.
Signed-off-by: Julian Braha <julianbraha@gmail.com>
---
Changes since v1:
- properly support trailing '!' and leading spaces (sashiko / Nathan)
Link to v1:
https://lore.kernel.org/all/20261010095001.265759-1-julianbraha@gmail.com/
scripts/kconfig/expr.c | 28 ++++++++++++++++++++--------
scripts/kconfig/lkc.h | 6 +++++-
scripts/kconfig/mconf.c | 2 +-
| 7 ++++++-
scripts/kconfig/nconf.c | 2 +-
scripts/kconfig/util.c | 2 ++
6 files changed, 35 insertions(+), 12 deletions(-)
diff --git a/scripts/kconfig/expr.c b/scripts/kconfig/expr.c
index 2b91d16bf14f..9284ccb20259 100644
--- a/scripts/kconfig/expr.c
+++ b/scripts/kconfig/expr.c
@@ -1155,30 +1155,40 @@ 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;
+ unsigned int prefix_len = strlen(gs->s) - gs->wrap_pos;
- 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 + extra_length) > gs->max_width)
- str_append(gs, "\\\n");
+ if (last_line_length > gs->indent + prefix_len &&
+ last_line_length + extra_length > gs->max_width) {
+ gs->s[gs->wrap_pos] = '\0';
+ str_printf(gs, "\n%*s", gs->indent, "");
+ while (prefix_len--)
+ str_append(gs, "!");
+ if (!sym)
+ str += strspn(str, " ");
+ }
}
str_append(gs, str);
if (sym && sym->type != S_UNKNOWN)
str_printf(gs, " [=%s]", sym_str);
+ /* Ensure '!' stays attached to the symbol on wrap */
+ if (sym || strcmp(str, "!"))
+ gs->wrap_pos = strlen(gs->s);
}
void expr_gstr_print(const struct expr *e, struct gstr *gs)
{
+ gs->wrap_pos = strlen(gs->s);
expr_print(e, expr_print_gstr_helper, gs, E_NONE);
}
@@ -1209,5 +1219,7 @@ 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(" - ");
+ gs->wrap_pos = strlen(gs->s);
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..a1d3e366fb76 100644
--- a/scripts/kconfig/lkc.h
+++ b/scripts/kconfig/lkc.h
@@ -65,6 +65,9 @@ struct gstr {
* wrapped not to exceed the max_width value
*/
int max_width;
+ /* Indentation of wrapped expression lines. */
+ int indent;
+ size_t wrap_pos;
};
struct gstr str_new(void);
void str_free(struct gstr *gs);
@@ -101,7 +104,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 ebfc5bd09c1c..ba258a032094 100644
--- a/scripts/kconfig/mconf.c
+++ b/scripts/kconfig/mconf.c
@@ -433,7 +433,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();
res_title = str_new();
--git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
index 2b2166edeb25..be5a19c8e0ed 100644
--- a/scripts/kconfig/menu.c
+++ b/scripts/kconfig/menu.c
@@ -689,6 +689,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");
}
@@ -768,6 +769,7 @@ static void get_symbol_props_str(struct gstr *r, struct symbol *sym,
expr = expr_alloc_and(expr, prop->expr);
if (expr) {
str_append(r, prefix);
+ r->indent = strlen(prefix);
expr_gstr_print(expr, r);
str_append(r, "\n");
}
@@ -790,6 +792,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");
}
@@ -828,12 +831,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 4c9c4ee7c3a7..83c13ff108d6 100644
--- a/scripts/kconfig/nconf.c
+++ b/scripts/kconfig/nconf.c
@@ -743,7 +743,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);
res_title = str_new();
str_printf(&res_title, "Search Results (%d)", sym_cnt);
diff --git a/scripts/kconfig/util.c b/scripts/kconfig/util.c
index 0809aa061b6a..5b80393048cb 100644
--- a/scripts/kconfig/util.c
+++ b/scripts/kconfig/util.c
@@ -77,6 +77,8 @@ struct gstr str_new(void)
gs.s = xmalloc(sizeof(char) * 64);
gs.len = 64;
gs.max_width = 0;
+ gs.indent = 0;
+ gs.wrap_pos = 0;
strcpy(gs.s, "\0");
return gs;
}
--
2.56.0
next prev parent reply other threads:[~2026-11-10 17:35 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-10 17:35 [PATCH v2 0/3] " Julian Braha
2026-11-10 17:35 ` [PATCH v2 1/3] kconfig: print the output of expr_alloc_and() instead of printing '&&' Julian Braha
2026-11-10 17:35 ` Julian Braha [this message]
2026-11-10 17:35 ` [PATCH v2 3/3] kconfig: show continuation at the end of wrapped lines 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=20261110173526.1548434-3-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®