Last active
December 4, 2025 00:21
-
-
Save lee2sman/f84e03ef5e5209a9466d2c0795c2d50a to your computer and use it in GitHub Desktop.
A p5.js to L5 script converter - used for converting reference and example code from the p5 site for L5
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # p5.js to L5 Converter | |
| # Usage: ./convert.sh input.js [output.lua] | |
| if [ $# -eq 0 ]; then | |
| echo "Usage: $0 input.js [output.lua]" | |
| echo "Converts p5.js JavaScript files to L5 Lua syntax" | |
| exit 1 | |
| fi | |
| INPUT_FILE="$1" | |
| OUTPUT_FILE="${2:-${INPUT_FILE%.*}.lua}" | |
| if [ ! -f "$INPUT_FILE" ]; then | |
| echo "Error: Input file '$INPUT_FILE' not found" | |
| exit 1 | |
| fi | |
| echo "Converting $INPUT_FILE to $OUTPUT_FILE..." | |
| # Create temporary file for processing | |
| TEMP_FILE=$(mktemp) | |
| # Add L5 require statement and copy input to temp file | |
| echo 'require("L5")' > "$TEMP_FILE" | |
| echo "" >> "$TEMP_FILE" | |
| cat "$INPUT_FILE" >> "$TEMP_FILE" | |
| # Protect template variable syntax ${ ... } BEFORE we convert braces | |
| # Replace ${ with placeholder | |
| sed -i 's/\${/__DLBR__/g' "$TEMP_FILE" | |
| # Replace the } that closes a ${...} expression (anything between __DLBR__ and }) | |
| # Match any characters that are not } after __DLBR__ | |
| sed -i 's/__DLBR__\([^}]*\)}/__DLBR__\1__RBR__/g' "$TEMP_FILE" | |
| # Function definitions | |
| sed -i 's/function \([a-zA-Z_][a-zA-Z0-9_]*\)(\([^)]*\))\s*{/function \1(\2)/g' "$TEMP_FILE" | |
| # For loops | |
| sed -i 's/for\s*(\s*let\s\+\([a-zA-Z_][a-zA-Z0-9_]*\)\s*=\s*\([^;]*\)\s*;\s*\([a-zA-Z_][a-zA-Z0-9_]*\)\s*<\s*\([^;]*\)\s*;\s*[^)]*)\s*{/for \1=\2,\4-1 do/g' "$TEMP_FILE" | |
| sed -i 's/for\s*(\s*let\s\+\([a-zA-Z_][a-zA-Z0-9_]*\)\s*=\s*\([^;]*\)\s*;\s*\([a-zA-Z_][a-zA-Z0-9_]*\)\s*<=\s*\([^;]*\)\s*;\s*[^)]*)\s*{/for \1=\2,\4 do/g' "$TEMP_FILE" | |
| # For...of loops - convert for (let x of array) to for _,x in ipairs(array) do | |
| sed -i 's/for\s*(\s*let\s\+\([a-zA-Z_][a-zA-Z0-9_]*\)\s\+of\s\+\([^)]*\))\s*{/for _,\1 in ipairs(\2) do/g' "$TEMP_FILE" | |
| sed -i 's/for\s*(\s*const\s\+\([a-zA-Z_][a-zA-Z0-9_]*\)\s\+of\s\+\([^)]*\))\s*{/for _,\1 in ipairs(\2) do/g' "$TEMP_FILE" | |
| # Operators | |
| sed -i 's/\([a-zA-Z_][a-zA-Z0-9_]*\)\s*+=\s*\([^;]*\)/\1 = \1 + \2/g' "$TEMP_FILE" | |
| sed -i 's/\([a-zA-Z_][a-zA-Z0-9_]*\)\s*-=\s*\([^;]*\)/\1 = \1 - \2/g' "$TEMP_FILE" | |
| sed -i 's/\([a-zA-Z_][a-zA-Z0-9_]*\)\s*\*=\s*\([^;]*\)/\1 = \1 * \2/g' "$TEMP_FILE" | |
| sed -i 's/\([a-zA-Z_][a-zA-Z0-9_]*\)\s*\/=\s*\([^;]*\)/\1 = \1 \/ \2/g' "$TEMP_FILE" | |
| sed -i 's/\([a-zA-Z_][a-zA-Z0-9_]*\)++/\1 = \1 + 1/g' "$TEMP_FILE" | |
| sed -i 's/++\([a-zA-Z_][a-zA-Z0-9_]*\)/\1 = \1 + 1/g' "$TEMP_FILE" | |
| sed -i 's/\([a-zA-Z_][a-zA-Z0-9_]*\)--/\1 = \1 - 1/g' "$TEMP_FILE" | |
| sed -i 's/--\([a-zA-Z_][a-zA-Z0-9_]*\)/\1 = \1 - 1/g' "$TEMP_FILE" | |
| # Comments - convert // to -- (after var-- operator conversion) | |
| sed -i 's|//|--|g' "$TEMP_FILE" | |
| sed -i 's|/\*|--\[\[|g' "$TEMP_FILE" | |
| sed -i 's|\*/|\]\]|g' "$TEMP_FILE" | |
| # Remove semicolons | |
| sed -i 's/;$//g' "$TEMP_FILE" | |
| # Convert createCanvas to size | |
| sed -i 's/createCanvas(/size(/g' "$TEMP_FILE" | |
| # Control structures | |
| # Handle else if before converting if | |
| sed -i 's/}\s*else if\s*(\([^)]*\))\s*{/elseif \1 then/g' "$TEMP_FILE" | |
| # Handle regular if | |
| sed -i 's/if\s*(\([^)]*\))/if \1 then/g' "$TEMP_FILE" | |
| # Handle standalone else | |
| sed -i 's/}\s*else/else/g' "$TEMP_FILE" | |
| # Replace braces with end | |
| sed -i 's/{//g' "$TEMP_FILE" | |
| sed -i 's/}/end/g' "$TEMP_FILE" | |
| # Convert JavaScript arrays to Lua tables: [...] to {...} | |
| sed -i 's/\[/{/g' "$TEMP_FILE" | |
| sed -i 's/\]/}/g' "$TEMP_FILE" | |
| # Variable declarations | |
| sed -i 's/let \([a-zA-Z_][a-zA-Z0-9_]*\)\s*=/local \1 =/g' "$TEMP_FILE" | |
| sed -i 's/var \([a-zA-Z_][a-zA-Z0-9_]*\)\s*=/local \1 =/g' "$TEMP_FILE" | |
| sed -i 's/const \([a-zA-Z_][a-zA-Z0-9_]*\)\s*=/local \1 =/g' "$TEMP_FILE" | |
| sed -i 's/let \([a-zA-Z_][a-zA-Z0-9_]*\);*/local \1/g' "$TEMP_FILE" | |
| sed -i 's/var \([a-zA-Z_][a-zA-Z0-9_]*\);*/local \1/g' "$TEMP_FILE" | |
| sed -i 's/const \([a-zA-Z_][a-zA-Z0-9_]*\);*/local \1/g' "$TEMP_FILE" | |
| # Operators | |
| sed -i 's/===/==/g' "$TEMP_FILE" | |
| sed -i 's/!==/~=/g' "$TEMP_FILE" | |
| sed -i 's/!=/~=/g' "$TEMP_FILE" | |
| sed -i 's/&&/ and /g' "$TEMP_FILE" | |
| sed -i 's/||/ or /g' "$TEMP_FILE" | |
| # Console.log to print | |
| sed -i 's/console\.log/print/g' "$TEMP_FILE" | |
| # Convert template literals to Lua concatenation | |
| # Convert __DLBR__var__RBR__ to __VAR__var__ENDVAR__ (temporarily) | |
| sed -i 's/__DLBR__\([^_]*\)__RBR__/__VAR__\1__ENDVAR__/g' "$TEMP_FILE" | |
| # Replace backticks | |
| sed -i 's/`\([^`]*\)`/"\1"/g' "$TEMP_FILE" | |
| # Replace __VAR__x__ENDVAR__ with "..x.." | |
| sed -i 's/__VAR__\([^_]*\)__ENDVAR__/"..\1.."/g' "$TEMP_FILE" | |
| # Clean up double quotes between .. operators: ".."" -> ".." | |
| sed -i 's/"\.\.""/.../g' "$TEMP_FILE" | |
| # Clean up at start: "".. -> empty (remove both quotes and dots) | |
| sed -i 's/""\.\.//g' "$TEMP_FILE" | |
| # Clean up at end: .."" -> empty (remove both dots and quotes) | |
| sed -i 's/\.\.""//g' "$TEMP_FILE" | |
| # Move converted content to output file | |
| mv "$TEMP_FILE" "$OUTPUT_FILE" | |
| echo "Output saved to $OUTPUT_FILE" | |
| # Clean up | |
| rm -f "$TEMP_FILE" 2>/dev/null | |
| echo | |
| echo "Note: This is a basic conversion. You may need to manually adjust:" | |
| echo "- For loop bounds (JavaScript 0-based vs Lua 1-based indexing)" | |
| echo "- Function names that don't have direct L5 equivalents" | |
| echo "- Complex expressions and syntax" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment