mirror of
https://github.com/harvard-edge/cs249r_book.git
synced 2026-05-03 16:18:49 -05:00
TinyTorch educational deep learning framework now lives at tinytorch/
Structure:
- tinytorch/src/ - Source modules (single source of truth)
- tinytorch/tito/ - CLI tool
- tinytorch/tests/ - Test suite
- tinytorch/site/ - Jupyter Book website
- tinytorch/milestones/ - Historical ML implementations
- tinytorch/datasets/ - Educational datasets (tinydigits, tinytalks)
- tinytorch/assignments/ - NBGrader assignments
- tinytorch/instructor/ - Teaching materials
Workflows (with tinytorch- prefix):
- tinytorch-ci.yml - CI/CD pipeline
- tinytorch-publish-dev.yml - Dev site deployment
- tinytorch-publish-live.yml - Live site deployment
- tinytorch-build-pdf.yml - PDF generation
- tinytorch-release-check.yml - Release validation
Repository Variables added:
- TINYTORCH_ROOT = tinytorch
- TINYTORCH_SRC = tinytorch/src
- TINYTORCH_SITE = tinytorch/site
- TINYTORCH_TESTS = tinytorch/tests
All workflows use \${{ vars.TINYTORCH_* }} for path configuration.
Note: tinytorch/site/_static/favicon.svg kept as SVG (valid for favicons)
233 lines
5.7 KiB
Bash
Executable File
233 lines
5.7 KiB
Bash
Executable File
#!/bin/bash
|
|
# VHS to Terminalizer Converter
|
|
# Converts VHS tape files to Terminalizer YAML configs for polished output
|
|
|
|
set -e
|
|
|
|
# Colors
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m'
|
|
|
|
echo -e "${BLUE}🎬 VHS → Terminalizer Converter${NC}"
|
|
echo "======================================"
|
|
echo ""
|
|
|
|
# Check arguments
|
|
if [ $# -lt 1 ]; then
|
|
echo -e "${RED}Usage: $0 <tape-file> [output-yml]${NC}"
|
|
echo ""
|
|
echo "Examples:"
|
|
echo " $0 docs/_static/demos/tapes/01-zero-to-ready.tape"
|
|
echo " $0 docs/_static/demos/tapes/01-zero-to-ready.tape 01-custom.yml"
|
|
exit 1
|
|
fi
|
|
|
|
TAPE_FILE="$1"
|
|
OUTPUT_YML="${2:-$(basename "$TAPE_FILE" .tape).yml}"
|
|
|
|
# Check if tape file exists
|
|
if [ ! -f "$TAPE_FILE" ]; then
|
|
echo -e "${RED}❌ Tape file not found: $TAPE_FILE${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
echo -e "${BLUE}📄 Input: $TAPE_FILE${NC}"
|
|
echo -e "${BLUE}📝 Output: $OUTPUT_YML${NC}"
|
|
echo ""
|
|
|
|
# Check if terminalizer is installed
|
|
if ! command -v terminalizer &> /dev/null; then
|
|
echo -e "${YELLOW}⚠️ Terminalizer not installed${NC}"
|
|
echo ""
|
|
echo "Install with: npm install -g terminalizer"
|
|
echo ""
|
|
echo -e "${BLUE}For now, creating a template config...${NC}"
|
|
fi
|
|
|
|
# Extract metadata from VHS tape
|
|
WIDTH=$(grep "^Set Width" "$TAPE_FILE" | awk '{print $3}')
|
|
HEIGHT=$(grep "^Set Height" "$TAPE_FILE" | awk '{print $3}')
|
|
THEME=$(grep "^Set Theme" "$TAPE_FILE" | sed -n 's/Set Theme "\(.*\)"/\1/p')
|
|
OUTPUT_GIF=$(grep "^Output" "$TAPE_FILE" | awk '{print $2}' | tr -d '"')
|
|
|
|
# Convert Catppuccin Mocha to Terminalizer theme
|
|
TERM_THEME="monokai" # Default fallback
|
|
case "$THEME" in
|
|
"Catppuccin Mocha")
|
|
TERM_THEME="monokai"
|
|
;;
|
|
"Dracula")
|
|
TERM_THEME="dracula"
|
|
;;
|
|
esac
|
|
|
|
echo -e "${GREEN}📊 Extracted Settings:${NC}"
|
|
echo " Dimensions: ${WIDTH}x${HEIGHT}"
|
|
echo " Theme: $THEME → $TERM_THEME"
|
|
echo " Output: $OUTPUT_GIF"
|
|
echo ""
|
|
|
|
# Parse VHS commands and convert to Terminalizer format
|
|
echo -e "${BLUE}🔄 Converting commands...${NC}"
|
|
|
|
# Create Terminalizer config header
|
|
cat > "$OUTPUT_YML" << EOF
|
|
# Terminalizer Config
|
|
# Auto-generated from VHS tape: $TAPE_FILE
|
|
# Date: $(date +"%Y-%m-%d %H:%M:%S")
|
|
|
|
config:
|
|
# Recording settings
|
|
command: bash -l
|
|
cwd: /tmp
|
|
|
|
# Terminal dimensions
|
|
cols: $((WIDTH / 10))
|
|
rows: $((HEIGHT / 20))
|
|
|
|
# Rendering
|
|
repeat: 0
|
|
quality: 100
|
|
frameDelay: auto
|
|
maxIdleTime: 2000
|
|
|
|
# Style
|
|
theme:
|
|
background: "transparent"
|
|
foreground: "#abb2bf"
|
|
cursor: "#c678dd"
|
|
|
|
# Watermark
|
|
watermark:
|
|
imagePath: null
|
|
style:
|
|
position: absolute
|
|
right: 15px
|
|
bottom: 15px
|
|
width: 100px
|
|
opacity: 0.9
|
|
|
|
# Cursor style
|
|
cursorStyle: block
|
|
|
|
# Font
|
|
fontFamily: "JetBrains Mono, Monaco, Menlo, monospace"
|
|
fontSize: 18
|
|
lineHeight: 1.2
|
|
letterSpacing: 0
|
|
|
|
# Recording frames
|
|
records:
|
|
EOF
|
|
|
|
# Parse VHS tape and convert commands
|
|
# This is a simplified converter - it extracts Type and Enter commands
|
|
# and converts Sleep to delays
|
|
|
|
FRAME_COUNT=0
|
|
DELAY_MS=0
|
|
|
|
while IFS= read -r line; do
|
|
# Skip comments and empty lines
|
|
[[ "$line" =~ ^[[:space:]]*# ]] && continue
|
|
[[ -z "$line" ]] && continue
|
|
|
|
# Parse Type commands
|
|
if [[ "$line" =~ ^Type[[:space:]]+"(.+)"$ ]]; then
|
|
TEXT="${BASH_REMATCH[1]}"
|
|
if [ $FRAME_COUNT -gt 0 ]; then
|
|
# Add accumulated delay to previous frame
|
|
sed -i '' "s/delay: 0$/delay: $DELAY_MS/" "$OUTPUT_YML"
|
|
DELAY_MS=0
|
|
fi
|
|
|
|
# Add typing frame
|
|
cat >> "$OUTPUT_YML" << FRAME
|
|
- delay: 0
|
|
content: "$TEXT"
|
|
FRAME
|
|
((FRAME_COUNT++))
|
|
|
|
# Parse Enter commands
|
|
elif [[ "$line" =~ ^Enter ]]; then
|
|
if [ $FRAME_COUNT -gt 0 ]; then
|
|
sed -i '' "s/delay: 0$/delay: $DELAY_MS/" "$OUTPUT_YML"
|
|
DELAY_MS=0
|
|
fi
|
|
|
|
cat >> "$OUTPUT_YML" << FRAME
|
|
- delay: 0
|
|
content: "\\r"
|
|
FRAME
|
|
((FRAME_COUNT++))
|
|
|
|
# Parse Sleep commands and accumulate
|
|
elif [[ "$line" =~ ^Sleep[[:space:]]+([0-9]+)(ms|s) ]]; then
|
|
SLEEP_VAL="${BASH_REMATCH[1]}"
|
|
SLEEP_UNIT="${BASH_REMATCH[2]}"
|
|
|
|
if [ "$SLEEP_UNIT" = "s" ]; then
|
|
DELAY_MS=$((DELAY_MS + SLEEP_VAL * 1000))
|
|
else
|
|
DELAY_MS=$((DELAY_MS + SLEEP_VAL))
|
|
fi
|
|
|
|
# Parse Wait commands and convert to reasonable delay
|
|
elif [[ "$line" =~ ^Wait[[:space:]]+([0-9]+)?s?[[:space:]]*Line ]]; then
|
|
WAIT_TIMEOUT="${BASH_REMATCH[1]:-5}"
|
|
# Convert Wait to a reasonable delay (half the timeout)
|
|
DELAY_MS=$((DELAY_MS + (WAIT_TIMEOUT * 1000 / 2)))
|
|
fi
|
|
|
|
done < "$TAPE_FILE"
|
|
|
|
# Apply final delay if any
|
|
if [ $DELAY_MS -gt 0 ] && [ $FRAME_COUNT -gt 0 ]; then
|
|
sed -i '' "s/delay: 0$/delay: $DELAY_MS/" "$OUTPUT_YML"
|
|
fi
|
|
|
|
echo -e "${GREEN}✅ Converted $FRAME_COUNT frames${NC}"
|
|
echo ""
|
|
|
|
# Add usage instructions
|
|
cat << USAGE
|
|
|
|
${BLUE}📋 Next Steps:${NC}
|
|
|
|
1. ${YELLOW}Review the generated config:${NC}
|
|
cat $OUTPUT_YML
|
|
|
|
2. ${YELLOW}Record with Terminalizer:${NC}
|
|
terminalizer record $OUTPUT_YML -c $OUTPUT_YML
|
|
|
|
${BLUE}Or manually replay commands:${NC}
|
|
The config contains the command sequence.
|
|
You may need to run commands manually in the terminal.
|
|
|
|
3. ${YELLOW}Render to GIF:${NC}
|
|
terminalizer render $OUTPUT_YML -o ${OUTPUT_GIF}
|
|
|
|
4. ${YELLOW}Preview:${NC}
|
|
terminalizer play $OUTPUT_YML
|
|
|
|
${BLUE}💡 Tips:${NC}
|
|
- Terminalizer configs may need manual adjustment
|
|
- The converter provides a starting point
|
|
- Check timing and add missing pauses
|
|
- Terminalizer creates smoother, more polished GIFs
|
|
|
|
${YELLOW}⚠️ Note:${NC}
|
|
Terminalizer requires manual execution, unlike VHS.
|
|
The converted config shows the command sequence,
|
|
but you'll need to type them during recording.
|
|
|
|
For fully automated workflow, stick with VHS.
|
|
Use Terminalizer only for final polish.
|
|
|
|
USAGE
|
|
|
|
echo -e "${GREEN}✅ Conversion complete!${NC}"
|