Skip to content

Commit 596a878

Browse files
committed
1. show overview
2. fix bugs
1 parent 2f20caa commit 596a878

File tree

1 file changed

+61
-32
lines changed

1 file changed

+61
-32
lines changed

jsonfmt.py

Lines changed: 61 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -69,25 +69,21 @@ def parse_to_pyobj(text: str, jpath: Optional[str]) -> tuple[Any, str]:
6969
return subelements, fmt
7070

7171

72-
def output(output_fp: IO, text: str, fmt: str, cp2clip: bool):
73-
# copy the result to clipboard
74-
if cp2clip:
75-
pyperclip.copy(text)
76-
print_inf('result copied to clipboard.')
77-
return
78-
elif stdout.isatty():
79-
# highlight the text when output to TTY divice
80-
Lexer = {'json': JsonLexer, 'toml': TOMLLexer, 'yaml': YamlLexer}[fmt]
81-
colored_text = highlight(text, Lexer(), TerminalFormatter())
82-
win_w, win_h = get_terminal_size()
83-
# use pager when line-hight > screen hight or
84-
if text.count('\n') >= win_h or len(text) > win_w * (win_h - 1):
85-
with patch("sys.stdin.isatty", lambda *_: True):
86-
pager(colored_text)
72+
def get_overview(py_obj: Any):
73+
def clip_value(value: Any):
74+
if isinstance(value, str):
75+
return '...'
76+
elif isinstance(value, (list, tuple)):
77+
return []
78+
elif isinstance(value, dict):
79+
return {k: clip_value(v) for k, v in value.items()}
8780
else:
88-
output_fp.write(colored_text)
81+
return value
82+
83+
if isinstance(py_obj, list):
84+
return [clip_value(py_obj[0])]
8985
else:
90-
output_fp.write(text)
86+
return clip_value(py_obj)
9187

9288

9389
def format_to_text(py_obj: Any, fmt: str, *,
@@ -104,36 +100,62 @@ def format_to_text(py_obj: Any, fmt: str, *,
104100
elif fmt == 'toml':
105101
if not isinstance(py_obj, dict):
106102
msg = 'the pyobj must be a Mapping when format to toml'
107-
print_err(msg)
108103
raise ParseError(msg)
109104
return toml.dumps(py_obj)
110105

111-
elif fmt == 'toml':
106+
elif fmt == 'yaml':
112107
return yaml.safe_dump(py_obj, allow_unicode=not escape, indent=indent,
113108
sort_keys=sort_keys)
114109

115110
else:
116111
raise ParseError('Unknow format')
117112

118113

119-
def process(input_fp: IO, jpath: Optional[str], *,
120-
overwrite: bool, cp2clip: bool, compact: bool,
121-
escape: bool, indent: int, sort_keys: bool):
114+
def output(output_fp: IO, text: str, fmt: str, cp2clip: bool):
115+
# copy the result to clipboard
116+
if cp2clip:
117+
pyperclip.copy(text)
118+
print_inf('result copied to clipboard.')
119+
return
120+
elif stdout.isatty():
121+
# highlight the text when output to TTY divice
122+
Lexer = {'json': JsonLexer, 'toml': TOMLLexer, 'yaml': YamlLexer}[fmt]
123+
colored_text = highlight(text, Lexer(), TerminalFormatter())
124+
win_w, win_h = get_terminal_size()
125+
# use pager when line-hight > screen hight or
126+
if text.count('\n') >= win_h or len(text) > win_w * (win_h - 1):
127+
with patch("sys.stdin.isatty", lambda *_: True):
128+
pager(colored_text)
129+
else:
130+
output_fp.write(colored_text)
131+
else:
132+
output_fp.seek(0)
133+
output_fp.truncate()
134+
output_fp.write(text)
135+
136+
137+
def process(input_fp: IO, jpath: Optional[str], to_format: Optional[str], *,
138+
compact: bool, cp2clip: bool, escape: bool, indent: int,
139+
overview: bool, overwrite: bool, sort_keys: bool):
122140
# parse and format
123141
input_text = input_fp.read()
124142
py_obj, fmt = parse_to_pyobj(input_text, jpath)
125-
formated_text = format_to_text(py_obj, fmt,
143+
144+
if overview:
145+
py_obj = get_overview(py_obj)
146+
147+
to_format = to_format or fmt
148+
formated_text = format_to_text(py_obj, to_format,
126149
compact=compact, escape=escape,
127150
indent=indent, sort_keys=sort_keys)
128151

152+
# output the result
129153
if input_fp.name == '<stdin>' or not overwrite:
130154
output_fp = stdout
131155
else:
132156
# truncate file to zero length before overwrite
133-
input_fp.seek(0)
134-
input_fp.truncate()
135157
output_fp = input_fp
136-
output(output_fp, formated_text, fmt, cp2clip)
158+
output(output_fp, formated_text, to_format, cp2clip)
137159

138160

139161
def parse_cmdline_args(args: Optional[Sequence[str]] = None):
@@ -144,11 +166,12 @@ def parse_cmdline_args(args: Optional[Sequence[str]] = None):
144166
help='copy the result to clipboard')
145167
parser.add_argument('-e', dest='escape', action='store_true',
146168
help='escape non-ASCII characters')
147-
parser.add_argument('-f', dest='format', default='json',
148-
choices=['json', 'toml', 'yaml'],
169+
parser.add_argument('-f', dest='format', choices=['json', 'toml', 'yaml'],
149170
help='the format to output ''(default: %(default)s)')
150171
parser.add_argument('-i', dest='indent', type=int, default=2,
151172
help='number of spaces for indentation (default: %(default)s)')
173+
parser.add_argument('-o', dest='overview', action='store_true',
174+
help='show data structure overview')
152175
parser.add_argument('-O', dest='overwrite', action='store_true',
153176
help='overwrite the formated text to original file')
154177
parser.add_argument('-p', dest='jsonpath', type=str,
@@ -176,10 +199,16 @@ def main():
176199
try:
177200
# read from file
178201
input_fp = open(file, 'r+') if isinstance(file, str) else file
179-
process(input_fp, args.jsonpath,
180-
overwrite=args.overwrite, cp2clip=cp2clip,
181-
compact=args.compact, escape=args.escape,
182-
indent=args.indent, sort_keys=args.sort_keys)
202+
process(input_fp,
203+
args.jsonpath,
204+
args.format,
205+
compact=args.compact,
206+
cp2clip=cp2clip,
207+
escape=args.escape,
208+
indent=args.indent,
209+
overview=args.overview,
210+
overwrite=args.overwrite,
211+
sort_keys=args.sort_keys)
183212
except ParseError as err:
184213
print_err(err)
185214
except FileNotFoundError:

0 commit comments

Comments
 (0)