tree-sitter-analyzer 0.2.0__py3-none-any.whl → 0.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of tree-sitter-analyzer might be problematic. Click here for more details.

Files changed (78) hide show
  1. tree_sitter_analyzer/__init__.py +133 -121
  2. tree_sitter_analyzer/__main__.py +11 -12
  3. tree_sitter_analyzer/api.py +531 -539
  4. tree_sitter_analyzer/cli/__init__.py +39 -39
  5. tree_sitter_analyzer/cli/__main__.py +12 -13
  6. tree_sitter_analyzer/cli/commands/__init__.py +26 -27
  7. tree_sitter_analyzer/cli/commands/advanced_command.py +88 -88
  8. tree_sitter_analyzer/cli/commands/base_command.py +160 -155
  9. tree_sitter_analyzer/cli/commands/default_command.py +18 -19
  10. tree_sitter_analyzer/cli/commands/partial_read_command.py +141 -133
  11. tree_sitter_analyzer/cli/commands/query_command.py +81 -82
  12. tree_sitter_analyzer/cli/commands/structure_command.py +138 -121
  13. tree_sitter_analyzer/cli/commands/summary_command.py +101 -93
  14. tree_sitter_analyzer/cli/commands/table_command.py +232 -233
  15. tree_sitter_analyzer/cli/info_commands.py +120 -121
  16. tree_sitter_analyzer/cli_main.py +277 -276
  17. tree_sitter_analyzer/core/__init__.py +15 -20
  18. tree_sitter_analyzer/core/analysis_engine.py +591 -574
  19. tree_sitter_analyzer/core/cache_service.py +320 -330
  20. tree_sitter_analyzer/core/engine.py +557 -560
  21. tree_sitter_analyzer/core/parser.py +293 -288
  22. tree_sitter_analyzer/core/query.py +494 -502
  23. tree_sitter_analyzer/encoding_utils.py +458 -460
  24. tree_sitter_analyzer/exceptions.py +337 -340
  25. tree_sitter_analyzer/file_handler.py +217 -222
  26. tree_sitter_analyzer/formatters/__init__.py +1 -1
  27. tree_sitter_analyzer/formatters/base_formatter.py +167 -168
  28. tree_sitter_analyzer/formatters/formatter_factory.py +78 -74
  29. tree_sitter_analyzer/formatters/java_formatter.py +287 -270
  30. tree_sitter_analyzer/formatters/python_formatter.py +255 -235
  31. tree_sitter_analyzer/interfaces/__init__.py +9 -10
  32. tree_sitter_analyzer/interfaces/cli.py +528 -557
  33. tree_sitter_analyzer/interfaces/cli_adapter.py +322 -319
  34. tree_sitter_analyzer/interfaces/mcp_adapter.py +180 -170
  35. tree_sitter_analyzer/interfaces/mcp_server.py +405 -416
  36. tree_sitter_analyzer/java_analyzer.py +218 -219
  37. tree_sitter_analyzer/language_detector.py +398 -400
  38. tree_sitter_analyzer/language_loader.py +224 -228
  39. tree_sitter_analyzer/languages/__init__.py +10 -11
  40. tree_sitter_analyzer/languages/java_plugin.py +1129 -1113
  41. tree_sitter_analyzer/languages/python_plugin.py +737 -712
  42. tree_sitter_analyzer/mcp/__init__.py +31 -32
  43. tree_sitter_analyzer/mcp/resources/__init__.py +44 -47
  44. tree_sitter_analyzer/mcp/resources/code_file_resource.py +212 -213
  45. tree_sitter_analyzer/mcp/resources/project_stats_resource.py +560 -550
  46. tree_sitter_analyzer/mcp/server.py +333 -345
  47. tree_sitter_analyzer/mcp/tools/__init__.py +30 -31
  48. tree_sitter_analyzer/mcp/tools/analyze_scale_tool.py +621 -557
  49. tree_sitter_analyzer/mcp/tools/analyze_scale_tool_cli_compatible.py +242 -245
  50. tree_sitter_analyzer/mcp/tools/base_tool.py +54 -55
  51. tree_sitter_analyzer/mcp/tools/read_partial_tool.py +300 -302
  52. tree_sitter_analyzer/mcp/tools/table_format_tool.py +362 -359
  53. tree_sitter_analyzer/mcp/tools/universal_analyze_tool.py +543 -476
  54. tree_sitter_analyzer/mcp/utils/__init__.py +105 -106
  55. tree_sitter_analyzer/mcp/utils/error_handler.py +549 -549
  56. tree_sitter_analyzer/models.py +470 -481
  57. tree_sitter_analyzer/output_manager.py +261 -264
  58. tree_sitter_analyzer/plugins/__init__.py +333 -334
  59. tree_sitter_analyzer/plugins/base.py +477 -446
  60. tree_sitter_analyzer/plugins/java_plugin.py +608 -625
  61. tree_sitter_analyzer/plugins/javascript_plugin.py +446 -439
  62. tree_sitter_analyzer/plugins/manager.py +362 -355
  63. tree_sitter_analyzer/plugins/plugin_loader.py +85 -83
  64. tree_sitter_analyzer/plugins/python_plugin.py +606 -598
  65. tree_sitter_analyzer/plugins/registry.py +374 -366
  66. tree_sitter_analyzer/queries/__init__.py +26 -27
  67. tree_sitter_analyzer/queries/java.py +391 -394
  68. tree_sitter_analyzer/queries/javascript.py +148 -149
  69. tree_sitter_analyzer/queries/python.py +285 -286
  70. tree_sitter_analyzer/queries/typescript.py +229 -230
  71. tree_sitter_analyzer/query_loader.py +254 -260
  72. tree_sitter_analyzer/table_formatter.py +468 -448
  73. tree_sitter_analyzer/utils.py +277 -277
  74. {tree_sitter_analyzer-0.2.0.dist-info → tree_sitter_analyzer-0.3.0.dist-info}/METADATA +21 -6
  75. tree_sitter_analyzer-0.3.0.dist-info/RECORD +77 -0
  76. tree_sitter_analyzer-0.2.0.dist-info/RECORD +0 -77
  77. {tree_sitter_analyzer-0.2.0.dist-info → tree_sitter_analyzer-0.3.0.dist-info}/WHEEL +0 -0
  78. {tree_sitter_analyzer-0.2.0.dist-info → tree_sitter_analyzer-0.3.0.dist-info}/entry_points.txt +0 -0
@@ -1,155 +1,160 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
- """
4
- Base Command Class
5
-
6
- Abstract base class for all CLI commands implementing the Command Pattern.
7
- """
8
-
9
- import asyncio
10
- from abc import ABC, abstractmethod
11
- from argparse import Namespace
12
- from typing import Any, Optional
13
-
14
- from ...core.analysis_engine import AnalysisRequest, get_analysis_engine
15
- from ...file_handler import read_file_partial
16
- from ...language_detector import detect_language_from_file, is_language_supported
17
- from ...models import AnalysisResult
18
- from ...output_manager import output_error, output_info
19
-
20
-
21
- class BaseCommand(ABC):
22
- """
23
- Base class for all CLI commands.
24
-
25
- Implements common functionality like file validation, language detection,
26
- and analysis engine interaction.
27
- """
28
-
29
- def __init__(self, args: Namespace):
30
- """Initialize command with parsed arguments."""
31
- self.args = args
32
- self.analysis_engine = get_analysis_engine()
33
-
34
- def validate_file(self) -> bool:
35
- """Validate input file exists and is accessible."""
36
- if not hasattr(self.args, "file_path") or not self.args.file_path:
37
- output_error("ERROR: File path not specified.")
38
- return False
39
-
40
- import os
41
-
42
- if not os.path.exists(self.args.file_path):
43
- output_error(f"ERROR: File not found: {self.args.file_path}")
44
- return False
45
-
46
- return True
47
-
48
- def detect_language(self) -> Optional[str]:
49
- """Detect or validate the target language."""
50
- if hasattr(self.args, "language") and self.args.language:
51
- target_language = self.args.language.lower()
52
- if (not hasattr(self.args, "table") or not self.args.table) and (not hasattr(self.args, "quiet") or not self.args.quiet):
53
- output_info(f"INFO: Language explicitly specified: {target_language}")
54
- else:
55
- target_language = detect_language_from_file(self.args.file_path)
56
- if target_language == "unknown":
57
- output_error(
58
- f"ERROR: Could not determine language for file '{self.args.file_path}'."
59
- )
60
- return None
61
- else:
62
- if (not hasattr(self.args, "table") or not self.args.table) and (not hasattr(self.args, "quiet") or not self.args.quiet):
63
- output_info(
64
- f"INFO: Language auto-detected from extension: {target_language}"
65
- )
66
-
67
- # Language support validation
68
- if not is_language_supported(target_language):
69
- if target_language != "java":
70
- if (not hasattr(self.args, "table") or not self.args.table) and (not hasattr(self.args, "quiet") or not self.args.quiet):
71
- output_info(
72
- "INFO: Trying with Java analysis engine. May not work correctly."
73
- )
74
- target_language = "java" # Fallback
75
-
76
- return target_language
77
-
78
- async def analyze_file(self, language: str) -> Optional["AnalysisResult"]:
79
- """Perform file analysis using the unified analysis engine."""
80
- try:
81
- # Handle partial read if enabled
82
- if hasattr(self.args, 'partial_read') and self.args.partial_read:
83
- try:
84
- partial_content = read_file_partial(
85
- self.args.file_path,
86
- start_line=self.args.start_line,
87
- end_line=getattr(self.args, 'end_line', None),
88
- start_column=getattr(self.args, 'start_column', None),
89
- end_column=getattr(self.args, 'end_column', None)
90
- )
91
- if partial_content is None:
92
- output_error("ERROR: Failed to read file partially")
93
- return None
94
- except Exception as e:
95
- output_error(f"ERROR: Failed to read file partially: {e}")
96
- return None
97
-
98
- request = AnalysisRequest(
99
- file_path=self.args.file_path,
100
- language=language,
101
- include_complexity=True,
102
- include_details=True,
103
- )
104
- analysis_result = await self.analysis_engine.analyze(request)
105
-
106
- if not analysis_result or not analysis_result.success:
107
- error_msg = (
108
- analysis_result.error_message
109
- if analysis_result
110
- else "Unknown error"
111
- )
112
- output_error(f"ERROR: Analysis failed: {error_msg}")
113
- return None
114
-
115
- return analysis_result
116
-
117
- except Exception as e:
118
- output_error(f"ERROR: An error occurred during analysis: {e}")
119
- return None
120
-
121
- def execute(self) -> int:
122
- """
123
- Execute the command.
124
-
125
- Returns:
126
- int: Exit code (0 for success, 1 for failure)
127
- """
128
- # Validate inputs
129
- if not self.validate_file():
130
- return 1
131
-
132
- # Detect language
133
- language = self.detect_language()
134
- if not language:
135
- return 1
136
-
137
- # Execute the specific command
138
- try:
139
- return asyncio.run(self.execute_async(language))
140
- except Exception as e:
141
- output_error(f"ERROR: An error occurred during command execution: {e}")
142
- return 1
143
-
144
- @abstractmethod
145
- async def execute_async(self, language: str) -> int:
146
- """
147
- Execute the command asynchronously.
148
-
149
- Args:
150
- language: Detected/specified target language
151
-
152
- Returns:
153
- int: Exit code (0 for success, 1 for failure)
154
- """
155
- pass
1
+ #!/usr/bin/env python3
2
+ """
3
+ Base Command Class
4
+
5
+ Abstract base class for all CLI commands implementing the Command Pattern.
6
+ """
7
+
8
+ import asyncio
9
+ from abc import ABC, abstractmethod
10
+ from argparse import Namespace
11
+ from typing import Optional
12
+
13
+ from ...core.analysis_engine import AnalysisRequest, get_analysis_engine
14
+ from ...file_handler import read_file_partial
15
+ from ...language_detector import detect_language_from_file, is_language_supported
16
+ from ...models import AnalysisResult
17
+ from ...output_manager import output_error, output_info
18
+
19
+
20
+ class BaseCommand(ABC):
21
+ """
22
+ Base class for all CLI commands.
23
+
24
+ Implements common functionality like file validation, language detection,
25
+ and analysis engine interaction.
26
+ """
27
+
28
+ def __init__(self, args: Namespace):
29
+ """Initialize command with parsed arguments."""
30
+ self.args = args
31
+ self.analysis_engine = get_analysis_engine()
32
+
33
+ def validate_file(self) -> bool:
34
+ """Validate input file exists and is accessible."""
35
+ if not hasattr(self.args, "file_path") or not self.args.file_path:
36
+ output_error("ERROR: File path not specified.")
37
+ return False
38
+
39
+ import os
40
+
41
+ if not os.path.exists(self.args.file_path):
42
+ output_error(f"ERROR: File not found: {self.args.file_path}")
43
+ return False
44
+
45
+ return True
46
+
47
+ def detect_language(self) -> str | None:
48
+ """Detect or validate the target language."""
49
+ if hasattr(self.args, "language") and self.args.language:
50
+ target_language = self.args.language.lower()
51
+ if (not hasattr(self.args, "table") or not self.args.table) and (
52
+ not hasattr(self.args, "quiet") or not self.args.quiet
53
+ ):
54
+ output_info(f"INFO: Language explicitly specified: {target_language}")
55
+ else:
56
+ target_language = detect_language_from_file(self.args.file_path)
57
+ if target_language == "unknown":
58
+ output_error(
59
+ f"ERROR: Could not determine language for file '{self.args.file_path}'."
60
+ )
61
+ return None
62
+ else:
63
+ if (not hasattr(self.args, "table") or not self.args.table) and (
64
+ not hasattr(self.args, "quiet") or not self.args.quiet
65
+ ):
66
+ output_info(
67
+ f"INFO: Language auto-detected from extension: {target_language}"
68
+ )
69
+
70
+ # Language support validation
71
+ if not is_language_supported(target_language):
72
+ if target_language != "java":
73
+ if (not hasattr(self.args, "table") or not self.args.table) and (
74
+ not hasattr(self.args, "quiet") or not self.args.quiet
75
+ ):
76
+ output_info(
77
+ "INFO: Trying with Java analysis engine. May not work correctly."
78
+ )
79
+ target_language = "java" # Fallback
80
+
81
+ return target_language
82
+
83
+ async def analyze_file(self, language: str) -> Optional["AnalysisResult"]:
84
+ """Perform file analysis using the unified analysis engine."""
85
+ try:
86
+ # Handle partial read if enabled
87
+ if hasattr(self.args, "partial_read") and self.args.partial_read:
88
+ try:
89
+ partial_content = read_file_partial(
90
+ self.args.file_path,
91
+ start_line=self.args.start_line,
92
+ end_line=getattr(self.args, "end_line", None),
93
+ start_column=getattr(self.args, "start_column", None),
94
+ end_column=getattr(self.args, "end_column", None),
95
+ )
96
+ if partial_content is None:
97
+ output_error("ERROR: Failed to read file partially")
98
+ return None
99
+ except Exception as e:
100
+ output_error(f"ERROR: Failed to read file partially: {e}")
101
+ return None
102
+
103
+ request = AnalysisRequest(
104
+ file_path=self.args.file_path,
105
+ language=language,
106
+ include_complexity=True,
107
+ include_details=True,
108
+ )
109
+ analysis_result = await self.analysis_engine.analyze(request)
110
+
111
+ if not analysis_result or not analysis_result.success:
112
+ error_msg = (
113
+ analysis_result.error_message
114
+ if analysis_result
115
+ else "Unknown error"
116
+ )
117
+ output_error(f"ERROR: Analysis failed: {error_msg}")
118
+ return None
119
+
120
+ return analysis_result
121
+
122
+ except Exception as e:
123
+ output_error(f"ERROR: An error occurred during analysis: {e}")
124
+ return None
125
+
126
+ def execute(self) -> int:
127
+ """
128
+ Execute the command.
129
+
130
+ Returns:
131
+ int: Exit code (0 for success, 1 for failure)
132
+ """
133
+ # Validate inputs
134
+ if not self.validate_file():
135
+ return 1
136
+
137
+ # Detect language
138
+ language = self.detect_language()
139
+ if not language:
140
+ return 1
141
+
142
+ # Execute the specific command
143
+ try:
144
+ return asyncio.run(self.execute_async(language))
145
+ except Exception as e:
146
+ output_error(f"ERROR: An error occurred during command execution: {e}")
147
+ return 1
148
+
149
+ @abstractmethod
150
+ async def execute_async(self, language: str) -> int:
151
+ """
152
+ Execute the command asynchronously.
153
+
154
+ Args:
155
+ language: Detected/specified target language
156
+
157
+ Returns:
158
+ int: Exit code (0 for success, 1 for failure)
159
+ """
160
+ pass
@@ -1,19 +1,18 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
- """
4
- Default Command
5
-
6
- Handles default analysis when no specific command is specified.
7
- """
8
-
9
- from ...output_manager import output_error
10
- from .base_command import BaseCommand
11
-
12
-
13
- class DefaultCommand(BaseCommand):
14
- """Default command that shows error when no specific command is given."""
15
-
16
- async def execute_async(self, language: str) -> int:
17
- """Execute default command - show error for missing options."""
18
- output_error("ERROR: クエリまたは--advancedオプションを指定してください")
19
- return 1
1
+ #!/usr/bin/env python3
2
+ """
3
+ Default Command
4
+
5
+ Handles default analysis when no specific command is specified.
6
+ """
7
+
8
+ from ...output_manager import output_error
9
+ from .base_command import BaseCommand
10
+
11
+
12
+ class DefaultCommand(BaseCommand):
13
+ """Default command that shows error when no specific command is given."""
14
+
15
+ async def execute_async(self, language: str) -> int:
16
+ """Execute default command - show error for missing options."""
17
+ output_error("ERROR: クエリまたは--advancedオプションを指定してください")
18
+ return 1
@@ -1,133 +1,141 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
- """
4
- Partial Read Command
5
-
6
- Handles partial file reading functionality, extracting specified line ranges.
7
- """
8
- import json
9
- from typing import TYPE_CHECKING
10
-
11
- from ...file_handler import read_file_partial
12
- from ...output_manager import output_data, output_json, output_section
13
- from .base_command import BaseCommand
14
-
15
- if TYPE_CHECKING:
16
- pass
17
-
18
-
19
- class PartialReadCommand(BaseCommand):
20
- """Command for reading partial file content by line range."""
21
-
22
- def __init__(self, args):
23
- """Initialize with arguments but skip base class analysis engine setup."""
24
- self.args = args
25
- # Don't call super().__init__() to avoid unnecessary analysis engine setup
26
-
27
- def validate_file(self) -> bool:
28
- """Validate input file exists and is accessible."""
29
- if not hasattr(self.args, "file_path") or not self.args.file_path:
30
- from ...output_manager import output_error
31
- output_error("ERROR: File path not specified.")
32
- return False
33
-
34
- import os
35
-
36
- if not os.path.exists(self.args.file_path):
37
- from ...output_manager import output_error
38
- output_error(f"ERROR: File not found: {self.args.file_path}")
39
- return False
40
-
41
- return True
42
-
43
- def execute(self) -> int:
44
- """
45
- Execute partial read command.
46
-
47
- Returns:
48
- int: Exit code (0 for success, 1 for failure)
49
- """
50
- # Validate inputs
51
- if not self.validate_file():
52
- return 1
53
-
54
- # Validate partial read arguments
55
- if not self.args.start_line:
56
- from ...output_manager import output_error
57
- output_error("ERROR: --start-line is required")
58
- return 1
59
-
60
- if self.args.start_line < 1:
61
- from ...output_manager import output_error
62
- output_error("ERROR: --start-line must be 1 or greater")
63
- return 1
64
-
65
- if self.args.end_line and self.args.end_line < self.args.start_line:
66
- from ...output_manager import output_error
67
- output_error("ERROR: --end-line must be greater than or equal to --start-line")
68
- return 1
69
-
70
- # Read partial content
71
- try:
72
- partial_content = read_file_partial(
73
- self.args.file_path,
74
- start_line=self.args.start_line,
75
- end_line=getattr(self.args, 'end_line', None),
76
- start_column=getattr(self.args, 'start_column', None),
77
- end_column=getattr(self.args, 'end_column', None)
78
- )
79
-
80
- if partial_content is None:
81
- from ...output_manager import output_error
82
- output_error("ERROR: Failed to read file partially")
83
- return 1
84
-
85
- # Output the result
86
- self._output_partial_content(partial_content)
87
- return 0
88
-
89
- except Exception as e:
90
- from ...output_manager import output_error
91
- output_error(f"ERROR: Failed to read file partially: {e}")
92
- return 1
93
-
94
- def _output_partial_content(self, content: str) -> None:
95
- """Output the partial content in the specified format."""
96
- # Build result data
97
- result_data = {
98
- "file_path": self.args.file_path,
99
- "range": {
100
- "start_line": self.args.start_line,
101
- "end_line": getattr(self.args, 'end_line', None),
102
- "start_column": getattr(self.args, 'start_column', None),
103
- "end_column": getattr(self.args, 'end_column', None),
104
- },
105
- "content": content,
106
- "content_length": len(content),
107
- }
108
-
109
- # Build range info for header
110
- range_info = f"Line {self.args.start_line}"
111
- if hasattr(self.args, 'end_line') and self.args.end_line:
112
- range_info += f"-{self.args.end_line}"
113
-
114
- # Output format selection
115
- output_format = getattr(self.args, 'output_format', 'text')
116
-
117
- if output_format == 'json':
118
- # Pure JSON output
119
- output_json(result_data)
120
- else:
121
- # Human-readable format with header
122
- output_section("Partial Read Result")
123
- output_data(f"File: {self.args.file_path}")
124
- output_data(f"Range: {range_info}")
125
- output_data(f"Characters read: {len(content)}")
126
- output_data("") # Empty line for separation
127
-
128
- # Output the actual content
129
- print(content, end='') # Use print to avoid extra formatting
130
-
131
- async def execute_async(self, language: str) -> int:
132
- """Not used for partial read command."""
133
- return self.execute()
1
+ #!/usr/bin/env python3
2
+ """
3
+ Partial Read Command
4
+
5
+ Handles partial file reading functionality, extracting specified line ranges.
6
+ """
7
+
8
+ from typing import TYPE_CHECKING
9
+
10
+ from ...file_handler import read_file_partial
11
+ from ...output_manager import output_data, output_json, output_section
12
+ from .base_command import BaseCommand
13
+
14
+ if TYPE_CHECKING:
15
+ pass
16
+
17
+
18
+ class PartialReadCommand(BaseCommand):
19
+ """Command for reading partial file content by line range."""
20
+
21
+ def __init__(self, args):
22
+ """Initialize with arguments but skip base class analysis engine setup."""
23
+ self.args = args
24
+ # Don't call super().__init__() to avoid unnecessary analysis engine setup
25
+
26
+ def validate_file(self) -> bool:
27
+ """Validate input file exists and is accessible."""
28
+ if not hasattr(self.args, "file_path") or not self.args.file_path:
29
+ from ...output_manager import output_error
30
+
31
+ output_error("ERROR: File path not specified.")
32
+ return False
33
+
34
+ import os
35
+
36
+ if not os.path.exists(self.args.file_path):
37
+ from ...output_manager import output_error
38
+
39
+ output_error(f"ERROR: File not found: {self.args.file_path}")
40
+ return False
41
+
42
+ return True
43
+
44
+ def execute(self) -> int:
45
+ """
46
+ Execute partial read command.
47
+
48
+ Returns:
49
+ int: Exit code (0 for success, 1 for failure)
50
+ """
51
+ # Validate inputs
52
+ if not self.validate_file():
53
+ return 1
54
+
55
+ # Validate partial read arguments
56
+ if not self.args.start_line:
57
+ from ...output_manager import output_error
58
+
59
+ output_error("ERROR: --start-line is required")
60
+ return 1
61
+
62
+ if self.args.start_line < 1:
63
+ from ...output_manager import output_error
64
+
65
+ output_error("ERROR: --start-line must be 1 or greater")
66
+ return 1
67
+
68
+ if self.args.end_line and self.args.end_line < self.args.start_line:
69
+ from ...output_manager import output_error
70
+
71
+ output_error(
72
+ "ERROR: --end-line must be greater than or equal to --start-line"
73
+ )
74
+ return 1
75
+
76
+ # Read partial content
77
+ try:
78
+ partial_content = read_file_partial(
79
+ self.args.file_path,
80
+ start_line=self.args.start_line,
81
+ end_line=getattr(self.args, "end_line", None),
82
+ start_column=getattr(self.args, "start_column", None),
83
+ end_column=getattr(self.args, "end_column", None),
84
+ )
85
+
86
+ if partial_content is None:
87
+ from ...output_manager import output_error
88
+
89
+ output_error("ERROR: Failed to read file partially")
90
+ return 1
91
+
92
+ # Output the result
93
+ self._output_partial_content(partial_content)
94
+ return 0
95
+
96
+ except Exception as e:
97
+ from ...output_manager import output_error
98
+
99
+ output_error(f"ERROR: Failed to read file partially: {e}")
100
+ return 1
101
+
102
+ def _output_partial_content(self, content: str) -> None:
103
+ """Output the partial content in the specified format."""
104
+ # Build result data
105
+ result_data = {
106
+ "file_path": self.args.file_path,
107
+ "range": {
108
+ "start_line": self.args.start_line,
109
+ "end_line": getattr(self.args, "end_line", None),
110
+ "start_column": getattr(self.args, "start_column", None),
111
+ "end_column": getattr(self.args, "end_column", None),
112
+ },
113
+ "content": content,
114
+ "content_length": len(content),
115
+ }
116
+
117
+ # Build range info for header
118
+ range_info = f"Line {self.args.start_line}"
119
+ if hasattr(self.args, "end_line") and self.args.end_line:
120
+ range_info += f"-{self.args.end_line}"
121
+
122
+ # Output format selection
123
+ output_format = getattr(self.args, "output_format", "text")
124
+
125
+ if output_format == "json":
126
+ # Pure JSON output
127
+ output_json(result_data)
128
+ else:
129
+ # Human-readable format with header
130
+ output_section("Partial Read Result")
131
+ output_data(f"File: {self.args.file_path}")
132
+ output_data(f"Range: {range_info}")
133
+ output_data(f"Characters read: {len(content)}")
134
+ output_data("") # Empty line for separation
135
+
136
+ # Output the actual content
137
+ print(content, end="") # Use print to avoid extra formatting
138
+
139
+ async def execute_async(self, language: str) -> int:
140
+ """Not used for partial read command."""
141
+ return self.execute()