Skip to content

Fix cheatsheet opening raw HTML in VSCode #875

Open
@pokey

Description

@pokey

The problem

For some people, our cheatsheet will open the raw HTML in an editor if they have that set as their default for HTML. The problem is that Python's webbrowser module doesn't handle file:// urls well; it basically calls open, which causes the OS to use the default app for opening HTML, rather than opening it in the user's default browser, as it does for http:// urls.

The solution

We need to roll our own default browser detector using 3 different routes, one for each of mac, linux and windows:

And then just fallback to using webbrowser.open if the detection method fails.

We could think about upstreaming this solution to Python's webbrowser module.

Alternative solution: local HTTP server

One possibility is to switch to using a local HTTP server.

The HTTP server code would look something like the following:

import http from "http";

const requestListener = function (req, res) {
    fs.readFile("~/.cursorless/cheatsheet/index.html")
        .then(contents => {
            res.setHeader("Content-Type", "text/html");
            res.writeHead(200);
            res.end(contents);
        })
};

const server = http.createServer(requestListener);
server.listen(0, "localhost");

We'd probably want to have a port file in ~/.cursorless/port that indicates which port the cheatsheet is being served on.

Note that we'd want to make sure that the various VSCode windows coordinate with one another so that we don't have each one running an HTTP server. We could do so as follows, in response to the user requesting a cheatsheet. First update the index.html. Then,

  • If focused window has a server running, just do nothing
  • Otherwise, check to see if there is already a port file
    • If no port file, spawn a server at a new port and create a port file
    • If there is a port file, make a HEAD request to the port, with a timeout. Note that we don't want to use the regular HTTP timeout, as that's just for connections; instead we should just use setTimeout and then cancel the request if it hasn't completed. Instead of a HEAD request, we could consider making a request for a particular path, and expect a specific response, just to make sure something else isn't running on that port
      • If request succeeds, update the index.html and continue
      • If it fails, spawn a server at a new port and update the port file

I don't think a server this simple should present a security risk, but maybe there's issues with the whole port file thing / the fact that something else might be running at that port?

This approach would also address #911, if we added VSCode port forwarding (via asExternalUri)

Some random links related to this approach, that may or may not be helpful 🤷:

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentationtalonRelated to cursorless-talon

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions