280 lines
5.7 KiB
Markdown
280 lines
5.7 KiB
Markdown
# Integration Patterns for Scripts and Skills
|
|
|
|
Best practices for using VSCode CLI in automation, scripts, and Claude skills.
|
|
|
|
## Safe File Opening Pattern
|
|
|
|
**Always validate before opening:**
|
|
|
|
```bash
|
|
FILE_PATH="$1"
|
|
LINE="${2:-1}"
|
|
COLUMN="${3:-0}"
|
|
|
|
# Validation
|
|
if [[ ! -f "$FILE_PATH" ]]; then
|
|
echo "Error: File not found: $FILE_PATH" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# Convert to absolute path
|
|
ABS_PATH="$(cd "$(dirname "$FILE_PATH")" && pwd)/$(basename "$FILE_PATH")"
|
|
|
|
# Open safely
|
|
code -g "$ABS_PATH:$LINE:$COLUMN"
|
|
```
|
|
|
|
## Error Location Navigation
|
|
|
|
**Open file at compiler/linter error location:**
|
|
|
|
```bash
|
|
# Parse error output
|
|
ERROR_FILE="src/main.c"
|
|
ERROR_LINE="42"
|
|
ERROR_COL="15"
|
|
|
|
# Open at exact error location
|
|
echo "Opening error location: $ERROR_FILE:$ERROR_LINE:$ERROR_COL"
|
|
code -g "$ERROR_FILE:$ERROR_LINE:$ERROR_COL"
|
|
```
|
|
|
|
## TODO Finding and Navigation
|
|
|
|
**Search for TODOs and open at location:**
|
|
|
|
```bash
|
|
# Find all TODO(human) markers
|
|
grep -n "TODO(human)" *.py | while IFS=: read -r file line content; do
|
|
echo "$file:$line - $content"
|
|
done
|
|
|
|
# Open specific TODO
|
|
code -g publisher.py:36
|
|
```
|
|
|
|
**Interactive TODO selection:**
|
|
|
|
```bash
|
|
# Create numbered list
|
|
grep -n "TODO" *.js | nl
|
|
|
|
# User selects number, open that file:line
|
|
selected_todo=$(grep -n "TODO" *.js | sed -n "${TODO_NUM}p")
|
|
file=$(echo "$selected_todo" | cut -d: -f1)
|
|
line=$(echo "$selected_todo" | cut -d: -f2)
|
|
|
|
code -g "$file:$line"
|
|
```
|
|
|
|
## Relative to Absolute Path Conversion
|
|
|
|
**Ensure reliable path resolution:**
|
|
|
|
```bash
|
|
# Convert relative path to absolute
|
|
to_absolute_path() {
|
|
local path="$1"
|
|
|
|
if [[ "$path" = /* ]]; then
|
|
# Already absolute
|
|
echo "$path"
|
|
else
|
|
# Convert to absolute
|
|
echo "$(cd "$(dirname "$path")" && pwd)/$(basename "$path")"
|
|
fi
|
|
}
|
|
|
|
# Usage
|
|
ABS_FILE=$(to_absolute_path "$RELATIVE_FILE")
|
|
code -g "$ABS_FILE:$LINE"
|
|
```
|
|
|
|
## Path with Spaces Handling
|
|
|
|
**Always quote paths:**
|
|
|
|
```bash
|
|
# Safe quoting function
|
|
open_at_line() {
|
|
local file="$1"
|
|
local line="$2"
|
|
|
|
# Quote the entire file:line argument
|
|
code -g "$file:$line"
|
|
}
|
|
|
|
# Usage
|
|
open_at_line "my project/src/app.js" 42
|
|
```
|
|
|
|
## Multiple File Opening with Context
|
|
|
|
**Open related files with informative output:**
|
|
|
|
```bash
|
|
echo "Opening MQTT publisher and subscriber files:"
|
|
|
|
echo " - Publisher TODO at line 36 (connection setup)"
|
|
code -g PiPico/publisher.py:36
|
|
|
|
echo " - Subscriber TODO at line 45 (callback implementation)"
|
|
code -g PiPico/subscriber.py:45
|
|
```
|
|
|
|
## Window Behavior for Skills
|
|
|
|
**Avoid disrupting user's current work:**
|
|
|
|
```bash
|
|
# Option 1: New window (safest, doesn't disturb current work)
|
|
code -n -g "$FILE:$LINE"
|
|
|
|
# Option 2: Reuse window (convenient, adds as tab)
|
|
code -r -g "$FILE:$LINE"
|
|
|
|
# Option 3: Default behavior (reuses window)
|
|
code -g "$FILE:$LINE"
|
|
```
|
|
|
|
**Recommendation for skills:** Use default behavior (no -n or -r) to match user expectations.
|
|
|
|
## Error Handling Wrapper
|
|
|
|
**Comprehensive error handling:**
|
|
|
|
```bash
|
|
safe_open_code() {
|
|
local file="$1"
|
|
local line="${2:-1}"
|
|
local col="${3:-0}"
|
|
|
|
# Validate file exists
|
|
if [[ ! -f "$file" ]]; then
|
|
echo "Error: File not found: $file" >&2
|
|
return 1
|
|
fi
|
|
|
|
# Validate line is a number
|
|
if ! [[ "$line" =~ ^[0-9]+$ ]]; then
|
|
echo "Error: Line must be a number: $line" >&2
|
|
return 1
|
|
fi
|
|
|
|
# Validate column is a number
|
|
if ! [[ "$col" =~ ^[0-9]+$ ]]; then
|
|
echo "Error: Column must be a number: $col" >&2
|
|
return 1
|
|
fi
|
|
|
|
# Convert to absolute path
|
|
local abs_path
|
|
abs_path="$(cd "$(dirname "$file")" && pwd)/$(basename "$file")"
|
|
|
|
# Open with error handling
|
|
if ! code -g "$abs_path:$line:$col"; then
|
|
echo "Error: Failed to open file in VSCode" >&2
|
|
return 1
|
|
fi
|
|
|
|
echo "Opened $file at line $line, column $col"
|
|
return 0
|
|
}
|
|
|
|
# Usage
|
|
safe_open_code "src/app.js" 42 10
|
|
```
|
|
|
|
## Grep Integration
|
|
|
|
**Open grep results at specific line:**
|
|
|
|
```bash
|
|
# Search for pattern and open matches
|
|
pattern="$1"
|
|
grep -n "$pattern" *.js | while IFS=: read -r file line content; do
|
|
echo "Found in $file at line $line: $content"
|
|
read -p "Open this file? (y/n) " -n 1 -r
|
|
echo
|
|
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
|
code -g "$file:$line"
|
|
fi
|
|
done
|
|
```
|
|
|
|
## Git Diff Integration
|
|
|
|
**Open files with changes:**
|
|
|
|
```bash
|
|
# Get list of changed files
|
|
git diff --name-only | while read -r file; do
|
|
# Get first changed line number
|
|
first_change=$(git diff "$file" | grep -m1 "^@@" | \
|
|
sed 's/^@@ -[0-9,]* +\([0-9]*\).*/\1/')
|
|
|
|
if [[ -n "$first_change" ]]; then
|
|
echo "Opening $file at line $first_change (first change)"
|
|
code -g "$file:$first_change"
|
|
fi
|
|
done
|
|
```
|
|
|
|
## Context Provision
|
|
|
|
**Always provide context when opening files:**
|
|
|
|
```bash
|
|
# Good: Tells user why file is being opened
|
|
echo "Opening authentication logic at the security vulnerability (line 42)"
|
|
code -g src/auth.js:42
|
|
|
|
# Good: Explains what's at this location
|
|
echo "Opening publisher.py at line 36 (MQTT connection TODO)"
|
|
code -g publisher.py:36
|
|
|
|
# Less helpful: No context
|
|
code -g file.js:42
|
|
```
|
|
|
|
## Batch Opening with Delays
|
|
|
|
**Avoid overwhelming user with many files:**
|
|
|
|
```bash
|
|
files_to_open=(
|
|
"file1.js:10"
|
|
"file2.js:20"
|
|
"file3.js:30"
|
|
)
|
|
|
|
for file_spec in "${files_to_open[@]}"; do
|
|
echo "Opening $file_spec"
|
|
code -g "$file_spec"
|
|
sleep 0.5 # Brief delay between opens
|
|
done
|
|
```
|
|
|
|
## Platform Detection
|
|
|
|
**Handle different operating systems:**
|
|
|
|
```bash
|
|
# Detect platform and adjust accordingly
|
|
case "$(uname -s)" in
|
|
Linux*) editor_cmd="code" ;;
|
|
Darwin*) editor_cmd="code" ;; # macOS
|
|
CYGWIN*|MINGW*|MSYS*)
|
|
# Windows with Git Bash
|
|
editor_cmd="code"
|
|
;;
|
|
*)
|
|
echo "Unknown platform" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
# Use detected command
|
|
"$editor_cmd" -g "$FILE:$LINE"
|
|
```
|