Coverage for liitos/description_lists.py: 100.00%
35 statements
« prev ^ index » next coverage.py v7.6.10, created at 2025-01-05 17:22:35 +00:00
« prev ^ index » next coverage.py v7.6.10, created at 2025-01-05 17:22:35 +00:00
1"""Apply any option command to subsequent description environment.
3Implementation Note: The empty string marker is used to indicate absence of option command.
4"""
6from collections.abc import Iterable
7from enum import Enum
8from typing import Union
10from liitos import log
12Modus = Enum('Modus', 'COPY OPTION')
13NO_OPTION: str = ''
15OPTION_STARTT_TRIGGER_STARTSWITH = r'\option['
16DESCRIPTION_START_TRIGGER_STARTSWITH = r'\begin{description}'
19def filter_seek_option(line: str, slot: int, modus: Modus, opt: str, outgoing: list[str]) -> tuple[Modus, str]:
20 r"""Filter line, seek for an option command, and return updated mnodus, opt pair.
22 Examples:
24 >>> filtered = []
25 >>> m, opt = filter_seek_option(r'\option[]', 0, Modus.COPY, NO_OPTION, filtered)
26 >>> assert not filtered
27 >>> assert m == Modus.OPTION
28 >>> assert opt == '[]'
30 >>> filtered = []
31 >>> m, opt = filter_seek_option('foo', 0, Modus.COPY, NO_OPTION, filtered)
32 >>> assert filtered == ['foo']
33 >>> assert m == Modus.COPY
34 >>> assert opt == NO_OPTION
36 >>> filtered = []
37 >>> m, opt = filter_seek_option(r'\option[foo=bar]', 0, Modus.COPY, NO_OPTION, filtered)
38 >>> assert not filtered
39 >>> assert m == Modus.OPTION
40 >>> assert opt == '[foo=bar]'
41 """
42 if line.startswith(OPTION_STARTT_TRIGGER_STARTSWITH):
43 log.info(f'trigger an option mod for the next description environment at line #{slot + 1}|{line}')
44 opt = '[' + line.split(OPTION_STARTT_TRIGGER_STARTSWITH, 1)[1].strip()
45 modus = Modus.OPTION
46 log.info(f' -> parsed option as ({opt})')
47 else:
48 outgoing.append(line)
50 return modus, opt
53def filter_seek_description(line: str, slot: int, modus: Modus, opt: str, outgoing: list[str]) -> tuple[Modus, str]:
54 r"""Filter line, seek for a description, add options if applicable, and return updated mnodus, option pair.
56 Examples:
58 >>> filtered = []
59 >>> m, opt = filter_seek_description('quux', 0, Modus.OPTION, '[foo=bar]', filtered)
60 >>> assert filtered == ['quux']
61 >>> assert m == Modus.OPTION
62 >>> assert opt == '[foo=bar]'
64 >>> filtered = []
65 >>> m, opt = filter_seek_description(r'\begin{description}', 0, Modus.OPTION, NO_OPTION, filtered)
66 >>> assert filtered == [r'\begin{description}']
67 >>> assert m == Modus.COPY
68 >>> assert opt == NO_OPTION
70 >>> filtered = []
71 >>> m, opt = filter_seek_description(r'\begin{description}', 0, Modus.OPTION, '[foo=bar]', filtered)
72 >>> assert filtered == [r'\begin{description}[foo=bar]']
73 >>> assert m == Modus.COPY
74 >>> assert opt == NO_OPTION
75 """
76 if line.startswith(DESCRIPTION_START_TRIGGER_STARTSWITH):
77 if opt != NO_OPTION:
78 log.info(f'- found the option target start at line #{slot + 1}|{line}')
79 outgoing.append(f'{DESCRIPTION_START_TRIGGER_STARTSWITH}{opt}')
80 else:
81 outgoing.append(line)
82 modus = Modus.COPY
83 opt = NO_OPTION
84 else:
85 outgoing.append(line)
87 return modus, opt
90def options(incoming: Iterable[str], lookup: Union[dict[str, str], None] = None) -> list[str]:
91 r"""Later alligator. \option[style=multiline,leftmargin=6em]
93 Examples:
95 >>> in_opts = '[style=multiline,leftmargin=6em]'
96 >>> opt_line = f'\\option{in_opts}'
97 >>> beg_desc = '\\begin{description}'
98 >>> lines_in = ['a', '', opt_line, '', beg_desc, 'whatever']
99 >>> lines_in
100 ['a', '', '\\option[style=multiline,leftmargin=6em]', '', '\\begin{description}', 'whatever']
101 >>> processed = options(lines_in)
102 >>> processed
103 ['a', '', '', '\\begin{description}[style=multiline,leftmargin=6em]', 'whatever']
104 """
105 outgoing: list[str] = []
106 modus = Modus.COPY
107 opt = NO_OPTION
108 for slot, line in enumerate(incoming):
109 if modus == Modus.COPY:
110 modus, opt = filter_seek_option(line, slot, modus, opt, outgoing)
111 else: # if modus == Modus.OPTION:
112 modus, opt = filter_seek_description(line, slot, modus, opt, outgoing)
114 return outgoing