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

LiveShare Functionality #626

Merged
merged 19 commits into from
Jun 11, 2021
Merged

LiveShare Functionality #626

merged 19 commits into from
Jun 11, 2021

Conversation

ElianHugh
Copy link
Collaborator

What problem did you solve?

Closes #555

General functionality

Vscode-R functions related to the session watcher currently do not function in LiveShare sessions. This means that the workspace viewer, dataview, plots, etc., do not work for guests.

This PR implements a 'LiveSession Listener', which allows for the sharing of file content and the forwarding of commands from a guest session to the host terminal. Thus, dataview, plots, browsers, and the workspace viewer should now function for guest sessions.

image

Settings & controls

This PR also contributes a liveshare control view, for tweaking guest access to the R workspace. This involves the following controls:

  • command forwarding
    • Whether the host allows guests to forward commands to the host terminal. E.g. workspace viewer view, remove
  • workspace sharing
    • Allows guests access to the R environment and related files
  • share ports
    • Automatically share & close browser ports with the guest

image

Default state can be controlled through three contributed settings.

Features

  • Attach terminal
  • Send commands to terminal
  • Plots (images)
  • Dataview: file
  • Dataview: table
  • Dataview: list
  • Browser
  • Webview: I didn't change much but it seems to work regardless? Might need someone else to check this one
  • Help Pages
  • Control menu/view

**I've intentionally left addin functionality out of this PR, as it is either a bigger undertaking or does not function with guest sessions at all. When initially adding guest access to addins, there was significant desyncing between host and guest sessions, so I have decided to leave it out. Further complicating the issue, there is no way (at the moment) of distinguishing between a guest addin call and a host addin call.

Extra things to note

  • Adds vsls as a dependency
  • The window has to be reloaded if liveshare is not enabled prior to starting an R session
  • Both the host and the guest have to be running vscode-R with this PR
  • the guest does not need R installed

How can I check this pull request?

  1. Have the LiveShare extension installed
  2. Have session watcher enabled
  3. Start an R LiveShare session, session watcher capabilities should be functional** for both host and guest

Implements session watcher features for LiveShare guests
@ElianHugh
Copy link
Collaborator Author

As an aside, I've tried to write this with minimal impact on vscode-R development in mind. For example, the readContent function in util.ts is a drop-in replacement for readFile, which delegates to the guest service when necessary.

Ideally, contributors shouldn't have to worry about making their feature work on LiveShare as well. If there's anything I can do on this PR to help with this, please let me know!

@gvelasq
Copy link
Contributor

gvelasq commented Apr 30, 2021

@ElianHugh, are there additional steps required to try this PR beyond those listed here? I have not tried out development VS Code extensions before. I installed npm and Node.js with Homebrew, and can confirm that I have the R and Live Share extensions installed, and session watcher enabled. But when I press F5 to load the extension cloned from your repo, then open a folder with R files, I get the following error:

Activating extension 'Ikuyadeu.r' failed: Cannot find module '~/vscode-R/dist/extension'
Require stack: - /Applications/Visual Studio Code.app/Contents/Resources/app/out/vs/loader.js - /Applications/Visual Studio Code.app/Contents/Resources/app/out/bootstrap-amd.js - /Applications/Visual Studio Code.app/Contents/Resources/app/out/bootstrap-fork.js.

@ElianHugh
Copy link
Collaborator Author

@ElianHugh, are there additional steps required to try this PR beyond those listed here? I have not tried out development VS Code extensions before. I installed npm and Node.js with Homebrew, and can confirm that I have the R and Live Share extensions installed, and session watcher enabled. But when I press F5 to load the extension cloned from your repo, then open a folder with R files, I get the following error:

Activating extension 'Ikuyadeu.r' failed: Cannot find module '~/vscode-R/dist/extension'
Require stack: - /Applications/Visual Studio Code.app/Contents/Resources/app/out/vs/loader.js - /Applications/Visual Studio Code.app/Contents/Resources/app/out/bootstrap-amd.js - /Applications/Visual Studio Code.app/Contents/Resources/app/out/bootstrap-fork.js.

Thanks for checking out the PR! The install instructions should be all that you need. Just to double check, did you run npm install in the extension folder, prior to pressing F5?

Also, depending on your local set-up, building the extension can hang. E.g. sometimes the npm terminal will ask if you want to use webpack, but not actually focus the terminal

package.json Outdated Show resolved Hide resolved
@gvelasq
Copy link
Contributor

gvelasq commented May 2, 2021

Thanks for checking out the PR! The install instructions should be all that you need. Just to double check, did you run npm install in the extension folder, prior to pressing F5?

Also, depending on your local set-up, building the extension can hang. E.g. sometimes the npm terminal will ask if you want to use webpack, but not actually focus the terminal

Thanks for the tip. You were correct, I had missed the npm install step. I was able to get it working, and it looks great! A few notes:

  1. Based on the description of the PR above I was not sure I fully understood how the 'Forward guest commands' menu item was supposed to work. I expected that enabling it as the host, without toggling anything in the Live Share extension, would allow any kind of guest (connecting from a desktop VS Code instance or a browser instance) to type in the R terminal and share commands (e.g., write to the shared R workspace). Instead, the shared R terminal behaved as other shared terminals do on Live Share even when 'Forward guest commands' was enabled for a guest connecting in the browser. When a guest connecting from a browser tries to write in the R terminal with this menu item enabled, they see the following:

Cannot edit a read-only terminal.
Source: Live Share (Extension)

The host needed to explicitly enable read/write permissions on the shared R terminal by going to Live Share > Session Details > Shared Terminals > R Interactive (Read-only) > Right-click > Make Read/Write.

I'm not sure that I know the best answer, but perhaps there can be an additional menu item in the R extension 'Live Share Controls' menu that detects and displays the status of the shared R terminal in the Live Share extension (not shared, read-only, read-write), and which ideally could be used to toggle sharing permissions for the R terminal directly from the R extension without needing to navigate to the Live Share extension? Or, perhaps this is just an issue for guests connecting from a browser and not for guests connecting from a desktop VS Code application with the R and Live Share extensions installed?

  1. This may be outside the scope of this PR, but the VS Code R extension cannot be installed when a guest connects via a browser, but the host is still able to share a Read/Write R terminal with guests connecting from a browser. The guest on a browser is able to interact with objects in the shared R workspace from the terminal, but they can't see the workspace itself without the R extension installed. Currently the error when trying to install the R extension from a guest browser is this:

The 'R' extension is not available in VS Code Web. Click 'More Information' to learn more.

Is it possible to make the R extension available to guests connecting from a browser? Guest browsers are a special use case for Live Share so perhaps this last point could become a separate issue so this PR could be merged first.

Many thanks again for the effort, this is a great contribution!

@ElianHugh
Copy link
Collaborator Author

ElianHugh commented May 4, 2021

  1. Based on the description of the PR above I was not sure I fully understood how the 'Forward guest commands' menu item was supposed to work. I expected that enabling it as the host, without toggling anything in the Live Share extension, would allow any kind of guest (connecting from a desktop VS Code instance or a browser instance) to type in the R terminal and share commands (e.g., write to the shared R workspace). Instead, the shared R terminal behaved as other shared terminals do on Live Share even when 'Forward guest commands' was enabled for a guest connecting in the browser.

The intent of the "forward guest commands" was to fix the issue of non-invasive vscode-R commands from failing due to a terminal being read only1. E.g. viewing a workspace viewer item would fail (something fairly innocuous). Toggling this allows the host to prevent or allow ALL users from using vscode-R commands (such as the workspace viewer commands). This is mainly handled this way due to the liveshare permissions API still being in development.

Having said that, I think what the "forward guest commands" button does could definitely be better communicated.

Is it possible to make the R extension available to guests connecting from a browser? Guest browsers are a special use case for Live Share so perhaps this last point could become a separate issue so this PR could be merged first.

Unfortunately I think you're on the money in terms of the difficulty in getting browsers to work with the R workspace.

One issue is that there are still certain functions that require a file to parse for them to work. For instance, the (default) plot viewer requires an image file2. The PR gets around this by getting the file content from the host, and then creating the file on the guest machine. The issue, then, is handling how the browser handles (and has access to) file systems vs. how an application handles file systems. It may be possible to handle this disparity, but I suspect this may prove to be difficult.

The other issue was to do with sharing terminals in browsers - last time I checked this was still in development, which meant I couldn't do much until it was finalized.

Thank you very much for the feedback!


  1. Originally, I had guest sessions search for a valid guest R terminal and then push commands to the found terminal. However, this introduced issues in not always finding the right terminal, especially when the guest first joins. Relying on the host terminals means that commands will function even if a guest terminal is still booting up, and moreover will always refer to the right terminal. The caveat, of course, is that we cannot rely on terminal permissions for the moment.
  2. There may be a way around creating files through virtual documents, but admittedly I don't fully understand how they work.

@gvelasq
Copy link
Contributor

gvelasq commented May 7, 2021

@ElianHugh, thanks very much for clarifying and again many thanks for the impressive effort!

Having said that, I think what the "forward guest commands" button does could definitely be better communicated.

I'll make a few suggestions for the display text and hover text for the menu item, but please feel free to disregard if you have better alternatives.

The other issue was to do with sharing terminals in browsers - last time I checked this was still in development, which meant I couldn't do much until it was finalized.

I just tested this again and it remains true that sharing terminals (e.g., zsh) in browsers is not supported as per this tweet. That said, if the host makes the R terminal read/write in the Live Share extension, it does work on a guest browser even though zsh does not! The R terminal is labeled as Local on the guest browser, and seems to bypass .radian_profile because on my host machine I have options(radian.insert_new_line = FALSE) but the guest browser R terminal inserts new lines between R prompts.

src/rShareTree.ts Outdated Show resolved Hide resolved
src/rShareTree.ts Outdated Show resolved Hide resolved
@gvelasq
Copy link
Contributor

gvelasq commented May 13, 2021

As an aside, I've tried to write this with minimal impact on vscode-R development in mind. For example, the readContent function in util.ts is a drop-in replacement for readFile, which delegates to the guest service when necessary.

Ideally, contributors shouldn't have to worry about making their feature work on LiveShare as well. If there's anything I can do on this PR to help with this, please let me know!

@renkun-ken, could you please review? It would be great to see this merged.

@renkun-ken
Copy link
Member

Thanks! I'll do more testing on this soon.

@renkun-ken
Copy link
Member

I didn't have experience using LiveShare before. I just play with this PR a bit, and it is astonishing. Everything seems to already work quite smoothly.

I'll take a closer look at the code and use it more thoroughly and see if I can find something to improve.

Thanks for the great work!

src/rShare.ts Outdated Show resolved Hide resolved
src/rShare.ts Outdated Show resolved Hide resolved
src/rShare.ts Outdated Show resolved Hide resolved
src/rShare.ts Outdated Show resolved Hide resolved
- isLiveShare now relies on liveSession instead of a new vsls.getApi() call
-- Many functions are now synchronous as a result
- Various tooltip changes to clarify 'forward guest commands'
- Clean up helper bool functions
@ElianHugh
Copy link
Collaborator Author

I just tested this again and it remains true that sharing terminals (e.g., zsh) in browsers is not supported as per this tweet. That said, if the host makes the R terminal read/write in the Live Share extension, it does work on a guest browser even though zsh does not! The R terminal is labeled as Local on the guest browser, and seems to bypass .radian_profile because on my host machine I have options(radian.insert_new_line = FALSE) but the guest browser R terminal inserts new lines between R prompts.

@gvelasq I've had a look at this codespace FAQ and it looks like the more significant issue is that vscode-R can't be installed in the browser, and therefore custom functionality such as this PR isn't available in the browser :(

From the link above:

Why is an extension not installable in the browser

There are a small number of extensions that have built-in assumptions or need to run on the desktop. Examples are when an extension accesses files from the VS Code installation on the desktop or when an extension depends on a executable that must run in a desktop environment. When you try to install such an extension in the browser, you will be informed that the extension is not available.

As per #641, liveshare files are moved to a /liveshare/ folder, and the "r" prefix has been removed from their name
@gvelasq
Copy link
Contributor

gvelasq commented May 26, 2021

@ElianHugh thanks for looking into the Codespaces FAQ. It's good to know that it's not possible to install the vscode-R extension for Live Share guests connecting via a browser. Since Live Share in vscode-R will require guests to connect via their own VS Code desktop instance, that suggests to me that ongoing efforts to facilitate installation and configuration for vscode-R will also help Live Share uptake for this extension.

Thanks to @renkun-ken and @ManuelHentschel for their technical reviews — what remains to be done before this PR can be merged?

@renkun-ken
Copy link
Member

renkun-ken commented May 26, 2021

Now the LiveShare does not hang at startup on macOS. But it looks like the guest session cannot attach to the active terminal. The terminal on host works well and is attached as usual.

image

@renkun-ken
Copy link
Member

renkun-ken commented May 26, 2021

I tested on Ubuntu and both host and guest session works well with attached session (e.g. View(mtcars)).

However, when the host is Ubuntu and the guest is macOS, the guest cannot attach to active terminal. When the host is macOS and the guest is Ubuntu, the guest cannot attach to active terminal either.

@ElianHugh
Copy link
Collaborator Author

I tested on Ubuntu and both host and guest session works well with attached session (e.g. View(mtcars)).

However, when the host is Ubuntu and the guest is macOS, the guest cannot attach to active terminal. When the host is macOS and the guest is Ubuntu, the guest cannot attach to active terminal either.

Very weird, but that does help narrow down the issue a bit. I looked at Ubuntu host to Windows guest and that seems to work well too. I'll have access to a mac shortly, so should be able to pinpoint what the issue is!

@ElianHugh
Copy link
Collaborator Author

Hi @renkun-ken, I tried this PR on a mac with a fresh install of vscode, and it seems to work okay for me. I did, however, have to enable session watcher prior to joining the session.

image

So, the source of the issue is likely to stem from the doesTermExist command:

export function doesTermExist(): boolean {
    const termNames = ['R', 'R Interactive'];
    for (const [i] of vscode.window.terminals.entries()) {
        const terminal = vscode.window.terminals[i];
        const terminalName = terminal.name;
        if (termNames.includes(terminalName)) {
            return true;
        }
    }
    return false;
}

Is it possible that the terminal doesn't have the names listed under const termNames? That would be the "easiest" answer to this problem I think

@renkun-ken
Copy link
Member

Thanks for pointing out the termNames. I always type r to start a radian in terminal (see https://github.com/Ikuyadeu/vscode-R/wiki/R-Session-watcher#advanced-usage-for-self-managed-r-sessions) but the automatically determined terminal name is python3).

I use R: Create R Terminal or manually start an radian and rename the terminal to a proper name R, then share the session, everything works well now on both Ubuntu and macOS.

I notice that if I don't have an active terminal before sharing the session and a guest joins, then starting an active terminal does not make the guest attach to the terminal. The only way to make it work is to attach to a session before a guest joins.

@renkun-ken
Copy link
Member

Do you think it is handy to support join before attach? If not, would you like to write more in the error message so that user knows what should be done?

@ElianHugh
Copy link
Collaborator Author

Do you think it is handy to support join before attach? If not, would you like to write more in the error message so that user knows what should be done?

Guest attach should definitely mirror host attach at all times (aside from when the workspace isn't shared). I'll have a commit to fix this soon

@ElianHugh
Copy link
Collaborator Author

Thanks for pointing out the termNames. I always type r to start a radian in terminal (see Ikuyadeu/vscode-R/wiki/R-Session-watcher#advanced-usage-for-self-managed-r-sessions) but the automatically determined terminal name is python3).

To get around the name issue, I can make use of !!pid on the host side. However, the issue is that the pid isn't removed once the terminal is disposed, so this method could be a bit clunky in some cases

@renkun-ken
Copy link
Member

To get around the name issue, I can make use of !!pid on the host side. However, the issue is that the pid isn't removed once the terminal is disposed, so this method could be a bit clunky in some cases

I wonder why we really need a check or filter here?

@ElianHugh
Copy link
Collaborator Author

To get around the name issue, I can make use of !!pid on the host side. However, the issue is that the pid isn't removed once the terminal is disposed, so this method could be a bit clunky in some cases

I wonder why we really need a check or filter here?

You're probably right - previously it was to prevent undefined objects crashing the guest session, but the upcoming changes don't really warrant it

@renkun-ken
Copy link
Member

I'm testing the latest build of this PR and it seems the guest can no longer attach to host session however I tried.

@ElianHugh
Copy link
Collaborator Author

ElianHugh commented Jun 10, 2021

I'm testing the latest build of this PR and it seems the guest can no longer attach to host session however I tried.

I wonder if this is due to the API timeout implemented previously? I've noticed the same too, but usually restarting the extension fixes it. It may be worth exposing the retry command to the guest session, or prompting the guest somehow

Reference pic for latest push:
image

@renkun-ken
Copy link
Member

Looks like it is indeed caused by the default timeout 3000. I adjust it to 5000 and it works now.

@renkun-ken
Copy link
Member

renkun-ken commented Jun 10, 2021

Let me test again on macOS and take a closer look at the behavior of vsls.getApi which could take forever as I mentioned.

@renkun-ken
Copy link
Member

I tested on macOS and I have to increase the timeout to 8000 to make it work.

Let me take a closer look into this.

@renkun-ken
Copy link
Member

Looks like vsls.getApi() does not hang any more (not sure why). I guess we could set the timeout to 10000 which is quite safe for most cases.

- Change timeout default: 3000 => 10000
- Remove leftover information message
- Fix accidental merge overwrite
@renkun-ken
Copy link
Member

renkun-ken commented Jun 11, 2021

I found a quirky behavior of guest httpd plot viewer. Make sure to put the following in the ~/.Rprofile to enable native httpgd plot viewer:

options(vsc.use_httpgd = TRUE)

In a live share session, start an R session and try the following code:

plot(rnorm(100))

which opens up an httpgd plot viewer tab. Then create a shinyApp:

shiny::runExample("01_hello")

A brower tab is shown. On both host and guest window, put these two viewers in the same editor view column. Moving the slide in the shiny app will always reveal the httpgd plot viewer on the guest side but not on the host side.

Kapture 2021-06-11 at 09 58 21

- notifyGuestPlotManager is now called less often, preventing it from taking focus unexpectedly
@ElianHugh
Copy link
Collaborator Author

A brower tab is shown. On both host and guest window, put these two viewers in the same editor view column. Moving the slide in the shiny app will always reveal the httpgd plot viewer on the guest side but not on the host side.

I could replicate this - looks like the notifyGuestPlotManager call was too eager in updating. I've moved this under the checkState method, and should now be fixed

@renkun-ken
Copy link
Member

Thanks @ElianHugh for the quick fix. It works well now.

R/vsc.R Outdated Show resolved Hide resolved
@renkun-ken
Copy link
Member

Once this PR is merged, I suggest that we add @ElianHugh as a collaborator since this is such a nice and important feature which needs good maintainence. @Ikuyadeu @andycraig @ManuelHentschel

- .UUID -> uuid
- Shorten commandNode label
Copy link
Member

@renkun-ken renkun-ken left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM Thanks for the nice work!

@renkun-ken
Copy link
Member

@gvelasq @ManuelHentschel Any more comments?

Copy link
Member

@ManuelHentschel ManuelHentschel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work, thanks!

src/plotViewer/index.ts Outdated Show resolved Hide resolved
src/plotViewer/index.ts Outdated Show resolved Hide resolved
src/liveshare/shareCommands.ts Outdated Show resolved Hide resolved
Comment on lines +3 to +4
[![Badge](https://aka.ms/vsls-badge)](https://aka.ms/vsls)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So far, we don't have any other badges (e.g. version, cicd, license, installs, rating...) in the readme. Personally I'd suggest we either agree on a sensible set of badges or just not have any badges at all.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense to me - I'll remove the badge for now

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Putting a single badge is perfectly ok to me, just like https://github.com/Microsoft/vscode-cpptools 😺

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this is just a matter of personal preference, so feel free to leave the badge in, if you agree on this :)

src/liveshare/share.ts Outdated Show resolved Hide resolved
- request() to liveShareRequest()
- onRequest() to liveShareOnRequest()
- use index design pattern
- remove global shareurl
- remove badge from README
Copy link
Member

@ManuelHentschel ManuelHentschel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM (Please remember to fix the linter warnings before merging)

@ElianHugh ElianHugh closed this Jun 11, 2021
@ElianHugh ElianHugh reopened this Jun 11, 2021
@ElianHugh
Copy link
Collaborator Author

Finger slipped on the GitHub app :)

Thank you for the kind words, and the in-depth reviews! I will fix up the linter issues shortly

- Appease the linter gods
@renkun-ken
Copy link
Member

Looks like this PR is good to merge now.

@renkun-ken renkun-ken merged commit e736b8e into REditorSupport:master Jun 11, 2021
@gvelasq
Copy link
Contributor

gvelasq commented Jun 11, 2021

Looks like this PR is good to merge now.

Thank you for all of your amazing work on this!

@Ikuyadeu
Copy link
Member

@ElianHugh
Great contribution!
Now, I send the collaborator invitation to you.
I'm happy if you have interested to join us.

As mentioned in # 98, the management of this repository will be moved from me within a year.
However, collaborators' access will remain the same.
I hope you will participate in the development for a long time.

@MilesMcBain
Copy link
Collaborator

Congratulations all this is looking incredible!!

@ElianHugh
Copy link
Collaborator Author

@ElianHugh
Great contribution!
Now, I send the collaborator invitation to you.
I'm happy if you have interested to join us.

As mentioned in # 98, the management of this repository will be moved from me within a year.
However, collaborators' access will remain the same.
I hope you will participate in the development for a long time.

Thank you for the kind words and the invitation! More than happy to help out :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implement shared R workspace in VS Live Share
6 participants