Skip to content

Conversation

@franknoirot
Copy link
Contributor

WIP towards #8880, built off of #9064 which was a proof-of-concept. This still has just a bit more polish to be done but I think I've proven that this is very doable. Most of the cleanup remaining comes from needing to translate our overwrought scaffolding around CodeMirror and the EditorState into neater little effects. I think by the end of this the execution loop might be a bare CodeMirror plugin, which I am fucking thrilled about.

@vercel
Copy link

vercel bot commented Dec 5, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
modeling-app Ready Ready Preview, Comment Dec 17, 2025 2:35am

Comment on lines +1005 to +1151
// setEditorView(editorView: EditorView) {
// this.overrideTreeHighlighterUpdateForPerformanceTracking()
// }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ohh I just saw this! There is an issue I've created recently: #9184

Basically we called overrideTreeHighlighterUpdateForPerformanceTracking each time an edit was made wrapping the update function multiple times.
A simple fix is to keep track of the plugins already patched, or only call this once at init time (or if plugins change).

My fix would very likely conflict with this PR so I will postpone fixing it. Let me know if you prefer to fix it in your PR, or otherwise I will wait for this to merge and fix afterwards.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yeah I wanted to put a pin in that while I worked out the other unknowns in this PR, but I think I can bring this back or solve what it's trying to do much more simply now that we won't re-render all over the place and obliterate the EditorView.

Copy link
Contributor Author

@franknoirot franknoirot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm really excited for this one.

import type { Node } from '@rust/kcl-lib/bindings/Node'

import { CustomIcon } from '@src/components/CustomIcon'
import { useCodeMirror } from '@src/components/layout/areas/CodeEditor'
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All the diff in this PR is to get rid of this import so I could delete that file. What I've got is the start of a "microEditor" CodeMirror setup defined below, which we can package up and use as our common KCL input in a follow-up PR. Most of the annoyance here is now just that the component still re-renders like mad because off all my careless useMemos and so on, but that's how it actually is in prod.

Comment on lines +47 to +49
const editorParent = useRef<HTMLDivElement>(null)
useEffect(() => {
return () => {
kclEditorActor.send({ type: 'setKclEditorMounted', data: false })
kclEditorActor.send({ type: 'setLastSelectionEvent', data: undefined })
kclManager.diagnostics = []
}
editorParent.current?.appendChild(kclManager.editorView.dom)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BYE REACT DON'T NEED YA

Comment on lines +168 to +171
// New code to just update the CodeMirror extensions directly.
kclManager.editorView.dispatch({
effects: kclLspCompartment.reconfigure(Prec.highest(lsp)),
})
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left basically everything the same with the LspProvider but it can go soon. I'm pretty confident we can make it instantiate when a project is opened just from KclManager and never touch React, especially once we get a proper openProject method in there and store the opened project and executing file; those are the only things that the useEffects in this component are here for.

} from '@kittycad/codemirror-lsp-client'
import { reportRejection } from '@src/lib/trap'
import { deferExecution } from '@src/lib/utils'
import { deferredCallback } from '@src/lib/utils'
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure it's kinda noisy, but when I saw deferExecution I thought for sure this was some kind of engine execution wrapper, and it's really just a nice little deferring utility (perhaps with overlapping usefulness with our debounce function but that's for another day)


/** A view plugin that requests completions from the server after a delay */
export class KclPlugin implements PluginValue {
private viewUpdate: ViewUpdate | null = null
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class would hold onto viewUpdate, a very risky thing to hold onto since they're so ephemeral.

Comment on lines 1469 to 1566
set code(code: string) {
this.editorView.dispatch({
changes: {
from: 0,
to: this.editorView.state.doc.length,
insert: code,
},
})
this._code.value = code
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now setting the code value will dispatch, instead of bounce around.

Comment on lines -1436 to +1618
.writeFile(this._currentFilePath, this.code ?? '')
.writeFile(this._currentFilePath, newCode)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as with executeCode above, this.code is a bad pattern and not guaranteed to be up-to-date. Now we pass in new code from the ViewUpdate listener extension, which is.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved to @src/editor/plugins/theme/index.ts

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that I'm comfortable working with CodeMirror I loathe the boilerplate and type runaround of how I've used XState here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BYE REACT BYE

@franknoirot franknoirot force-pushed the franknoirot/8880/kill-react-codemirror branch from b6dc567 to f7fe680 Compare December 5, 2025 16:19
franknoirot added a commit that referenced this pull request Dec 8, 2025
Baby step towards #8885 broken out from a larger effort in #9190. Just
meant to start categorizing and commenting on the many class properties
in this class, as we step towards consolidating them.
franknoirot added a commit that referenced this pull request Dec 8, 2025
Towards #8885, stacked on #9236. Adding a for-now unused CodeMirror
extension that registers the AST as a StateField on the EditorView.
Right now we trash the EditorView constantly so that value will not be
trustworthy, but it will be once we remove all our React scaffolding
around CodeMirror, which is a work-in-progress in #9190. Then this will
be available to become the canonical derived AST state, automatically
updated whenever the code is updated by the user.
franknoirot added a commit that referenced this pull request Dec 8, 2025
Towards #8885, stacked on #9236. Adding a for-now unused CodeMirror
extension that registers the AST as a StateField on the EditorView.
Right now we trash the EditorView constantly so that value will not be
trustworthy, but it will be once we remove all our React scaffolding
around CodeMirror, which is a work-in-progress in #9190. Then this will
be available to become the canonical derived AST state, automatically
updated whenever the code is updated by the user.
franknoirot added a commit that referenced this pull request Dec 9, 2025
Towards #8885, stacked on #9236. Adding a for-now unused CodeMirror
extension that registers the AST as a StateField on the EditorView.
Right now we trash the EditorView constantly so that value will not be
trustworthy, but it will be once we remove all our React scaffolding
around CodeMirror, which is a work-in-progress in #9190. Then this will
be available to become the canonical derived AST state, automatically
updated whenever the code is updated by the user.
@franknoirot
Copy link
Contributor Author

franknoirot commented Dec 9, 2025

Taking just a bit of a detour here so that I can break out some refactor PRs and PRs that add CodeMirror extensions for other derived state. I'll return to this after a few of the PRs I've broken out from it land.

@franknoirot franknoirot force-pushed the franknoirot/8880/kill-react-codemirror branch from 423fe17 to d1d4b0f Compare December 9, 2025 21:54
franknoirot added a commit that referenced this pull request Dec 10, 2025
Towards #8885, broken out from #9190. Refactors the KCL LSP extension to
not store any EditorView or other state. In addition, splits out
concerns of highlighting engine-side entities and executing code. Users
should experience no degradations from this refactor, although it is
possible that this fixes some niche case bugs.
franknoirot added a commit that referenced this pull request Dec 10, 2025
* Organize class properties on KclManager

Baby step towards #8885 broken out from a larger effort in #9190. Just
meant to start categorizing and commenting on the many class properties
in this class, as we step towards consolidating them.

* Update snapshots

* Update snapshots

* Revert AST setter

This contained material changes that break the app currently, relying on
other future changes.

* Update snapshots

* Update snapshots

* Update snapshots

* Revert changes to `code` setter

These rely on other changes to come to work properly.

* Update snapshots

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
@franknoirot franknoirot force-pushed the franknoirot/8880/kill-react-codemirror branch from ab7d796 to df5305e Compare December 10, 2025 16:11
@franknoirot franknoirot force-pushed the franknoirot/8880/kill-react-codemirror branch from ebcd92b to d8b7e66 Compare December 16, 2025 20:38
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.

3 participants