Pico² is releasing on Feb 9th 2025! Follow on itch.io for updates!
See the Pico² Design Document!
I don’t use the built-in PICO-8 code editor as I find it far too limiting. Here’s a breakdown of my VS Code setup when I’m coding for PICO-8.
The pico8-ls Extension adds a language server for PICO-8 Lua. This means you get auto-complete snippets, syntax highlighting, definition on hover and even jump to definition across Lua files. Highly recommended!
I use Material Theme.
Python for the pre-processor script.
I work directly in the projects
folder, since PICO-8 launches here automatically.
I made a script which removes all single- and multi-line comments, but leaves new lines where applicable. This means any traceback errors in PICO-8 will show you the right line numbers!
Before:
After:
This obviously still uses characters, so ideally use a better script if you actually want to minify your script for export.
Open your project folder in VS Code. You should have a .p8
main PICO-8 file in there. On the same level as this .p8
file, make:
output
remove_comments.py
.p8
file (call it whatever you want)- my_game
- output
my_game.p8
my_game_copy.p8
remove_comments.py
Copy and paste the following code into the Python file.
import re
import sys
import os, shutil
def remove_comments(file_path, output_path):
with open(file_path, 'r') as file:
code = file.read()
# Regex to remove single-line and multi-line comments
# -- matches two dashes at start
# \[\[ matches the opening [[ of multiline
# [\s\S]* matches any character, including newlines
# * is lazy match, stops at first ]]
# \]\] matches closing ]]
no_comments = re.sub(r'--\[\[[\s\S]*?\]\]--', replace_with_empty_lines, code)
# (?<!\[) negative lookbehind ensures -- is not preceded by [
# -- matches two dashes at start
# [^\[] matches any character that is NOT [
# .* matches the rest of the line after --, up to end of line
no_comments = re.sub(r'(?<!\[)--[^\[].*', '', no_comments)
with open(output_path, 'w') as output_file:
output_file.write(no_comments)
# Function to replace each match
def replace_with_empty_lines(match):
comment = match.group(0) # Extract the comment content
line_count = comment.count('\n') # Count lines in the comment block
return '\n' * line_count # Replace with that many newlines
if __name__ == "__main__":
folder = './output'
# Empty the output folder
for filename in os.listdir(folder):
file_path = os.path.join(folder, filename)
try:
if os.path.isfile(file_path) or os.path.islink(file_path):
os.unlink(file_path)
elif os.path.isdir(file_path):
shutil.rmtree(file_path)
except Exception as e:
print('Failed to delete %s. Reason: %s' % (file_path, e))
# Get arguments after current file
files = sys.argv[1:]
"""
files = [
"file1.lua", "file1_out.lua",
"file2.lua", "file2_out.lua",
"file3.lua", "file3_out.lua",
...
]
"""
# Clean up all files
while len(files)!=0:
file_in = files.pop(0)
file_out = files.pop(0)
remove_comments(file_in, f"./output/{file_out}")
Next, go to Terminal > Configure Tasks... > Create tasks.json file from template > Others
.
You’ll find that file in your project directory, in the .vscode
folder. Open tasks.json
and copy and paste the following code there.
{
"version": "2.0.0",
"tasks": [
{
"label": "Remove Comments",
"type": "shell",
"command": "python",
"args": [
"remove_comments.py",
"file1.lua", "file1_out.lua",
],
"group": {
"kind": "build",
"isDefault": true
},
"presentation": {
"reveal": "silent"
}
}
]
}
Go to Terminal > Configure Default Build Task > Remove Comments
.
Finally, go to View > Command Palette > Preferences: Open User Settings (JSON)
.
Find "[pico-8-lua]"
and change it to this:
"[pico-8-lua]": {
"editor.suggest.showSnippets": false
},
First, open the Terminal/Command Prompt (a separate app, not the built-in one for VS Code).
Open PICO-8 by typing:
/System/Volumes/Data/Applications/PICO-8.app/Contents/MacOS/pico8
This is for MacOS, but it’s probably similar for other operating systems - just write the path to the executable.
This lets you use printh()
in your code, which prints to that terminal window. Invaluable for debugging!
All your code will be written in separate .lua
files instead of the .p8
cart itself.
For example, see this file structure after the set-up:
- my_game
- .vscode
tasks.json
- output
my_game.p8
my_game_copy.p8
remove_comments.py
main.lua
Let’s say I want to add a file called main.lua
.
When you want to make a new file, follow these steps:
.lua
file in the main directory (already done in structure above).my_game.p8
file, write the following: #include ./output/main_out.lua
my_game_copy.p8
file, write the following: #include ./main.lua
.vscode/tasks.json
, add the following arguments (in order):
"main.lua"
"main_out.lua"
file1.lua
can be seen in the code you copied and pasted. You should remove that example..lua
file, and in the bottom right, set the editor to use tabs instead of spaces.
When you want to run your code and test your game:
Shift+Cmd+B
or Shift+Ctrl+B
Cmd+R
or Ctrl+R
The regex file is commented if you’re curious - it seems to break if you put --
in a string, so don’t do that! I don’t know much about regex so I can’t be bothered to fix it.
The pico8-ls extension works very well even across separate .lua
files. However, our my_game.p8
cart now only includes the _out.lua
cleaned files. This means when you open the commented .lua
files, the languages server doesn’t pick them up.
I fixed this by including the duplicate my_game_copy.p8
, which includes the commented files and tricks the language server into thinking it’s the real files!
Also the task could probably be simplified, but again I don’t want to spend forever making it perfect, it’s good enough for me!
Finally, I changed that setting because the extension would often autocomplete do
and end
to random Japanese characters which is super annoying. That line removes the autocomplete.
There’s the full set-up; hope it helps!
Follow on Twitter @wsasaki01 Follow on Bluesky at wsasaki.bsky.social
Did you like this post? Tell us
Leave a comment
Log in with your itch.io account to leave a comment.