codemirror blob: Integrate with Sourcegraph extensions
Created by: fkling
Note: This is a big PR, I don't expect a detailed review, but please ask if something is unclear. Disclaimer: I'm using CodeMirror to the best of my abilities. I still don't quite know when using a field would be better than a facet for example. So a lot of how the extensions are setup/configured is still in flux.
This commit introduces a way to interface with Sourcegraph extensions so that we can support hovercards and document highlights. I believe all extension points are supported:
- Hovers (albeit incomplete; will complete in another PR)
- Document highlights
- Text decorations (including column view)
- Status bar
- Selection updates
This is big PR so let me provide a high level overview:
codemirror/sourcegraph-extensions.ts
contains the extensions that communicate directly with the Sourcegraph extensions API.
Where possible (and reasonable) I separated CodeMirror specific logic into separate modules and let the Sourcegraph extensions integrations interface with those via facets. In same cases it didn't make sense to introduce additional extension points and the Sourcegraph extensions integrations directly listen to CodeMirror events.
codemirror/decorations.ts
implements the logic to convert TextDocumentDecoration
s into CodeMirror decorations. Inputs are provided via a facet, which is used for the Sourcegraph extensions integration as well as the git blame data coming from BlobPage
(under the new core workflow integration). Note that decorations are only created/rendered for the lines that are currently visible.
codemirror/document-highlights.ts
contains CodeMirror extensions that
- listen to, debounce and filer CodeMirror events to determine the current mouse position
- query one or more data sources for document highlights data
- convert document highlights to CodeMirror extensions
Currently the only data source is provided by the Sourcegraph extensions integration.
codemirror/hovercard.ts
contains logic to render hovercard data as CodeMirror hover tooltips.
The hovercards implementation isn't complete yet, I will finish this in a future PR.
codemirror/index.ts
contains logic that I didn't know where else to put.
codemirror/utils.ts
contains, as the name implies, a couple of helper
functions used by various extensions.
Also note that I switched from using EditorView.editable
to EditorState.readOnly
. This allows us to focus the editor and have a proper selection. That selection is sent to the extensions host when it changes. This is currently not synced with selected lines and I don't know what exactly we want to do in that area.
Note: The current blob view contains a lot of logic to clean up decorations and other state when switching documents. We avoid that with CodeMirror by completely resetting the editor's state when loading a new document so we get most of the cleanup for free.
I also made some changes to existing components to avoid code duplication or to fix things:
-
Blob.tsx
: Exported the function to group text decorations -
CodeMirrorQueryInput.tsx
,input/extensions/index.tsx
: Moved thecreateUpdatableField
helper function toCodeMirrorEditor.ts
to make it sharable. -
ColumnDecorator.tsx
: Extracted inner component. -
LineDecorator.tsx
: Extracted inner component. -
BlobStatusBarContainer.module.scss
needed to removeisolate
otherwise hovercards would be rendered underneath the extensions sidebar.isolate
doesn't seem necessary here but I don't know for sure.
Note on React integration
I'm currently creating a new root via createRoot
and it seems to work but I feel like it's not optimal. (you might notice in the video that the line decorations seem to be rendered one after each other).
https://user-images.githubusercontent.com/179026/181710762-f85830c3-b557-4c3b-b2a3-267d62d04dfc.mp4
Test plan
- Enable CodeMirror with
enableCodeMirrorFileView
- Enable extensions (e.g. git extras and codecov)
- Navigate to a file, text decorations (if any) are rendered at the end of the line
- With git-extras, enable
enableExtensionsDecorationsColumnView
and see blame data being rendered in a column. - With git-extras, enable
extensionsAsCoreFeatures
and see blame data being rendered in a column (might want to disableenableExtensionsDecorationsColumnView
to see that it really works). - Toggle light/dark theme, decorations should update accordingly
- Hover over tokens, hovecards and document highlights should appear
App preview:
Check out the client app preview documentation to learn more.