_E=True _D=False _C=' ' _B='\n' _A=None from contextlib import contextmanager from._compat import term_len from.parser import split_opt from.termui import get_terminal_size FORCED_WIDTH=_A def measure_table(rows): A={} for C in rows: for(B,D)in enumerate(C):A[B]=max(A.get(B,0),term_len(D)) return tuple(A for(B,A)in sorted(A.items())) def iter_rows(rows,col_count): for A in rows:A=tuple(A);yield A+('',)*(col_count-len(A)) def wrap_text(text,width=78,initial_indent='',subsequent_indent='',preserve_paragraphs=_D): A=text;from._textwrap import TextWrapper as I;A=A.expandtabs();E=I(width,initial_indent=initial_indent,subsequent_indent=subsequent_indent,replace_whitespace=_D) if not preserve_paragraphs:return E.fill(A) F=[];C=[];B=_A def H(): if not C:return if C[0].strip()=='\x08':F.append((B or 0,_E,_B.join(C[1:]))) else:F.append((B or 0,_D,_C.join(C))) del C[:] for D in A.splitlines(): if not D:H();B=_A else: if B is _A:J=term_len(D);D=D.lstrip();B=J-term_len(D) C.append(D) H();G=[] for(B,K,A)in F: with E.extra_indent(_C*B): if K:G.append(E.indent_only(A)) else:G.append(E.fill(A)) return'\n\n'.join(G) class HelpFormatter: def __init__(B,indent_increment=2,width=_A,max_width=_A): C=max_width;A=width;B.indent_increment=indent_increment if C is _A:C=80 if A is _A: A=FORCED_WIDTH if A is _A:A=max(min(get_terminal_size()[0],C)-2,50) B.width=A;B.current_indent=0;B.buffer=[] def write(A,string):A.buffer.append(string) def indent(A):A.current_indent+=A.indent_increment def dedent(A):A.current_indent-=A.indent_increment def write_usage(A,prog,args='',prefix='Usage: '): E=prefix;B=f"{E:>{A.current_indent}}{prog} ";D=A.width-A.current_indent if D>=term_len(B)+20:C=_C*term_len(B);A.write(wrap_text(args,D,initial_indent=B,subsequent_indent=C)) else:A.write(B);A.write(_B);C=_C*(max(A.current_indent,term_len(E))+4);A.write(wrap_text(args,D,initial_indent=C,subsequent_indent=C)) A.write(_B) def write_heading(A,heading):A.write(f"{'':>{A.current_indent}}{heading}:\n") def write_paragraph(A): if A.buffer:A.write(_B) def write_text(A,text):C=max(A.width-A.current_indent,11);B=_C*A.current_indent;A.write(wrap_text(text,C,initial_indent=B,subsequent_indent=B,preserve_paragraphs=_E));A.write(_B) def write_dl(A,rows,col_max=30,col_spacing=2): G=col_spacing;C=rows;C=list(C);E=measure_table(C) if len(E)!=2:raise TypeError('Expected two columns for definition list') B=min(E[0],col_max)+G for(F,H)in iter_rows(C,len(E)): A.write(f"{'':>{A.current_indent}}{F}") if not H:A.write(_B);continue if term_len(F)<=B-G:A.write(_C*(B-term_len(F))) else:A.write(_B);A.write(_C*(B+A.current_indent)) I=max(A.width-B-2,10);J=wrap_text(H,I,preserve_paragraphs=_E);D=J.splitlines() if D: A.write(f"{D[0]}\n") for K in D[1:]:A.write(f"{'':>{B+A.current_indent}}{K}\n") if len(D)>1:A.write(_B) else:A.write(_B) @contextmanager def section(self,name): A=self;A.write_paragraph();A.write_heading(name);A.indent() try:yield finally:A.dedent() @contextmanager def indentation(self): self.indent() try:yield finally:self.dedent() def getvalue(A):return''.join(A.buffer) def join_options(options): A=[];B=_D for C in options: D=split_opt(C)[0] if D=='/':B=_E A.append((len(D),C)) A.sort(key=lambda x:x[0]);A=', '.join(A[1]for A in A);return A,B