Script your coding demos to perfection with this VS Code extension – no typos, no missteps, just flawless, stress-free presentations every time. Execute each demo step seamlessly, just like advancing through a presentation!
Currently, the extension supports the following features:
- Highlighting code in a file.
- Multiple demo files located in the
.demo
folder. - Support for code/snippet files in the
.demo
folder, allowing you to define multiple reusable steps. - Explorer panel to execute your demo steps (you can move it to the activity bar).
- Run through the demo steps by executing the
Demo Time: Start
command. - Presentation mode that allows you to use a clicker to navigate through the demo steps.
- Run a specific demo step from a command execution using the
demo-time.runById
command. - Place your variables in a
variables.json
file in the.demo
folder and reference them like{variable_name}
in your demo steps. - Detachable presenter view which you can move to a different screen.
- Adding notes to your demo steps.
To use the extension, you need to create a .demo
folder in your workspace. Once created, you can add a JSON file which contains the demo and its steps.
{
"$schema": "https://demotime.elio.dev/demo-time.schema.json",
"title": "<title>",
"description": "<description>",
"demos": []
}
Add your demos to the demos
array. Each demo can consist of multiple steps.
{
"title": "<title>",
"description": "<description>",
"steps": []
}
You can also add "icons" to your demo steps to make them more recognizable. You can use the following icons:
{
"title": "<title>",
"description": "<description>",
"icons": {
"start": "<name of the icon (optional)>",
"end": "<name of the icon (optional)>"
},
"steps": []
}
Use the icon names you can find in the icon listing from the Visual Studio Code documentation.
Find more information on the file actions documentation page.
Action | Description | Usage |
---|---|---|
create
|
Create a new file |
{
"action": "create",
"path": "<relative path to the file>",
"content": "<content of the file> (optional)",
"contentPath": "<relative path to the file in the .demo folder> (optional)"
} |
open
|
Open a file |
{
"action": "open",
"path": "<relative path to the file>"
} |
markdownPreview
|
Preview a Markdown file |
{
"action": "markdownPreview",
"path": "<relative path to the file>"
} |
save
|
Save the current active file |
{
"action": "save"
} |
rename
|
Rename a file |
{
"action": "rename",
"path": "<relative path to the file>",
"dest": "<new file name/path>"
} |
deleteFile
|
Delete a file |
{
"action": "deleteFile",
"path": "<relative path to the file>"
} |
close
|
Close the current active file |
{
"action": "close"
} |
closeAll
|
Close all open files |
{
"action": "closeAll",
} |
Find more information on the text actions documentation page.
Action | Description | Usage |
---|---|---|
insert
|
Insert code into a file |
// Via position
{
"action": "insert",
"path": "<relative path to the file>",
"position": "<position>",
"content": "<content of the file> (optional)",
"contentPath": "<relative path to the file in the .demo folder> (optional)",
"lineInsertionDelay": "<delay in milliseconds to insert each line> (optional)"
}
// Via placeholders
{
"action": "insert",
"path": "<relative path to the file>",
"startPlaceholder": "<start placeholder>",
"endPlaceholder": "<end placeholder>",
"content": "<content of the file> (optional)",
"contentPath": "<relative path to the file in the .demo folder> (optional)",
"lineInsertionDelay": "<delay in milliseconds to insert each line> (optional)"
} |
replace
|
Replace code in a file |
// Via position
{
"action": "replace",
"path": "<relative path to the file>",
"position": "<position>",
"content": "<content of the file> (optional)",
"contentPath": "<relative path to the file in the .demo folder> (optional)",
"lineInsertionDelay": "<delay in milliseconds to insert each line> (optional)"
}
// Via placeholders
{
"action": "replace",
"path": "<relative path to the file>",
"startPlaceholder": "<start placeholder>",
"endPlaceholder": "<end placeholder>",
"content": "<content of the file> (optional)",
"contentPath": "<relative path to the file in the .demo folder> (optional)",
"lineInsertionDelay": "<delay in milliseconds to insert each line> (optional)"
} |
delete
|
Delete code from a file |
// Via position
{
"action": "delete",
"path": "<relative path to the file>",
"position": "<position>"
}
// Via placeholders
{
"action": "delete",
"path": "<relative path to the file>",
"startPlaceholder": "<start placeholder>",
"endPlaceholder": "<end placeholder>"
} |
highlight
|
Highlight code in a file. Check out the settings section to customize the highlight colors. |
// Via position
{
"action": "highlight",
"path": "<relative path to the file>",
"position": "<position>",
"zoom": "<zoom level> (optional)"
}
// Via placeholders
{
"action": "highlight",
"path": "<relative path to the file>",
"startPlaceholder": "<start placeholder>",
"endPlaceholder": "<end placeholder>",
"zoom": "<zoom level> (optional)"
} |
positionCursor
|
Postion the cursor at a specific line and character position |
// Via position
{
"action": "positionCursor",
"path": "<relative path to the file>",
"position": "<position>"
}
// Via start placeholder
{
"action": "positionCursor",
"path": "<relative path to the file>",
"startPlaceholder": "<start placeholder>",
} |
unselect
|
Unselect code in a file |
{
"action": "unselect",
"path": "<relative path to the file>"
} |
write
|
Write a single line of text to the editor |
// Write to current active position
{
"action": "write",
"content": "Hello World"
}
// Write to a specific position in a file
// Via position
{
"action": "write",
"content": "Hello World",
"path": "<relative path to the file>",
"position": "<position>"
}
// Via start placeholder
{
"action": "write",
"content": "Hello World",
"path": "<relative path to the file>",
"startPlaceholder": "<start placeholder>",
} |
format
|
Format the content of the active file |
{
"action": "format"
} |
Find more information on the setting actions documentation page.
Action | Description | Usage |
---|---|---|
setSetting
|
Update a setting in Visual Studio Code |
{
"action": "setSetting",
"setting": {
"key": "<setting key>",
"value": "<value>"
}
} |
Here is an example of how you can hide the activity and status bar in Visual Studio Code.
{
"action": "setSetting",
"args": {
"setting": "workbench.statusBar.visible",
"value": false
}
},
{
"action": "setSetting",
"args": {
"setting": "workbench.activityBar.location",
"value": "hidden"
}
}
To reset the settings, you can use the following steps:
{
"action": "setSetting",
"setting": {
"key": "workbench.statusBar.visible",
"value": null
}
},
{
"action": "setSetting",
"setting": {
"key": "workbench.activityBar.location",
"value": null
}
}
Find more information on the time actions documentation page.
Action | Description | Usage |
---|---|---|
waitForTimeout
|
Wait for a specific amount of time |
{
"action": "waitForTimeout",
"timeout": "<timeout in milliseconds>"
} |
waitForInput
|
Wait until the user presses a key |
{
"action": "waitForInput"
} |
Find more information on the vscode actions documentation page.
Action | Description | Usage |
---|---|---|
executeVSCodeCommand
|
Execute a VSCode command |
{
"action": "executeVSCodeCommand",
"command": "<command to execute>",
"args": "<arguments to pass to the command (optional)>",
"path": "<relative path to the file (optional, when defined, the args property is ignored.)>"
} |
showInfoMessage
|
Show a notification in Visual Studio Code |
{
"action": "showInfoMessage",
"message": "<message>"
} |
Find more information on the terminal actions documentation page.
Action | Description | Usage |
---|---|---|
executeTerminalCommand
|
Execute a command in the terminal |
{
"action": "executeTerminalCommand",
"command": "<command to execute>",
"terminalId": "<terminal id (optional)>"
} |
closeTerminal
|
Close the terminal |
{
"action": "closeTerminal",
"command": "<command to execute>",
"terminalId": "<terminal id (optional)>"
} |
Find more information on the snippet actions documentation page.
Action | Description | Usage |
---|---|---|
snippet
|
Use a snippet in which you can define multiple reusable steps |
{
"action": "snippet",
"contentPath": "<relative path to the file in the .demo folder> (optional)"
"args": {
// Define the argument name in the snippet file with curly braces {argument name}
"<argument name>": "<argument value>"
}
} |
You can find examples of snippets in the snippets folder.
In the demo file, you can reference a snippet file. The snippet file can contain multiple steps which can be reused in multiple demos.
{
"action": "snippet",
"contentPath": "./snippets/insert_and_highlight.json",
"args": {
"MAIN_FILE": "sample.json",
"CONTENT_PATH": "content.txt",
"CONTENT_POSITION": "3",
"HIGHLIGHT_POSITION": "4"
}
}
The
contentPath
property its value is relative to the.demo
folder. So, in the example above, the snippet file is located in the.demo/snippets
folder.
In the
args
property, you can define the arguments/variables which you want to use in the snippet file. In the snippet file, you can reference these arguments with curly braces{argument name}
.
In the insert_and_highlight.json
file, you can define the steps you want to execute.
[
{
"action": "unselect",
"path": "{MAIN_FILE}"
},
{
"action": "insert",
"path": "{MAIN_FILE}",
"contentPath": "{CONTENT_PATH}",
"position": "{CONTENT_POSITION}"
},
{
"action": "highlight",
"path": "{MAIN_FILE}",
"position": "{HIGHLIGHT_POSITION}"
}
]
Setting | Description | Default |
---|---|---|
demoTime.highlightBackground |
The background color of the highlighted code. | var(--vscode-editor-selectionBackground) |
demoTime.highlightBorderColor |
The border color of the highlighted code. | rgba(255,0,0,0.5) |
demoTime.highlightBlur |
Blur effect on the text which is not highlighted. | 0 |
demoTime.highlightOpacity |
The opacity of the text which is not highlighted. Number between 0 and 1. | 0.5 |
demoTime.highlightZoomEnabled |
Enable zooming when highlighting code. | false | number (zoom level) |
demoTime.previousEnabled |
Enable the previous command when in presentation mode. | false |
demoTime.showClock |
Show a clock in the status bar. | true |
demoTime.timer |
Count down timer for how long the session should last. If not set, it will not count down. The value is the number of minutes. | null |
demoTime.lineInsertionDelay |
The speed in milliseconds for inserting lines. If you set it to 0 , it will insert its content immediately. |
25 |
demoTime.api.enabled |
Enable the API to control the extension. | false |
demoTime.api.port |
The port on which the API should run. | 3710 |
The
demoTime.previousEnabled
is by default disabled to avoid conflicts when the previous action inserted content into a file. When you enable this setting, you can use theDemo Time: Previous
command to go back to the previous step or use the left clicker button.
Command | Description |
---|---|
Demo Time: Start |
Starts the demo or runs the next demo step. |
Demo Time: Previous |
Go back to the previous demo step (only in presentation mode and when the demoTime.previousEnabled setting is enabled). |
Demo Time: Add as demo step |
Add the current selection as a demo step to the demo file. |
Demo Time: Reset |
Reset all the demos. |
Demo Time: Start countdown |
Start the countdown clock (you need to define the time in the demoTime.timer setting). |
Demo Time: Reset countdown |
Reset the countdown clock. |
Demo Time: Toggle presentation mode |
Toggle the presentation mode. In this mode you'll be able to use your clicker or arrow keys for the Demo Time: Start and Demo Time: Previous commands. |
Demo Time: Show presenter view |
Open the presenter view which you can detach and move to another screen while presenting. |
The
Demo Time: Start
andDemo Time: Previous
commands have a keybinding assigned to them. You can override these keybindings in your Visual Studio Code settings.
The extension provides an API which you can use to control the extension. You can enable the API by setting the demoTime.api.enabled
setting to true
. When enabled, the API will run on the port defined in the demoTime.api.port
setting.
API URL: http://localhost:3710/api/next
This endpoint will execute the next step in the demo.
- Method:
GET
- Query parameters:
bringToFront
: Bring the Visual Studio Code window to the front. Default isfalse
.
This endpoint will execute a specific step by its ID in your demo.
You can call this endpoint via a GET
or POST
request.
- Method:
GET
- Query parameters:
id
: The ID of the step you want tobringToFront
: Bring the Visual Studio Code window to the front. Default isfalse
.
-
Method:
POST
-
Body:
{ "id": "<step id>", "bringToFront": "<bring the Visual Studio Code window to the front (optional) - default is false>" }
-
Headers:
Content-Type: application/json
You are also able to add notes to your demos. These notes can be used to provide additional information for yourself or others who will be executing the demo.
The notes should be created as a markdown file in the .demo
folder. Here is an example of how you can add notes to your demo:
{
"title": "<title>",
"description": "<description>",
"steps": [...],
"notes": {
"path": "<relative path in the .demo folder>",
"showOnTrigger": "<show notes on trigger (optional) - default is false>"
}
}
By default, the extension highlights the code in a box with a red border. You can customize how you want to highlight the code with the highlight settings.
Here is an example where the highlight border and background color are customized. Besides these color changes, the text which is not highlighted is blurred and its opacity is reduced to have a better focus on the highlighted code.
{
"demoTime.highlightBorderColor": "transparent",
"demoTime.highlightBackground": "rgba(19, 142, 151, 0.2)",
"demoTime.highlightOpacity": 0.5,
"demoTime.highlightBlur": 2,
}
You can define variables in a variables.json
file in the .demo
folder. You can reference these variables in your demo steps by using curly braces {variable_name}
.
{
"SLIDES_URL": "http://localhost:3030"
}
{
"action": "executeVSCodeCommand",
"command": "simpleBrowser.show",
"args": "{SLIDES_URL}"
}
For the positioning of the text to insert, there are two options:
- Use the
position
property to specify the location where the action should be performed. With this property, you can specify the line number, character position, or a range of lines and characters. - Use the
startPlaceholder
andendPlaceholder
properties to specify the text to search for in the file to determine the location where the action should be performed.
For the position
property, you can use the following values:
number
: The line numbernumber:number
: The start and end line numbernumber,number
: The start line and characternumber,number:number,number
: The start line and character and the end line and character- The
start
andend
keywords can also be used instead of the line numbersstart
will be replaced by the first line numberend
will be replaced by the last line number
Examples:
"position": "10" // Line 10
"position": "10:20" // Lines 10 to 20
"position": "10,5" // Start line 10, character 5
"position": "10,5:20,10" // Start line 10, character 5 to end line 20, character 10
For the startPlaceholder
and endPlaceholder
properties, you specify the text to search for in the file.
Examples:
"startPlaceholder": "// Start of demo1"
"endPlaceholder": "// End of demo1"
The text will be replaced from the start of the
startPlaceholder
to the end of theendPlaceholder
.
In the file, the placeholders should be defined like this:
// Start of demo1
const ext = 'Demo Time';
// End of demo1
When you want to insert content to a file, you can use the content
or contentPath
properties in the demo step.
Property | Description |
---|---|
content |
This property allows you to add the content directly in the JSON file, but this can make your JSON file quite big and it can be hard to read. |
contentPath |
This property allows you to reference a file in the .demo folder. This way you can keep your JSON file clean and add the content in separate files. Important: the path is relative to the .demo folder. |
When you use two screens during a presentation, you can use the detachable presenter view which you can move to another screen. This way you can keep an eye on the next steps while presenting without showing it to your audience.
Follow these steps to use the presenter view:
- Run the
Demo Time: Show presenter view
command to open the presenter view. - The presenter view will open in detached mode. If that is not the case, you can drag tab out of the Visual Studio Code window.
- Once detached, you can move it to another screen.
Here is an example demo:
{
"$schema": "https://demotime.elio.dev/demo-time.schema.json",
"title": "Sample demo",
"description": "This is a sample demo configuration to show the capabilities of the extension.",
"demos": [
{
"title": "Step 1",
"description": "This is step 1",
"steps": [
{
"action": "create",
"path": "sample.json",
"content": "{\n \"firstName\": \"Elio\",\n \"lastName\": \"Struyf\"\n}"
},
{
"action": "open",
"path": "sample.json"
},
{
"action": "highlight",
"path": "sample.json",
"position": "2:3"
}
]
},
{
"title": "Step 2",
"description": "This is step 2",
"steps": [
{
"action": "snippet",
"contentPath": "./snippets/insert_and_highlight.json",
"args": {
"MAIN_FILE": "sample.json",
"CONTENT_PATH": "content.txt",
"CONTENT_POSITION": "3",
"HIGHLIGHT_POSITION": "4"
}
}
]
}
]
}
You can also explore a comprehensive example in the following GitHub Repositories:
If you enjoy my work and find them useful, consider sponsor me and the ecosystem to help Open Source sustainable. Thank you!