Here is a version that will highlight the current line for all outlines 
that are open at the time you run the script.  Open the outline, select the 
top-level node, and press <CTRL-b>.  If you open any other outlines after 
this, you will need to run it again. 

As a reminder, you can override the highlight color with a CSS color value 
of your choice by using the *@string line-highlight-color *setting.  
Standard colors like *blue*  are understood, and also numerical values like 
*#234567*.  Other color expressions are not understood.

I expect line highlighting to get into Leo right after 6.4 is released - no 
more need to run a batch file.  It's working well on my system.

On Friday, August 27, 2021 at 9:45:12 AM UTC-4 [email protected] wrote:

> Here is the current version of the script, after some cleanup and 
> reorganization, and one change to get it to work under PyQt6.11 as well as 
> PyQt5.
>
> On Thursday, August 26, 2021 at 6:49:14 PM UTC-4 [email protected] wrote:
>
>> I now have reasonable colors for highlighting of very dark and very light 
>> themes, as well as for no-theme color schemes that forgot to set the 
>> background color.
>>
>> On Thursday, August 26, 2021 at 5:25:26 PM UTC-4 [email protected] wrote:
>>
>>> @ekr asked me to see about getting Leo's body editor to highlight the 
>>> current line.  This was in response to a request in Issue 2150 
>>> <https://github.com/leo-editor/leo-editor/issues/2150>.  I've made some 
>>> progress, which I report here.  I'd say it's about 3/4 of the way there.
>>>
>>> I have a working script that, when run, highlights the cursor line in 
>>> the visible node's body.  Here's what is left to do:
>>>
>>> 1. The highlight color isn't visible for very dark or very light 
>>> background colors.  Currently the highlight color is a modification of the 
>>> text background color as specified in the theme's stylesheet.  The way this 
>>> color is arrived at needs to be improved .  And I'm not yet sure how to 
>>> handle the case where no theme at all is in use (some people have tweaked 
>>> Leo's colors without using a theme).
>>>
>>> The highlight color scheme works well with the three 
>>> tbp_xxx_solarized.leo themes.
>>>
>>> 2. The code needs to have a proper home.  Presumably this will be in the 
>>> qt_text.py plugin.
>>>
>>> 3. The code needs to be hooked up to the body's cursor events so that 
>>> the highlight code knows that it has to change lines.
>>>
>>> Also, as a longer term matter, the code does not use any wrappers or 
>>> abstractions, so it will only work for Qt-based Guis.  This can be 
>>> addressed later, if it appears that there might be a viable non-Qt Gui 
>>> version of Leo.
>>>
>>> I've attached the current version of the code.  Open it in Leo.  Select 
>>> a line in the top node.  Run the script by pressing CTRL-b.  The current 
>>> line should highlight, although you may not be able to see it if you are 
>>> using a very dark or light theme, including Leo's default theme.  Put the 
>>> cursor on a different line in the same body.  Press CTRL-b again.  The 
>>> highlight should shift to the new cursor line.
>>>
>>> Please let me know if you find any problems (apart from the actual 
>>> highlight color).
>>>
>>

-- 
You received this message because you are subscribed to the Google Groups 
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/leo-editor/bd946f07-0539-43b4-8300-ade6f8f54b92n%40googlegroups.com.
<?xml version="1.0" encoding="utf-8"?>
<!-- Created by Leo: http://leoeditor.com/leo_toc.html -->
<leo_file xmlns:leo="http://leoeditor.com/namespaces/leo-python-editor/1.1"; >
<leo_header file_format="2"/>
<vnodes>
<v t="tom.20210827170535.1"><vh>Highlight Current Line</vh>
<v t="tom.20210827170535.2"><vh>highlightCurrentLine</vh>
<v t="tom.20210827170535.3"><vh>parse_css</vh></v>
<v t="tom.20210827170535.4"><vh>assign_bg</vh></v>
<v t="tom.20210827170535.5"><vh>calc_hl</vh></v>
</v>
</v>
</vnodes>
<tnodes>
<t tx="tom.20210827170535.1">@language python
from leo.core.leoQt import QtGui
QColor = QtGui.QColor
FullWidthSelection = 0x06000 # works for both Qt5 and Qt6

@others

for cc in g.app.commanders():
    w = cc.frame.body.wrapper
    editor = w.widget
    editor.cursorPositionChanged.connect(highlightCurrentLine)</t>
<t tx="tom.20210827170535.2">@language python
def highlightCurrentLine():
    """Highlight cursor line.
    
    Based in part on code from
    https://doc.qt.io/qt-5/qtwidgets-widgets-codeeditor-example.html
    """

    ssm = c.styleSheetManager
    sheet = ssm.expand_css_constants(c.active_stylesheet)

    bg = c.config.getString('line-highlight-color') or ''
    hl_color = QColor(bg)
    if hl_color.getHsv() == (0, 0, 0, 255) and bg != 'black':
        # Always returns black for an invalid color
        # So compute the color instead
        fg, bg = parse_css(sheet, 'QTextEdit')
        bg_color = QColor(bg) if bg else assign_bg(fg)
        hl_color = calc_hl(bg_color)

    selection = editor.ExtraSelection()
    selection.format.setBackground(hl_color)
    selection.format.setProperty(FullWidthSelection, True)
    selection.cursor = editor.textCursor()
    selection.cursor.clearSelection()

    editor.setExtraSelections([selection])
</t>
<t tx="tom.20210827170535.3">@language python
def parse_css(css_string, clas=''):
    """Extract colors from a css stylesheet string. 
    
    This is an extremely simple-minded function. It assumes
    that no quotation marks are being used, and that the
    first block in braces with the name clas is the controlling
    css for our widget.
    
    Returns a tuple of strings (foregound, background).
    """
    # Get first block with name matching "clas'
    block = css_string.split(clas, 1)
    block = block[1].split('{', 1)
    block = block[1].split('}', 1)

    # Split into styles separated by ";"
    styles = block[0].split(';')

    # Split into fields separated by ":"
    fields = [style.split(':') for style in styles if style.strip()]

    # Only get fields whose names are "color" and "background"
    color = bg = ''
    for style, val in fields:
        style = style.strip()
        if style == 'color':
            color = val.strip()
        elif style == 'background':
            bg = val.strip()
        if color and bg:
            break
    return color, bg

</t>
<t tx="tom.20210827170535.4">@language python
def assign_bg(fg):
    """If fg or bg colors are missing, assign
    reasonable values.  Can happen with incorrectly
    constructed themes, or no-theme color schemes.
    
    RETURNS
    a QColor object for the background color
    """
    if not fg:
        fg = 'black' # QTextEdit default
        bg = 'white' # QTextEdit default
    if fg == 'black':
        bg = 'white' # QTextEdit default
    else:
        fg_color = QColor(fg)
        h, s, v, a = fg_color.getHsv()
        if v &lt; 128: # dark foreground
            bg = 'white'
        else:
            bg = 'black'
    return QColor(bg)
</t>
<t tx="tom.20210827170535.5">@language python
def calc_hl(bg_color):
    """Return the line highlight color.
    
    ARGUMENT
    bg_color -- a QColor object for the background color
    
    RETURNS
    a QColor object for the highlight color
    """
    h, s, v, a = bg_color.getHsv()

    if v &lt; 40:
        v = 60
        bg_color.setHsv(h, s, v, a)
    elif v &gt; 240:
        v = 220
        bg_color.setHsv(h, s, v, a)
    elif v &lt; 128:
        bg_color = bg_color.lighter(130)
    else:
        bg_color = bg_color.darker(130)

    return bg_color
</t>
</tnodes>
</leo_file>

Reply via email to