Add Help menu and contextual tooltips to GUI
- Add Help menu with quick guides: Getting Started, Create Tool, Install Tools, Publish Tools, Keyboard Shortcuts, About - F1 shortcut opens Getting Started guide - Add tooltips to Tool Builder section headings (Arguments, Steps, Output Template) that appear on hover over the label text - Add tooltips to Registry page controls (search, filters, pagination) - Enhance sidebar tooltips with keyboard shortcuts Co-Authored-By: Claude Opus 4.5 <[email protected]>
This commit is contained in:
@@ -0,0 +1,363 @@
|
||||
"""Help dialogs for CmdForge GUI."""
|
||||
|
||||
from PySide6.QtWidgets import (
|
||||
QDialog, QVBoxLayout, QHBoxLayout, QLabel, QPushButton,
|
||||
QTextBrowser
|
||||
)
|
||||
from PySide6.QtCore import Qt
|
||||
|
||||
|
||||
# Help content for quick guides
|
||||
HELP_CONTENT = {
|
||||
"getting_started": {
|
||||
"title": "Getting Started with CmdForge",
|
||||
"content": """
|
||||
<h3>Welcome to CmdForge!</h3>
|
||||
<p>CmdForge lets you create AI-powered command-line tools that work like any Unix command.</p>
|
||||
|
||||
<h4>Quick Start Steps:</h4>
|
||||
<ol>
|
||||
<li><strong>Configure a Provider</strong> - Go to <em>Providers</em> in the sidebar and add an AI backend (like Claude or GPT). This is required before running AI tools.</li>
|
||||
<li><strong>Browse the Registry</strong> - Check out the <em>Registry</em> to discover tools shared by the community.</li>
|
||||
<li><strong>Install Tools</strong> - Click on any tool and hit <em>Install</em> to add it to your system.</li>
|
||||
<li><strong>Create Your Own</strong> - Use the <em>Tool Builder</em> to create custom AI-powered commands.</li>
|
||||
<li><strong>Use in Terminal</strong> - Run your tools like any command: <code>my-tool < input.txt</code></li>
|
||||
</ol>
|
||||
|
||||
<h4>Key Concepts:</h4>
|
||||
<ul>
|
||||
<li><strong>Steps</strong> - Tools are made of steps: Prompt (AI call), Code (Python), or Tool (chain another tool)</li>
|
||||
<li><strong>Variables</strong> - Use <code>{variable}</code> to pass data between steps</li>
|
||||
<li><strong>Arguments</strong> - Add flags like <code>--format</code> that users can set when running the tool</li>
|
||||
</ul>
|
||||
|
||||
<h4>Keyboard Shortcuts:</h4>
|
||||
<table>
|
||||
<tr><td><code>Ctrl+N</code></td><td>Create new tool</td></tr>
|
||||
<tr><td><code>Ctrl+S</code></td><td>Save current tool</td></tr>
|
||||
<tr><td><code>Ctrl+R</code></td><td>Refresh current page</td></tr>
|
||||
<tr><td><code>Ctrl+1-4</code></td><td>Navigate to pages</td></tr>
|
||||
<tr><td><code>Ctrl+Q</code></td><td>Quit</td></tr>
|
||||
<tr><td><code>Escape</code></td><td>Close tool builder</td></tr>
|
||||
</table>
|
||||
"""
|
||||
},
|
||||
"create_tool": {
|
||||
"title": "How to Create a Tool",
|
||||
"content": """
|
||||
<h3>Creating a New Tool</h3>
|
||||
|
||||
<h4>Step 1: Start the Tool Builder</h4>
|
||||
<p>Click <em>Create Tool</em> on the Welcome page, or press <code>Ctrl+N</code> from anywhere.</p>
|
||||
|
||||
<h4>Step 2: Fill in Basic Info</h4>
|
||||
<ul>
|
||||
<li><strong>Name</strong> - Use lowercase letters, numbers, and hyphens (e.g., <code>summarize-text</code>)</li>
|
||||
<li><strong>Description</strong> - Brief explanation shown in listings</li>
|
||||
<li><strong>Category</strong> - Pick from Text, Developer, Data, or add your own</li>
|
||||
</ul>
|
||||
|
||||
<h4>Step 3: Add Arguments (Optional)</h4>
|
||||
<p>Arguments let users customize tool behavior:</p>
|
||||
<ul>
|
||||
<li><strong>Flag</strong> - The command-line flag (e.g., <code>--max</code>)</li>
|
||||
<li><strong>Variable</strong> - Name to use in templates (e.g., <code>max</code>)</li>
|
||||
<li><strong>Default</strong> - Value when flag isn't provided</li>
|
||||
</ul>
|
||||
|
||||
<h4>Step 4: Add Steps</h4>
|
||||
<p>Steps define what your tool does:</p>
|
||||
<ul>
|
||||
<li><strong>Prompt Step</strong> - Calls an AI provider with your template. Use <code>{input}</code> for stdin content.</li>
|
||||
<li><strong>Code Step</strong> - Runs Python code. Variables are available directly (e.g., <code>input</code>, <code>response</code>).</li>
|
||||
<li><strong>Tool Step</strong> - Calls another CmdForge tool, enabling composition.</li>
|
||||
</ul>
|
||||
|
||||
<h4>Step 5: Set Output Template</h4>
|
||||
<p>The output template defines what your tool prints. Use <code>{variable}</code> to include step outputs.</p>
|
||||
<p>Example: <code>{response}</code> prints the last AI response.</p>
|
||||
|
||||
<h4>Step 6: Save</h4>
|
||||
<p>Press <code>Ctrl+S</code> or click <em>Save</em>. Your tool is now available as a command!</p>
|
||||
|
||||
<h4>Example: Simple Summarizer</h4>
|
||||
<pre>
|
||||
Name: summarize
|
||||
Steps:
|
||||
1. Prompt [claude] -> response
|
||||
"Summarize this text: {input}"
|
||||
Output: {response}
|
||||
</pre>
|
||||
<p>Run it: <code>echo "Long text..." | summarize</code></p>
|
||||
"""
|
||||
},
|
||||
"install_tools": {
|
||||
"title": "How to Install Tools",
|
||||
"content": """
|
||||
<h3>Installing Tools from the Registry</h3>
|
||||
|
||||
<h4>Step 1: Open the Registry</h4>
|
||||
<p>Click <em>Registry</em> in the sidebar to browse community tools.</p>
|
||||
|
||||
<h4>Step 2: Find a Tool</h4>
|
||||
<ul>
|
||||
<li><strong>Search</strong> - Type keywords in the search box</li>
|
||||
<li><strong>Filter by Category</strong> - Use the dropdown to narrow results</li>
|
||||
<li><strong>Sort</strong> - Order by popularity, newest, or name</li>
|
||||
<li><strong>Tags</strong> - Click tags on tools to filter by tag</li>
|
||||
</ul>
|
||||
|
||||
<h4>Step 3: Review Tool Details</h4>
|
||||
<p>Click on a tool to see:</p>
|
||||
<ul>
|
||||
<li>Description and usage information</li>
|
||||
<li>Rating and download count</li>
|
||||
<li>Publisher reputation</li>
|
||||
<li>Available versions</li>
|
||||
</ul>
|
||||
|
||||
<h4>Step 4: Install</h4>
|
||||
<ul>
|
||||
<li>Select a version (or use <em>Latest</em>)</li>
|
||||
<li>Click <em>Install</em></li>
|
||||
<li>Wait for confirmation</li>
|
||||
</ul>
|
||||
|
||||
<h4>Step 5: Use the Tool</h4>
|
||||
<p>Installed tools are available immediately in your terminal:</p>
|
||||
<pre>
|
||||
echo "text" | tool-name
|
||||
cat file.txt | tool-name --flag value
|
||||
tool-name --help
|
||||
</pre>
|
||||
|
||||
<h4>Updates</h4>
|
||||
<p>Tools with available updates show a green arrow (<span style="color: #48bb78;">↑</span>) in the list. Click <em>Update</em> to get the latest version.</p>
|
||||
|
||||
<h4>Managing Installed Tools</h4>
|
||||
<p>Go to <em>Tools</em> in the sidebar to see all your installed tools, edit them, or delete ones you no longer need.</p>
|
||||
"""
|
||||
},
|
||||
"publish_tools": {
|
||||
"title": "How to Publish Tools",
|
||||
"content": """
|
||||
<h3>Publishing Your Tools</h3>
|
||||
|
||||
<h4>Prerequisites</h4>
|
||||
<ul>
|
||||
<li>A tool you've created and tested</li>
|
||||
<li>A registry account (sign up at cmdforge.brrd.tech)</li>
|
||||
</ul>
|
||||
|
||||
<h4>Step 1: Connect Your Account</h4>
|
||||
<ol>
|
||||
<li>Go to the <em>Providers</em> page</li>
|
||||
<li>Click <em>Connect to Registry</em></li>
|
||||
<li>Log in or register</li>
|
||||
</ol>
|
||||
|
||||
<h4>Step 2: Prepare Your Tool</h4>
|
||||
<ul>
|
||||
<li>Give it a clear, descriptive name</li>
|
||||
<li>Write a helpful description</li>
|
||||
<li>Choose the right category</li>
|
||||
<li>Test it thoroughly</li>
|
||||
</ul>
|
||||
|
||||
<h4>Step 3: Publish</h4>
|
||||
<ol>
|
||||
<li>Go to the <em>Tools</em> page</li>
|
||||
<li>Select the tool you want to publish</li>
|
||||
<li>Click <em>Publish</em></li>
|
||||
<li>Add tags to help users find it</li>
|
||||
<li>Set the initial version number</li>
|
||||
<li>Click <em>Submit</em></li>
|
||||
</ol>
|
||||
|
||||
<h4>Versioning</h4>
|
||||
<p>When you update a published tool:</p>
|
||||
<ul>
|
||||
<li><strong>Patch</strong> (1.0.0 → 1.0.1) - Bug fixes</li>
|
||||
<li><strong>Minor</strong> (1.0.0 → 1.1.0) - New features, backward compatible</li>
|
||||
<li><strong>Major</strong> (1.0.0 → 2.0.0) - Breaking changes</li>
|
||||
</ul>
|
||||
|
||||
<h4>Best Practices</h4>
|
||||
<ul>
|
||||
<li>Write clear descriptions and examples</li>
|
||||
<li>Use semantic versioning</li>
|
||||
<li>Test before publishing updates</li>
|
||||
<li>Respond to user feedback</li>
|
||||
</ul>
|
||||
"""
|
||||
},
|
||||
"keyboard_shortcuts": {
|
||||
"title": "Keyboard Shortcuts",
|
||||
"content": """
|
||||
<h3>Keyboard Shortcuts</h3>
|
||||
|
||||
<h4>Global</h4>
|
||||
<table style="width: 100%;">
|
||||
<tr><td style="width: 40%;"><code>Ctrl+N</code></td><td>Create new tool</td></tr>
|
||||
<tr><td><code>Ctrl+S</code></td><td>Save current tool</td></tr>
|
||||
<tr><td><code>Ctrl+R</code></td><td>Refresh current page</td></tr>
|
||||
<tr><td><code>Ctrl+Q</code></td><td>Quit application</td></tr>
|
||||
<tr><td><code>F1</code></td><td>Show help</td></tr>
|
||||
</table>
|
||||
|
||||
<h4>Navigation</h4>
|
||||
<table style="width: 100%;">
|
||||
<tr><td style="width: 40%;"><code>Ctrl+1</code></td><td>Go to Welcome page</td></tr>
|
||||
<tr><td><code>Ctrl+2</code></td><td>Go to Tools page</td></tr>
|
||||
<tr><td><code>Ctrl+3</code></td><td>Go to Registry page</td></tr>
|
||||
<tr><td><code>Ctrl+4</code></td><td>Go to Providers page</td></tr>
|
||||
</table>
|
||||
|
||||
<h4>Tool Builder</h4>
|
||||
<table style="width: 100%;">
|
||||
<tr><td style="width: 40%;"><code>Escape</code></td><td>Close builder / cancel</td></tr>
|
||||
<tr><td><code>Ctrl+S</code></td><td>Save tool</td></tr>
|
||||
</table>
|
||||
|
||||
<h4>Lists and Tables</h4>
|
||||
<table style="width: 100%;">
|
||||
<tr><td style="width: 40%;"><code>Double-click</code></td><td>Edit selected item</td></tr>
|
||||
<tr><td><code>Drag & Drop</code></td><td>Reorder steps</td></tr>
|
||||
</table>
|
||||
"""
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class QuickGuideDialog(QDialog):
|
||||
"""Dialog showing a quick guide on a topic."""
|
||||
|
||||
def __init__(self, guide_key: str, parent=None):
|
||||
super().__init__(parent)
|
||||
|
||||
guide = HELP_CONTENT.get(guide_key, {})
|
||||
self.setWindowTitle(guide.get("title", "Help"))
|
||||
self.setMinimumSize(550, 450)
|
||||
self.resize(600, 500)
|
||||
self.setModal(True)
|
||||
|
||||
self._setup_ui(guide)
|
||||
|
||||
def _setup_ui(self, guide: dict):
|
||||
"""Set up the dialog UI."""
|
||||
layout = QVBoxLayout(self)
|
||||
layout.setContentsMargins(24, 24, 24, 24)
|
||||
layout.setSpacing(16)
|
||||
|
||||
# Content browser with styled HTML
|
||||
browser = QTextBrowser()
|
||||
browser.setOpenExternalLinks(True)
|
||||
browser.setStyleSheet("""
|
||||
QTextBrowser {
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
font-size: 13px;
|
||||
}
|
||||
""")
|
||||
|
||||
# Build styled content
|
||||
content = f"""
|
||||
<style>
|
||||
h3 {{ color: #2d3748; margin-bottom: 8px; }}
|
||||
h4 {{ color: #4a5568; margin-top: 16px; margin-bottom: 8px; }}
|
||||
p {{ color: #4a5568; margin-bottom: 8px; line-height: 1.5; }}
|
||||
ul, ol {{ color: #4a5568; margin-bottom: 8px; }}
|
||||
li {{ margin-bottom: 4px; }}
|
||||
code {{ background: #edf2f7; padding: 2px 6px; border-radius: 3px; font-family: monospace; }}
|
||||
pre {{ background: #edf2f7; padding: 12px; border-radius: 6px; font-family: monospace; overflow-x: auto; }}
|
||||
table {{ border-collapse: collapse; margin: 8px 0; }}
|
||||
td {{ padding: 6px 12px; }}
|
||||
em {{ color: #667eea; }}
|
||||
</style>
|
||||
{guide.get("content", "")}
|
||||
"""
|
||||
browser.setHtml(content)
|
||||
layout.addWidget(browser, 1)
|
||||
|
||||
# Close button
|
||||
btn_layout = QHBoxLayout()
|
||||
btn_layout.addStretch()
|
||||
|
||||
btn_close = QPushButton("Close")
|
||||
btn_close.setMinimumWidth(100)
|
||||
btn_close.clicked.connect(self.accept)
|
||||
btn_layout.addWidget(btn_close)
|
||||
|
||||
layout.addLayout(btn_layout)
|
||||
|
||||
|
||||
class AboutDialog(QDialog):
|
||||
"""About CmdForge dialog."""
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.setWindowTitle("About CmdForge")
|
||||
self.setFixedSize(400, 300)
|
||||
self.setModal(True)
|
||||
self._setup_ui()
|
||||
|
||||
def _setup_ui(self):
|
||||
"""Set up the dialog UI."""
|
||||
layout = QVBoxLayout(self)
|
||||
layout.setContentsMargins(32, 32, 32, 32)
|
||||
layout.setSpacing(16)
|
||||
|
||||
# Logo/title
|
||||
title = QLabel("CmdForge")
|
||||
title.setStyleSheet("""
|
||||
font-size: 32px;
|
||||
font-weight: bold;
|
||||
color: #667eea;
|
||||
""")
|
||||
title.setAlignment(Qt.AlignCenter)
|
||||
layout.addWidget(title)
|
||||
|
||||
# Tagline
|
||||
tagline = QLabel("AI-Powered CLI Tool Builder")
|
||||
tagline.setStyleSheet("font-size: 14px; color: #718096;")
|
||||
tagline.setAlignment(Qt.AlignCenter)
|
||||
layout.addWidget(tagline)
|
||||
|
||||
layout.addSpacing(16)
|
||||
|
||||
# Version info
|
||||
try:
|
||||
from cmdforge import __version__
|
||||
version = __version__
|
||||
except ImportError:
|
||||
version = "unknown"
|
||||
|
||||
version_label = QLabel(f"Version {version}")
|
||||
version_label.setStyleSheet("color: #4a5568;")
|
||||
version_label.setAlignment(Qt.AlignCenter)
|
||||
layout.addWidget(version_label)
|
||||
|
||||
# Description
|
||||
desc = QLabel(
|
||||
"Create custom terminal commands that call AI providers,\n"
|
||||
"chain prompts with Python code, and use them like\n"
|
||||
"any Unix pipe command."
|
||||
)
|
||||
desc.setStyleSheet("color: #718096; font-size: 12px;")
|
||||
desc.setAlignment(Qt.AlignCenter)
|
||||
layout.addWidget(desc)
|
||||
|
||||
layout.addStretch()
|
||||
|
||||
# Links
|
||||
links = QLabel(
|
||||
'<a href="https://cmdforge.brrd.tech" style="color: #667eea;">Website</a>'
|
||||
)
|
||||
links.setOpenExternalLinks(True)
|
||||
links.setAlignment(Qt.AlignCenter)
|
||||
layout.addWidget(links)
|
||||
|
||||
# Close button
|
||||
btn_close = QPushButton("Close")
|
||||
btn_close.clicked.connect(self.accept)
|
||||
layout.addWidget(btn_close)
|
||||
Reference in New Issue
Block a user