Two independent changes:

1) formatter_functions.py: change a quoted string to an italic string so it is the same as in other functions.

2) ffml_processor.py: use look ahead in the parser to detect parse nodes with text that can be inlined.
This commit is contained in:
Charles Haley 2025-07-23 12:49:28 +01:00
parent 3b094d798c
commit 9f195c761e
2 changed files with 31 additions and 11 deletions

View File

@ -576,6 +576,16 @@ class FFMLProcessor:
'\\': NodeKinds.CHARACTER '\\': NodeKinds.CHARACTER
} }
can_be_inlined = ( NodeKinds.CODE_TEXT,
NodeKinds.ITALIC_TEXT,
NodeKinds.BOLD_TEXT,
NodeKinds.END_SUMMARY,
NodeKinds.GUI_LABEL,
NodeKinds.REF,
NodeKinds.URL,
NodeKinds.CHARACTER
)
def __init__(self): def __init__(self):
self.document = DocumentNode() self.document = DocumentNode()
self.input = None self.input = None
@ -584,11 +594,10 @@ class FFMLProcessor:
def error(self, message): def error(self, message):
raise ValueError(f'{message} on line {self.input_line} in "{self.document_name}"') raise ValueError(f'{message} on line {self.input_line} in "{self.document_name}"')
def find(self, for_what): def find(self, for_what, at_pos=-1):
p = self.input.find(for_what, self.input_pos) pos = at_pos if at_pos >= 0 else self.input_pos
if p < 0: p = self.input.find(for_what, pos)
return -1 return -1 if p < 0 else p - pos
return -1 if p < 0 else p - self.input_pos
def move_pos(self, to_where): def move_pos(self, to_where):
for c in self.input[self.input_pos:self.input_pos+to_where]: for c in self.input[self.input_pos:self.input_pos+to_where]:
@ -614,13 +623,14 @@ class FFMLProcessor:
def startswith(self, txt): def startswith(self, txt):
return self.input.startswith(txt, self.input_pos) return self.input.startswith(txt, self.input_pos)
def find_one_of(self): def find_one_of(self, at_pos=-1):
positions = [] positions = []
pos = at_pos if at_pos >= 0 else self.input_pos
for s in self.keywords: for s in self.keywords:
p = self.find(s) p = self.find(s, pos)
if p == 0: if p == 0:
return self.keywords[s] return self.keywords[s]
positions.append(self.find(s)) positions.append(p)
positions = list(filter(lambda x: x >= 0, positions)) positions = list(filter(lambda x: x >= 0, positions))
if positions: if positions:
return min(positions) return min(positions)
@ -731,8 +741,18 @@ class FFMLProcessor:
p = self.find_one_of() p = self.find_one_of()
if p > 0: if p > 0:
txt = self.text_to(p) txt = self.text_to(p)
txt = txt[:-1].replace('\n', ' ') + txt[-1] if txt != '\n':
parent.add_child(TextNode(txt)) # Look ahead to see if the next parse node's text can be
# inline with this text. If so, change a trailing newline
# to a trailing space.
last_char = txt[-1]
txt = txt[:-1].replace('\n', ' ')
if last_char == '\n' and self.find_one_of(self.input_pos + p) in self.can_be_inlined:
last_char = ' '
parent.add_child(TextNode(txt + last_char))
else:
# Bare newlines are passed through unchanged
parent.add_child(TextNode(txt))
self.move_pos(p) self.move_pos(p)
elif p == NodeKinds.BLANK_LINE: elif p == NodeKinds.BLANK_LINE:
parent.add_child(BlankLineNode()) parent.add_child(BlankLineNode())

View File

@ -2445,7 +2445,7 @@ r'''
``virtual_libraries()`` -- return a comma-separated list of Virtual libraries that ``virtual_libraries()`` -- return a comma-separated list of Virtual libraries that
contain this book.[/] This function works only in the GUI. If you want to use these contain this book.[/] This function works only in the GUI. If you want to use these
values in save-to-disk or send-to-device templates then you must make a custom values in save-to-disk or send-to-device templates then you must make a custom
"Column built from other columns", use the function in that column's template, `Column built from other columns`, use the function in that column's template,
and use that column's value in your save/send templates. and use that column's value in your save/send templates.
''') ''')