Add cf tutorial and graceful Ctrl+C handling
- Add Interactive Tool Picker tutorial to web docs - Handle SIGINT signal for clean exit on Ctrl+C - Add KeyboardInterrupt handling in main() - Add tutorial to Getting Started section in TOC Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
f6bb863f60
commit
def8baf344
|
|
@ -329,11 +329,24 @@ def main():
|
||||||
"""Entry point for cf command."""
|
"""Entry point for cf command."""
|
||||||
global _ui_out
|
global _ui_out
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import signal
|
||||||
|
|
||||||
|
# Handle Ctrl+C gracefully
|
||||||
|
def handle_sigint(sig, frame):
|
||||||
|
# Restore cursor and exit cleanly
|
||||||
|
sys.stderr.write(SHOW_CURSOR)
|
||||||
|
sys.stderr.flush()
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
signal.signal(signal.SIGINT, handle_sigint)
|
||||||
|
|
||||||
# Read piped input if stdin is not a tty
|
# Read piped input if stdin is not a tty
|
||||||
piped_input = None
|
piped_input = None
|
||||||
if not sys.stdin.isatty():
|
if not sys.stdin.isatty():
|
||||||
piped_input = sys.stdin.read()
|
try:
|
||||||
|
piped_input = sys.stdin.read()
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
# Check if we have a terminal available
|
# Check if we have a terminal available
|
||||||
if not os.path.exists('/dev/tty'):
|
if not os.path.exists('/dev/tty'):
|
||||||
|
|
@ -346,6 +359,9 @@ def main():
|
||||||
try:
|
try:
|
||||||
with TTYInput() as tty_input:
|
with TTYInput() as tty_input:
|
||||||
result = run_picker(tty_input)
|
result = run_picker(tty_input)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
_write(SHOW_CURSOR)
|
||||||
|
sys.exit(0)
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
print(f"cf requires a terminal: {e}", file=sys.stderr)
|
print(f"cf requires a terminal: {e}", file=sys.stderr)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
|
||||||
|
|
@ -231,6 +231,96 @@ cat complex_algorithm.py | explain --level expert</code></pre>
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"interactive-picker": {
|
||||||
|
"title": "Interactive Tool Picker",
|
||||||
|
"description": "Use the cf command to quickly find and run tools",
|
||||||
|
"parent": "getting-started",
|
||||||
|
"content": """
|
||||||
|
<p class="lead">The <code>cf</code> command lets you browse, filter, and run your tools interactively
|
||||||
|
without remembering exact names. It's especially powerful when chaining tools together.</p>
|
||||||
|
|
||||||
|
<h2 id="basic-usage">Basic Usage</h2>
|
||||||
|
<p>Just type <code>cf</code> to open the picker:</p>
|
||||||
|
<pre><code class="language-bash">cf</code></pre>
|
||||||
|
|
||||||
|
<p>You'll see an inline dropdown with all your tools. Start typing to filter:</p>
|
||||||
|
<pre><code class="language-text">> sum▌
|
||||||
|
▸ summarize ⚙ - Summarize text using AI
|
||||||
|
summary-bullets - Convert text to bullet points
|
||||||
|
assume-role - Assume an expert persona</code></pre>
|
||||||
|
|
||||||
|
<h2 id="controls">Controls</h2>
|
||||||
|
<table class="w-full my-4">
|
||||||
|
<thead class="bg-gray-100">
|
||||||
|
<tr><th class="px-4 py-2 text-left">Key</th><th class="px-4 py-2 text-left">Action</th></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr class="border-b"><td class="px-4 py-2">Type characters</td><td class="px-4 py-2">Fuzzy filter by name or description</td></tr>
|
||||||
|
<tr class="border-b"><td class="px-4 py-2">↑ / ↓</td><td class="px-4 py-2">Move selection up/down</td></tr>
|
||||||
|
<tr class="border-b"><td class="px-4 py-2">Enter</td><td class="px-4 py-2">Run the selected tool</td></tr>
|
||||||
|
<tr class="border-b"><td class="px-4 py-2">Tab</td><td class="px-4 py-2">Configure arguments (if tool has ⚙)</td></tr>
|
||||||
|
<tr class="border-b"><td class="px-4 py-2">Esc / Ctrl+C</td><td class="px-4 py-2">Cancel and exit</td></tr>
|
||||||
|
<tr><td class="px-4 py-2">Backspace</td><td class="px-4 py-2">Delete filter characters</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2 id="piping-input">Piping Input</h2>
|
||||||
|
<p>Pipe content into <code>cf</code> just like any other tool:</p>
|
||||||
|
<pre><code class="language-bash"># Select a tool to process a file
|
||||||
|
cat article.txt | cf
|
||||||
|
|
||||||
|
# Pipe from another command
|
||||||
|
curl -s https://api.example.com/data | cf</code></pre>
|
||||||
|
|
||||||
|
<p>The picker appears, you choose a tool, and the piped content flows through it.</p>
|
||||||
|
|
||||||
|
<h2 id="chaining">Chaining Pickers</h2>
|
||||||
|
<p>The real power comes from chaining multiple pickers to build pipelines interactively:</p>
|
||||||
|
<pre><code class="language-bash"># Interactive two-stage pipeline
|
||||||
|
cat document.txt | cf | cf
|
||||||
|
|
||||||
|
# Three-stage processing
|
||||||
|
cf | cf | cf</code></pre>
|
||||||
|
|
||||||
|
<p>Each <code>cf</code> in the chain shows the picker. Select a tool, see its output, then
|
||||||
|
select another tool to process that output. You're building pipelines on the fly.</p>
|
||||||
|
|
||||||
|
<div class="bg-cyan-50 border-l-4 border-cyan-500 p-4 my-4">
|
||||||
|
<p class="font-semibold text-cyan-800">Example: Research Workflow</p>
|
||||||
|
<p class="text-cyan-700">
|
||||||
|
<code>cat notes.txt | cf | cf | cf</code><br><br>
|
||||||
|
Pick <strong>summarize</strong> → Pick <strong>extract-keywords</strong> → Pick <strong>format-markdown</strong><br><br>
|
||||||
|
You just built a summarize → extract → format pipeline without typing a single tool name.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 id="configuring-args">Configuring Arguments</h2>
|
||||||
|
<p>Tools with arguments show a ⚙ icon. Press <strong>Tab</strong> instead of Enter to configure them:</p>
|
||||||
|
<pre><code class="language-text">summarize arguments:
|
||||||
|
▸ --max-length: 200 # Maximum summary length
|
||||||
|
--format: paragraph
|
||||||
|
Tab:edit Enter:run Esc:back</code></pre>
|
||||||
|
|
||||||
|
<p>Use ↑/↓ to select an argument, Tab to edit it, Enter to run with your settings.</p>
|
||||||
|
|
||||||
|
<h2 id="tips">Tips</h2>
|
||||||
|
<ul>
|
||||||
|
<li><strong>Fuzzy matching</strong> - Type "smz" to match "summarize", or search by description</li>
|
||||||
|
<li><strong>Fast selection</strong> - If the tool you want is highlighted, just hit Enter</li>
|
||||||
|
<li><strong>Escape anytime</strong> - Ctrl+C or Esc exits cleanly without running anything</li>
|
||||||
|
<li><strong>Combine with scripts</strong> - Use <code>cf</code> in shell scripts for interactive steps</li>
|
||||||
|
</ul>
|
||||||
|
""",
|
||||||
|
"headings": [
|
||||||
|
("basic-usage", "Basic Usage"),
|
||||||
|
("controls", "Controls"),
|
||||||
|
("piping-input", "Piping Input"),
|
||||||
|
("chaining", "Chaining Pickers"),
|
||||||
|
("configuring-args", "Configuring Arguments"),
|
||||||
|
("tips", "Tips"),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
"publishing": {
|
"publishing": {
|
||||||
"title": "Publishing Tools",
|
"title": "Publishing Tools",
|
||||||
"description": "Share your tools with the CmdForge community",
|
"description": "Share your tools with the CmdForge community",
|
||||||
|
|
@ -4226,6 +4316,7 @@ def get_toc():
|
||||||
SimpleNamespace(slug="getting-started", title="Getting Started", children=[
|
SimpleNamespace(slug="getting-started", title="Getting Started", children=[
|
||||||
SimpleNamespace(slug="installation", title="Installation"),
|
SimpleNamespace(slug="installation", title="Installation"),
|
||||||
SimpleNamespace(slug="first-tool", title="Your First Tool"),
|
SimpleNamespace(slug="first-tool", title="Your First Tool"),
|
||||||
|
SimpleNamespace(slug="interactive-picker", title="Interactive Picker (cf)"),
|
||||||
SimpleNamespace(slug="visual-builder", title="Visual Builder"),
|
SimpleNamespace(slug="visual-builder", title="Visual Builder"),
|
||||||
SimpleNamespace(slug="yaml-config", title="YAML Config"),
|
SimpleNamespace(slug="yaml-config", title="YAML Config"),
|
||||||
]),
|
]),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue