ck-preprocess/mri_synthmorph/synthmorph/utils.py
2025-02-02 12:29:19 +08:00

93 lines
2.8 KiB
Python

import shutil
import textwrap
def resolve_abbrev(needle, strings, lower=False):
"""Return a full-length string matching a substring from the beginning.
Parameters
----------
needle : str
Substring of one of several `strings`.
strings : str or iterable of str
Full-length strings, one of which should begin with `needle`.
lower : bool, optional
Convert needle to lowercase before matching.
Returns
-------
str
String in `strings` that begins with `needle` if there is no ambiguity.
If there is not exactly one match, the function will return `needle`.
"""
if isinstance(strings, str):
strings = [strings]
strings = tuple(strings)
if lower:
needle = needle.lower()
matches = [f for f in strings if f.startswith(needle)]
return matches[0] if len(matches) == 1 else needle
def rewrap_text(text, width=None, hard='\t\n', hard_indent=0, end=''):
"""Rewrap text such that lines fill the available horizontal space.
Reformats individual paragraphs of a text body, considering subsequent
lines with identical indentation as paragraphs. For unspecified width, the
function will attempt to determine the extent of the terminal.
Parameters
----------
text : str
Text to rewrap.
width : int, optional
Maximum line width. None means the width of the terminal as determined
by `textwrap`, defaulting to 80 characters for background processes.
hard : str, optional
String interpreted as a hard break when terminating a line. Useful for
inserting a line break without changing the indentation level. Must end
with a line break and will be removed from the output text.
hard_indent : int, optional
Number of additional whitespace characters by which to indent the lines
following a hard break. See `hard`.
end : str, optional
Append to the reformatted text.
Returns
-------
out : str
Reformatted text.
"""
# Inputs.
if width is None:
width = shutil.get_terminal_size().columns
lines = text.splitlines(keepends=True)
# Merge lines to paragraphs.
pad = []
pad_hard = []
par = []
for i, line in enumerate(lines):
ind = len(line) - len(line.lstrip())
if i == 0 or ind != pad[-1] or lines[i - 1].endswith(hard):
par.append('')
pad.append(ind)
pad_hard.append(ind)
if line.endswith(hard):
line = line.replace(hard, '\n')
pad_hard[-1] += hard_indent
par[-1] += line[ind:]
# Reformat paragraphs.
for i, _ in enumerate(par):
par[i] = textwrap.fill(
par[i], width,
initial_indent=' ' * pad[i], subsequent_indent=' ' * pad_hard[i],
)
return '\n'.join(par) + end