diff --git a/codemcp/code_command.py b/codemcp/code_command.py index 6789bbb..a042df4 100644 --- a/codemcp/code_command.py +++ b/codemcp/code_command.py @@ -8,6 +8,7 @@ import tomli from .common import normalize_file_path, truncate_output_content +from .file_utils import async_open_text from .git import commit_changes, get_repository_root, is_git_repository from .shell import run_command @@ -218,14 +219,15 @@ async def run_code_command( return f"Error: {error_msg}" -async def run_formatter_without_commit(file_path: str) -> Tuple[bool, str]: +async def run_formatter_without_commit(file_path: str) -> Tuple[bool, str, str]: """Run the formatter on a specific file without performing pre/post commit operations. Args: file_path: Absolute path to the file to format Returns: - A tuple containing (success_status, message) + A tuple containing (success_status, message, post_format_content) + The post_format_content will be an empty string if formatting failed Raises: Propagates any unexpected errors during formatting @@ -236,7 +238,7 @@ async def run_formatter_without_commit(file_path: str) -> Tuple[bool, str]: # Get the format command from config - this is the only expected failure mode format_command = get_command_from_config(project_dir, "format") if not format_command: - return False, "No format command configured in codemcp.toml" + return False, "No format command configured in codemcp.toml", "" # Use relative path from project_dir for the formatting command rel_path = os.path.relpath(file_path, project_dir) @@ -251,6 +253,18 @@ async def run_formatter_without_commit(file_path: str) -> Tuple[bool, str]: text=True, ) + # Read the file after formatting to get the current content + post_format_content = "" + if os.path.exists(file_path): + try: + post_format_content = await async_open_text(file_path, encoding="utf-8") + except Exception as e: + logging.warning(f"Failed to read formatted file: {e}") + # If we get here, the formatter ran successfully truncated_stdout = truncate_output_content(result.stdout, prefer_end=True) - return True, f"File formatted successfully:\n{truncated_stdout}" + return ( + True, + f"File formatted successfully:\n{truncated_stdout}", + post_format_content, + ) diff --git a/codemcp/tools/write_file.py b/codemcp/tools/write_file.py index 3efa8f4..2877253 100644 --- a/codemcp/tools/write_file.py +++ b/codemcp/tools/write_file.py @@ -65,11 +65,27 @@ async def write_file_content( # Try to run the formatter on the file format_message = "" - formatter_success, formatter_output = await run_formatter_without_commit(file_path) + post_format_content = content + ( + formatter_success, + formatter_output, + post_format_content, + ) = await run_formatter_without_commit(file_path) if formatter_success: logging.info(f"Auto-formatted {file_path}") if formatter_output.strip(): - format_message = f"\nAuto-formatted the file" + # If the file was actually changed by the formatter + if post_format_content and post_format_content != content: + # Update the content in memory (it's already updated on disk) + content = post_format_content + + # Show a snippet of the formatted content (first few lines) + lines = post_format_content.split("\n") + snippet_lines = min(7, len(lines)) # Show up to 7 lines + snippet = "\n".join(lines[:snippet_lines]) + format_message = ( + f"\nAuto-formatted the file. Here's how it looks now:\n{snippet}" + ) else: # Only log warning if there was actually a format command configured but it failed if not "No format command configured" in formatter_output: