moops 0.7.1__tar.gz → 0.7.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {moops-0.7.1 → moops-0.7.2}/PKG-INFO +1 -1
- {moops-0.7.1 → moops-0.7.2}/pyproject.toml +1 -1
- {moops-0.7.1 → moops-0.7.2}/src/moops/interface.py +50 -2
- {moops-0.7.1 → moops-0.7.2}/README.md +0 -0
- {moops-0.7.1 → moops-0.7.2}/src/moops/__init__.py +0 -0
- {moops-0.7.1 → moops-0.7.2}/src/moops/_choice_options.py +0 -0
- {moops-0.7.1 → moops-0.7.2}/src/moops/_control_mirroring.py +0 -0
- {moops-0.7.1 → moops-0.7.2}/src/moops/_embed.py +0 -0
- {moops-0.7.1 → moops-0.7.2}/src/moops/_input_map.py +0 -0
- {moops-0.7.1 → moops-0.7.2}/src/moops/_markdown.py +0 -0
- {moops-0.7.1 → moops-0.7.2}/src/moops/_naming.py +0 -0
- {moops-0.7.1 → moops-0.7.2}/src/moops/_options.py +0 -0
- {moops-0.7.1 → moops-0.7.2}/src/moops/_parse.py +0 -0
- {moops-0.7.1 → moops-0.7.2}/src/moops/_preset_state.py +0 -0
- {moops-0.7.1 → moops-0.7.2}/src/moops/_query_params.py +0 -0
- {moops-0.7.1 → moops-0.7.2}/src/moops/_run.py +0 -0
- {moops-0.7.1 → moops-0.7.2}/src/moops/_run_button.py +0 -0
- {moops-0.7.1 → moops-0.7.2}/src/moops/_ui_workarounds.py +0 -0
- {moops-0.7.1 → moops-0.7.2}/src/moops/_value_resolution.py +0 -0
- {moops-0.7.1 → moops-0.7.2}/src/moops/_variant.py +0 -0
- {moops-0.7.1 → moops-0.7.2}/src/moops/group.py +0 -0
- {moops-0.7.1 → moops-0.7.2}/src/moops/presets.py +0 -0
- {moops-0.7.1 → moops-0.7.2}/src/moops/workarounds.py +0 -0
|
@@ -13,6 +13,47 @@ from . import _input_map, _options, _parse, _query_params
|
|
|
13
13
|
from .presets import Presets
|
|
14
14
|
|
|
15
15
|
|
|
16
|
+
def _wrap_usage(prefix: str, parts: list[str], width: int = 88) -> str:
|
|
17
|
+
indent = " " * len(prefix)
|
|
18
|
+
lines: list[str] = []
|
|
19
|
+
current = prefix
|
|
20
|
+
first_on_line = True
|
|
21
|
+
for part in parts:
|
|
22
|
+
attempt = current + part if first_on_line else current + " " + part
|
|
23
|
+
if first_on_line or len(attempt) <= width:
|
|
24
|
+
current = attempt
|
|
25
|
+
first_on_line = False
|
|
26
|
+
else:
|
|
27
|
+
lines.append(current)
|
|
28
|
+
current = indent + part
|
|
29
|
+
lines.append(current)
|
|
30
|
+
return "\n".join(lines)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _wrap_help_line(line: str, width: int = 88) -> list[str]:
|
|
34
|
+
if len(line) <= width:
|
|
35
|
+
return [line]
|
|
36
|
+
sep = ": "
|
|
37
|
+
sep_idx = line.find(sep)
|
|
38
|
+
if sep_idx == -1:
|
|
39
|
+
return [line]
|
|
40
|
+
header = line[: sep_idx + 1] # e.g. " --option METAVAR:"
|
|
41
|
+
indent = " "
|
|
42
|
+
result = [header]
|
|
43
|
+
current = indent
|
|
44
|
+
first_on_line = True
|
|
45
|
+
for word in line[sep_idx + len(sep) :].split():
|
|
46
|
+
attempt = current + word if first_on_line else current + " " + word
|
|
47
|
+
if first_on_line or len(attempt) <= width:
|
|
48
|
+
current = attempt
|
|
49
|
+
first_on_line = False
|
|
50
|
+
else:
|
|
51
|
+
result.append(current)
|
|
52
|
+
current = indent + word
|
|
53
|
+
result.append(current)
|
|
54
|
+
return result
|
|
55
|
+
|
|
56
|
+
|
|
16
57
|
@dataclasses.dataclass
|
|
17
58
|
class Interface:
|
|
18
59
|
"""Controls registered by a subgroup's interface, for passing to the parent."""
|
|
@@ -95,13 +136,15 @@ class Interface:
|
|
|
95
136
|
usage_parts = list(self._format_usage_parts(_usage_placeholders(self)))
|
|
96
137
|
usage_parts.extend(("[--interactive]", "[-h/--help]"))
|
|
97
138
|
name = self.command.rsplit("/", 1)[-1]
|
|
98
|
-
|
|
139
|
+
prefix = f"Usage: {name} "
|
|
140
|
+
segments = [_wrap_usage(prefix, usage_parts)]
|
|
99
141
|
help_lines = list(self._format_help_lines())
|
|
100
142
|
if help_lines:
|
|
101
143
|
segments.append("\n".join(help_lines))
|
|
102
144
|
return "\n\n".join(segments)
|
|
103
145
|
|
|
104
146
|
def _format_help_lines(self) -> typing.Iterator[str]:
|
|
147
|
+
prev_was_group_with_content = False
|
|
105
148
|
for ctrl in self.controls:
|
|
106
149
|
if (sub_iface := _attached_interface(ctrl)) is not None:
|
|
107
150
|
lines = list(sub_iface._format_help_lines())
|
|
@@ -109,10 +152,15 @@ class Interface:
|
|
|
109
152
|
yield ""
|
|
110
153
|
yield f"{sub_iface.help_heading}:"
|
|
111
154
|
yield from lines
|
|
155
|
+
prev_was_group_with_content = bool(lines)
|
|
112
156
|
else:
|
|
113
157
|
input_control = self.input_map.get(ctrl)
|
|
114
158
|
if input_control is not None and not self._is_overridden(input_control):
|
|
115
|
-
|
|
159
|
+
if prev_was_group_with_content:
|
|
160
|
+
yield ""
|
|
161
|
+
for help_line in input_control.format_help_lines():
|
|
162
|
+
yield from _wrap_help_line(help_line)
|
|
163
|
+
prev_was_group_with_content = False
|
|
116
164
|
|
|
117
165
|
def _format_usage_parts(
|
|
118
166
|
self, placeholders_by_option: dict[str, str]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|