···23572357 // For multi-word commands like "open groups", we need to check if typed text
23582358 // matches the full command name before splitting on spaces
23592359 let typedCommand, typedParams;
23602360- const trimmedTyped = state.typed.trim();
23602360+ // Use originalTyped (what user actually typed) for highlight boundary,
23612361+ // so Tab-cycled suggestions show the original input bold and completion dim
23622362+ const userTyped = state.originalTyped || state.typed;
23632363+ const trimmedUserTyped = userTyped.trim();
2361236423622365 // Check if typed text matches full command or command + params
23632363- if (trimmedTyped.toLowerCase() === selectedMatch.toLowerCase()) {
23642364- // Exact match - typed text IS the command (possibly with trailing space)
23652365- typedCommand = trimmedTyped;
23662366- typedParams = state.typed.substring(trimmedTyped.length); // Just the trailing space if any
23672367- } else if (state.typed.toLowerCase().startsWith(selectedMatch.toLowerCase() + ' ')) {
23682368- // Command with parameters - text after command name + space is params
23692369- typedCommand = selectedMatch;
23662366+ if (state.typed.toLowerCase().startsWith(selectedMatch.toLowerCase() + ' ')) {
23672367+ // Command with parameters - highlight original typed command portion, show params
23682368+ // Use originalTyped for highlight length but state.typed for actual param text
23692369+ typedCommand = trimmedUserTyped.toLowerCase().startsWith(selectedMatch.toLowerCase())
23702370+ ? trimmedUserTyped.substring(0, Math.min(trimmedUserTyped.length, selectedMatch.length))
23712371+ : trimmedUserTyped;
23702372 typedParams = state.typed.substring(selectedMatch.length);
23712371- } else if (selectedMatch.toLowerCase().startsWith(trimmedTyped.toLowerCase())) {
23722372- // Typed text is a prefix of the command (e.g., "list n" → "list notes")
23732373- // Treat entire typed text as command part, no params
23742374- typedCommand = trimmedTyped;
23732373+ } else if (selectedMatch.toLowerCase().startsWith(trimmedUserTyped.toLowerCase())) {
23742374+ // Typed text is a prefix of the command (e.g., "ta" → "tags", or "list n" → "list notes")
23752375+ // Bold the user-typed portion, dim the rest
23762376+ typedCommand = trimmedUserTyped;
23752377 typedParams = '';
23782378+ } else if (trimmedUserTyped.toLowerCase() === selectedMatch.toLowerCase()) {
23792379+ // Exact match - typed text IS the command
23802380+ typedCommand = trimmedUserTyped;
23812381+ typedParams = state.typed.substring(trimmedUserTyped.length);
23762382 } else {
23772377- // Partial match - use first space as split point (original behavior)
23782378- const hasParameters = state.typed.includes(' ');
23792379- typedCommand = hasParameters ? state.typed.substring(0, state.typed.indexOf(' ')) : state.typed;
23832383+ // Partial match in middle or no clear match - use first space as split point
23842384+ const hasParameters = userTyped.includes(' ');
23852385+ typedCommand = hasParameters ? userTyped.substring(0, userTyped.indexOf(' ')) : userTyped;
23802386 typedParams = hasParameters ? state.typed.substring(state.typed.indexOf(' ')) : '';
23812387 }
23822388