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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: moops
3
- Version: 0.7.1
3
+ Version: 0.7.2
4
4
  Summary: Write Marimo notebooks that also work as CLI scripts, with unified UI controls
5
5
  Keywords: marimo,notebooks,cli,testing
6
6
  Author: Yair Chuchem
@@ -4,7 +4,7 @@ build-backend = "uv_build"
4
4
 
5
5
  [project]
6
6
  name = "moops"
7
- version = "0.7.1"
7
+ version = "0.7.2"
8
8
  description = "Write Marimo notebooks that also work as CLI scripts, with unified UI controls"
9
9
  license = "MIT"
10
10
  readme = "README.md"
@@ -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
- segments = [f"Usage: {name} {' '.join(usage_parts)}"]
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
- yield from input_control.format_help_lines()
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