Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Support Shinylive export/import #44

Merged
merged 28 commits into from
May 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
fc544ff
feat(shinylive): Send current app to shinylive
gadenbuie Apr 28, 2024
30794db
feat(shinylive): Add saveAppFromUrl
gadenbuie Apr 28, 2024
1a3c5e8
feat(shinylive): Add Create from Selected FIles explorer command
gadenbuie Apr 29, 2024
c52829a
chore: Adjust title of create from active file command
gadenbuie Apr 29, 2024
f658b6f
chore(createFromExplorer): First arg is ignored intentionally
gadenbuie Apr 29, 2024
493ddb8
chore: Hide `createFromExplorer` from command palette
gadenbuie Apr 29, 2024
462ee35
chore: comment
gadenbuie Apr 29, 2024
f4399c0
docs: Add inline function docs
gadenbuie Apr 29, 2024
74bad48
feat(shinylive): Support release/dev shinylive hosts
gadenbuie Apr 29, 2024
3122ba4
docs: fill out enum descriptions
gadenbuie Apr 29, 2024
3c33b5e
chore: rename `appMode` and `openAction` for clarity
gadenbuie Apr 29, 2024
fa4fb64
docs: Update README
gadenbuie Apr 29, 2024
871a5c6
docs: Add changelog item
gadenbuie Apr 29, 2024
ee13768
feat: Save single-file shinylive apps as a single file rather than di…
gadenbuie Apr 30, 2024
f8320c6
Merge 'upstream/main' into 'feat/shinylive'
gadenbuie Apr 30, 2024
3693f56
docs: Slight edit to readme
gadenbuie Apr 30, 2024
191c466
fix: cancel creating link if user cancels from quickpick menus
gadenbuie May 1, 2024
a461020
feat: Add description of app/editor modes to quick pick
gadenbuie May 1, 2024
f390af2
fix: Don't save multi-file apps that aren't contained to a single folder
gadenbuie May 1, 2024
4bae38a
chore: Confirm with user before overwriting files
gadenbuie May 1, 2024
f638ed2
refactor: rename `createAndOpenShinyliveLink`
gadenbuie May 1, 2024
a6ca953
docs: small docstring edits
gadenbuie May 1, 2024
753ff5d
rename: createFromActiveEditor
gadenbuie May 1, 2024
ced67aa
fix(createFromActiveEditor): don't require a saved file for
gadenbuie May 1, 2024
ff46e75
chore: Use `vscode.Uri` everywhere with better path math
gadenbuie May 1, 2024
815a643
refactor: Don't need the "cancelled" message, user knows they cancelled
gadenbuie May 1, 2024
88f6e07
chore: Make sure "Shinylive" is first or second word in error messages
gadenbuie May 1, 2024
86e6d07
chore: remove "fs" import
gadenbuie May 1, 2024
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
- Added a new setting, `shiny.previewType`, to control where the Shiny app preview should be opened. (#40)
- Added a new `shinyexpress` snippet to quickly create a basic Shiny Express app in Python. (#42)
- The extension now correctly escapes commands on PowerShell 7 where the binary is named `pwsh.exe`. (#48)
- The extension can now create Shinylive links or save apps from Shinylive links (#44):
- **Create ShinyLive Link from Active File** creates a Shinylive link from the active file (Command Palette).
- **Create ShinyLive Link from Selected Files** creates a Shinylive link from the selected files or directories in the right-click context menu of the File Explorer.
- **Save App from Shinylive Link** saves an app and its files from a Shinylive link (Command Palette).

## 0.1.6

Expand Down
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ This is an extension to help launch [Shiny applications](https://shiny.posit.co)

## Features

### Run and Debug Shiny Apps

The main features of this extension are additional options in the Run button menu when editing an `app.py` or `app.R` file to "Run Shiny App" or "Debug Shiny App" (Python only).

![Run app](https://shiny.posit.co/py/docs/assets/vscode.png)
Expand All @@ -15,6 +17,20 @@ It also provides a couple of code snippets in both Python and R:

For a complete Shiny for Python experience in VS Code, please [visit our docs for more information](https://shiny.posit.co/py/docs/install-create-run.html#vs-code), including instructions for configuring the type checker and debugger for use with Shiny.

### Shinylive

You can use the extension to create shareable links to your apps using [Shinylive](https://shinylive.io), a free service for sharing Shiny apps via static hosting. Shinylive links encode the app's code and data in the URL, so you can share your app with others without needing to deploy it to a server. When the link is opened, the app runs in the user's browser using special version of Python or R that can run in the browser.

**To create a Shinylive link from your app**, you have two choices:

1. For single-file apps, e.g. `app.py` or `app.R`, run the **Create ShinyLive Link from Active File** from the command palette with the app file open and active.

2. For multi-file apps, select all of the files or directories you want to include in your Shinylive app in the Explorer pane. Then right click on the selection and choose **Create ShinyLive Link from Selected Files**.

The Shiny extension will ask you which app mode you want to use (display the _app_ or show an _editor_ next to the app) and what action to take (to _open_ or _copy_ the link).You can also configure these options in the extension settings.

For the reverse operation, use the **Save App from Shinylive Link** command in the command palette to save an app and its files from a Shinylive link. You'll be prompted to paste the Shinylive link and then to choose where the app will be saved in your workspace.

## Extension Settings

This extension contributes the following settings for Python and R.
Expand All @@ -30,3 +46,10 @@ Note that there is no setting for Python executable path or virtual environment.

- `shiny.r.port`: The port number to listen on when running a Shiny app. (By default, 0, which will choose a random port for each workspace.)
- `shiny.r.devmode`: When `true` (default), Shiny for R apps are launched [in developer mode](https://shiny.posit.co/r/reference/shiny/latest/devmode.html).

### Shinylive

- `shiny.shinylive.appMode`: Should the Shinylive link open the app in `"app"` mode, showing only the app and an optional header, or in `"editor"` mode with the app alongside an editor and console pane. The default is `"ask"`, which prompts you each time you create Shinylive link.
- `shiny.includeHeader`: Include the "Shiny" header in the Shinylive link when opening in app mode?
- `shiny.shinylive.openAction`: What action should be taken when opening a Shinylive link? Options are `"open"` to open the link in an external browser, `"copy"` the link to the clipboard, or `"ask"`. The default is `"ask"`, which prompts you each time you create a Shinylive link.
- `shiny.shinylive.host`: The Shinylive host used when creating a Shinylive link. The default is `"https://shinylive.io"`, which uses the latest released version of Shiny in Python or R. Or `"https://posit-dev.github.io/shinylive"`, which uses the latest development version of Shiny in Python or R.
84 changes: 83 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,41 @@
"title": "Run Shiny App",
"icon": "$(play)",
"enablement": "editorLangId == r && shellExecutionSupported"
},
{
"category": "Shiny",
"command": "shiny.shinylive.createFromActiveEditor",
"title": "Create ShinyLive Link from Active Editor",
"icon": "$(cloud-upload)",
"enablement": "editorLangId == python || editorLangId == r"
},
{
"category": "Shiny",
"command": "shiny.shinylive.saveAppFromUrl",
"title": "Save App from Shinylive Link",
"icon": "$(cloud-download)"
},
{
"category": "Shiny",
"command": "shiny.shinylive.createFromExplorer",
"title": "Create Shinylive Link from Selected Files",
"icon": "$(cloud-upload)"
}
],
"menus": {
"explorer/context": [
{
"command": "shiny.shinylive.createFromExplorer",
"group": "shinylive",
"when": "true"
}
],
"commandPalette": [
{
"command": "shiny.shinylive.createFromExplorer",
"when": "false"
}
],
"editor/title/run": [
{
"command": "shiny.python.runApp",
Expand Down Expand Up @@ -118,7 +150,55 @@
"shiny.r.devmode": {
"type": "boolean",
"default": true,
"description": "Enable dev mode when running a Shiny for R app by running `shiny::devmode()` before launching the app."
"markdownDescription": "Enable dev mode when running a Shiny for R app by running `shiny::devmode()` before launching the app."
},
"shiny.shinylive.appMode": {
"type": "string",
"default": "ask",
"description": "Which Shinylive mode to use when creating a Shinylive app.",
"enum": [
"ask",
"app",
"editor"
],
"enumDescriptions": [
"Ask which mode to use.",
"App mode displays only the app with an optional header.",
"Editor mode displays the app alongside an editor and console."
]
},
"shiny.shinylive.openAction": {
"type": "string",
"default": "ask",
"description": "Choose the default action upon creating a Shinylive link.",
"enum": [
"ask",
"open",
"copy"
],
"enumDescriptions": [
"Ask which action to take.",
"Open the link in the default browser.",
"Copy the link to the clipboard."
]
},
"shiny.shinylive.includeHeader": {
"type": "boolean",
"default": true,
"description": "Include the Shiny header when creating Shinylive app links. Only relevant for app mode Shinylive links."
},
"shiny.shinylive.host": {
"type": "string",
"default": "https://shinylive.io",
"description": "The default Shinylive host to use when creating Shinylive app links.",
"enum": [
"https://shinylive.io",
"https://posit-dev.github.io/shinylive"
],
"enumDescriptions": [
"Uses the latest released version of Shiny in Python or R.",
"Uses the latest development version of Shiny in Python or R."
]
}
}
}
Expand Down Expand Up @@ -150,6 +230,8 @@
"@types/winreg": "^1.2.36",
"@vscode/python-extension": "^1.0.5",
"fs": "^0.0.1-security",
"istextorbinary": "^9.5.0",
"lz-string": "^1.5.0",
"winreg": "^1.2.5"
}
}
24 changes: 22 additions & 2 deletions src/extension.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,29 @@
import * as vscode from "vscode";
import * as path from "path";
import { pyRunApp, rRunApp, pyDebugApp, onDidStartDebugSession } from "./run";
import {
shinyliveCreateFromActiveEditor,
shinyliveSaveAppFromUrl,
shinyliveCreateFromExplorer,
} from "./shinylive";

export function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(
vscode.commands.registerCommand("shiny.python.runApp", pyRunApp),
vscode.commands.registerCommand("shiny.python.debugApp", pyDebugApp),
vscode.commands.registerCommand("shiny.r.runApp", rRunApp)
vscode.commands.registerCommand("shiny.r.runApp", rRunApp),
vscode.commands.registerCommand(
"shiny.shinylive.createFromActiveEditor",
shinyliveCreateFromActiveEditor
),
vscode.commands.registerCommand(
"shiny.shinylive.saveAppFromUrl",
shinyliveSaveAppFromUrl
),
vscode.commands.registerCommand(
"shiny.shinylive.createFromExplorer",
shinyliveCreateFromExplorer
)
);

const throttledUpdateContext = new Throttler(2000, () => {
Expand Down Expand Up @@ -119,7 +136,10 @@ class Throttler {
}
}

function isShinyAppUsername(filename: string, language: string): boolean {
export function isShinyAppUsername(
filename: string,
language: string
): boolean {
filename = path.basename(filename);

const extension = { python: "py", r: "R" }[language];
Expand Down
Loading