Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
709bad8
feat: protect code cell options from being formatted
mcanouil Feb 8, 2025
5fc93c2
refactor: prepend hashpipe and rename counter variable
mcanouil Feb 8, 2025
cc2a8b0
chore: add changelog entry
mcanouil Feb 9, 2025
0694f60
Merge branch 'main' into feat/protect-options-formatting
mcanouil Mar 3, 2025
a48b0dd
Merge branch 'main' into feat/protect-options-formatting
mcanouil Mar 8, 2025
42d626d
Merge branch 'main' into feat/protect-options-formatting
mcanouil Apr 3, 2025
c96b819
feat: protect code cell options from being formatted
mcanouil Feb 8, 2025
7573a4e
refactor: prepend hashpipe and rename counter variable
mcanouil Feb 8, 2025
7bbb8c7
chore: add changelog entry
mcanouil Feb 9, 2025
d11c117
Merge branch 'feat/protect-options-formatting' of https://github.com/…
mcanouil Oct 5, 2025
a7cee84
Merge branch 'quarto-dev:main' into feat/protect-options-formatting
mcanouil Oct 5, 2025
f39071a
test: draft for testign document formatting with Python code blocks
mcanouil Oct 5, 2025
4903dbe
test: try to format cell only
mcanouil Oct 5, 2025
a3694d6
test: skip extension installation for now
mcanouil Oct 5, 2025
ba09180
test: remove timeout increase
mcanouil Oct 5, 2025
31d5415
test: use command line to install extension
mcanouil Oct 5, 2025
d2f81c8
test: install Black formatter extension
mcanouil Oct 5, 2025
4307811
test: add debugging code
mcanouil Oct 5, 2025
fb7c178
test: change testing approach
mcanouil Oct 19, 2025
d36433a
chore: merge branch 'main' into feat/protect-options-formatting
mcanouil Oct 19, 2025
da31716
test: tweak formatting test timing and documents
mcanouil Oct 19, 2025
2d08760
refactor: use hardcoded expected values
mcanouil Oct 19, 2025
03872b3
chore: Add subtitle to format-python.qmd
mcanouil Oct 20, 2025
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 apps/vscode/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@

- Fix issue where format on save could overwrite the contents of a document with incorrect results (<https://github.com/quarto-dev/quarto/pull/688>).

- Protect code cell options from formatting (<https://github.com/quarto-dev/quarto/pull/655>).

## 1.119.0 (Release on 2025-03-21)

- Use `QUARTO_VISUAL_EDITOR_CONFIRMED` > `PW_TEST` > `CI` to bypass (`true`) or force (`false`) the Visual Editor confirmation dialogue (<https://github.com/quarto-dev/quarto/pull/654>).
Expand All @@ -52,6 +54,8 @@
- Update cell background configuration to add the ability to use the appropriate theme color. The `quarto.cells.background` settings have changed names so you may need to update your configuration (<https://github.com/quarto-dev/quarto/pull/679>).
- Use new command to switch between source and visual editors in Positron (<https://github.com/quarto-dev/quarto/pull/684>).

- Protect code cell options from formatting (<https://github.com/quarto-dev/quarto/pull/655>).

## 1.118.0 (Release on 2024-11-26)

- Provide F1 help at cursor in Positron (<https://github.com/quarto-dev/quarto/pull/599>)
Expand Down
14 changes: 13 additions & 1 deletion apps/vscode/src/providers/format.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import {
virtualDocForLanguage,
withVirtualDocUri,
} from "../vdoc/vdoc";
import { languageOptionComment } from "./option";


export function activateCodeFormatting(engine: MarkdownEngine) {
Expand Down Expand Up @@ -204,7 +205,18 @@ async function formatActiveCell(editor: TextEditor, engine: MarkdownEngine) {
}

async function formatBlock(doc: TextDocument, block: TokenMath | TokenCodeBlock, language: EmbeddedLanguage) {
const optionComment = languageOptionComment(language.ids[0]) + "| ";
const blockLines = lines(codeForExecutableLanguageBlock(block));
let optionLines = 0;
if (optionComment) {
for (const line of blockLines) {
if (line.startsWith(optionComment)) {
optionLines++;
} else {
break;
}
}
}
blockLines.push("");
const vdoc = virtualDocForCode(blockLines, language);
const edits = await executeFormatDocumentProvider(
Expand All @@ -225,7 +237,7 @@ async function formatBlock(doc: TextDocument, block: TokenMath | TokenCodeBlock,
);
return new TextEdit(range, edit.newText);
})
.filter(edit => blockRange.contains(edit.range));
.filter(edit => blockRange.contains(edit.range) && edit.range.start.line > block.range.start.line + optionLines);
return adjustedEdits;
}
}
Expand Down
2 changes: 1 addition & 1 deletion apps/vscode/src/providers/option.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ function handleOptionEnter(editor: TextEditor, comment: string) {
}
}

function languageOptionComment(language: string) {
export function languageOptionComment(language: string) {
// some mappings
if (language === "ojs") {
language = "js";
Expand Down
10 changes: 10 additions & 0 deletions apps/vscode/src/test/examples/format-python.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
title: Formatting Python Code Cells
subtitle: https://github.com/quarto-dev/quarto/pull/655
format: html
---

```{python}
#| label: my-code
x=1;y=2;z=x+y
```
92 changes: 92 additions & 0 deletions apps/vscode/src/test/formatting.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import * as vscode from "vscode";
import * as assert from "assert";
import * as path from "path";
import { openAndShowTextDocument, wait } from "./test-utils";

/**
* Creates a document formatting provider from a formatting function.
* @param format - Function that transforms source text
* @returns Document formatting edit provider
*/
function createFormatterFromStringFunc(
format: (sourceText: string) => string
): vscode.DocumentFormattingEditProvider {
return {
provideDocumentFormattingEdits(
document: vscode.TextDocument
): vscode.TextEdit[] {
const text = document.getText();
const formatted = format(text);
return [
new vscode.TextEdit(
new vscode.Range(
document.positionAt(0),
document.positionAt(text.length)
),
formatted
),
];
},
};
}

/**
* Sets the cursor position in the active editor.
* @param line - Line number
* @param character - Character position
*/
function setCursorPosition(line: number, character: number): void {
const editor = vscode.window.activeTextEditor;
if (editor) {
const position = new vscode.Position(line, character);
editor.selection = new vscode.Selection(position, position);
}
}

/**
* Tests formatter on a file at a given cursor position.
* @param filename - Name of test file
* @param position - Tuple of line and character position
* @param format - Formatting function
* @returns Formatted document text
*/
async function testFormatter(
filename: string,
[line, character]: [number, number],
format: (sourceText: string) => string
) {
const { doc } = await openAndShowTextDocument(filename);

const formattingEditProvider =
vscode.languages.registerDocumentFormattingEditProvider(
{ scheme: "file", language: "python" },
createFormatterFromStringFunc(format)
);

setCursorPosition(line, character);
await wait(450);
await vscode.commands.executeCommand("quarto.formatCell");
await wait(450);

const result = doc.getText();
formattingEditProvider.dispose();
await vscode.commands.executeCommand("workbench.action.closeActiveEditor");

return result;
}

suite("Code Block Formatting", function () {
test("Format Python code block protects options from formatting", async function () {
const formattedResult = await testFormatter(
"format-python.qmd",
[7, 0],
(sourceText: string): string => sourceText.trim() + "\n"
);

assert.ok(formattedResult.includes("x = 1"), "Code should be formatted");
assert.ok(
formattedResult.includes("#| label: my-code"),
"Code Cell option should be preserved"
);
});
});
Loading