Skip to content

Add Copy action to hover popup to copy plaintext to clipboard#2885

Closed
kylebebak wants to merge 2 commits into
sublimelsp:mainfrom
kylebebak:main
Closed

Add Copy action to hover popup to copy plaintext to clipboard#2885
kylebebak wants to merge 2 commits into
sublimelsp:mainfrom
kylebebak:main

Conversation

@kylebebak

@kylebebak kylebebak commented Apr 27, 2026

Copy link
Copy Markdown

This PR adds a copy link/command/button to the hover popup, so users can copy the plaintext rendered by this popup to the clipboard

E.g. when hovering over the text in the screenshot and clicking copy, the following text is copied to the clipboard:

Screenshot 2026-04-27 at 2 06 52 PM
```pyright_python
(method) def on_pre_close(
    self: Self@Listener,
    view: View
) -> None
```

---
Called when a view is about to be closed. The view will still be in the window at this point.

Related issues

Implementation details

  • Append a Copy link after Rename in the hover actions row, wired to the existing LspCopyTextCommand
  • Add hover_plaintext() on LspHoverCommand to source plaintext directly from the LSP Hover.contents value, preserving spacing and line breaks without round-tripping through HTML
  • Add plaintext_from_lsp_content() to handle all three LSP content shapes (MarkedString, MarkupContent, list[MarkedString])
  • Add strip_single_code_fence() to drop the surrounding ``` when the hover is a single fenced code block

Kyle Bebak and others added 2 commits April 27, 2026 13:41
- Append a `Copy` link after `Rename` in the hover actions row, wired to the existing `LspCopyTextCommand`
- Add `hover_plaintext()` on `LspHoverCommand` to source plaintext directly from the LSP `Hover.contents` value, preserving spacing and line breaks without round-tripping through HTML
- Add `plaintext_from_lsp_content()` to handle all three LSP content shapes (`MarkedString`, `MarkupContent`, `list[MarkedString]`)
- Add `strip_single_code_fence()` to drop the surrounding ` ``` ` when the hover is a single fenced code block
@rchl

rchl commented Apr 29, 2026

Copy link
Copy Markdown
Member

This is pretty bad UX. A random copy button that copies some arbitrary block.

Also fragile regexp and parsing content is not really the way to go.

@rchl rchl closed this Apr 29, 2026
@kylebebak

Copy link
Copy Markdown
Author

A random copy button that copies some arbitrary block.

@rchl, it seems like you really didn't like this change. I don't know whether that's because you're opposed to the feature or the implementation. I'm guessing it's not the feature, given that you merged a PR with a similar feature here (copy buttons for diagnostics). So let's assume it's the implementation

What would make the UX better? Specifically, what would make the Copy button less "random"? A copy icon like the one added in the PR I just mentioned? Where would you want that icon?

Also, what would make the block less "arbitrary"? It's copying the full contents of the popup.

If you don't like SINGLE_CODE_FENCE_RE regexp and strip_single_code_fence function they can just be removed. Then you get output wrapped in a code fence with e.g. pyright_python syntax, which doesn't seem optimal to me, but for this feature it's not important

```pyright_python
(parameter) content: MarkupContent | MarkedStringWithLanguage
```

As for "parsing content", I assume you're referring to plaintext_from_lsp_content. I'd like to just copy the plaintext that goes into the popup before it's marked up, but I'm not sure where's the best place to do that. Extracting the plaintext from the marked up hover contents is easy enough, not fragile AFAICT, and means this PR doesn't have to touch any plumbing in this hover.py module

@jwortmann @rwols Is this typically how you guys respond to first-time contributors?

@jwortmann

Copy link
Copy Markdown
Member

I think copying the entire Markdown content (i.e. what you call "plaintext" here, but in practice it's almost always Markdown, because MarkedString is deprecated for a long time) from the hover request is not very useful. In my opinion it would be better to have such copy buttons only for the content of fenced code blocks.

Like here on GitHub:

copy-github

Or on our docs website:

copy-docs

But this is not so trivial to implement, because it would probably need to be done already in the mdpopups library, and then as an opt-in feature. And afaik the (mini-)HTML converter of mdpopups is also just a wrapper around another library for Markdown parsing. Also it might not be possible to render a floating button like that in minihtml, so it probably needs to put the copy button above or below of the fenced code block.

@rchl

rchl commented Apr 30, 2026

Copy link
Copy Markdown
Member

I would just suggest discussing solution before implementing to avoid cases like this.

It's just not a good UX and we knew already that there isn't really a good way of implementing it.

Also:

  • the actual implementation has failed to copy some popup contents during 1 min of testing for me.
  • the copy button is not visible if someone disables the bottom buttons
  • it's not clear what the copy button actually copies

@kylebebak

Copy link
Copy Markdown
Author

Thanks to both of you for responding

I think copying the entire Markdown content ... from the hover request is not very useful.

It's just not a good UX and we knew already that there isn't really a good way of implementing it.

It sounds like you guys have already thought about this in depth, and UX nits aside you would simply rather not implement this feature

In my opinion it would be better to have such copy buttons only for the content of fenced code blocks.

This would mean you can't copy e.g. the class or function docstring that appears below the code block. Copying the docstring is useful IMO

Also, I don't know whether it's possible to have multiple fenced code blocks in this hover panel. If it is, I don't think having e.g. multiple copy icons to the right of the code blocks, like the copy icons rendered for diagnostics, would be better UX than having a single Copy button/icon. In any case, based on @jwortmann 's comment, it's not really feasible to implement it that way

I think this feature is both simple enough and useful enough to warrant inclusion in the plugin, and that the UX in my implementation is neither beautiful nor ugly. With some minor tweaks maybe you'd like it more. It gets the job done. Thanks again for your feedback

@predragnikolic

Copy link
Copy Markdown
Member

Thanks for putting the effort into creating this PR.

Usually PR don't go this way.
But people usually open up an issue where we first discuss it, before someone implements it in a PR,
so we don't end up in a situation where someone put effort, but the PR ended up being closed because the person lacked previous context/feedback.

So ideally, Sublime would allow selecting text in the popup. (You can follow this issue sublimehq/sublime_text#1649) That would be the best user experience.

In the meantime, LSP had lots of discussion on how to implement the copy functionally in popups #2618 in a way that makes most sense. (Thus we limited the feature to only support the most common use case - copying diagnostic messages from the popup. Originally I did implement it to copy more sections in the popup, but due to ST API constraints and feedback, we decided to not do that - your PR is similar to something we already tried)

To sum up,
We kind of know what the limitations are,
But I hope the next step would be good ST to allow users to copy text from the popup.

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.

4 participants