Skip to content

Commit d36433a

Browse files
committed
chore: merge branch 'main' into feat/protect-options-formatting
2 parents fb7c178 + b1a2cab commit d36433a

File tree

9 files changed

+216
-112
lines changed

9 files changed

+216
-112
lines changed

apps/vscode/CHANGELOG.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
# Changelog
22

3-
## 1.126.0 (Unreleased)
3+
## 1.127.0 (Unreleased)
44

5-
## 1.125.0 (Release on 2025-09-03)
5+
- Added a new setting `quarto.useBundledQuartoInPositron` to prefer the Quarto CLI bundled with Positron when available. This setting has precedence _between_ `quarto.path` and `quarto.usePipQuarto`, and has no effect outside of Positron (<https://github.com/quarto-dev/quarto/pull/841>).
6+
7+
## 1.126.0 (Release on 2025-10-08)
8+
9+
- Fixed a bug opening non-Quarto files in visual mode on saving (<https://github.com/quarto-dev/quarto/pull/848>).
10+
11+
## 1.125.0 (Release on 2025-10-03)
612

713
- Fixed an issue where attribute values containing '='s could be truncated in some scenarios (<https://github.com/quarto-dev/quarto/pull/814>).
814
- Fixed an issue where a loading spinner for qmd previews wasn't dismissed on preview errors (<https://github.com/quarto-dev/quarto/pull/823>).

apps/vscode/package.json

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
"pandoc",
1212
"quarto"
1313
],
14-
"version": "1.126.0",
14+
"version": "1.127.0",
1515
"repository": {
1616
"type": "git",
1717
"url": "https://github.com/quarto-dev/quarto/tree/main/apps/vscode"
@@ -1105,7 +1105,13 @@
11051105
"order": 11,
11061106
"type": "boolean",
11071107
"default": true,
1108-
"markdownDescription": "When using a venv or conda environment, prefer Quarto CLI installed with pip in that environment. This will override Quarto CLI in the `PATH`, but not an explicitly configured `#quarto.path#`."
1108+
"markdownDescription": "When using a venv or conda environment, prefer Quarto CLI installed with pip in that environment. This will override Quarto CLI in the `PATH`, but not an explicitly configured `#quarto.path#` or the bundled Quarto when `#quarto.useBundledQuartoInPositron#` is enabled."
1109+
},
1110+
"quarto.useBundledQuartoInPositron": {
1111+
"order": 11,
1112+
"type": "boolean",
1113+
"default": false,
1114+
"markdownDescription": "When in Positron, prefer the bundled Quarto CLI provided by the IDE. This will override Quarto CLI from `quarto.usePipQuarto` and in the `PATH`, but not an explicitly configured `#quarto.path#`. Note that this setting has no effect outside of Positron."
11091115
},
11101116
"quarto.render.renderOnSave": {
11111117
"order": 12,
@@ -1446,6 +1452,7 @@
14461452
"nanoid": "^4.0.0",
14471453
"p-queue": "^8.0.1",
14481454
"picomatch": "^2.3.1",
1455+
"@posit-dev/positron": "^0.1.0",
14491456
"quarto-core": "*",
14501457
"quarto-lsp": "*",
14511458
"quarto-vscode-editor": "*",

apps/vscode/src/core/quarto.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import * as path from "node:path";
1717
import * as fs from "node:fs";
1818

1919
import { window, env, workspace, Uri } from "vscode";
20+
import { tryAcquirePositronApi } from "@posit-dev/positron";
2021
import { QuartoContext } from "quarto-core";
2122
import { activePythonInterpreter, pythonIsCondaEnv, pythonIsVenv } from "./python";
2223
import { isWindows } from "./platform";
@@ -35,6 +36,38 @@ export async function configuredQuartoPath() {
3536
return quartoPath;
3637
}
3738

39+
// check if we should use bundled Quarto in Positron
40+
const useBundledQuarto = config.get("useBundledQuartoInPositron", false); // Default is now false
41+
if (useBundledQuarto) {
42+
// Check if we're in Positron
43+
const isPositron = tryAcquirePositronApi();
44+
45+
if (isPositron) {
46+
// Use path relative to the application root for Positron's bundled Quarto
47+
const rootPath = env.appRoot; // Use vscode.env.appRoot as the application root path
48+
const positronQuartoPath = path.join(
49+
rootPath,
50+
"quarto",
51+
"bin",
52+
isWindows() ? "quarto.exe" : "quarto"
53+
);
54+
55+
if (fs.existsSync(positronQuartoPath)) {
56+
return positronQuartoPath;
57+
} else {
58+
// Log error when bundled Quarto can't be found
59+
console.error(
60+
`useBundledQuartoInPositron is enabled but bundled Quarto not found at expected path: ${positronQuartoPath}. ` +
61+
`Verify Quarto is bundled in the Positron installation.`
62+
);
63+
64+
window.showWarningMessage(
65+
"Unable to find bundled Quarto in Positron; falling back to system installation"
66+
);
67+
}
68+
}
69+
}
70+
3871
// if we can use pip quarto then look for it within the currently python (if its a venv/condaenv)
3972
const usePipQuarto = config.get("usePipQuarto", true);
4073
if (usePipQuarto) {

apps/vscode/src/main.ts

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
import * as vscode from "vscode";
1717
import * as path from "path";
18+
import { tryAcquirePositronApi } from "@posit-dev/positron";
1819
import { MarkdownEngine } from "./markdown/engine";
1920
import { kQuartoDocSelector } from "./core/doc";
2021
import { activateLsp, deactivate as deactivateLsp } from "./lsp/client";
@@ -60,7 +61,7 @@ export async function activate(context: vscode.ExtensionContext) {
6061
quartoPath,
6162
workspaceFolder,
6263
// Look for quarto in the app root; this is where Positron installs it
63-
[path.join(vscode.env.appRoot, 'quarto', 'bin')],
64+
[path.join(vscode.env.appRoot, "quarto", "bin")],
6465
vscode.window.showWarningMessage
6566
);
6667
if (quartoContext.available) {
@@ -129,9 +130,53 @@ export async function activate(context: vscode.ExtensionContext) {
129130
// activate providers common to browser/node
130131
activateCommon(context, host, engine, commands);
131132

133+
// Register configuration change listener for Quarto path settings
134+
registerQuartoPathConfigListener(context, outputChannel);
135+
132136
outputChannel.info("Activated Quarto extension.");
133137
}
134138

139+
/**
140+
* Register a listener for changes to Quarto path settings that require a restart
141+
*/
142+
function registerQuartoPathConfigListener(context: vscode.ExtensionContext, outputChannel: vscode.LogOutputChannel) {
143+
// Check if we're in Positron
144+
const isPositron = tryAcquirePositronApi();
145+
146+
// List of settings that require restart when changed
147+
const quartoPathSettings = [
148+
"quarto.path",
149+
"quarto.usePipQuarto",
150+
];
151+
const positronPathSettings = [
152+
"quarto.useBundledQuartoInPositron"
153+
];
154+
155+
// Listen for configuration changes
156+
context.subscriptions.push(
157+
vscode.workspace.onDidChangeConfiguration(event => {
158+
// Check if any of our path settings changed
159+
const requiresRestart = quartoPathSettings.some(setting => event.affectsConfiguration(setting));
160+
const requiresPositronRestart = isPositron && positronPathSettings.some(setting => event.affectsConfiguration(setting));
161+
162+
if (requiresRestart || requiresPositronRestart) {
163+
outputChannel.info(`Quarto path settings changed, restart required: ${quartoPathSettings.filter(setting =>
164+
event.affectsConfiguration(setting)).join(", ")}`);
165+
166+
// Prompt user to restart
167+
vscode.window.showInformationMessage(
168+
"Quarto path settings have changed. Please reload the window for changes to take effect.",
169+
"Reload Window"
170+
).then(selection => {
171+
if (selection === "Reload Window") {
172+
vscode.commands.executeCommand("workbench.action.reloadWindow");
173+
}
174+
});
175+
}
176+
})
177+
);
178+
}
179+
135180
export async function deactivate() {
136181
return deactivateLsp();
137182
}

apps/vscode/src/providers/editor/toggle.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -129,18 +129,18 @@ export async function reopenEditorInVisualMode(
129129
// reopen in visual mode
130130
commands.executeCommand('positron.reopenWith', document.uri, 'quarto.visualEditor');
131131
} else {
132-
workspace.onDidSaveTextDocument(async (doc: TextDocument) => {
133-
// open in visual mode
134-
VisualEditorProvider.recordPendingSwitchToVisual(doc);
135-
await commands.executeCommand('workbench.action.closeActiveEditor');
136-
await commands.executeCommand("vscode.openWith",
137-
doc.uri,
138-
VisualEditorProvider.viewType,
139-
{ viewColumn }
140-
);
141-
});
142-
// save, which will trigger `onDidSaveTextDocument`
132+
// save then close
143133
await commands.executeCommand("workbench.action.files.save");
134+
await commands.executeCommand('workbench.action.closeActiveEditor');
135+
VisualEditorProvider.recordPendingSwitchToVisual(document);
136+
137+
// open in visual mode
138+
await commands.executeCommand(
139+
"vscode.openWith",
140+
document.uri,
141+
VisualEditorProvider.viewType,
142+
{ viewColumn }
143+
);
144144
}
145145
}
146146

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
print("Hello World")

apps/vscode/src/test/quartoDoc.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,20 @@ suite("Quarto basics", function () {
4141
roundtripSnapshotTest('capsule-leak.qmd');
4242

4343
roundtripSnapshotTest('attr-equals.qmd');
44+
45+
// a test to prevent situations like https://github.com/quarto-dev/quarto/issues/845
46+
test("Can open a non-qmd file normally", async function () {
47+
const { editor, doc } = await openAndShowTextDocument("hello.lua");
48+
49+
editor.edit((editBuilder) => {
50+
editBuilder.insert(new vscode.Position(0, 0), 'print("hiyo")\n');
51+
});
52+
doc.save();
53+
54+
await wait(1700); // approximate time to open visual editor, just in case
55+
56+
assert.equal(vscode.window.activeTextEditor, editor, 'quarto extension interferes with other files opened in VSCode!');
57+
});
4458
});
4559

4660
/**

claude.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# Quarto Development Guide
2+
3+
## Project Overview
4+
5+
Quarto is an open-source scientific and technical publishing system built on [Pandoc](https://pandoc.org). This repository contains the source code for various parts of the Quarto ecosystem, with the main CLI implementation housed in a separate repository ([quarto-cli](https://github.com/quarto-dev/quarto-cli)).
6+
7+
### Main Components
8+
9+
- **VS Code Extension**: The primary VS Code extension for working with Quarto documents
10+
- **Writer**: An experimental web-based editor for Quarto documents (not used in production yet)
11+
- **LSP**: Language server for Quarto documents
12+
- **Core Packages**: Shared libraries used across multiple components
13+
14+
## Development Workflow
15+
16+
Each component has specific development guidelines. Refer to the corresponding CONTRIBUTING.md files:
17+
18+
- VS Code extension: [apps/vscode/CONTRIBUTING.md](apps/vscode/CONTRIBUTING.md) - Contains detailed instructions for building, debugging, and releasing the extension
19+
20+
## Repository Structure
21+
22+
The repository is organized as a monorepo using Yarn workspaces and Turborepo for build orchestration:
23+
24+
- `apps/`: Contains standalone applications
25+
- `vscode/`: VS Code extension for Quarto
26+
- `writer/`: Experimental web-based Quarto editor (not in production, ignore this for now)
27+
- `lsp/`: Language Server Protocol implementation
28+
- `panmirror/`: WYSIWYG editor component
29+
- `packages/`: Contains shared libraries
30+
- `core/`: Core functionality shared across packages
31+
- `editor-*/`: Editor-related packages
32+
- `quarto-core/`: Quarto-specific core functionality
33+
- Other utility packages
34+
35+
## Build System
36+
37+
Quarto uses [turborepo](https://turbo.build/) to manage the monorepo build process:
38+
39+
- `turbo.json`: Defines the pipeline configuration for common tasks
40+
- Common commands:
41+
- `yarn build`: Builds all packages and applications
42+
- `yarn dev-writer`: Runs the writer app in development mode
43+
- `yarn dev-vscode`: Runs the VS Code extension in development mode
44+
- `yarn lint`: Runs linters across all workspaces
45+
- `yarn build-vscode`: Builds only the VS Code extension and its dependencies
46+
47+
The turborepo pipeline helps optimize build times by caching build artifacts and respecting the dependency graph between packages.
48+
49+
## Testing
50+
51+
Testing procedures vary by component:
52+
53+
- VS Code extension: Run `yarn test-vscode` to compile test files and run them with the vscode-test CLI
54+
- Other components have specific test commands defined in their respective package.json files
55+
56+
57+
## Additional Resources
58+
59+
- [Quarto Website](https://quarto.org)
60+
- [Extension on Microsoft marketplace](https://marketplace.visualstudio.com/items?itemName=quarto.quarto)
61+
- [Extension on Open VSX Registry](https://open-vsx.org/extension/quarto/quarto)
62+
- [Quarto GitHub Organization](https://github.com/quarto-dev)
63+
64+
# Instructions

0 commit comments

Comments
 (0)