batrachian-toad 0.5.22__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.
- batrachian_toad-0.5.22.dist-info/METADATA +197 -0
- batrachian_toad-0.5.22.dist-info/RECORD +120 -0
- batrachian_toad-0.5.22.dist-info/WHEEL +4 -0
- batrachian_toad-0.5.22.dist-info/entry_points.txt +2 -0
- batrachian_toad-0.5.22.dist-info/licenses/LICENSE +661 -0
- toad/__init__.py +46 -0
- toad/__main__.py +4 -0
- toad/_loop.py +86 -0
- toad/about.py +90 -0
- toad/acp/agent.py +671 -0
- toad/acp/api.py +47 -0
- toad/acp/encode_tool_call_id.py +12 -0
- toad/acp/messages.py +138 -0
- toad/acp/prompt.py +54 -0
- toad/acp/protocol.py +426 -0
- toad/agent.py +62 -0
- toad/agent_schema.py +70 -0
- toad/agents.py +45 -0
- toad/ansi/__init__.py +1 -0
- toad/ansi/_ansi.py +1612 -0
- toad/ansi/_ansi_colors.py +264 -0
- toad/ansi/_control_codes.py +37 -0
- toad/ansi/_keys.py +251 -0
- toad/ansi/_sgr_styles.py +64 -0
- toad/ansi/_stream_parser.py +418 -0
- toad/answer.py +22 -0
- toad/app.py +557 -0
- toad/atomic.py +37 -0
- toad/cli.py +257 -0
- toad/code_analyze.py +28 -0
- toad/complete.py +34 -0
- toad/constants.py +58 -0
- toad/conversation_markdown.py +19 -0
- toad/danger.py +371 -0
- toad/data/agents/ampcode.com.toml +51 -0
- toad/data/agents/augmentcode.com.toml +40 -0
- toad/data/agents/claude.com.toml +41 -0
- toad/data/agents/docker.com.toml +59 -0
- toad/data/agents/geminicli.com.toml +28 -0
- toad/data/agents/goose.ai.toml +51 -0
- toad/data/agents/inference.huggingface.co.toml +33 -0
- toad/data/agents/kimi.com.toml +35 -0
- toad/data/agents/openai.com.toml +53 -0
- toad/data/agents/opencode.ai.toml +61 -0
- toad/data/agents/openhands.dev.toml +44 -0
- toad/data/agents/stakpak.dev.toml +61 -0
- toad/data/agents/vibe.mistral.ai.toml +27 -0
- toad/data/agents/vtcode.dev.toml +62 -0
- toad/data/images/frog.png +0 -0
- toad/data/sounds/turn-over.wav +0 -0
- toad/db.py +5 -0
- toad/dec.py +332 -0
- toad/directory.py +234 -0
- toad/directory_watcher.py +96 -0
- toad/fuzzy.py +140 -0
- toad/gist.py +2 -0
- toad/history.py +138 -0
- toad/jsonrpc.py +576 -0
- toad/menus.py +14 -0
- toad/messages.py +74 -0
- toad/option_content.py +51 -0
- toad/os.py +0 -0
- toad/path_complete.py +145 -0
- toad/path_filter.py +124 -0
- toad/paths.py +71 -0
- toad/pill.py +23 -0
- toad/prompt/extract.py +19 -0
- toad/prompt/resource.py +68 -0
- toad/protocol.py +28 -0
- toad/screens/action_modal.py +94 -0
- toad/screens/agent_modal.py +172 -0
- toad/screens/command_edit_modal.py +58 -0
- toad/screens/main.py +192 -0
- toad/screens/permissions.py +390 -0
- toad/screens/permissions.tcss +72 -0
- toad/screens/settings.py +254 -0
- toad/screens/settings.tcss +101 -0
- toad/screens/store.py +476 -0
- toad/screens/store.tcss +261 -0
- toad/settings.py +354 -0
- toad/settings_schema.py +318 -0
- toad/shell.py +263 -0
- toad/shell_read.py +42 -0
- toad/slash_command.py +34 -0
- toad/toad.tcss +752 -0
- toad/version.py +80 -0
- toad/visuals/columns.py +273 -0
- toad/widgets/agent_response.py +79 -0
- toad/widgets/agent_thought.py +41 -0
- toad/widgets/command_pane.py +224 -0
- toad/widgets/condensed_path.py +93 -0
- toad/widgets/conversation.py +1626 -0
- toad/widgets/danger_warning.py +65 -0
- toad/widgets/diff_view.py +709 -0
- toad/widgets/flash.py +81 -0
- toad/widgets/future_text.py +126 -0
- toad/widgets/grid_select.py +223 -0
- toad/widgets/highlighted_textarea.py +180 -0
- toad/widgets/mandelbrot.py +294 -0
- toad/widgets/markdown_note.py +13 -0
- toad/widgets/menu.py +147 -0
- toad/widgets/non_selectable_label.py +5 -0
- toad/widgets/note.py +18 -0
- toad/widgets/path_search.py +381 -0
- toad/widgets/plan.py +180 -0
- toad/widgets/project_directory_tree.py +74 -0
- toad/widgets/prompt.py +741 -0
- toad/widgets/question.py +337 -0
- toad/widgets/shell_result.py +35 -0
- toad/widgets/shell_terminal.py +18 -0
- toad/widgets/side_bar.py +74 -0
- toad/widgets/slash_complete.py +211 -0
- toad/widgets/strike_text.py +66 -0
- toad/widgets/terminal.py +526 -0
- toad/widgets/terminal_tool.py +338 -0
- toad/widgets/throbber.py +90 -0
- toad/widgets/tool_call.py +303 -0
- toad/widgets/user_input.py +23 -0
- toad/widgets/version.py +5 -0
- toad/widgets/welcome.py +31 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
from functools import lru_cache
|
|
2
|
+
import os.path
|
|
3
|
+
from typing import Iterable
|
|
4
|
+
|
|
5
|
+
from rich.cells import cell_len
|
|
6
|
+
from textual.geometry import Size
|
|
7
|
+
from textual.reactive import reactive
|
|
8
|
+
from textual.content import Content
|
|
9
|
+
from textual.widget import Widget
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def radiate_range(total: int) -> Iterable[tuple[int, int]]:
|
|
13
|
+
"""Generate pairs of indexes, gradually growing from the center.
|
|
14
|
+
|
|
15
|
+
Args:
|
|
16
|
+
total: Total size of range.
|
|
17
|
+
|
|
18
|
+
Yields:
|
|
19
|
+
Pairs of indexes.
|
|
20
|
+
"""
|
|
21
|
+
if not total:
|
|
22
|
+
return
|
|
23
|
+
left = right = total // 2
|
|
24
|
+
yield (left, right)
|
|
25
|
+
while left >= 0 or right < total:
|
|
26
|
+
left -= 1
|
|
27
|
+
if left >= 0:
|
|
28
|
+
yield (left + 1, right)
|
|
29
|
+
right += 1
|
|
30
|
+
if right <= total:
|
|
31
|
+
yield (left + 1, right)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@lru_cache(maxsize=16)
|
|
35
|
+
def condense_path(path: str, width: int, *, prefix: str = "") -> str:
|
|
36
|
+
"""Condense a path to fit within the given cell width.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
path: The path to condense.
|
|
40
|
+
width: Maximum cell width.
|
|
41
|
+
prefix: A string to be prepended to the result.
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
A condensed string.
|
|
45
|
+
"""
|
|
46
|
+
# TODO: handle OS separators and path issues
|
|
47
|
+
if cell_len(path) <= width:
|
|
48
|
+
return path
|
|
49
|
+
components = path.split("/")
|
|
50
|
+
condensed = components
|
|
51
|
+
trailing_slash = path.endswith("/")
|
|
52
|
+
candidate = prefix + "/".join(condensed)
|
|
53
|
+
if trailing_slash and candidate and not candidate.endswith("/"):
|
|
54
|
+
candidate += "/"
|
|
55
|
+
|
|
56
|
+
for left, right in radiate_range(len(components)):
|
|
57
|
+
if cell_len(candidate) < width:
|
|
58
|
+
return candidate
|
|
59
|
+
condensed = [*components[:left], "…", *components[right:]]
|
|
60
|
+
candidate = prefix + "/".join(condensed)
|
|
61
|
+
if trailing_slash and candidate and not candidate.endswith("/"):
|
|
62
|
+
candidate += "/"
|
|
63
|
+
|
|
64
|
+
return candidate
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class CondensedPath(Widget):
|
|
68
|
+
path = reactive("")
|
|
69
|
+
display_path = reactive("")
|
|
70
|
+
|
|
71
|
+
def on_resize(self) -> None:
|
|
72
|
+
self.watch_path(self.path)
|
|
73
|
+
|
|
74
|
+
def watch_path(self, path: str) -> None:
|
|
75
|
+
if not path or not self.size:
|
|
76
|
+
return
|
|
77
|
+
path = os.path.abspath(path)
|
|
78
|
+
self.tooltip = str(path)
|
|
79
|
+
user_root = os.path.abspath(os.path.expanduser("~/"))
|
|
80
|
+
if not user_root.endswith("/"):
|
|
81
|
+
user_root += "/"
|
|
82
|
+
if path.startswith(user_root):
|
|
83
|
+
path = "~/" + path[len(user_root) :]
|
|
84
|
+
self.display_path = path
|
|
85
|
+
|
|
86
|
+
def render(self) -> Content:
|
|
87
|
+
return Content(condense_path(self.display_path, self.size.width))
|
|
88
|
+
|
|
89
|
+
def get_content_width(self, container: Size, viewport: Size) -> int:
|
|
90
|
+
if self.display_path:
|
|
91
|
+
return Content(self.display_path).cell_length
|
|
92
|
+
else:
|
|
93
|
+
return container.width
|