Progress on context composition
This commit is contained in:
+1
-1
@@ -50,7 +50,7 @@ This file tracks all major tracks for the project. Each track has its own detail
|
|||||||
*Link: [./tracks/context_comp_slices_20260510/](./tracks/context_comp_slices_20260510/)*
|
*Link: [./tracks/context_comp_slices_20260510/](./tracks/context_comp_slices_20260510/)*
|
||||||
*Goal: Enhance slice visualization with visual editor, annotation support (tags/comments), and view presets.*
|
*Goal: Enhance slice visualization with visual editor, annotation support (tags/comments), and view presets.*
|
||||||
|
|
||||||
14. [ ] **Track: Context Preview & Slice Editor Fixes**
|
14. [~] **Track: Context Preview & Slice Editor Fixes**
|
||||||
*Link: [./tracks/context_preview_fixes_20260516/](./tracks/context_preview_fixes_20260516/)*
|
*Link: [./tracks/context_preview_fixes_20260516/](./tracks/context_preview_fixes_20260516/)*
|
||||||
*Goal: Fix Preview button generating empty content, and Inspect/Slices buttons failing to open their respective editor panels.*
|
*Goal: Fix Preview button generating empty content, and Inspect/Slices buttons failing to open their respective editor panels.*
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import sys
|
||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
sys.path.insert(0, str(Path(__file__).parent.parent.resolve()))
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
from simulation.sim_base import run_sim
|
||||||
|
from simulation.sim_tools import click_tab, click_button_by_label
|
||||||
|
from src.gui_2 import App
|
||||||
|
from src.models import FileItem
|
||||||
|
|
||||||
|
async def verify_preview(app: App):
|
||||||
|
# Let the GUI render once
|
||||||
|
await asyncio.sleep(0.1)
|
||||||
|
|
||||||
|
app.context_files = [FileItem(path='src/aggregate.py', auto_aggregate=True)]
|
||||||
|
app.controller.context_files = app.context_files
|
||||||
|
|
||||||
|
# Try rendering _render_files_and_media
|
||||||
|
app.show_windows["Context Preview"] = True
|
||||||
|
|
||||||
|
await asyncio.sleep(0.1)
|
||||||
|
click_tab(app, "Context Composition")
|
||||||
|
await asyncio.sleep(0.1)
|
||||||
|
|
||||||
|
click_button_by_label(app, "Preview##ctx")
|
||||||
|
await asyncio.sleep(0.2)
|
||||||
|
|
||||||
|
print("--- PREVIEW TEXT ---")
|
||||||
|
print(repr(app.context_preview_text[:200]))
|
||||||
|
print("--------------------")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
os.environ['SLOP_TEST_HOOKS'] = '1'
|
||||||
|
run_sim(verify_preview)
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
import sys
|
||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
# Fix sys.path
|
||||||
|
current_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
project_root = os.path.dirname(current_dir)
|
||||||
|
src_dir = os.path.join(project_root, "src")
|
||||||
|
|
||||||
|
for d in [project_root, src_dir]:
|
||||||
|
if d not in sys.path:
|
||||||
|
sys.path.insert(0, d)
|
||||||
|
|
||||||
|
# Ensure thirdparty is in sys.path
|
||||||
|
thirdparty = os.path.join(project_root, "thirdparty")
|
||||||
|
if thirdparty not in sys.path:
|
||||||
|
sys.path.insert(0, thirdparty)
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
from simulation.sim_base import BaseSimulation, run_sim
|
||||||
|
from src.gui_2 import App
|
||||||
|
from src.models import FileItem
|
||||||
|
|
||||||
|
class VerifyTrackFixesSim(BaseSimulation):
|
||||||
|
async def run(self):
|
||||||
|
app = self.app
|
||||||
|
print("[Sim] Starting verification of track fixes...")
|
||||||
|
|
||||||
|
# 1. Setup a test file in context
|
||||||
|
test_file = os.path.abspath("src/aggregate.py")
|
||||||
|
f_item = FileItem(path=test_file)
|
||||||
|
app.context_files = [f_item]
|
||||||
|
app.controller.context_files = app.context_files
|
||||||
|
|
||||||
|
await asyncio.sleep(0.5)
|
||||||
|
|
||||||
|
# 2. Verify AST Inspector
|
||||||
|
print("[Sim] Testing AST Inspector...")
|
||||||
|
app.ui_inspecting_ast_file = f_item
|
||||||
|
app._show_ast_inspector = True
|
||||||
|
await asyncio.sleep(0.5)
|
||||||
|
|
||||||
|
# Check if nodes were cached
|
||||||
|
if app._cached_ast_nodes:
|
||||||
|
print(f"[Sim] SUCCESS: AST nodes cached ({len(app._cached_ast_nodes)} nodes)")
|
||||||
|
else:
|
||||||
|
print("[Sim] FAILURE: No AST nodes cached")
|
||||||
|
|
||||||
|
# 3. Verify Slice Editor
|
||||||
|
print("[Sim] Testing Slice Editor...")
|
||||||
|
app.ui_editing_slices_file = f_item
|
||||||
|
app.text_viewer_title = f"Slices: {test_file}"
|
||||||
|
from src import mcp_client
|
||||||
|
app.text_viewer_content = mcp_client.read_file(test_file)
|
||||||
|
app.text_viewer_type = "python"
|
||||||
|
app.show_text_viewer = True
|
||||||
|
app.show_windows["Text Viewer"] = True
|
||||||
|
await asyncio.sleep(0.5)
|
||||||
|
|
||||||
|
# Test Auto-Populate button
|
||||||
|
print("[Sim] Testing Auto-Populate AST Slices...")
|
||||||
|
app._populate_auto_slices(f_item)
|
||||||
|
if f_item.custom_slices:
|
||||||
|
print(f"[Sim] SUCCESS: Auto-slices populated ({len(f_item.custom_slices)} slices)")
|
||||||
|
else:
|
||||||
|
print("[Sim] FAILURE: No auto-slices populated")
|
||||||
|
|
||||||
|
# 4. Verify Context Preview
|
||||||
|
print("[Sim] Testing Context Preview...")
|
||||||
|
app.context_preview_text = app.controller._do_generate()[0]
|
||||||
|
if "## Files" in app.context_preview_text and "aggregate.py" in app.context_preview_text:
|
||||||
|
print("[Sim] SUCCESS: Context preview generated with content")
|
||||||
|
else:
|
||||||
|
print(f"[Sim] FAILURE: Context preview text length: {len(app.context_preview_text)}")
|
||||||
|
|
||||||
|
print("[Sim] Verification finished.")
|
||||||
|
self.stop()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
os.environ['SLOP_TEST_HOOKS'] = '1'
|
||||||
|
run_sim(VerifyTrackFixesSim)
|
||||||
@@ -205,12 +205,20 @@ def build_file_items(base_dir: Path, files: list[str | dict[str, Any]]) -> list[
|
|||||||
if path.suffix == ".py":
|
if path.suffix == ".py":
|
||||||
if not parser: parser = ASTParser("python")
|
if not parser: parser = ASTParser("python")
|
||||||
content = parser.get_skeleton(content, path=str(path))
|
content = parser.get_skeleton(content, path=str(path))
|
||||||
|
elif path.suffix in ['.c', '.h', '.cpp', '.hpp', '.cxx', '.cc']:
|
||||||
|
from src import mcp_client
|
||||||
|
if path.suffix in ['.c', '.h']: content = mcp_client.ts_c_get_skeleton(str(path))
|
||||||
|
else: content = mcp_client.ts_cpp_get_skeleton(str(path))
|
||||||
else:
|
else:
|
||||||
content = summarize.summarise_file(path, content)
|
content = summarize.summarise_file(path, content)
|
||||||
elif view_mode == "outline":
|
elif view_mode == "outline":
|
||||||
if path.suffix == ".py":
|
if path.suffix == ".py":
|
||||||
if not parser: parser = ASTParser("python")
|
if not parser: parser = ASTParser("python")
|
||||||
content = parser.get_code_outline(content, path=str(path))
|
content = parser.get_code_outline(content, path=str(path))
|
||||||
|
elif path.suffix in ['.c', '.h', '.cpp', '.hpp', '.cxx', '.cc']:
|
||||||
|
from src import mcp_client
|
||||||
|
if path.suffix in ['.c', '.h']: content = mcp_client.ts_c_get_code_outline(str(path))
|
||||||
|
else: content = mcp_client.ts_cpp_get_code_outline(str(path))
|
||||||
else:
|
else:
|
||||||
content = summarize.summarise_file(path, content)
|
content = summarize.summarise_file(path, content)
|
||||||
elif view_mode == "none":
|
elif view_mode == "none":
|
||||||
|
|||||||
@@ -955,6 +955,7 @@ class AppController:
|
|||||||
self.ui_new_track_name: str = ""
|
self.ui_new_track_name: str = ""
|
||||||
self.ui_new_track_desc: str = ""
|
self.ui_new_track_desc: str = ""
|
||||||
self.ui_new_track_type: str = "feature"
|
self.ui_new_track_type: str = "feature"
|
||||||
|
self.ui_project_conductor_dir: str = ""
|
||||||
self.ui_conductor_setup_summary: str = ""
|
self.ui_conductor_setup_summary: str = ""
|
||||||
self.ui_last_script_text: str = ""
|
self.ui_last_script_text: str = ""
|
||||||
self.ui_last_script_output: str = ""
|
self.ui_last_script_output: str = ""
|
||||||
|
|||||||
+62
-12
@@ -18,6 +18,13 @@ import time
|
|||||||
import tomli_w
|
import tomli_w
|
||||||
import typing
|
import typing
|
||||||
from contextlib import ExitStack, nullcontext
|
from contextlib import ExitStack, nullcontext
|
||||||
|
|
||||||
|
# Ensure thirdparty is in sys.path for defer
|
||||||
|
_project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
_thirdparty = os.path.join(_project_root, "thirdparty")
|
||||||
|
if _thirdparty not in sys.path:
|
||||||
|
sys.path.insert(0, _thirdparty)
|
||||||
|
|
||||||
from defer import defer
|
from defer import defer
|
||||||
from imgui_bundle import imgui, hello_imgui, immapp, imgui_node_editor as ed, imgui_color_text_edit as ced
|
from imgui_bundle import imgui, hello_imgui, immapp, imgui_node_editor as ed, imgui_color_text_edit as ced
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@@ -923,8 +930,21 @@ class App:
|
|||||||
"""
|
"""
|
||||||
from src import mcp_client
|
from src import mcp_client
|
||||||
import re
|
import re
|
||||||
mcp_client.configure([{"path": f_item.path}])
|
from pathlib import Path
|
||||||
outline = mcp_client.py_get_code_outline(f_item.path)
|
import os
|
||||||
|
proj_dir = str(Path(self.controller.active_project_path).parent.resolve()) if getattr(self, 'controller', None) and self.controller.active_project_path else None
|
||||||
|
abs_path = f_item.path if os.path.isabs(f_item.path) else os.path.join(proj_dir or '.', f_item.path)
|
||||||
|
mcp_client.configure([{"path": abs_path}], [proj_dir] if proj_dir else None)
|
||||||
|
|
||||||
|
f_path_lower = f_item.path.lower()
|
||||||
|
try:
|
||||||
|
if f_path_lower.endswith('.py'): outline = mcp_client.py_get_code_outline(abs_path)
|
||||||
|
elif f_path_lower.endswith(('.c', '.h')): outline = mcp_client.ts_c_get_code_outline(abs_path)
|
||||||
|
elif f_path_lower.endswith(('.cpp', '.hpp', '.cxx', '.cc')): outline = mcp_client.ts_cpp_get_code_outline(abs_path)
|
||||||
|
else: return
|
||||||
|
except Exception:
|
||||||
|
return
|
||||||
|
|
||||||
if outline.startswith("ERROR") or outline.startswith("ACCESS DENIED"):
|
if outline.startswith("ERROR") or outline.startswith("ACCESS DENIED"):
|
||||||
return
|
return
|
||||||
pattern = re.compile(r'^\s*\[(.*?)\] (.*?) \(Lines (\d+)-(\d+)\)', re.MULTILINE)
|
pattern = re.compile(r'^\s*\[(.*?)\] (.*?) \(Lines (\d+)-(\d+)\)', re.MULTILINE)
|
||||||
@@ -2841,8 +2861,13 @@ def render_context_batch_actions(app: App, total_lines: int, total_ast: int) ->
|
|||||||
if not app.context_files:
|
if not app.context_files:
|
||||||
app.context_preview_text = "# Context Composition Empty\n\nNo files have been added to the context composition yet."
|
app.context_preview_text = "# Context Composition Empty\n\nNo files have been added to the context composition yet."
|
||||||
else:
|
else:
|
||||||
app.controller.context_files = app.context_files
|
try:
|
||||||
app.context_preview_text = app.controller._do_generate()[0]
|
app.controller.context_files = app.context_files
|
||||||
|
app.context_preview_text = app.controller._do_generate()[0]
|
||||||
|
except Exception as e:
|
||||||
|
import traceback
|
||||||
|
err = traceback.format_exc()
|
||||||
|
app.context_preview_text = f"# Error generating preview\n\n```python\n{err}\n```"
|
||||||
app.show_windows["Context Preview"] = True
|
app.show_windows["Context Preview"] = True
|
||||||
imgui.same_line()
|
imgui.same_line()
|
||||||
imgui.text(f" | Total: {len(app.context_files)} files, {total_lines} lines, {total_ast} AST elements")
|
imgui.text(f" | Total: {len(app.context_files)} files, {total_lines} lines, {total_ast} AST elements")
|
||||||
@@ -2911,7 +2936,8 @@ def render_ast_inspector_modal(app: App) -> None:
|
|||||||
app._show_ast_inspector = False
|
app._show_ast_inspector = False
|
||||||
|
|
||||||
#region: AST Inspector
|
#region: AST Inspector
|
||||||
expanded, opened = imgui.begin_popup_modal('AST Inspector', True, imgui.WindowFlags_.always_auto_resize)
|
imgui.set_next_window_size(imgui.ImVec2(1200, 800), imgui.Cond_.first_use_ever)
|
||||||
|
expanded, opened = imgui.begin_popup_modal('AST Inspector', True, imgui.WindowFlags_.none)
|
||||||
if opened:
|
if opened:
|
||||||
if expanded:
|
if expanded:
|
||||||
if app.ui_inspecting_ast_file is None:
|
if app.ui_inspecting_ast_file is None:
|
||||||
@@ -2923,6 +2949,11 @@ def render_ast_inspector_modal(app: App) -> None:
|
|||||||
if f_path != app._cached_ast_file_path:
|
if f_path != app._cached_ast_file_path:
|
||||||
outline = ""
|
outline = ""
|
||||||
try:
|
try:
|
||||||
|
from src import mcp_client
|
||||||
|
from pathlib import Path
|
||||||
|
proj_dir = str(Path(app.controller.active_project_path).parent.resolve()) if getattr(app, 'controller', None) and app.controller.active_project_path else None
|
||||||
|
mcp_client.configure([{"path": f_path}], [proj_dir] if proj_dir else None)
|
||||||
|
|
||||||
if f_path.lower().endswith('.py'): outline = mcp_client.py_get_code_outline(f_path)
|
if f_path.lower().endswith('.py'): outline = mcp_client.py_get_code_outline(f_path)
|
||||||
elif f_path.lower().endswith(('.c', '.h')): outline = mcp_client.ts_c_get_code_outline(f_path)
|
elif f_path.lower().endswith(('.c', '.h')): outline = mcp_client.ts_c_get_code_outline(f_path)
|
||||||
else: outline = mcp_client.ts_cpp_get_code_outline(f_path)
|
else: outline = mcp_client.ts_cpp_get_code_outline(f_path)
|
||||||
@@ -2959,12 +2990,14 @@ def render_ast_inspector_modal(app: App) -> None:
|
|||||||
imgui.text(f"Inspecting AST: {f_path}")
|
imgui.text(f"Inspecting AST: {f_path}")
|
||||||
imgui.separator()
|
imgui.separator()
|
||||||
|
|
||||||
|
avail = imgui.get_content_region_avail()
|
||||||
|
table_height = max(100.0, avail.y - imgui.get_frame_height_with_spacing() - 10)
|
||||||
#region: ast_dual_pane
|
#region: ast_dual_pane
|
||||||
if imgui.begin_table('ast_dual_pane', 2, imgui.TableFlags_.resizable | imgui.TableFlags_.borders_inner_v):
|
if imgui.begin_table('ast_dual_pane', 2, imgui.TableFlags_.resizable | imgui.TableFlags_.borders_inner_v, imgui.ImVec2(0, table_height)):
|
||||||
imgui.table_next_column()
|
imgui.table_next_column()
|
||||||
|
|
||||||
#region: LEFT COLUMN (Tree) ---
|
#region: LEFT COLUMN (Tree) ---
|
||||||
imgui.begin_child("ast_tree_scroll", imgui.ImVec2(0, 600), True)
|
imgui.begin_child("ast_tree_scroll", imgui.ImVec2(0, 0), True)
|
||||||
if True:
|
if True:
|
||||||
if not app._cached_ast_nodes: imgui.text("No AST nodes found or error fetching outline.")
|
if not app._cached_ast_nodes: imgui.text("No AST nodes found or error fetching outline.")
|
||||||
else:
|
else:
|
||||||
@@ -2977,7 +3010,14 @@ def render_ast_inspector_modal(app: App) -> None:
|
|||||||
imgui.dummy(imgui.ImVec2(indent * 10, 0))
|
imgui.dummy(imgui.ImVec2(indent * 10, 0))
|
||||||
imgui.same_line()
|
imgui.same_line()
|
||||||
imgui.text(f"[{kind}] {name}")
|
imgui.text(f"[{kind}] {name}")
|
||||||
imgui.same_line(imgui.get_window_width() - 200)
|
|
||||||
|
# Calculate space left and align radio buttons to the right
|
||||||
|
btn_width = 150 # Estimated width of the 3 radio buttons
|
||||||
|
avail_width = imgui.get_content_region_avail().x
|
||||||
|
if avail_width > btn_width:
|
||||||
|
imgui.same_line(imgui.get_window_width() - btn_width)
|
||||||
|
else:
|
||||||
|
imgui.same_line()
|
||||||
|
|
||||||
current_mode = f_item.ast_mask.get(full_path, 'hide')
|
current_mode = f_item.ast_mask.get(full_path, 'hide')
|
||||||
|
|
||||||
@@ -2994,7 +3034,7 @@ def render_ast_inspector_modal(app: App) -> None:
|
|||||||
imgui.table_next_column()
|
imgui.table_next_column()
|
||||||
|
|
||||||
#region: RIGHT COLUMN (Content) ---
|
#region: RIGHT COLUMN (Content) ---
|
||||||
imgui.begin_child("ast_content_scroll", imgui.ImVec2(0, 600), True)
|
imgui.begin_child("ast_content_scroll", imgui.ImVec2(0, 0), True)
|
||||||
if True:
|
if True:
|
||||||
if not hasattr(app, '_cached_ast_file_lines') or not app._cached_ast_file_lines:
|
if not hasattr(app, '_cached_ast_file_lines') or not app._cached_ast_file_lines:
|
||||||
imgui.text("No file content loaded.")
|
imgui.text("No file content loaded.")
|
||||||
@@ -3117,8 +3157,10 @@ def render_context_files_table(app: App) -> None:
|
|||||||
|
|
||||||
f_path = f_item.path if hasattr(f_item, "path") else str(f_item)
|
f_path = f_item.path if hasattr(f_item, "path") else str(f_item)
|
||||||
is_sel = f_path in app.ui_selected_context_files
|
is_sel = f_path in app.ui_selected_context_files
|
||||||
|
f_item.auto_aggregate = is_sel
|
||||||
changed_sel, is_sel = imgui.checkbox(f"##sel{i}", is_sel)
|
changed_sel, is_sel = imgui.checkbox(f"##sel{i}", is_sel)
|
||||||
if changed_sel:
|
if changed_sel:
|
||||||
|
f_item.auto_aggregate = is_sel
|
||||||
if imgui.get_io().key_shift and app._last_selected_context_index != -1:
|
if imgui.get_io().key_shift and app._last_selected_context_index != -1:
|
||||||
start = min(app._last_selected_context_index, i)
|
start = min(app._last_selected_context_index, i)
|
||||||
end = max(app._last_selected_context_index, i)
|
end = max(app._last_selected_context_index, i)
|
||||||
@@ -4104,6 +4146,9 @@ def render_text_viewer_window(app: App) -> None:
|
|||||||
app._slice_sel_start = -1; app._slice_sel_end = -1
|
app._slice_sel_start = -1; app._slice_sel_end = -1
|
||||||
imgui.same_line()
|
imgui.same_line()
|
||||||
if imgui.button("Clear Selection"): app._slice_sel_start = -1; app._slice_sel_end = -1
|
if imgui.button("Clear Selection"): app._slice_sel_start = -1; app._slice_sel_end = -1
|
||||||
|
imgui.same_line()
|
||||||
|
if imgui.button("Auto-Populate AST Slices"): app._populate_auto_slices(app.ui_editing_slices_file)
|
||||||
|
|
||||||
to_remove = -1
|
to_remove = -1
|
||||||
for idx, slc in enumerate(app.ui_editing_slices_file.custom_slices):
|
for idx, slc in enumerate(app.ui_editing_slices_file.custom_slices):
|
||||||
imgui.push_id(f"slc_row_{idx}"); imgui.text(f"Slice {idx+1}: {slc['start_line']}-{slc['end_line']}"); imgui.same_line()
|
imgui.push_id(f"slc_row_{idx}"); imgui.text(f"Slice {idx+1}: {slc['start_line']}-{slc['end_line']}"); imgui.same_line()
|
||||||
@@ -4127,14 +4172,19 @@ def render_text_viewer_window(app: App) -> None:
|
|||||||
lines = app.text_viewer_content.splitlines(); draw_list = imgui.get_window_draw_list()
|
lines = app.text_viewer_content.splitlines(); draw_list = imgui.get_window_draw_list()
|
||||||
for i, line_text in enumerate(lines):
|
for i, line_text in enumerate(lines):
|
||||||
line_num = i + 1; pos = imgui.get_cursor_screen_pos(); line_height = imgui.get_text_line_height()
|
line_num = i + 1; pos = imgui.get_cursor_screen_pos(); line_height = imgui.get_text_line_height()
|
||||||
is_sliced = any(slc['start_line'] <= line_num <= slc['end_line'] for slc in app.ui_editing_slices_file.custom_slices)
|
|
||||||
if is_sliced: draw_list.add_rect_filled(pos, imgui.ImVec2(pos.x + imgui.get_content_region_avail().x, pos.y + line_height), imgui.get_color_u32(vec4(255, 165, 0, 0.2)))
|
is_auto_sliced = any(slc['start_line'] <= line_num <= slc['end_line'] for slc in app.ui_editing_slices_file.custom_slices if slc.get('tag') == 'auto-ast')
|
||||||
|
is_manual_sliced = any(slc['start_line'] <= line_num <= slc['end_line'] for slc in app.ui_editing_slices_file.custom_slices if slc.get('tag') != 'auto-ast')
|
||||||
|
|
||||||
|
if is_manual_sliced: draw_list.add_rect_filled(pos, imgui.ImVec2(pos.x + imgui.get_content_region_avail().x, pos.y + line_height), imgui.get_color_u32(vec4(255, 165, 0, 0.2)))
|
||||||
|
elif is_auto_sliced: draw_list.add_rect_filled(pos, imgui.ImVec2(pos.x + imgui.get_content_region_avail().x, pos.y + line_height), imgui.get_color_u32(vec4(0, 255, 0, 0.15)))
|
||||||
|
|
||||||
if app._slice_sel_start != -1 and app._slice_sel_end != -1:
|
if app._slice_sel_start != -1 and app._slice_sel_end != -1:
|
||||||
s, e = min(app._slice_sel_start, app._slice_sel_end), max(app._slice_sel_start, app._slice_sel_end)
|
s, e = min(app._slice_sel_start, app._slice_sel_end), max(app._slice_sel_start, app._slice_sel_end)
|
||||||
if s <= line_num <= e: draw_list.add_rect_filled(pos, imgui.ImVec2(pos.x + imgui.get_content_region_avail().x, pos.y + line_height), imgui.get_color_u32(vec4(100, 100, 255, 0.3)))
|
if s <= line_num <= e: draw_list.add_rect_filled(pos, imgui.ImVec2(pos.x + imgui.get_content_region_avail().x, pos.y + line_height), imgui.get_color_u32(vec4(100, 100, 255, 0.3)))
|
||||||
imgui.selectable(f"{line_num:4} | {line_text}##ln{line_num}", False)
|
imgui.selectable(f"{line_num:4} | {line_text}##ln{line_num}", False)
|
||||||
if imgui.is_item_clicked(): app._slice_sel_start = line_num; app._slice_sel_end = line_num
|
if imgui.is_item_clicked(): app._slice_sel_start = line_num; app._slice_sel_end = line_num
|
||||||
if imgui.is_item_hovered() and imgui.is_mouse_down(0): app._slice_sel_end = line_num
|
if imgui.is_item_hovered(imgui.HoveredFlags_.allow_when_blocked_by_active_item) and imgui.is_mouse_down(0): app._slice_sel_end = line_num
|
||||||
elif tv_type in renderer._lang_map:
|
elif tv_type in renderer._lang_map:
|
||||||
if app._text_viewer_editor is None:
|
if app._text_viewer_editor is None:
|
||||||
app._text_viewer_editor = ced.TextEditor(); app._text_viewer_editor.set_read_only_enabled(True); app._text_viewer_editor.set_show_line_numbers_enabled(True)
|
app._text_viewer_editor = ced.TextEditor(); app._text_viewer_editor.set_read_only_enabled(True); app._text_viewer_editor.set_show_line_numbers_enabled(True)
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ def test_ast_inspector_line_range_parsing():
|
|||||||
mock_imgui.begin_child.return_value = True
|
mock_imgui.begin_child.return_value = True
|
||||||
# radio_button returns (changed, active)
|
# radio_button returns (changed, active)
|
||||||
mock_imgui.radio_button.return_value = (False, False)
|
mock_imgui.radio_button.return_value = (False, False)
|
||||||
|
mock_imgui.get_content_region_avail.return_value.y = 800.0
|
||||||
|
mock_imgui.get_frame_height_with_spacing.return_value = 24.0
|
||||||
|
|
||||||
# Setup imscope mocks
|
# Setup imscope mocks
|
||||||
mock_imscope.window.return_value.__enter__.return_value = (True, True)
|
mock_imscope.window.return_value.__enter__.return_value = (True, True)
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import pytest
|
||||||
|
import time
|
||||||
|
import requests
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
|
||||||
|
def test_context_preview_and_ast_inspector(live_gui):
|
||||||
|
process, script_path = live_gui
|
||||||
|
|
||||||
|
# Give it a second to stabilize
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
# Set context file
|
||||||
|
resp = requests.post("http://127.0.0.1:8999/api/gui", json={
|
||||||
|
"action": "set_value",
|
||||||
|
"item": "files",
|
||||||
|
"value": ["src/aggregate.py"]
|
||||||
|
})
|
||||||
|
assert resp.status_code == 200
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
# Trigger Context Preview
|
||||||
|
resp = requests.post("http://127.0.0.1:8999/api/gui", json={
|
||||||
|
"action": "click",
|
||||||
|
"item": "btn_preview_ctx" # wait, there is no btn_preview_ctx registered in _clickable_actions
|
||||||
|
})
|
||||||
|
|
||||||
|
# Wait, the best way to verify if _do_generate works without crashing is
|
||||||
|
# checking /api/v1/context
|
||||||
|
resp = requests.get("http://127.0.0.1:8999/api/v1/context")
|
||||||
|
assert resp.status_code == 200
|
||||||
|
data = resp.json()
|
||||||
|
assert "## Files" in data["markdown"]
|
||||||
|
assert "aggregate.py" in data["markdown"]
|
||||||
|
print("SUCCESS: Context Generation works.")
|
||||||
Reference in New Issue
Block a user