AQIT
0.1.0
Toggle main menu visibility
Loading...
Searching...
No Matches
ascii_layout.py
Go to the documentation of this file.
1
# Copyright (c) 2025-present Aquin Labs Private Limited. All Rights Reserved.
2
"""Shared ASCII terminal layout primitives for aquin CLI surfaces."""
3
4
from
__future__
import
annotations
5
6
import
shutil
7
import
textwrap
8
9
# Hard-coded slant figlet — no runtime dep on pyfiglet.
10
BANNER =
r"""
11
___ ____ __ _______ __
12
/ | / __ \/ / / / _/ | / /
13
/ /| |/ / / / / / // // |/ /
14
/ ___ / /_/ / /_/ // // /| /
15
/_/ |_\___\_\____/___/_/ |_/
16
"""
.strip(
"\n"
)
17
18
19
def
width
() -> int:
20
try
:
21
cols = shutil.get_terminal_size().columns
22
except
OSError:
23
cols = 80
24
return
max(64, min(cols, 96))
25
26
27
def
ascii_safe
(text: str) -> str:
28
return
(
29
text.replace(
"\u2014"
,
"-"
)
30
.replace(
"\u2500"
,
"-"
)
31
.replace(
"\u00b7"
,
"|"
)
32
.replace(
"\u2019"
,
"'"
)
33
.replace(
"\u2026"
,
"..."
)
34
)
35
36
37
def
rule
(char: str =
"="
, w: int |
None
=
None
) -> str:
38
return
char * (w
or
width
())
39
40
41
def
center
(text: str, w: int |
None
=
None
) -> str:
42
return
text.center(w
or
width
())
43
44
45
def
center_block
(lines: list[str], w: int |
None
=
None
) -> list[str]:
46
"""Pad lines to equal width, then center the block as one unit."""
47
w = w
or
width
()
48
if
not
lines:
49
return
[]
50
block_w = max(len(line)
for
line
in
lines)
51
padded = [line.ljust(block_w)
for
line
in
lines]
52
left = max(0, (w - block_w) // 2)
53
return
[(
" "
* left) + line
for
line
in
padded]
54
55
56
def
box_top
(w: int |
None
=
None
) -> str:
57
w = w
or
width
()
58
return
"+"
+
"-"
* (w - 2) +
"+"
59
60
61
def
box_bottom
(w: int |
None
=
None
) -> str:
62
return
box_top
(w)
63
64
65
def
box_line
(text: str, w: int |
None
=
None
) -> str:
66
w = w
or
width
()
67
inner = w - 4
68
text =
ascii_safe
(text)
69
if
len(text) > inner:
70
text = text[: inner - 3] +
"..."
71
return
f
"| {text.ljust(inner)} |"
72
73
74
def
box_lines
(text: str, w: int |
None
=
None
) -> list[str]:
75
w = w
or
width
()
76
inner = w - 4
77
text =
ascii_safe
(text)
78
stripped = text.strip()
79
80
if
not
stripped:
81
return
[
box_line
(
""
, w)]
82
83
if
len(text) <= inner:
84
return
[
box_line
(text, w)]
85
86
if
all(c
in
"-=_."
for
c
in
stripped):
87
return
[
box_line
(
"-"
* inner, w)]
88
89
wrapped = textwrap.wrap(
90
text,
91
width=inner,
92
break_long_words=
False
,
93
break_on_hyphens=
False
,
94
)
95
return
[
box_line
(line, w)
for
line
in
wrapped]
96
97
98
def
kv_line
(label: str, value: str, *, label_width: int = 10, w: int |
None
=
None
) -> str:
99
"""Boxed key/value row: ' label value'."""
100
w = w
or
width
()
101
key = label[:label_width].ljust(label_width)
102
return
box_line
(f
" {key} {ascii_safe(value)}"
, w)
103
104
105
def
print_logo
() -> None:
106
"""Bare Aquin figlet — used for `aquin` with no args."""
107
print(BANNER)
108
print()
109
110
111
def
print_banner
(*, subtitle: str, w: int |
None
=
None
) ->
None
:
112
w = w
or
width
()
113
print()
114
print(
rule
(
"="
, w))
115
for
line
in
center_block
(BANNER.splitlines(), w):
116
print(line.rstrip())
117
print(
center
(subtitle, w))
118
print(
rule
(
"="
, w))
119
print()
120
121
122
def
print_section
(title: str, body_lines: list[str], *, w: int |
None
=
None
) ->
None
:
123
"""Print a titled ASCII box. body_lines are already boxed or plain content rows."""
124
w = w
or
width
()
125
print(
box_top
(w))
126
print(
box_line
(title.upper(), w))
127
print(
box_line
(
""
, w))
128
for
line
in
body_lines:
129
if
line.startswith(
"| "
)
and
line.endswith(
" |"
):
130
print(line)
131
else
:
132
for
boxed
in
box_lines
(line, w):
133
print(boxed)
134
print(
box_bottom
(w))
135
print()
aquin.ascii_layout.box_bottom
str box_bottom(int|None w=None)
Definition
ascii_layout.py:65
aquin.ascii_layout.box_line
str box_line(str text, int|None w=None)
Definition
ascii_layout.py:69
aquin.ascii_layout.print_banner
None print_banner(*, str subtitle, int|None w=None)
Definition
ascii_layout.py:115
aquin.ascii_layout.print_logo
None print_logo()
Definition
ascii_layout.py:109
aquin.ascii_layout.box_top
str box_top(int|None w=None)
Definition
ascii_layout.py:60
aquin.ascii_layout.ascii_safe
str ascii_safe(str text)
Definition
ascii_layout.py:31
aquin.ascii_layout.width
int width()
Definition
ascii_layout.py:23
aquin.ascii_layout.rule
str rule(str char="=", int|None w=None)
Definition
ascii_layout.py:41
aquin.ascii_layout.print_section
None print_section(str title, list[str] body_lines, *, int|None w=None)
Definition
ascii_layout.py:126
aquin.ascii_layout.center
str center(str text, int|None w=None)
Definition
ascii_layout.py:45
aquin.ascii_layout.center_block
list[str] center_block(list[str] lines, int|None w=None)
Definition
ascii_layout.py:49
aquin.ascii_layout.box_lines
list[str] box_lines(str text, int|None w=None)
Definition
ascii_layout.py:78
aquin.ascii_layout.kv_line
str kv_line(str label, str value, *, int label_width=10, int|None w=None)
Definition
ascii_layout.py:102
aquin
ascii_layout.py
AQIT · Aquin Labs Private Limited · Apache 2.0 · Generated by
1.18.0