hydra-synth / hydra

Livecoding networked visuals in the browser
https://hydra.ojack.xyz
GNU Affero General Public License v3.0
2.12k stars 255 forks source link

Add IntelliSense support #109

Open arnoson opened 3 years ago

arnoson commented 3 years ago

First of all: thank you so much for this awesome live coding editor! Has been a lot of fun to use.

The only thing that I'm missing would be IntelliSense support, so I don't have to jump between the editor and the docs all the time. I researched a bit and although it should be possible to add this to CodeMirror, Monaco Editor has this all build in, even allowing to specify the types with JSDocs.

ojack commented 2 years ago

Just wanted to loopback here -- would love to add this also. I am not sure what the best way to go about adding this is, but will research and comment here.

brucelane commented 2 years ago

I did some code for that

arnoson commented 2 years ago

Great to hear that you are interested in this feature @ojack! I guess switching from CodeMirror to Monaco and using a similar setup like this (https://microsoft.github.io/monaco-editor/playground.html#extending-language-services-configure-javascript-defaults) would be the easiest way. At the same time Monaco provides realtime linting with error/helper tooltips, so this would make hydra really beginner friendly.

@brucelane can you share your code?

ojack commented 2 years ago

There is also some autocomplete in CodeMirror: https://codemirror.net/6/examples/autocompletion/

I tried implementing at one point but didn't get very far.

arnoson commented 2 years ago

The CodeMirror example looks like a lot of manual setup, whereas Monaco works with a d.ts file (or string) out of the box. Creating the autocompletions for the hydra API with a d.ts file would flexible and easy to maintain.

Here is a quick example: https://codepen.io/arnoson/pen/JjrZNZV?editors=0110 I implemented autocompletion for osc and rotate with this type definition:

declare interface HydraContext {
  time: number
  // ...
}

declare type HydraArg = number | (ctx: HydraContext): number

// Global functions
declare function osc(frequency?: HydraArg, sync?: HydraArg, offset?: HydraArg): Hydra
// ...

// The chainable hydra object
declare interface Hydra {
  osc: typeof osc
  rotate(angle?: HydraArg, speed?: HydraArg): Hydra
  // ...
}

Another advantage of using type definitions ist that they can also be shipped with npm so even when using hydra-synth standalone we would get full autocompletion support in vscode or atom.

ojack commented 2 years ago

Oooh cool! so I guess it would be possible to auto-generate the types file from within hydra-synth using the function definition file: https://github.com/ojack/hydra-synth/blob/main/src/glsl/glsl-functions.js , and then load that from within the hydra web editor.

I am open to switching to monaco editor, but have a list of things to check when comparing to CodeMirror:

  1. which has a smaller bundle size?
  2. works on mobile?
  3. is it possible to streamline/completely customize the information contained in the autocomplete overlay?

In case it is useful, here is code for generating a list of all functions with their parameters and default values (as used at https://ojack.xyz/hydra-functions/):

const hydraFunctions = require('hydra-synth/src/glsl/glsl-functions')

const methods = hydraFunctions.map((obj) => `${obj.name}( ${obj.inputs.map((input) => `${input.name}${input.default ? `: ${input.default}`: ''}`).join(', ')} )`)
ojack commented 2 years ago

Gathering examples -- here is a screenshot of code completion in Gibber https://gibber.cc/alpha/playground/ (i think using codemirror), which has some really nice features such as the color-coded type system.

Screenshot 2022-01-05 at 16 00 05

arnoson commented 2 years ago

Didn't know about the autogeneration for hydra-functions! Should be possible to autogenerate the type definitions, I can take a look at it if I find some time.

I like the gibber overlays and agree that it would be great to customize them in a way similar to this!

Regarding your questions:

  1. Monaco is quite big although it can be made a bit lighter if you use it with weback and only select the features you really want. But still this would be a few hundred kb. I guess for a good code editor it is worth it but maybe problematic on mobile.
  2. The documentation states that it doesn't work on mobile. I just did a quick test and the official examples worked on firefox on android. But I read that touch isn't really good.
  3. The overlayers all have css classes so it should be possible but it might be a hack und difficult to completely customize the content.

So yeah, considering these points there are quite a lot of downsides. A solution for 1 and 2 would be to use CodeMirror on mobile and Monaco on desktop and lazyload them. I guess most users will use desktop for more advanced coding so this would be still worth it.

In the end it may depend on how easy or difficult it is to get autocompletion to work with CodeMirror and if this extra work is worth it compared to monaco.

ojack commented 2 years ago

Thank you for researching this so quickly! I can see the benefit of both editors in different contexts, although generally like to keep things light weight. I would also like to eventually publish the editor component as its own module, similar to https://github.com/patriciogonzalezvivo/glslEditor , so in either case it could be easier to switch out. For the time being I think next steps are:

  1. Add types to hydra-synth auto-generated from glsl-functions.js file
  2. Restructure this repo a bit so the editor is its own module https://github.com/ojack/hydra/issues/153
  3. Continue researching / trying out autocomplete in CodeMirror and monaco
folz commented 2 years ago

Seeing this thread - I have a livecode environment I'm working on which uses CodeMirror 6, typescript-vfs, and a handwritten hydra.d.ts to provide IntelliSense and typechecking. I used this thread for getting started.

So it is possible to do in CM6, and was pretty straightforward. I have tried using monaco-editor before for another project and found it a lot more cumbersome to work with - it really, really wants to be the central focus of your page, and I found it was a bit tricky to integrate into an overall application. Could have been just me though.

Screen Shot 2022-01-08 at 10 43 21 AM

ojack commented 2 years ago

Ooooh this is great! @folz

I am now remembering I had a really hard time with monaco trying to have more than one editor on a single page and eventually gave up.

brucelane commented 2 years ago

I've done better back in the day...

folz commented 2 years ago

Just published my livecode environment, in case it's helpful seeing the implementation:

ojack commented 2 years ago

@brucelane are you referring to https://github.com/ojack/hydra/pull/99? I remember that this version attaches global key commands to specific functions, but don't remember there being an Intellisense / code hinting portion. Feel free to share or elaborate here :)

brucelane commented 2 years ago

Yes, it was a proposition, open to debate. The choices were examples, like mr for modulateRepeat. Could be anything. It was also an opportunity to get the variable names to get some in-situ help: mr -> modulateRepeat(repeatX = 2) Some people on the demo I made and the forum wanted it to happen at that time. Anyway, I moved back to use c++ and cinder with an old hydra fork of mine which supported frag(``) and sharing the regl generated fragment shaders to cinder via websockets.

ojack commented 2 years ago

@brucelane yes I love this idea and am unfortunately just getting around to everything now. Feel free to chime in with ideas here as well.

btw, the frag() is still there in hydra-synth, it just uses glsl() instead.

const shaderPasses = osc().rotate().glsl()
console.log(shaderPasses)
arnoson commented 2 years ago

Your setup looks really good @folz! I didn't know about Codemirror 6, seems like a better choice than Monaco :)

MaxPuig commented 1 month ago

Hey, I recently discover this project and I find it amazing. Is this feature still something that could be added to Hydra? I saw https://github.com/hydra-synth/hydra/pull/99 is now closed without getting merged.