On Thu, Nov 13, 2025 at 5:46 PM Charlie Ma <[email protected]> wrote:
>
> This is a very helpful deep dive. As an occasional user, and still a newb, I 
> greatly benefit from this demonstration of stepping through the docs. Thank 
> you.
> But you’d need to be a programmer to understand how to trace through these 
> functions as you did here. (Fortunately I am one, though not with scheme).
> This highlights a gap in LilyPond documentation and usability.
>
> Also I think you meant to demonstrate this use of Internals as an 
> alternative, or improvement, over googling (which Shane did to find 
> “stringOneTopmost”). But your effort started with the answer he already found.
> It begs the question how one would have found this, via the docs, if one only 
> started with the idea: “I want the highest sounding string on the bottom 
> line.”
>

There's no question that there is a gap in LilyPond documentation.
Actually. it's an intentional gap.  If we had every possible variation
shown in the Notation Reference, the NR would be at least ten times
the size that it is now.  Of course, with search tools, we could
easily search the NR.  But somebody would have to write all those NR
sections, and we don't have anybody to do that.  As I mentioned, this
particular search is one of the hardest I know of -- because the
layout object you expect to have a property to change the behaviour
(the StaffSymbol for the TabStaff context) doesn't actually have the
property you need.  One needs to think carefully about where the
changes would need to happen to have what you'd like to see (the
TabNoteHead shows up on a different line, so the property affects
TabNoteHead, not StaffSymbol).

Let me try to show you how I would have done it.

The question -- I want to have the string with the highest pitch on
the bottom of my tablature.  I wonder how I can do that?

Let's see.  I need to change the way a tabulature staff is displayed.I
wonder what properties I can find about tabulature staffs.  Oh, I
know, I'll go to the Internals Reference, and  look up all the
properties of tab staffs.  OK, now I need to decide -- am I looking
for a context property or a layout object property.  TabStaff is a
context, so maybe it's a context property.  But TabStaff is not the
thing on the paper; I don't know what that output object is.  How can
I figure it out?

Let me go to the think I know about, the TabStaff Context.  That's
section 2.1 of the Internals Reference:

https://lilypond.org/doc/v2.24/Documentation/internals/contexts

Looking on that page, I see 2.1.36 TabStaff.  Let me go there:

https://lilypond.org/doc/v2.24/Documentation/internals/tabstaff

Look at the context properties set by the context.  Nothing seems
related to my problem.

Look at the grob properties set by the context.  They are set for a
number of different grobs.  Do any of them look promising?  Nope, but
I do see that there is a property that affects a TabNoteHead.  So at
least the context knows about TabNoteHead.  So far, nothing useful.

Now let me look at the engravers.  Two seem possibly promising:
Staff_symbol_engraver -- it creates the staff lines;
Tab_staff_symbol_engraver -- creates a tab staff symbol and looks at
stringTunings.  Let me jump first into the Tab_staff_symbol engraver,
because it is tablature specific:

https://lilypond.org/doc/v2.24/Documentation/internals/tab_005fstaff_005fsymbol_005fengraver

Hmm -- only stringTunings there.  Not particularly helpful.   But it
links to StaffSymbol.  So let me follow it.

https://lilypond.org/doc/v2.24/Documentation/internals/staffsymbol

Lots of properties there.  None looks helpful.  Let me scratch my
head, and think about it.  How would the tablature staff look
different if the highest-pitch string were on the bottom?  I guess it
wouldn't look any different.  Just a certain number of lines.  Oh,
yeah, the doc on the Tab_staff_symbol_engraver said that it read
stringTunings to determine the number of lines in a tab staff.  But it
didn't say anything about pitches.  So maybe the StaffSymbol doesn't
actually know about pitches.

I'm stuck.  What to do?  Here are two possible cases:

Case 1:
What changes when we put the highest pitch string on the bottom of the
TabStaff? The vertical location of the TabNoteHead.  So let's look at
the TabNoteHead layout object (grob).  IR. 3.1 All Layout Objects:

https://lilypond.org/doc/v2.24/Documentation/internals/all-layout-objects

Oh.  There I see 3.1.11 TabNoteHead

https://lilypond.org/doc/v2.24/Documentation/internals/tabnotehead

Look at the properties.  None of the properties seem to make sense.
But the object is created by the Tab_note_heads_engraver.  So let me
follow that link.

https://lilypond.org/doc/v2.24/Documentation/internals/tab_005fnote_005fheads_005fengraver

Now look at the properties.  Lots of potentially-interesting properties:

highStringOne (boolean)stringOneTopmost (boolean)

stringTunings (list)

All of these properties affect automatic tablature calculations.  I
might be able to figure out from these what I should do.

highStringOne -- tells me if the highest pitch string is string one.
In this case, it is, so highStringOne should be true.
stringTunings -- we've already set the stringTunings as we want it.
stringOneTopmost -- oh, we don't want stringOneTopmost, so we should
set this to false.

Now, we can't set properties in engravers; we must either do it in
grobs or contexts.  We might want to set it in the TabNoteHead grob;
but the TabNoteHead grob doesn't support this property.  So let's look
for a good context.  We could use the TabVoice context (the
Tab_note_heads_engraver lives in the TabVoice context), but we
wouldn't want to have different TabVoice contexts in the same TabStaff
to have different settings of this property.  So I think we should put
it in the TabStaff context.  And when we try that, it works.

Case 2:
I have no idea what to change.  So let me look at all of the layout
object properties (Internals Reference 3.3 User Backend Properies)

https://lilypond.org/doc/v2.24/Documentation/internals/user-backend-properties

Lots of properties.  How can I search them?  What if I search in this
page for tab?  One property -- double-stem-separation, which applies
to tab stems.  Not applicable.

So let's look at all context properties (Internals Reference 2.3
Tunable Context Properties):

https://lilypond.org/doc/v2.24/Documentation/internals/tunable-context-properties

Again, search in the page for tab. THis is helpful:

highStringOne (boolean)

Whether the first string is the string with highest pitch on the
instrument. This used by the automatic string selector for tablature
notation.


stringOneTopmost (boolean)

Whether the first string is printed on the top line of the tablature.

stringTunings (list)

The tablature strings tuning. It is a list of the pitches of each
string (starting with the lowest numbered one).

These properties can now help me to think about what I want.  Is
string one the highest pitch?  Yes.  So this should be true

Is the first string printed on the top line of the tablature?  No.  So
this should be false.  And we know it's a context property, so we try
to decide the context to use, and TabStaff seems to make the most
sense.  Let's try it.  And it works.

I know this is difficult.  But it's doable.  And as you develop the
skill to do this, it becomes easier and easier to have LilyPond do
what you want, no matter how non-standard it is.

It takes practice.  But I think it's worth it.

Thanks,

Carl

Reply via email to