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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

# Development version

- Added support for formatting notebook cells (progress towards #405, @kv9898).


# 0.8.0

- Added support for table formatting of `tribble()` and `fcase()` calls (#113).
Expand Down
71 changes: 57 additions & 14 deletions crates/lsp/src/handlers_format.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,3 @@
//
// handlers_format.rs
//
// Copyright (C) 2024 Posit Software, PBC. All rights reserved.
//
//

use air_r_syntax::{RExpressionList, RSyntaxKind, RSyntaxNode, WalkEvent};
use biome_rowan::{AstNode, Language, SyntaxElement};
use biome_text_size::{TextRange, TextSize};
Expand Down Expand Up @@ -54,13 +47,23 @@ pub(crate) fn document_formatting(
let format_options = workspace_settings.to_format_options(&doc.contents, &doc.settings);

match format_source_with_parse(&doc.contents, &doc.parse, format_options)? {
FormattedSource::Changed(formatted) => Ok(Some(to_proto::replace_all_edit(
&doc.contents,
&formatted,
&doc.line_index,
doc.position_encoding,
doc.endings,
)?)),
FormattedSource::Changed(mut formatted) => {
// For notebook cells, remove the trailing newline that the formatter adds.
// The formatter always adds a trailing newline for R files (which is correct
// for standalone files), but notebook cells should not have this trailing newline
// to avoid an empty line at the end of the chunk.
if uri.scheme() == "vscode-notebook-cell" && formatted.ends_with('\n') {
formatted.pop();
}

Ok(Some(to_proto::replace_all_edit(
&doc.contents,
&formatted,
&doc.line_index,
doc.position_encoding,
doc.endings,
)?))
}
FormattedSource::Unchanged => Ok(None),
}
}
Expand Down Expand Up @@ -646,6 +649,46 @@ mod tests {
assert_eq!(output, expect);
}

#[tokio::test]
async fn test_format_notebook_cells() {
let mut client = new_test_client().await;

// Notebook cells use the `vscode-notebook-cell` scheme
// They should NOT have a trailing newline, unlike regular files
let filename = FileName::Url(String::from("vscode-notebook-cell:/path/to/notebook#cell1"));

let input = "1+1";
// Note: No trailing newline in the expected output for notebook cells
let expect = "1 + 1";
let doc = Document::doodle(input);
let output = client.format_document(&doc, filename).await;
assert_eq!(output, expect);

// Test with multiple lines
let filename = FileName::Url(String::from("vscode-notebook-cell:/path/to/notebook#cell2"));
let input = "1+1\nx<-2";
let expect = "1 + 1\nx <- 2";
let doc = Document::doodle(input);
let output = client.format_document(&doc, filename).await;
assert_eq!(output, expect);

// Test with a trailing line
let filename = FileName::Url(String::from("vscode-notebook-cell:/path/to/notebook#cell3"));
let input = "1+1\n";
let expect = "1 + 1";
let doc = Document::doodle(input);
let output = client.format_document(&doc, filename).await;
assert_eq!(output, expect);

// Test with two trailing lines
let filename = FileName::Url(String::from("vscode-notebook-cell:/path/to/notebook#cell3"));
let input = "1+1\n\n";
let expect = "1 + 1";
let doc = Document::doodle(input);
let output = client.format_document(&doc, filename).await;
assert_eq!(output, expect);
}

#[tokio::test]
async fn test_format_default_excluded_files() {
let as_file_url = |path: &str| {
Expand Down
1 change: 1 addition & 0 deletions editors/code/src/lsp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ export class Lsp {
documentSelector: [
{ language: "r", scheme: "untitled" },
{ language: "r", scheme: "file" },
{ language: "r", scheme: "vscode-notebook-cell" },
{ language: "r", pattern: "**/*.{r,R}" },
{ language: "r", pattern: "**/*.{rprofile,Rprofile}" },
],
Expand Down