Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 90 additions & 0 deletions docs/variable-substitutions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# Variable Substitutions

BrightScript extension supports variable substitutions in launch.json configurations to make your debugging workflow more flexible and dynamic.

## Overview

Variable substitutions allow you to avoid hardcoding values in your launch configurations. Instead of specifying static IP addresses or passwords, you can use variables that are resolved at runtime.

## Available Variable Substitutions

| Variable | Description | Behavior |
|----------|-------------|----------|
| `${promptForHost}` | Prompts you to enter or select a host IP address | Shows input dialog or device picker when debugging starts |
| `${promptForPassword}` | Prompts you to enter the device password | Shows password input dialog when debugging starts |
| `${activeHost}` | Uses the currently active device | Automatically uses pre-configured device, or prompts if none set |
| `${host}` | References the resolved host value | Can be used in other fields like `deepLinkUrl` |

## `${promptForHost}` - Interactive Host Selection

The most common variable substitution. When used, VS Code will:
- Show a list of discovered Roku devices (if device discovery is enabled)
- Allow manual IP entry
- Remember the last used device

```json
{
"host": "${promptForHost}"
}
```

## `${promptForPassword}` - Interactive Password Entry

Prompts for the developer password when debugging starts:

```json
{
"password": "${promptForPassword}"
}
```

## `${activeHost}` - Smart Device Selection

**New!** Uses the currently active device without prompting, but gracefully falls back to prompting if no device is set. This provides the best of both worlds: convenience when you have a preferred device, flexibility when you don't.

### Basic Usage

```json
{
"version": "0.2.0",
"configurations": [
{
"type": "brightscript",
"name": "Launch with Current Device",
"request": "launch",
"host": "${activeHost}",
"password": "${promptForPassword}",
"rootDir": "${workspaceFolder}",
"files": [
"manifest",
"source/**/*.*",
"components/**/*.*",
"images/**/*.*"
]
}
]
}
```

### Requirements

To use `${activeHost}` optimally, you should set an active device using one of these methods:

1. **Via Command Palette:**
- Open Command Palette (`Ctrl+Shift+P` / `Cmd+Shift+P`)
- Type "BrightScript: Set Active Device"
- Enter the IP address of your Roku device

2. **Via Device List:**
- Use the Roku Devices view in the sidebar to select a device (if device discovery is enabled)

3. **Via Debugging Session:**
- The active device is automatically set when you start a debugging session with `${promptForHost}`

### Fallback Handling

If you use `${activeHost}` but no active device is set, it will automatically fallback to prompting for host selection (same behavior as `${promptForHost}`).

This provides a seamless experience:
- **When active device is set**: Uses it automatically without prompting
- **When no active device**: Falls back to the device picker/input dialog
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,7 @@
},
"deepLinkUrl": {
"type": "string",
"description": "A full deep link url to start the debugging session. There's no pretty way of launching directly to a deep link, so the app must be side-loaded, it auto-runs, we stop the app, and then launch it again using the deep link. You may use ${promptForHost}, ${host}, ${promptForQueryParams} which only asks for the URL-encoded querystring, and ${promptForDeepLinkUrl} to enter the entire deep link url at launch-time.",
"description": "A full deep link url to start the debugging session. There's no pretty way of launching directly to a deep link, so the app must be side-loaded, it auto-runs, we stop the app, and then launch it again using the deep link. You may use ${promptForHost}, ${activeHost}, ${host}, ${promptForQueryParams} which only asks for the URL-encoded querystring, and ${promptForDeepLinkUrl} to enter the entire deep link url at launch-time.",
"default": "http://${host}:8060/launch/dev?${promptForQueryParams}"
},
"password": {
Expand Down Expand Up @@ -2101,7 +2101,7 @@
},
"brightscript.debug.deepLinkUrl": {
"type": "string",
"description": "A full deep link url to start the debugging session. There's no pretty way of launching directly to a deep link, so the app must be side-loaded, it auto-runs, we stop the app, and then launch it again using the deep link. You may use ${promptForHost}, ${host}, ${promptForQueryParams} which only asks for the URL-encoded querystring, and ${promptForDeepLinkUrl} to enter the entire deep link url at launch-time.",
"description": "A full deep link url to start the debugging session. There's no pretty way of launching directly to a deep link, so the app must be side-loaded, it auto-runs, we stop the app, and then launch it again using the deep link. You may use ${promptForHost}, ${activeHost}, ${host}, ${promptForQueryParams} which only asks for the URL-encoded querystring, and ${promptForDeepLinkUrl} to enter the entire deep link url at launch-time.",
"default": "http://${host}:8060/launch/dev?${promptForQueryParams}",
"scope": "resource"
},
Expand Down
3 changes: 2 additions & 1 deletion src/DebugConfigurationProvider.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ describe('BrightScriptConfigurationProvider', () => {
activeDeviceManager,
null,
vscode.window.createOutputChannel('Extension'),
userInputManager
userInputManager,
null // BrightScriptCommands is not used in this test
);
});

Expand Down
7 changes: 6 additions & 1 deletion src/DebugConfigurationProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import cloneDeep = require('clone-deep');
import { rokuDeploy } from 'roku-deploy';
import type { DeviceInfo } from 'roku-deploy';
import type { UserInputManager } from './managers/UserInputManager';
import type { BrightScriptCommands } from './BrightScriptCommands';


export class BrightScriptDebugConfigurationProvider implements DebugConfigurationProvider {
Expand All @@ -30,7 +31,8 @@ export class BrightScriptDebugConfigurationProvider implements DebugConfiguratio
private activeDeviceManager: ActiveDeviceManager,
private telemetryManager: TelemetryManager,
private extensionOutputChannel: vscode.OutputChannel,
private userInputManager: UserInputManager
private userInputManager: UserInputManager,
private brightScriptCommands: BrightScriptCommands
) {
this.context = context;
this.activeDeviceManager = activeDeviceManager;
Expand Down Expand Up @@ -429,6 +431,9 @@ export class BrightScriptDebugConfigurationProvider implements DebugConfiguratio
} else {
config.host = await this.userInputManager.promptForHostManual();
}
} else if (config.host.trim() === '${activeHost}') {
// Get the current remote host from workspace state (it will prompt for host as a fallback)
config.host = await this.brightScriptCommands.getRemoteHost();
}

//check the host and throw error if not provided or update the workspace to set last host
Expand Down
2 changes: 1 addition & 1 deletion src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ export class Extension {
);

//register the debug configuration provider
let configProvider = new BrightScriptDebugConfigurationProvider(context, activeDeviceManager, this.telemetryManager, this.extensionOutputChannel, userInputManager);
let configProvider = new BrightScriptDebugConfigurationProvider(context, activeDeviceManager, this.telemetryManager, this.extensionOutputChannel, userInputManager, this.brightScriptCommands);
context.subscriptions.push(
vscode.debug.registerDebugConfigurationProvider('brightscript', configProvider)
);
Expand Down
Loading