bettermusic / studio

WIP for a Design System and component library to power a suite of music tools. Most notably a chord chart editor & renderer.
https://www.bettermusic.tech/
Other
6 stars 0 forks source link

💡 RFC: CodeMirror 6 Language Support #248

Closed isaiahdahl closed 1 year ago

isaiahdahl commented 1 year ago

RFC: CodeMirror 6 Language(s) Support

Summary

Write language support to ultimately enable syntax highlighting for the editor web component for the studio chord chart editor.

CleanShot 2022-10-24 at 14 07 55

How The Library Works / Context

We have a parsing library (ChordSheetJS) that can take text in different formats and compile it into a common AST that we can then format through various outputs. The web components we're creating will have a Editor (CodeMirror editor) and a Renderer Component, which is watching changes in the editor, and then running it through the parsing library and rendering it.

Editing Modes

There are two main syntax's ChordPro and Chords Over Words that we want to support. The rules and differences between the two are defined visually with notes here:

https://www.figma.com/file/2X5dJO3LWpOXrF2YfsAVMQ/Chord-Charts?node-id=405%3A6557

Down the road we'd like to support more syntax's. Some are very slight modifications on either chordpro or chords over words and may not even warrant a new syntax or dialect because the rules don't conflict. There's an issue/RFC we've created here outlining all (some) the potential conflicts.

The main additional one to take note of is OnSong. The OnSong format has support for a sort of half blend between chords over words (lyrics) and ChordPro. Plus a few extras. But there are some conflicts with how we'd like to support things where we can't just implement the support for the OnSong format and call it good. If you scroll down in the Figma file you can see where I've highlighted differences not outlined in that differences RFC yet.

Priority is to support Chords Over Words & ChordPro as they are outlined in the Figma board.

You can assume that it will either be edited in a mode of one or the other. Meaning we won't need to support a half chords over words half chordpro mode.

I only mention the OnSong format so that you can make an informed decision about how best to architect it, because obviously even though they are different, there's a lot of overlap.

As I've mentioned before in my head I was thinking we'd have one grammar that supports two dialects chordpro and chordsOverWords Then for some of the other formats where there is very little conflict, we could add additional dialects down the road. (ie. UltimateGuitar )

For the format OnSong where I think there will be more conflict then resolved with dialects, we could just do a completely new language support down the road.

^ Possibly this is wrong though and it'd be achievable to do it all in one grammar using dialects.

Again, the main ones we want to prioritize are supporting Chords Over Words and Chordpro as outlined in the Figma. 99% of editing will happen in one of these two formats.

What we've started

You can find the latest stable iteration of the grammar we've created here:

packages/codemirror-lang-chordpro/src/syntax.grammar

In it you'll find a pretty clear breakdown of what a chord is. Pasting here for reference.

Chord { "("? (symbolChord | numericChord | numeralChord | bassOnlyChord | rhythmSymbol) ")"? }
...
@tokens {
  ...
  // Notes & Chord Parts
  symbolNote { $[A-G] }
  numeralNote { 'I' | 'II' | 'III' | 'IV' | 'V' | 'VI' | 'VII' | 'i' | 'ii' | 'iii' | 'iv' | 'v' | 'vi' | 'vii'  }
  numericNote { $[1-7] }
  suffix { $[a-zA-Z0-9\(\#)]* }
  accidental { $[b#] }

  // Bass 
  symbolChordBass { symbolNote accidental? }
  numericChordBass { accidental? numericNote }
  numeralChordBass { accidental? numeralNote? }

  // Chords Patterns
  symbolChord { symbolNote accidental? suffix? ('/' symbolChordBass)? }
  numericChord { accidental? numericNote suffix? ( '/' numericChordBass)?  }
  numeralChord { accidental? numeralNote suffix? ( '/' numeralChordBass)?  }

  // Bass Only Chords
  bassOnlyChord { '/' (symbolChordBass | numericChordBass | numeralChordBass) }

  // Special Symbols
  rhythmSymbol { $[x|/-] }
  @precedence { bassOnlyChord, rhythmSymbol }
  ...
}

Which supports: CleanShot 2022-11-07 at 15 52 07 But there's nothing working for Chords Over Words

The component library is packages/studio

Relevant files making the studio editor component work if you want them are: packages/studio/src/stores/editor_store.ts packages/studio/src/utils/codemirror.utils.ts

Not sure if it would be helpful but you could refer to the PeggyJS grammers that power the PeggyJS parser for the ChordSheetJS library

packages/chordsheetjs/src/parser/*_grammar.pegjs

chord_grammar.pegjs is shared between the other two pegjs grammars. There's a build script that appends chord_grammar.pegjs to each.

Deliverables: