Body Nodes That Do Not Use A Mono-spaced Font

93 views
Skip to first unread message

Thomas Passin

unread,
Feb 14, 2023, 11:50:50 PM2/14/23
to leo-editor
Leo uses a mono-spaced font for body text.  No doubt this comes from Leo's background as a programming editor/IDE.  But many people don't use it like that, or not only like that.  They use it for creating documents, notes, or other non-programming uses.  For these uses, non-monospaced fonts can be easier to read, and also more compact.  What would be involved in making Leo use other fonts for certain nodes?

If it were for all nodes a font change would be easy: just change the font-family setting in the theme outline.  But this would make all nodes of all outlines use the same font, which is not what we want.

There is an obvious way to prevent this: subclass the body widget , which is a LeoQTextBrowser.  In the theme, add a new logical font family, and in the Qt CSS stylesheet, specify this font family for the subclassed objects.  Use this subclassed body editor for the non-mono-spaced nodes.  Easy.

The next questions are how to change the editor widget on any body node you want, and how to have Leo remember which one to use for which node when the outline is reloaded.

Changing the editor widget will probably  not be hard.  A commander could contain two of them rather than one.  All existing body editor code would still work since the subclassed widget would have the same interface as the current one.

Persisting the map between nodes and editor class - I'm not clear about the best way to do that.  It could be included when other properties are written to the sqllite database, such as the record of which nodes were expanded when an outline is saved.

Alternatively, perhaps a new directive would be the best way to handle it.  When a page is scanned for directives, if this new one is found the editor is swapped out if necessary.

To sum up, to introduce the new capability to Leo, we would need to:

1. Subclass the current body editor class;
2. Add new commands to change or restore the body editor type on a per node basis;
3. Add new commands to make the change to a subtree or the entire outline;
4. Create a way to persist the type of editor to use for nodes across save/restore actions;
5. Enhance some of the theme outlines.
6. Decide whether child nodes should inherit their parent's body editor.

Except for 4) and 6) none of this seems like it would need much effort to implement.  I'm not sure how much effort would be needed for the persistence aspect.  If child nodes should inherit their parent's editor type, that would take some careful work to make sure that all related commands pick up the alternate editor properly.

Please post here with ideas and suggestions!  Is this something that people would be interested in?

Edward K. Ream

unread,
Feb 15, 2023, 8:11:19 AM2/15/23
to leo-e...@googlegroups.com
On Tue, Feb 14, 2023 at 10:50 PM Thomas Passin <tbp1...@gmail.com> wrote:
Leo uses a mono-spaced font for body text. 

Happy, this statement is not correct. Unless I am mistaken, Leo can already do what you want.

Leo's syntax colorer sets fonts, and those fonts can depend on @language.

Please refer to leoSettings.leo#@settings-->Syntax coloring,
especially the subnode: Language-specific fonts and colors

I suspect that adding a node @font rest fonts will suffice.

Edward

Edward K. Ream

unread,
Feb 15, 2023, 8:13:57 AM2/15/23
to leo-editor
On Wednesday, February 15, 2023 at 7:11:19 AM UTC-6 Edward K. Ream wrote:

I suspect that adding a node @font rest fonts will suffice.

I should have said: add this node to myLeoSettings.leo.

Please report your experiences. It will be worthwhile to document this capability.

Edward

Thomas Passin

unread,
Feb 15, 2023, 8:53:15 AM2/15/23
to leo-editor
@ekr: "Leo uses a mono-spaced font for body text. 
Happy, this statement is not correct. Unless I am mistaken, Leo can already do what you want."

My statement was oversimplified - the body font is normally set in the stylesheet and it could be chosen to be a non-monospaced font.

Thomas Passin

unread,
Feb 15, 2023, 9:09:32 AM2/15/23
to leo-editor
@ekr:  "I suspect that adding a node @font rest fonts will suffice."

I must be missing the magic way to do this, because none of these changed the font for @language rest nodes.  I've tried:

headline: @font rest
body: font-family = Georgia

headline: @font rest
body: font-family: Georgia

headline: @font rest
body: rest_font_family = Georgia

headline: @font rest font-family: Georgia

headline: @font rest Georgia

headline: @font rest = font-family: Georgia

headline: @font rest = Georgia


Edward K. Ream

unread,
Feb 15, 2023, 10:32:48 AM2/15/23
to leo-e...@googlegroups.com
On Wed, Feb 15, 2023 at 8:09 AM Thomas Passin <tbp1...@gmail.com> wrote:
@ekr:  "I suspect that adding a node @font rest fonts will suffice."

I must be missing the magic way to do this

It looks like there is a bug somewhere. I expected the following to work:


1. Create a test node (headline doesn't matter, but mine is --- tests of @language rest) containing:

@language rest
**Bold**
plain rest text.
*Italics*

2. Save your test file with the test node selected.

3. Restart your test file with --trace=coloring in effect.

On startup, the trace will show a large trace of the configDict, containing many keys. The start of this trace will looks something like this:

configDict: {'blank': '#E5E5E5',
'comment': 'solarized-orange',
'comment.hashbang': '#408080',
...

Then you'll see the usual syntax coloring trace. Something like this:

mainLoop
NEW NODE: --- tests of @language rest

setTag: rest.leokeyword                    0  14       '@language rest' rest_main:
setTag: rest.keyword2                      0   8             '**Bold**' rest_main:match_at_language
setTag: rest.keyword4                      0   9            '*Italics*' rest_main:rest_rule14


Your task is to set these key/value pairs to your liking.

A. In myLeoSettings.leo, under the node Language-specific fonts and colors,
create an organizer node (with  rest as the headline)

B. Under this rest organizer node, create other nodes to set specific settings. Use the traces as your guide.

For example, I created the node: @color rest-keyword3-color = red
The body text doesn't matter: put any comments there you like.

Bug: settings don't affect the configDict.  I'll investigate.

Edward

Thomas Passin

unread,
Feb 15, 2023, 1:59:55 PM2/15/23
to leo-editor
This is all obscure, and doesn't appear to apply anyway.  I don't want to color the text for various keywords, I want to set the font-family for all text in the node - preferably without needing to enumerate every kind of keyword, which names I don't think are documented anywhere.

It seems that there may be some machinery the could be used in pbc.doFont(),  but when I forced the dictionary for @node rest to contain ('font-family', 'Georgia'), which would seem to be the expected contents, the font in my test node wasn't changed.  Also, the way the key/values are obtained from the @node processing makes it impossible to extract those values from the @node.  There is some magic involved here, and I'm not surprised if there's a bug.

In the standard Leo distro, those @nodes are only used for @language forth, and the Forth colorizer handler uses special bespoke classes.  So there may be a bug that the special Forth code works around but no other language hits.

Thomas Passin

unread,
Feb 15, 2023, 2:14:40 PM2/15/23
to leo-editor
Not quite true: there are a few @font php nodes too. 

Thomas Passin

unread,
Feb 15, 2023, 2:55:06 PM2/15/23
to leo-editor
The only place the jEdit colorizer does anything about fonts is this:

def getFontFromParams(self, family: Any, size: Any, slant: Any, weight: Any, defaultSize: int = 12) -> None:
    return None


That is to say, it does nothing about getting or setting fonts.

Edward K. Ream

unread,
Feb 16, 2023, 8:45:36 AM2/16/23
to leo-editor
On Wednesday, February 15, 2023 at 9:32:48 AM UTC-6 Edward K. Ream wrote:

> It looks like there is a bug somewhere.

I'll fix #3149 soon.

Edward

Thomas Passin

unread,
Feb 17, 2023, 6:00:48 PM2/17/23
to leo-editor
Here is a script so you can see if you like the effect of having a non-monospaced font for non-code bodies.  It only works for @language rest nodes. Copy the script below into a node in your workbook.  Run it with CTRL-B.  After that, any time you switch to an @language rest node, it will use the alternate font.  It hooks select3 so it won't detect if you change the @language directive until you switch nodes again.

STYLE = ('QTextBrowser {'
                'font-family: Corbel, "Opens Sans","Sans-serif";'
                'font-size: 12pt;}')
NOSTYLE = 'QTextBrowser {}'
DIRECT = '@language rest'

def set_alt_body_font(tag, keys):
    c = keys['c']
    css = NOSTYLE
    for p in c.p.self_and_parents():
        lines = p.b[:300].splitlines()  # find directive if it's not in the first line
        has_direct = [True for line in lines if line.startswith(DIRECT)]
        if DIRECT in p.h or has_direct:
            css = STYLE
            break

    editor = c.frame.body.wrapper.widget
    editor.setStyleSheet(css)

ud = g.user_dict
ud['alt_body_font_proc'] = set_alt_body_font

g.registerHandler('select3', ud['alt_body_font_proc'])



Thomas Passin

unread,
Feb 17, 2023, 8:37:30 PM2/17/23
to leo-editor
Here's an improved version that can detect more common languages -

STYLE = ('LeoQTextBrowser {'

                'font-family: Corbel, "Opens Sans","Sans-serif";'
                'font-size: 12pt;}')
NOSTYLE = 'LeoQTextBrowser {}'
DIRECT = ('@language rest', '@language md', '@language asciidoc',
          '@language text', '@language plain',
          '@rest', '@md', '@rst', '@adoc',
          ':id:', ':ref:')

def has_direct(s, h):
    lines = s[:1000].splitlines()
    for line in lines:
        for d in DIRECT:
            if h.startswith(d) or line.startswith(d):
                return True
    return False


def set_alt_body_font(tag, keys):
    c = keys['c']
    css = NOSTYLE
    for p in c.p.self_and_parents():
        if has_direct(p.b, p.h):

            css = STYLE
            break

    editor = c.frame.body.wrapper.widget
    editor.setStyleSheet(css)

ud = g.user_dict
ud['alt_body_font_proc'] = set_alt_body_font

g.registerHandler('select3', ud['alt_body_font_proc'])
On Friday, February 17, 2023 at 6:00:48 PM UTC-5 Thomas Passin wrote:
Here is a script so you can see if you like the effect of having a non-monospaced font for non-code bodies.  It only works for @language rest nodes. Copy the script below into a node in your workbook.  Run it with CTRL-B.  After that, any time you switch to an @language rest node, it will use the alternate font.  It hooks select3 so it won't detect if you change the @language directive until you switch nodes again.
[snip]

Edward K. Ream

unread,
Feb 18, 2023, 11:45:05 AM2/18/23
to leo-e...@googlegroups.com
On Fri, Feb 17, 2023 at 5:00 PM Thomas Passin <tbp1...@gmail.com> wrote:
Here is a script so you can see if you like the effect of having a non-monospaced font for non-code bodies.

Thanks, Thomas, for this work. PR #3150 is still a work in progress. It's kinda a can of worms. It might make it into the next release, but it might not.

Edward

Thomas Passin

unread,
Feb 18, 2023, 12:17:21 PM2/18/23
to leo-editor
My script could easily be turned into a light-weight plugin, and it could use settings to change fonts, etc. as well as which kinds of nodes to act on, and be able to be turned on and off.  Maybe this would be easier than straightening out the can of worms ...

Edward K. Ream

unread,
Feb 18, 2023, 1:31:57 PM2/18/23
to leo-e...@googlegroups.com
On Sat, Feb 18, 2023 at 11:17 AM Thomas Passin <tbp1...@gmail.com> wrote:
My script could easily be turned into a light-weight plugin, and it could use settings to change fonts, etc. as well as which kinds of nodes to act on, and be able to be turned on and off.  Maybe this would be easier than straightening out the can of worms ...

I think it's essential to fix the issue. It's going to take some time and it's too late for the changes to appear in Leo 6.7.2. But feel free to experiment with a plugin. You never need my permission to do that :-)

Edward
Reply all
Reply to author
Forward
0 new messages