@@ -2230,16 +2230,32 @@ impl SingleSessionApp {
22302230 self . slash_suggestions . query . as_str ( )
22312231 } ;
22322232 let prefix = prefix. to_ascii_lowercase ( ) ;
2233- DESKTOP_SLASH_COMMANDS
2234- . iter ( )
2235- . copied ( )
2236- . filter ( |( usage, _) | {
2237- usage
2238- . split_whitespace ( )
2239- . next ( )
2240- . unwrap_or ( usage)
2241- . starts_with ( & prefix)
2242- } )
2233+
2234+ let mut prefix_matches = Vec :: new ( ) ;
2235+ let mut fuzzy_matches: Vec < ( usize , usize , & ' static str , & ' static str ) > = Vec :: new ( ) ;
2236+ for ( usage, description) in DESKTOP_SLASH_COMMANDS . iter ( ) . copied ( ) {
2237+ let command = usage. split_whitespace ( ) . next ( ) . unwrap_or ( usage) ;
2238+ let command_lower = command. to_ascii_lowercase ( ) ;
2239+ if command_lower. starts_with ( & prefix) {
2240+ prefix_matches. push ( ( usage, description) ) ;
2241+ } else if let Some ( score) = desktop_slash_fuzzy_score ( & prefix, & command_lower) {
2242+ fuzzy_matches. push ( ( score, command. len ( ) , usage, description) ) ;
2243+ }
2244+ }
2245+
2246+ fuzzy_matches. sort_by ( |a, b| {
2247+ a. 0 . cmp ( & b. 0 )
2248+ . then_with ( || a. 1 . cmp ( & b. 1 ) )
2249+ . then_with ( || a. 2 . cmp ( & b. 2 ) )
2250+ } ) ;
2251+
2252+ prefix_matches
2253+ . into_iter ( )
2254+ . chain (
2255+ fuzzy_matches
2256+ . into_iter ( )
2257+ . map ( |( _, _, usage, description) | ( usage, description) ) ,
2258+ )
22432259 . take ( DESKTOP_SLASH_SUGGESTION_ROW_LIMIT )
22442260 . collect ( )
22452261 }
@@ -4751,6 +4767,38 @@ fn model_choice_search_text(choice: &DesktopModelChoice) -> String {
47514767 . to_lowercase ( )
47524768}
47534769
4770+ fn desktop_slash_fuzzy_score ( needle : & str , haystack : & str ) -> Option < usize > {
4771+ if needle. is_empty ( ) {
4772+ return Some ( 0 ) ;
4773+ }
4774+
4775+ let needle = needle. strip_prefix ( '/' ) . unwrap_or ( needle) ;
4776+ let haystack = haystack. strip_prefix ( '/' ) . unwrap_or ( haystack) ;
4777+ if needle. is_empty ( ) {
4778+ return Some ( 0 ) ;
4779+ }
4780+
4781+ if let Some ( first_char) = needle. chars ( ) . next ( )
4782+ && !haystack. starts_with ( & needle[ ..first_char. len_utf8 ( ) ] )
4783+ {
4784+ return None ;
4785+ }
4786+
4787+ let mut score = 0usize ;
4788+ let mut position = 0usize ;
4789+ for ch in needle. chars ( ) {
4790+ let offset = haystack[ position..] . find ( ch) ?;
4791+ score += offset;
4792+ position += offset + ch. len_utf8 ( ) ;
4793+ }
4794+
4795+ if needle. len ( ) > 1 && score > needle. len ( ) * 3 {
4796+ return None ;
4797+ }
4798+
4799+ Some ( score)
4800+ }
4801+
47544802fn dedupe_model_choices ( choices : Vec < DesktopModelChoice > ) -> Vec < DesktopModelChoice > {
47554803 let mut deduped: Vec < DesktopModelChoice > = Vec :: new ( ) ;
47564804 for choice in choices {
0 commit comments