diff --git a/src/artist.coffee b/src/artist.coffee index 942c446..61698e8 100644 --- a/src/artist.coffee +++ b/src/artist.coffee @@ -68,6 +68,8 @@ class Artist @current_octave_shift = 0 @bend_start_index = null @bend_start_strings = null + @in_beam = false + @beam_notes = [] @rendered = false @renderer_context = null @@ -340,7 +342,11 @@ class Artist stave_note.addDotToAll() stave_note.setPlayNote(params.play_note) if params.play_note? - stave_notes.push stave_note + stave_note.beamset = @beamset # adapted from https://github.com/0xfe/vextab/pull/124#issuecomment-833214140 + if @in_beam + @beam_notes.push stave_note + else + stave_notes.push stave_note addTabNote: (spec, play_note=null) -> tab_notes = _.last(@staves).tab_notes @@ -388,6 +394,31 @@ class Artist stave.tab_notes.push(bar_note) stave.note_notes.push(bar_note) if stave.note? + # adapted from https://github.com/0xfe/vextab/pull/124#issuecomment-833214140 + setBeam: (action) -> + @beamset = action + + openBeam: (type) -> + L "openBeam: ", type + if @in_beam + throw new Vex.RERR("ArtistError", "Already in beam") + @in_beam = true + @beam_notes = [] + + closeBeam: (type) -> + L "closeBeam: ", type + if not @in_beam + throw new Vex.RERR("ArtistError", "Not in beam") + b = new Vex.Flow.Beam(@beam_notes, true) + for n in @beam_notes + n.setBeam(b) + # _.last(@staves).note_notes.push b # doesn't work + _.last(@staves).note_notes.push n + + # @stave_articulations.push b + @in_beam = false + @beam_notes = [] + makeBend = (from_fret, to_fret) -> direction = Vex.Flow.Bend.UP text = "" diff --git a/src/vextab.coffee b/src/vextab.coffee index 8ab25c6..3fe6ec7 100644 --- a/src/vextab.coffee +++ b/src/vextab.coffee @@ -73,20 +73,23 @@ class VexTab return params parseCommand: (element) -> - if element.command is "bar" - @artist.addBar(element.type) - - if element.command is "tuplet" - @artist.makeTuplets(element.params.tuplet, element.params.notes) - - if element.command is "annotations" - @artist.addAnnotations(element.params) - - if element.command is "rest" - @artist.addRest(element.params) - - if element.command is "command" - @artist.runCommand(element.params, element._l, element._c) + switch element.command + when "bar" + @artist.addBar(element.type) + when "tuplet" + @artist.makeTuplets(element.params.tuplet, element.params.notes) + when "annotations" + @artist.addAnnotations(element.params) + when "rest" + @artist.addRest(element.params) + when "command" + @artist.runCommand(element.params, element._l, element._c) + when "open_beam" + @artist.openBeam(element.params) + when "close_beam" + @artist.closeBeam(element.params) + else + throw newError(element.command, "Invalid command '#{element.command}'") parseChord: (element) -> L "parseChord:", element @@ -110,6 +113,13 @@ class VexTab @artist.setDuration(element.time, element.dot) if element.command + # Code here adapted from https://github.com/0xfe/vextab/pull/124#issuecomment-833214140 + # open_beam and close_beam are not really command but state + # set beam state (this state would be saved in stavenote array) + if (element.command == "open_beam") + @artist.setBeam("open") + if (element.command == "close_beam") + @artist.setBeam("close") @parseCommand(element) if element.chord diff --git a/tests/tests.coffee b/tests/tests.coffee index b064313..e3289a4 100644 --- a/tests/tests.coffee +++ b/tests/tests.coffee @@ -53,6 +53,7 @@ class VexTabTests test "Rests in Tab", @restsInTab test "Multi String Tab", @multiStringTab test "Time Signature based Beaming", @timeSigBeaming + test "User Beaming", @beaming test "Override Fret-Note", @overrideFretNote test "Mixed Tuplets", @mixedTuplets test "Accidental Strategies", @accidentalStrategies @@ -595,6 +596,21 @@ class VexTabTests """ renderTest assert, "Time Signature based Beaming", code + @beaming: (assert) -> + code = """ + tabstave notation=true tablature=true time=4/4 + notes :32 [ 2/3 5/2 ] :q 5/1 + """ + renderTest assert, "User Beaming", code + + # adapted from https://github.com/0xfe/vextab/pull/124#issuecomment-833214140 + code = """ +tabstave notation=true tablature=false clef=treble time=4/4 + notes =|: :8 F/4 :q F/4 :8 F/4 [ tF/4 E/4 ] :q D/4 + notes | :qd D/4 :8 F/4 [ F/4 A/4 G/4 F/4 ] + """ + renderTest assert, "User Beaming 2", code + @multiStringTab: (assert) -> code = """ tabstave key=A strings=4