ChordPro / chordpro

Reference implementation of the ChordPro standard for musical lead sheets.
Other
310 stars 51 forks source link

markup in chord definition ignored (related to truesf?) #283

Closed gwyndaf closed 1 year ago

gwyndaf commented 1 year ago

New issue occurring with dev releases 026 through to 028

I have a chord defined with:

{title: Chord markup test}
{define: Bm7 copy Bm7 display "Bm<span size=80% rise=30%>7</span>"}
Just a [Bm7]

but the Bm7 doesn't display superscript 7 as in earlier versions. Same behaviour across a larger test sample.

It seems config-related, and I think I've narrowed it down: the problem seems caused by having truesf set to true and goes away if set to false.

sciurius commented 1 year ago

Thanks for testing.

Currently the default display string is statically copied in the (rest of the) chords defined in the config file. Once the config is processed it doesn't exist anymore.

If there were a real global default setting for "display", would you still need being able to set it in the chords config?

As for the incidental observations, I'm aware of this problem. Just need to find some time to address it.

gwyndaf commented 1 year ago

TLDR: no I don't also need display defaults in chord configs if there's a real global setting.

Personally, I don't have any specific need to set a default display format in the chord configs. I've already got mine set up with explicit display values, I update chords only occasionally, and my process populates display values automatically so it's relatively quick. That approach already works well, and quite efficiently.

But, because display values are no longer copied from the instrument config with {define copy}, it means a bit more work on some songs to style those chords so they're consistent with chords from the config, plus of course those that are explicitly defined. And more again if I want to apply different style/display choices to the same collection.

So, a real global default display setting would be far more useful, if that determines the default display format of {define} chord names (explicit or copied) as well as those from configs*. I don't also need to set defaults for each set of instrument chords.

That could also let me use different default chord display settings in my helvetica.json and roboto.json config files. and maybe makes possible configs to support the MuseJazz font (maybe Campani too, but that seems more complex). Depending on your implementation, it might then be possible to set the default chord display style for each song, e.g. {+settings.chord_display} (not sure I've a use for that right now, but someone might).

My underlying thinking is probably two things: 1) A core principle of keeping content and styling separate (as far as possible), like HTML and CSS. So I can re-use the same song sources with different configs to suit different purposes (e.g. for accessibility). 2) Chord name styling seems related more to output styling more than it is to instrument definition. For instance, I might use different rise values in markup depending on the font being used.

gwyndaf commented 1 year ago

* Interesting question of when a global display default should apply.

If my config defines Cm7 with no display value, should the default display value apply? Yes

If my config defines Cm7@3 with a display value of Cm<sup>7</sup>, should the default display format apply to that? No

If my config defines Cm7@3 with a display value of Cm7, should the default display value apply? ???

I'm not sure I have a clear answer, but it does make me realise this: since you added support for Pango markup (which is very useful), we now have both content and styling of the chord name. Do we need to recognise a separation between those two qualities in order to clarify the challenge?

sciurius commented 1 year ago

It's the old HTML-before-CSS all over again...

We can consider "%{root}%{qual}%{ext|<sup>%{}</sup>}%{bass|/%{}}" to be a pure style sheet (no chord related content). "Cm7" is a degenerate style sheet (fixed content). Or, indeed, separate them.

{define ... display "Cm7" style "%{root}%{qual}%{ext|<sup>%{}</sup>}%{bass|/%{}}" ... }

Display must then be something that can be analysed into root, qual, etc..

gwyndaf commented 1 year ago

Yes, that makes a lot of sense.

Also, having a global default for display content (i.e. chord name) makes absolutely no sense, so maybe global setting might be called settings.chordformat for clarity. I guess the default value would probably be %{name}

That setting could be applied to any chords (with your example above) that don't already have style. Or don't include markup in display (for backward compatibility, if that's a consideration).

Maybe format is a better name than style? Just in case you decide to introduce a style (sheet) concept (e.g. named custom styles) at some future point... :)

sciurius commented 1 year ago

Assuming

{define ... display "Cm7" format "%{root}%{qual}%{ext|<sup>%{}</sup>}%{bass|/%{}}" ... }

(where format may be set globally) what would be typical use cases for having a display value?

gwyndaf commented 1 year ago

1. Main use case for me is currently of the form:

{define-ukulele: Am7/C copy Am7 display "Am<span size=80% rise=30%>7</span>" }
{define-ukulele: C6 copy Am7 display "Am<span size=80% rise=30%>7</span>" }

With a global chord format setting, I'd anticipate those could be achieved as below (with global format applied to the display value):

{define-ukulele: Am7/C copy Am7 display "Am7" }
{define-ukulele: C6 copy Am7 display "Am7" }

In previous versions the display value was also copied from the instrument config, so I now need to reiterate those manually with {define ... display ... }.

Broader context is a playing group of mixed instruments and levels, to provide easier (or easier-looking) chords/names for beginners, which fit sonically even if a compromise: my aim is encouragement rather than excellence! For instance, slash chords are often unfeasible/meaningless on ukulele, or too daunting for beginners, so I'll often substitute easier (but compatible) chords.

2. Another, less common case, but I think could probably be achieved without display:

{define-ukulele: D† copy D@2 display "D<sup>†</sup>" }

Context: if a song already uses standard D voicing, suggest an alternate voicing in some places, and reference that alternate form as D† in a footnote.

I believe%{ext} captures trailing unrecognised characters, so suspect this could be realised as either of

{define-ukulele: D† copy D@2 format "\%{root}\%{qual}<sup>†</sup>" }
{define-ukulele: D† copy D@2 format "\%{root}\%{qual}<sup>\%{ext}</sup>" }

This does assume that format will accept additional (non-chordname) characters, as well as chord metadata.

sciurius commented 1 year ago

I'm trying to get the semantics of display and format clear.

{define: C6 copy Am7 display "Am7" format "\%{root}\%{qual}\%{ext|<sup>\%{}</sup>}\%{bass|/\%{}}" }

Assuming that the format shown is the global format (we have to think of a place in the config) this reduces to:

{define: C6 copy Am7 display Am7}

The chord properties (root, qual) are now taken from display instead of the chord name. So display must be an understandable chord name. In general, display should only contain chord info, and format should only have references to chord info. Of course, noone will prevent you from omitting display and writing format "Am<sup>7</sup>".

What should display default to? The given name C6 or the copied name Am7?

sciurius commented 1 year ago

Or, in the style of LATEX: copy and copy* where the latter does (not?) copy the display property.

gwyndaf commented 1 year ago
{define: C6 copy Am7 }

behaviour is probably at the heart of the question. With release version (up to and including v6.010,) display defaults to the value copied from the config. In current development versions, it's not copied and defaults to the chord name being defined. With no copy, it naturally defaults to the chord name being defined.

I don't know the reasons for that current change how copy handles of display. Perhaps it's to simplify parsing of chords and/or avoid issues when the display value contains markup?

Personally, I don't think there's an intuitive 'best' way of doing this. I've been adapting my approach as Chordpro's functionality evolves. Up to now it's been useful defaulting to display values from my config because they contain markup (and avoids rewriting it in {define}), but that reason goes away - mostly or entirely - if there's a global format default. All my config display markup follows the same format so becomes redundant with a global setting.

The copy / copy* approach seems really neat. It essentially reflects what seem the two {define copy} scenarios: 1) an alternate voicing {define: C copy C@3} (displays C by default) 2) a substitute chord {define: C6 copy* Am7} (display Am7 by default)

I don't have a strong view which way round those two should operate. Backward compatibility suggests copy should still default to config display value (if present), and copy* defaults to chord name. Maybe the LATEX convention suggest the other way around? If there's no display in config, copy and copy* should both default to chord name anyway.


In terms of definitions, yes it makes sense that content in display is only understandable chords names (essentially 'musical' information). Would that include unknown extensions in relaxed mode, or also strict (because of temporary relaxation for parsing)? For instance, suffix to identify multiple chord variants in a song.

format then makes sense as the container for stylistic description, although allowing explicit text values seems a useful flexibility. So it could accommodate non-musical text embellishments, like {format ">> %{name} <<"} to highlight an extra special chord!


Where in the config to place format default? It will determine chord display format in both song body and chord diagrams, so close relatives (who it should probably be near) seem to be settings.inline-chords and pdf.diagrams.

If it's at settings level, that could also apply to, say, HTML output (as well as PDF). Would there be a good reason for needing different format defaults for PDF and HTML (or LATEX) output, in the same config? I haven't used HTML or LATEX output but, if I did, I'd probably develop separate configs for each output format. So maybe that's more about whether 'out of the box' defaults need to be different for PDF/HTML/LATEX.

Another factor might be whether it could be redefined temporarily at song level, e.g. as {+settings.chord-format}. It's not a use case that's arisen for me (yet), but might be a consideration.

In the absence of other good reasons, my feeling is maybe it should go at settings level, near inline-chords.

sciurius commented 1 year ago

Thanks for your valuable feedback. You're a great help sorting things out. I think this summarizes it:

  1. settings.chord-format will globally set a format that is applied at output time if not overruled.
  2. copy will copy display and format to be compatible with 6.010.
  3. copy* will not copy display and format.
  4. display will parse its argument using relaxed mode for chord properties. If the root is recognized and the rest is not the rest will be the ext property.
gwyndaf commented 1 year ago

You're very welcome. My programming skills are limited, but I'm fairly good at thinking through, and imagining awkward cases!

This test file might useful: chord_parse_test.cho.txt

It's geared toward current dev version, but easily adaptable for proposed changes (replace display with format). chord_parse_test.cho.pdf

sciurius commented 1 year ago

Under the assumption that very few people are currently using copy and display...

  1. copyall will copy all, including display and format, same as 6.010 copy.
  2. copy will copy all except display and format.

Do you think this will already break something?

gwyndaf commented 1 year ago

That seems a reasonable assumption.

Even for that small group, I don't foresee anything breaking fatally. However, if config includes display, they might need a small adjustment of existing {define ... copy ...} to {define ... copyall ... } for continuity, to match current output. So that might be worth highlighting in release notes.

sciurius commented 1 year ago

It will definitely be documented (and announced on the forum). Copy and display are first documented in 6.010, I will send a message to stop using copy and display since their semantics is going to change in 6.020.

For example, this will no longer work:

{define Am7 display "Am<sup>7</sup>"}

and should become format instead of display. Even better, leave it to the global format.

And I'll mark display/format/copy/copyall as experimental, just to be sure.

sciurius commented 1 year ago

I think I've got most of it in 6.010_015. Looking forward to your feedback.

gwyndaf commented 1 year ago

Fantastic. I'm a bit squeezed with work right now, so only cursory testing until the weekend.

So far, settings.chord-format and format seem to behave as expected.

Might be some issue with handling display though. From initial testing:

{define Bbm* copy Bbm display "C#6" format "<b>\%{name}</b>"}

outputs a Bbm chord, displaying name Bbm*, but I was expecting it to display C#6 in output. Similar behaviour with or without format parameter, or using %{root}%{qual} rather than %{name}. C#6 is an understood chord name with no markup, so I think should be an acceptable value for display?

It appears as if format (explicit in {define} or default from chord-format) is operating on the chord name, rather than the display name.

I think there might be a related issue with display values from config being ignored (using {define ... copyall ...), but that config includes markup in display, so is possibly invalid and I'll need to edit the config for further testing.

sciurius commented 1 year ago

I'll take a look.

I have also revised some of the docs, trying to explain how it works. https://www.chordpro.org/beta/chordpro-chords/ https://www.chordpro.org/beta/directives-define/ https://www.chordpro.org/beta/chordpro-configuration-format-strings/#chord-format-string

gwyndaf commented 1 year ago

OK, here's a bit of strangeness. I don't quite understand what's happening, but it might offer some insight.

I've created a test config that includes a silly (for testing purposes) display name

    { "name" : "A",   "base" : 1,   "frets" :  [ 0,0,2,2,2,0 ],   "fingers"  :  [ 0,0,1,2,3,0 ],   "display"  :  "A2"  }, 

If I use only that config and -X, to process this:

{title: Chord display test}
{define A frets 0 0 2 2 2 0}
[A]

I expect my output to be a simple 'A' diagram, as defined in the song, because it's a fresh {define} with no copy or copyall, so it should replace the A definition from the config (I believe).

But I get an 'A2' display name. That suggests it's taking display from the config, even without any copy.

Similar behaviour if I change display value in the config to A3 or A4, but not A* or A1 (simply 'A' output). That's probably a side-issue: I think display can take any understood name, yes? Seems the same behaviour whether chordnames is strict or relaxed

gwyndaf commented 1 year ago

Using the previous example, if I output to Chordpro format, I get (as expected)

{title: Chord display test for guitar}
{define: A base-fret 1 frets 0 0 2 2 1 0}
{define: A               base-fret  1    frets   0   0   2   2   1   0   }
[A]

and that outputs to PDF as expected, with chord displaying as 'A'.

So maybe something odd is happening with display during PDF output?

gwyndaf commented 1 year ago

Similar test sequence, but using explicit {define ... display A3} in the song.

chord_display_test3b.cho.txt > chord_display_test3b.pdf

chord_display_test3b_out.cho.txt > chord_display_test3a_out.pdf

I'm not totally sure how the processing sequence works, but this seems something like the config display values are somehow getting 'stuck' or 'remembered' somewhere (sorry that's my best language for these things!) even if they're not used, so they come back into the PDF output process.

gwyndaf commented 1 year ago

To eliminate the possibility of display names like A2 or A3 causing problems, same tests run using display values of C and D, with the same results, i.e. output directly to PDF contains the config display name, and regardless of whether {define} includes a display value.

Behaviour seems fine (as expected) with output to intermediate Chordpro file, which is then processed to PDF with only -X (no config).

gwyndaf commented 1 year ago

Overall, it's seeming extremely useful. I can remove ~90% of my display (now format) elements from {define} because formatting is now determined by the global setting.

Some other observations, which relate more broadly to {define}:

  1. [N.C] doesn't seem to output at all (i.e. in song body). Same behaviour whether it's defined in instrument config or explicit {define}. But I know this (and other non-musical 'chords') are a special challenge.
  2. {define-keyboard: Am/E keys 7 0 3 } should - I believe - show E-C-A on the keyboard diagram, but I'm getting the standard (root position) chord. I've never tried that before, so errors might be mine :)
sciurius commented 1 year ago

I went back to the drawing board (almost literally) and decided to first work out precisely how it should work before further hacking on the implementation. After all, it should make sense to the users.

https://chordpro.org/beta/chords/

Your feedback is appreciated. Note that the drawing board already revealed a couple of things that went wrong during the adding of new features so I hope it will make things easier to implement and better to maintain.

gwyndaf commented 1 year ago

OK, here are broad thoughts. Very much a user's perspective: I don't know how these relate to the actual processing!

Context: I'm not sure where you're planning to put this in the documentation. You've done a clear conceptual overview of how chords get used and names get parsed into metadata, so this seems more like part of the {define} directive page. It seems to fall naturally into 'diagram' and 'name' sections, so this seems to suit replacing from here onwards.

Opening section: might be clearer described as {define: A copy B display C format Z ... }? Conceptually, that progresses logically from 'substance' (diagrams) through to 'style' (formatted output name).

Overall, I think my conceptual structure/overview might be: 1) Reference how the chord is named in the song: [A]: {define A} 2) Use a boilerplate/template chord B from the config (or earlier definition): copy, e.g. {define A copy B} 3) Define (or redefine) content of the chord diagram graphic: frets/fingers/keys 4) Adjust the appearance/styling of the chord diagram: diagram 5) Change the displayed chord name to C (in song body and diagram): display ( {define A copy B display C} ) 6) Adjust visual appearance.of the chord name 'C' (in song body and diagram): format ({define A copy B display C format Z})

I think that reflects the order in which each parameter should modify the ones that come before it. I think the directive accepts the parameters in any order, but this seems to me the order in which they take effect.

I'll try to write the above as a table that clearly shows where different defaults/settings are set. To follow.

I've maybe a few tweaks to specific wording for clarity, to follow, but I think this ordering/structural point might be the most useful.

sciurius commented 1 year ago

Thanks for great feedback! I incorporated most (if not all ☺) remarks and suggestions.

https://chordpro.org/beta/chords/

gwyndaf commented 1 year ago

That seems clearer to me, and makes sense to revisit copyall after discussing display and format.

This might still be useful: Define_behaviour.odt

It was a useful exercise for me to break down sources and defaults for all the define parameters, particularly as diagram and format build on top of appearance settings elsewhere. This is how I think they're meant to work: some bits are uncertain, but I guess it's useful for testing working assumptions!

sciurius commented 1 year ago

Great table! I made a couple of changes (that also answer some of your questions).

Define_behaviour.odt

sciurius commented 1 year ago

Do you think there is still a purpose for display in config chord definitions? There was a purpose when display controlled the appearance but now it merely changes the name. Effectively the following two are identical:

{ "name" : "B", ... },                   // alternative A
{ "name" : "A", "display" : "B", ... },  // alternative B

Both define a chord B, but alternative B yields a chord with a display property. This then only matters for a define with copyall:

{define: C copyall B ...}

With alternative A this will display B, with alternative B this will define B. Or would I need to use

{define: C copyall A ...}

to use alternative B?

Do you still see use cases for this?

gwyndaf commented 1 year ago

I do sometimes want to keep a particular chordname in the song source (e.g. [Fmaj7]), but output a different name and diagram conditionally, for specific instruments, e.g. Am for ukulele. Previously, that's relied on display in the config, to provide the output chordname. AFAIK name in the config was only used as a key to link with the {define copy}.

But, it's a good idea to simplify things, and seems like essentially using name as a value, as well as key for referencing. If understand correctly:

It's elegant, and I can't think of any problems with that. I've looked through all my {define} and can't see any where it would cause problems. The name copyall still seems meaningful, because it's effectively copying the name as well as the diagram properties.

So, maybe it's worth trying, and I'll see if I can break it? :)

One thought: I don't know if display in {define} is still useful to keep? Maybe for flagging multiple chord voicings within a song, e.g. what I currently have as {define-ukulele: D† copy D@2 display D<sup>†</sup>}. How might that work with the new logic?

Maybe format is also redundant in the config? I think settings.chord-format might now deal with all cases where I've added markup in my configs, plus some additional cases where I added markup in {define }. But, if it's not causing problems, perhaps best left alone. And it's essentially doing the job in configs that display used to, so might fill in odd cases.

sciurius commented 1 year ago

I think you made a good case for keeping display in the config, and have it work analogous to the one in {define }. So in your config you can have different voicings for the same chord:

{ "name" : "D@2", "display" : "D", ... },
{ "name" : "D@4", "display" : "D", ... },

In the song you would use [D@2] and get a D on output, with the D@2 voicing.

Similar for copy:

{define D† copy "D@2" ...}                     ← will display `D†`
{define D† copyall "D@2" ...}                  ← will display `D`
Hello [D†]World
gwyndaf commented 1 year ago

Oh, that wasn't my intention: I thought it was a neat idea to simplify the config.

My approach to alternate voicings doesn't use display from the config. With my usage, the config name (e.g. D@2) is only ever a key for referencing the definition as {define D copy D@2}. That is, my song source contains [D], and D@2 never appears in the song source or output. Occasionally I'll use [D†] in the song for an second voicing, and use {define} to specify the voicing (from config). That allows me to choose different voicings for different instruments, with conditional {define- }.

However, if a song uses [D@2] in the song source, and doesn't modify/copy it with {define} then, yes, I guess that would need display in the config to be output it as 'D' (otherwise D doesn't exist anywhere). I don't use that approach, but some people might, and it allows multiple voicings to be accessed without additional {define} directives.

My other use case, of (conditional) substitute chords previously did rely on display from the config, but your idea that copyall copies the chordname from name (not display) addresses that need without using display values.

So, the question is, if display stays in the config, how to determine whether copyall copies the name or display chordname? Or does that present three {define} copying scenarios: 1) copy only diagram properties: copy 2) copy diagram properties and name chordname (your proposed copyall) 3) copy diagram properties and display chordname (current dev copyall)

sciurius commented 1 year ago

The name is what you refer to, the display is what is shown.

These two are equivalent (first line is config, second is song source):

{ "name" : "X", "display" : "Y", ... },
{define X display Y ...}

To use (i.e., refer to) either, you use X. What is shown in the output is Y. Same for copy/copyall:

{define Z copy X ... }

The name is never copied, copy copies the diagram properties, and with copyall display and format are copied as well.

AFAICS this is reasonably straightforward. By using display you can do very confusing things but that's the users own responsibility.

Without display it is all fully compatible with the 6.000 situation so it shouldn't break anything.

gwyndaf commented 1 year ago

OK, that makes sense. It's clear, compatible, and flexible.

So, my understanding of how it would work in the main use cases (all assuming suitable config entries): 1) Alternate voicing 'direct': [D@2] in song source (displays as 'D@2' if no display in config, otherwise uses config display value (e.g. 'D') 2) Alternate voicing 'indirectly': [D]in song source and {define-guitar D copy D@2} (displays as 'D', ignores any display value in config) 3) Multiple alternate voicings 'indirectly': as 2. above plus [D†] in source and {define-guitar D† copy D@5} (displays as 'D†', ignores any display value in config) 4) Substitute (e.g. 'easier') chord: [Fmaj7] in source and {define-ukulele Fmaj7 copyall Am} (displays as config display value (e.g. 'Am'), or 'Fmaj7' if no display in config)

sciurius commented 1 year ago

Yes!!!

sciurius commented 1 year ago

I'm going to work on the redesign. I have the optimistic feeling that it will lead to scrapping several special cases and loopholes in the code.

sciurius commented 1 year ago

What is your opinion on parenthesized chords? Is (C) a distinct chord like C† or is it just a C chord with special formatting.

EDIT: Sometimes asking the question is answering it... You can use (C) but not define it. So it is a C chord with a special formatting.

gwyndaf commented 1 year ago

It's not a convention I'm familiar with to denote (alternate) chords.

Personally, I tend to use inline chords, enclosed in parentheses (as per this example: Cripple_Creek_Ferry (guitar) git.pdf. It would probably confuse people if I used parentheses to also denote alternate chords!

It could still be a valid convention for people who use above-the-line chords, so I'm guessing your edit suggests it could be achieved with:

{define C† copy C@3 format "(\%{name})" }  OR
{define C† copy C@3 format "(\%{root}\%{qual})" }

I imagine the first of these would output as (C†) and the second as (C)

AnniePerson commented 1 year ago

imho (C) is just a C that might be alternatively played or might be skipped in certain cases. Nothing special, should be handled and transposed as other chords, (Cm), (C6) or so could also occur.

Regards

Herbert

PS: Sorry, I became pretty silent for a while. Very busy with other things and not affected by the lengthy discussion with Gwyndaf. I'll be back.

-- Herbert Schneider @.*** http://www.moonlightcrisis.de https://www.facebook.com/MoonlightCrisis http://www.frankenbaend.de https://www.facebook.com/Frankenbaend

Am 20. Juni 2023 17:00:08 MESZ schrieb Johan Vromans @.***>:

What is your opinion on parenthesized chords? Is (C) a distinct chord like C† or is it just a C chord with special formatting.

-- Reply to this email directly or view it on GitHub: https://github.com/ChordPro/chordpro/issues/283#issuecomment-1598965041 You are receiving this because you are subscribed to this thread.

Message ID: @.***>

sciurius commented 1 year ago

As Herbert mentioned, it's a way to indicate an alternative/optional chord, mostly in progressions, e.g. C, (C/B), (C/A), Am. It has nothing to do with the chord itself. It's a special case in the notation.

gwyndaf commented 1 year ago

Ah, that makes sense.

I flag optional/passing chords with a suffix, e.g., C* and make them smaller in output. Using current (development) syntax:

{define C*  copyall C format "<small>\%{name}</small>" diagram #888888}

As I think you both suggest, format will allow a lot of control over how such chords appear in output :)

sciurius commented 1 year ago

Today I checked in what I think (hope) is the major part of an internal redesign of chord handling.

The approach is to take the chord name, strip parens and markup, and use that as the handle for the chord. The parens and markup are stored internally with the handle. This approach made a lot of things easier but required changes in many places, including backends and tests.

You can use 6.010_017 for testing. Don't spend too much energy yet, I'd be supprised if any song comes out as expected ☺.

gwyndaf commented 1 year ago

Well, using my 'testing' songs (broadly with display metadata shifted into format), at a very quick glance I don't see any unexpected chord issues.

A couple of observations, which might well disappear as development progresses...

1) On some individual songs, song lines (but not chord grids) wrap within a narrow space, about 50% normal page width. Seems to arise when processing individual songs but not a songbook collection.

2) The following errors seem to arise during PDF generation for some, but not all, songs:

Missing info for chord App::Music::ChordPro::Chords::Appearance=HASH(0x559d90507718) at /media/data/Shared/Music/Technology/ChordPro/git/chordpro/script/../lib/App/Music/ChordPro/Output/PDF.pm line 1653.
    App::Music::ChordPro::Output::PDF::songline(HASH(0x559d93846358), 42, 219.491539817337, HASH(0x559d91fc55d8), "song", App::Music::ChordPro::Song=HASH(0x559d904f8e90), "indent", 0) called at /media/data/Shared/Music/Technology/ChordPro/git/chordpro/script/../lib/App/Music/ChordPro/Output/PDF.pm line 995
    App::Music::ChordPro::Output::PDF::generate_song(App::Music::ChordPro::Song=HASH(0x559d904f8e90), HASH(0x559d91075bb0)) called at /media/data/Shared/Music/Technology/ChordPro/git/chordpro/script/../lib/App/Music/ChordPro/Output/PDF.pm line 99
    App::Music::ChordPro::Output::PDF::generate_songbook("App::Music::ChordPro::Output::PDF", App::Music::ChordPro::Songbook=HASH(0x559d8eea8180)) called at /media/data/Shared/Music/Technology/ChordPro/git/chordpro/script/../lib/App/Music/ChordPro.pm line 253
    App::Music::ChordPro::chordpro() called at /media/data/Shared/Music/Technology/ChordPro/git/chordpro/script/../lib/App/Music/ChordPro.pm line 92
    App::Music::ChordPro::main() called at /media/data/Shared/Music/Technology/ChordPro/git/chordpro/script/../lib/App/Music/ChordPro.pm line 85
    main::run() called at /media/data/Shared/Music/Technology/ChordPro/git/chordpro/script/chordpro line 48

I know _017 is very much work-in-progress, so won't try to investigate any specific correlation patterns right now. But happy to do so if either of the above is a surprise to you :)

sciurius commented 1 year ago

Great! This is precisely the feedback I'm looking for.

Internally, instead of a chord name I now have an object that has the chord name as a property. So where traditionally the code used e.g. $chord, it now must use $chord->key. Using $chord will yield a stringified representation of the object, which looks like App::Music::ChordPro::Chords::Appearance=HASH(0x559d90507718). So the 2nd problem locates a place in the code that still needs to be adjusted.
My gut feeling is that the 1st problem has a similar cause, and that the wrapping algorithm uses the stringified representation instead of the chord name to determine the (textual) length of the chord name.

To be continued...

sciurius commented 1 year ago

6.010_019 should have a number of approvements.

If you still hit the Missing info for chord App::Music::ChordPro::Chords::Appearance please send the stacktrace.

sciurius commented 1 year ago

Sure. See https://www.chordpro.org/chordpro/chordpro_markup/

gwyndaf commented 1 year ago

Thanks Johan, I'll check it out.

I've copied your above reply to the user forum, where I think it was aimed :)

gwyndaf commented 1 year ago

I ran _020 with a book of >100 songs using two instrument configs, and no error messages. I'm slowly going through visual output to check whether it's as expected.

Right now, here's an interesting one:

{define D7sus2/C copyall C6}
[D7sus2/C]

and instrument config including

 { "name" : "C6",   "base" : 1,   "frets" :  [ -1,3,2,2,1,0 ],   "fingers"  :  [ 0,4,2,3,1,0 ],   "display"  :  "C6"  }, 

Output has C6 in the song body, but D7sus2/C as diagram label (but frets/fingering for C6): Suddenly_I_See TEST.pdf

If I modify to {define D7sus2/C copy C6 display C6} (which I think should be equivalent), all is as expected, with C6 shown as both chord in song, and diagram label.

So, is seems like copyall is maybe copying the config's display value only to the song body, and not to the diagram?

gwyndaf commented 1 year ago

Possibly related:

{define-keyboard! D7sus2/C copy C6 display C6}
{define-guitar D7sus2/C frets x 3 0 2 3 0 fingers 0 2 0 1 3 0 }
[D7sus2/C]

outputs (for guitar) a chord with D7sus2/C frets/fingers, but displayed as C6 in both song and diagram: Suddenly_I_See_TEST2.pdf

I think this is unexpected. {define-guitar} includes no copy, so I wouldn't expect it to copy any values, e.g. display, from the earlier relevant {define}.

However, if all {define} that match the condition (guitar) are applied cumulatively regardless of copy/copyall, then it makes sense, but that might be a behaviour change, intentional or otherwise.

sciurius commented 1 year ago

Interesting!
I'm on a gig today so won't be able to take a look until tomorrow.