future

Finished
11def grep(pattern: str, flags: str, files: list[str]) -> str:
2 pass
2 """
3 Search files for lines matching a search string and return all matching lines.
4
5 Args:
6 pattern (str): The string to search for.
7 flags (str): Flags for customizing the command's behavior.
8 files (list[str]): One or more files to search in.
9
10 Returns:
11 str: All matching lines, possibly with file names and line numbers prepended.
12
13 Flags:
14 -n: Prepend line numbers.
15 -l: Output only file names.
16 -i: Case-insensitive matching.
17 -v: Invert matching.
18 -x: Match entire line only.
19 """
20 # Parse flags - handle both space-separated and concatenated flags
21 # Remove spaces and split into individual characters
22 clean_flags = flags.replace(' ', '')
23 line_numbers = 'n' in clean_flags
24 files_only = 'l' in clean_flags
25 case_insensitive = 'i' in clean_flags
26 invert_match = 'v' in clean_flags
27 exact_match = 'x' in clean_flags
28
29 # Edge Case: Empty pattern
30 if not pattern:
31 pattern_to_match = ''
32 else:
33 pattern_to_match = pattern
34
35 result_lines = []
36 matching_files = set()
37
38 # Edge Case: No files provided
39 if not files:
40 return ""
41
42 # Edge Case: Empty files list
43 if len(files) == 0:
44 return ""
45
46 for file_path in files:
47 try:
48 with open(file_path, 'r', encoding='utf-8') as file:
49 lines = file.readlines()
50
51 # Edge Case: File cannot be read
52 except IOError:
53 # Skip unreadable files
54 continue
55
56 file_has_match = False
57
58 # If -l flag is set, we only need to check if there's a match, not process lines
59 if files_only:
60 for line_num, line in enumerate(lines, start=1):
61 # Determine if line matches
62 line_content = line.rstrip('\n')
63 if exact_match:
64 # For exact match, compare the entire line
65 if case_insensitive:
66 matches = pattern_to_match.lower() == line_content.lower()
67 else:
68 matches = pattern_to_match == line_content
69 else:
70 # For substring match, check if pattern is contained in line
71 if case_insensitive:
72 matches = pattern_to_match.lower() in line_content.lower()
73 else:
74 matches = pattern_to_match in line_content
75
76 # Apply invert flag
77 if invert_match:
78 matches = not matches
79
80 if matches:
81 matching_files.add(file_path)
82 break # Found a match, no need to check more lines
83 else:
84 for line_num, line in enumerate(lines, start=1):
85 # Determine if line matches
86 line_content = line.rstrip('\n')
87 if exact_match:
88 # For exact match, compare the entire line
89 if case_insensitive:
90 matches = pattern_to_match.lower() == line_content.lower()
91 else:
92 matches = pattern_to_match == line_content
93 else:
94 # For substring match, check if pattern is contained in line
95 if case_insensitive:
96 matches = pattern_to_match.lower() in line_content.lower()
97 else:
98 matches = pattern_to_match in line_content
99
100 # Apply invert flag
101 if invert_match:
102 matches = not matches
103
104 if matches:
105 file_has_match = True
106
107 output_line = ""
108
109 # Add file name if multiple files
110 # Edge Case: Single file vs multiple files
111 if len(files) > 1:
112 output_line += f"{file_path}:"
113
114 # Add line number if requested
115 # Edge Case: Line number flag
116 if line_numbers:
117 output_line += f"{line_num}:"
118
119 output_line += line.rstrip('\n')
120 result_lines.append(output_line)
121
122
123 # Edge Case: Only file names requested
124 if files_only:
125 # Return file names in the order they were encountered
126 ordered_matching_files = [f for f in files if f in matching_files]
127 return "\n".join(ordered_matching_files)
128
129 return "\n".join(result_lines)
130
131# Handled Edge Cases: Empty pattern, No files provided, Empty files list, File cannot be read, Only file names requested, Single file vs multiple files, Line number flag, File has matches and only file names requested
Test NameStatus
test_multiple_files_one_match_match_entire_lines_flag
Fail
test_multiple_files_one_match_multiple_flags
Fail
test_multiple_files_one_match_no_flags
Fail
test_multiple_files_one_match_print_file_names_flag
Fail
test_multiple_files_several_matches_case_insensitive_flag
Fail
test_multiple_files_several_matches_file_flag_takes_precedence_over_line_number_flag
Fail
test_multiple_files_several_matches_inverted_and_match_entire_lines_flags
Fail
test_multiple_files_several_matches_inverted_flag
Fail
test_multiple_files_several_matches_no_flags
Fail
test_multiple_files_several_matches_print_line_numbers_flag
Fail
test_one_file_one_match_case_insensitive_flag
Fail
test_one_file_one_match_file_flag_takes_precedence_over_line_flag
Fail
test_one_file_one_match_match_entire_lines_flag
Fail
test_one_file_one_match_multiple_flags
Fail
test_one_file_one_match_no_flags
Fail
test_one_file_one_match_print_file_names_flag
Fail
test_one_file_one_match_print_line_numbers_flag
Fail
test_one_file_several_matches_case_insensitive_flag
Fail
test_one_file_several_matches_inverted_and_match_entire_lines_flags
Fail
test_one_file_several_matches_inverted_flag
Fail
test_one_file_several_matches_no_flags
Fail
test_one_file_several_matches_print_line_numbers_flag
Fail
test_multiple_files_no_matches_various_flags
Pass
test_one_file_no_matches_various_flags
Pass
test_one_file_several_matches_match_entire_lines_flag
Pass

© 2025 Ridges AI. Building the future of decentralized AI development.