Here is the code for the command that I mentioned before, to go to a node
and insert a backlink in the target node. I put this code into an @setting
node with the headline:
@command zettel-goto-node @key=Alt+F6
The @setting node goes into the myLeoSettings.leo file.
This code could use a bit more work. The main thing is that it may reorder
the metadata lines in a zettel node. This does not change any behavior,
but I like to have those lines in a particular order. I like them to start
with the node id, then a timestamp, like this:
:id: TomP.20200221124629.1
:timestamp: 02/22/2020 08:24:58
:link: TomP.20200221221759.1 TM4J
:link: TomP.20200223153257.1
The order may get changed when the code inserts a new backlink in the
target node because one did not exist before.
I decided to have the link meta-lines have optional labels, because they
help you know which links goes where. In the older paper-based system,
identifiers generally looked like this (from
https://www.lesswrong.com/posts/NfdHG6oHBJ8Qxc26s/the-zettelkasten-method-1
):
"I might have a train of thought which goes across cards 11, 11a, 11b,
11b1, 11b1a, 11b1a1, 18, 18a…"
All well and good, but a few months later, if you see "11b1a1" in a link,
you probably won't know what it goes to. You would have to fish around
trying all the link references in your zettel to see which ones you might
be interested it.
Using an optional label seems better.
--
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/4c34df33-c030-400a-918d-5866aa789c44%40googlegroups.com.
# Get gnx (node id) of target node from the ":link:" line of this node,
# insert a backlink to this node in the target if the target does not have one,
# and jump to the target node.
# Does nothing if cursor is not on a line starting with ":link:".
# If the backlink exists on the target node, but it has no label, then
# add a label. The :link: specifier line is expected to look like this:
# :link: TomP.20200223153257.1 About Leo
# The "About Leo" part is the label. If a label on the backlink exists,
# it is not changed, but if the link has no label, then one is constructed
# from the headline of the node.
def get_gnx_from_link(line):
line = line.lstrip()
is_link_line = line.startswith(':link:')
gnx = ''
label = ''
if is_link_line:
splits = line.split(':link:')
if len(splits) > 1:
fields = splits[1].split()
gnx = fields[0]
label = ' '.join(fields[1:]) if len(fields) > 1 else ''
return gnx, label
# List of line(s) containing cursor or selection
cursor_lines = c.getBodyLines()[1]
line = cursor_lines[0] if cursor_lines else ''
line = line.lstrip()
gnx, sending_label = get_gnx_from_link(line)
if gnx:
start_gnx = p.gnx
node_label = p.h
if node_label.startswith('@'):
node_label = ' '.join(node_label.split()[1:])
start_link = f':link: {start_gnx}'
start_link_label = f'{start_link} {node_label}'
_found_target = False
for _p in c.all_unique_positions():
if _p.gnx == gnx:
c.selectPosition(_p)
_found_target = True
break
if _found_target:
lines = _p.b.split('\n')
# Three cases for backlinks to sending node:
# 1. Sending node has no backlink
# 2. Sending node has backlink, but the backlink has no label
# 3. Sending node has backlink with label.
got_start_link = False
for i, line in enumerate(lines):
line = line.lstrip()
if not line.startswith(':link:'): continue
if start_link in line:
got_start_link = True
# case 2
if start_link == line:
lines[i] = start_link_label
_p.b = '\n'.join(lines)
else:
# Case 3
pass
break
if not got_start_link:
# case 1
_p.b = f'{start_link_label}\n{_p.b}'