* [PATCH v2 1/3] kconfig: print the output of expr_alloc_and() instead of printing '&&'
2026-11-10 17:35 [PATCH v2 0/3] kconfig: wrap long expressions in menuconfig Julian Braha
@ 2026-11-10 17:35 ` Julian Braha
2026-11-10 17:35 ` [PATCH v2 2/3] kconfig: wrap long expressions in menuconfig Julian Braha
2026-11-10 17:35 ` [PATCH v2 3/3] kconfig: show continuation at the end of wrapped lines Julian Braha
2 siblings, 0 replies; 4+ messages in thread
From: Julian Braha @ 2026-11-10 17:35 UTC (permalink / raw)
To: nathan, nsc
Cc: ojeda, a.hindborg, nico, rdunlap, grahamr, jakub.git,
linux-kbuild, linux-kernel, rust-for-linux, Julian Braha
Clean up expression printing for 'select' and 'imply' (which ANDs the
select/imply targets), to properly call expr_alloc_and() and print the
output, instead of printing a literal ' && '.
This is necessary to ensure that any '&&' at the end of those lines can
wrap properly.
Signed-off-by: Julian Braha <julianbraha@gmail.com>
---
| 17 +++++++----------
1 file changed, 7 insertions(+), 10 deletions(-)
--git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
index 1a3ad09a92d2..2b2166edeb25 100644
--- a/scripts/kconfig/menu.c
+++ b/scripts/kconfig/menu.c
@@ -761,19 +761,16 @@ static void get_prompt_str(struct gstr *r, struct property *prop,
static void get_symbol_props_str(struct gstr *r, struct symbol *sym,
enum prop_type tok, const char *prefix)
{
- bool hit = false;
+ struct expr *expr = NULL;
struct property *prop;
- for_all_properties(sym, prop, tok) {
- if (!hit) {
- str_append(r, prefix);
- hit = true;
- } else
- str_printf(r, " && ");
- expr_gstr_print(prop->expr, r);
- }
- if (hit)
+ for_all_properties(sym, prop, tok)
+ expr = expr_alloc_and(expr, prop->expr);
+ if (expr) {
+ str_append(r, prefix);
+ expr_gstr_print(expr, r);
str_append(r, "\n");
+ }
}
/*
--
2.56.0
^ permalink raw reply [flat|nested] 4+ messages in thread* [PATCH v2 2/3] kconfig: wrap long expressions in menuconfig
2026-11-10 17:35 [PATCH v2 0/3] kconfig: wrap long expressions in menuconfig 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
2026-11-10 17:35 ` [PATCH v2 3/3] kconfig: show continuation at the end of wrapped lines Julian Braha
2 siblings, 0 replies; 4+ messages in thread
From: Julian Braha @ 2026-11-10 17:35 UTC (permalink / raw)
To: nathan, nsc
Cc: ojeda, a.hindborg, nico, rdunlap, grahamr, jakub.git,
linux-kbuild, linux-kernel, rust-for-linux, Julian Braha
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
^ permalink raw reply [flat|nested] 4+ messages in thread* [PATCH v2 3/3] kconfig: show continuation at the end of wrapped lines
2026-11-10 17:35 [PATCH v2 0/3] kconfig: wrap long expressions in menuconfig 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 ` [PATCH v2 2/3] kconfig: wrap long expressions in menuconfig Julian Braha
@ 2026-11-10 17:35 ` Julian Braha
2 siblings, 0 replies; 4+ messages in thread
From: Julian Braha @ 2026-11-10 17:35 UTC (permalink / raw)
To: nathan, nsc
Cc: ojeda, a.hindborg, nico, rdunlap, grahamr, jakub.git,
linux-kbuild, linux-kernel, rust-for-linux, Julian Braha
Add a visible continuation '\' to the end of each wrapped line.
This is because some line wraps are not otherwise obvious to the reader,
for example if a line ends with a symbol name instead of an operator.
(Below example uses an 80-column terminal)
Here, it would be less obvious without '\' (GPIO_TQMX86):
Depends on: GPIOLIB [=y] && (MFD_TQMX86 [=y] || COMPILE_TEST [=y]) \
&& HAS_IOPORT_MAP [=y]
Signed-off-by: Julian Braha <julianbraha@gmail.com>
---
scripts/kconfig/expr.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/scripts/kconfig/expr.c b/scripts/kconfig/expr.c
index 0b3f2d7bc809..a539b617b62f 100644
--- a/scripts/kconfig/expr.c
+++ b/scripts/kconfig/expr.c
@@ -1167,12 +1167,15 @@ static void expr_print_gstr_helper(void *data, struct symbol *sym, const char *s
if (sym_str && sym->type != S_UNKNOWN)
extra_length += 4 + strlen(sym_str);
+ extra_length += strlen(" \\");
last_line_length = strlen(last_cr ? last_cr + 1 : gs->s);
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, "");
+ if (gs->s[gs->wrap_pos - 1] != ' ')
+ str_append(gs, " ");
+ str_printf(gs, "\\\n%*s", gs->indent, "");
while (prefix_len--)
str_append(gs, "!");
if (!sym)
--
2.56.0
^ permalink raw reply [flat|nested] 4+ messages in thread