coder / code-server

VS Code in the browser
https://coder.com
MIT License
66.51k stars 5.45k forks source link

Support hyperlinks to local/project files with scheme like `vscode://` / `code-oss://` #6785

Closed belonesox closed 1 month ago

belonesox commented 2 months ago

What is your suggestion?

Is it possible to enable support for all of this, or are there policy or architectural solutions that will prevent this?

Why do you want this feature?

I wish to support "hyperlink browsing" for my project files (hyperlinks in comments, "includes" in documentation files, etc). Lot of extensions support tunable hyperlinking, like regex robin, but without support for schemes vscode:// / code-oss://, they are unusable in code-server.

Are there any workarounds to get this functionality today?

Unfortunately, no. :(

Are you interested in submitting a PR for this?

I've tried debugging, I see that the RelayURLService that provides all this in vscode is not loaded by dependencies in code-server, looks it is too complicated for a one-line patch. If there is no policy prohibiting it, and I get a hint on how to do it properly, I may try to implement and test.

code-asher commented 2 months ago

This is probably an issue with Codespaces/vscode.dev as well right? If so, might be worth sending a feature request upstream.

But also https://github.com/coder/code-server/issues/1571 seems related. In theory you could register a web+code-oss://handler, but I do not believe browsers will let you do code-oss://.

belonesox commented 2 months ago

This is probably an issue with Codespaces/vscode.dev as well right? If so, might be worth sending a feature request upstream.

What github project is upstream to code-server? I thought that this project is upstream to theme "VS Code in the browser".

But also #1571 seems related. In theory you could register a web+code-oss://handler, but I do not believe browsers will let you do code-oss://.

Scheme name not for browsers, but for LinkHandler in code-server, so I do not care, how the scheme would be named (vscode:// is better for compatibility with VSCode), if code-server will support clicking on links in text, and open files like in this demo (look how blue "!include" links open project files):

https://github.com/gpoore/codebraid-preview-vscode/assets/1609739/71dd448b-6705-42db-9311-2584c2efd927

code-asher commented 2 months ago

What github project is upstream to code-server? I thought that this project is upstream to theme "VS Code in the browser".

code-server consumes VS Code, so that makes VS Code upstream. At least, that is how I understand it.

code-server basically just wraps VS Code's own web server (the thing used in Codespaces), with a few patches and extra endpoints. All the core functionality is in https://github.com/microsoft/vscode.

support clicking on links in text, and open files like in this demo

Ah, I misunderstood what you were asking. The markdown preview runs in an iframe and all network requests are intercepted by a service worker, so it should be technically feasible to make vscode:// links work without needing to register any link handlers with the browser. But, I am not sure what exactly needs to be done.

This looks related: https://github.com/microsoft/vscode/issues/199009

Vigilans commented 2 months ago

Using this code snippet from https://github.com/microsoft/vscode-python-debugger/issues/136#issuecomment-1819272403, and replace vscode:// with code-oss://:

import os
import socket
import json

def _get_vscode_debug_launcher_url(port: int):
    launch_config = {
        "name": "Python: Remote Attach",
        "type": "python",
        "request": "attach",
        "connect": {"host": "localhost", "port": port},
        "pathMappings": [
            {"localRoot": "${workspaceFolder}", "remoteRoot": os.getcwd()}
        ],
        "justMyCode": False,
    }
    launch_config = json.dumps(launch_config)
    return f"code-oss://fabiospampinato.vscode-debug-launcher/launch?args={launch_config}"

def _handle_vscode_remote(vscode_ipc: str, port: int):
    # the VSCode Remote extension does not support `code --open-url {url}` with a `vscode://` extension
    # This may change in the future, but for now we need to bypass this limitation by using the VSCode IPC
    # secket to send the `vscode://` url to the VSCode instance server directly
    import requests

    from urllib3.connection import HTTPConnection
    from urllib3.connectionpool import HTTPConnectionPool
    from requests.adapters import HTTPAdapter

    class VSCodeIPCConnection(HTTPConnection):
        def __init__(self):
            super().__init__("localhost")

        def connect(self):
            self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
            self.sock.connect(vscode_ipc)

    class VSCodeIPCConnectionPool(HTTPConnectionPool):
        def __init__(self):
            super().__init__("localhost")

        def _new_conn(self):
            return VSCodeIPCConnection()

    class VSCodeIPCAdapter(HTTPAdapter):
        def get_connection(self, url, proxies=None):
            return VSCodeIPCConnectionPool()

    session = requests.Session()
    session.mount("code-oss://", VSCodeIPCAdapter())
    session.post(
        "code-oss://",
        headers={"content-type": "application/json", "accept": "application/json"},
        json={
            "type": "openExternal",
            "uris": [_get_vscode_debug_launcher_url(port)],
        },
    )

if __name__ == "__main__":
    import debugpy

    # Find an open port to listen on
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind(("localhost", 0))
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    port = s.getsockname()[1]
    s.close()

    debugpy.listen(port)

    # If we're in a local vscode terminal session, we need to tell VSCode to connect to the debug adapter
    # using fabiospampinato.vscode-debug-launcher extension
    if os.environ.get("TERM_PROGRAM") == "vscode":
        vscode_ipc = os.environ.get("VSCODE_IPC_HOOK_CLI")
        if vscode_ipc:
            # If VSCode is running in a remote SSH or container session, this gets pretty complex
            _handle_vscode_remote(vscode_ipc, port)
        else:
            # If VSCode is running locally (ie not using the Remote SSH or Remote Containers extensions),
            # this is pretty straightforward
            import subprocess

            subprocess.run(
                ["code", "--open-url", _get_vscode_debug_launcher_url(port)]
            )

    # If we're not in a VSCode terminal window, we will need to prompt the user to connect to the debug adapter
    # with their preferred editor's debugger
    print(f"Waiting for debugger to attach on port {port}...")
    debugpy.wait_for_client()

the code-server page seems handled this url and responds, but do not do anything meaningful: image

Any chance to look into it to make it work?

code-asher commented 1 month ago

Very interesting. Sending a code-oss:// link to the socket to launch an extension. I believe this will not help in the case of the readme preview, but it does seem like it has some interesting use cases.

But, I am not sure why it does not work the same as remote. Does it work in Codespaces?

belonesox commented 1 month ago

code-server consumes VS Code, so that makes VS Code upstream. At least, that is how I understand it.

On VS Code it works , code-oss:// or vscode:// depending on product.json depending on urlProtocol parameter in product.json file.

To see how it works, we can install for example https://github.com/dlevs/vscode-regex-robin and add to settings something like

"regexrobin.rules": [
    {
        "regex": "(include|include-entry) +([^\\n]+)",
        "tree": {
            "group": "include links"
        },
        "editor": [
            {
                "link": "vscode://file${fileDirname}/$2",
                "color": "#3639EF",
                "hoverMessage": "Open $2"
            }
        ]
    }
],

and all links like include in text editor of vscode will be hyperlinked and processed as vscode:// (like on screencast). For code-server here should work "link": "code-oss://file${fileDirname}/$2",, but it does not.

So there is no problem in upstream.

Ah, I misunderstood what you were asking. The markdown preview runs in an iframe and all network requests are intercepted by a service worker, so it should be technically feasible to make vscode:// links work without needing to register any link handlers with the browser.

I seem to have confused you with this screencast (part with markdown preview is irrelevant).

On initialization of VSCode it calls

image

image

image

So if we setup regex-robin like described above, it makes "include" strings in editor to code-oss links

image

and processed it right way

image

image

and finally open as file:

image

I've tried debugging, I see that the RelayURLService that provides all this processing in vscode is not loaded by dependencies in code-server.

Should I make reproduceable example project for code-server? May it help?

code-asher commented 1 month ago

On VS Code it works So there is no problem in upstream

Upstream has essentially two separate editors that share most of their code: a native version that runs in Electron, and a web version that runs in the browser with a Node backend. code-server bundles that web version. Microsoft uses that web version in Codespaces, which is why we ask folks to test there to see if it is an upstream issue.

Well, technically they have three versions; they have another web version without any backend (this is what vscode.dev is).

This RelayUrlService appears to be only available in the Electron version. Maybe because it relies on protocol handlers that cannot be registered from the browser. So it will have to be rewritten upstream to work in the browser.

https://github.com/microsoft/vscode/wiki/How-to-Contribute#code-server-web

belonesox commented 1 month ago

Upstream has essentially two separate editors that share most of their code: a native version that runs in Electron, and a web

Oww, sorry for bothering you , I was blind (I thought code-server upstream here, and vscode only for desktop). ¯\_(ツ)_/¯

I debug a little and see — my problem solved:

It is little inconvenient for settings consistency, but okay.

So here bug can be closed. Sorry again and thank you!

code-asher commented 1 month ago

All good, no worries!

Ahhhh vscode-remote works? That is really good to know. Nice find!