@@ -3453,10 +3453,27 @@ def _value_info(sym):
34533453 # Returns a string showing 'sym's value
34543454
34553455 # Only put quotes around the value for string symbols
3456- return "Value: {}\n " .format (
3456+ s = "Value: {}\n " .format (
34573457 '"{}"' .format (sym .str_value ) if sym .orig_type == STRING else sym .str_value
34583458 )
34593459
3460+ # Add origin information to explain where the value comes from
3461+ origin = sym .origin
3462+ if origin :
3463+ kind , sources = origin
3464+ if kind == "select" :
3465+ if sources :
3466+ s += " (selected by: {})\n " .format (", " .join (sources ))
3467+ elif kind == "imply" :
3468+ if sources :
3469+ s += " (implied by: {})\n " .format (", " .join (sources ))
3470+ elif kind == "default" :
3471+ s += " (from default)\n "
3472+ elif kind == "assign" :
3473+ s += " (user assigned)\n "
3474+
3475+ return s
3476+
34603477
34613478def _choice_syms_info (choice ):
34623479 # Returns a string listing the choice symbols in 'choice'. Adds
@@ -3818,6 +3835,68 @@ def _error(text):
38183835 _msg ("Error" , text )
38193836
38203837
3838+ def _get_force_info (sym ):
3839+ # Returns a string indicating what's forcing a symbol's value, or None
3840+ # if the value is not being forced by select/imply.
3841+ #
3842+ # Example return values:
3843+ # " [selected by FOO]"
3844+ # " [implied by BAR, BAZ]"
3845+
3846+ if sym .orig_type not in (BOOL , TRISTATE ):
3847+ return None
3848+
3849+ origin = sym .origin
3850+ if not origin :
3851+ return None
3852+
3853+ kind , sources = origin
3854+ if kind not in ("select" , "imply" ) or not sources :
3855+ return None
3856+
3857+ # Format the force info string
3858+ prefix = "selected by" if kind == "select" else "implied by"
3859+ sym_names = _extract_controlling_symbols (sources )
3860+
3861+ if not sym_names :
3862+ return None
3863+
3864+ # Show up to 2 symbols to keep line length reasonable
3865+ if len (sym_names ) <= 2 :
3866+ return " [{} {}]" .format (prefix , ", " .join (sym_names ))
3867+
3868+ return " [{} {}, +{}]" .format (prefix , ", " .join (sym_names [:2 ]), len (sym_names ) - 2 )
3869+
3870+
3871+ def _extract_controlling_symbols (expr_list ):
3872+ # Extracts the primary controlling symbol from each expression string
3873+ # Returns a list of unique symbol names
3874+ #
3875+ # For "A && B", extracts "A" (the symbol doing the select/imply)
3876+ # For "A || B", extracts both "A" and "B"
3877+ # For simple "A", extracts "A"
3878+ #
3879+ # This avoids showing condition symbols as if they're doing the select/imply
3880+
3881+ sym_names = []
3882+ for expr in expr_list :
3883+ # Split on && first - we only want symbols before &&
3884+ # For "FOO && BAR", we want FOO (the selector), not BAR (the condition)
3885+ and_idx = expr .find (" && " )
3886+ primary = expr [:and_idx ].strip () if and_idx != - 1 else expr .strip ()
3887+
3888+ # Now handle || - all parts are equal
3889+ if " || " in primary :
3890+ for part in primary .split (" || " ):
3891+ part = part .strip ()
3892+ if part and part not in sym_names :
3893+ sym_names .append (part )
3894+ elif primary and primary not in sym_names :
3895+ sym_names .append (primary )
3896+
3897+ return sym_names
3898+
3899+
38213900def _node_str (node ):
38223901 # Returns the complete menu entry text for a menu node.
38233902 #
@@ -3863,6 +3942,11 @@ def _node_str(node):
38633942
38643943 s += " (NEW)"
38653944
3945+ # Show what's controlling this symbol if it's selected/implied
3946+ force_info = _get_force_info (sym )
3947+ if force_info :
3948+ s += force_info
3949+
38663950 if isinstance (node .item , Choice ) and node .item .tri_value == 2 :
38673951 # Print the prompt of the selected symbol after the choice for
38683952 # choices in y mode
0 commit comments