Add content CLI
This commit is contained in:
1 parent
3da32a4a90
commit
661ee019e5
10 files changed
+387
No files matched your search
@@ -0,0 +1,70 @@
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
PROJECT_ROOT = Path(__file__).resolve().parents[2]
|
||||
CONTENT_DIR = PROJECT_ROOT / "content"
|
||||
INLINE_LIST_MAX_LENGTH = 80
|
||||
INDENT = "\t"
|
||||
|
||||
|
||||
def content_path(name: str) -> Path:
|
||||
return CONTENT_DIR / name
|
||||
|
||||
|
||||
def load(name: str):
|
||||
with content_path(name).open(encoding="utf-8") as file:
|
||||
return json.load(file)
|
||||
|
||||
|
||||
def save(name: str, data) -> None:
|
||||
text = format_value(data, 0) + "\n"
|
||||
content_path(name).write_text(text, encoding="utf-8")
|
||||
|
||||
|
||||
def is_primitive(value) -> bool:
|
||||
return not isinstance(value, (dict, list))
|
||||
|
||||
|
||||
def encode(value) -> str:
|
||||
return json.dumps(value, ensure_ascii=False)
|
||||
|
||||
|
||||
def format_inline_dict(data: dict) -> str:
|
||||
if not data:
|
||||
return "{}"
|
||||
pairs = ", ".join(f"{encode(key)}: {format_value(value, 0)}" for key, value in data.items())
|
||||
return "{ " + pairs + " }"
|
||||
|
||||
|
||||
def format_inline_list(items: list) -> str:
|
||||
return "[" + ", ".join(encode(item) for item in items) + "]"
|
||||
|
||||
|
||||
def format_value(value, depth: int) -> str:
|
||||
if isinstance(value, dict):
|
||||
return format_dict(value, depth)
|
||||
if isinstance(value, list):
|
||||
return format_list(value, depth)
|
||||
return encode(value)
|
||||
|
||||
|
||||
def format_dict(data: dict, depth: int) -> str:
|
||||
if depth > 0 and all(is_primitive(value) or is_short_primitive_list(value) for value in data.values()):
|
||||
return format_inline_dict(data)
|
||||
inner_indent = INDENT * (depth + 1)
|
||||
lines = [f"{inner_indent}{encode(key)}: {format_value(value, depth + 1)}" for key, value in data.items()]
|
||||
return "{\n" + ",\n".join(lines) + "\n" + INDENT * depth + "}"
|
||||
|
||||
|
||||
def is_short_primitive_list(value) -> bool:
|
||||
return isinstance(value, list) and all(is_primitive(item) for item in value) and len(format_inline_list(value)) <= INLINE_LIST_MAX_LENGTH
|
||||
|
||||
|
||||
def format_list(items: list, depth: int) -> str:
|
||||
if not items:
|
||||
return "[]"
|
||||
if is_short_primitive_list(items):
|
||||
return format_inline_list(items)
|
||||
inner_indent = INDENT * (depth + 1)
|
||||
lines = [f"{inner_indent}{format_value(item, depth + 1)}" for item in items]
|
||||
return "[\n" + ",\n".join(lines) + "\n" + INDENT * depth + "]"
|
||||
Reference in new issue
Block a user