Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 40 additions & 1 deletion codemcp/code_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import logging
import os
import subprocess
from typing import Any, Dict, List, Optional, cast
from typing import Any, Dict, List, Optional, Tuple, cast

import tomli

Expand All @@ -15,6 +15,7 @@
"get_command_from_config",
"check_for_changes",
"run_code_command",
"run_formatter_without_commit",
]


Expand Down Expand Up @@ -215,3 +216,41 @@ async def run_code_command(
error_msg = f"Error during {command_name}: {e}"
logging.error(error_msg)
return f"Error: {error_msg}"


async def run_formatter_without_commit(file_path: str) -> Tuple[bool, 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)

Raises:
Propagates any unexpected errors during formatting
"""
# Get the project directory (repository root)
project_dir = await get_repository_root(file_path)

# 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"

# Use relative path from project_dir for the formatting command
rel_path = os.path.relpath(file_path, project_dir)

# Run the formatter with the specific file path
command = format_command + [rel_path]
result = await run_command(
command,
cwd=project_dir,
check=True,
capture_output=True,
text=True,
)

# 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}"
19 changes: 18 additions & 1 deletion codemcp/tools/edit_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from difflib import SequenceMatcher
from typing import Any, Dict, List, Tuple

from ..code_command import run_formatter_without_commit
from ..common import get_edit_snippet
from ..file_utils import (
async_open_text,
Expand Down Expand Up @@ -773,6 +774,22 @@ async def edit_file_content(
if read_file_timestamps is not None:
read_file_timestamps[full_file_path] = os.stat(full_file_path).st_mtime

# Try to run the formatter on the file
format_message = ""
formatter_success, formatter_output = await run_formatter_without_commit(
full_file_path
)
if formatter_success:
logger.info(f"Auto-formatted {full_file_path}")
if formatter_output.strip():
format_message = "\nAuto-formatted the file"
else:
# Only log warning if there was actually a format command configured but it failed
if not "No format command configured" in formatter_output:
logger.warning(
f"Failed to auto-format {full_file_path}: {formatter_output}"
)

# Generate a snippet of the edited file to show in the response
snippet = get_edit_snippet(content, old_string, new_string)

Expand All @@ -787,4 +804,4 @@ async def edit_file_content(
else:
git_message = f"\n\nFailed to commit changes to git: {message}"

return f"Successfully edited {full_file_path}\n\nHere's a snippet of the edited file:\n{snippet}{git_message}"
return f"Successfully edited {full_file_path}\n\nHere's a snippet of the edited file:\n{snippet}{format_message}{git_message}"
16 changes: 15 additions & 1 deletion codemcp/tools/write_file.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#!/usr/bin/env python3

import logging
import os

from ..code_command import run_formatter_without_commit
from ..file_utils import (
check_file_path_and_permissions,
check_git_tracking_for_existing_file,
Expand Down Expand Up @@ -61,6 +63,18 @@ async def write_file_content(
# Write the content with UTF-8 encoding and proper line endings
await write_text_content(file_path, content, "utf-8", line_endings)

# Try to run the formatter on the file
format_message = ""
formatter_success, formatter_output = 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"
else:
# Only log warning if there was actually a format command configured but it failed
if not "No format command configured" in formatter_output:
logging.warning(f"Failed to auto-format {file_path}: {formatter_output}")

# Commit the changes
git_message = ""
success, message = await commit_changes(file_path, description, chat_id)
Expand All @@ -69,4 +83,4 @@ async def write_file_content(
else:
git_message = f"\nFailed to commit changes to git: {message}"

return f"Successfully wrote to {file_path}{git_message}"
return f"Successfully wrote to {file_path}{format_message}{git_message}"