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
