Implement the view command
(self, path: Path, view_range: Optional[List[int]] = None)
| 481 | self.logs.append(f"File created successfully at: {self._get_display_path(path)}") |
| 482 | |
| 483 | def view(self, path: Path, view_range: Optional[List[int]] = None): |
| 484 | """Implement the view command""" |
| 485 | if path.is_dir(): |
| 486 | if view_range: |
| 487 | self.logs.append("The `view_range` parameter is not allowed when `path` points to a directory.") |
| 488 | return |
| 489 | |
| 490 | out = subprocess.run( |
| 491 | rf"find {path} -maxdepth 2 -not -path '*/\.*'", |
| 492 | shell=True, |
| 493 | stdout=subprocess.PIPE, |
| 494 | stderr=subprocess.PIPE, |
| 495 | ) |
| 496 | # Use errors="replace" so non-UTF-8 bytes (e.g. GBK-encoded filenames on Windows) don't crash decoding. |
| 497 | stdout = out.stdout.decode("utf-8", errors="replace") |
| 498 | stderr = out.stderr.decode("utf-8", errors="replace") |
| 499 | |
| 500 | if not stderr: |
| 501 | stdout = stdout.replace(str(path), self._get_display_path(path)) |
| 502 | stdout = f"Here's the files and directories up to 2 levels deep in {self._get_display_path(path)}, excluding hidden items:\n{stdout}\n" |
| 503 | self.logs.append(stdout) |
| 504 | return |
| 505 | |
| 506 | file_content = self.read_file(path) |
| 507 | if view_range: |
| 508 | if len(view_range) != 2 or not all(isinstance(i, int) for i in view_range): |
| 509 | self.logs.append("Invalid `view_range`. It should be a list of two integers.") |
| 510 | return |
| 511 | file_lines = file_content.split("\n") |
| 512 | n_lines_file = len(file_lines) |
| 513 | init_line, final_line = view_range |
| 514 | if init_line < 1 or init_line > n_lines_file: |
| 515 | self.logs.append( |
| 516 | f"Invalid `view_range`: {view_range}. Its first element `{init_line}` should be within the range of lines of the file: {[1, n_lines_file]}" |
| 517 | ) |
| 518 | return |
| 519 | if final_line > n_lines_file: |
| 520 | self.logs.append( |
| 521 | f"Invalid `view_range`: {view_range}. Its second element `{final_line}` should be smaller than the number of lines in the file: `{n_lines_file}`" |
| 522 | ) |
| 523 | return |
| 524 | if final_line != -1 and final_line < init_line: |
| 525 | self.logs.append( |
| 526 | f"Invalid `view_range`: {view_range}. Its second element `{final_line}` should be larger or equal than its first `{init_line}`" |
| 527 | ) |
| 528 | return |
| 529 | |
| 530 | if final_line == -1: |
| 531 | final_line = n_lines_file |
| 532 | |
| 533 | # Expand the viewport to include the whole function or class |
| 534 | init_line, final_line = WindowExpander(suffix=path.suffix).expand_window( |
| 535 | file_lines, init_line, final_line, max_added_lines=MAX_WINDOW_EXPANSION_VIEW |
| 536 | ) |
| 537 | |
| 538 | file_content = "\n".join(file_lines[init_line - 1 : final_line]) |
| 539 | else: |
| 540 | if path.suffix == ".py" and len(file_content) > MAX_RESPONSE_LEN and USE_FILEMAP: |
no test coverage detected