-
Notifications
You must be signed in to change notification settings - Fork 203
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
Feat: Add Prettier Support to TypeScript Notebook #231
Conversation
Should this be debounced auto or a manual format button & key bind to avoid changing the lines around as someone works if they pause between typing? |
Could this be done on the server to avoid making the client bundle even heavier and avoid the need to send the entire formatted file down to the server, change the fs, and then sync back with the client |
It’s true, but the lengthy process isn’t ideal for near real-time auto-formatting, and the sync model is currently not supported. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for this!
TLDR: implementation looks great but I'm not sure this is the UX we want.
- I think having code shift out from under me after a slight pause in typing is not ideal. In my editor it formats only on save which is an explicit action I take. In Srcbook, we don't explicitly save, so that won't work here. However, I think we can apply the same principle and use a keyboard shortcut and/or icon as the explicit action for formatting. This way I opt-in to each format which I feel pretty strongly about.
- If we use a keyboard shortcut and/or icon, then we don't need the database entry for auto format.
- I'm torn on the client-side vs server-side formatting functionality. I would prefer it to take place inside the folder we create for the Srcbook (similar to how we handle tsconfig and type checking). That is, I would expect that repository to have prettier installed in its deps and the prettier config to be located in that folder as well. In theory, this makes ejecting a srcbook folder a breeze, which is something I think we'll eventually want to do. BUT, if the user presses the format icon and there's a delay I agree that's a poor experience. I wonder if it's fast enough there's no real delay?
- It's ok if we do it in a follow up PR, but the prettier settings should be editable by the user, the same as package.json or tsconfig.json.
Excellent work on implementation here but I think we should change the UX
onClick={onFormatCode} | ||
tabIndex={1} | ||
> | ||
<CodeXml size={16} /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couple notes on this:
- I wonder if there's a common icon for code formatting? This icon is ambiguous and could be used to indicate many different things in a product like ours. Maybe braces, but that doesn't feel much different?
- This icon feels a bit odd with the current debounce UX. You have < 2 seconds after typing anything before pressing this icon will have no affect. That said, it is useful if you import a srcbook that isn't formatted according to your settings and want to format the cell without typing in it first.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -643,6 +680,27 @@ function CodeEditor({ | |||
|
|||
const updateCellOnServerDebounced = useDebouncedCallback(updateCellOnServer, DEBOUNCE_DELAY); | |||
|
|||
const formatCellCode = async (source: string, viewUpdate: ViewUpdate) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: There's no await
inside this function so we don't need the async
keyword in this case. Alternatively can change to using await and ditch the promise callbacks.
@swk777 @benjreinhart On the server driven delay the back and forth with the WS in local is ~50ms (hardware dependent) under the current system including validation with zod, so it should not create any sort of noticeable delay to a user, this may be different for a hosted instance but even a 500ms delay if you play a little animation isn't an issue since the format is something you do maybe once or twice when working on a cell. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the contrib @swk777
I apologize, I think the ticket should have been more specific on what we wanted, but I agree with Ben's review. I think a better behavior is to implement the formatting on the backend side, with the ability to trigger it from the frontend. So:
- on each cell, you can click a button in the action bar (
PaintbrushVertical
) which formats it by calling a websocket eventCellUpdateFormatCell
and updating the cell.source. - [Stretch 1] Auto-format on export: if auto-format is enabled, we format all saves on export only. Otherwise as @benjreinhart says, things change while you're typing and that's a very jarring experience.
- [Stretch 2]: add a global keyboard shortcut to format all cells (and/or format current active cell).
onClick={onFormatCode} | ||
tabIndex={1} | ||
> | ||
<CodeXml size={16} /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the detailed feedback
Does this approach sound good to you? @benjreinhart @nichochar |
24d57ac
to
8190fba
Compare
@swk777 When you're finishing this up can you merge main back in and run |
ddb6a94
to
5298c9c
Compare
@swk777 please merge main in and get tests and format checks passing |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code side all looks good just the note on making errors on format runs include more information on the front end.
It’s true, I’ve now routed the output to stderr. The error does overlap somewhat with the ones in the problems panel, but it currently depends on the TypeScript package installation. Once #210 is completed, I can work on further optimizations. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking really good, excited for this. Couple last minute items but it's almost good to go. Thank you!
keymap.of([ | ||
{ key: 'Mod-Enter', run: evaluateModEnter }, | ||
{ | ||
key: 'Mod-Shift-f', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we use Shift+Option+F for this (this is what vscode uses)? I'm a bit worried about cmd+f and shift+cmd+f because those are universally used for searching a file or searching a project, which we'll probably want at some point.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This just got me thinking should we add srcbook keymap support as a JSON and with the default, vscode, jetbrains, vim keymaps vim may be hard for nav but at least for basic actions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That would be cool but I would say that's out of scope for this PR (not that you're proposing doing it here)
@@ -296,7 +298,69 @@ export function updateCell(session: SessionType, cell: CellType, updates: CellUp | |||
return updateCodeCell(session, cell, updates); | |||
} | |||
} | |||
|
|||
async function ensurePrettierInstalled(dir: string): Promise<boolean> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some thoughts here:
- If formatting is going to be a first class citizen in all Srcbooks, then we should create every new srcbook with it already present in the package.json's
devDependencies
- If we do check for its presence here, are we able to use
depcheck
? We already use this indeps.ts
and it looks like it has "special" support for prettier. - If the dep is missing, I'm inclined to prompt the user for installing it. While this does introduce an extra manual step, it keeps the user in the loop and gives faster feedback than if they waited for install to happen behind the scenes. This should rarely happen if we include prettier in the dependencies when creating new srcbooks, so I think that's acceptable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I stand behind number 3 above but in the interest of getting this out sooner than later, we can ignore that piece for now and leave this code (though would be good to use depcheck).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ohh I just noticed we are doing 1) here already, nice
try { | ||
npmInstall({ | ||
cwd: dir, | ||
packages: ['prettier'], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should install this in the devDependencies
You're going to want to rebase main as well given the navigation updates (#267). |
all done, thx |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You'll need to rebase though as #270 touched all the dependency files.
@@ -0,0 +1,7 @@ | |||
--- | |||
'@srcbook/shared': minor |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also just noticed this is minor
, but for now I would like to keep all the versions on patch
. Do you mind regenerating this changeset such that these are all patch
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you don't need to regen just change the text to patch and it'll work
This is awesome, appreciate all your work here! 🙏🏻 |
Amazing, thanks for the great contribution, really like having it in there, it feels great. After using it a couple of times, I think we'll want to add some indication that it's running (like AI has a purple ring, and running a process has a yellow ring), but we'll ask design for this. Thanks @swk777 🚀 👊 |
implement #209
Minor Details
• Upgraded Radix UI to include the brush icon
• Moved Prettier configuration to package.json since having a standalone configuration doesn’t seem crucial at this point.
• Set Command+Shift+F as the shortcut for formatting.