Show all R expression outputs in Quarto cells#14185
Conversation
|
All contributors have signed the CLA ✍️ ✅ |
|
I have read the CLA Document and I hereby sign the CLA |
jmcphers
left a comment
There was a problem hiding this comment.
This approach is going to be too slow to be practical in many situations. It's going to create an RPC round trip for every single line of code in the cell, and those can be very slow e.g. over remote SSH or on loaded systems.
To make this efficient, we should find statement boundaries via a single RPC to the back end (probably going through to Ark on the R side), or by precomputing them via a new LSP method during edits.
We do appreciate the contribution and are aware that lots of people are interested in this feature!
|
I updated this to use a single backend boundary query through Ark ( |
I see the update in this PR to ask Ark for the boundaries, but none on the Ark side to implement the back end of the RPC. Do you have the accompanying Ark changes? If so, can you open a PR for them as well? |
|
I implemented this on Ark side too, opening the PR right now. |
lionel-
left a comment
There was a problem hiding this comment.
I like your current approach that calls the LSP request we implemented in posit-dev/ark#533. We don't want to go through the kernel via the UI comm (cf your recent Ark-side PR) because that would necessarily make the input boundaries unavailable while R is busy. In practice this will also be the case with the Ark LSP (already the case on Windows, soon on Unix platforms too, see posit-dev/ark#1222). In the future though, this request will live in the standalone Oak LSP which will make it fully independent of the state of the kernel.
So what this PR implements is the right shape overall: positron-r dispatches that call to whatever backend is suitable (Ark LSP, Ark kernel, Oak LSP, ...). I'm just not sure we should do it from callMethod which is meant to execute code in the kernel.
The one potential advantage of callMethod is that it would keep input boundaries more private, and would not tie us to a particular interface. We have never used it anywhere yet so it's kind of experimental (in particular until we do #5272). So we could use it temporarily.
That said, I'd still expose the input boundaries more cleanly. A better model than callMethod for this feature is the provider-like interface of StatementRangeProvider in positron.d.ts. WDYT @jmcphers?
| } | ||
|
|
||
| callMethod(method: string, ...args: any[]): Thenable<any> { | ||
| async callMethod(method: string, ...args: any[]): Promise<any> { |
There was a problem hiding this comment.
Interesting, I've never had the thought that callMethod() could dispatch outside the kernel. It's not what it was made for (cf doc in positron.d.ts).
| if (method === 'inputBoundaries') { | ||
| // Quarto asks for R input boundaries through the LSP so it can split | ||
| // expressions without paying for a completeness check per line. | ||
| const text = typeof args[0] === 'string' ? args[0] : ''; |
There was a problem hiding this comment.
Probably should throw if malformed
| }); | ||
|
|
||
| describe('Output Handling', () => { | ||
| it('queries input boundaries once and keeps each R result', async () => { |
There was a problem hiding this comment.
It would be reassuring to have tests with incomplete and parse-error sections.
|
Thank you, I addressed these problems in I’m still new to this codebase, so I really appreciate the guidance and explanations. I updated the PR to follow the approach you suggested instead of using |
jmcphers
left a comment
There was a problem hiding this comment.
This approach looks much better!
A few more things to tweak:
- The new behavior wherein we split up the statements can be great for people who expect it, but others will expect it to work more like notebooks do. We should have an option to gate this behavior (default to on is okay).
- As written this is hardcoded to R. We should avoid language-specific paths in the Quarto execution manager. Instead, it should be gated on whether an input boundary provider exists for the language (see the statement range provider for examples). This will allow third party language packs to implement boundary splitting if they desire without us needing to add special casing here.
|
I updated the PR to address both points. Added Removed the R-specific branching from the Quarto execution manager. It now creates the boundary model using the cell language and only splits when an input boundary provider matches that language. If no provider matches or the boundaries are malformed, it falls back to whole-range execution. I also updated the R provider selector and added tests for disabled splitting, no matching provider, non-R provider splitting, malformed boundaries, and the existing R behavior. |
|
Teşekkürler, very much appreciate the contribution! I am going to move this to #14615 so our CI can run on it, follow updates there. |
|
You are welcome, I want to thank you too for your assistance throughout the way. I will track it from that PR. |
Supersedes #14185. ### Release Notes #### New Features - Show inline output of each individual R expression when running Quarto cells (#14185; thanks to @metehankaygsz) #### Bug Fixes - N/A Test tags: @:quarto @:console @:editor --------- Co-authored-by: Metehan Kaygısız <metehankaygsz@yahoo.com.tr>
|
This is all looking great and working well for me. I've merged #14615 into Positron so will close this PR. Thanks again! |
Summary
This makes separate outputs from an R chunk appear together below the chunk instead of showing only the final implicit result.
Related to #5272 and #13505.
Testing
npm run compile-check-ts-nativenpx vitest run src/vs/workbench/contrib/positronQuarto/test/browser/quartoExecutionManager.vitest.ts