From a55a1200a0141127c148d2905618c87e613e98db Mon Sep 17 00:00:00 2001 From: Ed_ Date: Sun, 17 May 2026 12:40:10 -0400 Subject: [PATCH] last progress before ending last session --- src/file_cache.py | 59 +++++++++++++++++++++++++++++++++++++++-------- src/gui_2.py | 4 +--- src/summarize.py | 21 ++++++++++++++--- 3 files changed, 68 insertions(+), 16 deletions(-) diff --git a/src/file_cache.py b/src/file_cache.py index 0aa2aad9..98ac8444 100644 --- a/src/file_cache.py +++ b/src/file_cache.py @@ -205,30 +205,69 @@ class ASTParser: """ [C: src/mcp_client.py:_search_file, src/mcp_client.py:py_find_usages, src/mcp_client.py:py_get_hierarchy, src/mcp_client.py:trace, src/outline_tool.py:CodeOutliner.outline, src/outline_tool.py:CodeOutliner.walk, src/summarize.py:_summarise_python] """ - if node.type == "function_definition": - body = node.child_by_field_name("body") + if node.type in ("function_definition", "method_definition", "template_declaration"): + # If template, look for inner function/method + target_node = node + if node.type == "template_declaration": + for child in node.children: + if child.type in ("function_definition", "method_definition"): + target_node = child + break + + body = target_node.child_by_field_name("body") + if not body: + # C++ fallback: sometimes the body is just a compound_statement without a field name in certain contexts + for child in target_node.children: + if child.type in ("compound_statement", "block"): + body = child + break + if body and body.type in ("block", "compound_statement"): indent = " " * body.start_point.column first_stmt = None for child in body.children: - if child.type != "comment": + if child.type not in ("comment", "{", "}"): first_stmt = child break + initializer = None - for child in node.children: - if child.type == "field_initializer_list": - initializer = child - break + if self.language_name in ("cpp", "c"): + for child in target_node.children: + if child.type == "field_initializer_list": + initializer = child + break + if first_stmt and is_docstring(first_stmt): start_byte = first_stmt.end_byte end_byte = body.end_byte if end_byte > start_byte: - edits.append((start_byte, end_byte, f"\n{indent}...")) + # Keep closing brace if it exists + if body.children and body.children[-1].type in ("}", "end"): + end_byte = body.children[-1].start_byte + edits.append((start_byte, end_byte, f"\n{indent} ... ")) + else: + edits.append((start_byte, end_byte, f"\n{indent}...")) else: + # If there's an initializer list (C++), we strip it too or start from it start_byte = initializer.start_byte if initializer else body.start_byte end_byte = body.end_byte - repl = "..." - edits.append((start_byte, end_byte, repl)) + + # Try to preserve braces for C-style languages + if body.type == "compound_statement" and len(body.children) >= 2: + if body.children[0].type == "{" and body.children[-1].type == "}": + start_byte = body.children[0].end_byte + end_byte = body.children[-1].start_byte + edits.append((start_byte, end_byte, " ... ")) + else: + edits.append((start_byte, end_byte, "...")) + else: + edits.append((start_byte, end_byte, "...")) + + if node.type == "template_declaration": + # We handled the inner function body, so we should skip visiting its children + # but we still want to visit other siblings if any (unlikely for template) + pass + for child in node.children: walk(child) walk(tree.root_node) diff --git a/src/gui_2.py b/src/gui_2.py index 71732077..1d025e68 100644 --- a/src/gui_2.py +++ b/src/gui_2.py @@ -3279,9 +3279,7 @@ def render_context_presets(app: App) -> None: if ch: app.ui_active_context_preset = preset_names[new_idx] if preset_names[new_idx]: - app.controller.load_context_preset(preset_names[new_idx]) - app.controller._refresh_from_project() - app.context_files = list(app.controller.files) + app.load_context_preset(preset_names[new_idx]) imgui.table_next_column() if active: diff --git a/src/summarize.py b/src/summarize.py index 84c18c38..3c817c87 100644 --- a/src/summarize.py +++ b/src/summarize.py @@ -129,9 +129,24 @@ def _summarise_generic(path: Path, content: str) -> str: line_count = len(lines) suffix = path.suffix.lstrip(".").upper() or "TEXT" parts = [f"**{suffix}** — {line_count} lines"] - preview = lines[:8] - if preview: - parts.append("preview:\n```\n" + "\n".join(preview) + "\n```") + + # Heuristic for C-style languages + important_lines = [] + for line in lines[:200]: + trimmed = line.strip() + if not trimmed or trimmed.startswith("//") or trimmed.startswith("/*") or trimmed.startswith("*"): + continue + if re.match(r'^\s*(class|struct|namespace|enum|template|void|int|float|double|char|bool|virtual|static|inline|extern|#define|#include)\b', line): + important_lines.append(trimmed) + if len(important_lines) >= 15: + break + + if important_lines: + parts.append("Key elements / Outline:\n- " + "\n- ".join(important_lines)) + else: + preview = [l for l in lines[:10] if l.strip()] + if preview: + parts.append("preview:\n```\n" + "\n".join(preview) + "\n```") return "\n".join(parts) _SUMMARISERS: dict[str, Callable[[Path, str], str]] = {