def post_ledger_action(self) -> Path:
"""Call .server.ledger.(move|copy|add_empty_new)_booking."""
+ if 'remove_redundant_empty_lines' in self.postvars.as_dict:
+ self.server.ledger.remove_redundant_empty_lines()
+ return Path(self.path)
if 'add_booking' in self.postvars.as_dict:
id_ = self.server.ledger.add_empty_block()
else:
Path('/').joinpath(_PAGENAME_EDIT_STRUCTURED
).joinpath(self.path_toks[2]))
return
- ctx = {'unsaved_changes': self.server.ledger.tainted, 'path': self.path}
+ ctx = {'unsaved_changes': self.server.ledger.tainted,
+ 'path': self.path}
if self.pagename == 'balance':
self.get_balance(ctx)
elif self.pagename.startswith(_PREFIX_EDIT):
def get_ledger(self, ctx: dict[str, Any], raw: bool) -> None:
"""Display ledger of all Bookings."""
ctx['blocks'] = self.server.ledger.blocks
+ ctx['has_redundant_empty_lines'] =\
+ self.server.ledger.has_redundant_empty_lines
self._send_rendered(
_PAGENAME_LEDGER_RAW if raw else _PAGENAME_LEDGER_STRUCTURED, ctx)
"""Return as how to be written in .dat file's text content."""
comment_part = ' ; '.join([''] + [s for s in [self.comment] if s])
code_part = f'{self.code} ' if self.code else ''
- return f'{code_part}{comment_part.lstrip()}'
+ return f'{code_part}{comment_part.lstrip()}'.rstrip()
def copy(self) -> Self:
"""Create new instance copying the fields named in .to_copy."""
"""Grow self by lines."""
self._lines += lines
+ @property
+ def redundant_empty_lines(self):
+ """If self has more empty lines than necessary."""
+ redundancies = []
+ prev_line = None
+ idx_last_non_empty = -1
+ for idx, line in enumerate(self._lines):
+ if line.comment:
+ idx_last_non_empty = idx
+ elif '' == prev_line and not line.comment:
+ redundancies += [line]
+ prev_line = line
+ redundancies += [line for line in self._lines[idx_last_non_empty + 2:]
+ if line not in redundancies]
+ return redundancies
+
+ def remove_redundant_empty_lines(self):
+ """From self remove redundant empty lines."""
+ for line in self.redundant_empty_lines:
+ self._lines.remove(line)
+
class _Booking(_LinesBlock[_BookingLine]):
return False
return True
+ @property
+ def has_redundant_empty_lines(self) -> bool:
+ """If any gaps have redunant empty lines."""
+ return bool([b for b in self.blocks if b.gap.redundant_empty_lines])
+
+ def remove_redundant_empty_lines(self) -> None:
+ """From all .blocks remove redundant empty lines."""
+ for gap in [b.gap for b in self.blocks if b.gap.redundant_empty_lines]:
+ gap.remove_redundant_empty_lines()
+
@property
def tainted(self) -> bool:
"""If ._dat_lines different to those of last .load()."""
+{% macro ledger_empty_lines_fix(has_redundant_empty_lines) %}
+{% if has_redundant_empty_lines %}
+ Detected redundant empty lines in gaps, <input type="submit" name="remove_redundant_empty_lines" value="fix?" />
+ <hr />
+{% endif %}
+{% endmacro %}
+
+
+
{% macro ledger_block_columns(mode, block) %}
<tr></tr><!-- just to keep the background-color alternation in proper order -->
<tr id="block_{{block.id_}}">
{% block content %}
<form action="/ledger_raw" method="POST">
+{{macros.ledger_empty_lines_fix(has_redundant_empty_lines)}}
<table class="alternating">
{% for block in blocks %}
{{macros.ledger_block_columns('raw', block)}}
{% block content %}
<form action="/ledger_structured" method="POST">
+{{macros.ledger_empty_lines_fix(has_redundant_empty_lines)}}
<table class="alternating">
{% for block in blocks %}
{{macros.ledger_block_columns('structured', block)}}