Search for node by GNX with g.findGnx

91 views
Skip to first unread message

lewis

unread,
Jul 18, 2023, 7:15:15 AM7/18/23
to leo-editor
Using this script to search for a node by a Gnx:

GNX_ID: str = g.app.gui.runAskOkCancelStringDialog(c,'SEARCH Node by GNX',"Enter search GNX: ").strip()
p0 = g.findGnx(GNX_ID, c)  # moves to position p0
g.es_clickable_link(c, p0, 0, (p0.h))  # clickable-link, use p.h


If the node matching GNX is empty (no body text) it displays a persistent clickable link in Log pane.

However if the node matching GNX contains body text it gives errors:
    is_sentinel: can not happen. delims: (None, '<!--', '-->')
    is_sentinel: can not happen. delims: (None, '<!--', '-->')
    is_sentinel: can not happen. delims: (None, '<!--', '-->')
    is_sentinel: can not happen. delims: (None, '<!--', '-->')
   
A clickable link displays in Log pane but when pressed the link is not persistent, the clickable link disappears and the errors repeat.

Edward K. Ream

unread,
Jul 18, 2023, 7:33:33 AM7/18/23
to leo-e...@googlegroups.com
On Tue, Jul 18, 2023 at 6:15 AM lewis <lewi...@fastmail.com.au> wrote:
Using this script to search for a node by a Gnx:

GNX_ID: str = g.app.gui.runAskOkCancelStringDialog(c,'SEARCH Node by GNX',"Enter search GNX: ").strip()
p0 = g.findGnx(GNX_ID, c)  # moves to position p0
g.es_clickable_link(c, p0, 0, (p0.h))  # clickable-link, use p.h


If the node matching GNX is empty (no body text) it displays a persistent clickable link in Log pane.

Your script should ensure that p0 is not None.

GNX_ID may not be correct, but that depends on what you entered.

The following @button script works for me, regardless of p (or p.b):

g.es_clickable_link(c, p, 0, p.h)

Edward

lewis

unread,
Jul 18, 2023, 8:11:38 AM7/18/23
to leo-editor
On Tuesday, July 18, 2023 at 9:33:33 PM UTC+10 Edward K. Ream wrote:
GNX_ID may not be correct, but that depends on what you entered.
I know that the GNX_ID is correct as I have used (p.v.gnx) to get the GNX.

The following @button script works for me, regardless of p (or p.b):

g.es_clickable_link(c, p, 0, p.h)

Edward

Have you used 
p0 = g.findGnx(GNX_ID, c)  # moves to position p0
to replicate the issue? I do not have the same errors and the clickable link persists if script searches for node by node name using:
p = g.findNodeAnywhere(c, node_name)

Lewis

Edward K. Ream

unread,
Jul 18, 2023, 9:20:47 AM7/18/23
to leo-e...@googlegroups.com
On Tue, Jul 18, 2023 at 7:11 AM lewis <lewi...@fastmail.com.au> wrote:

Have you used 
p0 = g.findGnx(GNX_ID, c)  # moves to position p0
to replicate the issue?

No. Why should I?  The problem is with GNX_ID.

execute-script with the following works for me:

print(p)
prev = p.back()
gnx = prev.gnx
p0 = g.findGnx(gnx, c)  # moves to position p0
print(p0)

The result:

<pos 2813234759936 childIndex: 7 lvl: 0 key: 2813208689856:7 --- response re script error>
<pos 2813234779584 childIndex: 7 lvl: 0 key: 2813208689856:7 --- response re script error>
<pos 2813235231360 childIndex: 7 lvl: 0 key: 2813208689856:7 --- response re script error>
<pos 2815272710784 childIndex: 6 lvl: 0 key: 2813207467584:6 Recent code>


This is your scripting problem, not mine.

Edward

Thomas Passin

unread,
Jul 18, 2023, 3:58:56 PM7/18/23
to leo-editor
The problem here is not with findGnx() or es_clickable_link().  The problem is that  g.app.gui.runAskOkCancelStringDialog(c,'SEARCH Node by GNX',"Enter search GNX: ") is failing to find an existing gnx.  Checking to see if it has returned None or not will prevent a exception, but the failure is a bug.

This statement is based on the one  test case I ran, in which I got the gnx into the clipboard and pasted it from there into the dialog.

Thomas Passin

unread,
Jul 18, 2023, 4:07:43 PM7/18/23
to leo-editor
I didn't word that right. I meant that the string returned by the dialog isn't a gnx string that can be found.  In my test case, the gnx in the clipboard started with "gnx:" When I manually removed the "gnx:" prefix, @Lewis's script ran correctly. 

Edward K. Ream

unread,
Jul 18, 2023, 4:16:31 PM7/18/23
to leo-e...@googlegroups.com
On Tue, Jul 18, 2023 at 3:07 PM Thomas Passin <tbp1...@gmail.com> wrote:
I didn't word that right. I meant that the string returned by the dialog isn't a gnx string that can be found.  In my test case, the gnx in the clipboard started with "gnx:" When I manually removed the "gnx:" prefix, @Lewis's script ran correctly. 

Thanks for your analysis. The OP might be better off using g.findAnyUnl.

Edward

Thomas Passin

unread,
Jul 18, 2023, 5:08:24 PM7/18/23
to leo-editor
I think that findGnx() should work whether or not the string starts with the "gnx:" prefix.

Edward K. Ream

unread,
Jul 18, 2023, 5:25:29 PM7/18/23
to leo-e...@googlegroups.com
On Tue, Jul 18, 2023 at 4:08 PM Thomas Passin <tbp1...@gmail.com> wrote:
I think that findGnx() should work whether or not the string starts with the "gnx:" prefix.

That would be another function. I'm not going to change anything just because people are confused.

Why are we discussing this? Copy a gnx-base unl from the status area. Paste into body text. Ctrl-click.

Or understand the existings functions.

Edward

lewis

unread,
Jul 20, 2023, 9:06:14 AM7/20/23
to leo-editor
@tbpassin thanks for your observation that the script works. Occasionally I use the script to locate a Gnx that appears in a console ouput.

From Leo's glossary on Gnx:
 Such gnx’s permanently and uniquely identify nodes. Gnx’s have the form:
id.yyyymmddhhmmss
id.yyyymmddhhmmss.n


So it seemed reasonable to me that if I enter such a Gnx that g.findGnx would work.

Thomas Passin

unread,
Jul 20, 2023, 10:21:45 AM7/20/23
to leo-editor
I'm inclined to agree.

Edward K. Ream

unread,
Jul 20, 2023, 12:43:54 PM7/20/23
to leo-e...@googlegroups.com
On Thu, Jul 20, 2023 at 9:21 AM Thomas Passin <tbp1...@gmail.com> wrote:
I'm inclined to agree.

Functions do what they do, regardless of their names or docstrings :-)

If you want to know what they are guaranteed to do, look at their unit tests.

Edward

vitalije

unread,
Jul 21, 2023, 2:57:16 AM7/21/23
to leo-editor
By the way, I've just looked at g.findGnx it uses c.all_unique_positions to visit all positions (skipping sub-trees of clones) and checking if the gnx matches. There is much faster way to generate all positions having same vnode. It is called c.all_positions_for_v(v).

# to find a position of a v-node with the given gnx
# all you really need to do is
v = c.fileCommands.gnxDict[gnx]
p = next(c.all_positions_for_v(v))

This is a generator and it visits all parents, grand parents, grand grand parents, ... and their direct children (complexity O(log n)), not all unique positions in the outline (which would have complexity of O(n)).

jkn

unread,
Jul 21, 2023, 3:13:24 AM7/21/23
to leo-editor
Hmm - I know there is a smiley here, but ... really?

Seems like a rather tautological approach to code and testing quality to me.

    J^n
Reply all
Reply to author
Forward
0 new messages