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

Is it possible to hide the constrained part completely? #17

Closed
addlistener opened this issue Sep 9, 2022 · 5 comments
Closed

Is it possible to hide the constrained part completely? #17

addlistener opened this issue Sep 9, 2022 · 5 comments
Labels
wontfix This will not be worked on

Comments

@addlistener
Copy link

addlistener commented Sep 9, 2022

Use case: providing some extra handmade function for the tutorial. At the same time I also want the auto completion.

Let's say

def uploadToServer(text):
    # some pretty complex function here I'd like to hide

# The visible part
result = computation by the user
uploadToServer(result)
  1. I would use addExtraLib if possible. But it seems it's only available for js/ts and it seems hard to implement for other languages (maybe it depends on the native capability of typescript names are global by default?).
  2. And I also tried provideCompletionItems etc. But it will break the language protocol server linting & completion.
  3. In the end I guess hiding is the best option?
@Pranomvignesh
Copy link
Owner

Pranomvignesh commented Sep 10, 2022

Hi @jchnxu,

I will suggest you to go with addExtraLib API, and if it is not available for python ( or language which you are using ), you have to open an issue in monaco-editor

Constrained Editor doesn't modify the text model or completions part of the monaco editor, it just undos the changes done in the constrained areas based on the previously provided ranges.

Hiding a block of code and then using that for autocompletion requires changes in the text model of the monaco editor. Moreover it messes with the line numbers of the code which is the base variable that Constrained editor uses for its manipulation

You can also refer : microsoft/monaco-editor#45

@Pranomvignesh Pranomvignesh added the wontfix This will not be worked on label Sep 10, 2022
@addlistener
Copy link
Author

addlistener commented Sep 11, 2022

Thanks @Pranomvignesh ! I think I nailed it. I did it by adding middleware to the lsp server.

Moreover it messes with the line numbers of the code

This is also a problem easy to solve within 20 lines of code. Pretty happy when I thought about it.

And thank you again for your excellent work. You should know that your repo helped a lot of people. I read a lot these days on posts of people needing it.

@Pranomvignesh
Copy link
Owner

Thanks @jchnxu

@oceangravity
Copy link

oceangravity commented Jan 22, 2024

Thanks @Pranomvignesh ! I think I nailed it. I did it by adding middleware to the lsp server.

Moreover it messes with the line numbers of the code

This is also a problem easy to solve within 20 lines of code. Pretty happy when I thought about it.

And thank you again for your excellent work. You should know that your repo helped a lot of people. I read a lot these days on posts of people needing it.

Hi @addlistener, I have the same issue, can you share your solution to hide the restricted areas, please? 😥

@addlistener
Copy link
Author

@oceangravity There's a lot of code. The main idea is to hack the line numbers when "textDocument/didChange" and ""textDocument/didOpen".

It's just a demo code, not really battle tested.

import * as server from "@codingame/monaco-jsonrpc/lib/server";
...

function launch(socket) {
  const reader = new rpc.WebSocketMessageReader(socket);
  const writer = new rpc.WebSocketMessageWriter(socket);
  console.log("Starting lsp");
  const socketConnection = server.createConnection(reader, writer, () =>
    socket.dispose()
  );
  const serverConnection = server.createServerProcess(
    "lsp",
    pyRunBin,
    [
      "start_pylsp.py",
      // '-vv', // debug log for pylsp
    ],
    {
      cwd: pyRunRoot,
    }
  );
  server.forward(socketConnection, serverConnection, transformMessageForPython);
}


const transformMessageForPython = (message) => {
  // console.log(message.id, message.method, message.isReq, message.isRes);
  // return message;

  traverse(message.params, offsetLineNo(isReq(message)));
  traverse(message.result, offsetLineNo(isReq(message))); // response messages have "result" instead of "params"

  if (message.method === "textDocument/didChange") {
    // console.log("did change", JSON.stringify(message.params, " ", 2));

    // TODO
    const newLastLine =
      getVariableLastLine(message.params.variableList || [], {
        useTypeHint: true,
      }) + "  # NOQA";

    // console.log(
    //   "oldLastLine",
    //   modelLastLine[message.params.textDocument.uri]
    // );
    // console.log("message.params", JSON.stringify(message.params));
    message.params = {
      ...message.params,
      contentChanges: [
        {
          range: {
            start: { line: lastLineIdx, character: 0 },
            // "end" is exclusive
            // and we leave the '\n' not touched in this replacement
            // https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#range
            end: {
              line: lastLineIdx,
              character: modelLastLine[message.params.textDocument.uri].length,
            },
          },
          text: newLastLine,
        },
        ...message.params.contentChanges,
      ],
    };
    // console.log("message.params new", JSON.stringify(message.params));

    modelLastLine[message.params.textDocument.uri] = newLastLine;

    // console.log("updated:", modelLastLine[message.params.textDocument.uri]);
  }

  if (message.method === "textDocument/didOpen") {
    const newLastLine =
      getVariableLastLine(message.params.variableList || [], {
        useTypeHint: true,
      }) + "  # NOQA";
    modelLastLine[message.params.textDocument.uri] = newLastLine;

    message.params.textDocument.text =
      replaceLastLine(prefix, newLastLine) +
      (message.params.textDocument.text || "");

    // console.log("updated:", modelLastLine[message.params.textDocument.uri]);
  }

  if (rpc.isRequestMessage(message)) {
    if (message.method === lsp.InitializeRequest.type.method) {
      const initializeParams = message.params;

      // to quit when parent process quit https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#initializeParams
      initializeParams.processId = process.pid;
    }
    // console.log("mid request", message);
  } else if (rpc.isResponseMessage(message)) {
    // console.log("mid response", message);

    // trigger sugguestions for myDict["key"] / myDict.get("key")
    if (message.result?.capabilities?.completionProvider?.triggerCharacters) {
      message.result.capabilities.completionProvider.triggerCharacters = dedupe(
        [
          ...message.result.capabilities.completionProvider.triggerCharacters,
          // // TODO need to support unicode? https://www.asmeurer.com/python-unicode-variable-names/
          // ..."abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_".split(
          //   ""
          // ),
          "[",
          "(",
          "'",
          '"',
        ]
      );
    }
  } else if (rpc.isNotificationMessage(message)) {
    // console.log("mid notification", message);

    // filter out diagnostics in our code
    if (
      message.method === "textDocument/publishDiagnostics" &&
      message.params?.diagnostics?.length
    ) {
      message.params.diagnostics = message.params.diagnostics.filter((d) => {
        return (d.range?.start?.line ?? -1) >= 0;
      });
    }
  } else {
    // console.log("mid other", message);
  }

  return message;
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
wontfix This will not be worked on
Projects
None yet
Development

No branches or pull requests

3 participants