]>
crepu.dev Git - config.git/blob - djavu-asus/elpy/rpc-venv/lib/python3.11/site-packages/click/formatting.py
2 from contextlib
import contextmanager
3 from gettext
import gettext
as _
5 from ._compat
import term_len
6 from .parser
import split_opt
8 # Can force a width. This is used by the test system
9 FORCED_WIDTH
: t
.Optional
[int] = None
12 def measure_table(rows
: t
.Iterable
[t
.Tuple
[str, str]]) -> t
.Tuple
[int, ...]:
13 widths
: t
.Dict
[int, int] = {}
16 for idx
, col
in enumerate(row
):
17 widths
[idx
] = max(widths
.get(idx
, 0), term_len(col
))
19 return tuple(y
for x
, y
in sorted(widths
.items()))
23 rows
: t
.Iterable
[t
.Tuple
[str, str]], col_count
: int
24 ) -> t
.Iterator
[t
.Tuple
[str, ...]]:
26 yield row
+ ("",) * (col_count
- len(row
))
32 initial_indent
: str = "",
33 subsequent_indent
: str = "",
34 preserve_paragraphs
: bool = False,
36 """A helper function that intelligently wraps text. By default, it
37 assumes that it operates on a single paragraph of text but if the
38 `preserve_paragraphs` parameter is provided it will intelligently
39 handle paragraphs (defined by two empty lines).
41 If paragraphs are handled, a paragraph can be prefixed with an empty
42 line containing the ``\\b`` character (``\\x08``) to indicate that
43 no rewrapping should happen in that block.
45 :param text: the text that should be rewrapped.
46 :param width: the maximum width for the text.
47 :param initial_indent: the initial indent that should be placed on the
48 first line as a string.
49 :param subsequent_indent: the indent string that should be placed on
50 each consecutive line.
51 :param preserve_paragraphs: if this flag is set then the wrapping will
52 intelligently handle paragraphs.
54 from ._textwrap
import TextWrapper
56 text
= text
.expandtabs()
57 wrapper
= TextWrapper(
59 initial_indent
=initial_indent
,
60 subsequent_indent
=subsequent_indent
,
61 replace_whitespace
=False,
63 if not preserve_paragraphs
:
64 return wrapper
.fill(text
)
66 p
: t
.List
[t
.Tuple
[int, bool, str]] = []
70 def _flush_par() -> None:
73 if buf
[0].strip() == "\b":
74 p
.append((indent
or 0, True, "\n".join(buf
[1:])))
76 p
.append((indent
or 0, False, " ".join(buf
)))
79 for line
in text
.splitlines():
85 orig_len
= term_len(line
)
87 indent
= orig_len
- term_len(line
)
92 for indent
, raw
, text
in p
:
93 with wrapper
.extra_indent(" " * indent
):
95 rv
.append(wrapper
.indent_only(text
))
97 rv
.append(wrapper
.fill(text
))
99 return "\n\n".join(rv
)
103 """This class helps with formatting text-based help pages. It's
104 usually just needed for very special internal cases, but it's also
105 exposed so that developers can write their own fancy outputs.
107 At present, it always writes into memory.
109 :param indent_increment: the additional increment for each level.
110 :param width: the width for the text. This defaults to the terminal
111 width clamped to a maximum of 78.
116 indent_increment
: int = 2,
117 width
: t
.Optional
[int] = None,
118 max_width
: t
.Optional
[int] = None,
122 self
.indent_increment
= indent_increment
123 if max_width
is None:
128 width
= max(min(shutil
.get_terminal_size().columns
, max_width
) - 2, 50)
130 self
.current_indent
= 0
131 self
.buffer: t
.List
[str] = []
133 def write(self
, string
: str) -> None:
134 """Writes a unicode string into the internal buffer."""
135 self
.buffer.append(string
)
137 def indent(self
) -> None:
138 """Increases the indentation."""
139 self
.current_indent
+= self
.indent_increment
141 def dedent(self
) -> None:
142 """Decreases the indentation."""
143 self
.current_indent
-= self
.indent_increment
146 self
, prog
: str, args
: str = "", prefix
: t
.Optional
[str] = None
148 """Writes a usage line into the buffer.
150 :param prog: the program name.
151 :param args: whitespace separated list of arguments.
152 :param prefix: The prefix for the first line. Defaults to
156 prefix
= f
"{_('Usage:')} "
158 usage_prefix
= f
"{prefix:>{self.current_indent}}{prog} "
159 text_width
= self
.width
- self
.current_indent
161 if text_width
>= (term_len(usage_prefix
) + 20):
162 # The arguments will fit to the right of the prefix.
163 indent
= " " * term_len(usage_prefix
)
168 initial_indent
=usage_prefix
,
169 subsequent_indent
=indent
,
173 # The prefix is too long, put the arguments on the next line.
174 self
.write(usage_prefix
)
176 indent
= " " * (max(self
.current_indent
, term_len(prefix
)) + 4)
179 args
, text_width
, initial_indent
=indent
, subsequent_indent
=indent
185 def write_heading(self
, heading
: str) -> None:
186 """Writes a heading into the buffer."""
187 self
.write(f
"{'':>{self.current_indent}}{heading}:\n")
189 def write_paragraph(self
) -> None:
190 """Writes a paragraph into the buffer."""
194 def write_text(self
, text
: str) -> None:
195 """Writes re-indented text into the buffer. This rewraps and
196 preserves paragraphs.
198 indent
= " " * self
.current_indent
203 initial_indent
=indent
,
204 subsequent_indent
=indent
,
205 preserve_paragraphs
=True,
212 rows
: t
.Sequence
[t
.Tuple
[str, str]],
214 col_spacing
: int = 2,
216 """Writes a definition list into the buffer. This is how options
217 and commands are usually formatted.
219 :param rows: a list of two item tuples for the terms and values.
220 :param col_max: the maximum width of the first column.
221 :param col_spacing: the number of spaces between the first and
225 widths
= measure_table(rows
)
227 raise TypeError("Expected two columns for definition list")
229 first_col
= min(widths
[0], col_max
) + col_spacing
231 for first
, second
in iter_rows(rows
, len(widths
)):
232 self
.write(f
"{'':>{self.current_indent}}{first}")
236 if term_len(first
) <= first_col
- col_spacing
:
237 self
.write(" " * (first_col
- term_len(first
)))
240 self
.write(" " * (first_col
+ self
.current_indent
))
242 text_width
= max(self
.width
- first_col
- 2, 10)
243 wrapped_text
= wrap_text(second
, text_width
, preserve_paragraphs
=True)
244 lines
= wrapped_text
.splitlines()
247 self
.write(f
"{lines[0]}\n")
249 for line
in lines
[1:]:
250 self
.write(f
"{'':>{first_col + self.current_indent}}{line}\n")
255 def section(self
, name
: str) -> t
.Iterator
[None]:
256 """Helpful context manager that writes a paragraph, a heading,
259 :param name: the section name that is written as heading.
261 self
.write_paragraph()
262 self
.write_heading(name
)
270 def indentation(self
) -> t
.Iterator
[None]:
271 """A context manager that increases the indentation."""
278 def getvalue(self
) -> str:
279 """Returns the buffer contents."""
280 return "".join(self
.buffer)
283 def join_options(options
: t
.Sequence
[str]) -> t
.Tuple
[str, bool]:
284 """Given a list of option strings this joins them in the most appropriate
285 way and returns them in the form ``(formatted_string,
286 any_prefix_is_slash)`` where the second item in the tuple is a flag that
287 indicates if any of the option prefixes was a slash.
290 any_prefix_is_slash
= False
293 prefix
= split_opt(opt
)[0]
296 any_prefix_is_slash
= True
298 rv
.append((len(prefix
), opt
))
300 rv
.sort(key
=lambda x
: x
[0])
301 return ", ".join(x
[1] for x
in rv
), any_prefix_is_slash