@@ -61,7 +61,15 @@ impl<C: ParserConfig> QueryParser<C> {
6161 . rev ( )
6262 . take_while ( |& b| b != b':' )
6363 . all ( |b| b. is_ascii_digit ( ) ) ;
64- if !matches ! ( constraint, Constraint :: FilePath ( _) ) && !has_location_suffix {
64+
65+ // for grep we don't want to treat a part of path like pathname
66+ let treat_as_text = matches ! ( constraint, Constraint :: PathSegment ( _) )
67+ && config. treat_lone_path_as_text ( ) ;
68+
69+ if !matches ! ( constraint, Constraint :: FilePath ( _) )
70+ && !has_location_suffix
71+ && !treat_as_text
72+ {
6573 constraints. push ( constraint) ;
6674 return FFFQuery {
6775 raw_query,
@@ -958,6 +966,111 @@ mod tests {
958966 assert_eq ! ( result. grep_text( ) , "profile.h" ) ;
959967 }
960968
969+ #[ test]
970+ fn test_ai_grep_leading_slash_path_alone_is_text_not_path_segment ( ) {
971+ // A leading-slash multi-segment path like `/api/tests/` or `/api/tests`
972+ // used as the sole query token should be treated as fuzzy text, NOT as
973+ // a PathSegment constraint. The user is searching for files matching
974+ // that path string, not trying to scope results to a directory.
975+ use crate :: AiGrepConfig ;
976+ let parser = QueryParser :: new ( AiGrepConfig ) ;
977+
978+ // With trailing slash
979+ let result = parser. parse ( "/api/tests/" ) ;
980+ assert_eq ! (
981+ result. constraints. len( ) ,
982+ 0 ,
983+ "Expected no constraints for '/api/tests/', got {:?}" ,
984+ result. constraints
985+ ) ;
986+ assert ! (
987+ matches!( result. fuzzy_query, FuzzyQuery :: Text ( "/api/tests/" ) ) ,
988+ "Expected FuzzyQuery::Text, got {:?}" ,
989+ result. fuzzy_query
990+ ) ;
991+
992+ // Without trailing slash
993+ let result = parser. parse ( "/api/tests" ) ;
994+ assert_eq ! (
995+ result. constraints. len( ) ,
996+ 0 ,
997+ "Expected no constraints for '/api/tests', got {:?}" ,
998+ result. constraints
999+ ) ;
1000+ assert ! (
1001+ matches!( result. fuzzy_query, FuzzyQuery :: Text ( "/api/tests" ) ) ,
1002+ "Expected FuzzyQuery::Text, got {:?}" ,
1003+ result. fuzzy_query
1004+ ) ;
1005+ }
1006+
1007+ #[ test]
1008+ fn test_grep_leading_slash_path_alone_is_text_not_path_segment ( ) {
1009+ // Same behavior for regular GrepConfig — single-token path-like
1010+ // queries are search terms, not directory filters.
1011+ let parser = QueryParser :: new ( GrepConfig ) ;
1012+
1013+ let result = parser. parse ( "/api/tests/" ) ;
1014+ assert_eq ! (
1015+ result. constraints. len( ) ,
1016+ 0 ,
1017+ "GrepConfig: expected no constraints for '/api/tests/', got {:?}" ,
1018+ result. constraints
1019+ ) ;
1020+ assert ! (
1021+ matches!( result. fuzzy_query, FuzzyQuery :: Text ( "/api/tests/" ) ) ,
1022+ "GrepConfig: expected FuzzyQuery::Text, got {:?}" ,
1023+ result. fuzzy_query
1024+ ) ;
1025+
1026+ let result = parser. parse ( "/api/tests" ) ;
1027+ assert_eq ! (
1028+ result. constraints. len( ) ,
1029+ 0 ,
1030+ "GrepConfig: expected no constraints for '/api/tests', got {:?}" ,
1031+ result. constraints
1032+ ) ;
1033+ assert ! (
1034+ matches!( result. fuzzy_query, FuzzyQuery :: Text ( "/api/tests" ) ) ,
1035+ "GrepConfig: expected FuzzyQuery::Text, got {:?}" ,
1036+ result. fuzzy_query
1037+ ) ;
1038+ }
1039+
1040+ #[ test]
1041+ fn test_file_search_leading_slash_path_alone_stays_path_segment ( ) {
1042+ // FileSearchConfig (fuzzy file finder) should still treat a lone
1043+ // `/api/tests/` as a PathSegment constraint — the user is scoping
1044+ // the file list to that directory.
1045+ let parser = QueryParser :: new ( FileSearchConfig ) ;
1046+
1047+ let result = parser. parse ( "/api/tests/" ) ;
1048+ assert_eq ! (
1049+ result. constraints. len( ) ,
1050+ 1 ,
1051+ "FileSearchConfig: expected PathSegment constraint, got {:?}" ,
1052+ result. constraints
1053+ ) ;
1054+ assert ! (
1055+ matches!( result. constraints[ 0 ] , Constraint :: PathSegment ( "api/tests" ) ) ,
1056+ "FileSearchConfig: expected PathSegment(\" api/tests\" ), got {:?}" ,
1057+ result. constraints[ 0 ]
1058+ ) ;
1059+
1060+ let result = parser. parse ( "/api/tests" ) ;
1061+ assert_eq ! (
1062+ result. constraints. len( ) ,
1063+ 1 ,
1064+ "FileSearchConfig: expected PathSegment constraint, got {:?}" ,
1065+ result. constraints
1066+ ) ;
1067+ assert ! (
1068+ matches!( result. constraints[ 0 ] , Constraint :: PathSegment ( "api/tests" ) ) ,
1069+ "FileSearchConfig: expected PathSegment(\" api/tests\" ), got {:?}" ,
1070+ result. constraints[ 0 ]
1071+ ) ;
1072+ }
1073+
9611074 #[ test]
9621075 fn test_ai_grep_filename_with_extension_only_promotes_to_text ( ) {
9631076 // Same case with an Extension constraint — no fuzzy text means the
0 commit comments